summaryrefslogtreecommitdiffstats
path: root/reladminif/databaseif.pgc
diff options
context:
space:
mode:
Diffstat (limited to 'reladminif/databaseif.pgc')
-rw-r--r--reladminif/databaseif.pgc1382
1 files changed, 1382 insertions, 0 deletions
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