summaryrefslogtreecommitdiffstats
path: root/reladminif
diff options
context:
space:
mode:
Diffstat (limited to 'reladminif')
-rw-r--r--reladminif/Makefile.am68
-rw-r--r--reladminif/adminif.hh174
-rw-r--r--reladminif/adminif.pgc90
-rw-r--r--reladminif/adminifcommon.cc163
-rw-r--r--reladminif/binaryrepresentation.hh31
-rw-r--r--reladminif/databaseif.hh222
-rw-r--r--reladminif/databaseif.pgc1382
-rw-r--r--reladminif/databaseifcommon.cc242
-rw-r--r--reladminif/dbnamedobject.cc179
-rw-r--r--reladminif/dbnamedobject.hh121
-rw-r--r--reladminif/dbobject.cc459
-rw-r--r--reladminif/dbobject.hh291
-rw-r--r--reladminif/dbobjectiditerator.cc103
-rw-r--r--reladminif/dbobjectiditerator.hh108
-rw-r--r--reladminif/dbobjectiterator.cc104
-rw-r--r--reladminif/dbobjectiterator.hh104
-rw-r--r--reladminif/dbref.cc874
-rw-r--r--reladminif/dbref.hh301
-rw-r--r--reladminif/destroyable.hh52
-rw-r--r--reladminif/eoid.cc231
-rw-r--r--reladminif/eoid.hh146
-rw-r--r--reladminif/externs.h81
-rw-r--r--reladminif/lists.h106
-rw-r--r--reladminif/objectbroker.hh506
-rw-r--r--reladminif/objectbroker.pgc1029
-rw-r--r--reladminif/objectbrokercommon.cc1144
-rw-r--r--reladminif/oidif.hh307
-rw-r--r--reladminif/oidif.pgc135
-rw-r--r--reladminif/oidifcommon.cc414
-rw-r--r--reladminif/sqlerror.hh118
-rw-r--r--reladminif/sqlerror.pgc198
-rw-r--r--reladminif/sqlglobals.h50
-rw-r--r--reladminif/test/Makefile90
-rw-r--r--reladminif/test/admintest.C92
-rw-r--r--reladminif/test/check.cc301
-rw-r--r--reladminif/test/dbnamedobjtest.C88
-rw-r--r--reladminif/test/dbreftest.C70
-rw-r--r--reladminif/test/demobld.sql125
-rw-r--r--reladminif/test/demodrop.sql42
-rw-r--r--reladminif/test/eoidtest.C128
-rw-r--r--reladminif/test/indextest.cc227
-rw-r--r--reladminif/test/perstest.C1155
-rw-r--r--reladminif/test/test_databaseif.cc203
-rw-r--r--reladminif/test/testcenter.h47
-rw-r--r--reladminif/test/testconnect.c395
-rw-r--r--reladminif/test/testta.pgc281
-rw-r--r--reladminif/transactionif.hh107
-rw-r--r--reladminif/transactionif.pgc242
-rw-r--r--reladminif/transactionifcommon.cc69
49 files changed, 13195 insertions, 0 deletions
diff --git a/reladminif/Makefile.am b/reladminif/Makefile.am
new file mode 100644
index 0000000..07a6e99
--- /dev/null
+++ b/reladminif/Makefile.am
@@ -0,0 +1,68 @@
+# -*-Makefile-*- (for Emacs)
+#
+# This file is part of rasdaman community.
+#
+# Rasdaman community is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Rasdaman community is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+#
+# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+# rasdaman GmbH.
+#
+# For more information please see <http://www.rasdaman.org>
+# or contact Peter Baumann via <baumann@rasdaman.com>.
+#
+# MAKEFILE FOR:
+# reladminif
+#
+#
+# COMMENTS:
+# - stagerif not used
+#
+##################################################################
+
+AM_CXXFLAGS=@BASEDBCXXFLAGS@
+AM_LDFLAGS=@BASEDBLDFLAGS@
+
+.SUFFIXES= .@EMBEDDEDSQLEXT@ .@EMBEDDEDSQLOUT@
+.@EMBEDDEDSQLEXT@.@EMBEDDEDSQLOUT@:
+ $(EMBEDDEDSQLPRECOMPILER) $@ $<
+
+
+noinst_LIBRARIES=libreladminif.a
+libreladminif_a_SOURCES=adminifcommon.cc adminif.hh databaseifcommon.cc databaseif.hh \
+ transactionifcommon.cc transactionif.hh sqlerror.hh \
+ oidifcommon.cc oidif.hh dbobject.cc dbobject.hh \
+ dbnamedobject.cc dbnamedobject.hh eoid.cc eoid.hh \
+ dbref.cc dbref.hh objectbrokercommon.cc objectbroker.hh \
+ dbobjectiterator.cc dbobjectiterator.hh \
+ externs.h lists.h binaryrepresentation.hh destroyable.hh \
+ sqlglobals.h dbobjectiditerator.hh
+EXTRA_libreladminif_a_SOURCES=adminif.pgc databaseif.pgc transactionif.pgc \
+ sqlerror.pgc oidif.pgc objectbroker.pgc \
+ dbobjectiditerator.cc
+
+libreladminif_a_LIBADD= adminif.$(OBJEXT) databaseif.$(OBJEXT) transactionif.$(OBJEXT) \
+ sqlerror.$(OBJEXT) oidif.$(OBJEXT) objectbroker.$(OBJEXT)
+libreladminif_a_DEPENDENCIES= adminif.$(OBJEXT) databaseif.$(OBJEXT) transactionif.$(OBJEXT) \
+ sqlerror.$(OBJEXT) oidif.$(OBJEXT) objectbroker.$(OBJEXT)
+
+
+BUILT_SOURCES= adminif.@EMBEDDEDSQLOUT@ databaseif.@EMBEDDEDSQLOUT@ transactionif.@EMBEDDEDSQLOUT@ \
+ sqlerror.@EMBEDDEDSQLOUT@ oidif.@EMBEDDEDSQLOUT@ objectbroker.@EMBEDDEDSQLOUT@
+
+
+CLEANFILES= adminif.@EMBEDDEDSQLOUT@ databaseif.@EMBEDDEDSQLOUT@ transactionif.@EMBEDDEDSQLOUT@ \
+ sqlerror.@EMBEDDEDSQLOUT@ oidif.@EMBEDDEDSQLOUT@ objectbroker.@EMBEDDEDSQLOUT@ \
+ client.bm client.dbg client.log ir.out
+
+
diff --git a/reladminif/adminif.hh b/reladminif/adminif.hh
new file mode 100644
index 0000000..6d4024b
--- /dev/null
+++ b/reladminif/adminif.hh
@@ -0,0 +1,174 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#ifndef _ADMINIF_HH_
+#define _ADMINIF_HH_
+
+/************************************************************************
+ *
+= *
+ * PURPOSE:
+ *
+ *
+ * COMMENTS:
+ *
+ ***********************************************************************/
+
+class AdminIf;
+class DatabaseIf;
+
+class r_Error;
+
+#include <iostream>
+#include "lists.h"
+
+class AdminIf;
+
+//@ManMemo: Module: {\bf reladminif}.
+
+/*@Doc:
+An AdminIf instance has to be obtained, before any work with the base
+DBMS can be done. Only one instance can exist at any time. The class
+follows the singleton design pattern (Gamma et. al. p. 127ff.).
+
+{\bf Functionality}
+
+At the moment, AdminIf is responsible for the state of a transaction.
+persistent objects rely on this class to decide if they should write
+changes back into the db. It also carries a list of compressed tiles.
+Before a session is opened, no persistence capable classes can be used (e.g.
+\Ref{BLOBTile})! Remember to also create a \Ref{DatabaseIf} instance
+before using a persistence capable class.
+
+{\bf Example}
+
+{\tt AdminIf* myAdmin = AdminIf::instance();}
+
+...
+
+{\tt delete myAdmin;}
+
+*/
+
+const int SYSTEMNAME_MAXLEN=256;
+
+class AdminIf
+ {
+ public:
+ static AdminIf* instance();
+ /*@Doc:
+ satic function used to access instance of AdminIf and start session.
+ */
+
+ static DatabaseIf* getCurrentDatabaseIf();
+ /*@Doc:
+ static function used to access the current databaseif object
+ */
+
+ static void setCurrentDatabaseIf(DatabaseIf* db);
+ /*@Doc:
+ static function used to store the current databaseif object in AdminIf
+ this function should only be called by DatabaseIf, DatabasIf
+ is responsible for setting the databaseif object to
+ NULL at destruction time.
+ */
+
+ ~AdminIf();
+ /*@Doc:
+ issues a ROLLBACK WORK RELEASE
+ deinitializes the ObjectBroker
+ deinitializes benchmark timers
+ */
+
+ static char* getSystemName();
+ /*@Doc:
+ returns Oracle on oracle
+ */
+
+ static void setReadOnlyTA(bool newReadOnlyTA);
+ /*@Doc:
+ sets readOnlyTA, should only be used by \Ref{TransactionIf}
+ */
+
+ static bool isReadOnlyTA();
+ /*@Doc:
+ checks for read only TA.
+ */
+
+ static bool isAborted();
+ /*@Doc:
+ used by DBObject::validate() to determine if it should execute the persistency functions
+ */
+
+ static void setAborted(bool newAborted);
+ /*@Doc:
+ used by transactionif to set the aborted status of the transaction
+ */
+
+ protected:
+ AdminIf() throw (r_Error);
+ /*@Doc:
+ constructor, can not be used from outside.
+ initializes the objectbroker
+ does a CONNECT, when successful sets validConnection to true else false,
+ then a ROLLBACK WORK RELEASE
+ throws exception if connection fails
+ */
+
+ private:
+ static AdminIf* myInstance;
+ /*@Doc:
+ pointer to instance (just needed for Singleton pattern).
+ */
+
+ static DatabaseIf* myDatabaseIf;
+ /*@Doc:
+ pointer to the current DatabaseIf object
+ */
+
+ static bool validConnection;
+ /*@Doc:
+ flag for error when opening session: false if error.
+ */
+
+ static bool readOnlyTA;
+ /*@Doc:
+ flag for read only transactions
+ */
+
+ static const char dbmsName[SYSTEMNAME_MAXLEN];
+ /*@Doc:
+ holds the specific name of dbms
+ */
+
+ static char systemName[SYSTEMNAME_MAXLEN];
+ /*@Doc:
+ Store the dbms name using dbmsName
+ */
+
+ static bool _isAborted;
+ /*@Doc:
+ flag for aborted transactions
+ */
+ };
+
+#endif
diff --git a/reladminif/adminif.pgc b/reladminif/adminif.pgc
new file mode 100644
index 0000000..5e1a03d
--- /dev/null
+++ b/reladminif/adminif.pgc
@@ -0,0 +1,90 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * implements adminif interface using the PostgreSQL DBMS.
+ *
+ *
+ * COMMENTS:
+ * none
+ *
+ ***********************************************************************/
+
+static const char rcsid[] = "@(#)reladminif,AdminIf: $Id: adminif.ec,v 1.6 2003/12/27 23:11:43 rasdev Exp $";
+
+#include "debug-srv.hh"
+#include "sqlerror.hh"
+
+// general embedded SQL related definitions
+EXEC SQL include sqlglobals.h;
+
+#include "adminif.hh"
+#include "raslib/rmdebug.hh"
+#include "objectbroker.hh"
+
+extern char globalConnectId[256];
+const char AdminIf::dbmsName[SYSTEMNAME_MAXLEN]="PostgreSQL";
+
+AdminIf::AdminIf() throw (r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "Adminif", "AdminIf()");
+ ENTER( "AdminIf::AdminIf" );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char id[STRING_MAXLEN];
+ EXEC SQL END DECLARE SECTION;
+
+ strncpy((char *)&id, globalConnectId, sizeof(id)-1);
+
+ TALK( "EXEC SQL CONNECT TO " << id );
+ EXEC SQL CONNECT TO :id;
+
+ if (check("AdminIf Connect\0"))
+ {
+ validConnection = false;
+ TALK( "connect unsuccessful; wrong connect string?" );
+ cout << "Error: connect unsuccessful; wrong connect string '" << globalConnectId << "' ?" << endl;
+ throw r_Error( 830 );
+ }
+ else
+ {
+ validConnection = true;
+ TALK( "connect ok" );
+ }
+
+ TALK( "EXEC SQL ROLLBACK WORK" );
+ EXEC SQL ROLLBACK WORK;
+
+#ifndef FASTCONNECT
+ TALK( "EXEC SQL DISCONNECT CURRENT" );
+ EXEC SQL DISCONNECT CURRENT;
+#endif
+
+ ObjectBroker::init();
+
+ LEAVE( "AdminIf::AdminIf, SQLCODE=" << SQLCODE );
+ RMDBGEXIT(4, RMDebug::module_adminif, "Adminif", "AdminIf() " << validConnection);
+}
+
diff --git a/reladminif/adminifcommon.cc b/reladminif/adminifcommon.cc
new file mode 100644
index 0000000..f4409e3
--- /dev/null
+++ b/reladminif/adminifcommon.cc
@@ -0,0 +1,163 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * Code with embedded SQL for relational DBMS
+ *
+ *
+ * COMMENTS:
+ * none
+ *
+ ***********************************************************************/
+
+#include <string.h>
+#if defined(DECALPHA) || defined(LINUX) || defined(AIX) || defined(SOLARIS)
+//#include <algorith.h>
+//#elif defined(LINUX) || defined(AIX) || defined(SOLARIS)
+#include <algorithm>
+#endif
+
+#include "raslib/error.hh"
+#include "adminif.hh"
+
+#include "raslib/rmdebug.hh"
+#include "sqlerror.hh"
+#include "objectbroker.hh"
+
+#include "externs.h"
+
+// defined in rasserver.cc
+extern char globalConnectId[256];
+
+AdminIf* AdminIf::myInstance = NULL;
+
+bool AdminIf::validConnection = false;
+
+bool AdminIf::readOnlyTA = false;
+
+DatabaseIf* AdminIf::myDatabaseIf = NULL;
+
+char AdminIf::systemName[SYSTEMNAME_MAXLEN];
+
+bool AdminIf::_isAborted = false;
+
+bool
+AdminIf::isAborted()
+ {
+ RMDBGENTER(4, RMDebug::module_adminif, "Adminif", "isAborted()");
+ bool retval=false;
+
+#ifdef READ_ONLY_RMAN
+ retval=true;
+#else
+ retval=_isAborted;
+#endif
+ RMDBGEXIT(4, RMDebug::module_adminif, "AdminIf", "isAborted() " << retval);
+ return retval;
+ }
+
+void
+AdminIf::setAborted(bool newAborted)
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "AdminIf", "setAborted(" << newAborted << ") " << _isAborted);
+ _isAborted = newAborted;
+ }
+
+DatabaseIf*
+AdminIf::getCurrentDatabaseIf()
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "getCurrentDatabaseIf() " << myDatabaseIf);
+ return myDatabaseIf;
+ }
+
+void
+AdminIf::setCurrentDatabaseIf(DatabaseIf* db)
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "setCurrentDatabaseIf(" << db << ") " << myDatabaseIf);
+ myDatabaseIf = db;
+ }
+
+AdminIf*
+AdminIf::instance()
+ {
+ RMDBGENTER(4, RMDebug::module_adminif, "Adminif", "instance() " << myInstance);
+ AdminIf* retval=NULL;
+
+ strcpy((char*)&systemName, dbmsName);
+ if(!myInstance)
+ {
+ myInstance = new AdminIf();
+ }
+ if(validConnection)
+ retval=myInstance;
+
+ RMDBGEXIT(4, RMDebug::module_adminif, "Adminif", "instance() " << retval);
+ return retval;
+ }
+
+AdminIf::~AdminIf()
+ {
+ RMDBGENTER(4, RMDebug::module_adminif, "Adminif", "~AdminIf()");
+
+ myInstance = NULL;
+ ObjectBroker::deinit();
+
+#ifdef RMANBENCHMARK
+ DBObject::readTimer.setOutput(0);
+
+ DBObject::updateTimer.setOutput(0);
+
+ DBObject::deleteTimer.setOutput(0);
+
+ DBObject::insertTimer.setOutput(0);
+
+ OId::oidAlloc.setOutput(0);
+
+ OId::oidResolve.setOutput(0);
+#endif
+ RMDBGEXIT(4, RMDebug::module_adminif, "Adminif", "~AdminIf()");
+ }
+
+void
+AdminIf::setReadOnlyTA(bool newReadOnlyTA)
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "setReadOnlyTA(" << newReadOnlyTA << ")" << readOnlyTA);
+ readOnlyTA = newReadOnlyTA;
+ }
+
+bool
+AdminIf::isReadOnlyTA()
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "isReadOnlyTA()" << readOnlyTA);
+ return readOnlyTA;
+ }
+
+char*
+AdminIf::getSystemName()
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "getSystemName()" <<systemName);
+ return systemName;
+ }
+
diff --git a/reladminif/binaryrepresentation.hh b/reladminif/binaryrepresentation.hh
new file mode 100644
index 0000000..d2e3f0f
--- /dev/null
+++ b/reladminif/binaryrepresentation.hh
@@ -0,0 +1,31 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+class BinaryRepresentation
+ {
+ public:
+ char* binaryName;
+ char* binaryData;
+ size_t binaryLength;
+ static const char* fileTag;
+ };
+
diff --git a/reladminif/databaseif.hh b/reladminif/databaseif.hh
new file mode 100644
index 0000000..f8b8954
--- /dev/null
+++ b/reladminif/databaseif.hh
@@ -0,0 +1,222 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#ifndef _DATABASEIF_HH_
+#define _DATABASEIF_HH_
+
+/************************************************************************
+ *
+ *
+ * PURPOSE:
+ *
+ *
+ * COMMENTS:
+ *
+ ***********************************************************************/
+
+//@ManMemo: Module: {\bf reladminif}.
+/*@Doc:
+With a DatabaseIf instance a database can be opened or closed. There
+is also functionality for creating and deleting DBs. A
+database has to be open, before persistence capable classes can be
+used (see also \Ref{AdminIf}).
+
+{\bf Example}
+
+{\tt DatabaseIf database;}
+
+{\tt database.open( "myDatabase" )}
+
+...
+
+{\tt database.close();}
+*/
+
+class DatabaseIf;
+class TransactionIf;
+
+#include <iostream>
+using std::cout;
+using std::endl;
+using std::ostream;
+
+#include "raslib/error.hh"
+
+class DatabaseIf
+ {
+ public:
+ friend std::ostream& operator<< (std::ostream& stream, DatabaseIf& db);
+ /*@Doc:
+ prints the status of the database (connected, online, offline, name)
+ */
+
+ /// opens database with name {\tt dbName}.
+ void open( const char* dbName ) throw(r_Error);
+ /*@Doc:
+ Precondition: not opened, not connected, db exists
+ Postcondition: open, not connected, db exists
+ If last opened database was not closed (throw r_Error::r_Error_DatabaseOpen)),
+ If database does not exist (throw r_Error::r_Error_DatabaseUnknown).
+ In the current implementation this value is returned, when dbName is not RASBASE,
+ regardles if the db exists or not.
+ */
+
+ void close();
+ /*@Doc:
+ Precondition: open, not connected, db exists
+ Postcondition: not open, not connected, db exists
+ closes currently opened database. only frees name and sets connected/opened to false.
+ */
+
+ static void createDB( const char* dbName, const char* schemaName, const char* volumeName=0 ) throw(r_Error);
+ /*@Doc:
+ Precondition: not open, not connected, db does not exist
+ Postcondition: not open, not connected, db exists
+ creates a new database. schemaName and volumeName are ignored.
+ only successful if dbName is RASBASE
+ */
+
+ static void destroyDB(const char* dbName) throw(r_Error);
+ /*@Doc:
+ Precondition: not open, not connected, db exists
+ Postcondition: not open, not connected, db does not exist
+ destroys an existing database with name {\tt dbName}.
+ Database must not be open in order to be destroyed.
+ A transaction must not be opened.
+ Returns -1 if database does not exist.
+ */
+
+
+ void garbage();
+ /*@Doc:
+ this method does not do anything
+ */
+
+ const char* getName() const;
+ /*@Doc:
+ returns a pointer to the name of the db.
+ */
+
+ DatabaseIf();
+ /*@Doc:
+ constructor. Initializes opened, myName and connected to 0
+ */
+
+ bool isConnected() const;
+ /*@Doc:
+ true when there has been an EXEC SQL CONNECT
+ */
+
+ bool isOpen() const;
+ /*@Doc:
+ true when it was opened by a transaction
+ */
+
+ ~DatabaseIf();
+ /*@Doc:
+ executes a baseDBMSClose() if it is still connected.
+ */
+
+ static bool databaseExists(const char* dbname) throw (r_Error);
+ /*@Doc:
+ Precondition: none checked. db must be open and connected.
+ Postcondition: none
+ basedbms error thrown.
+ checks if a database has been created.
+ */
+
+ static bool isConsistent() throw (r_Error);
+ /*@Doc:
+ Precondition: none checked. db must be open and connected.
+ Postcondition: none
+ basedbms error thrown if something really bad happens.
+ checks if counters are ok.
+ */
+
+ protected:
+ friend class TransactionIf;
+
+ void baseDBMSOpen() throw (r_Error);
+ /*@Doc:
+ Precondition: current database = 0
+ Postcondition: current database = this
+ issues a CONNECT.
+ sets the DatabaseIf object in AdminIf to this.
+ */
+
+ void baseDBMSClose();
+ /*@Doc:
+ Precondition: current database = this
+ Postcondition: current database = 0
+ issues a ROLLBACK WORK RELEASE in oracle.
+ issues a DISCONNECT in db2.
+ sets the DatabaseIf object in AdminIf to 0, if it was the same.
+ */
+
+ static void connect() throw (r_Error);
+ /*@Doc:
+ Precondition: none checked.
+ Postcondition: none.
+ issues a CONNECT.
+ throws r_Error if there is a problem during connection.
+ */
+
+ static void disconnect() throw (r_Error);
+ /*@Doc:
+ Precondition: none checked.
+ Postcondition: none.
+ issues a CONNECT.
+ throws r_Error if there is a problem during disconnection.
+ */
+
+ void checkCompatibility() throw (r_Error);
+ /*@Doc:
+ Precondition: none checked.
+ Postcondition: none.
+ throws r_Error if the current rasdaman system does not match the database.
+ */
+
+ private:
+ bool opened;
+ /*@Doc:
+ TRUE only if database is open.
+ */
+
+ char* myName;
+ /*@Doc:
+ Valid only if opened.
+ */
+
+ bool connected;
+ /*@Doc:
+ TRUE only if database connection exists ; )
+ */
+
+ static const char* DefaultDatabaseName;
+ /*@Doc:
+ only one database is supported. any database name given is compared to this string.
+ access to the db is only granted if the name of the database is the same as this string.
+ */
+
+ };
+
+#endif
diff --git a/reladminif/databaseif.pgc b/reladminif/databaseif.pgc
new file mode 100644
index 0000000..cec18c5
--- /dev/null
+++ b/reladminif/databaseif.pgc
@@ -0,0 +1,1382 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+// This is -*- C++ -*-
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * Code with embedded SQL for PostgreSQL DBMS
+ *
+ *
+ * COMMENTS:
+ * - need connection via ECPG and libqg, use non-public interface to
+ * obtain libpq style connection ptr from ECPG structure
+ * - global variable globalConnectId used for DB server identification, maybe better as constructor parameter
+ * - dbName parameter not evaluated
+ * - PG: no CLUSTER index available
+ * - PG: index always in same schema as table
+ * - replaced "if ((SQLCODE != SQLOK) && (SQLCODE != SQLNULLFETCHED))"
+ * by "if (SQLCODE < 0 || SQLCODE == SQLNODATAFOUND)"
+ * - databaseExists() not used
+ * - attribute name 'OId' -> 'UOId' (for UDFs), 'OId' -> 'Id' (for IXs)
+ * to avoid PG name clash with attr type
+ * - except for RAS_COUNTERS, "no data" means no error, but that we need to initialize the empty table
+ *
+ ***********************************************************************/
+
+static const char rcsid[] = "@(#)reladminif,DatabaseIf: $Id: databaseif.ec,v 1.9 2003/12/27 23:11:43 rasdev Exp $";
+
+#include "debug/debug.hh"
+
+// general embedded SQL related definitions
+EXEC SQL include sqlglobals.h;
+
+// SQL error codes:
+EXEC SQL include "externs.h"
+
+// PG stuff
+#include "libpq-fe.h" // C interface to PgSQL
+// libq-style connection ptr taken from ECPG connect (needed for libq functions):
+// (currently used by relblobif/blobtile.pgc)
+PGconn *pgConn = NULL;
+
+// we use a non-public interface to obtain the connection ptr
+// defs are taken from PG's /src/interfaces/ecpg/ecpglib/extern.h
+// --- START non-public PG
+struct ECPGtype_information_cache
+{
+ struct ECPGtype_information_cache *next;
+ int oid;
+ bool isarray;
+};
+
+struct connection
+{
+ char *name;
+ PGconn *conn; // changed name to avoid component name clash of gcc3 -- PB 2005-feb-08
+ bool committed;
+ int autocommit;
+ struct ECPGtype_information_cache *cache_head;
+ struct connection *next;
+};
+
+
+// need to safeguard this from C++ name mangling -- PB 2005-feb-09
+//#ifdef __cplusplus
+//extern "C" {
+//#endif
+// struct connection *ECPGget_connection(const char *);
+//#ifdef __cplusplus
+//}
+//#endif
+
+// --- END non-public PG
+
+#include "databaseif.hh"
+#include "raslib/rmdebug.hh"
+#include "sqlerror.hh"
+#include "oidif.hh"
+#include "adminif.hh"
+
+extern char globalConnectId[256];
+// size of ARCHITECTURE attribute in RAS_ADMIN:
+#define SIZE_ARCH_RASADMIN 20
+
+
+void
+DatabaseIf::disconnect() throw (r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "disconnect()");
+ ENTER( "DatabaseIf::disconnect" );
+
+ TALK( "EXEC SQL ROLLBACK WORK" );
+ EXEC SQL ROLLBACK WORK;
+ // 'ok' or 'no begin work issued' (which happens at a close database)
+ if (SQLCODE != SQLOK && SQLCODE != -255)
+ {
+ check("DatabaseIf::disconnect() ROLLBACK\0");
+ TALK( "Error while issuing ROLLBACK");
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "error occured while issuing a ROLLBACK");
+ }
+
+#ifndef FASTCONNECT
+ TALK( "EXEC SQL DISCONNECT CURRENT" );
+ EXEC SQL DISCONNECT CURRENT;
+ if (SQLCODE != SQLOK)
+ {
+ check("DatabaseIf::disconnect() DISCONNECT\0");
+ TALK( "Error while issuing DISCONNECT");
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "error occured while issuing a DISCONNECT");
+ }
+ pgConn = NULL;
+#endif
+
+ LEAVE( "DatabaseIf::disconnect, SQLCODE=" << SQLCODE );
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "disconnect() SQLCODE=" << SQLCODE);
+}
+
+void
+DatabaseIf::connect() throw (r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "connect()");
+ ENTER( "DatabaseIf::connect" );
+
+#ifndef FASTCONNECT
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char id[STRING_MAXLEN];
+ EXEC SQL END DECLARE SECTION;
+
+
+ strcpy((char *)&id, globalConnectId);
+ TALK( "EXEC SQL CONNECT TO " << id );
+ EXEC SQL CONNECT TO :id AS rasdaConn; // "AS" param must be same as down in ECPGget_connection()
+ if (SQLCODE != SQLOK)
+ {
+ check("DatabaseIf::connect() CONNECT");
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "connect() SQLCODE=" << SQLCODE);
+ TALK( "error in connect, SQLCODE=" << SQLCODE );
+ generateException();
+ }
+ char newConnectId[256];
+ sprintf(newConnectId, "dbname='%s'", id);
+ pgConn = PQconnectdb(newConnectId);
+ if (pgConn == NULL || PQstatus(pgConn) == CONNECTION_BAD) {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "Error: cannot obtain libpq connection" );
+ TALK( "Error: cannot obtain libpq connection" );
+ generateException();
+ }
+
+ /*
+
+ // get connection ptr for libpq based access
+ struct connection *interimConn = NULL;
+ interimConn = ECPGget_connection( "rasdaConn" ); // param must be same as up in CONNECT ... AS
+ if (interimConn == NULL || interimConn->conn == NULL)
+ {
+ }
+ pgConn = interimConn->conn;*/
+
+#endif
+
+ LEAVE( "DatabaseIf::connect, SQLCODE=" << SQLCODE );
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "connect()");
+}
+
+void
+DatabaseIf::checkCompatibility() throw (r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "checkCompatibility()");
+ ENTER( "DatabaseIf::checkCompatibility" );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long rasver1; // rasdaman version as stored in db
+ long schemaver1; // schema version as stored in db
+ char* arch1[SIZE_ARCH_RASADMIN]; // used for reading architecture from db
+ char *myArchitecture = RASARCHITECTURE; // used for architecture selection
+ EXEC SQL END DECLARE SECTION;
+
+ TALK( "EXEC SQL SELECT ServerVersion, IFVersion INTO :rasver1, :schemaver1 FROM RAS_ADMIN WHERE Architecture = " << myArchitecture );
+ EXEC SQL SELECT
+ ServerVersion, IFVersion
+ INTO
+ :rasver1, :schemaver1
+ FROM
+ RAS_ADMIN
+ WHERE
+ Architecture = :myArchitecture;
+ TALK( "-> rasver1=" << rasver1 << ", schemaver1=" << schemaver1 );
+ if (SQLCODE != SQLOK)
+ {
+ check("DatabaseIf::baseDBMSOpen() check schema\0");
+ // this error is not supported by PG -- PB 2005-jan-07
+ // if (SQLCODE == SQLTABLEUNKNOWN)...
+
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMInit::logOut << "The Database is incompatible with the current RasServer." << std::endl \
+ << "Database has no entry for the current platform." << std::endl \
+ << "You are using rasserver:" << std::endl \
+ << "\tversion " << RMANVERSION << std::endl \
+ << "\tschema " << RASSCHEMAVERSION << std::endl \
+ << "\tplatform " << RASARCHITECTURE << std::endl;
+ EXEC SQL DECLARE admincursor CURSOR FOR
+ SELECT
+ ServerVersion, IFVersion, Architecture
+ FROM
+ RAS_ADMIN;
+ EXEC SQL OPEN admincursor;
+ do
+ {
+ (void) memset( arch1, '\0', (size_t) sizeof(arch1) ); // just to make sure string is terminated
+ EXEC SQL FETCH admincursor INTO :rasver1, :schemaver1, :arch1;
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE != SQLNODATAFOUND)
+ {
+ check("DatabaseIf::checkCompatibility()\0");
+ RMInit::logOut << "DBMS Error occured during compatibility check." << std::endl \
+ << "Please see Debug Log for additional information." << std::endl;
+ EXEC SQL CLOSE admincursor;
+ generateException();
+ }
+ break;
+ }
+ RMInit::logOut << "Found database entries for rasserver:" << std::endl \
+ << "\tversion " << rasver1 << std::endl \
+ << "\tschema " << schemaver1 << std::endl \
+ << "\tplatform " << arch1 << std::endl << std::endl \
+ << "Please see Migration Documentation." << std::endl;
+ } while (true);
+
+ EXEC SQL CLOSE admincursor;
+ throw r_Error(DATABASE_INCOMPATIBLE);
+ }
+ else
+ {
+ RMInit::logOut << "DBMS Error occured during compatibility check." << std::endl \
+ << "Please see Debug Log for additional information." << std::endl;
+ generateException();
+ }
+ }
+ else
+ {
+ if (schemaver1 != RASSCHEMAVERSION)
+ {
+ RMInit::logOut << "The Database is incompatible with the current RasServer." << std::endl \
+ << "The database was generated with:" << std::endl \
+ << "\tversion " << rasver1 << std::endl \
+ << "\tschema " << schemaver1 << std::endl \
+ << "\tplatform " << arch1 << std::endl << std::endl \
+ << "You are using rasserver:" << std::endl \
+ << "\tversion " << RMANVERSION << std::endl \
+ << "\tschema " << RASSCHEMAVERSION << std::endl \
+ << "\tplatform " << RASARCHITECTURE << std::endl \
+ << "Please see Migration Documentation." << std::endl;
+ throw r_Error(DATABASE_INCOMPATIBLE);
+ }
+#if 0 // do not check against release, v6 has same schema as v5! -- PB 2005-sep-18
+ // check only against major release number -- PB 2003-sep-08
+ if (rasver1/1000 != RMANVERSION/1000)
+ {
+ RMInit::logOut << "The Database is incompatible with the current RasServer." << std::endl \
+ << "The database was generated with:" << std::endl \
+ << "\tversion " << rasver1 << std::endl \
+ << "\tschema " << schemaver1 << std::endl \
+ << "\tplatform " << arch1 << std::endl << std::endl \
+ << "You are using rasserver:" << std::endl \
+ << "\tversion " << RMANVERSION << std::endl \
+ << "\tschema " << RASSCHEMAVERSION << std::endl \
+ << "\tplatform " << RASARCHITECTURE << std::endl \
+ << "Please see Migration Documentation." << std::endl;
+ throw r_Error(DATABASE_INCOMPATIBLE);
+ }
+#endif // 0
+ }
+
+ LEAVE( "DatabaseIf::checkCompatibility" );
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "checkComptatibility()");
+}
+
+bool
+DatabaseIf::isConsistent() throw (r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "isConsistent()");
+ ENTER( "DatabaseIf::isConsistent" );
+
+ bool retval=true;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long nextoid;
+ long checkoid; // was: double -- PB 2005-jul-12
+ short oidind;
+ char name2[255]; // must be able to hold counterNames elements, see oidif.cc
+ EXEC SQL END DECLARE SECTION;
+ nextoid = 0;
+ checkoid = 0;
+ oidind = 0;
+
+ (void) strncpy( name2, (char*) OId::counterNames[OId::DBMINTERVALOID], (size_t) sizeof(name2) );
+ TALK( "EXEC SQL SELECT NextValue INTO :nextoid FROM RAS_COUNTERS WHERE CounterName = " << name2 );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM
+ RAS_COUNTERS
+ WHERE
+ CounterName = :name2;
+ TALK( "-> nextoid=" << nextoid );
+ if (check("DatabaseIf::isConsistent() SELECT DBMINTERVALOID"))
+ generateException();
+
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(DomainId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_DOMAINS;
+ checkoid = 0;
+ TALK( "SELECT DomainId..." );
+ EXEC SQL SELECT DomainId INTO :checkoid INDICATOR :oidind
+ FROM RAS_DOMAINS
+ ORDER BY DomainId DESC LIMIT 1;
+ TALK( "-> SQLCODE=" << SQLCODE );
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(DomainId)");
+ generateException();
+ }
+ if ((checkoid > nextoid) && (oidind == 0))
+ {
+ RMInit::logOut << "The administrative tables for Domain Data is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_DOMAINS : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::MDDOID], (size_t) sizeof(name2) );
+ TALK( "SELECT NextValue FROM RAS_COUNTERS..." );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT MDDOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(MDDId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_MDDOBJECTS;
+ checkoid = 0;
+ TALK( "SELECT MDDId FROM RAS_MDDOBJECTS..." );
+ EXEC SQL SELECT MDDId INTO :checkoid INDICATOR :oidind
+ FROM RAS_MDDOBJECTS
+ ORDER BY MDDId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(MDDId)");
+ generateException();
+ }
+
+ if ((checkoid > nextoid) && (oidind == 0))
+ {
+ RMInit::logOut << "The administrative tables for MDD Objects is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_MDDOBJECTS : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::MDDCOLLOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT MDDCollOId"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(MDDCollId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_MDDCOLLNAMES;
+ checkoid = 0;
+ TALK( "SELECT MDDCollId FROM RAS_MDDCOLLNAMES..." );
+ EXEC SQL SELECT MDDCollId INTO :checkoid INDICATOR :oidind
+ FROM RAS_MDDCOLLNAMES
+ ORDER BY MDDCollId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(MDDCollId)");
+ generateException();
+ }
+
+ if ((checkoid > nextoid) && (oidind == 0))
+ {
+ RMInit::logOut << "The administrative tables for MDD Collections is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_MDDCOLLNAMES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::MDDTYPEOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT MDDTYPEOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(MDDTypeOId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_MDDTYPES;
+ checkoid = 0;
+ TALK( "SELECT MDDTypeOId FROM RAS_MDDTYPES..." );
+ EXEC SQL SELECT MDDTypeOId INTO :checkoid INDICATOR :oidind
+ FROM RAS_MDDTYPES
+ ORDER BY MDDTypeOId DESC LIMIT 1;
+ TALK( "SELECT MDDTypeOId FROM RAS_MDDTYPES..." );
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(MDDTypeOId)");
+ generateException();
+ }
+
+ if (checkoid > nextoid)
+ {
+ RMInit::logOut << "The administrative tables for MDDTypes is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_MDDTYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::MDDBASETYPEOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT MDDBASETYPEOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(MDDBaseTypeOId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_MDDBASETYPES;
+ checkoid = 0;
+ TALK( "SELECT MDDBaseTypeOId FROM RAS_MDDBASETYPES..." );
+ EXEC SQL SELECT MDDBaseTypeOId INTO :checkoid INDICATOR :oidind
+ FROM RAS_MDDBASETYPES
+ ORDER BY MDDBaseTypeOId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(MDDBaseTypeOId)");
+ generateException();
+ }
+
+ if (checkoid > nextoid)
+ {
+ RMInit::logOut << "The administrative tables for MDDBaseTypes is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_MDDBASETYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::MDDDIMTYPEOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT MDDDIMTYPEOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(MDDDimTypeOId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_MDDDIMTYPES;
+ checkoid = 0;
+ TALK( "SELECT MDDDimTypeOId FROM RAS_MDDDIMTYPES..." );
+ EXEC SQL SELECT MDDDimTypeOId INTO :checkoid INDICATOR :oidind
+ FROM RAS_MDDDIMTYPES
+ ORDER BY MDDDimTypeOId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(MDDDimTypeOId)");
+ generateException();
+ }
+
+ if (checkoid > nextoid)
+ {
+ RMInit::logOut << "The administrative tables for MDDDimensionTypes is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_MDDDIMTYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::MDDDOMTYPEOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT MDDDOMTYPEOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(MDDDomTypeOId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_MDDDOMTYPES;
+ checkoid = 0;
+ TALK( "SELECT MDDDomTypeOId FROM RAS_MDDDOMTYPES..." );
+ EXEC SQL SELECT MDDDomTypeOId INTO :checkoid INDICATOR :oidind
+ FROM RAS_MDDDOMTYPES
+ ORDER BY MDDDomTypeOId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(MDDDomTypeId)");
+ generateException();
+ }
+
+ if (checkoid > nextoid)
+ {
+ RMInit::logOut << "The administrative tables for MDDDomainTypes is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_MDDDOMTYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::STRUCTTYPEOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT STRUCTTYPEOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(BaseTypeId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_BASETYPENAMES;
+ checkoid = 0;
+ TALK( "SELECT BaseTypeId FROM RAS_BASETYPENAMES..." );
+ EXEC SQL SELECT BaseTypeId INTO :checkoid INDICATOR :oidind
+ FROM RAS_BASETYPENAMES
+ ORDER BY BaseTypeId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(BaseTypeId)");
+ generateException();
+ }
+
+ if ((checkoid > nextoid) && (oidind == 0))
+ {
+ RMInit::logOut << "The administrative tables for StructTypes is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_BASETYPENAMES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::SETTYPEOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT SETTYPEOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(SetTypeId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_SETTYPES;
+ checkoid = 0;
+ TALK( "SELECT SetTypeId FROM RAS_SETTYPES..." );
+ EXEC SQL SELECT SetTypeId INTO :checkoid INDICATOR :oidind
+ FROM RAS_SETTYPES
+ ORDER BY SetTypeId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(SetTypeId)");
+ generateException();
+ }
+
+ if ((checkoid > nextoid) && (oidind == 0))
+ {
+ RMInit::logOut << "The administrative tables for MDDTypes is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_SETTYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::BLOBOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT BLOBOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(BlobId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_TILES;
+ checkoid = 0;
+ TALK( "SELECT BlobId FROM RAS_TILES..." );
+ EXEC SQL SELECT BlobId INTO :checkoid INDICATOR :oidind
+ FROM RAS_TILES
+ ORDER BY BlobId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(BlobId)");
+ generateException();
+ }
+
+ if ((checkoid > nextoid) && (oidind == 0))
+ {
+ RMInit::logOut << "The administrative tables for BLOB Data is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_TILES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::MDDHIERIXOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT MDDHIERIXOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(MDDObjIxOId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_HIERIX;
+ checkoid = 0;
+ TALK( "SELECT MDDObjIxOId FROM RAS_HIERIX..." );
+ EXEC SQL SELECT MDDObjIxOId INTO :checkoid INDICATOR :oidind
+ FROM RAS_HIERIX
+ ORDER BY MDDObjIxOId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(MDDObjIxOId)");
+ generateException();
+ }
+
+ if (checkoid > (nextoid * 512 + OId::MDDHIERIXOID))
+ {
+ RMInit::logOut << "The administrative tables for hierarchical MDD indexes is inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_HIERIX : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << (nextoid * 512 + OId::MDDHIERIXOID) << std::endl;
+ retval=false;
+ }
+ checkoid = 0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ if(retval)
+ {
+ (void) strncpy( name2, (char*) OId::counterNames[OId::STORAGEOID], (size_t) sizeof(name2) );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name2;
+ if (check("DatabaseIf::isConsistent() SELECT STORAGEOID"))
+ generateException();
+ // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12
+ // EXEC SQL SELECT MAX(StorageId) INTO :checkoid INDICATOR :oidind
+ // FROM RAS_STORAGE;
+ checkoid=0;
+ TALK( "SELECT StorageId FROM RAS_STORAGE..." );
+ EXEC SQL SELECT StorageId INTO :checkoid INDICATOR :oidind
+ FROM RAS_STORAGE
+ ORDER BY StorageId DESC LIMIT 1;
+ // now "no data" means no error, but that we need to initialize the empty table
+ if (SQLCODE < 0)
+ {
+ check("DatabaseIf::isConsistent() SELECT MAX(StorageId)");
+ generateException();
+ }
+
+ if ((checkoid > nextoid) && (oidind == 0))
+ {
+ RMInit::logOut << "Fatal error: administrative tables for MDD storage structures are inconsistent. Please call support." << std::endl;
+ RMInit::dbgOut << std::endl << "Counter in RAS_STORAGE : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl;
+ retval=false;
+ }
+ checkoid=0;
+ nextoid=0;
+ oidind=0;
+ }
+
+ LEAVE( "DatabaseIf::isConsistent, retval=" << retval );
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "isConsistent() " << retval);
+ return retval;
+}
+
+void
+DatabaseIf::createDB(const char* dbName, const char* schemaName, const char* volumeName) throw(r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "create(" << dbName << ", " << schemaName << ", " << volumeName << ")");
+ ENTER( "DatabaseIf::createDB, dbName=" << dbName << ", schemaName=" << schemaName << ", volumeName=" << volumeName );
+
+ int i=0;
+ EXEC SQL BEGIN DECLARE SECTION;
+ long id;
+ long idd;
+ char name[255];
+ EXEC SQL END DECLARE SECTION;
+
+ name[0] = '\0'; // initialize to empty string
+
+ try
+ {
+ if (AdminIf::getCurrentDatabaseIf() != 0)
+ {
+ RMDBGMIDDLE(5, RMDebug::module_adminif, "DatabaseIf", "another database is open");
+ TALK( "Error: another database is open" );
+ throw r_Error(r_Error::r_Error_DatabaseOpen);
+ }
+ connect();
+ TALK( "EXEC SQL BEGIN WORK;");
+ EXEC SQL BEGIN WORK;
+ if(check("DatabaseIf::create() BEGIN WORK\0"))
+ generateException();
+
+/* not used, see comment with databaseExists()
+ // does database exist already?
+ if (databaseExists(dbName))
+ {
+ RMDBGMIDDLE(5, RMDebug::module_adminif, "DatabaseIf", "database already exists");
+ RMInit::logOut << "Database creation failed: database exists already." << std::endl;
+ TALK( "Error: database exists." );
+ throw r_Error(DATABASE_EXISTS);
+ }
+*/
+
+ // --- start table/index creation ------------------------------
+
+ // no index here because there is only one entry in the table
+ TALK( "EXEC SQL CREATE TABLE RAS_ADMIN ( IFVersion INTEGER NOT NULL, Architecture VARCHAR(20) NOT NULL, ServerVersion INTEGER NOT NULL) " );
+ EXEC SQL CREATE TABLE RAS_ADMIN (
+ IFVersion INTEGER NOT NULL,
+ Architecture VARCHAR(20) NOT NULL,
+ ServerVersion INTEGER NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_ADMIN\0"))
+ generateException();
+
+ id = RASSCHEMAVERSION;
+ idd = RMANVERSION;
+ (void) strncpy( name, RASARCHITECTURE, (size_t) sizeof(name) );
+
+ TALK( "EXEC SQL INSERT INTO RAS_ADMIN (IFVersion, Architecture, ServerVersion) VALUES (" << id << ", " << name << ", " << idd << ")" );
+ EXEC SQL INSERT INTO RAS_ADMIN (IFVersion, Architecture, ServerVersion) VALUES (:id, :name, :idd);
+ if(check("DatabaseIf::create() INSERT INTO RAS_ADMIN\0"))
+ generateException();
+
+ // no index here because there is only 20 entries in the table
+ TALK( "EXEC SQL CREATE TABLE RAS_COUNTERS ( NextValue INTEGER NOT NULL, CounterName VARCHAR(20) NOT NULL)" );
+ EXEC SQL CREATE TABLE RAS_COUNTERS (
+ NextValue INTEGER NOT NULL,
+ CounterName VARCHAR(20) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_COUNTERS\0"))
+ generateException();
+
+ // initialising RAS_COUNTERS
+ for(i = 1; i < OId::maxCounter; i++)
+ {
+ (void) strncpy( name, (char*) OId::counterNames[i], (size_t) sizeof(name) );
+ id = 1;
+ TALK( "EXEC SQL INSERT INTO RAS_COUNTERS (CounterName, NextValue) VALUES (" << name << "," << id << ")" );
+ EXEC SQL INSERT INTO RAS_COUNTERS (CounterName, NextValue) VALUES (:name, :id);
+ if(check("DatabaseIf::create() INSERT INTO RAS_COUNTERS\0"))
+ generateException();
+ }
+
+ TALK( "...and several more tables..." );
+
+ // relblobif
+ EXEC SQL CREATE TABLE RAS_TILES (
+ BlobId INTEGER NOT NULL,
+ DataFormat INTEGER,
+ Tile oid
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_TILES\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_TILES_IX
+ ON RAS_TILES (BlobId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_TILES_IX\0"))
+ generateException();
+
+ //ras_itiles
+ EXEC SQL CREATE TABLE RAS_ITILES (
+ ITileId INTEGER NOT NULL,
+ ITile oid
+ );
+ if (check("DatabaseIf::create() CREATE TABLE RAS_ITILES\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_ITILES_IX
+ ON RAS_ITILES (ITileId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_ITILES_IX\0"))
+ generateException();
+
+ // relcatalogif
+ EXEC SQL CREATE TABLE RAS_MDDTYPES (
+ MDDTypeOId DEC(15,0) NOT NULL,
+ MDDTypeName VARCHAR(254) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_MDDTYPES\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_MDDTYPES_IX
+ ON RAS_MDDTYPES (MDDTypeOId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDTYPES_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_ITMAP (
+ TileId INTEGER NOT NULL,
+ IndexId INTEGER NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_ITMAP\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_ITMAP_IX
+ ON RAS_ITMAP (TileId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_ITMAP_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_MDDBASETYPES (
+ MDDBaseTypeOId DEC(15,0) NOT NULL,
+ BaseTypeId DEC(15,0) NOT NULL,
+ MDDTypeName VARCHAR(254) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_MDDBASETYPES\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_MDDBASETYPES_IX
+ ON RAS_MDDBASETYPES (MDDBaseTypeOId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDBASETYPES_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_MDDDIMTYPES (
+ MDDDimTypeOId DEC(15,0) NOT NULL,
+ BaseTypeId DEC(15,0) NOT NULL,
+ Dimension INTEGER NOT NULL,
+ MDDTypeName VARCHAR(254) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_MDDDIMTYPES\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_MDDDIMTYPES_IX
+ ON RAS_MDDDIMTYPES (MDDDimTypeOId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDDIMTYPES_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_MDDDOMTYPES (
+ MDDDomTypeOId DEC(15,0) NOT NULL,
+ BaseTypeId DEC(15,0) NOT NULL,
+ DomainId INTEGER NOT NULL,
+ MDDTypeName VARCHAR(254) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_MDDDOMAINTYPES\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_MDDDOMTYPES_IX
+ ON RAS_MDDDOMTYPES (MDDDomTypeOId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDDOMTYPES_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_SETTYPES (
+ SetTypeId INTEGER NOT NULL,
+ MDDTypeOId DEC(15,0) NOT NULL,
+ SetTypeName VARCHAR(254) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_SETTYPES\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_SETTYPES_IX
+ ON RAS_SETTYPES (SetTypeId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_SETTYPES_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_BASETYPENAMES (
+ BaseTypeId SMALLINT NOT NULL,
+ BaseTypeName VARCHAR (254) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_BASETYPENAMES\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_BASETYPENAMES_IX
+ ON RAS_BASETYPENAMES (BaseTypeId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_BASETYPENAMES_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_BASETYPES (
+ BaseTypeId INTEGER NOT NULL,
+ Count SMALLINT NOT NULL,
+ ContentType DEC(15,0) NOT NULL,
+ ContentTypeName VARCHAR (254) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_BASETYPES\0"))
+ generateException();
+
+ EXEC SQL CREATE INDEX RAS_BASETYPESC_IX
+ ON RAS_BASETYPES (BaseTypeId);
+ if(check("DatabaseIf::create() CREATE INDEX RAS_BASETYPES_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_BASETYPES_IX
+ ON RAS_BASETYPES (BaseTypeId, Count);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_BASETYPES_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_DOMAINS (
+ DomainId INTEGER NOT NULL,
+ Dimension INTEGER NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_DOMAINS\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_DOMAINS_IX
+ ON RAS_DOMAINS (DomainId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_DOMAINS_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_DOMAINVALUES (
+ DomainId INTEGER NOT NULL,
+ DimensionCount INTEGER NOT NULL,
+ Low INTEGER,
+ High INTEGER
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_DOMAINVALUES\0"))
+ generateException();
+
+ EXEC SQL CREATE INDEX RAS_DOMAINVALUESC_IX
+ ON RAS_DOMAINVALUES (DomainId);
+ if(check("DatabaseIf::create() CREATE INDEX RAS_DOMAINVALUESC_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_DOMAINVALUES_IX
+ ON RAS_DOMAINVALUES (DomainId, DimensionCount);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_DOMAINVALUES_IX\0"))
+ generateException();
+
+ // relmddif
+ EXEC SQL CREATE TABLE RAS_MDDCOLLECTIONS (
+ MDDId INTEGER NOT NULL,
+ MDDCollId INTEGER NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_MDDCOLLECTIONS\0"))
+ generateException();
+
+ EXEC SQL CREATE INDEX RAS_COLLECTIONSC_IX
+ ON RAS_MDDCOLLECTIONS (MDDCOllId);
+ if(check("DatabaseIf::create() CREATE INDEX RAS_COLLECTIONSC_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_COLLECTIONS_IX
+ ON RAS_MDDCOLLECTIONS (MDDCOllId, MDDId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_COLLECTIONS_IX\0"))
+ generateException();
+
+ // referes to MDDSet
+ EXEC SQL CREATE TABLE RAS_MDDCOLLNAMES (
+ MDDCollId INTEGER NOT NULL,
+ SetTypeId INTEGER NOT NULL,
+ MDDCollName VARCHAR(254)
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_MDDCOLLNAMES\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_MDDCOLLNAMES_IX
+ ON RAS_MDDCOLLNAMES (MDDCollId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDCOLLNAMES_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_MDDOBJECTS (
+ MDDId INTEGER NOT NULL,
+ BaseTypeOId DEC(15,0) NOT NULL,
+ DomainId INTEGER NOT NULL,
+ PersRefCount INTEGER NOT NULL,
+ StorageOId DEC(15,0) NOT NULL,
+ NodeOId DEC(15,0)
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_MDDOBJECTS\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_MDDOBJECTS_IX
+ ON RAS_MDDOBJECTS (MDDId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDOBJECTS_IX\0"))
+ generateException();
+
+ //relstorageif
+ EXEC SQL CREATE TABLE RAS_STORAGE (
+ StorageId INTEGER NOT NULL,
+ DomainId INTEGER,
+ TileSize INTEGER,
+ PCTMin INTEGER,
+ PCTMax INTEGER,
+ IndexSize INTEGER,
+ IndexType SMALLINT,
+ TilingScheme SMALLINT,
+ DataFormat SMALLINT
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_MDDOBJECTS\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_STORAGE_IX
+ ON RAS_STORAGE (StorageId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_STORAGE_IX\0"))
+ generateException();
+
+ // relindexif
+ // may not be needed
+ EXEC SQL CREATE TABLE RAS_HIERIX (
+ MDDObjIxOId DEC(15,0) NOT NULL,
+ NumEntries SMALLINT NOT NULL,
+ Dimension SMALLINT NOT NULL,
+ ParentOId DEC(15,0) NOT NULL,
+ IndexSubType SMALLINT NOT NULL,
+ DynData OID
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_HIERIX\0"))
+ generateException();
+
+ // Note: table RAS_HIERIXDYN is not needed, we put each index node into the above DynData blob
+
+ EXEC SQL CREATE TABLE RAS_UDFBODY (
+ UOId DEC(15,0) NOT NULL,
+ Name VARCHAR(254) NOT NULL,
+ Body CHAR(3700) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_UDFBODY\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_UDFBODY_IX
+ ON RAS_UDFBODY (UOId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFBODY_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_UDFARGS (
+ UOId DEC(15,0) NOT NULL,
+ ArgNum SMALLINT NOT NULL,
+ ArgName VARCHAR(254) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_UDFARGS\0"))
+ generateException();
+
+ EXEC SQL CREATE INDEX RAS_UDFARGSC_IX
+ ON RAS_UDFARGS(UOId);
+ if(check("DatabaseIf::create() CREATE INDEX RAS_UDFARGSC_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_UDFARGS_IX
+ ON RAS_UDFARGS(UOId, ArgNum);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFARGS_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_UDFPACKAGE (
+ UOId DEC(15,0) NOT NULL,
+ Name VARCHAR(254) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_UDFPACKAGE\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_UDFPACKAGEN_IX
+ ON RAS_UDFPACKAGE (Name);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFPACKAGEN_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_UDFPACKAGEO_IX
+ ON RAS_UDFPACKAGE (UOId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFPACKAGEO_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE TABLE RAS_UDFNSCONTENT (
+ UOId DEC(15,0) NOT NULL,
+ UDFOId DEC(15,0) NOT NULL
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_UDFNSCONTENT\0"))
+ generateException();
+
+ EXEC SQL CREATE INDEX RAS_UDFNSCONTENTC_IX
+ ON RAS_UDFNSCONTENT(UOId);
+ if(check("DatabaseIf::create() CREATE INDEX RAS_UDFNSCONTENTC_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_UDFNSCONTENT_IX
+ ON RAS_UDFNSCONTENT(UOId, UDFOId);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFNSCONTENT_IX\0"))
+ generateException();
+
+ // We need 1 byte more because the first character may not be a \0 -> the first byte is always 13
+ // note: this does not hold for PG, but we keep it to remain cross-platform consistent in data
+ // note2: we use blob instead of varchar because the latter can hold only ascii data in PG
+ EXEC SQL CREATE TABLE RAS_RCINDEXDYN (
+ Id DEC(15,0) NOT NULL,
+ Count DEC(3,0) NOT NULL,
+ DynData oid
+ );
+ if(check("DatabaseIf::create() CREATE TABLE RAS_RCINDEXDYN\0"))
+ generateException();
+
+ EXEC SQL CREATE INDEX RAS_RCINDEXDYNC_IX
+ ON RAS_RCINDEXDYN (Id);
+ if(check("DatabaseIf::create() CREATE INDEX RAS_RCINDEXDYNC_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE UNIQUE INDEX RAS_RCINDEXDYN_IX
+ ON RAS_RCINDEXDYN (Id, Count);
+ if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_RCINDEXDYN_IX\0"))
+ generateException();
+
+ EXEC SQL CREATE VIEW RAS_MDDTYPES_VIEW
+ (MDDTypeOId, MDDTypeName)
+ AS
+ SELECT
+ MDDTypeOId * 512 + 3, MDDTypeName
+ FROM
+ RAS_MDDTYPES
+ UNION
+ SELECT
+ MDDBaseTypeOId * 512 + 4, MDDTypeName
+ FROM
+ RAS_MDDBASETYPES
+ UNION
+ SELECT
+ MDDDimTypeOId * 512 + 5, MDDTypeName
+ FROM
+ RAS_MDDDIMTYPES
+ UNION
+ SELECT
+ MDDDomTypeOId * 512 + 6, MDDTypeName
+ FROM
+ RAS_MDDDOMTYPES;
+ if(check("DatabaseIf::create() CREATE VIEW"))
+ generateException();
+
+ TALK( "EXEC SQL COMMIT WORK" );
+ EXEC SQL COMMIT WORK;
+ if(check("DatabaseIf::create() COMMIT WORK"))
+ generateException();
+
+ disconnect();
+ }
+ catch (r_Error& err)
+ {
+ // abort TA, ignore any error there
+ TALK( "EXEC SQL ABORT WORK;");
+ EXEC SQL ABORT WORK;
+
+ RMDBGMIDDLE(0, RMDebug::module_adminif, "DatabaseIf", "create(" << dbName << ", " << schemaName << ", " << volumeName << ") error caught " << err.what() << " " << err.get_errorno());
+ throw; // rethrow exception
+ }
+
+ LEAVE( "DatabaseIf::createDB, SQLCODE=" << SQLCODE );
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "create(" << dbName << ", " << schemaName << ", " << volumeName << ")");
+}
+
+void
+DatabaseIf::destroyDB(const char* dbName) throw(r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "destroyDB(" << dbName << ")");
+ ENTER( "DatabaseIf::destroyDB, dbName=" << dbName );
+
+ if (AdminIf::getCurrentDatabaseIf() != 0)
+ {
+ RMDBGMIDDLE(5, RMDebug::module_adminif, "DatabaseIf", "another database is already open");
+ LEAVE( "Error: another database is already open" );
+ RMInit::logOut << "Another database is already open." << std::endl << "Cannot destroy database " << dbName << "." << std::endl;
+ throw r_Error(r_Error::r_Error_DatabaseOpen);
+ }
+ connect();
+
+/* this check is omitted, see databaseExists() comment
+ // terminate processing of database was not found -- PB 2003-sep-05
+ // try
+ // {
+ if (!databaseExists(dbName))
+ {
+ RMDBGMIDDLE(5, RMDebug::module_adminif, "DatabaseIf", "unknown database");
+ LEAVE( "Error: Database unknown" );
+ RMInit::logOut << "Database " << dbName << " not found." << std::endl << "Cannot destroy database " << dbName << "." << std::endl;
+ throw r_Error(r_Error::r_Error_DatabaseUnknown);
+ }
+ // }
+ // catch (r_Error& err)
+ // {
+ // RMInit::logOut << "Caught exception while trying to check for existence of database: " << err.what() << " " << err.get_errorno() << " " << err.get_kind() << endl;
+ // RMInit::logOut << "Continuing with destruction of the database" << endl;
+ // TALK( "Continuing destruction of the database after error " << err.get_errorno() << " " << err.get_kind() );
+ // }
+*/
+
+ EXEC SQL BEGIN WORK;
+ check("DatabaseIf::destroyDB() BEGIN WORK\0");
+
+ EXEC SQL DROP VIEW RAS_MDDTYPES_VIEW;
+ check("DatabaseIf::destroyDB() DROP VIEW RAS_MDDTYPES_VIEW\0");
+
+ // relblobif
+ EXEC SQL DROP TABLE RAS_TILES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_TILES\0");
+
+ EXEC SQL DROP TABLE RAS_ITILES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_ITILES\0");
+
+ // relcatalogif
+ EXEC SQL DROP TABLE RAS_MDDTYPES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDTYPES\0");
+
+ EXEC SQL DROP TABLE RAS_ITMAP;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_ITMAP\0");
+
+ EXEC SQL DROP TABLE RAS_MDDBASETYPES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDBASETYPES\0");
+
+ EXEC SQL DROP TABLE RAS_MDDDIMTYPES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDDIMENSIONTYPES\0");
+
+ EXEC SQL DROP TABLE RAS_MDDDOMTYPES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDDOMAINTYPES\0");
+
+ EXEC SQL DROP TABLE RAS_SETTYPES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_SETTYPES\0");
+
+ EXEC SQL DROP TABLE RAS_BASETYPENAMES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_BASETYPENAMES\0");
+
+ EXEC SQL DROP INDEX RAS_BASETYPES_IX;
+ check("DatabaseIf::destroyDB() DROP INDEX RAS_BASETYPES_IX\0");
+
+ EXEC SQL DROP TABLE RAS_BASETYPES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_BASETYPES\0");
+
+ EXEC SQL DROP TABLE RAS_DOMAINS;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_DOMAINS\0");
+
+ EXEC SQL DROP TABLE RAS_DOMAINVALUES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_DOMAINVALUES\0");
+
+ // relmddif
+ // referes to DBMDDCollOIdEntry
+ EXEC SQL DROP TABLE RAS_MDDCOLLECTIONS;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDCOLLECTIONS\0");
+
+ // referes to MDDSet
+ EXEC SQL DROP TABLE RAS_MDDCOLLNAMES;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDCOLLNAMES\0");
+
+ EXEC SQL DROP TABLE RAS_MDDOBJECTS;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDOBJECTS\0");
+
+ // relindexif
+ // may not be needed
+ EXEC SQL DROP TABLE RAS_HIERIX;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_HIERIX\0");
+
+ EXEC SQL DROP INDEX RAS_HIERIXDYN_IX;
+ check("DatabaseIf::destroyDB() DROP INDEX RAS_HIERIXDYN_IX\0");
+
+ EXEC SQL DROP TABLE RAS_HIERIXDYN;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_HIERIXDYN\0");
+
+ EXEC SQL DROP TABLE RAS_STORAGE;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_STORAGE\0");
+
+ EXEC SQL DROP TABLE RAS_COUNTERS;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_COUNTERS\0");
+
+ EXEC SQL DROP TABLE RAS_UDFBODY;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_UDFBODY");
+
+ EXEC SQL DROP TABLE RAS_UDFARGS;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_UDFARGS");
+
+ EXEC SQL DROP TABLE RAS_UDFPACKAGE;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_UDFPACKAGE");
+
+ EXEC SQL DROP TABLE RAS_UDFNSCONTENT;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_UDFNSCONTENT");
+
+ EXEC SQL DROP INDEX RAS_RCINDEXDYN_IX;
+ check("DatabaseIf::destroyDB() DROP INDEX RAS_RCINDEXDYN_IX\0");
+
+ EXEC SQL DROP TABLE RAS_RCINDEXDYN;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_RCINDEXDYN\0");
+
+ EXEC SQL DROP TABLE RAS_ADMIN;
+ check("DatabaseIf::destroyDB() DROP TABLE RAS_ADMIN\0");
+
+ EXEC SQL COMMIT WORK;
+ check("DatabaseIf::destroyDB() COMMIT\0");
+
+ disconnect();
+
+ LEAVE( "DatabaseIf::destroyDB" );
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "destroyDB(" << dbName << ")");
+}
+
+/**
+This test is omitted because in PG it would fail the transaction,
+hence making continuation impossible.
+On the other hand, if the database really doesn't exist
+/ exists already (whatever is the erroneous situation)
+the transaction will fail for the very same reason.
+And here we can't decide what situation is good / not good!
+The only thing we lose is an appropriate error message
+on the top-level situation of the whole database.
+
+To make sure that no invocation of this function leads to erroneous results, we disable it.
+**/
+
+#if 0 // disable function to avoid invocation -- PB 2005-feb05
+bool
+DatabaseIf::databaseExists(const char* dbname) throw (r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "databaseExists(" << dbname << ")");
+ ENTER( "DatabaseIf::databaseExists, dbName(ignored)=" << dbname );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long nextoid;
+ short oidind;
+ char name1[255]; // must be large enough to hold counterNames, see oidif.cc
+ EXEC SQL END DECLARE SECTION;
+ bool retval = true;
+
+ (void) strncpy( name1, (char*) OId::counterNames[OId::DBMINTERVALOID], (size_t) sizeof(name1) );
+ TALK( "EXEC SQL SELECT NextValue INTO :nextoid FROM RAS_COUNTERS WHERE CounterName = " << name1 << ";" )
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name1;
+ retval = (SQLCODE == SQLOK) ? true : false;
+
+ LEAVE( "DatabaseIf::databaseExists, SQLCODE=" << SQLCODE << ", retval=" << retval );
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "databaseExists(" << dbname << ") retval " << retval);
+
+ return retval;
+}
+#endif // 0
diff --git a/reladminif/databaseifcommon.cc b/reladminif/databaseifcommon.cc
new file mode 100644
index 0000000..b3e3097
--- /dev/null
+++ b/reladminif/databaseifcommon.cc
@@ -0,0 +1,242 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+// This is -*- C++ -*-
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * Contains all code that is shared by the database interface implementations
+ *
+ *
+ * COMMENTS:
+ * - schema version depending on release doesn't make sense; rather change
+ * it when the schema _really_ changes!
+ *
+ ***********************************************************************/
+
+
+#include <string.h>
+#include <malloc.h>
+
+#include "globals.hh" // DEFAULT_DBNAME
+
+#include "databaseif.hh"
+#include "adminif.hh"
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "externs.h"
+#include "sqlerror.hh"
+#include "raslib/error.hh"
+#include "relcatalogif/alltypes.hh"
+
+// defined in rasserver.cc
+extern char globalConnectId[256];
+
+const char* DatabaseIf::DefaultDatabaseName = DEFAULT_DBNAME;
+
+DatabaseIf::~DatabaseIf()
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "~DatabaseIf()");
+ if (isConnected())
+ {
+ baseDBMSClose();
+ }
+ if (myName)
+ {
+ free(myName);
+ myName = NULL;
+ }
+
+ connected = false;
+ opened = false;
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "~DatabaseIf()");
+}
+
+bool
+DatabaseIf::isConnected() const
+{
+ RMDBGONCE(4, RMDebug::module_adminif, "DatabaseIf", "isConnected() " << connected);
+ return connected;
+}
+
+bool
+DatabaseIf::isOpen() const
+{
+ RMDBGONCE(4, RMDebug::module_adminif, "DatabaseIf", "isOpen() " << opened);
+ return opened;
+}
+
+void
+DatabaseIf::open(const char* dbName) throw(r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "open(" << dbName << ")");
+
+ if (opened)
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "another database is already open");
+ throw r_Error(r_Error::r_Error_DatabaseOpen);
+ }
+ else
+ {
+ //cannot do any further error checking
+ if ( 0 ) // we allow any other database name -- strcmp(dbName, DefaultDatabaseName))
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "database name unknown");
+ RMInit::logOut << "b_DatabaseIf::open(" << dbName << ") dbName=" << dbName << std::endl;
+ throw r_Error(r_Error::r_Error_DatabaseUnknown);
+ }
+ else
+ {
+ opened = true;
+ myName = strdup(dbName);
+ }
+ }
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "open(" << dbName << ")");
+}
+
+void
+DatabaseIf::baseDBMSOpen() throw (r_Error)
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "baseDBMSOpen() " << ((myName)? myName:"NULL"));
+ if (connected)
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "databasename is already connected");
+ throw r_Error(r_Error::r_Error_TransactionOpen);
+ }
+#ifdef RMANDEBUG
+ if (AdminIf::getCurrentDatabaseIf())
+ {
+ RMDBGMIDDLE(0, RMDebug::module_adminif, "DatabaseIf", "baseDBMSOpen() CurrentDatabaseIf != 0");
+ RMInit::logOut << "Transaction begin:" << std::endl \
+ << "There seems to be another database connection active (Internal State 1)." << std::endl \
+ << "Please contact Customer support." << std::endl;
+ throw r_Error(DATABASE_OPEN);
+ }
+#endif
+ AdminIf::setCurrentDatabaseIf(this);
+ connect();
+ connected = true;
+
+#ifdef DBMS_PGSQL // cannot have this check in PostgreSQL -- PB 2005-jan-09
+ if (!databaseExists(myName))
+ {
+ RMInit::logOut << "Database " << ((myName)? myName: "NULL") << " unknown" << std::endl;
+ throw r_Error(r_Error::r_Error_DatabaseUnknown);
+ }
+#endif // DBMS_PGSQL
+
+#ifndef FASTCONNECT
+ checkCompatibility();
+ if (!isConsistent())
+ {
+ RMInit::logOut << "Database " << ((myName)? myName: "NULL") << " inconsistent" << std::endl;
+ throw r_Error(DATABASE_INCONSISTENT);
+ }
+#endif
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "baseDBMSOpen()");
+}
+
+void
+DatabaseIf::close()
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "close()");
+ opened = false;
+ if (myName)
+ {
+ free(myName);
+ myName = NULL;
+ }
+ if (connected)
+ {
+ disconnect();
+ connected = false;
+ }
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "close()");
+}
+
+void
+DatabaseIf::baseDBMSClose()
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "baseDBMSClose()");
+#ifdef RMANDEBUG
+ if (AdminIf::getCurrentDatabaseIf() == this)
+ {
+#endif
+ AdminIf::setCurrentDatabaseIf(0);
+#ifdef RMANDEBUG
+ }
+ else
+ {
+ //this happens when a transaction is killed by the server
+ RMDBGONCE(0, RMDebug::module_adminif, "DatabaseIf", "baseDBMSClose() current DatabaseIf != this");
+ }
+#endif
+ disconnect();
+ connected = false;
+ RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "baseDBMSClose()");
+}
+
+DatabaseIf::DatabaseIf()
+ : opened(false),
+ connected(false),
+ myName(NULL)
+{
+ RMDBGONCE(4, RMDebug::module_adminif, "DatabaseIf", "DatabaseIf()");
+}
+
+const char*
+DatabaseIf::getName() const
+{
+ RMDBGONCE(4, RMDebug::module_adminif, "DatabaseIf", "getName() " << ((myName)? myName:"NULL"));
+ return myName;
+}
+
+ostream&
+operator << (ostream& stream, DatabaseIf& db)
+{
+ stream << "DatabaseIf" << std::endl;
+ stream << "\tConnected To\t: " << ((db.getName())? db.getName():" ") << std::endl;
+ if (db.opened)
+ {
+ if (db.connected)
+ {
+ stream << "\tDatabase is really ONLINE" << std::endl;
+ }
+ else
+ {
+ stream << "\tDatabase is only FAKE ONLINE" << std::endl;
+ }
+ }
+ else
+ {
+ stream << "\tDatabase is OFFLINE" << std::endl;
+ }
+ return stream;
+}
+
+void
+DatabaseIf::garbage( )
+{
+ RMDBGONCE(0, RMDebug::module_adminif, "DatabaseIf", "garbage() NOT IMPLEMENTED");
+}
+
diff --git a/reladminif/dbnamedobject.cc b/reladminif/dbnamedobject.cc
new file mode 100644
index 0000000..1ad2472
--- /dev/null
+++ b/reladminif/dbnamedobject.cc
@@ -0,0 +1,179 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "mymalloc/mymalloc.h"
+
+/*****************************************************************************
+ *
+ *
+ * PURPOSE:
+ *
+ *
+ *
+ * COMMENTS:
+ * uses embedded SQL
+ *
+ *****************************************************************************/
+
+#include <string.h>
+#include <stdlib.h>
+#include "dbnamedobject.hh"
+#include "dbobject.hh"
+#include "raslib/rmdebug.hh"
+
+// Beware: keep this value less or equal to STRING_MAXLEN in externs.h!
+#define MAXNAMELENGTH_CONST 200
+short DBNamedObject::MAXNAMELENGTH = MAXNAMELENGTH_CONST;
+
+const char* DBNamedObject::defaultName="unamed object\0";
+
+void
+DBNamedObject::printStatus(unsigned int level, std::ostream& stream) const
+{
+ DBObject::printStatus(level, stream);
+ stream << " Name: " << myName;
+}
+
+DBNamedObject::DBNamedObject(const OId& id) throw (r_Error)
+ : DBObject(id),
+ myName(NULL),
+ myNameSize(0)
+{
+ RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject(" << myOId << ")");
+}
+
+DBNamedObject::DBNamedObject()
+ : DBObject(),
+ myNameSize(0),
+ myName(NULL)
+{
+ RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject()");
+ setName(defaultName);
+}
+
+DBNamedObject::DBNamedObject(const DBNamedObject& old)
+ : DBObject(old),
+ myNameSize(0),
+ myName(NULL)
+{
+ RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject(const DBNamedObject& old)");
+ setName(old.getName());
+}
+
+DBNamedObject::DBNamedObject(const char* name)
+ : DBObject(),
+ myNameSize(0),
+ myName(NULL)
+{
+ RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject(" << name << ")");
+ setName(name);
+}
+
+DBNamedObject::DBNamedObject(const OId& id, const char* name)
+ : DBObject(id),
+ myNameSize(0),
+ myName(NULL)
+{
+ RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject(" << myOId << ", " << name << ")");
+ setName(name);
+}
+
+DBNamedObject::~DBNamedObject()
+{
+ RMDBGENTER(9, RMDebug::module_adminif, "DBNamedObject", "~DBNamedObject() " << myOId);
+ if (myName)
+ {
+ free(myName);
+ myName = NULL;
+ }
+ myNameSize = 0;
+ RMDBGEXIT(9, RMDebug::module_adminif, "DBNamedObject", "~DBNamedObject() " << myOId);
+}
+
+DBNamedObject&
+DBNamedObject::operator=(const DBNamedObject& old)
+{
+ RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "operator=(" << old.getName() << ") " << myName);
+ if (this != &old)
+ {
+ DBObject::operator=(old);
+ setName(old.getName());
+ }
+ return *this;
+}
+
+const char*
+DBNamedObject::getName() const
+{
+ RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "getName() " << myName);
+ return myName;
+}
+
+void
+DBNamedObject::setName(const char* newname)
+{
+ RMDBGENTER(9, RMDebug::module_adminif, "DBNamedObject", "setName(" << newname << ")");
+ if (myName)
+ {
+ RMDBGMIDDLE(10, RMDebug::module_adminif, "DBNamedObject", "myName\t:" << myName);
+ free(myName);
+ myName=NULL;
+ }
+ int len = strlen(newname);
+ if (len > MAXNAMELENGTH)
+ len = MAXNAMELENGTH;
+ myName = (char*)mymalloc((len + 1) * sizeof(char));
+ myNameSize = (len + 1) * sizeof(char);
+ strncpy(myName, newname, len);
+ *(myName + len) = 0;
+ RMDBGEXIT(9, RMDebug::module_adminif, "DBNamedObject", "setName(" << myName << ")");
+}
+
+void
+DBNamedObject::setName(const short length, const char* data)
+{
+ RMDBGENTER(9, RMDebug::module_adminif, "DBNamedObject", "setName(" << length << ", data ) " << myOId);
+ if (myName)
+ {
+ RMDBGMIDDLE(10,RMDebug::module_adminif, "DBNamedObject", "myName\t:" << myName);
+ free(myName);
+ myName=NULL;
+ }
+ int len = 0;
+ if (length > MAXNAMELENGTH)
+ len = MAXNAMELENGTH;
+ else
+ len = length;
+ myName = (char*)mymalloc((len + 1) * sizeof(char));
+ myNameSize = (len + 1) * sizeof(char);
+ strncpy(myName, data, len);
+ *(myName + len) = 0;
+ RMDBGMIDDLE(10,RMDebug::module_adminif, "DBNamedObject", "myName\t:" << myName);
+ RMDBGEXIT(9, RMDebug::module_adminif, "DBNamedObject", "setName(" << length << ", data ) " << myOId);
+}
+
+r_Bytes
+DBNamedObject::getMemorySize() const
+{
+ return sizeof(char) * myNameSize + DBObject::getMemorySize() + sizeof(unsigned short);
+}
+
diff --git a/reladminif/dbnamedobject.hh b/reladminif/dbnamedobject.hh
new file mode 100644
index 0000000..654547c
--- /dev/null
+++ b/reladminif/dbnamedobject.hh
@@ -0,0 +1,121 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#ifndef _DBNAMEDOBJECT_HH_
+#define _DBNAMEDOBJECT_HH_
+
+class DBObject;
+class DBNamedObject;
+
+#include "dbobject.hh"
+
+//@ManMemo: Module: {\bf reladminif}.
+/*@Doc:
+Has functionality for setting the name of itsself from VARCHAR structures.
+Takes care of too long names.
+Implements set/getName functionality.
+*/
+
+class DBNamedObject : public DBObject
+ {
+ public:
+ DBNamedObject();
+ /*@Doc:
+ sets Name to defaultName
+ */
+
+ DBNamedObject(const OId& id) throw (r_Error);
+ /*@Doc:
+ only initializes itself
+ */
+
+ DBNamedObject(const DBNamedObject& old);
+ /*@Doc:
+ sets myName to the name of the old object
+ */
+
+ DBNamedObject(const char* name);
+ /*@Doc:
+ sets myName to name
+ */
+
+ DBNamedObject(const OId& id, const char* name);
+ /*@Doc:
+ sets myName to name and calls DBObject(OId). this is needed by MDDSet.
+ */
+
+ virtual ~DBNamedObject();
+ /*@Doc:
+ frees myName
+ */
+
+ const char* getName() const;
+ /*@Doc:
+ returns a pointer to myName.
+ */
+
+ static short MAXNAMELENGTH;
+ /*@Doc:
+ the maximum length of a name.
+ */
+
+ DBNamedObject& operator=(const DBNamedObject& old);
+ /*@Doc:
+ takes care of the name
+ */
+
+ virtual r_Bytes getMemorySize() const;
+ /*@Doc:
+ Should be revised not to include attribute sizes
+ */
+
+ virtual void printStatus(unsigned int level = 0, std::ostream& stream = std::cout) const;
+ /*@Doc:
+ prints the status of DBObject + Name: myName
+ */
+
+ protected:
+
+ void setName(const char* newname);
+ /*@Doc:
+ renames the object
+ */
+
+ void setName(const short length, const char* data);
+ /*@Doc:
+ sets the name from a VARCHAR structure
+ */
+
+ char* myName;
+ /*@Doc:
+ the name of the object
+ */
+
+ unsigned short myNameSize;
+ /*@Doc:
+ the size of the name
+ */
+
+ static const char* defaultName;
+ };
+
+#endif
diff --git a/reladminif/dbobject.cc b/reladminif/dbobject.cc
new file mode 100644
index 0000000..eabe794
--- /dev/null
+++ b/reladminif/dbobject.cc
@@ -0,0 +1,459 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * Code with embedded SQL for relational DBMS
+ *
+ *
+ * COMMENTS:
+ * none
+ *
+ ***********************************************************************/
+
+// mainly for ostringstream:
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <cstring>
+
+using namespace std;
+
+#include "objectbroker.hh"
+#include "dbobject.hh"
+#include "adminif.hh"
+#include "externs.h"
+#include "raslib/rmdebug.hh"
+#include "raslib/error.hh"
+#include "eoid.hh"
+
+#ifdef RMANBENCHMARK
+RMTimer DBObject::readTimer = RMTimer("DBObject","read");
+RMTimer DBObject::updateTimer = RMTimer("DBObject","update");
+RMTimer DBObject::insertTimer = RMTimer("DBObject","insert");
+RMTimer DBObject::deleteTimer = RMTimer("DBObject","delete");
+#endif
+
+const char*
+BinaryRepresentation::fileTag = "RMAN";
+
+void
+DBObject::printStatus(unsigned int level, std::ostream& stream) const
+ {
+ char* indent = new char[level*2 +1];
+ for (int j = 0; j < level*2 ; j++)
+ indent[j] = ' ';
+ indent[level*2] = '\0';
+
+ stream << indent;
+ stream << myOId;
+ delete[] indent;
+ indent=0;
+ }
+
+r_Bytes
+DBObject::getTotalStorageSize() const
+ {
+ return 0;
+ }
+
+r_Bytes
+DBObject::getMemorySize() const
+ {
+ return sizeof(DBObject);
+ }
+
+void
+DBObject::setCached(bool newCached)
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "setCached(" << (int)newCached << ") " << myOId);
+ _isCached = newCached;
+ }
+
+bool
+DBObject::isCached() const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "isCached()" << (int) _isCached)
+ return _isCached;
+ }
+
+void
+DBObject::destroy()
+ {
+ RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "destroy() " << myOId);
+#ifdef RMANDEBUG
+ OId tempid(myOId);
+#endif
+ if (referenceCount == 0)
+ {
+ if (!_isCached)
+ {
+ //exception may be possible when !isModified()
+ if (!AdminIf::isReadOnlyTA())
+ {
+ RMDBGMIDDLE(10, RMDebug::module_adminif, "DBObject", "deleting object " << myOId);
+ delete this;//is dynamic and may be deleted
+ }
+ else {
+ if (!_isPersistent)
+ {
+ RMDBGMIDDLE(10, RMDebug::module_adminif, "DBObject", "deleting object " << myOId);
+ //is dynamic and may be deleted
+ delete this;
+ }
+ }
+ }
+ }
+#ifdef RMANDEBUG
+ RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "destroy() " << tempid);
+#else
+ RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "destroy()");
+#endif
+ }
+
+void
+DBObject::release()
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "release() ");
+ //no dynamic memory
+ }
+
+void DBObject::incrementReferenceCount(void)
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "incrementReferenceCount() " << referenceCount);
+ referenceCount++;
+ }
+
+void DBObject::decrementReferenceCount(void)
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "decrementReferenceCount() " <<referenceCount);
+ referenceCount--;
+ if (referenceCount == 0)
+ destroy();
+ }
+
+int
+DBObject::getReferenceCount(void) const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "getReferenceCount() " <<referenceCount);
+ return referenceCount;
+ }
+
+//public:
+DBObject::DBObject()
+ : _isInDatabase(false),
+ _isPersistent(false),
+ _isModified(true),
+ _isCached(false),
+ referenceCount(0),
+ objecttype(OId::INVALID),
+ myOId(0)
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "DBObject() " << myOId);
+ }
+
+DBObject::DBObject(const DBObject& old)
+ : _isInDatabase(old._isInDatabase),
+ _isPersistent(old._isPersistent),
+ _isModified(old._isModified),
+ _isCached(old._isCached),
+ referenceCount(old.referenceCount),
+ objecttype(old.objecttype),
+ myOId(old.myOId)
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "DBObject(const DBObject& old)" << myOId);
+ }
+
+//constructs an object and reads it from the database. the oid must match the type of the object.
+//a r_Error::r_Error_ObjectUnknown is thrown when the oid is not in the database.
+DBObject::DBObject(const OId& id) throw (r_Error)
+ : referenceCount(0),
+ _isCached(false),
+ myOId(id),
+ objecttype(id.getType())
+ {
+ //flags must be set by readFromDb()
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "DBObject(" << myOId << ")");
+ }
+
+DBObject&
+DBObject::operator=(const DBObject& old)
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "operator=(" << old.myOId << ")");
+ if (this != &old)
+ {
+ _isPersistent = old._isPersistent;
+ _isInDatabase = old._isInDatabase;
+ _isModified = old._isModified;
+ _isCached = old._isCached;
+ objecttype = old.objecttype;
+ myOId = old.myOId;
+ }
+ return *this;
+ }
+
+//setPersistent(true) makes the object persistent as soon as validate is called.
+//a r_Error::r_Error_TransactionReadOnly is thrown when the transaction is readonly.
+void
+DBObject::setPersistent(bool newPersistent) throw (r_Error)
+ {
+ RMDBGENTER(6, RMDebug::module_adminif, "DBObject", "setPersistent(" << (int)newPersistent << ") " << myOId);
+ if (newPersistent)
+ {//make object persistent
+ if (!_isPersistent)
+ {//object is not persistent
+ if (!AdminIf::isReadOnlyTA())
+ {//may be written to database
+ OId::allocateOId(myOId, objecttype);
+ _isPersistent = true;
+ _isModified = true;
+ ObjectBroker::registerDBObject(this);
+ RMDBGMIDDLE(6, RMDebug::module_adminif, "DBObject", "persistent\t: yes, was not persistent");
+ }
+ else {//read only transaction
+ RMDBGEXIT(6, RMDebug::module_adminif, "DBObject", "ReadOnlyTransaction");
+ RMInit::logOut << "DBObject::setPersistent() read only transaction" << endl;
+ throw r_Error(r_Error::r_Error_TransactionReadOnly);
+ }
+ }
+ else {//is already persitent
+ RMDBGMIDDLE(6, RMDebug::module_adminif, "DBObject", "persistent\t: yes, was already persistent");
+ }
+ }
+ else {//delete the object from database
+ if (_isPersistent)
+ {
+ if (!AdminIf::isReadOnlyTA())
+ {//may be deleted to database
+ RMDBGMIDDLE(6, RMDebug::module_adminif, "DBObject", "persistent\t: no, was persistent");
+ _isPersistent = false;
+ _isModified = true;
+ }
+ else {//read only transaction
+ RMDBGEXIT(6, RMDebug::module_adminif, "DBObject", "ReadOnlyTransaction");
+ RMInit::logOut << "DBObject::setPersistent() read only transaction" << endl;
+ throw r_Error(r_Error::r_Error_TransactionReadOnly);
+ }
+ }
+ else {
+ RMDBGMIDDLE(6, RMDebug::module_adminif, "DBObject", "persistent\t: no, was not persistent");
+ }
+ }
+ RMDBGEXIT(6, RMDebug::module_adminif, "DBObject", "setPersistent(" << (int)newPersistent << ") " << myOId);
+ }
+
+//tells if an object is persistent.
+bool
+DBObject::isPersistent() const
+ {
+ RMDBGONCE(6, RMDebug::module_adminif, "DBObject", "isPersistent()" << (int)_isPersistent);
+ return _isPersistent;
+ }
+
+//writes the object to database/deletes it or updates it.
+//a r_Error::r_Error_TransactionReadOnly is thrown when the transaction is readonly.
+void
+DBObject::validate() throw (r_Error)
+ {
+ RMDBGENTER(9, RMDebug::module_adminif, "DBObject", "validate() " << myOId);
+ if (_isModified)
+ {
+ if (!AdminIf::isReadOnlyTA())
+ {
+ if (!AdminIf::isAborted())
+ {
+ if (_isInDatabase)
+ {
+ if (_isPersistent)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "DBObject", "is persistent and modified and in database");
+#ifdef RMANBENCHMARK
+ updateTimer.resume();
+#endif
+ this->updateInDb();
+#ifdef RMANBENCHMARK
+ updateTimer.pause();
+#endif
+ }
+ else {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "DBObject", "is not persistent and in database");
+#ifdef RMANBENCHMARK
+ deleteTimer.resume();
+#endif
+ this->deleteFromDb();
+#ifdef RMANBENCHMARK
+ deleteTimer.pause();
+#endif
+ }
+ }
+ else {
+ if (_isPersistent)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "DBObject", "is persistent and modified and not in database");
+
+#ifdef RMANBENCHMARK
+ insertTimer.resume();
+#endif
+ this->insertInDb();
+#ifdef RMANBENCHMARK
+ insertTimer.pause();
+#endif
+ }
+ else {
+ //don´t do anything: not in db and not persistent
+ }
+ }
+ }
+ else {
+ //don´t do anything: is aborted
+ }
+ }
+ else {
+ //don´t do anything: is read only
+ }
+ }
+ else {
+ //don´t do anything: not modified
+ }
+ RMDBGEXIT(9, RMDebug::module_adminif, "DBObject", "validate() " << myOId);
+ }
+
+void
+DBObject::setModified() throw (r_Error)
+ {
+ RMDBGENTER(8, RMDebug::module_adminif, "DBObject", "setModified() " << myOId);
+ if (!AdminIf::isReadOnlyTA())
+ _isModified = true;
+ else {
+ RMDBGMIDDLE(5, RMDebug::module_adminif, "DBObject", "readonly transaction " << myOId);
+ //this happens really a lot.
+ //RMInit::logOut << "DBObject::setModified() read only transaction" << endl;
+ //throw r_Error(r_Error::r_Error_TransactionReadOnly);
+ _isModified = true;
+ }
+ RMDBGEXIT(8, RMDebug::module_adminif, "DBObject", "setModified() " << myOId);
+ }
+
+bool
+DBObject::isModified() const
+ {
+ RMDBGONCE(8, RMDebug::module_adminif, "DBObject", "isModified() " << (int)_isModified);
+ return _isModified;
+ }
+
+OId
+DBObject::getOId() const
+ {
+ RMDBGONCE(8, RMDebug::module_adminif, "DBObject", "getOId() " << myOId);
+ return myOId;
+ }
+
+EOId
+DBObject::getEOId() const
+ {
+ RMDBGONCE(8, RMDebug::module_adminif, "DBObject", "getEOId() " << myOId);
+ return EOId(myOId);
+ }
+
+OId::OIdType
+DBObject::getObjectType() const
+ {
+ RMDBGONCE(8, RMDebug::module_adminif, "DBObject", "getObjectType() " << objecttype);
+ return objecttype;
+ }
+
+DBObject::~DBObject()
+ {
+ RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "~DBObject() " << myOId);
+ ObjectBroker::deregisterDBObject(myOId);
+ RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "~DBObject() " << myOId);
+ }
+
+void
+DBObject::updateInDb() throw (r_Error)
+ {
+ RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "updateInDb() " << myOId);
+ _isModified = false;
+ _isInDatabase = true;
+ _isPersistent = true;
+ RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "updateInDb() " << myOId);
+ }
+
+//writes the object into the database. the object must not be in the database.
+void
+DBObject::insertInDb() throw (r_Error)
+ {
+ RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "insertInDb() " << myOId);
+ _isModified = false;
+ _isInDatabase = true;
+ _isPersistent = true;
+ RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "insertInDb() " << myOId);
+ }
+
+void
+DBObject::deleteFromDb() throw (r_Error)
+ {
+ RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "deleteFromDb() " << myOId);
+ _isModified = false;
+ _isInDatabase = false;
+ _isPersistent = false;
+ RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "deleteFromDb() " << myOId);
+ }
+
+void
+DBObject::readFromDb() throw (r_Error)
+ {
+ RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "readFromDb() " << myOId);
+ _isPersistent = true;
+ _isModified = false;
+ _isInDatabase = true;
+ RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "readFromDb() " << myOId);
+ }
+
+BinaryRepresentation
+DBObject::getBinaryRepresentation() const throw (r_Error)
+ {
+ RMInit::logOut << "getBinaryRepresentation() for " << objecttype << " not implemented" << endl;
+ throw r_Error(BINARYEXPORTNOTSUPPORTEDFOROBJECT);
+ }
+
+void
+DBObject::setBinaryRepresentation(const BinaryRepresentation& br) throw (r_Error)
+ {
+ RMInit::logOut << "setBinaryRepresentation() for " << objecttype << " not implemented" << endl;
+ throw r_Error(BINARYIMPORTNOTSUPPORTEDFOROBJECT);
+ }
+
+char*
+DBObject::getBinaryName() const
+ {
+ //if we use 64bit oids we have at most 20 digits + "_" + type
+ ostringstream o;
+ o << (int)objecttype << '_' << myOId.getCounter() << ".raw";
+ const char* temp = o.str().c_str();
+ char* retval = new char[strlen(temp) + 1];
+ memcpy(retval, temp, strlen(temp) + 1);
+ return retval;
+ }
diff --git a/reladminif/dbobject.hh b/reladminif/dbobject.hh
new file mode 100644
index 0000000..80e3360
--- /dev/null
+++ b/reladminif/dbobject.hh
@@ -0,0 +1,291 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#ifndef _DBOBJECT_HH_
+#define _DBOBJECT_HH_
+
+class DBObject;
+class EOId;
+
+template <class T> class DBRef;
+
+#include <iosfwd>
+
+#include "oidif.hh"
+#include "raslib/mddtypes.hh"
+#include "raslib/error.hh"
+#include "binaryrepresentation.hh"
+
+#ifdef RMANBENCHMARK
+#include "raslib/rmdebug.hh"
+#endif
+
+typedef DBRef<DBObject> DBObjectId;
+
+//@ManMemo: Module: {\bf reladminif}.
+/*@Doc:
+Base class for all persistent classes. it supplies functionality for reference counting,
+management by ObjectBroker, modification management, cache size.
+
+a persistent DBObject has a unique OId. this oid identifies it in the database.
+*/
+
+class DBObject
+ {
+ public:
+ virtual void destroy(void);
+ /*@Doc:
+ deletes the object if and only if
+ the refence count is zero and
+ the object is not cached and
+ the transaction is not readonly.
+ */
+
+ int getReferenceCount(void) const;
+ /*@Doc:
+ Returns the number of references that exist for this object
+ */
+
+ void incrementReferenceCount(void);
+ /*@Doc:
+ Reference counting functions. These should be private with friend DBRef, but the compiler
+ doesn't allow friend template classes, only instances. Don't call directly, only DBRef
+ is allowed to.
+ */
+
+ void decrementReferenceCount(void);
+ /*@Doc:
+ Reference counting functions. These should be private with friend DBRef, but the compiler
+ doesn't allow friend template classes, only instances. Don't call directly, only DBRef
+ is allowed to.
+ */
+
+ virtual ~DBObject();
+ /*@Doc:
+ deregisters this object with the ObjectBroker.
+ the oid is not invalidated to allow the ObjectBroker to kill it.
+ */
+
+ DBObject();
+ /*@Doc:
+ initializes all attributes. the oid is set to 0. the objecttype is set to OId::INVALID.
+ */
+
+ DBObject(const DBObject& old);
+ /*@Doc:
+ clones all attributes.
+ */
+
+ DBObject(const OId& id) throw (r_Error);
+ /*@Doc:
+ initializes only referenceCount, myOId, objecttype. _isCached is set to 0.
+ Subclasses may contain a call to readFromDb which can throw a r_Error_ObjectUnknown
+ or database related exception.
+ */
+
+ virtual void setPersistent(bool newPersistent) throw (r_Error);
+ /*@Doc:
+ setPersistent(true) makes the object persistent as soon as validate is called.
+ a r_Error_TransactionReadOnly is thrown when the transaction is readonly.
+ setPersistent(false) deletes the object from the database as soon as validate is called.
+ if the state of the object changes in a read only transaction
+ (e.g. persistent->non persistent) a r_Error_TransactionReadOnly is thrown.
+ */
+
+ bool isPersistent() const;
+ /*@Doc:
+ tells if an object is persistent.
+ */
+
+ void validate() throw (r_Error);
+ /*@Doc:
+ writes the object to database/deletes it or updates it.
+ any r_Errors from insertInDb, updateInDb, deleteFromDb, readFromDb are passed to the
+ caller.
+ */
+
+ virtual void setModified() throw (r_Error);
+ /*@Doc:
+ marks this object dirty.
+ a r_Error_TransactionReadOnly should be thrown when the transaction is readonly.
+ this is because of o2 related stuff in dbmddobject. should be taken care of.
+ */
+
+ bool isModified() const;
+ /*@Doc:
+ tells if this object is dirty.
+ */
+
+ OId getOId() const;
+ /*@Doc:
+ returns the oid of this object
+ */
+
+ EOId getEOId() const;
+ /*@Doc:
+ returns the EOId of this object.
+ */
+
+ OId::OIdType getObjectType() const;
+ /*@Doc:
+ returns the type of this object (MDDSet, ...). objects which are not
+ yet persistent also return their object type.
+ */
+
+ DBObject& operator=(const DBObject& old);
+ /*@Doc:
+ clones all DBObject attributes except reference count.
+ */
+
+ bool isCached() const;
+ /*@Doc:
+ tells if this object is cached.
+ */
+
+ virtual void setCached(bool newCached);
+ /*@Doc:
+
+ */
+
+ virtual r_Bytes getMemorySize() const;
+ /*@Doc:
+ returns the memory space used by this object.
+ */
+
+ virtual void printStatus(unsigned int level = 0, std::ostream& stream = std::cout) const;
+ /*@Doc:
+ prints the indent, OIdType, myOId as long and myOId as double.
+ */
+
+ virtual r_Bytes getTotalStorageSize() const;
+ /*@Doc:
+ returns the space taken up by this object in the database.
+ as dbobject has no persistent attributes it returns 0.
+ */
+
+ virtual BinaryRepresentation getBinaryRepresentation() const throw (r_Error);
+ /*@Doc:
+ returns the binary representation fit for storage in the database
+ */
+
+ virtual void setBinaryRepresentation(const BinaryRepresentation&) throw (r_Error);
+ /*@Doc:
+ set the objects state from the binary represenation
+ */
+
+ virtual char* getBinaryName() const;
+ /*Doc:
+ create the name for binary represenation from the oid
+ */
+
+#ifdef RMANBENCHMARK
+ static RMTimer readTimer;
+
+ static RMTimer updateTimer;
+
+ static RMTimer insertTimer;
+
+ static RMTimer deleteTimer;
+#endif
+
+ protected:
+ virtual void release();
+ /*@Doc:
+ releases all dynamic memory (references to other persistent obkjects).
+ this is needed for cross transactional caches.
+ dbobject does not have any dynamic memory.
+ */
+
+ virtual void readFromDb() throw (r_Error);
+ /*@Doc:
+ reads the object from database. myOId must be set!!!
+ a r_Error_ObjectUnknown is thrown when the oid is not in the database.
+ */
+
+ virtual void insertInDb() throw (r_Error);
+ /*@Doc:
+ writes the object into the database. the object must not be in the database.
+ a r_Error_TransactionReadOnly is thrown when the transaction is readonly.
+ this implementation checks for readOnlyTA
+ */
+
+ virtual void deleteFromDb() throw (r_Error);
+ /*@Doc:
+ deletes an object in the database.
+ a r_Error_TransactionReadOnly is thrown when the transaction is readonly.
+ this implementation checks for readOnlyTA
+ */
+
+ virtual void updateInDb() throw (r_Error);
+ /*@Doc:
+ updates an existing object in the database
+ a r_Error_TransactionReadOnly is thrown when the transaction is readonly.
+ this implementation checks for readOnlyTA
+ */
+
+ bool _isPersistent;
+ /*@Doc:
+ tells, if this object should be in the database or not.
+ */
+
+ bool _isInDatabase;
+ /*@Doc:
+ tells, if this object is already in the database.
+ */
+
+ bool _isModified;
+ /*@Doc:
+ tells, if this object has changed an should be updated in the database.
+ */
+
+ bool _isCached;
+ /*@Doc:
+ tells , if this objects is cached or not
+ */
+
+ OId myOId;
+ /*@Doc:
+ the oid of this object. is set by setPersistent(1) or by the constructor
+ of optional persistent objects (types).
+ */
+
+ OId::OIdType objecttype;
+ /*@Doc:
+ the type of this object. needed by setPersistent(1) to allocate the correct oid.
+ */
+
+ int referenceCount;
+ /*@Doc:
+ The number of references that exist for this file. Use get_reference() for reading
+ its value from derived classes. Modified by incr_reference and decr_reference.
+ */
+
+ private:
+
+ void sharedObjectInit(void);
+ /*@Doc:
+ Initialization code shared by all constructors.
+ does not do anything.
+ */
+ };
+
+#endif
diff --git a/reladminif/dbobjectiditerator.cc b/reladminif/dbobjectiditerator.cc
new file mode 100644
index 0000000..17889be
--- /dev/null
+++ b/reladminif/dbobjectiditerator.cc
@@ -0,0 +1,103 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "dbobjectiditerator.hh"
+#include "objectbroker.hh"
+#include "dbref.hh"
+#include "raslib/rmdebug.hh"
+
+template<class T>
+DBObjectIdIterator<T>::DBObjectIdIterator(const DBObjectIdIterator<T>& oidlist)
+ : mySet(NULL),
+ counter(0)
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator", "DBObjectIdIterator(const DBObjectIdIterator<T>&)");
+ mySet = oidlist.mySet;
+ myIter = mySet->begin();
+ }
+
+template<class T>
+DBObjectIdIterator<T>::DBObjectIdIterator(const std::set<DBRef<T>, std::less<DBRef<T> > >& oidlist)
+ : mySet(NULL),
+ counter(0)
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator", "DBObjectIdIterator(OIdSet)");
+ mySet = (std::set<DBRef<T>, std::less<DBRef<T> > >*)&oidlist;
+ myIter = mySet->begin();
+ }
+
+template<class T> void
+DBObjectIdIterator<T>::reset()
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator","reset()");
+ myIter = mySet->begin();
+ counter = 0;
+ }
+
+template<class T> bool
+DBObjectIdIterator<T>::not_done() const
+ {
+ RMDBGENTER(7, RMDebug::module_adminif, "DBObjectIdIterator","not_done()");
+ bool retval = false;
+ if (myIter == mySet->end())
+ {
+ retval = false;
+ }
+ else {
+ if (mySet->empty())
+ {
+ retval = false;
+ }
+ else {
+ if (counter == mySet->size())
+ retval = false;
+ else
+ retval = true;
+ }
+ }
+ RMDBGEXIT(7, RMDebug::module_adminif, "DBObjectIdIterator","not_done() " << retval);
+ return retval;
+ }
+
+template<class T> void
+DBObjectIdIterator<T>::advance()
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator","advance() " << counter);
+ myIter++;
+ counter++;
+ }
+
+template<class T> DBRef<T>
+DBObjectIdIterator<T>::get_element() const
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator", "get_element() " << (*myIter).getOId());
+ return (*myIter);
+ }
+
+template<class T>
+DBObjectIdIterator<T>::~DBObjectIdIterator()
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator", "~DBObjectIdIterator()");
+ mySet = NULL;
+ counter = 0;
+ }
+
diff --git a/reladminif/dbobjectiditerator.hh b/reladminif/dbobjectiditerator.hh
new file mode 100644
index 0000000..bb6ba78
--- /dev/null
+++ b/reladminif/dbobjectiditerator.hh
@@ -0,0 +1,108 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*
+ * 2007-may-10 CJ fixed compilation errors (gcc 4.1)
+*/
+
+#ifndef _DBOBJECtIdIterATOR_HH_
+#define _DBOBJECtIdIterATOR_HH_
+
+template <class T> class DBObjectIdIterator;
+template <class T> class DBRef;
+class ObjectBroker;
+
+#include "lists.h"
+//@ManMemo: Module: {\bf reladminif}.
+/*@Doc:
+
+this object gets a set of oids. when an oid is accessed the iterator returns a DBRef to the oid.
+
+*/
+
+
+template<class T>
+class DBObjectIdIterator
+ {
+ public:
+ DBObjectIdIterator(const std::set<DBRef<T>, std::less<DBRef<T> > >& oidlist);
+ /*@Doc:
+ constructs a new Iterator. the OIdSet will be deleted by the DBOBjectIdIterator.
+ there may be oids of objects with other classes present. you should be carefull
+ when using this feature - as in mddtypes/mddbasetypes/mdddim/domtypes
+ */
+
+ DBObjectIdIterator(const DBObjectIdIterator<T>& it);
+ /*@Doc:
+ */
+
+ ~DBObjectIdIterator();
+ /*@Doc:
+ deletes the OIdSet passed to it in the constructor
+ */
+
+ void reset();
+ /*@Doc:
+ resets the iterator to the beginning
+ */
+
+ bool not_done() const;
+ /*@Doc:
+ checks if there are more elements
+ */
+
+ void advance();
+ /*@Doc:
+ advances the iterator one entry
+ */
+
+ DBRef<T> get_element() const;
+ /*@Doc:
+ returns an dbref<object>
+ */
+
+ private:
+ typename std::set<DBRef<T>, std::less<DBRef<T> > >::iterator myIter;
+ /*@Doc:
+ internal pointer where the iterator is
+ */
+
+ std::set<DBRef<T>, std::less<DBRef<T> > >* mySet;
+ /*@Doc:
+ the actual list which is used to lookup objects by the objectbroker
+ */
+
+ unsigned int counter;
+ /*@Doc:
+ holds the actual position in set
+ */
+ };
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#include "dbobjectiditerator.cc"
+#endif
+#endif
+
+#endif
+
+
diff --git a/reladminif/dbobjectiterator.cc b/reladminif/dbobjectiterator.cc
new file mode 100644
index 0000000..69517b5
--- /dev/null
+++ b/reladminif/dbobjectiterator.cc
@@ -0,0 +1,104 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "dbobjectiterator.hh"
+#include "objectbroker.hh"
+#include "dbref.hh"
+#include "raslib/rmdebug.hh"
+
+template<class T>
+DBObjectIterator<T>::DBObjectIterator(const DBObjectIterator<T>& oidlist)
+ : mySet(NULL),
+ counter(0)
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator", "DBObjectIterator(const DBObjectIterator<T>&)");
+ mySet = new OIdSet(*(oidlist.mySet));
+ myIter = mySet->begin();
+ }
+
+template<class T>
+DBObjectIterator<T>::DBObjectIterator(const OIdSet& oidlist)
+ : mySet(NULL),
+ counter(0)
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator", "DBObjectIterator(OIdSet)");
+ mySet = new OIdSet(oidlist);
+ myIter = mySet->begin();
+ }
+
+template<class T> void
+DBObjectIterator<T>::reset()
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator","reset()");
+ myIter = mySet->begin();
+ counter = 0;
+ }
+
+template<class T> bool
+DBObjectIterator<T>::not_done() const
+ {
+ RMDBGENTER(7, RMDebug::module_adminif, "DBObjectIterator","not_done()");
+ bool retval = false;
+ if (myIter == mySet->end())
+ {
+ retval = false;
+ }
+ else {
+ if (mySet->empty())
+ {
+ retval = false;
+ }
+ else {
+ if (counter == mySet->size())
+ retval = false;
+ else
+ retval = true;
+ }
+ }
+ RMDBGEXIT(7, RMDebug::module_adminif, "DBObjectIterator","not_done() " << retval);
+ return retval;
+ }
+
+template<class T> void
+DBObjectIterator<T>::advance()
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator","advance() " << counter);
+ myIter++;
+ counter++;
+ }
+
+template<class T> DBRef<T>
+DBObjectIterator<T>::get_element() const
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator", "get_element() " << *myIter << " " << (*myIter).getType());
+ return DBRef<T>(*myIter);
+ }
+
+template<class T>
+DBObjectIterator<T>::~DBObjectIterator()
+ {
+ RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator", "~DBObjectIterator()");
+ delete mySet;
+ mySet = NULL;
+ counter = 0;
+ }
+
diff --git a/reladminif/dbobjectiterator.hh b/reladminif/dbobjectiterator.hh
new file mode 100644
index 0000000..4f04370
--- /dev/null
+++ b/reladminif/dbobjectiterator.hh
@@ -0,0 +1,104 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#ifndef _DBOBJECTITERATOR_HH_
+#define _DBOBJECTITERATOR_HH_
+
+template <class T> class DBObjectIterator;
+template <class T> class DBRef;
+class ObjectBroker;
+
+#include "lists.h"
+//@ManMemo: Module: {\bf reladminif}.
+/*@Doc:
+
+this object gets a set of oids. when an oid is accessed the iterator returns a DBRef to the oid.
+
+*/
+
+
+template<class T>
+class DBObjectIterator
+ {
+ public:
+ DBObjectIterator(const OIdSet& oidlist);
+ /*@Doc:
+ constructs a new Iterator. the OIdSet will be deleted by the DBOBjectIterator.
+ there may be oids of objects with other classes present. you should be carefull
+ when using this feature - as in mddtypes/mddbasetypes/mdddim/domtypes
+ */
+
+ DBObjectIterator(const DBObjectIterator<T>& it);
+ /*@Doc:
+ */
+
+ ~DBObjectIterator();
+ /*@Doc:
+ deletes the OIdSet passed to it in the constructor
+ */
+
+ void reset();
+ /*@Doc:
+ resets the iterator to the beginning
+ */
+
+ bool not_done() const;
+ /*@Doc:
+ checks if there are more elements
+ */
+
+ void advance();
+ /*@Doc:
+ advances the iterator one entry
+ */
+
+ DBRef<T> get_element() const;
+ /*@Doc:
+ returns an dbref<object>
+ */
+
+ private:
+ OIdSet::iterator myIter;
+ /*@Doc:
+ internal pointer where the iterator is
+ */
+
+ OIdSet* mySet;
+ /*@Doc:
+ the actual list which is used to lookup objects by the objectbroker
+ */
+
+ unsigned int counter;
+ /*@Doc:
+ holds the actual position in set
+ */
+ };
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#include "dbobjectiterator.cc"
+#endif
+#endif
+
+#endif
+
+
diff --git a/reladminif/dbref.cc b/reladminif/dbref.cc
new file mode 100644
index 0000000..1012371
--- /dev/null
+++ b/reladminif/dbref.cc
@@ -0,0 +1,874 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************
+ *
+ *
+ * PURPOSE:
+ * DBRef is a smart pointer for managing objects derived from
+ * the DbObject class.
+ *
+ *
+ * COMMENTS:
+ *
+ ************************************************************/
+
+
+#include "dbref.hh"
+#include <iostream>
+#include <stdio.h>
+#include "raslib/rmdebug.hh"
+#include "objectbroker.hh"
+#include "indexmgr/indexds.hh"
+#include "relindexif/dbrcindexds.hh"
+#include "relindexif/dbtcindex.hh"
+#include "indexmgr/hierindexds.hh"
+#include "debug/debug.hh"
+
+template <class T> bool
+DBRef<T>::pointerCaching = true;
+
+/*for testing
+bool
+DBRef<BLOBTile>::pointerCaching = false;
+
+bool
+DBRef<InlineTile>::pointerCaching = false;
+
+bool
+DBRef<DBTile>::pointerCaching = false;
+*/
+
+template <class T> void
+DBRef<T>::setPointerCaching(bool useIt)
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBRef", "setPointerCaching(" << useIt << ") " << pointerCaching );
+ pointerCaching = useIt;
+ }
+
+template <class T> bool
+DBRef<T>::getPointerCaching()
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "DBRef", "getPointerCaching() " << pointerCaching );
+ return pointerCaching;
+ }
+
+template <class T>
+DBRef<T>::DBRef(void)
+ : object(0),
+ objId(DBOBJID_NONE),
+ pointerValid(false)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "DBRef", "DBRef()");
+ }
+
+
+template <class T>
+DBRef<T>::DBRef(const OId &id)
+ : object(0),
+ pointerValid(false),
+ objId(id)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "DBRef", "DBRef(" << id << ")");
+ }
+
+
+template <class T>
+DBRef<T>::DBRef(double id)
+ : object(0),
+ pointerValid(false),
+ objId(id)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "DBRef", "DBRef(double " << id << ")");
+ }
+
+
+template <class T>
+DBRef<T>::DBRef(const DBRef<T> &src)
+ : object(0),
+ pointerValid(src.pointerValid),
+ objId(src.objId)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "DBRef(const DBRef) src.OId=" << src.objId);
+ if (pointerCaching)
+ {
+ if (src.object)
+ {
+ object = src.object;
+ objId = object->getOId();
+ object->incrementReferenceCount();
+ }
+ }
+ else {
+ if (pointerValid && src.object)
+ {
+ object = src.object;
+ }
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "DBRef(const DBRef) " << objId);
+ }
+
+
+template <class T>
+DBRef<T>::DBRef(T *ptr)
+ : object(ptr),
+ pointerValid(true),
+ objId(DBOBJID_NONE)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "DBRef(const T* " << ptr << ")");
+
+ if (object != 0)
+ {
+ objId = object->getOId();
+ object->incrementReferenceCount();
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "DBRef(T* " << ptr->getOId() << ")");
+ }
+ else {
+ pointerValid = false;
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "DBRef(T* 0) " << objId);
+ }
+ }
+
+
+template <class T>
+DBRef<T>::~DBRef(void)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "~DBRef() " << objId);
+ if ((object != 0) && pointerCaching)
+ object->decrementReferenceCount();
+ object = 0;
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "~DBRef() " << objId);
+ }
+
+template <class T>
+bool DBRef<T>::operator<(const DBRef<T>& other) const
+ {
+ RMDBGENTER(3, RMDebug::module_adminif, "DBRef", "DBRef<T>::operator<(" << other.objId << ", " << (r_Ptr)other.object << ") " << objId << ", " << (r_Ptr)object);
+ int ret = operator==(other);
+ return (ret == -1);
+ }
+
+template <class T>
+bool operator< (const DBRef<T> &me, const DBRef<T> &him)
+ {
+ RMDBGENTER(3, RMDebug::module_adminif, "DBRef", "operator<({" << me.getOId() << "}, {" << him.getOId() << "})");
+ return me.operator<(him);
+ }
+
+template <class T>
+int DBRef<T>::operator==(const DBRef<T> &src) const
+ {
+ RMDBGENTER(3, RMDebug::module_adminif, "DBRef", "operator==(" << src.objId << ", " << (r_Ptr)src.object << ") " << objId << ", " << (r_Ptr)object);
+ int retval = 0;
+ if (isInitialised())
+ {
+ if (src.isInitialised())
+ {
+ if (object)
+ {
+ if (object->isPersistent())
+ {//this persistent
+ if (src.object)
+ {
+ if (src.object->isPersistent())
+ {
+ if (object->getOId() < src.object->getOId())
+ retval = -1;
+ else
+ if (object->getOId() > src.object->getOId())
+ retval = +1;
+ //else == -> 0
+ }
+ else {//src is transient
+ retval = +1;
+ }
+ }
+ else {//src is persistent
+ if (object->getOId() < src.objId)
+ {
+ retval = -1;
+ }
+ else {
+ if (object->getOId() > src.objId)
+ retval = +1;
+ //else == -> 0
+ }
+ }
+ }
+ else {//this transient
+ if (src.object)
+ {
+ if (src.object->isPersistent())
+ {
+ retval = -1;
+ }
+ else {//src is transient
+ if (object < src.object)
+ retval = -1;
+ else
+ if (object > src.object)
+ retval = +1;
+ //else == -> 0
+ }
+ }
+ else {//src is persistent
+ retval = -1;
+ }
+ }
+ }
+ else {//this is persistent
+ if (src.object)
+ {
+ if (src.object->isPersistent())
+ {
+ if (objId < src.object->getOId())
+ {
+ retval = -1;
+ }
+ else {
+ if (objId > src.object->getOId())
+ retval = +1;
+ //else == -> 0
+ }
+
+ }
+ else {//src not persistent
+ retval = +1;
+ }
+ }
+ else {//src is persistent
+ if (objId < src.objId)
+ {
+ retval = -1;
+ }
+ else {
+ if (objId > src.objId)
+ retval = +1;
+ //else == -> 0
+ }
+ }
+ }
+ }
+ else {
+ retval = +1;
+ }
+ }
+ else {
+ if (src.isInitialised())
+ {
+ retval = -1;
+ }
+ //else is 0
+ }
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator==(" << src.objId << ") " << retval);
+ return retval;
+ }
+
+
+template <class T>
+DBRef<T> &DBRef<T>::operator=(const DBRef<T> &src)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator=(" << src.objId << ") " << objId);
+ if ((object != 0) && pointerCaching)
+ {
+ object->decrementReferenceCount();
+ }
+ object = src.object;
+ pointerValid = src.pointerValid;
+ objId = src.objId;
+ if (pointerCaching)
+ {
+ if (object)
+ {
+ objId = object->getOId();
+ object->incrementReferenceCount();
+ }
+ }
+ else {
+ if (object && pointerValid)
+ objId = object->getOId();
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator=(" << src.objId << ") " << objId);
+ return *this;
+ }
+
+
+template<class T>
+DBRef<T> &DBRef<T>::operator=(T *ptr)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator=( at " << ptr << " ) " << objId);
+ if ((object != 0) && pointerCaching)
+ object->decrementReferenceCount();
+
+ object = ptr;
+ if (object == 0)
+ {
+ objId = DBOBJID_NONE;
+ pointerValid = false;
+ }
+ else {
+ objId = object->getOId();
+ object->incrementReferenceCount();
+ pointerValid = true;
+ }
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator=( at " << ptr << " ) " << objId);
+ return *this;
+ }
+
+
+template <class T>
+T &DBRef<T>::operator *(void) throw ( r_Error )
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator*() " << objId);
+
+ if (is_null())
+ {
+ TALK( "DBRef::operator*(): object not found " << objId);
+ RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId);
+ r_Error err = r_Error(r_Error::r_Error_RefNull);
+ throw err;
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator*() " << objId);
+ return *object;
+ }
+
+
+template <class T>
+const T &DBRef<T>::operator *(void) const throw ( r_Error )
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator*() const " << objId);
+
+ if (is_null())
+ {
+ TALK( "DBRef::operator*(): object not found " << objId);
+ RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId);
+ r_Error err = r_Error(r_Error::r_Error_RefNull);
+ throw err;
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator*() " << objId);
+ return *object;
+ }
+
+
+#ifndef __GNUG__
+
+template <class T>
+T &DBRef<T>::operator[](int idx) const throw(r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator[](" << idx << ") " << objId);
+
+ if (is_null())
+ {
+ TALK( "DBRef::operator[](): object not found " << objId);
+ RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId);
+ r_Error err = r_Error(r_Error::r_Error_RefNull);
+ throw err;
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator[](" << idx << ") " << objId);
+ return *((this + idx).object);
+ }
+
+#endif
+
+template <class T>
+T *DBRef<T>::operator->(void) throw(r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator->() " << objId);
+
+ if (is_null())
+ {
+ TALK( "DBRef::operator->(): object not found " << objId);
+ RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId);
+ r_Error err = r_Error(r_Error::r_Error_RefNull);
+ throw err;
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator->() " << objId);
+ return object;
+ }
+
+
+template <class T>
+const T *DBRef<T>::operator->(void) const throw(r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator->() const " << objId);
+
+ if (is_null())
+ {
+ TALK( "DBRef::operator->(): object not found " << objId);
+ RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId);
+ r_Error err = r_Error(r_Error::r_Error_RefNull);
+ throw err;
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator->() const " << objId);
+ return object;
+ }
+
+
+template <class T>
+T *DBRef<T>::ptr(void) throw(r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "ptr() " << objId);
+
+ if (is_null())
+ {
+ TALK( "DBRef::ptr(): object not found " << objId);
+ RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId);
+ r_Error err = r_Error(r_Error::r_Error_RefNull);
+ throw err;
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "ptr() " << objId);
+ return object;
+ }
+
+
+template <class T>
+const T *DBRef<T>::ptr(void) const throw(r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "ptr() " << objId);
+
+ if (is_null())
+ {
+ TALK( "DBRef::ptr(): object not found " << objId);
+ RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId);
+ r_Error err = r_Error(r_Error::r_Error_RefNull);
+ throw err;
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "ptr() " << objId);
+ return object;
+ }
+
+
+template <class T>
+DBRef<T>::operator T*() throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator T*() " << objId);
+
+ if (is_null())
+ {
+ TALK( "DBRef::T*(): object not found " << objId);
+ RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId);
+ r_Error err = r_Error(r_Error::r_Error_RefNull);
+ throw err;
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator T*() " << objId);
+ return object;
+ }
+
+
+template <class T>
+DBRef<T>::operator const T*() const throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator const T*() const" << objId);
+
+ if (is_null())
+ {
+ TALK( "DBRef::T*(): object not found " << objId);
+ RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId);
+ r_Error err = r_Error(r_Error::r_Error_RefNull);
+ throw err;
+ }
+
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator const T*() " << objId);
+ return object;
+ }
+
+
+template <class T>
+OId DBRef<T>::getOId(void) const
+ {
+ if (object && pointerCaching)
+ ((DBRef<T>)*this).objId = object->getOId();
+ return objId;
+ }
+
+template <class T>
+void DBRef<T>::delete_object(void)
+ {
+ if (!is_null())
+ {
+ object->setPersistent(false);
+ object->decrementReferenceCount();
+ object = 0;
+ objId = DBOBJID_NONE;
+ }
+ else {
+ r_Error err;
+ if (objId.getType() == OId::INVALID)
+ {
+ err = r_Error(r_Error::r_Error_OIdInvalid);
+ }
+ else {
+ err = r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ RMDBGONCE(0, RMDebug::module_adminif, "DBRef", "delete_object() " << objId << " not ok")
+ throw err;
+ }
+ }
+
+template <class T>
+bool DBRef<T>::isInitialised() const
+ {
+ bool retval=false;
+ if (object)
+ retval=true;
+ else {
+ if (objId.getType() != OId::INVALID)
+ retval=true;
+ }
+ return retval;
+ }
+
+template <class T>
+bool DBRef<T>::is_valid(void) const
+ {
+ bool retval=false;
+ if (!is_null())
+ retval=true;
+ return retval;
+ }
+
+
+template <class T>
+void DBRef<T>::release()
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "release() " << objId);
+ if ((object != 0) && pointerCaching)
+ {
+ object->decrementReferenceCount();
+ }
+ object = 0;
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "release() " << objId);
+ }
+
+
+template <class T>
+DBRef<T>::operator DBRef<DBObject>() const
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBObject>() " << objId);
+ if (object && pointerCaching)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBObject>(" << object << ") " << objId);
+ return DBRef<DBObject>(object);
+ }
+ else {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBObject>(" << objId << ") " << objId);
+ return DBRef<DBObject>(objId);
+ }
+ }
+
+template <class T>
+DBRef<T>::operator DBRef<InlineTile>() const throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<InlineTile>() " << objId);
+ if (object && pointerCaching)
+ {
+ if (object->getObjectType() == OId::INLINETILEOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<InlineTile>() " << objId);
+ return DBRef<InlineTile>((InlineTile*)object);
+ }
+ }
+ else {
+ if (objId.getType() == OId::INLINETILEOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<InlineTile>() " << objId);
+ return DBRef<InlineTile>(objId);
+ }
+ }
+ TALK( "DBRef::<InlineTile>(): operator mismatch" << objId);
+ RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<InlineTile>() mismatch " << objId);
+ throw r_Error(r_Error::r_Error_DatabaseClassMismatch);
+ }
+
+template <class T>
+DBRef<T>::operator DBRef<DBTile>() const throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTile>() " << objId << "; object=" << (long) object );
+ TALK( "DBRef::DBRef<DBTile>(): object=" << (long) object );
+ if (object && pointerCaching)
+ {
+ if ((object->getObjectType() == OId::BLOBOID) || (object->getObjectType() == OId::INLINETILEOID))
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTile>() " << objId);
+ return DBRef<DBTile>((DBTile*)object);
+ }
+ }
+ else {
+ if ((objId.getType() == OId::BLOBOID) || (objId.getType() == OId::INLINETILEOID))
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTile>() " << objId);
+ return DBRef<DBTile>(objId);
+ }
+ }
+ if (object) { TALK( "DBRef::DBRef<DBTile>(): object->getObjectType()=" << object->getObjectType() ); }
+ TALK( "DBRef::DBRef<DBTile>(): objId->getObjectType()=" << objId.getType() );
+ TALK( "DBRef::DBRef<DBTile>(): operator mismatch" << objId );
+ if (object) { RMDBGMIDDLE(0, RMDebug::module_adminif, "DBRef", "object->getObjectType()=" << object->getObjectType() ); }
+ RMDBGMIDDLE(0, RMDebug::module_adminif, "DBRef", "objId->getObjectType()=" << objId.getType() );
+ RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTile>() mismatch " << objId);
+ throw r_Error(r_Error::r_Error_DatabaseClassMismatch);
+ }
+
+template <class T>
+DBRef<T>::operator DBRef<BLOBTile>() const throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<BLOBTile>() " << objId);
+ if (object && pointerCaching)
+ {
+ if (object->getObjectType() == OId::BLOBOID || (object->getObjectType() == OId::INLINETILEOID))
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<BLOBTile>() " << objId);
+ return DBRef<BLOBTile>((BLOBTile*)object);
+ }
+ }
+ else {
+ if ((objId.getType() == OId::BLOBOID) || (objId.getType() == OId::INLINETILEOID))
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<BLOBTile>() " << objId);
+ return DBRef<BLOBTile>(objId);
+ }
+ }
+ TALK( "DBRef::DBRef<BLOBTile>(): operator mismatch" << objId);
+ RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<BLOBTile>() mismatch " << objId);
+ throw r_Error(r_Error::r_Error_DatabaseClassMismatch);
+ }
+
+template <class T>
+DBRef<T>::operator DBRef<DBTCIndex>() const throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTCIndex>() " << objId);
+ if (object && pointerCaching)
+ {
+ if (object->getObjectType() == OId::DBTCINDEXOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTCIndex>() " << objId);
+ return DBRef<DBTCIndex>((DBTCIndex*)object);
+ }
+ }
+ else {
+ if (objId.getType() == OId::DBTCINDEXOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTCIndex>() " << objId);
+ return DBRef<DBTCIndex>(objId);
+ }
+ }
+ TALK( "DBRef::DBRef<DBTCIndex>(): operator mismatch" << objId);
+ RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTCIndex>() mismatch " << objId);
+ throw r_Error(r_Error::r_Error_DatabaseClassMismatch);
+ }
+
+template <class T>
+DBRef<T>::operator DBRef<DBHierIndex>() const throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBHierIndex>() " << objId);
+ if (object && pointerCaching)
+ {
+ if ((object->getObjectType() == OId::MDDHIERIXOID) || (object->getObjectType() == OId::DBTCINDEXOID))
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBHierIndex>() " << objId);
+ return DBRef<DBHierIndex>((DBHierIndex*)object);
+ }
+ }
+ else {
+ if ((objId.getType() == OId::MDDHIERIXOID) || (objId.getType() == OId::DBTCINDEXOID))
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBHierIndex>() " << objId);
+ return DBRef<DBHierIndex>(objId);
+ }
+ }
+ TALK( "DBRef::DBRef<DBHierIndex>(): operator mismatch" << objId);
+ RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<DBHierIndex>() mismatch " << objId);
+ throw r_Error(r_Error::r_Error_DatabaseClassMismatch);
+ }
+
+
+template <class T>
+DBRef<T>::operator DBRef<DBRCIndexDS>() const throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBRCIndexDS>() " << objId);
+ if (object && pointerCaching)
+ {
+ if (object->getObjectType() == OId::MDDRCIXOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBRCIndexDS>() " << objId);
+ return DBRef<DBRCIndexDS>((DBRCIndexDS*)object);
+ }
+ }
+ else {
+ if (objId.getType() == OId::MDDRCIXOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBRCIndexDS>() " << objId);
+ return DBRef<DBRCIndexDS>(objId);
+ }
+ }
+ TALK( "DBRef::DBRef<DBRCIndexDS>(): operator mismatch" << objId);
+ RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<DBRCIndexDS>() mismatch " << objId);
+ throw r_Error(r_Error::r_Error_DatabaseClassMismatch);
+ }
+
+
+template <class T>
+DBRef<T>::operator HierIndexDS*() const throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator HierIndexDS*() " << objId);
+ if (object && pointerCaching)
+ {
+ if ((object->getObjectType() == OId::MDDHIERIXOID) || (object->getObjectType() == OId::DBTCINDEXOID))
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator HierIndexDS*() " << objId);
+ return (HierIndexDS*)object;
+ }
+ }
+ else {
+ if (objId.getType() == OId::MDDHIERIXOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBHierIndexId" << objId);
+ DBRef<DBHierIndex> t(objId);
+ return (HierIndexDS*)t.ptr();
+ }
+ else {
+ if (objId.getType() == OId::DBTCINDEXOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBTCIndexId" << objId);
+ DBRef<DBTCIndex> t(objId);
+ return (HierIndexDS*)t.ptr();
+ }
+ }
+ }
+ TALK( "DBRef::HierIndexDS*(): operator mismatch" << objId);
+ RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator HierIndexDS*() mismatch " << objId);
+ throw r_Error(r_Error::r_Error_DatabaseClassMismatch);
+ }
+
+
+template <class T>
+DBRef<T>::operator IndexDS*() const throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() " << objId);
+ if (object && pointerCaching)
+ {
+ if ((object->getObjectType() == OId::MDDHIERIXOID) || (object->getObjectType() == OId::DBTCINDEXOID) || (object->getObjectType() == OId::MDDRCIXOID))
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() " << objId);
+ return (IndexDS*)object;
+ }
+ }
+ else {
+ if (objId.getType() == OId::MDDHIERIXOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBHierIndexId" << objId);
+ DBRef<DBHierIndex> t(objId);
+ return (IndexDS*)t.ptr();
+ }
+ else {
+ if (objId.getType() == OId::DBTCINDEXOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBTCIndexId" << objId);
+ DBRef<DBTCIndex> t(objId);
+ return (IndexDS*)t.ptr();
+ }
+ else {
+ if (objId.getType() == OId::MDDRCIXOID)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBRCIndexId" << objId);
+ DBRef<DBRCIndexDS> t(objId);
+ return (IndexDS*)t.ptr();
+ }
+ }
+ }
+ }
+ TALK( "DBRef::IndexDS*(): operator mismatch" << objId);
+ RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator IndexDS*() mismatch " << objId);
+ throw r_Error(r_Error::r_Error_DatabaseClassMismatch);
+ }
+
+
+template <class T>
+bool DBRef<T>::is_null(void) const
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "is_null() " << objId);
+ bool retval = false;
+ T* t = 0;
+ if (object == 0)
+ {
+ if (objId.getType() == OId::INVALID)
+ {
+ throw r_Error(r_Error::r_Error_OIdInvalid);
+ }
+ else {
+ try {
+ t = (T*)ObjectBroker::getObjectByOId(objId);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "found object");
+ t->incrementReferenceCount();
+ ((DBRef<T>*)this)->object = t;
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "object is at: " << object << " found object was at: " << t);
+ }
+ catch (r_Error& err)
+ {
+ if (err.get_kind() == r_Error::r_Error_ObjectUnknown)
+ retval = true;
+ else
+ throw;
+ }
+ }
+ }
+ else {
+ if (pointerCaching == false)
+ {
+ if (pointerValid == false)
+ {
+ try {
+ t = (T*)ObjectBroker::getObjectByOId(objId);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "found object");
+ t->incrementReferenceCount();
+ ((DBRef<T>*)this)->object = t;
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "object is at: " << object << " found object was at: " << t);
+ }
+ catch (r_Error& err)
+ {
+ if (err.get_kind() == r_Error::r_Error_ObjectUnknown)
+ retval = true;
+ else
+ throw;
+ }
+ }
+ else {
+ //retval = false; is done in initialize
+ }
+ }
+ else {
+ //retval = false; is done in initialize
+ }
+ }
+ RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "is_null() " << objId << " " << retval);
+ return retval;
+ }
diff --git a/reladminif/dbref.hh b/reladminif/dbref.hh
new file mode 100644
index 0000000..35065a9
--- /dev/null
+++ b/reladminif/dbref.hh
@@ -0,0 +1,301 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************
+ *
+ *
+ * PURPOSE:
+ * DBRef is a smart pointer for managing objects derived from
+ * the DbObject class.
+ *
+ *
+ * COMMENTS:
+ *
+ ************************************************************/
+
+
+#ifndef _DBREF_HH_
+#define _DBREF_HH_
+
+class DBHierIndex;
+class DBRCIndexDS;
+class DBTCIndex;
+class BLOBTile;
+class InlineTile;
+class DBTile;
+class OId;
+class DBObject;
+class r_Error;
+class IndexDS;
+class HierIndexDS;
+class DBMDDObj;
+
+template <class T> class DBRef;
+
+#include "oidif.hh"
+
+//@ManMemo: Module: {\bf reladminif}.
+/*@Doc:
+DBRef is a smart pointer class operating on classes derived from DbObject. A smart
+pointer to an object with a known id is created using DBRef<T>(id). The object
+managed by a given smart pointer can be changed (rebinding) by using the assignment
+operator.
+All access methods may throw database related r_Errors.
+*/
+
+#define DBOBJID_NONE OId()
+
+template <class T>
+class DBRef
+ {
+ public:
+
+ DBRef(void);
+ /*@Doc:
+ Default constructor. Object must be assigned a value before the first dereferencing.
+ */
+
+ DBRef(const OId &id);
+ /*@Doc:
+ Id-constructor, binds smart pointer to object with the given id (must only be unique
+ within class T, not within all classes derived from DbObject).
+ */
+
+ DBRef(OId::OIdPrimitive id);
+ /*@Doc:
+ Id-constructor, binds smart pointer to object with the given id (must only be unique
+ within class T, not within all classes derived from DbObject).
+ */
+
+ DBRef(const DBRef<T> &src);
+ /*@Doc:
+ Copy-constructor, binds smart pointer to the same object src is bound to.
+ */
+
+ DBRef(T *ptr);
+ /*@Doc:
+ Object-constructor, binds smart pointer explicitly to the object ptr.
+ */
+
+ ~DBRef(void);
+ /*@Doc:
+ Destructor: decrements reference count for the object that was managed by this
+ smart pointer.
+ */
+
+ bool operator<(const DBRef<T>& other) const;
+ /*@Doc:
+ Returns true if me.operator==(other) returns -1
+ */
+
+ int operator==(const DBRef<T> &src) const;
+ /*@Doc:
+ Comparison operator:
+ Returns:
+ -1 if this is not initialised and src is initialised
+ -1 if persistent and objId < src.objId
+ -1 if transient and src is persistent
+ -1 if transient and object < src.object
+ 0 if persistent and src persistent and myOId == src.myOId
+ 0 if transient and src transient and object == src.object
+ 0 if this is not initialised and src is not initialised
+ +1 if persistent and objId > src.objId
+ +1 if persistent and src is transient
+ +1 if transient and object > src.object
+ -1 if this is initialised and src is not initialised
+ */
+
+ DBRef<T> &operator=(const DBRef<T> &src);
+ /*@Doc:
+ Assignment operator: removes old binding and rebinds to the same object managed by src.
+ */
+
+ DBRef<T> &operator=(T *ptr);
+ /*@Doc:
+ Assignment operator: removes old binding and rebinds to object ptr.
+ */
+
+ T *operator->(void) throw (r_Error);
+ /*@Doc:
+ Dereferencing operator -> for accessing the managed object's members.
+ */
+
+ const T *operator->(void) const throw (r_Error);
+ /*@Doc:
+ Dereferencing operator -> for accessing the managed object's members.
+ */
+
+ T &operator*(void) throw (r_Error);
+ /*@Doc:
+ Dereferencing operator * for accessing the managed object.
+ */
+
+ const T &operator*(void) const throw (r_Error);
+ /*@Doc:
+ Dereferencing operator * for accessing the managed object.
+ */
+
+#ifndef __GNUG__
+ T &operator[](int idx) const throw (r_Error);
+ /*@Doc:
+ Dereferencing operator [] for accessing array objects.
+ */
+#endif
+
+ T *ptr(void) throw (r_Error);
+ /*@Doc:
+ Returns pointer to managed object.
+ */
+
+ const T *ptr(void) const throw (r_Error);
+ /*@Doc:
+ Returns pointer to managed object.
+ */
+
+ OId getOId(void) const;
+ /*@Doc:
+ Returns id of managed object
+ */
+
+ void delete_object(void);
+ /*@Doc:
+ deletes the object from database if it is valid else throws an exception.
+ */
+
+ bool is_null(void) const;
+ /*@Doc:
+ Returns false if valid binding exists, true otherwise.
+ this method may instantiate an object from the database
+ */
+
+ bool is_valid(void) const;
+ /*@Doc:
+ Returns true if valid binding exists, false otherwise
+ */
+
+ bool isInitialised() const;
+ /*@Doc:
+ Returns true if OId is valid or the pointer is valid, false otherwise
+ */
+
+ void release();
+ /*@Doc:
+ releases this DBRef pointer and refcount to its object
+ */
+
+ operator DBRef<DBObject>() const;
+ /*@Doc:
+ cast operator. works allways.
+ */
+
+ operator DBRef<BLOBTile>() const throw (r_Error);
+ /*@Doc:
+ cast operator. checks it the objects type is of OId::BLOBOID.
+ */
+
+ operator DBRef<DBTile>() const throw (r_Error);
+ /*@Doc:
+ cast operator. checks it the objects type is of OId::BLOBOID or OId::INLINETILEOID.
+ */
+
+ operator DBRef<InlineTile>() const throw (r_Error);
+ /*@Doc:
+ cast operator. checks it the objects type is of OId::INLINETILEOID.
+ */
+
+ operator DBRef<DBHierIndex>() const throw (r_Error);
+ /*@Doc:
+ cast operator. checks it the objects type is of OId::MDDHIERIXOID.
+ */
+
+ operator DBRef<DBTCIndex>() const throw (r_Error);
+ /*@Doc:
+ cast operator. checks it the objects type is of OId::INLINEIXOID.
+ */
+
+ operator DBRef<DBRCIndexDS>() const throw (r_Error);
+ /*@Doc:
+ cast operator. checks it the objects type is of OId::MDDRCIXOID.
+ */
+
+ operator IndexDS*() const throw (r_Error);
+ /*@Doc:
+ cast operator. checks it the objects type is of any valid index.
+ */
+
+ operator HierIndexDS*() const throw (r_Error);
+ /*@Doc:
+ cast operator. checks it the objects type is of any valid hierarchical index.
+ */
+
+ operator T*() throw (r_Error);
+ /*@Doc:
+ */
+
+ operator const T*() const throw (r_Error);
+ /*@Doc:
+ */
+
+ static void setPointerCaching(bool useIt);
+ /*@Doc:
+ Make the dbref store and use pointers.
+ If set to false the DBRef will always ask the objectbroker.
+ May be set at any time to false.
+ Only between transactions may it be set to true.
+ */
+
+ static bool getPointerCaching();
+ /*@Doc:
+ returns pointerCaching
+ */
+
+ private:
+
+
+ mutable T *object;
+ /*@Doc:
+ Pointer to the managed object or 0 if no binding exists.
+ */
+
+ OId objId;
+ /*@Doc:
+ id of managed object.
+ */
+
+ bool pointerValid;
+ /*@Doc:
+ whenever a smartpointer is initiaised by a pointer, this attribute is set to true.
+ this is neccessary for disabled pointer caching.
+ */
+
+ static bool pointerCaching;
+ };
+
+template <class T> bool operator< (const DBRef<T> &me, const DBRef<T> &him);
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#include "dbref.cc"
+#endif
+#endif
+
+#endif
diff --git a/reladminif/destroyable.hh b/reladminif/destroyable.hh
new file mode 100644
index 0000000..316cfeb
--- /dev/null
+++ b/reladminif/destroyable.hh
@@ -0,0 +1,52 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#ifndef _DESTROYABLE_HH_
+#define _DESTROYABLE_HH_
+
+/****************************************************************************
+ *
+ *
+ *
+ * COMMENTS:
+ *
+ ****************************************************************************/
+
+//@ManMemo: Module: {\bf reladminif}
+/*@Doc:
+
+This is an interface class. It is abstract. It supplies the signature that
+is required to allow other interfaces to be defined without a virtual destructor.
+*/
+
+class Destroyable
+ {
+ public:
+ virtual void destroy() = 0;
+ /*@Doc:
+ delete the object.
+ object may not be deleted when reference counting is enabled.
+ */
+
+ };
+
+#endif
diff --git a/reladminif/eoid.cc b/reladminif/eoid.cc
new file mode 100644
index 0000000..f07497e
--- /dev/null
+++ b/reladminif/eoid.cc
@@ -0,0 +1,231 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************
+ *
+ *
+ * PURPOSE:
+ * EOId is optimized for maps that contain only EOId of one system/database.
+ *
+ *
+ * COMMENTS:
+ *
+ **********************************************************************/
+
+#include "eoid.hh"
+#include "externs.h"
+#include "adminif.hh"
+#include "databaseif.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/error.hh"
+
+void
+EOId::print_status(std::ostream& s) const
+ {
+ s << systemName.c_str() << "|" << databaseName.c_str() << "|";
+ OId::print_status(s);
+ }
+
+std::ostream&
+operator<<(std::ostream& s, const EOId& d )
+ {
+ s << "EOId(" << d.getSystemName() << "|" << d.getBaseName() << "|" << d.getOId() << ")";
+ return s;
+ }
+
+std::ostream&
+operator<<(std::ostream& s, EOId& d )
+ {
+ s << "EOId(" << d.getSystemName() << "|" << d.getBaseName() << "|" << d.getOId() << ")";
+ return s;
+ }
+
+EOId::EOId(const char* systemname, const char* dbname, OId::OIdCounter id, OId::OIdType type)
+ : OId(id, type),
+ systemName(systemname),
+ databaseName(dbname)
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "EOId(" << systemname << "," << dbname << "," << id << "," << type << ")");
+ }
+
+EOId::EOId(const OId& id)
+ : OId(id)
+ {
+ RMDBGENTER(10, RMDebug::module_adminif, "EOId", "EOId(" << id << ")");
+ if (AdminIf::getCurrentDatabaseIf())
+ {
+ systemName = (AdminIf::getSystemName());
+ databaseName = (AdminIf::getCurrentDatabaseIf()->getName());
+ }
+ else {
+ RMDBGMIDDLE(10, RMDebug::module_adminif, "EOId", "EOId(" << id << ") no current databaseif");
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ }
+ RMDBGEXIT(10, RMDebug::module_adminif, "EOId", "EOId(" << id << ")");
+ }
+
+EOId::EOId()
+ : OId()
+ {
+ RMDBGENTER(10, RMDebug::module_adminif, "EOId", "EOId()");
+ if (AdminIf::getCurrentDatabaseIf())
+ {
+ systemName = (AdminIf::getSystemName());
+ databaseName = (AdminIf::getCurrentDatabaseIf()->getName());
+ }
+ else {
+ RMDBGMIDDLE(10, RMDebug::module_adminif, "EOId", "EOId() no current databaseif");
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ }
+ RMDBGEXIT(10, RMDebug::module_adminif, "EOId", "EOId()");
+ }
+
+EOId::~EOId()
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "~EOId()");
+ }
+
+const char*
+EOId::getSystemName() const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "getSystemName() " << systemName.c_str());
+ return systemName.c_str();
+ }
+
+
+const char*
+EOId::getBaseName() const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "getBaseName() " << databaseName.c_str());
+ return databaseName.c_str();
+ }
+
+
+OId
+EOId::getOId() const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "getOId() " << (OId)*this);
+ return(OId)*this;
+ }
+
+
+void
+EOId::allocateEOId(EOId& eoid, OId::OIdType t) throw (r_Error)
+ {
+ RMDBGENTER(10, RMDebug::module_adminif, "EOId", "allocateEOId(" << eoid << "," << t << ")");
+ if (AdminIf::getCurrentDatabaseIf())
+ {
+ eoid.systemName = AdminIf::getSystemName();
+ eoid.databaseName = AdminIf::getCurrentDatabaseIf()->getName();
+ }
+ else {
+ RMDBGMIDDLE(10, RMDebug::module_adminif, "EOId", "allocateEOId(" << eoid << ") no current databaseif");
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ }
+ allocateOId(eoid, t);
+ RMDBGEXIT(10, RMDebug::module_adminif, "EOId", "allocateEOId(" << eoid << "," << t << ")");
+ }
+
+bool
+EOId::operator==(const EOId& one) const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator==(" << one << ")");
+ bool retval=false;
+ if(OId::operator==(one))
+ if(systemName == one.systemName)
+ if(databaseName == one.databaseName)
+ retval=true;
+ return retval;
+ }
+
+bool
+EOId::operator!=(const EOId& one) const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator!=(" << one << ")");
+ return !EOId::operator==(one);
+ }
+
+EOId&
+EOId::operator=(const EOId& old)
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator=(" << old << ")");
+ if(this != &old)
+ {
+ OId::operator=(old);
+ systemName = old.systemName;
+ databaseName = old.databaseName;
+ }
+ return *this;
+ }
+
+bool
+EOId::operator<(const EOId& old) const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator<(" << old << ")");
+ bool retval=false;
+ if (OId::operator<(old))
+ retval=true;
+ if (!retval && (databaseName < old.databaseName))
+ retval=true;
+ if (!retval && (systemName < old.systemName))
+ retval=true;
+ return retval;
+ }
+
+bool
+EOId::operator>(const EOId& old) const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator>(" << old << ")");
+ bool retval=false;
+ if (OId::operator>(old))
+ retval=true;
+ if (!retval && (databaseName > old.databaseName))
+ retval=true;
+ if (!retval && (systemName > old.systemName))
+ retval=true;
+ return retval;
+ }
+
+bool
+EOId::operator<=(const EOId& old) const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator<=(" << old << ")");
+ bool retval=false;
+ if (operator<(old))
+ retval=true;
+ if (!retval && (operator==(old)))
+ retval=true;
+ return retval;
+ }
+
+bool
+EOId::operator>=(const EOId& old) const
+ {
+ RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator<=(" << old << ")");
+ bool retval=false;
+ if (operator>(old))
+ retval=true;
+ if (!retval && (operator==(old)))
+ retval=true;
+ return retval;
+ }
+
diff --git a/reladminif/eoid.hh b/reladminif/eoid.hh
new file mode 100644
index 0000000..968dcb5
--- /dev/null
+++ b/reladminif/eoid.hh
@@ -0,0 +1,146 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#ifndef _EOIDIF_HH_
+#define _EOIDIF_HH_
+/*************************************************************
+ *
+ *
+ * PURPOSE:
+ * EOId is optimized for maps that contain only EOId of one system/database.
+ *
+ *
+ * COMMENTS:
+ * When true multiple connections are implemented the order of compare
+ * statements in the operator"<" and ">" must be changed.
+ ***************************************************************************/
+
+class EOId;
+class r_Error;
+
+#include "oidif.hh"
+#include <string>
+
+//@ManMemo: Module: {\bf reladminif}.
+/*@Doc:
+EOId is optimized for maps that contain only EOId of one system/database.
+when true multiple connections are implemented the order of compare
+statements in the operator"<" and ">" must be changed.
+*/
+
+class EOId : public OId
+ {
+ public:
+ EOId(const char* systemname, const char* dbname, OId::OIdCounter id, OIdType type);
+ /*@Doc:
+ constructs a complete EOId.
+ */
+
+ EOId(const OId& id);
+ /*@Doc:
+ uses the currently open database to get system and db name
+ systemname and database name will be null string when the
+ database is not really open.
+ */
+
+ EOId();
+ /*@Doc:
+ uses the currently open database to get system and db name
+ systemname and database name will be null string when the
+ database is not really open.
+ */
+
+
+ ~EOId();
+ /*@Doc:
+ does not do anything.
+ */
+
+ EOId& operator=(const EOId& old);
+ /*@Doc:
+ assignes all atributes.
+ */
+
+
+ const char* getSystemName() const;
+ /*@Doc:
+ returns the system name, which is the same as the
+ one returned by databaseif.
+ */
+
+
+ const char* getBaseName() const;
+ /*@Doc:
+ returns the database name, which is the same as the
+ one returned by databaseif
+ */
+
+
+ OId getOId() const;
+ /*@Doc:
+ returns the oid of this eoid
+ */
+
+
+ void print_status(std::ostream& o) const;
+ /*@Doc:
+ returns the systemname|databasename|oid
+ */
+
+ static void allocateEOId(EOId& eoid, OId::OIdType t) throw (r_Error);
+ /*@Doc:
+ Allocates a new logical MDD EOid in the currently opened base.
+ throws an r_Error_DatabaseClosed when the database is not really open.
+ */
+
+ bool operator<(const EOId& old) const;
+
+ bool operator>(const EOId& old) const;
+
+ bool operator<=(const EOId& old) const;
+
+ bool operator>=(const EOId& old) const;
+
+ bool operator== (const EOId& one) const;
+
+ bool operator!= (const EOId& one) const;
+
+ private:
+
+ std::string databaseName;
+ /*@Doc:
+ the name of the database the oid of this eoid is valid for.
+ stl std::string was used because of the compare functionality.
+ */
+
+ std::string systemName;
+ /*@Doc:
+ the name of the system above mentioned database runs on
+ stl std::string was used because of the compare functionality.
+ */
+ };
+
+extern std::ostream& operator<<(std::ostream& s, EOId& d);
+
+extern std::ostream& operator<<(std::ostream& s, const EOId& d);
+
+#endif
diff --git a/reladminif/externs.h b/reladminif/externs.h
new file mode 100644
index 0000000..d947c7e
--- /dev/null
+++ b/reladminif/externs.h
@@ -0,0 +1,81 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*****************************************************************************
+ *
+ *
+ * PURPOSE:
+ * provide global definitions for embedded SQL usage (any base DBMS)
+ *
+ *
+ * COMMENTS:
+ * - uses embedded SQL
+ * - FIXME: should also contain stuff from sqlglobals.h, merge some time
+ *
+ *****************************************************************************/
+
+#ifndef _EXTERNS_H_
+#define _EXTERNS_H_
+
+const int SQLOK = 0;
+const short INDNULL = -1;
+
+#ifdef BASEDB_INFORMIX
+ const int SQLNULLFETCHED = -245;
+ const int SQLTABLEUNKNOWN = -206;
+ const int SQLNODATAFOUND = 100;
+
+ //SQLCODE and SQLSTATE are defined in the sqlca.h file
+#endif // informix
+
+#ifdef BASEDB_DB2
+ const int SQLNULLFETCHED = -1405;
+ const int SQLTABLEUNKNOWN = -942;
+ const int SQLNODATAFOUND = 100;
+
+ //declared in sqlerror.sqC
+ extern long SQLCODE;
+ extern char SQLSTATE[6];
+
+#endif // db2
+
+#ifdef BASEDB_ORACLE
+ const int SQLNULLFETCHED = -1405;
+ const int SQLTABLEUNKNOWN = -942;
+ const int SQLNODATAFOUND = 100;
+
+ #include <sqlca.h>
+ #define SQLCODE sqlca.sqlcode
+
+ //declared in sqlerror.pc
+ extern struct sqlca sqlca;
+#endif // oracle
+
+#ifdef BASEDB_PGSQL
+ #include "ecpgerrno.h" // PgSQL error codes
+ // const int SQLNULLFETCHED = -1405; unused
+ // const int SQLTABLEUNKNOWN = -942; not supported by PG
+ const int SQLNODATAFOUND = ECPG_NOT_FOUND;
+ //SQLCODE and SQLSTATE are defined in the sqlca.h file
+#endif // pgsql
+
+#endif // _EXTERNS_H_
diff --git a/reladminif/lists.h b/reladminif/lists.h
new file mode 100644
index 0000000..783c2af
--- /dev/null
+++ b/reladminif/lists.h
@@ -0,0 +1,106 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#ifndef _LISTS_H_
+#define _LISTS_H_
+
+#include <vector>
+#include <set>
+#include <map>
+#include "relmddif/mddid.hh"
+
+class DBObject;
+class OId;
+class InlineMinterval;
+class r_Minterval;
+class KeyObject;
+class IndexDS;
+class HierIndexDS;
+class Tile;
+
+#include "raslib/mddtypes.hh"
+
+//used to hold oids for indexes, blobs, and dbmintervals. no double entries
+typedef std::set< OId, std::less< double > > OIdSet;
+
+//used to hold oids for indexes, blobs, and dbmintervals. no double entries
+typedef std::set< const OId, std::less< double > > OIdConstSet;
+
+typedef std::vector<HierIndexDS*> HierIndexDSPVector;
+
+//used to hold DBObject*. e.g. in objectbroker to temporarily store them before deletion
+typedef std::vector<DBObject*> DBObjectPVector;
+
+//used to hold DBObject*. e.g. in objectbroker to temporarily store them before deletion
+typedef std::vector<const DBObject*> DBObjectPConstVector;
+
+//used to hold oids for indexes, blobs, and dbmintervals
+typedef std::vector<OId> OIdVector;
+
+//used to hold oids for indexes, blobs, and dbmintervals
+typedef std::vector<const OId> OIdConstVector;
+
+//holds type information on specific blobs which are stored in above oidlists
+typedef std::vector<r_Data_Format> CompTypeVector;
+
+typedef std::vector<const InlineMinterval*> IntervalPConstVector;
+
+typedef std::vector<InlineMinterval*> IntervalPVector;
+
+typedef std::vector<const InlineMinterval> IntervalConstVector;
+
+typedef std::vector<InlineMinterval> IntervalVector;
+
+typedef std::vector<const KeyObject*> KeyObjectPConstVector;
+
+typedef std::vector<KeyObject*> KeyObjectPVector;
+
+typedef std::vector<const KeyObject> KeyObjectConstVector;
+
+typedef std::vector<KeyObject> KeyObjectVector;
+
+typedef std::vector<r_Minterval> DomainVector;
+
+typedef std::vector<r_Minterval*> DomainPVector;
+
+typedef std::vector<const r_Minterval*> DomainPConstVector;
+
+typedef std::vector<IndexDS*> IndexPVector;
+
+typedef std::vector<Tile*> TilePVector;
+
+typedef std::map< double, DBObject*, std::less<double> > DBObjectPMap;
+typedef std::pair< double, DBObject* > DBObjectPPair;
+typedef std::pair< const double, DBObject* > ConstDBObjectPPair;
+
+typedef std::map< double, const DBObject*, std::less<double> > DBObjectPConstMap;
+typedef std::pair< double, const DBObject* > DBObjectPConstPair;
+typedef std::pair< const double, const DBObject* > ConstDBObjectPConstPair;
+
+typedef std::map< double, OId, std::less<double> > OIdMap;
+typedef std::pair< const double, OId > OIdPair;
+typedef std::pair< const double, const OId > OIdConstPair;
+
+typedef std::map< double, r_Minterval, std::less<double> > DomainMap;
+typedef std::pair< const double, r_Minterval > DomainPair;
+typedef std::pair< const double, const r_Minterval > DomainConstPair;
+#endif
diff --git a/reladminif/objectbroker.hh b/reladminif/objectbroker.hh
new file mode 100644
index 0000000..bb8d429
--- /dev/null
+++ b/reladminif/objectbroker.hh
@@ -0,0 +1,506 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#ifndef _OBJECTBROKER_HH_
+#define _OBJECTBROKER_HH_
+
+class ObjectBroker;
+class ULongType;
+class LongType;
+class CharType;
+class BoolType;
+class UShortType;
+class ShortType;
+class OctetType;
+class DoubleType;
+class FloatType;
+class ComplexType1;
+class ComplexType2;
+class StructType;
+class BaseType;
+class SetType;
+class MDDType;
+class Type;
+class DBObject;
+
+#include "oidif.hh"
+#include "raslib/error.hh"
+#include "lists.h"
+
+#ifdef RMANBENCHMARK
+#include "raslib/rmdebug.hh"
+#endif
+
+//@ManMemo: Module: {\bf reladminif}.
+/*@Doc:
+the ObjectBroker is one of the three columns one which the persistence layer rests:
+ObjectBroker, DBRef, DBObject.
+the ObjectBroker keeps track of all persistent objects which are loaded into memory.
+objects register themselves at this facility and deregister themselves when they are
+deleted.
+
+The ObjectBroker supplies functionality for accessing persistent objects by oid and by
+name.
+The ObjectBroker can be configured to serve as a cross transaction cache.
+The ObejctBroker can retrieve the oids of all objects of a specific type which are stored
+in the database.
+The list of objects which are kept by the ObjectBroker are cleared by TransactionIf.
+*/
+
+class ObjectBroker
+ {
+ public:
+ static bool freeMemory() throw (r_Error);
+ /*@Doc:
+ this will handle the memory issue.
+ returns true if memory was freed, false otherwise.
+ if false is returned there is really to much memory allocated and the transaction should be stopped.
+ */
+
+ static void deregisterTileIndexMapping(const OId& tileoid, const OId& indexoid);
+ /*@Doc:
+ deletes the object in the correct list
+ */
+
+ static void registerTileIndexMapping(const OId& tileoid, const OId& indexoid);
+ /*@Doc:
+ inserts the object in the correct list
+ */
+
+ static void registerDBObject(DBObject* object);
+ /*@Doc:
+ inserts the object in the correct list
+ */
+
+ static void deregisterDBObject(const OId& id);
+ /*@Doc:
+ removes the object with the specified oid from the list
+ */
+
+ static DBObject* getObjectByOId(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieve a dbobject from db. passes (r_Error)s from DBObject up.
+ */
+
+ static DBObject* isInMemory(const OId& id) throw (r_Error);
+ /*@Doc:
+ does not retrieve the object from db. only retrieves from memory.
+ if there is no matching object a 0 pointer is returned.
+ throws an (r_Error) if the OId has a invalid type
+ */
+
+ static OIdSet* getAllObjects(OId::OIdType type);
+ /*@Doc:
+ generates a list of all objects in the db and in memory with the
+ specified type. the vector must be deleted by the calling function
+ */
+
+ static MDDType* getMDDTypeByName(const char* name) throw (r_Error);
+ /*@Doc:
+ retrieves an object with that name and that type from the db.
+ this method was introduced to remove the spurious sqlwarnings.
+ passes (r_Error)s from DBObject up or ObjectNotFound when there is
+ no matching object
+ */
+
+ static DBObject* getObjectByName(OId::OIdType type, const char* name) throw (r_Error);
+ /*@Doc:
+ retrieves an object with that name and that type from the db.
+ passes (r_Error)s from DBObject up or ObjectNotFound when there is
+ no matching object
+ */
+
+ static void clearBroker() throw (r_Error);
+ /*@Doc:
+ deletes persistent objects from memory, depending on cache ofcourse.
+ any (r_Error)s thrown during the deletion/update/insert process are
+ handed up. the objects are removed before errors can occur. multiple
+ calls to clearBroker until the method completes are possible. memory
+ leaks may occur in this event.
+ */
+
+ static void clearCache() throw (r_Error);
+ /*@Doc:
+ deletes _all_ persistent objects from memory.
+ any (r_Error)s thrown during the deletion/update/insert process are
+ handed up. the objects are removed before errors can occur. multiple
+ calls to clearBroker until the method completes are possible. memory
+ leaks may occur in this event.
+ */
+
+ static void init();
+ /*@Doc:
+ initialize the atomic types and maps
+ */
+
+ static void deinit();
+ /*@Doc:
+ delete the atomic types and maps
+ */
+
+ static DBObjectPMap& getMap(OId::OIdType type) throw (r_Error);
+ /*@Doc:
+ returns a pointer to the store of objects of that particular type.
+ (r_Error) is thrown if there is no map for that type
+ */
+
+ protected:
+ static DBObject* loadDBMDDObj(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves MDDObjects from memory and from database
+ */
+
+ static DBObject* loadMDDSet(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves MDDSets from memory and from database
+ */
+
+ static DBObject* loadMDDType(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves MDDTypes from memory and from database
+ */
+
+ static DBObject* loadMDDBaseType(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves MDDBaseTypes from memory and from database
+ */
+
+ static DBObject* loadMDDDimensionType(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves MDDDimTypes from memory and from database
+ */
+
+ static DBObject* loadMDDDomainType(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves MDDDomTypes from memory and from database
+ */
+
+ static DBObject* loadStructType(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves StructTypes from memory and from database
+ */
+
+ static DBObject* loadSetType(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves SetTypes from memory and from database
+ */
+
+ static DBObject* loadBLOBTile(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves BLOBTiles from memory and from database.
+ knows how to get a inlinetile from a dbtcindex.
+ */
+
+ static DBObject* loadDBMinterval(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves DBMintervals from memory and from database
+ */
+
+ static DBObject* loadDBStorage(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves DBStorageLayout from memory and from database
+ */
+
+ static DBObject* loadDBHierIndex(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves HierIxs from memory and from database
+ */
+
+ static DBObject* loadDBTCIndex(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves DBTCIndex from memory and from database
+ */
+
+ static DBObject* loadInlineTile(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves InlineTiles from memory and from database
+ */
+
+ static DBObject* loadDBRCIndexDS(const OId& id) throw (r_Error);
+ /*@Doc:
+ retrieves DBRCIndexDS from memory and from database
+ */
+
+ static OId getOIdByName(OId::OIdType type, const char* name) throw (r_Error);
+ /*@Doc:
+ finds the oid of an object with the given type and name
+ */
+
+ static void clearMap(DBObjectPMap& theMap) throw (r_Error);
+ /*@Doc:
+ deletes entries in this map as long as they are not cached
+ (r_Error) is thrown when there is a problem in ~DBObject.
+ the object is removed from the map though.
+ */
+
+ static void completelyClearMap(DBObjectPMap& theMap) throw (r_Error);
+ /*@Doc:
+ deletes entries in this map
+ (r_Error) is thrown when there is a problem in ~DBObject.
+ the object is removed from the map though.
+ */
+
+
+ static OId getOIdOfMDDSet(const char* name) throw (r_Error);
+ /*@Doc:
+ retrieves MDDSets from memory and from database
+ */
+
+ static OId getOIdOfMDDType(const char* name) throw (r_Error);
+ /*@Doc:
+ retrieves MDDTypes from memory and from database
+ */
+
+ static OId getOIdOfMDDBaseType(const char* name) throw (r_Error);
+ /*@Doc:
+ retrieves MDDBaseTypes from memory and from database
+ */
+
+ static OId getOIdOfMDDDimensionType(const char* name) throw (r_Error);
+ /*@Doc:
+ retrieves MDDDimTypes from memory and from database
+ */
+
+ static OId getOIdOfMDDDomainType(const char* name) throw (r_Error);
+ /*@Doc:
+ retrieves MDDDomTypes from memory and from database
+ */
+
+ static OId getOIdOfStructType(const char* name) throw (r_Error);
+ /*@Doc:
+ retrieves StructTypes from memory and from database
+ */
+
+ static OId getOIdOfSetType(const char* name) throw (r_Error);
+ /*@Doc:
+ retrieves SetTypes from memory and from database
+ */
+
+ static OIdSet* getAllMDDObjects() throw (r_Error);
+ /*@Doc:
+ retrieves the oids of all MDD Objects from memory and from database
+ oidlist must be deallocated by the caller
+ (r_Error) occures in a database failure
+ */
+
+ static OIdSet* getAllMDDSets() throw (r_Error);
+ /*@Doc:
+ retrieves the oids of all MDDSets from memory and from database
+ oidlist must be deallocated by the caller
+ (r_Error) occures in a database failure
+ */
+
+ static OIdSet* getAllMDDTypes() throw (r_Error);
+ /*@Doc:
+ retrieves the oids of all MDDTypes from memory and from database
+ oidlist must be deallocated by the caller
+ (r_Error) occures in a database failure
+ */
+
+ static OIdSet* getAllMDDBaseTypes() throw (r_Error);
+ /*@Doc:
+ retrieves the oids of all MDDBaseTypes from memory and from database
+ oidlist must be deallocated by the caller
+ (r_Error) occures in a database failure
+ */
+
+ static OIdSet* getAllMDDDimensionTypes() throw (r_Error);
+ /*@Doc:
+ retrieves the oids of all MDDDimTypes from memory and from database
+ oidlist must be deallocated by the caller
+ (r_Error) occures in a database failure
+ */
+
+ static OIdSet* getAllMDDDomainTypes() throw (r_Error);
+ /*@Doc:
+ retrieves the oids of all MDDDomTypes from memory and from database
+ oidlist must be deallocated by the caller
+ (r_Error) occures in a database failure
+ */
+
+ static OIdSet* getAllStructTypes() throw (r_Error);
+ /*@Doc:
+ retrieves the oids of all StructTypes from memory and from database
+ oidlist must be deallocated by the caller
+ (r_Error) occures in a database failure
+ */
+
+ static OIdSet* getAllSetTypes() throw (r_Error);
+ /*@Doc:
+ retrieves the oids of all SetTypes from memory and from database
+ oidlist must be deallocated by the caller
+ (r_Error) occures in a database failure
+ */
+
+ static OIdSet* getAllAtomicTypes() throw (r_Error);
+ /*@Doc:
+ retrieves the oids of all AtomicTypes from memory
+ oidlist must be deallocated by the caller
+ (r_Error) should never occur
+ */
+
+ private:
+ ///the types have to be in fornt of* the maps because of static destructor!
+ static ULongType* theULong;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static CharType* theChar;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static BoolType* theBool;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static UShortType* theUShort;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static LongType* theLong;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static ShortType* theShort;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static OctetType* theOctet;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static DoubleType* theDouble;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static FloatType* theFloat;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static ComplexType1* theComplex1;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static ComplexType2* theComplex2;
+ /*@Doc:
+ a pointer to this member is returned by getObjectByOId().
+ */
+
+ static DBObjectPMap theDBMDDObjs;
+ /*@Doc:
+ holds all MDDObjects in memory
+ */
+
+ static DBObjectPMap theMDDSets;
+ /*@Doc:
+ holds all MDDSets in memory
+ */
+
+ static DBObjectPMap theMDDTypes;
+ /*@Doc:
+ holds all MDDTypes in memory
+ */
+
+ static DBObjectPMap theMDDBaseTypes;
+ /*@Doc:
+ holds all MDDBaseTypes in memory
+ */
+
+ static DBObjectPMap theMDDDimensionTypes;
+ /*@Doc:
+ holds all MDDDimTypes in memory
+ */
+
+ static DBObjectPMap theMDDDomainTypes;
+ /*@Doc:
+ holds all MDDDomTypes in memory
+ */
+
+ static DBObjectPMap theStructTypes;
+ /*@Doc:
+ holds all StructTypes in memory
+ */
+
+ static DBObjectPMap theSetTypes;
+ /*@Doc:
+ holds all SetTypes in memory
+ */
+
+ static DBObjectPMap theBLOBTiles;
+ /*@Doc:
+ holds all BLOBTiles in memory
+ */
+
+ static DBObjectPMap theDBMintervals;
+ /*@Doc:
+ holds all DBMintervals in memory
+ */
+
+ static DBObjectPMap theDBStorages;
+ /*@Doc:
+ holds all MDDEntries in memory
+ */
+
+ static DBObjectPMap theDBHierIndexs;
+ /*@Doc:
+ holds all HierIxs in memory
+ */
+
+ static DBObjectPMap theDBTCIndexs;
+ /*@Doc:
+ holds all HierIxs in memory
+ */
+
+ static DBObjectPMap theInlineTiles;
+ /*@Doc:
+ holds all InlineTiles in memory
+ */
+
+ static DBObjectPMap theAtomicTypes;
+ /*@Doc:
+ holds all SetTypes in memory
+ */
+
+ static DBObjectPMap theRCIndexes;
+ /*@Doc:
+ holds all RC Indexes in memory
+ */
+
+ static OIdMap theTileIndexMappings;
+ /*@Doc:
+ key (first/double) is oid of tile, value (second/oid) is oid of index.
+ */
+
+ };
+
+#endif
+
diff --git a/reladminif/objectbroker.pgc b/reladminif/objectbroker.pgc
new file mode 100644
index 0000000..9313d9c
--- /dev/null
+++ b/reladminif/objectbroker.pgc
@@ -0,0 +1,1029 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+// This is -*- C++ -*-
+
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * Code with embedded SQL for PostgreSQL DBMS
+ *
+ *
+ * COMMENTS:
+ * none
+ *
+ ***********************************************************************/
+
+static const char rcsid[] = "@(#)reladminif,ObjectBroker: $Id: objectbroker.ec,v 1.4 2003/12/27 23:11:43 rasdev Exp $";
+
+#include "debug-srv.hh"
+
+// general embedded SQL related definitions
+EXEC SQL include "sqlglobals.h";
+
+#include "objectbroker.hh"
+#include "raslib/rmdebug.hh"
+#include "sqlerror.hh"
+#include "relindexif/dbtcindex.hh"
+#include "relindexif/indexid.hh"
+#include "adminif.hh"
+#include "relindexif/dbrcindexds.hh"
+#include "relblobif/inlinetile.hh"
+#include "dbref.hh"
+#include "dbnamedobject.hh"
+#include "externs.h"
+#include "catalogmgr/typefactory.hh"
+
+DBObject*
+ObjectBroker::loadInlineTile(const OId& id) throw (r_Error)
+{
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "loadInlineTile(" << id << ")");
+ ENTER( "ObjectBroker::loadInlineTile, oid=" << id );
+
+ DBObject* retval = 0;
+ OIdMap::iterator i = theTileIndexMappings.find(id);
+ if (i != theTileIndexMappings.end())
+ {
+ DBTCIndexId dbtc((*i).second);
+ retval = (DBObject*)dbtc->getInlineTile(id);
+ }
+ else
+ {
+ try
+ {
+ retval = new InlineTile(id);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ }
+ catch (r_Error& error)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ }
+ if (retval == 0)
+ {
+ EXEC SQL BEGIN DECLARE SECTION;
+ long indexid;
+ long inlineid;
+ EXEC SQL END DECLARE SECTION;
+
+ indexid = 0;
+ inlineid = id.getCounter();
+
+ EXEC SQL SELECT
+ IndexId
+ INTO
+ :indexid
+ FROM
+ RAS_ITMAP
+ WHERE
+ TileId = :inlineid;
+ if (SQLCODE == SQLOK)
+ {
+ DBTCIndexId dbtc(OId(indexid, OId::DBTCINDEXOID));
+ retval = (DBObject*)dbtc->getInlineTile(id);
+ }
+ else
+ {
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "db error not found in db");
+ throw r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ else
+ {
+ check("ObjectBroker::loadInlineTile SELECT FROM RAS_ITMAP");
+ generateException();
+ }
+ }
+ }
+ DBObjectPPair myPair(retval->getOId(), retval);
+ theInlineTiles.insert(myPair);
+ }
+
+ LEAVE( "ObjectBroker::loadInlineTile, retval=" << retval );
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "loadInlineTile(" << id << ")");
+ return retval;
+}
+
+
+OId
+ObjectBroker::getOIdOfSetType(const char* name) throw (r_Error)
+{
+ ENTER( "ObjectBroker::getOIdOfSetType, name=" << name );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char setname[STRING_MAXLEN];
+ long setoid;
+ EXEC SQL END DECLARE SECTION;
+
+ OId retval;
+ int len = strlen(name);
+ if (len > DBNamedObject::MAXNAMELENGTH)
+ {
+ throw r_Error(TYPENAMEISTOOLONG);
+ }
+ (void) strncpy( setname, (char*) name, (size_t) sizeof(setname) );
+
+ EXEC SQL SELECT
+ SetTypeId
+ INTO
+ :setoid
+ FROM
+ RAS_SETTYPES
+ WHERE
+ SetTypeName = :setname;
+
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db");
+ throw r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ else
+ {
+ check("ObjectBroker::getOIdOfSetType()\0");
+ generateException();
+ }
+ }
+ else
+ {
+ retval = OId(setoid, OId::SETTYPEOID);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is in db with " << retval);
+ }
+
+ LEAVE( "ObjectBroker::getOIdOfSetType, retval=" << retval );
+ return retval;
+}
+
+MDDType*
+ObjectBroker::getMDDTypeByName(const char* name) throw (r_Error)
+{
+ ENTER( "ObjectBroker::getMDDTypeByName, name=" << name );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char mddtnamev[STRING_MAXLEN];
+ double mddtoidv;
+ EXEC SQL END DECLARE SECTION;
+
+ MDDType* retval = 0;
+ DBObjectPMap* theMaps[] = {&theMDDTypes, &theMDDBaseTypes, &theMDDDimensionTypes, &theMDDDomainTypes};
+
+ // FIXME: why do we iterate 5 times?
+ for (int a = 0; a < 4; a++)
+ {
+ DBObjectPMap& theMap = *theMaps[a];
+ //check if there is an object with that name already in memory
+ for (DBObjectPMap::iterator iter = theMap.begin(); iter != theMap.end(); iter++)
+ {
+ if (strcmp(((DBNamedObject*)(*iter).second)->getName(), name) == 0)
+ {
+ //RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", name << " equals " << ((DBNamedObject*)(*iter).second)->getName());
+ retval = (MDDType*)(*iter).second;
+ break;
+ }
+ else
+ {
+ //RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", name << " equals NOT " << ((DBNamedObject*)(*iter).second)->getName());
+ }
+ }
+ if (retval != 0)
+ break;
+ }
+
+ if (retval == 0)
+ {
+ int len = strlen(name);
+ if (len > DBNamedObject::MAXNAMELENGTH)
+ {
+ LEAVE( "ObjectBroker::getMDDTypeByName(): type name exceeding max length: " << name );
+ throw r_Error(TYPENAMEISTOOLONG);
+ }
+ (void) strncpy( mddtnamev, (char*) name, (size_t) sizeof(mddtnamev) );
+
+ TALK( "EXEC SQL SELECT MDDTypeOId INTO :mddtoidv FROM RAS_MDDTYPES_VIEW WHERE MDDTypeName = " << mddtnamev );
+ EXEC SQL SELECT MDDTypeOId
+ INTO :mddtoidv
+ FROM RAS_MDDTYPES_VIEW
+ WHERE MDDTypeName = :mddtnamev;
+
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db");
+ LEAVE( "ObjectBroker::getMDDTypeByName(): object not found" );
+ throw r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ else
+ {
+ check("ObjectBroker::getMDDTypeByName()\0");
+ LEAVE( "ObjectBroker::getMDDTypeByName(): database access error: " << SQLCODE );
+ generateException();
+ }
+ }
+ else
+ {
+ retval = (MDDType*)getObjectByOId(OId(mddtoidv));
+ }
+ }
+
+ LEAVE( "ObjectBroker::getMDDTypeByName, retval=" << retval );
+ return retval;
+}
+
+OId
+ObjectBroker::getOIdOfMDDType(const char* name) throw (r_Error)
+{
+ ENTER( "ObjectBroker::getOIdOfMDDType, name=" << name );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char mddtname[STRING_MAXLEN];
+ long mddtoid;
+ EXEC SQL END DECLARE SECTION;
+
+ OId retval;
+ int len = strlen(name);
+ if (len > DBNamedObject::MAXNAMELENGTH)
+ {
+ LEAVE( "ObjectBroker::getOIdOfMDDType(): name exceeds max length:" << name );
+ throw r_Error(TYPENAMEISTOOLONG);
+ }
+ (void) strncpy( mddtname, (char*) name, (size_t) sizeof(mddtname) );
+
+ TALK( "EXEC SQL SELECT MDDTypeOId INTO :mddtoid FROM RAS_MDDTYPES WHERE MDDTypeName = " << mddtname );
+ EXEC SQL SELECT MDDTypeOId
+ INTO :mddtoid
+ FROM RAS_MDDTYPES
+ WHERE MDDTypeName = :mddtname;
+
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db");
+ LEAVE( "ObjectBroker::getOIdOfMDDType(): object not in db" );
+ throw r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ else
+ {
+ check("ObjectBroker::getOIdOfMDDType()\0");
+ LEAVE( "ObjectBroker::getOIdOfMDDType(): db access error: " << SQLCODE );
+ generateException();
+ }
+ }
+ else
+ {
+ retval = OId(mddtoid,OId::MDDTYPEOID);
+ }
+
+ LEAVE( "ObjectBroker::getOIdOfMDDType, retval=" << retval );
+ return retval;
+}
+
+OId
+ObjectBroker::getOIdOfMDDBaseType(const char* name) throw (r_Error)
+{
+ ENTER( "ObjectBroker::getOIdOfMDDBaseType, name=" << name );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char mddbname[STRING_MAXLEN];
+ long mddboid;
+ EXEC SQL END DECLARE SECTION;
+
+ OId retval;
+ int len = strlen(name);
+ if (len > DBNamedObject::MAXNAMELENGTH)
+ {
+ LEAVE( "ObjectBroker::getOIdOfMDDBaseType(): name exceeds max length:" << name );
+ throw r_Error(TYPENAMEISTOOLONG);
+ }
+ (void) strncpy( mddbname, (char*) name, (size_t) sizeof(mddbname) );
+
+ TALK( "EXEC SQL SELECT MDDBaseTypeOId INTO :mddboid FROM RAS_MDDBASETYPES WHERE MDDTypeName = " << mddbname );
+ EXEC SQL SELECT MDDBaseTypeOId
+ INTO :mddboid
+ FROM RAS_MDDBASETYPES
+ WHERE MDDTypeName = :mddbname;
+
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db");
+ LEAVE( "ObjectBroker::getOIdOfMDDBaseType(): object not in db" );
+ throw r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ else
+ {
+ check("ObjectBroker::getOIdOfMDDBaseType()\0");
+ LEAVE( "ObjectBroker::getOIdOfMDDBaseType(): db access error: " << SQLCODE );
+ generateException();
+ }
+ }
+ else
+ {
+ retval = OId(mddboid,OId::MDDBASETYPEOID);
+ }
+
+ LEAVE( "ObjectBroker::getOIdOfMDDBaseType, retval=" << retval );
+ return retval;
+}
+
+OId
+ObjectBroker::getOIdOfMDDDimensionType(const char* name) throw (r_Error)
+{
+ ENTER( "ObjectBroker::getOIdOfMDDDimensionType, name=" << name );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char mdddiname[STRING_MAXLEN];
+ long mdddioid;
+ EXEC SQL END DECLARE SECTION;
+
+ OId retval;
+ int len = strlen(name);
+ if (len > DBNamedObject::MAXNAMELENGTH)
+ {
+ LEAVE( "ObjectBroker::getOIdOfMDDDimensionType(): name exceeds max length:" << name );
+ throw r_Error(TYPENAMEISTOOLONG);
+ }
+ (void) strncpy( mdddiname, (char*) name, (size_t) sizeof(mdddiname) );
+
+ TALK( "EXEC SQL SELECT MDDDimTypeOId INTO :mdddioid FROM RAS_MDDDIMTYPES WHERE MDDTypeName = " << mdddiname );
+ EXEC SQL SELECT MDDDimTypeOId
+ INTO :mdddioid
+ FROM RAS_MDDDIMTYPES
+ WHERE MDDTypeName = :mdddiname;
+
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db");
+ LEAVE( "ObjectBroker::getOIdOfMDDDimensionType(): object not in db" );
+ throw r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ else
+ {
+ check("ObjectBroker::getOIdOfMDDDimensionType()\0");
+ LEAVE( "ObjectBroker::getOIdOfMDDDimensionType(): db access error: " << SQLCODE );
+ generateException();
+ }
+ }
+ else
+ {
+ retval = OId(mdddioid,OId::MDDDIMTYPEOID);
+ }
+
+ LEAVE( "ObjectBroker::getOIdOfMDDDimensionType, retval=" << retval );
+ return retval;
+}
+
+OId
+ObjectBroker::getOIdOfMDDDomainType(const char* name) throw (r_Error)
+{
+ ENTER( "ObjectBroker::getOIdOfMDDDomainType, name=" << name );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char mdddoname[STRING_MAXLEN];
+ long mdddooid;
+ EXEC SQL END DECLARE SECTION;
+
+ OId retval;
+ int len = strlen(name);
+ if (len > DBNamedObject::MAXNAMELENGTH)
+ {
+ LEAVE( "ObjectBroker::getOIdOfMDDDomainType(): name exceeds max length:" << name );
+ throw r_Error(TYPENAMEISTOOLONG);
+ }
+ (void) strncpy( mdddoname, (char*) name, (size_t) sizeof(mdddoname) );
+
+ TALK( "EXEC SQL SELECT MDDDomTypeOId INTO :mdddooid FROM RAS_MDDDOMTYPES WHERE MDDTypeName = " << mdddoname );
+ EXEC SQL SELECT MDDDomTypeOId
+ INTO :mdddooid
+ FROM RAS_MDDDOMTYPES
+ WHERE MDDTypeName = :mdddoname;
+
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db");
+ LEAVE( "ObjectBroker::getOIdOfMDDDomainType(): object not in db" );
+ throw r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ else
+ {
+ check("ObjectBroker::getOIdOfMDDDomainType()\0");
+ LEAVE( "ObjectBroker::getOIdOfMDDDomainType(): db access error: " << SQLCODE );
+ generateException();
+ }
+ }
+ else
+ {
+ retval = OId(mdddooid,OId::MDDDOMTYPEOID);
+ }
+
+ LEAVE( "ObjectBroker::getOIdOfMDDDomainType, retval=" << retval );
+ return retval;
+}
+
+OId
+ObjectBroker::getOIdOfStructType(const char* name) throw (r_Error)
+{
+ ENTER( "ObjectBroker::getOIdOfStructType, name=" << name );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char structname[STRING_MAXLEN];
+ long structoid;
+ EXEC SQL END DECLARE SECTION;
+
+ OId retval;
+ int len = strlen(name);
+ if (len > DBNamedObject::MAXNAMELENGTH)
+ {
+ LEAVE( "ObjectBroker::getOIdOfStructType(): name exceeds max length:" << name );
+ throw r_Error(TYPENAMEISTOOLONG);
+ }
+ (void) strncpy( structname, (char*) name, (size_t) sizeof(structname) );
+
+ TALK( "EXEC SQL SELECT BaseTypeId INTO :structoid FROM RAS_BASETYPENAMES WHERE BaseTypeName = " << structname );
+ EXEC SQL SELECT BaseTypeId
+ INTO :structoid
+ FROM RAS_BASETYPENAMES
+ WHERE BaseTypeName = :structname;
+
+ if (SQLCODE != SQLOK)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db");
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db");
+ LEAVE( "ObjectBroker::getOIdOfStructType(): object not in db" );
+ throw r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ else
+ {
+ check("ObjectBroker::getOIdOfStructType()\0");
+ LEAVE( "ObjectBroker::getOIdOfStructType(): db access error: " << SQLCODE );
+ generateException();
+ }
+ }
+ else
+ {
+ retval = OId(structoid, OId::STRUCTTYPEOID);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is in db with " << retval);
+ }
+
+ LEAVE( "ObjectBroker::getOIdOfStructType, retval=" << retval );
+ return retval;
+}
+
+OId
+ObjectBroker::getOIdOfMDDSet(const char* name) throw (r_Error)
+{
+ ENTER( "ObjectBroker::getOIdOfMDDSet, name=" << name );
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ char collname[STRING_MAXLEN];
+ long colloid;
+ EXEC SQL END DECLARE SECTION;
+
+ OId retval;
+ int len = strlen(name);
+ if (len > DBNamedObject::MAXNAMELENGTH)
+ {
+ LEAVE( "ObjectBroker::getOIdOfMDDSet(): name exceeds max length:" << name );
+ throw r_Error(TYPENAMEISTOOLONG);
+ }
+ (void) strncpy( collname, (char*) name, (size_t) sizeof(collname) );
+
+ TALK( "EXEC SQL SELECT MDDCollId INTO :colloid FROM RAS_MDDCOLLNAMES WHERE MDDCollName = " << collname );
+ EXEC SQL SELECT MDDCollId
+ INTO :colloid
+ FROM RAS_MDDCOLLNAMES
+ WHERE MDDCollName = :collname;
+
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE == SQLNODATAFOUND)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db");
+ LEAVE( "ObjectBroker::getOIdOfMDDSet(): object not in db" );
+ throw r_Error(r_Error::r_Error_ObjectUnknown);
+ }
+ else
+ {
+ check("ObjectBroker::getOIdOfMDDSet()\0");
+ LEAVE( "ObjectBroker::getOIdOfMDDSet(): db access error: " << SQLCODE );
+ generateException();
+ }
+ }
+ else
+ {
+ retval = OId(colloid, OId::MDDCOLLOID);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is in db with " << retval);
+ }
+
+ LEAVE( "ObjectBroker::getOIdOfMDDSet, retval=" << retval );
+ return retval;
+}
+
+OIdSet*
+ObjectBroker::getAllSetTypes() throw (r_Error)
+{
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllSetTypes()");
+ ENTER( "ObjectBroker::getAllSetTypes" );
+
+ OIdSet* retval = new OIdSet();
+ DBObjectPMap& theMap = ObjectBroker::getMap(OId::SETTYPEOID);
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first);
+ retval->insert((*i).first);
+ }
+ OId id;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long settoid1;
+ EXEC SQL END DECLARE SECTION;
+
+ TALK( "EXEC SQL DECLARE setcursor CURSOR FOR SELECT SetTypeId FROM RAS_SETTYPES ORDER BY SetTypeId" );
+ EXEC SQL DECLARE setcursor CURSOR FOR
+ SELECT SetTypeId
+ FROM RAS_SETTYPES
+ ORDER BY SetTypeId;
+
+ TALK( "EXEC SQL OPEN setcursor" );
+ EXEC SQL OPEN setcursor;
+
+ do
+ {
+ TALK( "EXEC SQL FETCH setcursor INTO :settoid1" );
+ EXEC SQL FETCH setcursor INTO :settoid1;
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE != SQLNODATAFOUND)
+ {
+ check("ObjectBroker::getAllSetTypes\0");
+ TALK( "EXEC SQL CLOSE setcursor" );
+ EXEC SQL CLOSE setcursor;
+ delete retval;
+ retval = 0;
+ LEAVE( "ObjectBroker::getAllSetTypes(): db access error: " << SQLCODE );
+ generateException();
+ }
+ break;
+ }
+ id = OId(settoid1, OId::SETTYPEOID);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType());
+ TALK( "got object " << id << " " << id.getType());
+ retval->insert(id);
+ } while (1);
+
+ TALK( "EXEC SQL CLOSE setcursor" );
+ EXEC SQL CLOSE setcursor;
+
+ LEAVE( "ObjectBroker::getAllSetTypes, SQLCODE=" << SQLCODE );
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllSetTypes() ");
+ return retval;
+}
+
+OIdSet*
+ObjectBroker::getAllMDDTypes() throw (r_Error)
+{
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDTypes()");
+ ENTER( "ObjectBroker::getAllMDDTypes" );
+
+ OIdSet* retval = new OIdSet();
+ DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDTYPEOID);
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first);
+ retval->insert((*i).first);
+ }
+ OId id;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long mddtoid1;
+ EXEC SQL END DECLARE SECTION;
+
+ TALK( "EXEC SQL DECLARE mddtcursor CURSOR FOR SELECT MDDTypeOId FROM RAS_MDDTYPES ORDER BY MDDTypeOId" );
+ EXEC SQL DECLARE mddtcursor CURSOR FOR
+ SELECT MDDTypeOId
+ FROM RAS_MDDTYPES
+ ORDER BY MDDTypeOId;
+
+ TALK( "EXEC SQL OPEN mddtcursor" );
+ EXEC SQL OPEN mddtcursor;
+
+ do
+ {
+ TALK( "EXEC SQL FETCH mddtcursor INTO :mddtoid1" ) ;
+ EXEC SQL FETCH mddtcursor INTO :mddtoid1;
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE != SQLNODATAFOUND)
+ {
+ check("ObjectBroker::getAllMDDTypes()\0");
+ EXEC SQL CLOSE mddtcursor;
+ delete retval;
+ retval = 0;
+ LEAVE( "ObjectBroker::getAllMDDTypes(): db access error: " << SQLCODE );
+ generateException();
+ }
+ break;
+ }
+ id = OId(mddtoid1, OId::MDDTYPEOID);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType());
+ TALK( "got object " << id << " " << id.getType() );
+ retval->insert(id);
+ } while (1);
+
+ TALK( "EXEC SQL CLOSE mddtcursor" );
+ EXEC SQL CLOSE mddtcursor;
+
+ LEAVE( "ObjectBroker::getAllMDDTypes, retval=" << retval );
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDTypes() ");
+ return retval;
+}
+
+OIdSet*
+ObjectBroker::getAllMDDBaseTypes() throw (r_Error)
+{
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDBaseTypes()");
+ ENTER( "ObjectBroker::getAllMDDBaseTypes" );
+
+ OIdSet* retval = new OIdSet();
+ DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDBASETYPEOID);
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first);
+ retval->insert((*i).first);
+ }
+ OId id;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long mddboid1;
+ EXEC SQL END DECLARE SECTION;
+
+ TALK( "EXEC SQL DECLARE mddbcursor CURSOR FOR SELECT MDDBaseTypeOId FROM RAS_MDDBASETYPES ORDER BY MDDBaseTypeOId" );
+ EXEC SQL DECLARE mddbcursor CURSOR FOR
+ SELECT MDDBaseTypeOId
+ FROM RAS_MDDBASETYPES
+ ORDER BY MDDBaseTypeOId;
+
+ TALK( "EXEC SQL OPEN mddbcursor" );
+ EXEC SQL OPEN mddbcursor;
+
+ do
+ {
+ TALK( "EXEC SQL FETCH mddbcursor INTO :mddboid1" );
+ EXEC SQL FETCH mddbcursor INTO :mddboid1;
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE != SQLNODATAFOUND)
+ {
+ check("ObjectBroker::getAllMDDBaseTypes()\0");
+ EXEC SQL CLOSE mddbcursor;
+ delete retval;
+ retval = 0;
+ LEAVE( "ObjectBroker::getAllMDDBaseTypes(): db access error: " << SQLCODE );
+ generateException();
+ }
+ break;
+ }
+ id = OId(mddboid1, OId::MDDBASETYPEOID);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType());
+ TALK( "got object " << id << " " << id.getType() );
+ retval->insert(id);
+ } while (1);
+
+ TALK( "EXEC SQL CLOSE mddbcursor" );
+ EXEC SQL CLOSE mddbcursor;
+
+ LEAVE( "ObjectBroker::getAllMDDBaseTypes, retval=" << retval );
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDBaseTypes() ");
+ return retval;
+}
+
+OIdSet*
+ObjectBroker::getAllMDDDimensionTypes() throw (r_Error)
+{
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDDimensionTypes()");
+ ENTER( "ObjectBroker::getAllMDDDimensionTypes" );
+
+ OIdSet* retval = new OIdSet();
+ DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDDIMTYPEOID);
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first);
+ retval->insert((*i).first);
+ }
+ OId id;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long mdddioid1;
+ EXEC SQL END DECLARE SECTION;
+
+ TALK( "EXEC SQL DECLARE mdddicursor CURSOR FOR SELECT MDDDimTypeOId FROM RAS_MDDDIMTYPES ORDER BY MDDDimTypeOId" );
+ EXEC SQL DECLARE mdddicursor CURSOR FOR
+ SELECT MDDDimTypeOId
+ FROM RAS_MDDDIMTYPES
+ ORDER BY MDDDimTypeOId;
+
+ TALK( "EXEC SQL OPEN mdddicursor" );
+ EXEC SQL OPEN mdddicursor;
+
+ do
+ {
+ TALK( "EXEC SQL FETCH mdddicursor INTO :mdddioid1" );
+ EXEC SQL FETCH mdddicursor INTO :mdddioid1;
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE != SQLNODATAFOUND)
+ {
+ check("ObjectBroker::getAllMDDDimensionTypes()\0");
+ EXEC SQL CLOSE mdddicursor;
+ delete retval;
+ retval = 0;
+ LEAVE( "ObjectBroker::getAllMDDDimensionTypes(): db access error: " << SQLCODE );
+ generateException();
+ }
+ break;
+ }
+ id = OId(mdddioid1, OId::MDDDIMTYPEOID);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType());
+ TALK( "got object " << id << " " << id.getType() );
+ retval->insert(id);
+ } while (1);
+
+ TALK( "EXEC SQL CLOSE mdddicursor" );
+ EXEC SQL CLOSE mdddicursor;
+
+ LEAVE( "ObjectBroker::getAllMDDDimensionTypes, retval=" << retval );
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDDimensionTypes() ");
+ return retval;
+}
+
+OIdSet*
+ObjectBroker::getAllMDDDomainTypes() throw (r_Error)
+{
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDDomainTypes()");
+ ENTER( "ObjectBroker::getAllMDDDomainTypes" );
+
+ OIdSet* retval = new OIdSet();
+ DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDDOMTYPEOID);
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first);
+ retval->insert((*i).first);
+ }
+ OId id;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long mdddooid1;
+ EXEC SQL END DECLARE SECTION;
+
+ TALK( "EXEC SQL DECLARE mdddocursor CURSOR FOR SELECT MDDDomTypeOId FROM RAS_MDDDOMTYPES ORDER BY MDDDomTypeOId" );
+ EXEC SQL DECLARE mdddocursor CURSOR FOR
+ SELECT MDDDomTypeOId
+ FROM RAS_MDDDOMTYPES
+ ORDER BY MDDDomTypeOId;
+
+ TALK( "EXEC SQL OPEN mdddocursor" );
+ EXEC SQL OPEN mdddocursor;
+
+ do
+ {
+ TALK( "EXEC SQL FETCH mdddocursor INTO :mdddooid1" );
+ EXEC SQL FETCH mdddocursor INTO :mdddooid1;
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE != SQLNODATAFOUND)
+ {
+ check("ObjectBroker::getAllMDDDomainTypes()\0");
+ EXEC SQL CLOSE mdddocursor;
+ delete retval;
+ retval = 0;
+ LEAVE( "ObjectBroker::getAllMDDDomainTypes(): db access error: " << SQLCODE );
+ generateException();
+ }
+ break;
+ }
+ id = OId(mdddooid1, OId::MDDDOMTYPEOID);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType());
+ TALK( "got object " << id << " " << id.getType() );
+ retval->insert(id);
+ } while (1);
+ TALK( "EXEC SQL CLOSE mdddocursor" );
+ EXEC SQL CLOSE mdddocursor;
+
+ LEAVE( "ObjectBroker::getAllMDDDomainTypes" );
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDDomainTypes() ");
+ return retval;
+}
+
+OIdSet*
+ObjectBroker::getAllStructTypes() throw (r_Error)
+{
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllStructTypes()");
+ ENTER( "ObjectBroker::getAllStructTypes" );
+
+ OIdSet* retval = new OIdSet();
+ DBObjectPMap& theMap = ObjectBroker::getMap(OId::STRUCTTYPEOID);
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first);
+ retval->insert((*i).first);
+ }
+ OId id;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long structoid1;
+ short maxbuiltin;
+ EXEC SQL END DECLARE SECTION;
+
+ maxbuiltin = TypeFactory::MaxBuiltInId;
+
+ TALK( "EXEC SQL DECLARE structcursor CURSOR FOR SELECT BaseTypeId FROM RAS_BASETYPENAMES ORDER BY BaseTypeId" );
+ EXEC SQL DECLARE structcursor CURSOR FOR
+ SELECT BaseTypeId
+ FROM RAS_BASETYPENAMES
+ ORDER BY BaseTypeId;
+
+ TALK( "EXEC SQL OPEN structcursor" );
+ EXEC SQL OPEN structcursor;
+
+ do
+ {
+ TALK( "EXEC SQL FETCH structcursor INTO :structoid1" );
+ EXEC SQL FETCH structcursor INTO :structoid1;
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE != SQLNODATAFOUND)
+ {
+ check("ObjectBroker::getAllStructTypes()\0");
+ EXEC SQL CLOSE structcursor;
+ delete retval;
+ retval = 0;
+ LEAVE( "ObjectBroker::getAllStructTypes(): db access error: " << SQLCODE );
+ generateException();
+ }
+ break;
+ }
+ id = OId(structoid1, OId::STRUCTTYPEOID);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType());
+ TALK( "got object " << id << " " << id.getType() );
+ retval->insert(id);
+ } while (1);
+ TALK( "EXEC SQL CLOSE structcursor" );
+ EXEC SQL CLOSE structcursor;
+
+ LEAVE( "ObjectBroker::getAllStructTypes, retval=" << retval );
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllStructTypes() ");
+ return retval;
+}
+
+OIdSet*
+ObjectBroker::getAllMDDObjects() throw (r_Error)
+{
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDObjects()");
+ ENTER( "ObjectBroker::getAllMDDObjects" );
+
+ OIdSet* retval = new OIdSet();
+ DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDOID);
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first);
+ retval->insert((*i).first);
+ }
+ OId id;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long mddobjoid1;
+ EXEC SQL END DECLARE SECTION;
+
+ TALK(" EXEC SQL DECLARE mddobjcursor CURSOR FOR SELECT MDDId FROM RAS_MDDOBJECTS ORDER BY MDDId" );
+ EXEC SQL DECLARE mddobjcursor CURSOR FOR
+ SELECT MDDId
+ FROM RAS_MDDOBJECTS
+ ORDER BY MDDId;
+
+ TALK( "EXEC SQL OPEN mddobjcursor" );
+ EXEC SQL OPEN mddobjcursor;
+
+ do
+ {
+ TALK( "EXEC SQL FETCH mddobjcursor INTO :mddobjoid1" );
+ EXEC SQL FETCH mddobjcursor INTO :mddobjoid1;
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE != SQLNODATAFOUND)
+ {
+ check("ObjectBroker::getAllMDDObjects()\0");
+ EXEC SQL CLOSE mddobjcursor;
+ delete retval;
+ retval = 0;
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "Database Failed");
+ LEAVE( "ObjectBroker::getAllMDDObjects(): db access error: " << SQLCODE );
+ generateException();
+ }
+ break;
+ }
+ id = OId(mddobjoid1, OId::MDDOID);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType());
+ TALK( "got object " << id << " " << id.getType() );
+ retval->insert(id);
+ } while (1);
+ TALK( "EXEC SQL CLOSE mddobjcursor" );
+ EXEC SQL CLOSE mddobjcursor;
+
+ LEAVE( "ObjectBroker::getAllMDDObjects, retval=" << retval );
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDObjects() ");
+ return retval;
+}
+
+OIdSet*
+ObjectBroker::getAllMDDSets() throw (r_Error)
+{
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDSets()");
+ ENTER( "ObjectBroker::getAllMDDSets" );
+
+ OIdSet* retval = new OIdSet();
+ DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDCOLLOID);
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first);
+ retval->insert((*i).first);
+ }
+ OId id;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long colloid1;
+ EXEC SQL END DECLARE SECTION;
+
+ TALK( "EXEC SQL DECLARE collcursor CURSOR FOR SELECT MDDCollId FROM RAS_MDDCOLLNAMES ORDER BY MDDCollId" );
+ EXEC SQL DECLARE collcursor CURSOR FOR
+ SELECT MDDCollId
+ FROM RAS_MDDCOLLNAMES
+ ORDER BY MDDCollId;
+
+ TALK(" EXEC SQL OPEN collcursor" );
+ EXEC SQL OPEN collcursor;
+
+ do
+ {
+ TALK( "EXEC SQL FETCH collcursor INTO :colloid1" );
+ EXEC SQL FETCH collcursor INTO :colloid1;
+ if (SQLCODE != SQLOK)
+ {
+ if (SQLCODE != SQLNODATAFOUND)
+ {
+ check("ObjectBroker::getAllMDDSets()\0");
+ EXEC SQL CLOSE collcursor;
+ delete retval;
+ retval = 0;
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "Database Failed");
+ LEAVE( "ObjectBroker::getAllMDDSets(): db access error: " << SQLCODE );
+ generateException();
+ }
+ break;
+ }
+ id = OId(colloid1, OId::MDDCOLLOID);
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType());
+ TALK( "got object " << id << " " << id.getType() );
+ retval->insert(id);
+ } while (1);
+ TALK( "EXEC SQL CLOSE collcursor" );
+ EXEC SQL CLOSE collcursor;
+
+ LEAVE( "ObjectBroker::getAllMDDSets, retval=" << retval );
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDSets() ");
+ return retval;
+}
+
diff --git a/reladminif/objectbrokercommon.cc b/reladminif/objectbrokercommon.cc
new file mode 100644
index 0000000..648f3c6
--- /dev/null
+++ b/reladminif/objectbrokercommon.cc
@@ -0,0 +1,1144 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include <map>
+#include <set>
+#include <cstring>
+#include <cstdlib>
+
+#include "raslib/rmdebug.hh"
+#include "raslib/minterval.hh"
+#include "objectbroker.hh"
+#include "dbnamedobject.hh"
+#include "relstorageif/dbstoragelayout.hh"
+#include "adminif.hh"
+#include "relcatalogif/alltypes.hh"
+#include "relindexif/hierindex.hh"
+#include "relblobif/blobtile.hh"
+#include "relcatalogif/dbminterval.hh"
+#include "relblobif/inlinetile.hh"
+#include "relindexif/dbtcindex.hh"
+#include "sqlerror.hh"
+#include "relindexif/indexid.hh"
+#include "relmddif/mddid.hh"
+#include "dbref.hh"
+#include "relmddif/dbmddobj.hh"
+#include "catalogmgr/typefactory.hh"
+#include "relmddif/dbmddset.hh"
+#include "relindexif/dbrcindexds.hh"
+#include "debug.hh"
+
+#ifdef LINUX
+template class DBRef<BLOBTile>;
+template class DBRef<DBTile>;
+template class DBRef<InlineTile>;
+#endif
+
+using namespace std;
+
+LongType*
+ObjectBroker::theLong = 0;
+
+ShortType*
+ObjectBroker::theShort = 0;
+
+OctetType*
+ObjectBroker::theOctet = 0;
+
+ULongType*
+ObjectBroker::theULong = 0;
+
+UShortType*
+ObjectBroker::theUShort = 0;
+
+CharType*
+ObjectBroker::theChar = 0;
+
+BoolType*
+ObjectBroker::theBool = 0;
+
+DoubleType*
+ObjectBroker::theDouble = 0;
+
+FloatType*
+ObjectBroker::theFloat = 0;
+
+ComplexType1*
+ObjectBroker::theComplex1 = 0;
+
+ComplexType2*
+ObjectBroker::theComplex2 = 0;
+
+DBObjectPMap
+ObjectBroker::theAtomicTypes;
+
+DBObjectPMap
+ObjectBroker::theSetTypes;
+
+DBObjectPMap
+ObjectBroker::theMDDTypes;
+
+DBObjectPMap
+ObjectBroker::theMDDBaseTypes;
+
+DBObjectPMap
+ObjectBroker::theMDDDimensionTypes;
+
+DBObjectPMap
+ObjectBroker::theMDDDomainTypes;
+
+DBObjectPMap
+ObjectBroker::theStructTypes;
+
+DBObjectPMap
+ObjectBroker::theDBMintervals;
+
+DBObjectPMap
+ObjectBroker::theDBMDDObjs;
+
+DBObjectPMap
+ObjectBroker::theMDDSets;
+
+DBObjectPMap
+ObjectBroker::theDBStorages;
+
+DBObjectPMap
+ObjectBroker::theDBHierIndexs;
+
+DBObjectPMap
+ObjectBroker::theDBTCIndexs;
+
+DBObjectPMap
+ObjectBroker::theBLOBTiles;
+
+DBObjectPMap
+ObjectBroker::theInlineTiles;
+
+DBObjectPMap
+ObjectBroker::theRCIndexes;
+
+OIdMap
+ObjectBroker::theTileIndexMappings;
+
+bool
+ObjectBroker::freeMemory() throw (r_Error)
+ {
+ RMDBGONCE(0, RMDebug::module_adminif, "ObjectBroker", "memoryOverFlow()");
+ bool retval = false;
+ DBRef<BLOBTile>::setPointerCaching(false);
+ DBRef<DBTile>::setPointerCaching(false);
+ DBRef<InlineTile>::setPointerCaching(false);
+ if (!ObjectBroker::theBLOBTiles.empty())
+ {
+ int theLucky = ObjectBroker::theBLOBTiles.size() / 2;
+ DBObjectPMap::iterator it = ObjectBroker::theBLOBTiles.begin();
+ for (int i = 0; i < theLucky; i++, it++);
+ delete (*it).second;
+ retval = true;
+ }
+ return retval;
+ }
+
+void
+ObjectBroker::init()
+ {
+ RMDBGENTER(2, RMDebug::module_adminif, "ObjectBroker", "init()");
+ ObjectBroker::theLong = new LongType();
+
+ ObjectBroker::theShort = new ShortType();
+
+ ObjectBroker::theOctet = new OctetType();
+
+ ObjectBroker::theULong = new ULongType();
+
+ ObjectBroker::theUShort = new UShortType();
+
+ ObjectBroker::theChar = new CharType();
+
+ ObjectBroker::theBool = new BoolType();
+
+ ObjectBroker::theDouble = new DoubleType();
+
+ ObjectBroker::theFloat = new FloatType();
+
+ ObjectBroker::theComplex1 = new ComplexType1();
+
+ ObjectBroker::theComplex2 = new ComplexType2();
+
+ DBObject* atomicTypes[] = {theComplex2, theComplex1, theFloat, theDouble, theOctet, theShort, theLong, theUShort, theBool, theChar, theULong};
+ RMDBGIF(0, RMDebug::module_adminif, "ObjectBroker", \
+ if (sizeof(atomicTypes)/sizeof(DBObject*) != TypeFactory::MaxBuiltInId) \
+ { \
+ RMInit::logOut << "ObjectBroker::init() not all atomic types were added!" << endl; \
+ exit(1); \
+ } )
+ for (unsigned int a = 0; a < sizeof(atomicTypes)/sizeof(DBObject*); a++)
+ {
+ DBObjectPPair myPair(atomicTypes[a]->getOId(), atomicTypes[a]);
+ theAtomicTypes.insert(myPair);
+ }
+ RMDBGEXIT(2, RMDebug::module_adminif, "ObjectBroker", "init()");
+ }
+
+void
+ObjectBroker::deinit()
+ {
+ RMDBGONCE(2, RMDebug::module_adminif, "ObjectBroker", "deinit()");
+ if (ObjectBroker::theLong != 0)
+ {
+ delete ObjectBroker::theLong;
+ ObjectBroker::theLong = 0;
+ }
+
+ if (ObjectBroker::theShort != 0)
+ {
+ delete ObjectBroker::theShort;
+ ObjectBroker::theShort = 0;
+ }
+
+ if (ObjectBroker::theOctet != 0)
+ {
+ delete ObjectBroker::theOctet;
+ ObjectBroker::theOctet = 0;
+ }
+
+ if (ObjectBroker::theULong != 0)
+ {
+ delete ObjectBroker::theULong;
+ ObjectBroker::theULong = 0;
+ }
+
+ if (ObjectBroker::theUShort != 0)
+ {
+ delete ObjectBroker::theUShort;
+ ObjectBroker::theUShort = 0;
+ }
+
+ if (ObjectBroker::theChar != 0)
+ {
+ delete ObjectBroker::theChar;
+ ObjectBroker::theChar = 0;
+ }
+
+ if (ObjectBroker::theBool != 0)
+ {
+ delete ObjectBroker::theBool;
+ ObjectBroker::theBool = 0;
+ }
+
+ if (ObjectBroker::theDouble != 0)
+ {
+ delete ObjectBroker::theDouble;
+ ObjectBroker::theDouble = 0;
+ }
+
+ if (ObjectBroker::theFloat != 0)
+ {
+ delete ObjectBroker::theFloat;
+ ObjectBroker::theFloat = 0;
+ }
+
+ if (ObjectBroker::theComplex1 != 0)
+ {
+ delete ObjectBroker::theComplex1;
+ ObjectBroker::theComplex1 = 0;
+ }
+
+ if (ObjectBroker::theComplex2 != 0)
+ {
+ delete ObjectBroker::theComplex2;
+ ObjectBroker::theComplex2 = 0;
+ }
+
+ theAtomicTypes.clear();
+
+ theSetTypes.clear();
+
+ theMDDTypes.clear();
+
+ theMDDBaseTypes.clear();
+
+ theMDDDimensionTypes.clear();
+
+ theMDDDomainTypes.clear();
+
+ theStructTypes.clear();
+
+ theDBMintervals.clear();
+
+ theDBMDDObjs.clear();
+
+ theMDDSets.clear();
+
+ theDBStorages.clear();
+
+ theDBHierIndexs.clear();
+
+ theDBTCIndexs.clear();
+
+ theBLOBTiles.clear();
+
+ theInlineTiles.clear();
+
+ theRCIndexes.clear();
+
+ theTileIndexMappings.clear();
+ }
+
+DBObject*
+ObjectBroker::getObjectByOId(const OId& id) throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByOId(" << id << " " << id.getType() << ")");
+ DBObject* retval = 0;
+ if (id.getType() == OId::INVALID)
+ retval = 0;
+ else {
+ retval = ObjectBroker::isInMemory(id);
+ if (retval == 0)
+ {
+ switch (id.getType())
+ {
+ case OId::MDDOID:
+ retval = loadDBMDDObj(id);
+ break;
+ case OId::MDDCOLLOID:
+ retval = loadMDDSet(id);
+ break;
+ case OId::MDDTYPEOID:
+ retval = loadMDDType(id);
+ break;
+ case OId::MDDBASETYPEOID:
+ retval = loadMDDBaseType(id);
+ break;
+ case OId::MDDDIMTYPEOID:
+ retval = loadMDDDimensionType(id);
+ break;
+ case OId::MDDDOMTYPEOID:
+ retval = loadMDDDomainType(id);
+ break;
+ case OId::STRUCTTYPEOID:
+ retval = loadStructType(id);
+ break;
+ case OId::SETTYPEOID:
+ retval = loadSetType(id);
+ break;
+ case OId::BLOBOID:
+ retval = loadBLOBTile(id);
+ break;
+ case OId::DBMINTERVALOID:
+ retval = loadDBMinterval(id);
+ break;
+ case OId::STORAGEOID:
+ retval = loadDBStorage(id);
+ break;
+ case OId::MDDHIERIXOID:
+ retval = loadDBHierIndex(id);
+ break;
+ case OId::DBTCINDEXOID:
+ retval = loadDBTCIndex(id);
+ break;
+ case OId::INLINETILEOID:
+ retval = loadInlineTile(id);
+ break;
+ case OId::MDDRCIXOID:
+ retval = loadDBRCIndexDS(id);
+ break;
+ case OId::ATOMICTYPEOID:
+ RMInit::logOut << "Atomic type not found in memory." << endl;
+ default:
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByOId(" << id << " " << id.getType() << ")");
+ RMInit::logOut << "Retrival of Object Failed (Internal State 3)." << endl << "Please contact Customer Support." << endl;
+ throw r_Error(INVALID_OIDTYPE);
+ break;
+ }
+ }
+ }
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByOId(" << id << " " << id.getType() << ") " << retval);
+ return retval;
+ }
+
+
+DBObject*
+ObjectBroker::isInMemory(const OId& id) throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "isInMemory(" << id << " " << id.getType() << ")");
+ DBObject* retval = 0;
+ DBObjectPMap& theMap = ObjectBroker::getMap(id.getType());
+ DBObjectPMap::iterator i = theMap.find(id);
+ if (i != theMap.end())
+ {
+ retval = (*i).second;
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "found object with that id in map at " << (unsigned long)retval << " with id " << retval->getOId());
+ }
+ else {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "did not find object with that id in map");
+ }
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "isInMemory(" << id << " ( " << id.getCounter() << " "<< id.getType() << " ) ) " << retval);
+ return retval;
+ }
+
+void
+ObjectBroker::registerDBObject(DBObject* obj)
+ {
+ DBObjectPPair myPair(obj->getOId(), obj);
+ ObjectBroker::getMap(obj->getOId().getType()).insert(myPair);
+ }
+
+void
+ObjectBroker::deregisterDBObject(const OId& id)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "deregisterDBObject(" << id << ")");
+ if (id.getType() != OId::INVALID)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "size of map before\t: " << ObjectBroker::getMap(id.getType()).size());
+ DBObjectPMap& t = ObjectBroker::getMap(id.getType());
+ DBObjectPMap::iterator i = t.find(id);
+ if (i != t.end())
+ {
+ (*i).second = 0;
+ t.erase(i);
+ }
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "size of map after \t: " << ObjectBroker::getMap(id.getType()).size());
+ }
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "deregisterDBObject(" << id << ")");
+ }
+
+OIdSet*
+ObjectBroker::getAllObjects(OId::OIdType type)
+ {
+ OIdSet* retval = 0;
+ switch (type)
+ {
+ case OId::MDDCOLLOID:
+ retval = getAllMDDSets();
+ break;
+ case OId::MDDOID:
+ retval = getAllMDDObjects();
+ break;
+ case OId::MDDTYPEOID:
+ retval = getAllMDDTypes();
+ break;
+ case OId::MDDBASETYPEOID:
+ retval = getAllMDDBaseTypes();
+ break;
+ case OId::MDDDIMTYPEOID:
+ retval = getAllMDDDimensionTypes();
+ break;
+ case OId::MDDDOMTYPEOID:
+ retval = getAllMDDDomainTypes();
+ break;
+ case OId::STRUCTTYPEOID:
+ retval = getAllStructTypes();
+ break;
+ case OId::SETTYPEOID:
+ retval = getAllSetTypes();
+ break;
+ case OId::ATOMICTYPEOID:
+ retval = getAllAtomicTypes();
+ break;
+
+ default:
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "getAllObjects(" << type << ")");
+ RMInit::logOut << "Retrival of Object Failed (Internal State 4)." << endl << "Please contact Customer Support." << endl;
+ throw r_Error(INVALID_OIDTYPE);
+ break;
+ }
+ return retval;
+ }
+
+
+OId
+ObjectBroker::getOIdByName(OId::OIdType type, const char* name) throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getOIdByName(" << type << ", " << name << ")");
+ OId id;
+ switch (type)
+ {
+ case OId::MDDCOLLOID:
+ id = getOIdOfMDDSet(name);
+ break;
+ case OId::MDDTYPEOID:
+ id = getOIdOfMDDType(name);
+ break;
+ case OId::MDDBASETYPEOID:
+ id = getOIdOfMDDBaseType(name);
+ break;
+ case OId::MDDDIMTYPEOID:
+ id = getOIdOfMDDDimensionType(name);
+ break;
+ case OId::MDDDOMTYPEOID:
+ id = getOIdOfMDDDomainType(name);
+ break;
+ case OId::STRUCTTYPEOID:
+ id = getOIdOfStructType(name);
+ break;
+ case OId::SETTYPEOID:
+ id = getOIdOfSetType(name);
+ break;
+ case OId::ATOMICTYPEOID:
+ if(strcmp(name, ULongType::Name) == 0)
+ id = theULong->getOId();
+ else if(strcmp(name, BoolType::Name) == 0)
+ id = theBool->getOId();
+ else if(strcmp(name, CharType::Name) == 0)
+ id = theChar->getOId();
+ else if(strcmp(name, UShortType::Name) == 0)
+ id = theUShort->getOId();
+ else if(strcmp(name, LongType::Name) == 0)
+ id = theLong->getOId();
+ else if(strcmp(name, ShortType::Name) == 0)
+ id = theShort->getOId();
+ else if(strcmp(name, OctetType::Name) == 0)
+ id = theOctet->getOId();
+ else if(strcmp(name, DoubleType::Name) == 0)
+ id = theDouble->getOId();
+ else if(strcmp(name, FloatType::Name) == 0)
+ id = theFloat->getOId();
+ else if(strcmp(name, ComplexType1::Name) == 0)
+ id = theComplex1->getOId();
+ else if(strcmp(name, ComplexType2::Name) == 0)
+ id = theComplex2->getOId();
+ break;
+
+ default:
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getOIdByName(" << type << ", " << name << ")");
+ RMInit::logOut << "Retrival of Object Failed (Internal State 5)." << endl << "Please contact Customer Support." << endl;
+ throw r_Error(INVALID_OIDTYPE);
+ break;
+ }
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getOIdByName(" << type << ", " << name << ") " << id << " " << id.getType());
+ return id;
+ }
+
+
+DBObject*
+ObjectBroker::getObjectByName(OId::OIdType type, const char* name) throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByName(" << type << ", " << name << ")");
+ DBObject* retval = 0;
+ DBObjectPMap* theMap = 0;
+ switch (type)
+ {
+ case OId::MDDCOLLOID:
+ theMap = &theMDDSets;
+ break;
+ case OId::MDDTYPEOID:
+ theMap = &theMDDTypes;
+ break;
+ case OId::MDDBASETYPEOID:
+ theMap = &theMDDBaseTypes;
+ break;
+ case OId::MDDDIMTYPEOID:
+ theMap = &theMDDDimensionTypes;
+ break;
+ case OId::MDDDOMTYPEOID:
+ theMap = &theMDDDomainTypes;
+ break;
+ case OId::STRUCTTYPEOID:
+ theMap = &theStructTypes;
+ break;
+ case OId::SETTYPEOID:
+ theMap = &theSetTypes;
+ break;
+ case OId::ATOMICTYPEOID:
+ theMap = &theAtomicTypes;
+ break;
+ default:
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByName(" << type << ", " << name << ")");
+ RMInit::logOut << "Retrival of Object Failed (Internal State 6)." << endl << "Please contact Customer Support." << endl;
+ throw r_Error(INVALID_OIDTYPE);
+ break;
+ }
+
+ //check if there is an object with that name already in memory
+ for (DBObjectPMap::iterator iter = theMap->begin(); iter != theMap->end(); iter++)
+ {
+ if (strcmp(((DBNamedObject*)(*iter).second)->getName(), name) == 0)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", name << " equals " << ((DBNamedObject*)(*iter).second)->getName());
+ retval = (*iter).second;
+ break;
+ }
+ else {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", name << " equals NOT " << ((DBNamedObject*)(*iter).second)->getName());
+ }
+ }
+
+ //no - no matching object. try loading from db
+ if (!retval)
+ {
+ retval = ObjectBroker::getObjectByOId(ObjectBroker::getOIdByName(type,name));
+ }
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByName(" << type << ", " << name << ") " << retval);
+ return retval;
+ }
+
+void
+ObjectBroker::clearMap(DBObjectPMap& theMap) throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "clearMap()");
+ DBObjectPVector test;
+ test.reserve(theMap.size());
+ if (AdminIf::isAborted() || AdminIf::isReadOnlyTA())
+ {
+ //only delete objects that are modifed/not cached
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++ )
+ {
+ if ((*i).second->isModified() || !(*i).second->isCached())
+ {
+ RMDBGMIDDLE(117, RMDebug::module_adminif, "ObjectBroker", "preparing to delete " << (*i).second->getOId() << " " << (*i).second->getOId().getType());
+ test.push_back((*i).second);
+ //(*i).second = 0; not good because of circular dependencies in the destructors
+ }
+ else {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "leaving alone " << (*i).second->getOId() << " " << (*i).second->getOId().getType());
+ }
+ }
+ }
+ else {
+ //only delete objects that are not cached. validate the cached objects.
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "theMap are validated");
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++ )
+ {
+ if ((*i).second->isCached())
+ {
+ RMDBGMIDDLE(117, RMDebug::module_adminif, "ObjectBroker", "leaving alone because of cache " << (*i).second->getOId() << " " << (*i).second->getOId().getType());
+ (*i).second->validate();
+ }
+ else {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "preparing to delete " << (*i).second->getOId() << " " << (*i).second->getOId().getType());
+ test.push_back((*i).second);
+ //(*i).second = 0; not good because of circular dependencies in the destructors
+ }
+ }
+ }
+ for (DBObjectPVector::iterator i2 = test.begin(); i2 != test.end(); i2++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "deleting " << (*i2)->getOId() << " " << (*i2)->getOId().getType() << " size " << (*i2)->getMemorySize());
+ delete (*i2);
+ }
+ test.clear();
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "clearMap() ");
+ }
+
+void
+ObjectBroker::completelyClearMap(DBObjectPMap& theMap) throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "completelyClearMap()");
+ DBObjectPVector test;
+ test.reserve(theMap.size());
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++ )
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "preparing to delete " << (*i).second->getOId() << " " << (*i).second->getOId().getType());
+ (*i).second->validate();
+ test.push_back((*i).second);
+ //(*i).second = 0; not good because of circular dependencies in the destructors
+ }
+ for (DBObjectPVector::iterator i2 = test.begin(); i2 != test.end(); i2++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "deleting " << (*i2)->getOId() << " " << (*i2)->getOId().getType());
+ delete (*i2);
+ }
+ test.clear();
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "completelyClearMap() ");
+ }
+
+void
+ObjectBroker::clearBroker() throw (r_Error)
+ {
+ //do not ever clear the ATOMICTYPEOID map! those are on the stack, not heap!
+// ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::UDFOID));
+// ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::UDFPACKAGEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDCOLLOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDHIERIXOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDRCIXOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::DBTCINDEXOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::INLINETILEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::STORAGEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::SETTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDDOMTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDDIMTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDBASETYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::STRUCTTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::DBMINTERVALOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::BLOBOID));
+ theTileIndexMappings.clear();
+ }
+
+void
+ObjectBroker::clearCache() throw (r_Error)
+ {
+ //do not ever clear the ATOMICTYPEOID map! those are on the stack, not heap!
+// ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::UDFOID));
+// ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::UDFPACKAGEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDCOLLOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDHIERIXOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDRCIXOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::DBTCINDEXOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::INLINETILEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::STORAGEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::SETTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDDOMTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDDIMTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDBASETYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::STRUCTTYPEOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::DBMINTERVALOID));
+ ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::BLOBOID));
+ theTileIndexMappings.clear();
+ }
+
+DBObjectPMap&
+ObjectBroker::getMap(OId::OIdType type) throw (r_Error)
+ {
+ DBObjectPMap* theMap = 0;
+ switch (type)
+ {
+ case OId::MDDOID:
+ theMap = &theDBMDDObjs;
+ break;
+ case OId::MDDCOLLOID:
+ theMap = &theMDDSets;
+ break;
+ case OId::MDDTYPEOID:
+ theMap = &theMDDTypes;
+ break;
+ case OId::MDDBASETYPEOID:
+ theMap = &theMDDBaseTypes;
+ break;
+ case OId::MDDDIMTYPEOID:
+ theMap = &theMDDDimensionTypes;
+ break;
+ case OId::MDDDOMTYPEOID:
+ theMap = &theMDDDomainTypes;
+ break;
+ case OId::STRUCTTYPEOID:
+ theMap = &theStructTypes;
+ break;
+ case OId::SETTYPEOID:
+ theMap = &theSetTypes;
+ break;
+ case OId::BLOBOID:
+ theMap = &theBLOBTiles;
+ break;
+ case OId::INLINETILEOID:
+ theMap = &theInlineTiles;
+ break;
+ case OId::DBMINTERVALOID:
+ theMap = &theDBMintervals;
+ break;
+ case OId::STORAGEOID:
+ theMap = &theDBStorages;
+ break;
+ case OId::DBTCINDEXOID:
+ theMap = &theDBTCIndexs;
+ break;
+ case OId::MDDHIERIXOID:
+ theMap = &theDBHierIndexs;
+ break;
+ case OId::ATOMICTYPEOID:
+ theMap = &theAtomicTypes;
+ break;
+ case OId::MDDRCIXOID:
+ theMap = &theRCIndexes;
+ break;
+ default:
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "getMap(" << type << ")");
+ RMInit::logOut << "Retrival of Object Failed (Internal State 7)." << endl << "Please contact Customer Support." << endl;
+ throw r_Error(INVALID_OIDTYPE);
+ break;
+ }
+ return *theMap;
+ }
+
+DBObject*
+ObjectBroker::loadDBStorage(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new DBStorageLayout(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(), retval);
+ theDBStorages.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+DBObject*
+ObjectBroker::loadSetType(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new SetType(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(), retval);
+ theSetTypes.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+DBObject*
+ObjectBroker::loadMDDType(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new MDDType(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(),retval);
+ theMDDTypes.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+
+DBObject*
+ObjectBroker::loadMDDBaseType(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new MDDBaseType(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(), retval);
+ theMDDBaseTypes.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+
+DBObject*
+ObjectBroker::loadMDDDimensionType(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new MDDDimensionType(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(), retval);
+ theMDDDimensionTypes.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+
+DBObject*
+ObjectBroker::loadMDDDomainType(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new MDDDomainType(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(), retval);
+ theMDDDomainTypes.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+
+DBObject*
+ObjectBroker::loadStructType(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new StructType(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(), retval);
+ theStructTypes.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+
+DBObject*
+ObjectBroker::loadDBMinterval(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new DBMinterval(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair( retval->getOId(), retval);
+ theDBMintervals.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+
+DBObject*
+ObjectBroker::loadDBMDDObj(const OId& id) throw (r_Error)
+{
+ ENTER( "ObjectBroker::loadDBMDDObj, id=" << id );
+
+ DBObject* retval = 0;
+ try
+ {
+ retval = new DBMDDObj(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(), retval);
+ TALK( "found object, inserting " << retval->getOId() << " into result list" );
+ theDBMDDObjs.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ LEAVE( "ObjectBroker::loadDBMDDObj, object not found in db, throwing error " << error.what() );
+ throw error;
+ }
+
+ LEAVE( "ObjectBroker::loadDBMDDObj, retval=" << retval );
+ return retval;
+}
+
+
+DBObject*
+ObjectBroker::loadMDDSet(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new DBMDDSet(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(),retval);
+ theMDDSets.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+DBObject*
+ObjectBroker::loadDBTCIndex(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new DBTCIndex(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(), retval);
+ retval->setCached(true);
+ theDBTCIndexs.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+DBObject*
+ObjectBroker::loadDBHierIndex(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new DBHierIndex(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair(retval->getOId(),retval);
+ retval->setCached(true);
+ theDBHierIndexs.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+
+DBObject*
+ObjectBroker::loadBLOBTile(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new BLOBTile(id);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair( retval->getOId(),retval);
+ theBLOBTiles.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ if(retval)
+ {
+ delete retval;
+ retval=0;
+ }
+ throw error;
+ }
+ return retval;
+ }
+
+DBObject*
+ObjectBroker::loadDBRCIndexDS(const OId& id) throw (r_Error)
+ {
+ DBObject* retval = 0;
+ try {
+ retval = new DBRCIndexDS(id);
+ retval->setCached(true);
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db");
+ DBObjectPPair myPair( retval->getOId(),retval);
+ theRCIndexes.insert(myPair);
+ }
+ catch (r_Error& error)
+ {
+ RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db");
+ delete retval;
+ throw error;
+ }
+ return retval;
+ }
+
+void
+ObjectBroker::registerTileIndexMapping(const OId& tileoid, const OId& indexoid)
+ {
+ OIdPair p(tileoid, indexoid);
+ theTileIndexMappings.insert(p);
+ }
+
+void
+ObjectBroker::deregisterTileIndexMapping(const OId& tileoid, const OId& indexoid)
+ {
+ OIdPair p(tileoid, indexoid);
+ OIdMap::iterator i = theTileIndexMappings.find(tileoid);
+ if (i != theTileIndexMappings.end())
+ theTileIndexMappings.erase(i);
+ else
+ RMDBGONCE(0, RMDebug::module_adminif, "ObjectBroker", "deregisterIndexTileMapping(" << indexoid << ", " << tileoid << ") NOT FOUND");
+ }
+
+OIdSet*
+ObjectBroker::getAllAtomicTypes() throw (r_Error)
+ {
+ RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllAtomicTypes()");
+ OIdSet* retval = new OIdSet();
+ DBObjectPMap& theMap = ObjectBroker::getMap(OId::ATOMICTYPEOID);
+ for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++)
+ {
+ RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first);
+ retval->insert((*i).first);
+ }
+ RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllAtomicTypes() ");
+ return retval;
+ }
+
diff --git a/reladminif/oidif.hh b/reladminif/oidif.hh
new file mode 100644
index 0000000..33ce760
--- /dev/null
+++ b/reladminif/oidif.hh
@@ -0,0 +1,307 @@
+#ifndef _OIDIF_HH_
+#define _OIDIF_HH_
+
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/************************************************************************
+ *
+ *
+ * PURPOSE:
+ *
+ *
+ * COMMENTS:
+ *
+ ***********************************************************************/
+
+ //@ManMemo: Module: {\bf adminif}.
+
+class OId;
+
+#include <iostream>
+
+#include "raslib/error.hh"
+
+#ifdef RMANBENCHMARK
+#include "raslib/rmdebug.hh"
+#endif
+
+//@ManMemo: Module: {\bf reladminif}.
+/*@Doc:
+the oid is a structure containing a counter and a type field. based on the type
+it is possible to determine the type of the object the oid is refering to.
+the counter is used to pinpoint the exact instance of the object.
+
+currently there are 19 different persistent classes.
+
+the counter and type information is encoded into a double:
+ID_MULTIPLIER * counter + type;
+the counters for each oid type are stored in the database. their exact value is read
+when the transaction starts. the values are updated in the database at the end of a
+transaction. this can be a problem with multiple concurrent open read/write
+transactions.
+*/
+
+
+class OId
+ {
+ public:
+ enum OIdType { INVALID = 0,
+ MDDOID,
+ MDDCOLLOID,
+ MDDTYPEOID,
+ MDDBASETYPEOID,
+ MDDDIMTYPEOID,
+ MDDDOMTYPEOID,
+ STRUCTTYPEOID,
+ SETTYPEOID,
+ BLOBOID,
+ DBMINTERVALOID,
+ STORAGEOID,
+ MDDHIERIXOID,
+ DBTCINDEXOID,
+ INLINETILEOID,
+ INNEROID,
+ ATOMICTYPEOID,
+ UDFOID,
+ UDFPACKAGEOID,
+ MDDRCIXOID};
+ /*@Doc:
+ every persistent class needs a unique OIdType.
+ There is as always an exception: INNEROID is only used by DBTCIndex internally
+ */
+
+ typedef int OIdCounter;
+ /*@Doc:
+ every persistent object needs a unique OIdCounter within all persistent objects
+ with the same OIdType.
+ */
+
+ typedef double OIdPrimitive;
+ /*@Doc:
+ an oid can be converted from and to a primitive of this type.
+ */
+
+ static OIdPrimitive ID_MULTIPLIER;
+ /*@Doc:
+ is used to calculate the actual id and type from a given double
+ */
+
+ static void allocateOId(OId& id, OIdType type, OIdCounter howMany = 1);
+ /*@Doc:
+ allocates a OId for an object of the specified type or a whole bunch of them.
+ */
+
+ static void deinitialize();
+ /*@Doc:
+ writes the current state of the oid counters back
+ into the database.
+ */
+
+ static void initialize();
+ /*@Doc:
+ reads the state of the oid counters from the database.
+ */
+
+ OId::OIdType getType() const;
+ /*@Doc:
+ Returns type of the object with this OId.
+ */
+
+ OId(const OId& oldOId);
+ /*@Doc:
+ Copy constructor
+ */
+
+ OId(OIdCounter newId, OIdType type);
+ /*@Doc:
+ New OId with counter = newId, oidtype = type
+ */
+
+ OId(OIdPrimitive oidd);
+ /*@Doc:
+ generate a oid from a double.
+ */
+
+ OId();
+ /*@Doc:
+ invalid oid
+ */
+
+ OIdCounter getCounter() const;
+ /*@Doc:
+ returns the counter part of the oid.
+ */
+
+ void print_status(std::ostream& s = std::cout) const;
+ /*@Doc:
+ prints a double
+ */
+
+ operator double() const;
+ /*@Doc:
+ converts the oid to a double:
+ oid * OId::ID_MULTIPLIER + oidtype;
+ */
+
+ static const char* counterNames[];
+ /*@Doc:
+ holds the names of the counters in RAS_ADMIN, to go with counterIds
+ */
+
+ static unsigned int maxCounter;
+
+ OId& operator=(const OId& old);
+
+ bool operator== (const OId& one) const;
+
+ bool operator!= (const OId& one) const;
+
+ bool operator< (const OId& old) const;
+
+ bool operator> (const OId& old) const;
+
+ bool operator<= (const OId& old) const;
+
+ bool operator>= (const OId& old) const;
+
+ protected:
+ // protection agains writing back unloaded counters => inconsistent DB!!
+ static bool loadedOk;
+
+
+ OIdCounter oid;
+ /*@Doc:
+ the counter inside the oid
+ */
+
+ OIdType oidtype;
+ /*@Doc:
+ the type of object
+ */
+
+ static OIdCounter nextMDDOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextMDDCOLLOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextMDDTYPEOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextMDDBASETYPEOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextMDDDIMTYPEOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextMDDDOMTYPEOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextSTRUCTTYPEOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextSETTYPEOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextBLOBOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextDBMINTERVALOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextSTORAGEOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextMDDHIERIXOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ //static OIdCounter nextDBTCINDEXOID;
+ /*@Doc:
+ this counter is not used because mddhierix takes care of that
+ */
+
+ //static OIdCounter nextINLINETILEOID;
+ /*@Doc:
+ not used because they are the same as bloboid counter
+ */
+
+ static OIdCounter nextATOMICTYPEOID;
+ /*@Doc:
+ not used now because they are hard coded
+ */
+
+ static OIdCounter nextMDDRCIXOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextUDFOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter nextUDFPACKAGEOID;
+ /*@Doc:
+ counter which holds the next oid
+ */
+
+ static OIdCounter* counterIds[];
+ /*@Doc:
+ holds all OIdCounters of next* sort, to go with the counterNames.
+ */
+
+ };
+
+extern std::ostream& operator<<(std::ostream& in, const OId& d);
+
+extern std::ostream& operator<<(std::ostream& in, OId::OIdType d);
+
+extern bool operator== (const OId::OIdPrimitive one, const OId& two);
+
+extern bool operator== (const OId& two, const OId::OIdPrimitive one);
+
+#endif
diff --git a/reladminif/oidif.pgc b/reladminif/oidif.pgc
new file mode 100644
index 0000000..9f19254
--- /dev/null
+++ b/reladminif/oidif.pgc
@@ -0,0 +1,135 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+// This is -*- C++ -*-
+/*****************************************************************************
+ *
+ *
+ * PURPOSE:
+ *
+ *
+ * COMMENTS:
+ * uses embedded SQL
+ *
+ *****************************************************************************/
+
+static const char rcsid[] = "@(#)reladminif,OIdIf: $Id: oidif.ec,v 1.5 2003/12/27 23:11:43 rasdev Exp $";
+
+#include "debug-srv.hh"
+
+// general embedded SQL related definitions
+EXEC SQL include "sqlglobals.h";
+
+#include "oidif.hh"
+#include "raslib/rmdebug.hh"
+#include "sqlerror.hh"
+#include "adminif.hh"
+
+void
+OId::initialize()
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "OId", "initialize()");
+ ENTER( "OId::initialize" );
+
+ loadedOk = false;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ long nextoid;
+ char name[STRING_MAXLEN];
+ EXEC SQL END DECLARE SECTION;
+ nextoid = 0;
+ for (int i = 1; i < maxCounter; i++)
+ {
+ (void) strncpy( name, (char*) counterNames[i], (size_t) sizeof(name) );
+
+ TALK( "EXEC SQL SELECT NextValue INTO :nextoid FROM RAS_COUNTERS WHERE CounterName = " << name );
+ EXEC SQL SELECT NextValue INTO :nextoid
+ FROM RAS_COUNTERS
+ WHERE CounterName = :name;
+ TALK( "-> nextoid=" << nextoid );
+ if (check("OId::initialize() SELECT OId"))
+ {
+ RMInit::logOut << "OId::initialize() error reading " << name << endl;
+ generateException();
+ }
+ *counterIds[i] = nextoid;
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "read " << counterNames[i] << " " << *counterIds[i]);
+ }
+
+ loadedOk = true;
+
+ LEAVE( "OId::initialize" );
+ RMDBGEXIT(4, RMDebug::module_adminif, "OId", "initialize()");
+}
+
+void
+OId::deinitialize()
+{
+ RMDBGENTER(4, RMDebug::module_adminif, "OId", "deinitialize()");
+ ENTER( "OId::deinitialize" );
+
+ if (AdminIf::isReadOnlyTA())
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "do nothing is read only");
+ }
+ else
+ {
+ if (AdminIf::isAborted())
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "do nothing is aborted");
+ }
+
+ else if(loadedOk==false)
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "avoiding to write uninitialized counters into DB");
+ }
+
+ else
+ {
+ EXEC SQL BEGIN DECLARE SECTION;
+ long nextoid1;
+ char name2[STRING_MAXLEN];
+ EXEC SQL END DECLARE SECTION;
+
+ for (int i = 1; i < maxCounter; i++)
+ {
+ nextoid1 = *counterIds[i];
+ (void) strncpy( name2, (char*) counterNames[i], (size_t) sizeof(name2) );
+
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "setting " << name2 << " to " << nextoid1)
+ TALK( "EXEC SQL UPDATE RAS_COUNTERS SET NextValue = " << nextoid1 << " WHERE CounterName = " << name2 );
+ EXEC SQL UPDATE RAS_COUNTERS SET NextValue = :nextoid1
+ WHERE CounterName = :name2;
+ if (check("OId::deinitialize() UPDATE OId"))
+ {
+ RMInit::logOut << "OId::deinitialize() error writing " << name2 << endl;
+ }
+ }
+ }
+ }
+
+ loadedOk = false;
+
+ LEAVE( "OId::deinitialize" );
+ RMDBGEXIT(4, RMDebug::module_adminif, "OId", "deinitialize()");
+}
+
diff --git a/reladminif/oidifcommon.cc b/reladminif/oidifcommon.cc
new file mode 100644
index 0000000..ed75ef3
--- /dev/null
+++ b/reladminif/oidifcommon.cc
@@ -0,0 +1,414 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+// This is -*- C++ -*-
+/*****************************************************************************
+ *
+ *
+ * PURPOSE:
+ * code common to all database interface implementations
+ *
+ *
+ * COMMENTS:
+ * uses embedded SQL
+ *
+ *****************************************************************************/
+#include <string.h>
+#include "oidif.hh"
+#include "adminif.hh"
+#include "databaseif.hh"
+#include <stdlib.h>
+#include "externs.h"
+#include "sqlerror.hh"
+#include "raslib/error.hh"
+#include "raslib/rmdebug.hh"
+
+#ifdef RMANBENCHMARK
+RMTimer
+OId::oidAlloc("OId","allocateOId");
+#endif
+
+#ifdef RMANBENCHMARK
+RMTimer
+OId::oidResolve("OId","resolveOId");
+#endif
+
+double OId::ID_MULTIPLIER = 512;
+
+OId::OIdCounter OId::nextMDDOID = 0;
+
+OId::OIdCounter OId::nextMDDCOLLOID = 0;
+
+OId::OIdCounter OId::nextMDDTYPEOID = 0;
+
+OId::OIdCounter OId::nextMDDBASETYPEOID = 0;
+
+OId::OIdCounter OId::nextMDDDIMTYPEOID = 0;
+
+OId::OIdCounter OId::nextMDDDOMTYPEOID = 0;
+
+OId::OIdCounter OId::nextSTRUCTTYPEOID = 0;
+
+OId::OIdCounter OId::nextSETTYPEOID = 0;
+
+OId::OIdCounter OId::nextBLOBOID = 0;
+
+OId::OIdCounter OId::nextDBMINTERVALOID = 0;
+
+OId::OIdCounter OId::nextSTORAGEOID = 0;
+
+OId::OIdCounter OId::nextMDDHIERIXOID = 0;
+
+OId::OIdCounter OId::nextATOMICTYPEOID = 0;
+
+OId::OIdCounter OId::nextMDDRCIXOID = 0;
+
+OId::OIdCounter OId::nextUDFOID = 0;
+
+OId::OIdCounter OId::nextUDFPACKAGEOID = 0;
+
+unsigned int
+OId::maxCounter = 20;
+
+const char*
+OId::counterNames[] = { "INVALID",
+ "MDDOID",
+ "MDDCOLLOID",
+ "MDDTYPEOID",
+ "MDDBASETYPEOID",
+ "MDDDIMTYPEOID",
+ "MDDDOMTYPEOID",
+ "STRUCTTYPEOID",
+ "SETTYPEOID",
+ "BLOBOID",
+ "DBMINTERVALOID",
+ "STORAGEOID",
+ "MDDHIERIXOID",
+ "INLINEINDEXOID",
+ "INLINETILEOID",
+ "INNEROID",
+ "ATOMICTYPEOID",
+ "UDFOID",
+ "UDFPACKAGEOID",
+ "MDDRCIXOID"
+ };
+
+OId::OIdCounter*
+OId::counterIds[] = {
+ NULL,
+ &nextMDDOID,
+ &nextMDDCOLLOID,
+ &nextMDDTYPEOID,
+ &nextMDDBASETYPEOID,
+ &nextMDDDIMTYPEOID,
+ &nextMDDDOMTYPEOID,
+ &nextSTRUCTTYPEOID,
+ &nextSETTYPEOID,
+ &nextBLOBOID,
+ &nextDBMINTERVALOID,
+ &nextSTORAGEOID,
+ &nextMDDHIERIXOID,
+ &nextMDDHIERIXOID,
+ &nextBLOBOID,
+ &nextBLOBOID,
+ &nextATOMICTYPEOID,
+ &nextUDFOID,
+ &nextUDFPACKAGEOID,
+ &nextMDDRCIXOID
+ };
+
+bool OId::loadedOk = false;
+
+void
+OId::allocateOId(OId& id, OIdType type, OIdCounter howMany)
+ {
+ RMDBGENTER(4, RMDebug::module_adminif, "OId", "allocateOId(" << id << ", " << (OIdType)type << ")");
+ if (howMany == 0)
+ {
+ RMInit::logOut << "OId::allocateOId(" << id << ", " << type << ", " << howMany << ") allocation of zero oids not supported" << endl;
+ throw r_Error(r_Error::r_Error_CreatingOIdFailed);
+ }
+ if (type == INVALID || type == INNEROID || type == ATOMICTYPEOID || type > maxCounter)
+ {
+ RMInit::logOut << "OIDs of the specified type (" << type << " cannot be allocated." << endl;
+ throw r_Error(r_Error::r_Error_CreatingOIdFailed);
+ }
+ else {
+ id.oid = *counterIds[type];
+ *counterIds[type] = *counterIds[type] + howMany;
+ }
+ id.oidtype = type;
+ RMDBGEXIT(4, RMDebug::module_adminif, "OId", "allocateOId(" << id << ", " << type << ") ");
+ }
+
+OId::OId(const OId& oldOId)
+ {
+ RMDBGENTER(4, RMDebug::module_adminif, "OId", "OId(" << oldOId << ")");
+ oid = oldOId.oid;
+ oidtype = oldOId.oidtype;
+ RMDBGEXIT(4, RMDebug::module_adminif, "OId", "OId(" << oldOId << ")");
+ }
+
+OId::OId()
+ {
+ RMDBGENTER(4, RMDebug::module_adminif, "OId", "OId()");
+ oidtype = INVALID;
+ oid = 0;
+ RMDBGEXIT(4, RMDebug::module_adminif, "OId", "OId()");
+ }
+
+OId::OId(OIdPrimitive newId)
+ {
+ RMDBGENTER(4, RMDebug::module_adminif, "OId", "OId(OIdPrimitive " << newId << ")");
+ oid = newId / OId::ID_MULTIPLIER;
+ oidtype = (OId::OIdType)(newId - (OIdPrimitive)((OIdPrimitive)oid * OId::ID_MULTIPLIER));
+ RMDBGEXIT(4, RMDebug::module_adminif, "OId", "OId(OIdPrimitive " << newId << ") ID " << oid << " TYPE " << oidtype);
+ }
+
+OId::OId(OIdCounter newId, OIdType type)
+ {
+ RMDBGENTER(4, RMDebug::module_adminif, "OId", "OId(" << newId << "," << type << ")");
+ oidtype = type;
+ oid = newId;
+ RMDBGEXIT(4, RMDebug::module_adminif, "OId", "OId(" << newId << "," << type << ")");
+ }
+
+OId::OIdType
+OId::getType() const
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "getType() " << oidtype);
+ return oidtype;
+ }
+
+void
+OId::print_status(ostream& s) const
+ {
+ s << this;
+ }
+
+OId::OIdCounter
+OId::getCounter() const
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "getCounter() " << oid);
+ return oid;
+ }
+
+OId::operator double() const
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator() " << oid);
+ return oid * OId::ID_MULTIPLIER + oidtype;
+ }
+
+bool
+OId::operator!= (const OId& one) const
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator!=(" << one << ") " << *this);
+ return !(OId::operator==(one));
+ }
+
+bool
+OId::operator== (const OId& one) const
+ {
+ bool retval = false;
+ if (oidtype == one.oidtype)
+ {
+ retval = (oid == one.oid);
+ }
+ else {
+ retval = false;
+ }
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator==(" << one << ") " << *this << " retval=" << retval);
+ return retval;
+ }
+
+OId&
+OId::operator=(const OId& old)
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator=(" << old << ") "<< *this);
+ if (this != &old)
+ {
+ oid = old.oid;
+ oidtype = old.oidtype;
+ }
+ return *this;
+ }
+
+bool
+OId::operator<(const OId& old) const
+ {
+ bool retval = false;
+ if (oidtype == old.oidtype)
+ {
+ retval = (oid < old.oid);
+ }
+ else {
+ retval = (oidtype < old.oidtype);
+ }
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator<(" << old << ") " << *this << " retval=" << retval);
+ return retval;
+ }
+
+bool
+OId::operator>(const OId& old) const
+ {
+ bool retval = false;
+ if (oidtype == old.oidtype)
+ {
+ retval = (oid > old.oid);
+ }
+ else {
+ retval = (oidtype > old.oidtype);
+ }
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator>(" << old << ") " << *this << " retval=" << retval);
+ return retval;
+ }
+
+bool
+OId::operator<=(const OId& old) const
+ {
+ bool retval = false;
+ if (oidtype == old.oidtype)
+ {
+ retval = (oid <= old.oid);
+ }
+ else {
+ retval = (oidtype < old.oidtype);
+ }
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator<=(" << old << ") " << *this << " retval=" << retval);
+ return retval;
+ }
+
+bool
+OId::operator>=(const OId& old) const
+ {
+ bool retval = false;
+ if (oidtype == old.oidtype)
+ {
+ retval = (oid >= old.oid);
+ }
+ else {
+ retval = (oidtype > old.oidtype);
+ }
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator>=(" << old << ") " << *this << " retval=" << retval);
+ return retval;
+ }
+
+bool
+operator== (const double one, const OId& two)
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator==(" << one << "," << two << ")");
+ bool retval=false;
+ if (((double)two) == one)
+ retval=true;
+ return retval;
+ }
+
+bool
+operator== (const OId& two, const double one)
+ {
+ RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator==(" << two << "," << one << ")");
+ bool retval=false;
+ if (((double)two) == one)
+ retval=true;
+ return retval;
+ }
+
+std::ostream&
+operator<<(std::ostream& s, const OId& d)
+ {
+ s << "OId(" << d.getCounter() << ":" << d.getType() << ")";
+ return s;
+ }
+
+std::ostream&
+operator<<(std::ostream& s, OId::OIdType d)
+ {
+ switch (d)
+ {
+ case OId::INVALID:
+ s << "INVALID";
+ break;
+ case OId::MDDOID:
+ s << "MDDOID";
+ break;
+ case OId::MDDCOLLOID:
+ s << "MDDCOLLOID";
+ break;
+ case OId::MDDTYPEOID:
+ s << "MDDTYPEOID";
+ break;
+ case OId::MDDBASETYPEOID:
+ s << "MDDBASETYPEOID";
+ break;
+ case OId::MDDDIMTYPEOID:
+ s << "MDDDIMTYPEOID";
+ break;
+ case OId::MDDDOMTYPEOID:
+ s << "MDDDOMTYPEOID";
+ break;
+ case OId::STRUCTTYPEOID:
+ s << "STRUCTTYPEOID";
+ break;
+ case OId::SETTYPEOID:
+ s << "SETTYPEOID";
+ break;
+ case OId::BLOBOID:
+ s << "BLOBOID";
+ break;
+ case OId::DBMINTERVALOID:
+ s << "DBMINTERVALOID";
+ break;
+ case OId::STORAGEOID:
+ s << "STORAGEOID";
+ break;
+ case OId::MDDHIERIXOID:
+ s << "MDDHIERIXOID";
+ break;
+ case OId::DBTCINDEXOID:
+ s << "DBTCINDEXOID";
+ break;
+ case OId::INLINETILEOID:
+ s << "INLINETILEOID";
+ break;
+ case OId::INNEROID:
+ s << "INNEROIDOID";
+ break;
+ case OId::ATOMICTYPEOID:
+ s << "ATOMICTYPEOID";
+ break;
+ case OId::UDFOID:
+ s << "UDFOID";
+ break;
+ case OId::UDFPACKAGEOID:
+ s << "UDFPACKAGEOID";
+ break;
+ case OId::MDDRCIXOID:
+ s << "MDDRCIXOID";
+ break;
+ default:
+ s << "UNKNOWN: " << (int)d;
+ break;
+ }
+ return s;
+ }
+
+
diff --git a/reladminif/sqlerror.hh b/reladminif/sqlerror.hh
new file mode 100644
index 0000000..869fb86
--- /dev/null
+++ b/reladminif/sqlerror.hh
@@ -0,0 +1,118 @@
+#ifndef _SQLERROR_HH_
+#define _SQLERROR_HH_
+
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/************************************************************************
+ *
+ *
+ * PURPOSE:
+ *
+ *
+ * COMMENTS:
+ *
+ ***********************************************************************/
+
+//@ManMemo: Module: {\bf reladminif}.
+
+/*@Doc:
+
+ SQL Errors Handling
+
+*/
+#include <iostream>
+using std::cout;
+using std::endl;
+
+#include "raslib/error.hh"
+
+#ifdef BASEDB_DB2
+#define generateException() generateExceptionn(sqlca)
+
+void generateExceptionn(struct sqlca&) throw (r_Error);
+
+/*@Doc:
+generates a new r_Ebase_dbms exception and throws it.
+*/
+
+#define check(msg) checkk(msg, sqlca)
+int checkk(const char* msg, struct sqlca& mysql) throw( r_Error );
+ /*@Doc:
+ returns sqlcode, prints error messages when appropriate.
+ the msg is inserted in the error message.
+ changes are not rolledback, nothing is done to the connection.
+ */
+
+#endif
+
+#ifdef BASEDB_ORACLE
+void generateException() throw (r_Error);
+/*@Doc:
+generates a new r_Ebase_dbms exception and throws it.
+*/
+
+int check(const char* msg) throw (r_Error);
+/*@Doc:
+returns sqlcode, prints error messages when appropriate.
+the msg is inserted in the error message.
+changes are not rolledback, nothing is done to the connection.
+*/
+
+void printSQLError(void* err, int status);
+void printSQLError(void* err) throw (r_Error);
+/*@Doc:
+This diplays cli errors.
+*/
+#endif
+
+#ifdef BASEDB_INFORMIX
+void generateException() throw (r_Error);
+/*@Doc:
+This generates exceptions.
+*/
+
+int check(const char* msg, bool displayWarning = false) throw (r_Error);
+/*@Doc:
+This diplays esql errors.
+*/
+
+void printSQLError(int error, const char*);
+/*@Doc:
+This diplays cli errors.
+*/
+#endif
+
+#ifdef BASEDB_PGSQL
+void generateException() throw (r_Error);
+/*@Doc:
+This generates exceptions.
+*/
+
+int check(const char* msg) throw (r_Error);
+/*@Doc:
+Display error message if SQL errors have occurred.
+*/
+#endif
+
+#endif
+
diff --git a/reladminif/sqlerror.pgc b/reladminif/sqlerror.pgc
new file mode 100644
index 0000000..94d41a3
--- /dev/null
+++ b/reladminif/sqlerror.pgc
@@ -0,0 +1,198 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+// This is -*- C++ -*-
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * process base DBMS errors (PostgreSQL) by printing messages and throwing exceptions.
+ *
+ *
+ * COMMENTS:
+ * - different from other implementations in that no distinction between
+ * error and warning
+ * - the whole module should be redesigned for all DBMSs - very unconcise
+ * - no function printSQLError() as eg in Informix
+ * - FIXME: generateException() should be declared r_Ebase_dbms instead of r_Error
+ *
+ ***********************************************************************/
+
+static const char rcsid[] = "@(#)reladminif,SQLError: $Id: sqlerror.ec,v 1.4 2003/12/27 23:11:43 rasdev Exp $";
+
+// #define SQLCA_STORAGE_CLASS extern
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "sqlerror.hh"
+#include "externs.h"
+
+#include "raslib/rmdebug.hh"
+#include "raslib/error.hh"
+#include "debug-srv.hh"
+
+// general embedded SQL related definitions
+EXEC SQL include "sqlglobals.h";
+
+// SQLSTATE not available in PGSQL (SQLCODE is, funny enough)
+#define SQLSTATE sqlca.sqlstate
+
+// error codes
+EXEC SQL define SUCCESS 0;
+EXEC SQL define WARNING 1;
+EXEC SQL define NODATA 100;
+EXEC SQL define RTERROR -1;
+
+// general message buffer size
+#define BUFFER_SIZE 4000
+
+// SQL error message max size
+// FIXME: is this really enough?
+const int MSG_MAXLEN=BUFFER_SIZE;
+
+// length of buffer for remembering last message
+#define LASTERRORMSGLEN BUFFER_SIZE
+char lastErrorMsg[LASTERRORMSGLEN];
+
+/*
+ * The sqlstate_err() function checks the SQLSTATE status variable to see
+ * if an error or warning has occurred following an SQL statement.
+ */
+int sqlstate_err()
+{
+ int err_code = RTERROR;
+
+ if (SQLSTATE[0] == '0') /* trap '00', '01', '02' */
+ {
+ switch(SQLSTATE[1])
+ {
+ case '0': /* success - return 0 */
+ err_code = SUCCESS;
+ break;
+ case '1': /* warning - return 1 */
+ err_code = WARNING;
+ break;
+ case '2': /* end of data - return 100 */
+ err_code = NODATA;
+ break;
+ default: /* error - return SQLCODE */
+ break;
+ }
+ }
+ return err_code;
+} // sqlstate_err()
+
+
+/*
+ * The disp_sqlstate_err() function prints details into msgbuf.
+ */
+void disp_sqlstate_err(char* msgbuf, size_t length)
+{
+ char error_buffer[BUFFER_SIZE];
+ size_t characters_written = 0;
+
+ snprintf(error_buffer, BUFFER_SIZE, "SQLSTATE: %5s SQLCODE: %d\n", SQLSTATE, SQLCODE);
+ characters_written = strlen(error_buffer);
+ if (characters_written > length)
+ {
+ RMInit::logOut << "error message didn't fit into buffer: " << error_buffer << endl;
+ }
+ else
+ {
+ strcat(msgbuf, error_buffer);
+ }
+} // disp_sqlstate_err()
+
+/*
+ * disp_error(): print statement and error/warning text into buffer
+ */
+void disp_error(const char* stmt, char* msgbuf, size_t length)
+{
+ char error_buffer[BUFFER_SIZE];
+ snprintf(error_buffer, BUFFER_SIZE, "Warning/error in %s:\n", stmt);
+
+ size_t error_len = strlen(error_buffer);
+
+ if (error_len > length)
+ RMInit::logOut << "error message didn't fit into buffer: " << error_buffer << endl;
+ else
+ {
+ strcat(msgbuf, error_buffer);
+ length = length - error_len;
+ }
+ disp_sqlstate_err(msgbuf, length);
+} // disp_error()
+
+/*
+ * disp_exception(): if sql_errcode says there was an error,
+ * allocate msg buffer and copy error msg
+ */
+char* disp_exception(const char* stmt, int sqlerr_code)
+{
+ char* msgbuf = NULL;
+ switch (sqlerr_code)
+ {
+ case SUCCESS:
+ case NODATA:
+ break;
+ case WARNING:
+ case RTERROR:
+ msgbuf = new char[BUFFER_SIZE];
+ memset(msgbuf, 0, BUFFER_SIZE);
+ disp_error(stmt, msgbuf, BUFFER_SIZE);
+ break;
+ default:
+ RMInit::logOut << "Invalid exception state for " << stmt << " " << sqlerr_code << endl;
+ break;
+ }
+ return msgbuf;
+} // disp_exception()
+
+/*
+ * check(): check base DBMS for any error occurred during last
+ * database access and print message into log if so.
+ */
+int
+check(const char* stmt) throw (r_Error)
+{
+ char* msg = disp_exception(stmt, sqlstate_err());
+ if (msg != NULL)
+ {
+ RMInit::logOut << msg << endl;
+ snprintf(lastErrorMsg, LASTERRORMSGLEN, msg);
+ delete [] msg;
+ msg = NULL;
+ }
+ return SQLCODE;
+}
+
+// generate r_Ebase_dbms exception using SQL error code and message
+void
+generateException() throw (r_Error)
+{
+ TALK( "Throwing Exception (SQLCODE=" << SQLCODE << "): " << lastErrorMsg );
+ RMInit::dbgOut << "Throwing Exception (SQLCODE=" << SQLCODE << "): " << lastErrorMsg << endl;
+ throw r_Ebase_dbms( SQLCODE, lastErrorMsg );
+} // generateException()
+
diff --git a/reladminif/sqlglobals.h b/reladminif/sqlglobals.h
new file mode 100644
index 0000000..5ac83cf
--- /dev/null
+++ b/reladminif/sqlglobals.h
@@ -0,0 +1,50 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*****************************************************************************
+ *
+ *
+ * PURPOSE:
+ * provide global definitions for embedded SQL usage (any base DBMS)
+ *
+ *
+ * COMMENTS:
+ * - further SQL-relevant constants for C++ usage can be found in externs.h
+ *
+ *****************************************************************************/
+
+#ifndef _SQLGLOBALS_H_
+#define _SQLGLOBALS_H_
+
+// this syntax should be the same for all embedded SQL versions
+// right now only tested & used with Informix, though
+
+// max length of varchar attributes and other string buffers; incl padding zero
+// see $(INFORMIXDIR)/incl/esql/varchar.h
+// unfortunately there it is not made known to ESQL, so we must use a literal here
+EXEC SQL define VARCHAR_MAXLEN 255;
+EXEC SQL define STRING_MAXLEN 255;
+
+// SQL query string buffer size
+#define SQL_QUERY_BUFFER_SIZE 400
+
+#endif // _SQLGLOBALS_H_
diff --git a/reladminif/test/Makefile b/reladminif/test/Makefile
new file mode 100644
index 0000000..40097a2
--- /dev/null
+++ b/reladminif/test/Makefile
@@ -0,0 +1,90 @@
+# -*-Makefile-*-
+#
+# This file is part of rasdaman community.
+#
+# Rasdaman community is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Rasdaman community is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+#
+# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+# rasdaman GmbH.
+#
+# For more information please see <http://www.rasdaman.org>
+# or contact Peter Baumann via <baumann@rasdaman.com>. # Top Level makefile. This points to the various modules that have to be build
+# and/or deployed
+#
+# MAKEFILE FOR:
+# reladminif tests.
+#
+# COMMENTS:
+# - List environment dependencies, known bugs, specialities etc.
+#
+##################################################################
+######################### Definitions ############################
+
+# all test programs
+ALLTESTS = test_databaseif dbreftest admintest perstest eoidtest dbnamedobjtest testindex testconnect test_databaseif
+
+# Needed rasdaman libraries for linking. To be completed.
+NEEDEDLIBS = $(CACHETAMGR) $(QLPARSER) $(INDEXMGR) $(RELADMINIF) $(RELMDDIF) $(RELBLOBIF) $(RELINDEXIF) $(CACHETAMGR) $(RELCATALOGIF) $(RASLIB) $(RELADMINIF) $(RELMDDIF)
+
+# insert names of source files which need STL<TOOLKIT>
+# also insert names of source files which include .hh files which need stl
+NEEDSTL := dbreftest.C eoidtest.C admintest.C perstest.C dbnamedobjtest.C testindex.c
+
+# insert any files that are not object, bind or generated .c/.C files
+# e.g.: libs
+MISCCLEAN := client.bm client.dbg client.log ir.out core
+
+# insert object files here. makes only sense if oracle and db2 files are the same
+OBJS := dbreftest.o admintest.o perstest.o eoidtest.o dbnamedobjtest.o testindex.o testconnect.o test_databaseif.o
+
+# add to compile flag set
+CXXFLAGS += $(I_SYM)$(RMANBASE)/raslib
+
+########################### Targets ##############################
+
+# make all tests
+.PHONY: test
+test: $(ALLTESTS)
+
+indextest.o: indextest.cc
+ $(CXX) -c $(BASEDBCXXFLAGS) $(STLCXXFLAGS) $(CXXFLAGS) $<
+
+######################## Dependencies ############################
+
+admintest: admintest.o $(NEEDEDLIBS)
+admintest.o: admintest.C
+
+dbreftest: dbreftest.o
+dbreftest.o: dbreftest.C
+
+eoidtest: eoidtest.o
+eoidtest.o: eoidtest.C
+
+dbnamedobjtest: dbnamedobjtest.o
+dbnamedobjtest.o: dbnamedobjtest.C
+
+perstest: perstest.o
+perstest.o: perstest.C
+
+dbcheck.o: dbcheck.c
+dbcheck.c: dbcheck.pc
+dbcheck: dbcheck.o
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -L/home/proj/rasdaman/3rdParty/linux/lib -L$(RMANHOME)/lib -Xlinker -Bstatic $(LIBAKINSIDE) -lmddmgr -ltilemgr -lindexmgr -lcatalogmgr -lstoragemgr -lreladminif -lrelmddif -lrelstorageif -lrelindexif -lrelcatalogif -lrelblobif -lcompression -lconversion -lraslib $(RMANHOME)/mymalloc/mymalloc_svc.o -lpng -ltiff -ljpeg -lmfhdf -ldf -lz $(REL_STATIC_LIBS)
+
+check: check.o
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -L$(RMANHOME)/lib -Xlinker -Bstatic $(LIBAKINSIDE) -lmddmgr -ltilemgr -lindexmgr -lcatalogmgr -lstoragemgr -lreladminif -lrelmddif -lrelstorageif -lrelindexif -lrelcatalogif -lrelblobif -lcompression -lconversion -lraslib $(RMANHOME)/mymalloc/mymalloc_svc.o -lpng -ltiff -ljpeg -lmfhdf -ldf -lz $(REL_STATIC_LIBS)
+
+test_databaseif: test_databaseif.o ../databaseif.o
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(RMANBASE)/mymalloc/mymalloc_svc.o ../sqlerror.o ../oidif.o ../adminif.o -L$(RMANBASE)/lib -lraslib -lrasodmg $(BASEDBLDFLAGS)
+
diff --git a/reladminif/test/admintest.C b/reladminif/test/admintest.C
new file mode 100644
index 0000000..adf0d94
--- /dev/null
+++ b/reladminif/test/admintest.C
@@ -0,0 +1,92 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "raslib/rmdebug.hh"
+#include <iostream.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "adminif.hh"
+#include "databaseif.hh"
+#include "transactionif.hh"
+#include "raslib/rmdebug.hh"
+#include "externs.h"
+
+RMINITGLOBALS('C')
+
+
+int
+main(int argc, char *argv[])
+ {
+ int RManDebug2 = 5;
+ int RManModule = 1;
+ DatabaseIf database;
+ TransactionIf ta;
+ char* name = 0;
+
+ if (argc == 2)
+ name = argv[1];
+ else
+ name = "RASBASE";
+
+ cout << "OPENING DATABASEIF" << endl;
+ if (database.open(name))
+ {
+ cout << "ERROR OPENING DATABASE" << endl;
+ return -1;
+ }
+ cout << "OPENED DATABASEIF" << endl;
+
+ if (!database.databaseExists())
+ {
+ cout << "DATABASE EXISTS NOT" << endl;
+ cout << "CREATEING DATABASE" << endl;
+ database.create(name, 0, 0);
+ cout << "DATABASE CREATED" << endl;
+ }
+ else {
+ cout << "DATABASE EXISTS" << endl;
+ cout << "BEGINNING TRANSACTIONIF" << endl;
+ ta.begin(&database);
+ cout << "TRANSACTIONIF BEGUN" << endl;
+ cout << "DESTROYING DATABASE" << endl;
+ database.destroyDB(&ta, name);
+ cout << "DATABASE DESTROYED" << endl;
+ }
+ cout << "CLOSING DATABASEIF" << endl;
+ database.close();
+ cout << "CLOSED DATABASEIF" << endl;
+
+ cout << "OPENING DATABASEIF" << endl;
+ if (database.open(name))
+ {
+ cout << "ERROR OPENING DATABASE" << endl;
+ return -1;
+ }
+ cout << "OPENED DATABASEIF" << endl;
+ if (database.databaseExists())
+ cout << "DATABASE EXISTS" << endl;
+ else
+ cout << "DATABASE EXISTS NOT" << endl;
+ database.close();
+ cout << "CLOSED DATABASEIF" << endl;
+ }
diff --git a/reladminif/test/check.cc b/reladminif/test/check.cc
new file mode 100644
index 0000000..44e5892
--- /dev/null
+++ b/reladminif/test/check.cc
@@ -0,0 +1,301 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*
+get mddoid, iterate domain, dataformat
+
+select mdd
+get domain
+ {
+ begin ta
+ iterate over domain
+ retrieve tiles
+ alter tiles
+ commit ta
+ }
+*/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "server/template_inst.hh"
+#endif
+
+#include "reladminif/adminif.hh"
+#include "reladminif/databaseif.hh"
+#include "reladminif/transactionif.hh"
+#include "reladminif/oidif.hh"
+#include "mddmgr/mddobj.hh"
+#include "tilemgr/tile.hh"
+#include "cmlparser.hh"
+#include "raslib/mitera.hh"
+
+#define ALLDONE 0
+#define ERRORPARSINGCOMMANDLINE 1
+#define DOMAINMISSING 2
+#define OIDMISSING 3
+#define OIDINVALID 4
+#define DOMAINMISMATCH 5
+#define FAILED 6
+#define DOMAININVALID 7
+#define UNKNOWNDATAFORMAT 8
+
+char globalConnectId[256];
+
+RMINITGLOBALS('S')
+
+r_Minterval domain;
+OId oid;
+
+int
+main(int argc, char** argv)
+ {
+ RMInit::logOut.rdbuf(cout.rdbuf());
+ RMInit::dbgOut.rdbuf(cout.rdbuf());
+ int retval = 0;
+ CommandLineParser &cmlInter = CommandLineParser::getInstance();
+ CommandLineParameter &clp_help = cmlInter.addFlagParameter('h', "help", "show command line switches");
+ CommandLineParameter &clp_connect = cmlInter.addStringParameter(CommandLineParser::noShortName, "connect", "database connect string", "/");
+ CommandLineParameter &clp_mdddomain = cmlInter.addStringParameter(CommandLineParser::noShortName, "mdddomain", "the domain to do the changes in.");
+ CommandLineParameter &clp_domain = cmlInter.addStringParameter(CommandLineParser::noShortName, "domain", "the extent to be used when selecting data from the mdd.");
+ CommandLineParameter &clp_oid = cmlInter.addStringParameter(CommandLineParser::noShortName, "oid", "the oid of the mdd to operate on");
+ CommandLineParameter &clp_comptype = cmlInter.addStringParameter(CommandLineParser::noShortName, "storageformat", "name of storage format", "Array");
+ CommandLineParameter &clp_readonly = cmlInter.addFlagParameter('r', "readonly", "read only check");
+ try {
+ cmlInter.processCommandLine(argc, argv);
+ }
+ catch(CmlException& err)
+ {
+ cmlInter.printHelp();
+ cout << "Error parsing command line:" << endl;
+ cout << err.what() << endl;
+ return ERRORPARSINGCOMMANDLINE;
+ }
+ if (cmlInter.isPresent('h'))
+ {
+ cmlInter.printHelp();
+ return ALLDONE;
+ }
+ r_Data_Format storageFormat = r_Array;
+ if (cmlInter.isPresent("storageformat"))
+ {
+ storageFormat = get_data_format_from_name(cmlInter.getValueAsString("storageformat"));
+ if (storageFormat == r_Data_Format_NUMBER)
+ {
+ cout << "unknown data format " << cmlInter.getValueAsString("storageformat") << endl;
+ return UNKNOWNDATAFORMAT;
+ }
+ }
+ if (!cmlInter.isPresent("domain"))
+ {
+ cout << "domain is missing" << endl;
+ return DOMAINMISSING;
+ }
+ if (!cmlInter.isPresent("oid"))
+ {
+ cout << "oid is missing" << endl;
+ return OIDMISSING;
+ }
+ strcpy((char*)globalConnectId, cmlInter.getValueAsString("connect"));
+ cout << "connect " << globalConnectId << endl;
+ try {
+ domain = r_Minterval(cmlInter.getValueAsString("domain"));
+ }
+ catch (const r_Error& e)
+ {
+ cout << "domain is not valid: " << e.what() << " " << e.get_errorno() << endl;
+ return DOMAININVALID;
+ }
+ oid = OId(atol(cmlInter.getValueAsString("oid")));
+ if (oid.getType() != OId::MDDOID)
+ {
+ cout << "oid is not a mdd oid" << endl;
+ return OIDINVALID;
+ }
+ bool readonly = cmlInter.isPresent("readonly");
+ if (readonly)
+ {
+ cout << "performing read only check" << std::endl;
+ }
+ else {
+ cout << "performing recompression" << std::endl;
+ }
+ cout << "set up done" << endl;
+ AdminIf::instance();
+ DatabaseIf d;
+ TransactionIf t;
+ MDDObj* mdd = NULL;
+ r_Minterval completeDomain;
+ r_MiterArea* miter = NULL;
+ try {
+ d.open("RASBASE");
+ t.begin(&d, true);
+ mdd = new MDDObj(oid);
+ if (mdd->getCurrentDomain().dimension() == domain.dimension())
+ {
+ completeDomain = mdd->getCurrentDomain();
+ if (cmlInter.isPresent("mdddomain"))
+ {
+ try {
+ r_Minterval temp(cmlInter.getValueAsString("mdddomain"));
+ if (temp.dimension() == completeDomain.dimension())
+ {
+ cout << "Not using complete mdd domain (" << completeDomain << ") but " << temp << endl;
+ completeDomain = temp;
+ }
+ else {
+ cout << "Domains do not have same number of dimensions" << endl;
+ delete mdd;
+ mdd = NULL;
+ t.commit();
+ d.close();
+ return DOMAINMISMATCH;
+ }
+ }
+ catch (const r_Error& e2)
+ {
+ cout << "mdddomain parameter is not correct: " << e2.get_errorno() << " " << e2.what() << endl;
+ delete mdd;
+ mdd = NULL;
+ t.commit();
+ d.close();
+ return DOMAININVALID;
+ }
+ }
+ miter = new r_MiterArea(&domain, &completeDomain);
+ }
+ else {
+ t.commit();
+ d.close();
+ return DOMAINMISMATCH;
+ }
+ delete mdd;
+ mdd = NULL;
+ t.commit();
+ d.close();
+ }
+ catch (const r_Error& e)
+ {
+ delete miter;
+ miter = NULL;
+ cout << "Caught exception " << e.get_errorno() << " " << e.what() << endl;
+ try {
+ t.abort();
+ }
+ catch (const r_Error& ee)
+ {
+ cout << "Caugh exception while aborting " << ee.get_errorno() << " " << ee.what() << endl;
+ try {
+ t.abort();
+ }
+ catch (const r_Error& eee)
+ {
+ cout << "Caugh exception while 2nd aborting " << eee.get_errorno() << " " << eee.what() << endl;
+ }
+ }
+ try {
+ d.close();
+ }
+ catch (const r_Error& eeee)
+ {
+ cout << "Caugh exception while closing " << eeee.get_errorno() << " " << eeee.what() << endl;
+ }
+ return FAILED;
+ }
+ std::vector<Tile*>* tiles = NULL;
+ std::vector<Tile*>::iterator here;
+ std::vector<Tile*>::iterator end;
+ r_Minterval currentDomain;
+ while (!miter->isDone())
+ {
+ currentDomain = miter->nextArea();
+ try {
+ d.open("RASBASE");
+ t.begin(&d, readonly);
+ mdd = new MDDObj(oid);
+ tiles = mdd->intersect(currentDomain);
+ end = tiles->end();
+ if (tiles)
+ {
+ cout << "working on " << currentDomain << " with " << tiles->size() << " tiles" << endl;
+ for (here = tiles->begin(); here < end; here++)
+ {
+ cout << " tile " << (*here)->getDomain() << " " << (*here)->getDBTile()->getOId() << " " << (*here)->getDataFormat() << " " << (*here)->getCompressedSize();
+ if (!(*here)->decompress())
+ {
+ cout << " decompress failed";
+ }
+ if (((*here)->getDataFormat() != storageFormat) && (!readonly))
+ {
+ cout << " changing storage format";
+ (*here)->setCompressionFormat(storageFormat);
+ cout << " compressed size " << (*here)->getCompressedSize();
+ }
+ cout << endl;
+ }
+ }
+ else {
+ cout << currentDomain << " no tiles" << endl;
+ }
+ delete mdd;
+ mdd = NULL;
+ delete tiles;
+ tiles = NULL;
+ t.commit();
+ d.close();
+ }
+ catch (const r_Error& e)
+ {
+ delete miter;
+ miter = NULL;
+ delete tiles;
+ tiles = NULL;
+ cout << "Caught exception " << e.get_errorno() << " " << e.what() << endl;
+ try {
+ t.abort();
+ }
+ catch (const r_Error& ee)
+ {
+ cout << "Caugh exception while aborting " << ee.get_errorno() << " " << ee.what() << endl;
+ try {
+ t.abort();
+ }
+ catch (const r_Error& eee)
+ {
+ cout << "Caugh exception while 2nd aborting " << eee.get_errorno() << " " << eee.what() << endl;
+ }
+ }
+ try {
+ d.close();
+ }
+ catch (const r_Error& eeee)
+ {
+ cout << "Caugh exception while closing " << eeee.get_errorno() << " " << eeee.what() << endl;
+ }
+ return FAILED;
+ }
+ }
+ delete tiles;
+ tiles = NULL;
+ delete miter;
+ miter = NULL;
+ return retval;
+ }
diff --git a/reladminif/test/dbnamedobjtest.C b/reladminif/test/dbnamedobjtest.C
new file mode 100644
index 0000000..e0c47f4
--- /dev/null
+++ b/reladminif/test/dbnamedobjtest.C
@@ -0,0 +1,88 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "mymalloc/mymalloc.h"
+#include "raslib/rmdebug.hh"
+#include <iostream.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "dbnamedobject.hh"
+
+RMINITGLOBALS('C')
+
+int RManDebug2 = 6;
+int RManModule = 4;
+
+int
+main(int argc, char *argv[])
+ {
+ if (argc == 1)
+ {
+ cout << "Usage:" << endl;
+ cout << "\t1\t: " << endl << "\t\t" << endl;
+ }
+ else {
+ cout << "arg 1: " << argv[0] << " arg 2: " << argv[1] << " arg 3: " << argv[2] << endl;
+ OId* id = 0;
+ DBNamedObject* obj = 0;
+ char* text = (char*)mymalloc(sizeof(char) * 300);
+ struct {
+ short length;
+ char data[200];
+ } VARCHAR;
+
+ cout << "DATADUMP\t:" << VARCHAR.data << endl;
+ strcpy(VARCHAR.data, "aslkjfdhaskldjfjsd\0askdjfhdkjsladf\0laksjddf\0");
+ cout << "DATADUMP\t:" << VARCHAR.data << endl;
+ switch (atoi(argv[1]))
+ {
+ case 1:
+ strcpy(text, "maxidaxi\0waxitaxi");
+// id = new OId(1,1);
+ DBNamedObject::MAXNAMELENGTH = atoi(argv[2]);
+ cout << "Name: " << text << endl;
+ obj = new DBNamedObject(text);//*id, text);
+ cout << "Get Name: " << obj->getName() << endl;
+ break;
+ case 2:
+ DBNamedObject::MAXNAMELENGTH = atoi(argv[2]);
+ obj = new DBNamedObject(text);//*id, text);
+ cout << "Get Name: " << obj->getName() << endl;
+ VARCHAR.length = atoi(argv[3]);
+ obj->setName(VARCHAR.length, (char*)VARCHAR.data);
+ cout << "Get Name: " << obj->getName() << endl;
+ break;
+ case 3:
+ DBNamedObject::MAXNAMELENGTH = atoi(argv[2]);
+ obj = new DBNamedObject();
+ cout << "Get Name: " << obj->getName() << endl;
+ VARCHAR.length = atoi(argv[3]);
+ obj->setName(VARCHAR.length, (char*)VARCHAR.data);
+ cout << "Get Name: " << obj->getName() << endl;
+ break;
+ default:
+ cout << "DONT KNOW WHAT TO DO" << endl;
+ break;
+ }
+ }
+ }
diff --git a/reladminif/test/dbreftest.C b/reladminif/test/dbreftest.C
new file mode 100644
index 0000000..5c62b64
--- /dev/null
+++ b/reladminif/test/dbreftest.C
@@ -0,0 +1,70 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "raslib/rmdebug.hh"
+#include <iostream.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "dbnamedobject.hh"
+#include "dbref.hh"
+#include "dbobject.hh"
+#include "oidif.hh"
+#include "adminif.hh"
+#include "databaseif.hh"
+#include "oidif.hh"
+#include "transactionif.hh"
+
+#include "alltypes.hh"
+#include "typefactory.hh"
+
+#include "dbmddcoll.hh"
+#include "dbmddcolloidentry.hh"
+#include "dbmddobj.hh"
+
+#include "raslib/rmdebug.hh"
+
+RMINITGLOBALS('C')
+
+int RManDebug2 = 8;
+int RManModule = 3;
+
+int
+main(int argc, char *argv[])
+ {
+ OId t(10, OId::BASETYPEOID);
+
+ AdminIf* myAdmin;
+ DatabaseIf database;
+ TransactionIf ta;
+ RManDebug = 6;
+
+ myAdmin = AdminIf::instance();
+ database.open("RMAN");
+ ta.begin(&database);
+
+ DbRef<BaseType> p(t);
+ cout << "Type " << p->getName() << endl;
+
+ ta.abort();
+ database.close();
+ }
diff --git a/reladminif/test/demobld.sql b/reladminif/test/demobld.sql
new file mode 100644
index 0000000..0895e87
--- /dev/null
+++ b/reladminif/test/demobld.sql
@@ -0,0 +1,125 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+--
+-- $Header: /home/rasdev/CVS-repository/rasdaman/reladminif/test/demobld.sql,v 1.3 2003/12/27 23:11:46 rasdev Exp $
+-- Copyright (c) Oracle Corporation 1988, 1993. All Rights Reserved.
+--
+--
+-- This script creates the SQL*Plus demonstration tables.
+--
+-- It should be STARTed by each user wishing to access the tables.
+--
+
+set termout on
+prompt Building demonstration tables. Please wait.
+set termout off
+set feedback off
+
+ALTER SESSION SET NLS_LANGUAGE = AMERICAN;
+ALTER SESSION SET NLS_TERRITORY = AMERICA;
+
+DROP TABLE EMP;
+DROP TABLE DEPT;
+DROP TABLE BONUS;
+DROP TABLE SALGRADE;
+DROP TABLE DUMMY;
+
+CREATE TABLE EMP
+ (EMPNO NUMBER(4) NOT NULL,
+ ENAME VARCHAR2(10),
+ JOB VARCHAR2(9),
+ MGR NUMBER(4),
+ HIREDATE DATE,
+ SAL NUMBER(7,2),
+ COMM NUMBER(7,2),
+ DEPTNO NUMBER(2));
+
+INSERT INTO EMP VALUES
+ (7369,'SMITH','CLERK',7902,'17-DEC-80',800,NULL,20);
+INSERT INTO EMP VALUES
+ (7499,'ALLEN','SALESMAN',7698,'20-FEB-81',1600,300,30);
+INSERT INTO EMP VALUES
+ (7521,'WARD','SALESMAN',7698,'22-FEB-81',1250,500,30);
+INSERT INTO EMP VALUES
+ (7566,'JONES','MANAGER',7839,'2-APR-81',2975,NULL,20);
+INSERT INTO EMP VALUES
+ (7654,'MARTIN','SALESMAN',7698,'28-SEP-81',1250,1400,30);
+INSERT INTO EMP VALUES
+ (7698,'BLAKE','MANAGER',7839,'1-MAY-81',2850,NULL,30);
+INSERT INTO EMP VALUES
+ (7782,'CLARK','MANAGER',7839,'9-JUN-81',2450,NULL,10);
+INSERT INTO EMP VALUES
+ (7788,'SCOTT','ANALYST',7566,'09-DEC-82',3000,NULL,20);
+INSERT INTO EMP VALUES
+ (7839,'KING','PRESIDENT',NULL,'17-NOV-81',5000,NULL,10);
+INSERT INTO EMP VALUES
+ (7844,'TURNER','SALESMAN',7698,'8-SEP-81',1500,0,30);
+INSERT INTO EMP VALUES
+ (7876,'ADAMS','CLERK',7788,'12-JAN-83',1100,NULL,20);
+INSERT INTO EMP VALUES
+ (7900,'JAMES','CLERK',7698,'3-DEC-81',950,NULL,30);
+INSERT INTO EMP VALUES
+ (7902,'FORD','ANALYST',7566,'3-DEC-81',3000,NULL,20);
+INSERT INTO EMP VALUES
+ (7934,'MILLER','CLERK',7782,'23-JAN-82',1300,NULL,10);
+
+CREATE TABLE DEPT
+ (DEPTNO NUMBER(2),
+ DNAME VARCHAR2(14),
+ LOC VARCHAR2(13) );
+
+INSERT INTO DEPT VALUES
+ (10,'ACCOUNTING','NEW YORK');
+INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
+INSERT INTO DEPT VALUES
+ (30,'SALES','CHICAGO');
+INSERT INTO DEPT VALUES
+ (40,'OPERATIONS','BOSTON');
+
+CREATE TABLE BONUS
+ (
+ ENAME VARCHAR2(10),
+ JOB VARCHAR2(9),
+ SAL NUMBER,
+ COMM NUMBER
+ );
+
+CREATE TABLE SALGRADE
+ ( GRADE NUMBER,
+ LOSAL NUMBER,
+ HISAL NUMBER );
+
+INSERT INTO SALGRADE VALUES (1,700,1200);
+INSERT INTO SALGRADE VALUES (2,1201,1400);
+INSERT INTO SALGRADE VALUES (3,1401,2000);
+INSERT INTO SALGRADE VALUES (4,2001,3000);
+INSERT INTO SALGRADE VALUES (5,3001,9999);
+
+CREATE TABLE DUMMY
+ ( DUMMY NUMBER );
+
+INSERT INTO DUMMY VALUES (0);
+
+COMMIT;
+
+EXIT;
diff --git a/reladminif/test/demodrop.sql b/reladminif/test/demodrop.sql
new file mode 100644
index 0000000..282bf6d
--- /dev/null
+++ b/reladminif/test/demodrop.sql
@@ -0,0 +1,42 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+--
+-- $Header: /home/rasdev/CVS-repository/rasdaman/reladminif/test/demodrop.sql,v 1.3 2003/12/27 23:11:46 rasdev Exp $
+-- Copyright (c) Oracle Corporation 1988, 1993. All Rights Reserved.
+--
+--
+-- This script drops the SQL*Plus demonstration tables.
+--
+-- It should be STARTed by each owner of the tables.
+
+set termout on
+prompt Dropping demonstration tables. Please wait.
+set termout off
+
+DROP TABLE EMP;
+DROP TABLE DEPT;
+DROP TABLE BONUS;
+DROP TABLE SALGRADE;
+DROP TABLE DUMMY;
+
+EXIT;
diff --git a/reladminif/test/eoidtest.C b/reladminif/test/eoidtest.C
new file mode 100644
index 0000000..66aa0ee
--- /dev/null
+++ b/reladminif/test/eoidtest.C
@@ -0,0 +1,128 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "raslib/rmdebug.hh"
+#include <iostream.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "dbnamedobject.hh"
+#include "dbref.hh"
+#include "dbobject.hh"
+#include "oidif.hh"
+#include "adminif.hh"
+#include "databaseif.hh"
+#include "oidif.hh"
+#include "eoid.hh"
+#include "transactionif.hh"
+
+#include "alltypes.hh"
+#include "typefactory.hh"
+
+#include "dbmddcoll.hh"
+#include "dbmddcolloidentry.hh"
+#include "dbmddobj.hh"
+
+#include "raslib/rmdebug.hh"
+
+RMINITGLOBALS('C')
+
+int RManDebug2 = 8;
+int RManModule = 3;
+
+int
+main(int argc, char *argv[])
+ {
+ typedef map< EOId, string, less<EOId> > ap;
+ typedef pair< EOId, string > air;
+ ap* myMap = new ap();
+ AdminIf* myAdmin;
+ DatabaseIf database;
+ myAdmin = AdminIf::instance();
+ database.open("RMAN");
+ TransactionIf ta;
+ ta.begin(&database);
+
+ cout << "DBName " << database.getName() << endl;
+ cout << " or " << AdminIf::getCurrentDatabaseIf()->getName() << endl;;
+
+ OId* o = new OId(1, OId::BASETYPEOID);
+ EOId* e = new EOId("asys", "abase", 0L, 3);
+ string* s = new string("aa0");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("asys", "abase", 5L, 3);
+ s = new string("aa5");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("asys", "abase", 10L, 3);
+ s = new string("aa10");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("bsys", "abase", 0L, 3);
+ s = new string("ba0");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("bsys", "abase", 5L, 3);
+ s = new string("ba5");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("bsys", "abase", 10L, 3);
+ s = new string("ba10");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("asys", "bbase", 0L, 3);
+ s = new string("ab0");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("asys", "bbase", 5L, 3);
+ s = new string("ab5");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("asys", "bbase", 10L, 3);
+ s = new string("ab10");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("bsys", "bbase", 0L, 3);
+ s = new string("bb0");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("bsys", "bbase", 10L, 3);
+ s = new string("bb10");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("bsys", "bbase", 15L, 3);
+ s = new string("bb15");
+ myMap->insert(air(*e, *s));
+
+ e = new EOId("asys", "abase", 5L, 3);
+ s = new string("fuenf b");
+ myMap->insert(air(*e, *s));
+
+ int i = 0;
+ ap::iterator iter = myMap->begin();
+ for (; iter != myMap->end(); iter++)
+ {
+ i++;
+ cout << "Nummer " << i << " key " << (*iter).first << " value " << (*iter).second.c_str() << endl;
+ }
+ }
diff --git a/reladminif/test/indextest.cc b/reladminif/test/indextest.cc
new file mode 100644
index 0000000..fdcdfa9
--- /dev/null
+++ b/reladminif/test/indextest.cc
@@ -0,0 +1,227 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "mymalloc/mymalloc.h"
+#include <stdlib.h>
+#include <iostream>
+
+#include "chartype.hh"
+#include "cachetamgr/persmddcoll.hh"
+#include "cachetamgr/persmddobj.hh"
+#include "cachetamgr/perstile.hh"
+#include "cachetamgr/persmddcolliter.hh"
+
+#include "adminif.hh"
+#include "databaseif.hh"
+#include "transactionif.hh"
+#include "oidif.hh"
+
+#include "raslib/rminit.hh"
+#include "typefactory.hh"
+
+#include "dbmddobj.hh"
+#include "dbmddcoll.hh"
+
+#include "mddbasetype.hh"
+#include "mdddimensiontype.hh"
+#include "settype.hh"
+
+#ifndef BASEDB_O2
+#include "externs.h"
+#endif
+
+RMINITGLOBALS('C')
+#ifndef BASEDB_O2
+char* O2DBName = "RASBASE";
+#else
+char* O2DBName = "NorbertBase";
+#endif
+char *collName = "testColl";
+char defaultCollName[]= "ObjsContainer";
+
+#ifdef BASEDB_O2
+extern char* myExecArgv0 = "";
+#endif
+
+int
+main( int argc, char** argv)
+ {
+#ifdef BASEDB_O2
+ myExecArgv0 = argv[0];
+#endif
+ RManDebug = 3;
+#ifndef BASEDB_O2
+ RManModule = 0;
+#endif
+ RMInit::logOut = cout.rdbuf();
+ RMInit::dbgOut = cout.rdbuf();
+ RMInit::tileSize = 12;
+ MDDStorage::DefaultIxType = MDDStorage::RPlusTreeNode;
+
+ // variables representing O2 database, ta and session
+ DatabaseIf db;
+
+ // don't forget to initialize before using AdminIf!
+ AdminIf* myAdmin = AdminIf::instance();
+ TransactionIf ta;
+ // connect to the database
+ cout << "Connecting to database " << O2DBName << "..." << endl;
+ int errorDBOpen;
+ try {
+ errorDBOpen = db.open(O2DBName);
+ }
+ catch(...)
+ {
+ cout << "Caught Exception " << endl;
+ exit(-1);
+ }
+ ta.begin(&db);
+ int i = PersMDDColl::destroyRoot(collName, &db);
+ ta.commit();
+ ta.begin(&db);
+ const CollectionType* greyset = TypeFactory::mapSetType("GreySet");
+ MDDDimensionType* mddtype = (MDDDimensionType*)TypeFactory::mapMDDType("GreyCube");
+ if (!mddtype || !greyset)
+ {
+ cout << "didnt find types" << endl;
+ exit(-1);
+ }
+ OId oColl;
+ if (OId::allocateMDDCollOId(&oColl) == 0)
+ {
+ }
+ else
+ cout <<"Error allocating OId for collection " << endl;
+ PersMDDColl* col;
+ try {
+ // CollectionType* ct = TypeFactory::mapSetType("ObjsContainerType");
+ col = PersMDDColl::createRoot(collName, oColl, greyset, &db);
+ }
+ catch (...)
+ {
+ cout << "Error creating PersMDDColl" << endl;
+ exit(-1);
+ }
+
+ greyset = TypeFactory::mapSetType("GreySet3");
+ mddtype = (MDDDimensionType*)TypeFactory::mapMDDType("GreyCube");
+
+ OId oid1;
+ if (OId::allocateMDDOId(&oid1) == 0)
+ {
+
+ }
+ else
+ {
+ cout << "Error by allocation of OId" <<endl;
+ exit(1);
+ }
+
+ // read root object
+
+ PersMDDColl objsSet(collName);
+
+
+ // create MDD Object 1
+
+ r_Sinterval limits1Obj1(0l,100l);
+ r_Sinterval limits2Obj1(0l,100l);
+ r_Sinterval limits3Obj1(0l,100l);
+ r_Minterval dom(3);
+ dom << limits1Obj1 << limits2Obj1 << limits3Obj1;
+
+ PersMDDObj* MDDObj1 = new PersMDDObj(mddtype, dom, O2DBName, oid1);
+ cout << "created new persmddobj" << endl;
+
+ char* test = (char*)mymalloc((dom.cell_count() + 1) * mddtype->getBaseType()->getSize());
+ for (i = 0; i < 1000; i++)
+ test[i] = i%255;
+
+ dom[0].set_interval(0l,1l);
+ dom[1].set_interval(0l,1l);
+ dom[2].set_interval(0l,1l);
+ PersTile* tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test);
+ MDDObj1->insertTile(tile1Obj1);
+ cout << "1--------------" << endl;
+
+ dom[0].set_interval(2l,3l);
+ dom[1].set_interval(0l,1l);
+ dom[2].set_interval(0l,1l);
+ tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test);
+ MDDObj1->insertTile(tile1Obj1);
+ cout << "2--------------" << endl;
+
+ dom[0].set_interval(4l,5l);
+ dom[1].set_interval(0l,1l);
+ dom[2].set_interval(0l,1l);
+ tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test);
+ MDDObj1->insertTile(tile1Obj1);
+ cout << "3--------------" << endl;
+
+ dom[1].set_interval(0l,1l);
+ dom[0].set_interval(20l,21l);
+ dom[2].set_interval(0l,1l);
+ tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test);
+ MDDObj1->insertTile(tile1Obj1);
+ cout << "4--------------" << endl;
+
+ dom[1].set_interval(0l,1l);
+ dom[0].set_interval(22l,23l);
+ dom[2].set_interval(0l,1l);
+ tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test);
+ MDDObj1->insertTile(tile1Obj1);
+ cout << "5--------------" << endl;
+
+ dom[1].set_interval(0l,1l);
+ dom[0].set_interval(24l,25l);
+ dom[2].set_interval(0l,1l);
+ tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test);
+ MDDObj1->insertTile(tile1Obj1);
+ cout << "6--------------" << endl;
+
+ dom[1].set_interval(0l,1l);
+ dom[0].set_interval(10l,11l);
+ dom[2].set_interval(0l,1l);
+ tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test);
+ MDDObj1->insertTile(tile1Obj1);
+ cout << "7--------------" << endl;
+
+ dom[1].set_interval(0l,1l);
+ dom[0].set_interval(26l,27l);
+ dom[2].set_interval(0l,1l);
+ tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test);
+ MDDObj1->insertTile(tile1Obj1);
+ cout << "8--------------" << endl;
+
+ objsSet.insert(MDDObj1);
+
+ r_Point po("[10,0,1]");
+ char* utest = MDDObj1->pointQuery(po);
+ if (utest)
+ cout << "works" << endl;
+ else
+ cout << "failure" << endl;
+ ta.commit();
+ db.close();
+ }
+
+
diff --git a/reladminif/test/perstest.C b/reladminif/test/perstest.C
new file mode 100644
index 0000000..118fcf4
--- /dev/null
+++ b/reladminif/test/perstest.C
@@ -0,0 +1,1155 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include "mymalloc/mymalloc.h"
+#define TEST_PROTECTED
+#define TEST_PRIVATE
+
+#include <stdlib.h>
+#include <iostream.h>
+
+#include "ulongtype.hh"
+#include "cachetamgr/persmddcoll.hh"
+#include "cachetamgr/persmddobj.hh"
+#include "cachetamgr/perstile.hh"
+#include "cachetamgr/persmddcolliter.hh"
+
+#include "adminif.hh"
+#include "databaseif.hh"
+#include "transactionif.hh"
+#include "oidif.hh"
+
+#include "raslib/rminit.hh"
+#include "typefactory.hh"
+
+#include "dbmddobj.hh"
+#include "dbmddcoll.hh"
+
+#include "mddbasetype.hh"
+#include "mdddomaintype.hh"
+#include "settype.hh"
+
+#include "externs.h"
+
+
+
+/*
+ Global Variables
+*/
+
+RMINITGLOBALS('C')
+
+static char* O2DBName;
+char *collName;
+char defaultCollName[]= "ObjsContainer";
+OId globalOId1, globalOId2;
+OId globalCollOId;
+EOId globalEOId[4];
+int numObjsCreated;
+TransactionIf ta;
+int ExitNo;
+
+/*
+ Functions
+*/
+
+int
+getOption( )
+{
+ unsigned int result;
+ cout << endl;
+ cout << "Choose Option : " << endl;
+ cout << "-----------------------------------------------------------------"<<endl;
+ cout << " 1 - Create MDD collection with name .. " << collName << endl;
+ cout << " 2 - Populate collection with MDD objects (testConstructors) " << endl;
+ cout << " 3 - Access MDD collection given name (testAccessing) " << endl;
+ cout << " 4 - Access MDD collection given OId (testAccessing)" << endl;
+ cout << " 5 - Access MDD object given OId (testAccessingMDDObj) " << endl;
+ cout << " 6 - Remove MDD object from the collection given OId (testRemove) "<<endl;
+ cout << " 7 - Test PersMDDObj::intersect( ) (testSearch) " <<endl;
+ cout << " 8 - Test PersMDDColl::getCardinality( ) "<<endl;
+ cout << " 9 - Test PersMDDObj get functions "<< endl;
+ cout << " 10 - Remove MDD Collection given OId " << endl;
+ cout << " 11 - Insert MDD given OId in a second collection "<< endl;
+ cout << " 12 - Insert tile in MDD given OId "<< globalOId1 <<endl;
+ cout << " 13 - Test removeTile from MDD "<< globalOId1 << endl;
+ ExitNo = 14;
+ cout << " " << ExitNo << " - Exit " << endl;
+ cout << "------------------------------------------------------------------"<<endl;
+ cout << "Enter option: ";
+ cin >> result;
+ switch (result)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ return result;
+ break;
+ default:
+ return getOption();
+ }
+}
+
+// 1 - Create MDD collection
+static int createMDDColl( const char* collName, DatabaseIf* db );
+
+// 2 - Populate collection with MDD objects
+static void testConstructors( char* cn );
+
+// 3 - Retrieves an MDD collection with name cn and prints contents:
+static void testAccessing( char* cn );
+
+// 4 - Retrieves an MDD collection with OId o and prints contents:
+static void testAccessing( OId o );
+
+// 5 - Retrieves an MDD object with OId o and prints contents:
+static void testAccessingMDDObj( OId o );
+
+// Removes one of the MDD objects in the collection
+static void testRemove( );
+
+// 6 - Removes MDD object with OId o in the collection
+static void testRemove( OId o );
+
+// 7 - Test PersMDDObj::intersect( ) objects of the collection
+static void testSearch( );
+
+// 8 - Test PersMDDColl::getCardinality( )
+static void testGetCardinality( char* cn);
+
+// 9 - Scans collection and tests PersMDDObj get functions
+static void testGetFunctions( );
+
+//10 - Remove MDD collection given OId
+
+//11 - Insert MDD given OId in a second collection
+static void testInsertMDDObjColl( OId o, char* cn );
+
+//12 - Test later insertion of tile in PersMDDObj
+static void testLaterInsert( OId o );
+
+//13 - Test removeTile from an MDD obj
+static void testRemoveTile( OId o );
+
+// Tries accessing several OIds, including ilegal ones, to test
+// several error conditions.
+static void testAccessingOId( );
+
+
+/*************************************************************
+ * Function name.: int main( int argc, char** argv)
+ *
+ * Arguments.....:
+ * argc: number of arguments given to program
+ * argv: array of char* with arguments
+ * Return value..: exit status
+ * Description...: none
+ ************************************************************/
+int
+main( int argc, char** argv)
+{
+RManDebug = 10;
+RManModule = 0;
+RMInit::logOut = cout.rdbuf();
+RMInit::dbgOut = cout.rdbuf();
+RMInit::tileSize = 12;
+MDDStorage::DefaultIxType = MDDStorage::RPlusTreeNode;
+
+ // variables representing O2 database, ta and session
+ DatabaseIf database;
+
+ if( argc < 2 ) {
+ cout << "Usage: test_persmddcoll <database> [collName]" << endl;
+ return -1;
+ }
+ O2DBName = strdup( argv[1] );
+ if ( argc == 3 ) collName = strdup( argv[2] );
+ else
+ collName = defaultCollName;
+
+ // don't forget to initialize before using AdminIf!
+ AdminIf* myAdmin = AdminIf::instance();
+
+
+ // connect to the database
+ cout << "Connecting to database " << O2DBName
+ << "..." << endl;
+ int errorDBOpen;
+ try{
+ errorDBOpen = database.open( O2DBName );
+ }
+ catch( ...)
+ {
+ cout << "Caught Exception " << endl;
+ errorDBOpen = -6;
+ }
+ if ( errorDBOpen < 0 )
+ {
+ cout << "Database doesn't exist. Create it new ... " << endl;
+ cout << "Creating new database " << O2DBName
+ << "..." << endl;
+ database.create( O2DBName, "TestSMSchema" );
+ cout << "Connecting to database " << O2DBName
+ << "..." << endl;
+ try{
+ errorDBOpen = database.open( O2DBName );
+ }
+ catch(...)
+ {
+ errorDBOpen = -6;
+ }
+ }
+ if ( errorDBOpen < 0 )
+ {
+ cout << "Failed at opening newly created database " << errorDBOpen << endl;
+ cout << "Exiting " << endl;
+ return errorDBOpen;
+ }
+
+ ta.begin( &database );
+ cout << endl << "Deleting root object from the database ..." <<endl;
+ int i = PersMDDColl::destroyRoot( collName, &database );
+ cout << " i == " << i << endl;
+ // cout << " &database = " << long( &database) << endl;
+ ta.commit( );
+
+ char c;
+ int error;
+
+ for( unsigned opt = getOption( ); opt != ExitNo ; opt = getOption( ) )
+ {
+ cout <<"Transaction begin ... " << endl;
+ ta.begin( &database );
+ switch ( opt )
+ {
+ case 1: // 1 - Create MDD collection with name
+ // create root collection
+ cout << endl << "Creating mdd types and root collection..." << endl;
+ if ( createMDDColl( collName, &database ) != 0 )
+ {
+ cout <<"Error caught ................."<< endl;
+ cout << endl << "Ending O2 session..." << endl;
+ ta.commit( );
+ database.close( );
+ delete myAdmin;
+ exit( 1 );
+ }
+ break;
+
+ case 2: // 2 - Populate collection with MDD objects (testConstructors)
+ // create objects and put them in the collection
+ cout << endl << "Populate collection ..." << endl;
+ testConstructors( collName );
+ break;
+
+ case 3: // 3 - Access MDD collection given name (testAccessing)
+ // read coll and print contents
+ cout << endl << "Read collection " << collName << " and print contents..." << endl;
+ testAccessing( collName );
+ break;
+
+ case 4: // 4 - Access MDD collection given OId (testAccessing)
+ cout << endl << "Read collection " << globalCollOId << " and print contents..." << endl;
+ testAccessing( globalCollOId );
+ break;
+
+ case 5: // 5 - Access MDD object given OId (testAccessingMDDObj)
+ cout << endl << "Test Accessing MDD with OId " << globalOId1 << " ... " << endl;
+ testAccessingMDDObj( globalOId1 );
+ break;
+
+ case 6: // 6 - Remove MDD object from the collection given OId (testRemove)
+ cout<< endl << "Remove MDD with OId " << globalOId1 << " ..." << endl;
+ testRemove( globalOId1 );
+ break;
+
+ case 7: // 7 - Test PersMDDObj::intersect( ) (testSearch)
+ cout << endl << "Test region search ..." << endl;
+ testSearch( );
+ break;
+
+ case 8: // 8 - Test PersMDDColl::getCardinality( )
+ cout << endl << "Get cardinality of collection" << collName <<" ..." << endl;
+ testGetCardinality( collName );
+ break;
+
+ case 9: // 9 - Test PersMDDObj get functions
+ cout << endl <<"Test PersMDDObj get functions " << endl;
+ testGetFunctions( );
+ break;
+
+ case 10: // 10 - Remove MDD Collection given OId
+ cout << endl << "Remove MDD collection with OId ";
+ cout << globalCollOId << " ..." << endl;
+ error = PersMDDColl::destroyRoot( globalCollOId, &database );
+ if (error )
+ cout << " Error destroying root " << endl;
+ break;
+
+ case 11: // 11 - Insert MDD given OId in a second collection
+ cout << endl << "Insert Object with OId " << globalOId1;
+ cout << " in collection Coleccao1 " << endl;
+ cout << "First, create collection" << endl;
+ if ( createMDDColl( "Coleccao1", &database ) != 0 )
+ {
+ cout <<"Error caught ................."<< endl;
+ cout << endl << "Ending O2 session..." << endl;
+ ta.commit( );
+ database.close( );
+ delete myAdmin;
+ exit( 1 );
+ }
+ cout << "Then insert object with OId "<< globalOId1 << endl;
+ testInsertMDDObjColl( globalOId1 , "Coleccao1");
+ cout << endl;
+ break;
+
+ case 12: // 12 - Insert new tiles in the MDD object
+ cout << endl << "Insert Tile in object with OId " << globalOId1;
+ testLaterInsert( globalOId1 );
+ cout << endl;
+ break;
+
+ case 13: // 13 - Remove a tile from the MDD object
+ cout << endl << "Remove Tile from object with OId " << globalOId1;
+ testRemoveTile( globalOId1 );
+ cout << endl;
+ break;
+
+ default:
+ break;
+ }
+ cout <<"Transaction abort (A/a) or commit (default)? ";
+ cin >> c;
+ if ( c == 'A' || c == 'a' )
+ {
+ ta.abort( );
+ cout <<"End of Transaction Abort..."<<endl;
+ }
+ else
+ {
+ ta.commit( );
+ cout <<"End of Transaction Commit..."<<endl;
+ }
+ if ( opt == 6 )
+ {
+ cout<<"Garbage ? ( y /n ) ";
+ cin >> c;
+ if (c =='y' || c == 'Y' )
+ {
+ cout <<"Garbaging ..."<< endl;
+ ta.begin( &database );
+ database.garbage( );
+ ta.commit( );
+ }
+ }
+ cout <<"End of transaction commit... "<<endl;
+ } // for opt
+
+
+ cout << endl << "Ending O2 session..." << endl;
+ database.close( );
+ delete myAdmin;
+
+ free( O2DBName );
+ if ( collName != defaultCollName ) free( collName );
+ return 0;
+
+}
+
+/*************************************************************
+ * Functions......:
+ *
+ * static void
+ * testInsertMDDObjColl( OId o, char* cn )
+ *
+ * static void
+ * testConstructors( char* collName )
+ *
+ ************************************************************/
+static void
+testInsertMDDObjColl( OId o, char* cn )
+{
+ cout << "....testInsertMDDObjColl "<< o <<","<< cn << endl;
+ PersMDDObj* obj = new PersMDDObj( O2DBName,o );
+ PersMDDColl objsSet( cn );
+ objsSet.insert( obj );
+ delete obj;
+
+}
+
+static void testConstructors( char* collName )
+{
+
+ const BaseType* ulongTypeObj = TypeFactory::mapType("ULong");
+ const BaseType* boolTypeObj = TypeFactory::mapType("Bool");
+ const MDDBaseType* mType1 = (const MDDBaseType* ) TypeFactory::mapMDDType("TestSMDomainType2D");
+ const MDDBaseType* mType2 = (const MDDBaseType* ) TypeFactory::mapMDDType("TestSMDomainType3D");
+
+ cout << "....testConstructors"<< endl;
+
+ OId oid1;
+ if ( OId::allocateMDDOId( &oid1 ) == 0)
+ cout << "Successfull allocation of OId " << oid1 <<endl;
+ else
+ {
+ cout << "Error by allocation of OId" <<endl;
+ exit(1);
+ }
+ OId oid2;
+ if ( OId::allocateMDDOId( &oid2 ) == 0)
+ cout << "Successfull allocation of OId " << oid2 <<endl;
+ else
+ {
+ cout << "Error by allocation of OId" <<endl;
+ exit(1);
+ }
+
+ globalOId1 = oid1;
+ globalOId2 = oid2;
+
+ // read root object
+
+ PersMDDColl objsSet(collName);
+
+
+ // create MDD Object 1
+
+ cout << "Creating mddObj1" << endl;
+ cout << "tile 1 = nil, 10-12, 20-24 "<< endl;
+ r_Sinterval limits1Obj1(10l,12l);
+ r_Sinterval limits2Obj1(20l,24l);
+ r_Minterval dom(2);
+ dom << limits1Obj1 << limits2Obj1;
+
+ r_Minterval tmpInt = *( ( MDDDomainType* ) mType1 )->getDomain( );
+ PersMDDObj* MDDObj1 = new PersMDDObj( mType1, tmpInt, O2DBName, oid1 );
+
+ char* test = (char*)mymalloc((dom.cell_count() + 1) * 4);
+ memset(test, 0, (dom.cell_count() + 1) * 4);
+ cout << "created new persmddobj" << endl;
+ PersTile* tile1Obj1 = new PersTile( dom, ulongTypeObj, test );
+ cout << "created new perstile" << endl;
+ MDDObj1->insertTile(tile1Obj1);
+ cout << "inserted tile" << endl;
+
+ cout << "tile 2 = nil, 0-400, 22-24 "<< endl;
+ dom[0].set_interval(0l,400l);
+ dom[1].set_interval(22l,24l);
+ test = (char*)mymalloc((dom.cell_count() + 1) * 4);
+ memset(test, 0, (dom.cell_count() + 1) * 4);
+ cout << "created new perstile" << endl;
+ PersTile* tile2Obj1 = new PersTile( dom, ulongTypeObj, test );
+ cout << "insert tile" << endl;
+ MDDObj1->insertTile(tile2Obj1);
+ cout << "inserted tile" << endl;
+
+ cout << "tile 3 = nil, 0-600, 10-1000 "<< endl;
+ dom[0].set_interval(0l,600l);
+ dom[1].set_interval(10l,1000l);
+ test = (char*)mymalloc((dom.cell_count() + 1) * 4);
+ memset(test, 0, (dom.cell_count() + 1) * 4);
+ cout << "created new perstile" << endl;
+ PersTile* tile3Obj1 = new PersTile( dom, ulongTypeObj, test );
+ cout << "insert tile" << endl;
+ MDDObj1->insertTile(tile3Obj1);
+ cout << "inserted tile" << endl;
+
+ cout << "MDDObj1 == isPersistent:" << MDDObj1->isPersistent( )<< ";" <<endl;
+ MDDObj1->printStatus( );
+ cout << endl;
+
+ objsSet.insert(MDDObj1);
+
+ // create MDD Object
+ cout << "Creating mddObj2 "<< endl;
+ cout << "tile 1 = nil, 0-19, 20-59, 30-59 "<< endl;
+ r_Sinterval limits1Obj2(0l,19l);
+ r_Sinterval limits2Obj2(20l,59l);
+ r_Sinterval limits3Obj2(30l,59l);
+ r_Minterval dom2(3);
+ dom2 << limits1Obj2 << limits2Obj2 << limits3Obj2;
+
+ tmpInt = *( ( MDDDomainType* ) mType2 )->getDomain( );
+ PersMDDObj* MDDObj2 = new PersMDDObj( mType2, tmpInt, O2DBName, oid2 );
+
+ test = (char*)mymalloc((dom.cell_count() + 1) * 1);
+ memset(test, 0, (dom.cell_count() + 1) * 1);
+ PersTile* tile1Obj2 = new PersTile( dom2, boolTypeObj, test);
+ MDDObj2->insertTile( tile1Obj2 );
+
+ cout << "tile 2 = nil, 20-39, 60-79, 60-89 "<< endl;
+ dom2[0].set_interval(20l,39l);
+ dom2[1].set_interval(60l,79l);
+ dom2[2].set_interval(60l,89l);
+ test = (char*)mymalloc((dom.cell_count() + 1) * 1);
+ memset(test, 0, (dom.cell_count() + 1) * 1);
+ PersTile* tile2Obj2 = new PersTile( dom2, boolTypeObj, test);
+
+ MDDObj2->insertTile(tile2Obj2);
+
+
+ cout << "MDDObj2 == isPersistent:" << MDDObj2->isPersistent( )<< ";" <<endl;
+ MDDObj2->printStatus( );
+ cout << endl;
+
+/*
+ // This program doesn't work if the TA is aborted when OIds are
+ // allocated, even if all allocated OIds are binded. Question: is it
+ // because of dangling handles? This little test was done to
+ // check that.
+ // This without oids works with ta.abort
+ // conclusion: the problem with abort is not due to the handles
+ Handle hd;
+ d_Ref<DBMDDObj> refObj = MDDObj2->getDBMDDObjId();
+ hd = refObj.o2_get_handle();
+*/
+
+
+ objsSet.insert(MDDObj2);
+ numObjsCreated = 2;
+
+ cout << "Release all " << endl;
+
+ //( ( PersMDDColl ) objsSet ).releaseAll( );
+
+ cout << "Release all END" << endl;
+}
+
+
+/*************************************************************
+ * Function......: testAccessing( char* cn )
+ * testAccessing( OId o )
+ ************************************************************/
+
+static void testAccessing( char* cn )
+{
+ PersMDDObj* accessedObj;
+
+ cout << "....testAccessing collection "<< cn << endl;
+
+ try{
+ PersMDDColl objsSet( cn );
+
+ // To test PersMDDColl::printStatus( )
+ // objsSet.printStatus( );
+
+ // To test PersMDDObj::printStatus( ), MDDCollIter::createIterator( ) and
+ // MDDCollIter methods :
+
+ cout << "Iterating through the collection with PersMDDCollIter " << endl;
+ MDDCollIter* objsIt = objsSet.createIterator( );
+
+ for( int i = 1 ; objsIt->notDone( ); i++, objsIt->advance( ))
+ {
+ cout << i<<". MDD object in set:" << endl;
+ accessedObj = (PersMDDObj*) objsIt->getElement();
+ accessedObj->printStatus();
+ EOId eoid;
+ if ( accessedObj->getEOId( &eoid ) ==0 )
+ cout <<"EOId: " << eoid;
+ // old version cout <<"EOId: " << eoid.getSystemName( ) << eoid.getBaseName( ) << eoid.getOId( );
+ cout << endl << endl;
+ accessedObj->getEOId( &globalEOId[i-1] );
+ }
+ delete objsIt;
+ objsSet.releaseAll( );
+ }
+ catch ( r_Error& errObj)
+ {
+ cout <<"Error caught ................."<< endl;
+ }
+}
+
+static void testAccessing( OId o )
+{
+ PersMDDObj* accessedObj;
+
+ cout << "....testAccessing collection "<< o << endl;
+
+ try {
+ PersMDDColl objsSet( o, O2DBName );
+
+ OId o;
+ if ( objsSet.getOId( &o ) == 0 )
+ cout <<"getOId " << o << endl;
+ else
+ cout <<"Error getOId " << endl;
+
+ EOId eo;
+ if ( objsSet.getEOId( &eo ) == 0 )
+ cout << "getEOId " << eo <<endl;
+ // cout << "getEOId " << eo.getSystemName( ) <<":"<<eo.getBaseName( )<<":"<<eo.getOId( ) << endl;
+ else
+ cout <<"Error getEOId " << endl;
+
+ // To test PersMDDColl::printStatus( )
+ objsSet.printStatus( );
+
+ // To test PersMDDObj::printStatus( ), MDDCollIter::createIterator( ) and
+ // MDDCollIter methods :
+
+ cout << "Iterating through the collection with PersMDDCollIter " << endl;
+ MDDCollIter* objsIt = objsSet.createIterator( );
+
+ for( int i = 1 ; objsIt->notDone( ); i++, objsIt->advance( ))
+ {
+ cout << i<<". MDD object in set:" << endl;
+ accessedObj = (PersMDDObj*) objsIt->getElement();
+ accessedObj->printStatus();
+ EOId eoid;
+ if ( accessedObj->getEOId( &eoid ) ==0 )
+ cout <<"EOId: " << eoid ;
+ // cout <<"EOId: " << eoid.getSystemName( ) << eoid.getBaseName() << eoid.getOId( );
+ cout << endl << endl;
+ accessedObj->getEOId( &globalEOId[i-1] );
+ }
+ delete objsIt;
+ objsSet.releaseAll( );
+ }
+ catch ( r_Error& errObj)
+ {
+ cout <<"Error caught ................."<< endl;
+ }
+
+}
+
+/*************************************************************
+ * Function......: testAccessingMDDObj(OId o )
+ * testAccessingOId( )
+ *
+ ************************************************************/
+static void testAccessingMDDObj(OId o)
+{
+ PersMDDObj *mObj;
+
+ cout << "....testAccessingMDDObj"<<endl;
+
+ try{
+ mObj = new PersMDDObj( O2DBName, o);
+ mObj->printStatus( );
+ delete mObj;
+ }
+ catch (...)
+ {
+ cout <<" Object not found..." << endl;
+
+ }
+}
+
+static void testAccessingOId()
+{
+ PersMDDObj *mObj1, *mObj2, *mObj;
+ int result;
+ OId o(70000);
+ OId o1(5010);
+ OId o2(0);
+ OId o3(5);
+
+ cout << "....testAccessingOId"<<endl;
+
+
+ cout << "Test OIdIf::getType( )..."<<endl;
+ cout << "1.st MDDObj " << endl;
+ cout << "getType " << globalOId1.getType( O2DBName ) << endl;
+
+ cout << "2.nd MDDObj " << endl;
+ cout << "getType " << globalOId2.getType( O2DBName ) << endl;
+
+ // This crashes
+ // cout << "OId == 0 " << endl;
+ // cout << "getType " << o2.getType( O2DBName ) << endl;
+
+ cout << "OId == 5 " << endl;
+ cout << "getType " << o3.getType( O2DBName ) << endl;
+
+ cout << "MDDCollection " << endl;
+ cout << "getType " << globalCollOId.getType( O2DBName ) << endl;
+ // mObj2 = new PersMDDObj( O2DBName, globalOId2);
+ // mObj2->printStatus( );
+
+ cout << "Not used OId " << endl;
+ cout << "getType " << o1.getType( O2DBName ) << endl;
+
+ cout << "Nonexistent OId " << endl;
+ cout << "getType " << o.getType( O2DBName ) << endl;
+ // mObj2 = new PersMDDObj( O2DBName, globalOId2);
+ // mObj2->printStatus( );
+
+ cout <<"Loading PersMDDObjs from OIds " << endl;
+ mObj1 = new PersMDDObj( O2DBName, globalOId1);
+ mObj1->printStatus( );
+ mObj2 = new PersMDDObj( O2DBName, globalOId2);
+ mObj2->printStatus( );
+
+ delete mObj1;
+ delete mObj2;
+
+
+ for ( int i = 0; i < numObjsCreated; i++ )
+ {
+ cout << "Reading with " << i+1<< ".th EOId " ;
+ cout << globalEOId[i];
+ // cout << globalEOId[i].getSystemName( );
+ // cout << " ; "<< globalEOId[i].getBaseName( ) << ";" << globalEOId[i].getOId( );
+ cout << endl;
+
+
+ // result = o2_externalNameGetObject( &globalEOId[i], &hdObj );
+/*
+ result = globalEOId[i].getObject( &hdObj );
+ if ( result == 0 )
+ {
+ DBMDDObjId obj1(hdObj);
+ mObj = new PersMDDObj(obj1);
+ mObj->printStatus( );
+ }
+ else
+ cout << "No such object!!" << endl;
+ // o2_unref_handle( );
+ delete mObj;
+*/
+ }
+
+}
+
+/*************************************************************
+ * Function......: testLaterInsert()
+ *
+ ************************************************************/
+
+static void testLaterInsert( OId o )
+{
+ PersMDDObj* accessedObj;
+
+ cout << "....testLaterInsert"<<endl;
+
+ try{
+ accessedObj = new PersMDDObj( O2DBName, o);
+ }
+ catch (...)
+ {
+ cout <<" Object not found..." << endl;
+ return;
+ }
+
+ cout << "Current status of MDD object : " << endl;
+ accessedObj->printStatus( );
+ cout << endl << "Inserting new Tile ..."<< endl;
+
+ PersTile *t, *t2, *t3;
+ switch( accessedObj->getDimension( ) )
+ {
+ case 2 :
+ t2 = new PersTile( r_Minterval("[40:60,80:1200]"),
+ accessedObj->getCellType( ) );
+ t = t2;
+ break;
+ case 3 :
+ t3 = new PersTile(r_Minterval("[40:60,80:100,0:20]"),
+ accessedObj->getCellType( ) );
+ t = t3;
+ break;
+ default:
+ cout << "Error Dimensionality not expected" << endl;
+ break;
+ }
+ accessedObj->insertTile(t);
+ cout << " New status after insertion:" << endl;
+ accessedObj->printStatus();
+ cout << endl << endl;
+
+ delete accessedObj;
+}
+
+
+/*************************************************************
+ * Function......: testSearch()
+ *
+ ************************************************************/
+static void testSearch()
+{
+
+ MDDObj* accessedObj;
+
+ cout << "....testSearch"<<endl;
+
+ PersMDDColl objsSet(collName);
+
+ MDDCollIter* objsIt = objsSet.createIterator( );
+
+ for( int i = 1 ; objsIt->notDone( ); i++, objsIt->advance( ))
+ {
+ accessedObj = objsIt->getElement();
+
+ cout << "Accessed Object " << endl;
+ accessedObj->printStatus( );
+ cout << endl;
+
+ if (i == 1 || i == 2)
+ {
+ r_Minterval searchInt1(2);
+ r_Minterval searchInt2(3);
+ vector< Tile* >* entriesList;
+
+ cout << " -- " << i << ". MDD object in list. Search for:";
+ switch (i) {
+ case 1: searchInt1[0].set_interval(10l,20l);
+ searchInt1[1].set_interval(10l,30l);
+ cout << " 10-20, 10-30" << endl;
+ entriesList = accessedObj->intersect(searchInt1);
+ break;
+ case 2: searchInt2[0].set_interval(10l,20l);
+ searchInt2[1].set_interval(10l,30l);
+ searchInt2[2].set_interval(40l,50l);
+ cout << " 10-20, 10-30, 40-50" <<endl;
+ entriesList = accessedObj->intersect(searchInt2);
+ break;
+ default: break;
+ }
+ cout << " -- Search result: " << endl;
+ vector<Tile*>::iterator entryIt = entriesList->begin();
+
+ while (entryIt != entriesList->end())
+ {
+ // (*entryIt)->printStatus();
+ r_Minterval tileInterval = (*entryIt)->getDomain();
+ int dimensionality = tileInterval.dimension();
+
+ cout << " PersTile printStatus";
+ cout << " domain == " << dimensionality << ": ";
+ for (int i = 0; i <dimensionality; i++)
+ cout << tileInterval[i].low() << "-"
+ << tileInterval[i].high() <<", ";
+ cout << endl;
+
+ entryIt++;
+ }
+ delete entriesList;
+ }
+ }
+ delete objsIt;
+ // objsSet.releaseAll( );
+}
+
+/*************************************************************
+ * Function......: testRemoveTile(OId o )
+ *
+ ************************************************************/
+static void testRemoveTile(OId o)
+{
+ PersMDDObj *mObj;
+
+ cout << "....testRemoveTile from MDD Obj "<< o << endl;
+
+ try{
+ mObj = new PersMDDObj( O2DBName, o);
+ mObj->printStatus( );
+ }
+ catch (...)
+ {
+ cout <<" Object not found..." << endl;
+ return;
+ }
+
+ vector<Tile*>* tiles = mObj->getTiles( );
+
+ if ( tiles->size( ) == 0 )
+ {
+ cout <<"MDD object has no tiles !! "<< endl;
+ return;
+ }
+ else
+ {
+ int ix = tiles->size( )/2;
+
+ cout << "Removing "<< ix <<". tile from MDD Obj "<< endl;
+ cout << "Tile Description: " << (*tiles)[ix]->getDomain( ) << endl;
+
+ PersTile* t = (PersTile*) (*tiles)[ix];
+
+ mObj->removeTile( (*tiles)[ix] );
+
+ delete tiles;
+ delete mObj;
+ }
+}
+
+/*************************************************************
+ * Function......: testGetCardinality( const char* cn )
+ * testGetFunctions()
+ *
+ ************************************************************/
+static void testGetCardinality( char* cn )
+{
+ cout << "....testGetCardinality( "<< cn << " )" << endl;
+
+ try{
+ PersMDDColl objsSet( cn );
+ cout<< "Cardinality of collection " << objsSet.getCardinality( ) <<endl;
+ }
+ catch( r_Error& errObj)
+ {
+ cout <<"Error caught ................."<< endl;
+ }
+}
+
+static void testGetFunctions()
+{
+ PersMDDObj* accessedObj;
+
+ cout << "....testGetFunctions"<<endl;
+
+ PersMDDColl objsSet(collName);
+
+ MDDCollIter* objsIt = objsSet.createIterator( );
+
+ vector< Tile* >* entriesList;
+
+ for( int i = 1 ; objsIt->notDone( ); i++, objsIt->advance( ))
+ {
+ r_Minterval currDom;
+ r_Minterval defDom;
+
+ cout << " " << i << ". Object" << endl;
+ accessedObj = (PersMDDObj*) objsIt->getElement();
+
+
+ defDom = accessedObj->getDefinitionDomain( );
+ cout << " GetDefinitionDomain result: ";
+ defDom.print_status( );
+ cout << endl;
+
+ currDom = accessedObj->getCurrentDomain( );
+ cout << " GetCurrentDomain result: ";
+ currDom.print_status( );
+ cout << endl;
+
+ entriesList = accessedObj->getTiles( );
+ cout << " -- GetTiles result: " << endl;
+ vector<Tile*>::iterator entryIt = entriesList->begin();
+
+ while (entryIt != entriesList->end())
+ {
+ // (*entryIt)->printStatus();
+ r_Minterval tileInterval = (*entryIt)->getDomain();
+ int dimensionality = tileInterval.dimension();
+
+ cout << " PersTile ";
+ cout << " domain == " << dimensionality << ": ";
+ for (int i = 0; i <dimensionality; i++)
+ cout << tileInterval[i].low() << "-" << tileInterval[i].high() <<", ";
+ cout << endl;
+ entryIt++;
+ }
+ delete entriesList;
+ }
+ delete objsIt;
+ objsSet.releaseAll( );
+}
+
+/*************************************************************
+ * Function......: testRemove()
+ * testRemove( OId o )
+ *
+ ************************************************************/
+
+static void testRemove()
+{
+ PersMDDObj* accessedObj;
+
+ cout << "....testRemove"<<endl;
+
+ PersMDDColl objsSet(collName);
+ // PersMDDColl objsSet("Qualquercoisa");
+ // To test PersMDDColl::printStatus and PersMDDColl::remove
+
+
+ MDDCollIter* objsIt = objsSet.createIterator( );
+
+ cout << "-- Remove second element from collection " << endl;
+
+ for( int i = 1 ; objsIt->notDone( ) && i < 2; i++, objsIt->advance( ))
+ {
+ accessedObj = (PersMDDObj*) objsIt->getElement();
+ }
+ cout << "Delete of objsIt:" << endl;
+ delete objsIt;
+ cout << "Finished Delete of objsIt." << endl;
+ cout << "Remove accessedObj:" << endl;
+ objsSet.remove( accessedObj );
+ cout << "Finished Remove accessedObj." << endl;
+}
+
+static void testRemove( OId o )
+{
+
+ cout << "....testRemove( OId == " << o <<" ) "<< endl;
+
+ PersMDDColl objsSet(collName);
+ objsSet.remove( o, O2DBName );
+}
+
+
+/*************************************************************
+ * Function......: createMDDColl( )
+ ************************************************************/
+static int
+createMDDColl( const char* collName, DatabaseIf* db )
+{
+cout << "createMDDColl(" << collName << ", " << db->getName() << ")" << endl;
+ MDDDomainType* mType1 = 0;
+ MDDDomainType* mType2 = 0;
+ MDDType* mt = 0;
+ CollectionType* collType1 = 0;
+
+ const BaseType* ulongTypeObj = TypeFactory::mapType("ULong");
+
+ const MDDDomainType* cmType1 =
+ ( MDDDomainType* ) TypeFactory::mapMDDType( "TestSMDomainType2D" );
+ if (cmType1)
+ cout << "cmType1 " << cmType1->getName() << endl;
+ const MDDDomainType* cmType2 =
+ ( MDDDomainType* ) TypeFactory::mapMDDType( "TestSMDomainType3D" );
+ if (cmType2)
+ cout << "cmType1 " << cmType2->getName() << endl;
+
+ const CollectionType* collType =
+ (CollectionType*)TypeFactory::mapSetType( "ObjsContainerType" );
+ if (collType)
+ cout << "collType " << collType->getName() << endl;
+
+
+ if( !cmType1 || !cmType2 || !collType )
+ {
+ cout << "types not found!" << endl;
+ char name1[] = "TestSMDomainType2D";
+ char name2[] = "TestSMDomainType3D";
+
+ r_Sinterval limits1Obj1(0l,1000l);
+ r_Sinterval limits2Obj1(0l,800l);
+ r_Minterval dom1(2);
+ dom1 << limits1Obj1 << limits2Obj1;
+ cout << "MDD Type 1 , domain "<< dom1 << endl;
+
+ cout << " tile 1 = nil, 0-19, 20-59, 30-59 "<< endl;
+ r_Sinterval limits1Obj2(0l,19l);
+ r_Sinterval limits2Obj2(20l,59l);
+ r_Sinterval limits3Obj2(30l,59l);
+ r_Minterval dom2(3);
+ dom2 << limits1Obj2 << limits2Obj2 << limits3Obj2;
+ cout << "MDD Type 2 , domain "<< dom2 << endl;
+
+ // MDDDomainType* mType1 =
+ mType1 =
+ new MDDDomainType((char*) name1, ( BaseType* ) ulongTypeObj, dom1 );
+ // MDDDomainType* mType2 =
+ mType2 =
+ new MDDDomainType((char*) name2, ( BaseType* ) ulongTypeObj, dom2 );
+
+ cout << "MDD Type1 == ";
+ mType1->print_status( cout );
+ cout << endl;
+ cout << "MDD Type2 == ";
+ mType2->print_status( cout );
+ cout << endl;
+
+ TypeFactory::addMDDType( mType1 );
+ TypeFactory::addMDDType( mType2 );
+
+ if ( !collType )
+ {
+ cout << "Collection type newly created " << endl;
+ // MDDType* mt = new MDDType( );
+ mt = new MDDType( );
+ cout << "MDDtype created "<< endl;
+ collType1 = new SetType( "ObjsContainerType", mType1 );
+ cout << "Set Type created ... ";
+ collType = collType1;
+ TypeFactory::addSetType( (SetType*) collType );
+ cout <<" and added "<< endl;
+
+ }
+
+ }
+ else
+ cout << "types were found!" << endl;
+ //ta.commit( );
+
+ //ta.begin( );
+
+ cout << "Creating root collection" << endl;
+
+ // cout << " &database = " << long( db ) << endl;
+
+ OId oColl;
+ if( OId::allocateMDDCollOId( &oColl ) == 0 )
+ cout <<"Successfully allocated OId for collection " << oColl << endl;
+ else
+ cout <<"Error allocating OId for collection " << endl;
+ globalCollOId = oColl;
+
+ PersMDDColl* col;
+ try {
+ // CollectionType* ct = TypeFactory::mapSetType( "ObjsContainerType" );
+ col = PersMDDColl::createRoot( collName, oColl, collType, db );
+ }
+ catch (...)
+ {
+ cout <<"Error caught ................."<< endl;
+ return -1;
+ }
+
+ cout << "Committing TA ..."<< endl;
+ ta.commit( );
+
+ /*
+
+ cout <<"Freeing types ... "<< endl;
+
+ // if ( mType1 ) delete mType1;
+ cout << "Type 1 freed . "<< endl;
+ // if ( mType2 ) delete mType2;
+ cout << "Type 2 freed . "<< endl;
+ // if ( mt ) delete mt;
+ cout << "Type mt freed . "<< endl;
+ // if ( collType1 ) delete collType1;
+ cout << "Types collType1 freed . "<< endl;
+ */
+ if ( col ) delete col;
+ cout << "Col freed . "<< endl;
+
+
+ ta.begin( db );
+ return 0;
+}
diff --git a/reladminif/test/test_databaseif.cc b/reladminif/test/test_databaseif.cc
new file mode 100644
index 0000000..46caa5f
--- /dev/null
+++ b/reladminif/test/test_databaseif.cc
@@ -0,0 +1,203 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * test class DatabaseIf.
+ *
+ *
+ * PREREQUISITES:
+ * - needs COMPDATE (compilation date) defined, eg. cc -DCOMPDATE=\"`date`\"
+ *
+ * COMMENTS:
+ *
+ ***********************************************************************/
+
+static const char rcsid[] = "@(#)reladminif,DatabaseIf: $Id: databaseif.ec,v 1.9 2003/12/27 23:11:43 rasdev Exp $";
+
+using namespace std;
+
+#include <iostream.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "error.hh"
+#include "adminif.hh"
+#include "databaseif.hh"
+#include "externs.h"
+
+#include "raslib/rmdebug.hh"
+#define DEBUG_MAIN
+#include "debug.hh"
+
+
+RMINITGLOBALS('C')
+
+
+// test environment:
+#include "testcenter.h"
+
+#define ELLIPSIS "..."
+/// test macro for checking error condition, printing result, and aborting on error
+#define CHECK(p) { cout << "CHECKING " << "p"; \
+ if (!(p)) \
+ { cout << TEST_ERROR << endl; \
+ return false; \
+ } \
+ else \
+ { \
+ cout << TEST_OK << endl; \
+ } \
+ }
+
+/// ObjectBroker: dummy class to satisfy linker; real ObjectBroker functionality never used here.
+class ObjectBroker
+{
+ public:
+ void init();
+ void deinit();
+ bool freeMemory();
+};
+
+void ObjectBroker::init()
+{
+}
+void ObjectBroker::deinit()
+{
+}
+bool ObjectBroker::freeMemory()
+{
+ return true;
+}
+
+/// from server/rasserver_main.cc:
+char globalConnectId[256];
+
+/// doTest(): run the test cases
+/// preconditions:
+/// database does NOT yet exist
+/// @params:
+/// dbname name of database
+/// @returns:
+/// true if all tests succeeded
+/// false if some test failed
+
+bool doTest( const char *dbname )
+{
+ bool result = false; // overall test result
+ DatabaseIf *db = NULL; // our test candidate
+
+ try // capture eny eventual exception for reporting
+ {
+ // --- (1) good scenario
+
+ cout << "DatabaseIf constructor" << ELLIPSIS << flush;
+ db = new DatabaseIf();
+ cout << "new state is: " << *db;
+ CHECK( db != NULL );
+
+ cout << "create" << ELLIPSIS << endl;
+ db->createDB( dbname, NULL, NULL );
+ CHECK( db->isConnected() );
+ CHECK( db->isOpen() );
+
+ cout << "db open" << ELLIPSIS << endl;
+ db->open( dbname );
+ CHECK( db->isConnected() );
+ CHECK( db->isOpen() );
+
+ cout << "db close" << ELLIPSIS << endl;
+ db->close();
+ CHECK( db->isConnected() );
+ CHECK( db->isOpen() );
+
+ cout << "db destroy" << ELLIPSIS << endl;
+ db->destroyDB( dbname );
+ CHECK( db->isConnected() );
+ CHECK( db->isOpen() );
+
+ result = true;
+ }
+ // FIXME: what else should be caught explicitly?
+ catch(r_Error& myErr)
+ {
+ cout << "caught r_Error exception #" << myErr.get_errorno() << ": " << myErr.what() << endl;
+ result = false;
+ }
+ catch(bad_alloc)
+ {
+ cout << "caught bad_alloc exception" << endl;
+ result = false;
+ }
+ catch(...)
+ {
+ cout << "caught unknown exception" << endl;
+ result = false;
+ }
+
+ return result;
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *progName = argv[0]; // name of this test program
+
+ int RManDebug2 = 5; // debug trace settings
+ int RManModule = 1; // dito
+
+ char* dbName = "RASBASE"; // default database name
+ int result = RC_ERROR; // overall test exit code
+ char *resultText = NULL; // overall test status string
+
+ // --- parameter evaluation, launch msg
+ if (argc == 2)
+ dbName = argv[1];
+ else if (argc > 2)
+ {
+ cout << "usage: " << progName << " [dbname]" << endl;
+ return( RC_USAGE );
+ }
+ cout << progName << ", generated on " << COMPDATE << " for rasdaman version " << RMANVERSION << " and base DBMS " << BASEDBSTRING << "; using database '" << dbName << "'" << endl;
+
+ // --- all is fine, let's do the test
+ bool allFine = doTest( dbName );
+
+ if (allFine)
+ {
+ resultText = TEST_OK;
+ result = RC_OK;
+ }
+ else
+ {
+ resultText = TEST_ERROR;
+ result = RC_ERROR;
+ }
+
+ // --- done, epilogue
+ cout << progName << ": overall test result is " << resultText << endl;
+
+ return( result );
+}
+
diff --git a/reladminif/test/testcenter.h b/reladminif/test/testcenter.h
new file mode 100644
index 0000000..c17d94f
--- /dev/null
+++ b/reladminif/test/testcenter.h
@@ -0,0 +1,47 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * provide global settings for running system tests.
+ *
+ *
+ * COMMENTS:
+ *
+ ***********************************************************************/
+
+#ifndef _TESTCENTER_H_
+
+/// program exit codes
+#define RC_OK 0
+#define RC_USAGE 2
+#define RC_ERROR -1
+
+/// protocol output, must be canonical for automatic & regression testing
+#define TEST_OK "OK"
+#define TEST_ERROR "ERROR"
+
+#define _TESTCENTER_H_
+#endif _TESTCENTER_H_
+
diff --git a/reladminif/test/testconnect.c b/reladminif/test/testconnect.c
new file mode 100644
index 0000000..70215b7
--- /dev/null
+++ b/reladminif/test/testconnect.c
@@ -0,0 +1,395 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+#include <sqlhdr.h>
+#include <sqliapi.h>
+#line 1 "testconnect.ec"
+/* testconnect.ec
+test connection to Informix database
+*/
+
+#include <iostream>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <minmax.h>
+
+/*
+ * EXEC SQL INCLUDE SQLCA;
+ */
+#line 11 "testconnect.ec"
+
+#line 11 "testconnect.ec"
+#line 1 "/opt/informix/incl/esql/sqlca.h"
+/****************************************************************************
+ *
+ * IBM INC.
+ *
+ * PROPRIETARY DATA
+ *
+ * Licensed Material - Property Of IBM
+ *
+ * "Restricted Materails of IBM"
+ *
+ * IBM Informix Client SDK
+ *
+ * (c) Copyright IBM Corporation 2002. All rights reserved.
+ *
+ *
+ * Title: sqlca.h
+ * Sccsid: @(#)sqlca.h 9.4 1/18/93 11:09:48
+ * Description:
+ * SQL Control Area
+ *
+ ***************************************************************************
+ */
+
+#ifndef SQLCA_INCL
+#define SQLCA_INCL
+
+#include "ifxtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sqlca_s
+ {
+ int4 sqlcode;
+ char sqlerrm[72]; /* error message parameters */
+ char sqlerrp[8];
+ int4 sqlerrd[6];
+ /* 0 - estimated number of rows returned */
+ /* 1 - serial value after insert or ISAM error code */
+ /* 2 - number of rows processed */
+ /* 3 - estimated cost */
+ /* 4 - offset of the error into the SQL statement */
+ /* 5 - rowid after insert */
+#ifdef _FGL_
+ char sqlawarn[8];
+#else
+ struct sqlcaw_s
+ {
+ char sqlwarn0; /* = W if any of sqlwarn[1-7] = W */
+ char sqlwarn1; /* = W if any truncation occurred or
+ database has transactions or
+ no privileges revoked */
+ char sqlwarn2; /* = W if a null value returned or
+ ANSI database */
+ char sqlwarn3; /* = W if no. in select list != no. in into list or
+ turbo backend or no privileges granted */
+ char sqlwarn4; /* = W if no where clause on prepared update, delete or
+ incompatible float format */
+ char sqlwarn5; /* = W if non-ANSI statement */
+ char sqlwarn6; /* = W if server is in data replication secondary mode */
+ char sqlwarn7; /* = W if database locale is different from proc_locale
+ */
+ } sqlwarn;
+#endif
+ } ifx_sqlca_t;
+
+/* NOTE: 4gl assumes that the sqlwarn structure can be defined as
+ * sqlawarn -- an 8 character string, because single-char
+ * variables are not recognized in 4gl.
+ *
+ * If this structure should change, the code generated by 4gl compiler
+ * must also change
+ */
+
+#ifdef VMS
+noshare
+#endif /* VMS */
+
+#define SQLNOTFOUND 100
+
+#ifndef IFX_THREAD
+extern struct sqlca_s sqlca;
+
+extern int4 SQLCODE;
+
+extern char SQLSTATE[];
+#else /* IFX_THREAD */
+extern int4 * ifx_sqlcode();
+extern struct sqlca_s * ifx_sqlca();
+#define SQLCODE (*(ifx_sqlcode()))
+#define SQLSTATE ((char *)(ifx_sqlstate()))
+#define sqlca (*(ifx_sqlca()))
+#endif /* IFX_THREAD */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SQLCA_INCL */
+
+#line 101 "/opt/informix/incl/esql/sqlca.h"
+/*
+ * EXEC SQL define SUCCESS 0;
+ */
+#line 12 "testconnect.ec"
+
+/*
+ * EXEC SQL define WARNING 1;
+ */
+#line 13 "testconnect.ec"
+
+/*
+ * EXEC SQL define NODATA 100;
+ */
+#line 14 "testconnect.ec"
+
+/*
+ * EXEC SQL define RTERROR -1;
+ */
+#line 15 "testconnect.ec"
+
+#line 16 "testconnect.ec"
+
+/*
+ * The sqlstate_err() function checks the SQLSTATE status variable to see
+ * if an error or warning has occurred following an SQL statement.
+ */
+int4 sqlstate_err()
+{
+ int4 err_code = -1;
+
+ if(SQLSTATE[0] == '0') /* trap '00', '01', '02' */
+ {
+ switch(SQLSTATE[1])
+ {
+ case '0': /* success - return 0 */
+ err_code = 0;
+ break;
+ case '1': /* warning - return 1 */
+ err_code = 1;
+ break;
+ case '2': /* end of data - return 100 */
+ err_code = 100;
+ break;
+ default: /* error - return SQLCODE */
+ break;
+ }
+ }
+ return(err_code);
+}
+
+/*
+ * The disp_sqlstate_err() function executes the GET DIAGNOSTICS
+ * statement and prints the detail for each exception that is returned.
+ */
+void disp_sqlstate_err()
+{
+ mint j;
+
+/*
+ * EXEC SQL BEGIN DECLARE SECTION;
+ */
+#line 53 "testconnect.ec"
+#line 54 "testconnect.ec"
+#line 54 "testconnect.ec"
+mint exception_count;
+#line 55 "testconnect.ec"
+ char overflow[2];
+#line 56 "testconnect.ec"
+mint exception_num = 1;
+#line 57 "testconnect.ec"
+ char class_id[255];
+#line 58 "testconnect.ec"
+ char subclass_id[255];
+#line 59 "testconnect.ec"
+ char message[255];
+#line 60 "testconnect.ec"
+mint messlen;
+#line 61 "testconnect.ec"
+ char sqlstate_code[6];
+#line 62 "testconnect.ec"
+mint i;
+/*
+ * EXEC SQL END DECLARE SECTION;
+ */
+#line 63 "testconnect.ec"
+
+
+ printf("SQLSTATE: %s\n",SQLSTATE);
+ printf("SQLCODE: %d\n", SQLCODE);
+
+/*
+ * EXEC SQL get diagnostics :exception_count = NUMBER, :overflow = MORE;
+ */
+#line 68 "testconnect.ec"
+ {
+#line 68 "testconnect.ec"
+ static ifx_hostvar_t _SQhtab[] =
+ {
+ { 0, 1, 102, sizeof(exception_count), 0, 0, 0, 0 },
+ { 0, 2, 100, 2, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 }
+#line 68 "testconnect.ec"
+ };
+ _SQhtab[0].hostaddr = (char *)&exception_count;
+ _SQhtab[1].hostaddr = (overflow);
+#line 68 "testconnect.ec"
+ sqli_diag_get(ESQLINTVERSION, _SQhtab, -1);
+#line 68 "testconnect.ec"
+ }
+
+ printf("EXCEPTIONS: Number=%d\t", exception_count);
+ printf("More? %s\n", overflow);
+
+ for (i = 1; i <= exception_count; i++)
+ {
+/*
+ * EXEC SQL get diagnostics exception :i
+ * :sqlstate_code = RETURNED_SQLSTATE,
+ * :class_id = CLASS_ORIGIN, :subclass_id = SUBCLASS_ORIGIN,
+ * :message = MESSAGE_TEXT, :messlen = MESSAGE_LENGTH;
+ */
+#line 75 "testconnect.ec"
+ {
+#line 78 "testconnect.ec"
+ static ifx_hostvar_t _SQhtab[] =
+ {
+ { 0, 3, 100, 6, 0, 0, 0, 0 },
+ { 0, 4, 100, 255, 0, 0, 0, 0 },
+ { 0, 5, 100, 255, 0, 0, 0, 0 },
+ { 0, 6, 100, 255, 0, 0, 0, 0 },
+ { 0, 7, 102, sizeof(messlen), 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 }
+#line 78 "testconnect.ec"
+ };
+ _SQhtab[0].hostaddr = (sqlstate_code);
+ _SQhtab[1].hostaddr = (class_id);
+ _SQhtab[2].hostaddr = (subclass_id);
+ _SQhtab[3].hostaddr = (message);
+ _SQhtab[4].hostaddr = (char *)&messlen;
+#line 78 "testconnect.ec"
+ sqli_diag_get(ESQLINTVERSION, _SQhtab, i);
+#line 78 "testconnect.ec"
+ }
+
+ printf("EXCEPTION %d: SQLSTATE=%s\n", i, sqlstate_code);
+ message[messlen-1] = '\0';
+ printf("MESSAGE TEXT: %s\n", message);
+ j = byleng(class_id, stleng(class_id));
+ class_id[j] = '\0';
+ printf("CLASS ORIGIN: %s\n",class_id);
+ j = byleng(subclass_id, stleng(subclass_id));
+ subclass_id[j] = '\0';
+ printf("SUBCLASS ORIGIN: %s\n",subclass_id);
+ }
+}
+
+void disp_error(char* stmt)
+{
+}
+
+void disp_exception(char* stmt, int4 sqlerr_code, mint warn_flg)
+{
+ switch (sqlerr_code)
+ {
+ case 0:
+ case 100:
+ break;
+ case 1:
+ if(warn_flg)
+ {
+ printf("Warning encountered in %s\n", stmt);
+ disp_sqlstate_err();
+ }
+ break;
+ case -1:
+ printf("Error encountered in %s\n", stmt);
+ disp_sqlstate_err();
+ break;
+ default:
+ printf("INVALID EXCEPTION STATE for %s\n", stmt);
+ break;
+ }
+}
+
+int
+check()
+{
+ mint warn_flg = 1;
+ int4 sqlerr_code = 0;
+
+ sqlerr_code = sqlstate_err();
+ disp_exception((char*)"error", sqlerr_code, warn_flg);
+
+ return SQLCODE;
+}
+
+
+int
+main(int argc, char** argv)
+{
+ cout << argv[0] << " Informix database access test" << endl;
+ if (argc != 2)
+ {
+ cout << "Usage: " << argv[0] << " connectstring" << endl;
+ return 2;
+ }
+
+/*
+ * EXEC SQL BEGIN DECLARE SECTION;
+ */
+#line 143 "testconnect.ec"
+#line 144 "testconnect.ec"
+#line 144 "testconnect.ec"
+ char id[256];
+/*
+ * EXEC SQL END DECLARE SECTION;
+ */
+#line 145 "testconnect.ec"
+
+
+ strcpy( id, argv[1] );
+ cout << "using connect string: " << id << endl;
+
+/*
+ * EXEC SQL CONNECT TO :id;
+ */
+#line 150 "testconnect.ec"
+ {
+#line 150 "testconnect.ec"
+ sqli_connect_open(ESQLINTVERSION, 0, id, (char *) 0, (ifx_conn_t *) 0, 0);
+#line 150 "testconnect.ec"
+ }
+ check();
+
+/*
+ * EXEC SQL DISCONNECT CURRENT;
+ */
+#line 153 "testconnect.ec"
+ {
+#line 153 "testconnect.ec"
+ sqli_connect_close(3, (char *) 0, 0, 0);
+#line 153 "testconnect.ec"
+ }
+ check();
+
+ cout << argv[0] << ": done." << endl;
+ return 0;
+}
+
+
+#line 159 "testconnect.ec"
diff --git a/reladminif/test/testta.pgc b/reladminif/test/testta.pgc
new file mode 100644
index 0000000..38a994c
--- /dev/null
+++ b/reladminif/test/testta.pgc
@@ -0,0 +1,281 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * test class TransactionIF.
+ *
+ *
+ * COMMENTS:
+ * none
+ *
+ * PRECONDITIONS:
+ * - database exists and is accessible (PG & rasdaman server running)
+ * - reladminif/DatabaseIF works
+ *
+ ***********************************************************************/
+
+static const char rcsid[] = "@(#)reladminif,TransactionIf: $Id: testta.pgc,v 1.6 2003/12/27 23:11:43 rasdev Exp $";
+
+#define DEBUG_MAIN
+#include "debug.hh"
+
+// constants:
+#define DATABASE "RASBASE"
+
+// pointers representing O2, database, ta and session
+AdminIf* admin = NULL;
+DatabaseIf* db = NULL;
+TransactionIf* ta = NULL;
+
+int main()
+{
+ const char *prog = argv[0]; // this program's name
+
+ cout << prog << ": test for transactionif, generated on " << COMPDATE << endl;
+
+ // --- outmost exception catcher ------------------------
+ try
+ {
+
+ // --- (1) preparation: open connection
+ admin = AdminIf::instance();
+ if( !admin )
+ {
+ cout << prog << ": cannot create adminIf instance" << endl;
+ throw r_Error();
+ }
+ // connect to the database
+ db = new DatabaseIf();
+ if( !admin )
+ {
+ cout << prog << ": cannot create DatabaseIf instance" << endl;
+ throw r_Error();
+ }
+ db->open( DATABASE );
+
+ ta = new TransactionIf();
+ if( !admin )
+ {
+ cout << prog << ": cannot create TransactionIf instance" << endl;
+ throw r_Error();
+ }
+ ta->begin( db );
+ ta->abort( db );
+ ta->commit( db );
+
+ db->close();
+ }
+ catch(...)
+ {
+ cout << prog << ": error abort." << endl;
+ }
+
+ cout << prog << ": test for transactionif done." << endl;
+}
+
+
+void
+TransactionIf::begin( bool readOnly ) throw ( r_Error )
+{
+ RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ")");
+ ENTER( "TransactionIf::begin, readOnly=" << readOnly );
+
+ isReadOnly = readOnly;
+ AdminIf::setAborted(false);
+ AdminIf::setReadOnlyTA(readOnly);
+
+ TALK( "EXEC SQL BEGIN WORK" );
+ EXEC SQL BEGIN WORK;
+ if (sqlca.sqlwarn[2] == 'W') // real error, not just a warning
+ {
+ SQLCODE = 0; // FIXME: bad hack, as PG can't reset error state and SQLCODE is queried in many places -- PB 2005-jan-09
+ }
+ else
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing BEGIN");
+ LEAVE( "TransactionIf::begin(): error during BEGIN: " << SQLCODE );
+ generateException();
+ }
+
+ if (readOnly)
+ {
+ TALK( "EXEC SQL SET TRANSACTION READ ONLY" );
+ EXEC SQL SET TRANSACTION READ ONLY;
+ // no error check, as this doesn't inhibit work
+ }
+
+ // prelim.:have additional libpq TA -- PB 2005-jan-09
+ TALK( "PQexec( pgConn, BEGIN )" );
+ PGresult *pgResult = PQexec( pgConn, "BEGIN" );
+ if (PQresultStatus(pgResult) != PGRES_COMMAND_OK)
+ {
+ LEAVE( "TransactionIf::begin() Error: cannot open libpq TA: " << PQerrorMessage(pgConn) );
+ generateException();
+ }
+
+#ifdef RMANBENCHMARK
+ DBObject::readTimer.start();
+ DBObject::readTimer.pause();
+
+ DBObject::updateTimer.start();
+ DBObject::updateTimer.pause();
+
+ DBObject::deleteTimer.start();
+ DBObject::deleteTimer.pause();
+
+ DBObject::insertTimer.start();
+ DBObject::insertTimer.pause();
+
+ OId::oidAlloc.start();
+ OId::oidAlloc.pause();
+
+ OId::oidResolve.start();
+ OId::oidResolve.pause();
+#endif
+
+ OId::initialize();
+ TypeFactory::initialize();
+
+ LEAVE( "TransactionIf::begin, SQLCODE=" << SQLCODE );
+ RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ") ");
+}
+
+void
+TransactionIf::commit() throw ( r_Error )
+{
+ RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "commit()");
+ ENTER( "TransactionIf::commit" );
+
+ if (isReadOnly)
+ {
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "read only: aborting");
+ TALK( "TA is readonly: aborting" );
+ abort();
+ }
+ else
+ {
+ AdminIf::setAborted(false);
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "set aborted false");
+ TypeFactory::freeTempTypes();
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "freed temp types");
+ ObjectBroker::clearBroker();
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "cleared broker");
+ OId::deinitialize();
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "wrote oid counters");
+ AdminIf::setReadOnlyTA(false);
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "committing");
+
+ TALK( "EXEC SQL COMMIT WORK" );
+ EXEC SQL COMMIT WORK;
+ if (check("TransactionIf::begin() COMMIT\0"))
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing COMMIT");
+ LEAVE( "TransactionIf::commit(): error during COMMIT:" << SQLCODE );
+ generateException();
+ }
+
+ // prelim.:have additional libpq TA -- PB 2005-jan-09
+ TALK( "PQexec( pgConn, END )" );
+ PGresult *pgResult = PQexec( pgConn, "END" );
+ if (PQresultStatus(pgResult) != PGRES_COMMAND_OK)
+ {
+ LEAVE( "TransactionIf::commit() Error: cannot commit libpq TA: " << PQerrorMessage(pgConn) );
+ generateException();
+ }
+
+ if (lastBase)
+ {
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "closing dbms");
+ lastBase->baseDBMSClose();
+ }
+ }
+
+#ifdef RMANBENCHMARK
+ DBObject::readTimer.stop();
+
+ DBObject::updateTimer.stop();
+
+ DBObject::deleteTimer.stop();
+
+ DBObject::insertTimer.stop();
+
+ OId::oidAlloc.stop();
+
+ OId::oidResolve.stop();
+#endif
+
+ LEAVE( "TransactionIf::commit" );
+ RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "commit() " << endl << endl);
+}
+
+void
+TransactionIf::abort()
+{
+ RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "abort()");
+ ENTER( "TransactionIf::abort" );
+
+ // prelim.:have additional libpq TA -- PB 2005-jan-09
+ TALK( "PQexec( pgConn, ABORT )" );
+ PGresult *pgResult = PQexec( pgConn, "ABORT" );
+ if (PQresultStatus(pgResult) != PGRES_COMMAND_OK)
+ {
+ LEAVE( "TransactionIf::abort() Error: cannot abort libpq TA: " << PQerrorMessage(pgConn) );
+ generateException();
+ }
+
+ AdminIf::setAborted(true);
+ TypeFactory::freeTempTypes();
+ ObjectBroker::clearBroker();
+ OId::deinitialize();
+ AdminIf::setReadOnlyTA(false);
+
+ TALK( "EXEC SQL ROLLBACK WORK" );
+ EXEC SQL ROLLBACK WORK;
+ if (check("TransactionIf::abort() ROLLBACK\0"))
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing ROLLBACK");
+ TALK( "TransactionIf::abort(): error during ROLLBACK, still continuing: " << SQLCODE );
+ }
+ if(lastBase)
+ lastBase->baseDBMSClose();
+
+#ifdef RMANBENCHMARK
+ DBObject::readTimer.stop();
+
+ DBObject::updateTimer.stop();
+
+ DBObject::deleteTimer.stop();
+
+ DBObject::insertTimer.stop();
+
+ OId::oidAlloc.stop();
+
+ OId::oidResolve.stop();
+#endif
+
+ LEAVE( "TransactionIf::abort, SQLCODE=" << SQLCODE );
+ RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "abort() " << endl << endl);
+}
+
diff --git a/reladminif/transactionif.hh b/reladminif/transactionif.hh
new file mode 100644
index 0000000..757325d
--- /dev/null
+++ b/reladminif/transactionif.hh
@@ -0,0 +1,107 @@
+#ifndef _TRANSACTIONIF_HH_
+#define _TRANSACTIONIF_HH_
+
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/************************************************************************
+ *
+ *
+ * PURPOSE:
+ *
+ *
+ * COMMENTS:
+ *
+ ***********************************************************************/
+
+//@ManMemo: Module: {\bf transactionif}.
+
+/*@Doc:
+TransactionIf has the functionality to begin, commit and abort a base
+DBMS transaction.
+*/
+
+class TransactionIf;
+class DatabaseIf;
+
+#include <iostream>
+
+#include "raslib/error.hh"
+
+class TransactionIf
+ {
+ public:
+ void begin(DatabaseIf* currBase, bool readOnly = false) throw ( r_Error );
+ /*@Doc:
+ begin a TA.
+ By default, the TA started is a write TA. If {\tt readOnly} is set to 1,
+ the TA will be read only.
+ */
+
+ void commit() throw ( r_Error );
+ /*@Doc:
+ commit a transaction. make all changes permanent.
+ r_Error is thrown when any objects have problems
+ writting themselves to the database.
+ AdminIf::compCompTiles(), TypeFactory::freeTempTypes,
+ ObjectBroker::clearBroker, OId::deinitialize are called.
+ COMMIT is issued. the database is closed.
+ the benchmark timers are stopped.
+ */
+
+ void abort();
+ /*@Doc:
+ abort a TA. don't make changes permanent.
+ AdminIf::compCompTiles(), TypeFactory::freeTempTypes,
+ ObjectBroker::clearBroker, OId::deinitialize are called.
+ ROLLBACK is issued. the database is closed.
+ the benchmark timers are stopped.
+ */
+
+ DatabaseIf* getDatabaseIf();
+ /*@Doc:
+ returns the DatabaseIf object associated with this transaction.
+ */
+
+ private:
+ void begin( bool readOnly = false ) throw ( r_Error );
+ /*@Doc:
+ begin a TA. Internal usage only.
+ This function does not work if the appropriate initializations have'nt
+ been done. For that reason, it is only appropriate for internal usage.
+ By default, the TA started is a write TA. If {\tt readOnly} is set to 1,
+ the TA will be read only.
+ benchmark timers are started.
+ */
+
+ bool isReadOnly;
+ /*@Doc:
+ keeps track if the current TA is read only or not
+ */
+
+ static DatabaseIf* lastBase;
+ /*@Doc:
+ stores the last base used in begin();
+ */
+ };
+
+#endif
diff --git a/reladminif/transactionif.pgc b/reladminif/transactionif.pgc
new file mode 100644
index 0000000..6bd16f7
--- /dev/null
+++ b/reladminif/transactionif.pgc
@@ -0,0 +1,242 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * Code with embedded SQL for relational DBMS
+ *
+ *
+ * COMMENTS:
+ * - reconsider this 604 ignorance!
+ *
+ ***********************************************************************/
+
+static const char rcsid[] = "@(#)reladminif,TransactionIf: $Id: transactionif.ec,v 1.6 2003/12/27 23:11:43 rasdev Exp $";
+
+#include "debug.hh"
+
+// general embedded SQL related definitions
+EXEC SQL include sqlglobals.h;
+
+#include "transactionif.hh"
+#include "raslib/rmdebug.hh"
+#include "adminif.hh"
+#include "oidif.hh"
+#include "catalogmgr/typefactory.hh"
+#include "sqlerror.hh"
+#include "objectbroker.hh"
+#include "databaseif.hh"
+
+// PG stuff for libpg connection maintenance
+#include "libpq-fe.h"
+extern PGconn *pgConn;
+
+
+void
+TransactionIf::begin( bool readOnly ) throw ( r_Error )
+{
+ RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ")");
+ ENTER( "TransactionIf::begin, readOnly=" << readOnly );
+
+ isReadOnly = readOnly;
+ AdminIf::setAborted(false);
+ AdminIf::setReadOnlyTA(readOnly);
+
+ TALK( "EXEC SQL BEGIN WORK" );
+ EXEC SQL BEGIN WORK;
+ if (sqlca.sqlwarn[2] == 'W') // real error, not just a warning
+ {
+ SQLCODE = 0; // FIXME: bad hack, as PG can't reset error state and SQLCODE is queried in many places -- PB 2005-jan-09
+ }
+ else
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing BEGIN");
+ LEAVE( "TransactionIf::begin(): error during BEGIN: " << SQLCODE );
+ generateException();
+ }
+
+ if (readOnly)
+ {
+ TALK( "EXEC SQL SET TRANSACTION READ ONLY" );
+ EXEC SQL SET TRANSACTION READ ONLY;
+ // no error check, as this doesn't inhibit work
+ }
+
+ // prelim.:have additional libpq TA -- PB 2005-jan-09
+ TALK( "PQexec( pgConn, BEGIN )" );
+ PGresult *pgResult = PQexec( pgConn, "BEGIN" );
+ if (PQresultStatus(pgResult) != PGRES_COMMAND_OK)
+ {
+ LEAVE( "TransactionIf::begin() Error: cannot open libpq TA: " << PQerrorMessage(pgConn) );
+ generateException();
+ }
+
+#ifdef RMANBENCHMARK
+ DBObject::readTimer.start();
+ DBObject::readTimer.pause();
+
+ DBObject::updateTimer.start();
+ DBObject::updateTimer.pause();
+
+ DBObject::deleteTimer.start();
+ DBObject::deleteTimer.pause();
+
+ DBObject::insertTimer.start();
+ DBObject::insertTimer.pause();
+
+ OId::oidAlloc.start();
+ OId::oidAlloc.pause();
+
+ OId::oidResolve.start();
+ OId::oidResolve.pause();
+#endif
+
+ OId::initialize();
+ TypeFactory::initialize();
+
+ LEAVE( "TransactionIf::begin, SQLCODE=" << SQLCODE );
+ RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ") ");
+}
+
+void
+TransactionIf::commit() throw ( r_Error )
+{
+ RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "commit()");
+ ENTER( "TransactionIf::commit" );
+
+ if (isReadOnly)
+ {
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "read only: aborting");
+ TALK( "TA is readonly: aborting" );
+ abort();
+ }
+ else
+ {
+ AdminIf::setAborted(false);
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "set aborted false");
+ TypeFactory::freeTempTypes();
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "freed temp types");
+ ObjectBroker::clearBroker();
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "cleared broker");
+ OId::deinitialize();
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "wrote oid counters");
+ AdminIf::setReadOnlyTA(false);
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "committing");
+
+ // prelim.:have additional libpq TA -- PB 2005-jan-09
+ TALK( "PQexec( pgConn, END )" );
+ PGresult *pgResult = PQexec( pgConn, "END" );
+ if (PQresultStatus(pgResult) != PGRES_COMMAND_OK)
+ {
+ LEAVE( "TransactionIf::commit() Error: cannot commit libpq TA: " << PQerrorMessage(pgConn) );
+ generateException();
+ }
+
+ TALK( "EXEC SQL COMMIT WORK" );
+ EXEC SQL COMMIT WORK;
+ if (SQLCODE == -604) // = "no TA open" - seems to be a hickup from our double transaction
+ // so we ignore it; FIXME: reinvestigate! -- PB 25-aug-2005
+ {
+ TALK( "TransactionIf::commit(): ignoring 'no TA open' error (SQLCODE -604) during COMMIT." );
+ }
+ else if (check("TransactionIf::begin() COMMIT\0"))
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing COMMIT");
+ LEAVE( "TransactionIf::commit(): error during COMMIT:" << SQLCODE );
+ generateException();
+ }
+ if (lastBase)
+ {
+ RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "closing dbms");
+ lastBase->baseDBMSClose();
+ }
+ }
+
+#ifdef RMANBENCHMARK
+ DBObject::readTimer.stop();
+
+ DBObject::updateTimer.stop();
+
+ DBObject::deleteTimer.stop();
+
+ DBObject::insertTimer.stop();
+
+ OId::oidAlloc.stop();
+
+ OId::oidResolve.stop();
+#endif
+
+ LEAVE( "TransactionIf::commit" );
+ RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "commit() " << endl << endl);
+}
+
+void
+TransactionIf::abort()
+{
+ RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "abort()");
+ ENTER( "TransactionIf::abort" );
+
+ // prelim.:have additional libpq TA -- PB 2005-jan-09
+ TALK( "PQexec( pgConn, ABORT )" );
+ PGresult *pgResult = PQexec( pgConn, "ABORT" );
+ if (PQresultStatus(pgResult) != PGRES_COMMAND_OK)
+ {
+ LEAVE( "TransactionIf::abort() Error: cannot abort libpq TA: " << PQerrorMessage(pgConn) );
+ generateException();
+ }
+
+ AdminIf::setAborted(true);
+ TypeFactory::freeTempTypes();
+ ObjectBroker::clearBroker();
+ OId::deinitialize();
+ AdminIf::setReadOnlyTA(false);
+
+ TALK( "EXEC SQL ROLLBACK WORK" );
+ EXEC SQL ROLLBACK WORK;
+ if (check("TransactionIf::abort() ROLLBACK\0"))
+ {
+ RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing ROLLBACK");
+ TALK( "TransactionIf::abort(): error during ROLLBACK, still continuing: " << SQLCODE );
+ }
+ if(lastBase)
+ lastBase->baseDBMSClose();
+
+#ifdef RMANBENCHMARK
+ DBObject::readTimer.stop();
+
+ DBObject::updateTimer.stop();
+
+ DBObject::deleteTimer.stop();
+
+ DBObject::insertTimer.stop();
+
+ OId::oidAlloc.stop();
+
+ OId::oidResolve.stop();
+#endif
+
+ LEAVE( "TransactionIf::abort, SQLCODE=" << SQLCODE );
+ RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "abort() " << endl << endl);
+}
+
diff --git a/reladminif/transactionifcommon.cc b/reladminif/transactionifcommon.cc
new file mode 100644
index 0000000..730b5b7
--- /dev/null
+++ b/reladminif/transactionifcommon.cc
@@ -0,0 +1,69 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+/*************************************************************************
+ *
+ *
+ * PURPOSE:
+ * Code common to all DBMS interface implementations
+ */
+
+#include <iostream>
+
+#include "transactionif.hh"
+#include "adminif.hh"
+#include "catalogmgr/typefactory.hh"
+#include "oidif.hh"
+#include "raslib/rmdebug.hh"
+#include "databaseif.hh"
+#include "externs.h"
+#include "objectbroker.hh"
+#include "raslib/error.hh"
+#include "dbobject.hh"
+#include "sqlerror.hh"
+
+DatabaseIf* TransactionIf::lastBase = NULL;
+
+DatabaseIf*
+TransactionIf::getDatabaseIf()
+ {
+ RMDBGONCE(2, RMDebug::module_adminif, "TransactionIf", "getDatabaseIf() " << lastBase << endl);
+ return lastBase;
+ }
+
+void
+TransactionIf::begin( DatabaseIf* currBase, bool readOnly ) throw ( r_Error )
+ {
+ RMDBGENTER(4, RMDebug::module_adminif, "TransactionIf", "begin(" << currBase->getName() << ", " << readOnly << ")");
+ try {
+ currBase->baseDBMSOpen();
+ }
+ catch(r_Error& err) {
+ currBase->baseDBMSClose();
+ throw err;
+ }
+ lastBase = currBase;
+ begin(readOnly);
+ RMDBGEXIT(4, RMDebug::module_adminif, "TransactionIf", "begin(" << currBase->getName() << ", " << readOnly << ") ");
+ }
+
+