From 395a6c1f12514a3ef115ebf811dcbc2425e87bd4 Mon Sep 17 00:00:00 2001 From: cvs2svn <cvs2svn@cern.ch> Date: Mon, 9 Feb 2009 18:56:17 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'COOL_2_7_0'. git-svn-id: file:///git/lcgcool.svndb/cool/tags/COOL_2_7_0@15592 4525493e-7705-40b1-a816-d608a930855b --- RelationalCool/cmt/requirements | 144 + RelationalCool/cmt/version.cmt | 1 + RelationalCool/doc/BugReports.txt | 8 + RelationalCool/doc/CLEANUP_PLAN.txt | 130 + RelationalCool/doc/RAL_feedback.txt | 332 + RelationalCool/doc/README.CLOB | 215 + RelationalCool/doc/README.gmt | 44 + RelationalCool/doc/README.standalone | 221 + RelationalCool/doc/TODO.txt | 182 + RelationalCool/doc/hvsTagsSpec.txt | 15 + RelationalCool/doc/release.notes | 3019 +++++++++ RelationalCool/doc/unit_test_log.txt | 68 + RelationalCool/doc/userTagsImpl.txt | 451 ++ RelationalCool/doc/userTagsImpl2.txt | 467 ++ RelationalCool/doc/userTagsImpl3.txt | 70 + RelationalCool/doc/userTagsSpec.txt | 158 + RelationalCool/doc/userTagsSpec2.txt | 196 + RelationalCool/doc/userTagsSpec3.txt | 335 + .../python/CoolAuthentication/__init__.py | 87 + .../python/CoolDescribeTable/__init__.py | 218 + .../sql/oracleShowCreateTable.sql | 26 + .../python/CoolGatherSchemaStats/__init__.py | 36 + .../sql/oracleGatherSchemaStats.sql | 2 + .../python/CoolGatherTableStats/__init__.py | 55 + .../sql/oracleGatherTableStats.sql | 2 + .../python/CoolQueryManager/__init__.py | 192 + .../python/CoolShowTables/__init__.py | 128 + .../CoolShowTables/sql/oracleShowTables.sql | 14 + RelationalCool/scripts/coolAuthentication.py | 31 + RelationalCool/scripts/coolDescribeTable.py | 53 + RelationalCool/scripts/coolExecuteSql.csh | 189 + .../scripts/coolGatherSchemaStats.py | 24 + .../scripts/coolGatherTableStats.py | 31 + RelationalCool/scripts/coolQueryManager.py | 33 + RelationalCool/scripts/coolShowTables.py | 22 + RelationalCool/scripts/coolSqlplus.sh | 19 + RelationalCool/scripts/scramShowUses | 2 + RelationalCool/scripts/scramShowUses.awk | 450 ++ .../scripts/sql/oraclePurgeRecycleBin.sql | 2 + .../scripts/sql/oracleShowTables.sql | 3 + RelationalCool/scripts/wineWrap.sh | 123 + RelationalCool/src/AttributeTable.h | 94 + .../src/ConstRelationalObjectAdapter.cpp | 223 + .../src/ConstRelationalObjectAdapter.h | 142 + RelationalCool/src/ConstTimeAdapter.cpp | 94 + RelationalCool/src/ConstTimeAdapter.h | 82 + RelationalCool/src/CoolChrono.cpp | 64 + RelationalCool/src/CoolChrono.h | 57 + RelationalCool/src/CoralApplication.cpp | 401 ++ RelationalCool/src/CoralApplication.h | 84 + .../src/CoralConnectionServiceProxy.cpp | 48 + .../src/CoralConnectionServiceProxy.h | 122 + RelationalCool/src/DummyTransactionMgr.cpp | 22 + RelationalCool/src/DummyTransactionMgr.h | 74 + RelationalCool/src/HvsPathHandler.cpp | 160 + RelationalCool/src/HvsPathHandler.h | 102 + RelationalCool/src/HvsPathHandlerException.h | 33 + RelationalCool/src/HvsTagRecord.h | 131 + RelationalCool/src/IHvsTagMgr.h | 207 + RelationalCool/src/IHvsTagRecord.h | 70 + RelationalCool/src/IRelationalBulkOperation.h | 28 + RelationalCool/src/IRelationalCursor.h | 37 + .../src/IRelationalQueryDefinition.h | 135 + .../src/IRelationalTransactionMgr.h | 46 + RelationalCool/src/IteratorException.h | 150 + RelationalCool/src/ManualTransaction.cpp | 61 + RelationalCool/src/ManualTransaction.h | 58 + RelationalCool/src/ObjectId.cpp | 94 + RelationalCool/src/ObjectId.h | 95 + RelationalCool/src/ObjectIteratorCounter.cpp | 150 + RelationalCool/src/ObjectIteratorCounter.h | 58 + RelationalCool/src/ObjectVectorIterator.cpp | 92 + RelationalCool/src/ObjectVectorIterator.h | 85 + RelationalCool/src/ProcMemory.h | 197 + RelationalCool/src/RalBulkOperation.h | 56 + RelationalCool/src/RalCursor.h | 71 + RelationalCool/src/RalDatabase.cpp | 1479 +++++ RelationalCool/src/RalDatabase.h | 285 + RelationalCool/src/RalDatabaseSvc.cpp | 169 + RelationalCool/src/RalDatabaseSvc.h | 96 + RelationalCool/src/RalQueryMgr.cpp | 804 +++ RelationalCool/src/RalQueryMgr.h | 210 + RelationalCool/src/RalSchemaMgr.cpp | 1033 +++ RelationalCool/src/RalSchemaMgr.h | 184 + RelationalCool/src/RalSequenceMgr.cpp | 142 + RelationalCool/src/RalSequenceMgr.h | 81 + RelationalCool/src/RalSessionMgr.cpp | 349 + RelationalCool/src/RalSessionMgr.h | 135 + RelationalCool/src/RalTransactionMgr.cpp | 114 + RelationalCool/src/RalTransactionMgr.h | 78 + RelationalCool/src/RelationalChannelTable.cpp | 188 + RelationalCool/src/RelationalChannelTable.h | 114 + .../src/RelationalChannelTablesTable.cpp | 41 + .../src/RelationalChannelTablesTable.h | 82 + RelationalCool/src/RelationalDatabase.cpp | 1300 ++++ RelationalCool/src/RelationalDatabase.h | 512 ++ RelationalCool/src/RelationalDatabaseId.cpp | 334 + RelationalCool/src/RelationalDatabaseId.h | 175 + RelationalCool/src/RelationalDatabasePtr.h | 19 + .../src/RelationalDatabaseTable.cpp | 26 + RelationalCool/src/RelationalDatabaseTable.h | 110 + RelationalCool/src/RelationalException.cpp | 38 + RelationalCool/src/RelationalException.h | 446 ++ RelationalCool/src/RelationalFolder.cpp | 1731 +++++ RelationalCool/src/RelationalFolder.h | 539 ++ RelationalCool/src/RelationalFolderSet.cpp | 91 + RelationalCool/src/RelationalFolderSet.h | 111 + .../src/RelationalFolderSetUnsupported.cpp | 62 + .../src/RelationalFolderSetUnsupported.h | 124 + .../src/RelationalFolderUnsupported.cpp | 59 + .../src/RelationalFolderUnsupported.h | 388 ++ .../src/RelationalGlobalHeadTagTable.cpp | 29 + .../src/RelationalGlobalHeadTagTable.h | 61 + .../src/RelationalGlobalTagTable.cpp | 40 + RelationalCool/src/RelationalGlobalTagTable.h | 78 + .../src/RelationalGlobalUserTagTable.cpp | 29 + .../src/RelationalGlobalUserTagTable.h | 61 + RelationalCool/src/RelationalHvsNode.cpp | 170 + RelationalCool/src/RelationalHvsNode.h | 156 + .../src/RelationalHvsNodeRecord.cpp | 116 + RelationalCool/src/RelationalHvsNodeRecord.h | 115 + RelationalCool/src/RelationalHvsTagRecord.cpp | 93 + RelationalCool/src/RelationalHvsTagRecord.h | 79 + .../src/RelationalIovSharedSequenceTable.h | 30 + .../src/RelationalIovTablesTable.cpp | 44 + RelationalCool/src/RelationalIovTablesTable.h | 87 + RelationalCool/src/RelationalNodeMgr.cpp | 324 + RelationalCool/src/RelationalNodeMgr.h | 114 + RelationalCool/src/RelationalNodeTable.cpp | 114 + RelationalCool/src/RelationalNodeTable.h | 172 + RelationalCool/src/RelationalObject.cpp | 284 + RelationalCool/src/RelationalObject.h | 155 + .../src/RelationalObject2TagTable.cpp | 35 + .../src/RelationalObject2TagTable.h | 71 + .../src/RelationalObjectIterator.cpp | 457 ++ RelationalCool/src/RelationalObjectIterator.h | 198 + RelationalCool/src/RelationalObjectMgr.cpp | 1895 ++++++ RelationalCool/src/RelationalObjectMgr.h | 288 + RelationalCool/src/RelationalObjectPtr.h | 19 + RelationalCool/src/RelationalObjectTable.cpp | 1509 +++++ RelationalCool/src/RelationalObjectTable.h | 327 + .../src/RelationalObjectTableRow.cpp | 237 + RelationalCool/src/RelationalObjectTableRow.h | 177 + RelationalCool/src/RelationalPayloadQuery.cpp | 315 + RelationalCool/src/RelationalPayloadQuery.h | 129 + .../src/RelationalQueryDefinition.cpp | 445 ++ .../src/RelationalQueryDefinition.h | 226 + RelationalCool/src/RelationalQueryMgr.cpp | 106 + RelationalCool/src/RelationalQueryMgr.h | 314 + RelationalCool/src/RelationalSchemaMgr.cpp | 63 + RelationalCool/src/RelationalSchemaMgr.h | 208 + RelationalCool/src/RelationalSequence.cpp | 128 + RelationalCool/src/RelationalSequence.h | 112 + RelationalCool/src/RelationalSequenceMgr.cpp | 40 + RelationalCool/src/RelationalSequenceMgr.h | 92 + .../src/RelationalSequenceTable.cpp | 36 + RelationalCool/src/RelationalSequenceTable.h | 49 + .../src/RelationalSharedSequenceTable.cpp | 43 + .../src/RelationalSharedSequenceTable.h | 60 + RelationalCool/src/RelationalTableRow.cpp | 46 + RelationalCool/src/RelationalTableRow.h | 53 + RelationalCool/src/RelationalTableRowBase.cpp | 46 + RelationalCool/src/RelationalTableRowBase.h | 97 + RelationalCool/src/RelationalTag2TagTable.cpp | 30 + RelationalCool/src/RelationalTag2TagTable.h | 69 + RelationalCool/src/RelationalTagMgr.cpp | 1440 +++++ RelationalCool/src/RelationalTagMgr.h | 318 + RelationalCool/src/RelationalTagSequence.h | 30 + .../src/RelationalTagSharedSequenceTable.h | 30 + RelationalCool/src/RelationalTagTable.cpp | 32 + RelationalCool/src/RelationalTagTable.h | 64 + RelationalCool/src/RelationalTransaction.cpp | 56 + RelationalCool/src/RelationalTransaction.h | 66 + RelationalCool/src/SealBase_TimeInfo.cpp | 413 ++ RelationalCool/src/SealBase_TimeInfo.h | 135 + RelationalCool/src/SealBase_sysapi_TimeInfo.h | 97 + RelationalCool/src/SealBase_sysapi_Windows.h | 92 + RelationalCool/src/SealUtil_BaseSealChrono.h | 46 + RelationalCool/src/SealUtil_SealTimer.cpp | 101 + RelationalCool/src/SealUtil_SealTimer.h | 99 + RelationalCool/src/SealUtil_TimingItem.cpp | 101 + RelationalCool/src/SealUtil_TimingItem.h | 92 + RelationalCool/src/SimpleObject.h | 128 + RelationalCool/src/TimingReport.cpp | 126 + RelationalCool/src/TimingReport.h | 110 + RelationalCool/src/TimingReportMgr.cpp | 118 + RelationalCool/src/TimingReportMgr.h | 48 + RelationalCool/src/VersionInfo.h | 28 + RelationalCool/src/VersionNumber.h | 116 + RelationalCool/src/attributeListToString.h | 23 + RelationalCool/src/new/IHvsNodeMgr.h | 69 + RelationalCool/src/new/IHvsNodeRecordMgr.h | 61 + RelationalCool/src/new/IHvsTag.h | 43 + .../src/new/RelationalHvsTagMgr.cpp | 84 + RelationalCool/src/new/RelationalHvsTagMgr.h | 107 + RelationalCool/src/sigsegv.cpp | 296 + RelationalCool/src/sigsegv.h | 12 + RelationalCool/src/sleep.h | 19 + RelationalCool/src/timeToString.h | 92 + RelationalCool/src/uppercaseString.h | 21 + .../AttributeList/test_AttributeList.cpp | 124 + .../test_AttributeListDump.cpp | 22 + .../tests/BoolIO/authentication.xml | 14 + RelationalCool/tests/BoolIO/boolIO.cpp | 225 + RelationalCool/tests/BoolIO/boolIO.txt.MySQL | 25 + RelationalCool/tests/BoolIO/boolIO.txt.Oracle | 25 + RelationalCool/tests/BuildFile | 31 + RelationalCool/tests/CMS_ECAL/README.CMS_ECAL | 3 + RelationalCool/tests/CMS_ECAL/testCmsEcal.cpp | 254 + RelationalCool/tests/CMS_extRef/extraSQL.sql | 41 + .../tests/CMS_extRef/testCmsExtRef.cpp | 267 + .../test_ChannelSelection.cpp | 356 ++ .../tests/Channels/test_Channels.cpp | 685 ++ .../tests/ClobIO/authentication.xml | 14 + .../tests/ClobIO/clobInputOutput.cpp | 211 + RelationalCool/tests/Common/CoolDBUnitTest.h | 157 + RelationalCool/tests/Common/CoolUnitTest.h | 367 ++ RelationalCool/tests/Common/CppUnit_headers.h | 45 + .../tests/Common/CppUnit_testdriver.icpp | 4 + .../tests/Common/cppunit/TestListener.h | 23 + RelationalCool/tests/Common/releaser.h | 18 + .../tests/CoolCppUnitTestDriver.cpp | 72 + .../tests/CreateDatabase/createDatabase.cpp | 446 ++ .../HvsPathHandler/test_HvsPathHandler.cpp | 230 + RelationalCool/tests/HvsTags/test_HvsTags.cpp | 2738 ++++++++ .../tests/Int64IO/Int64InputOutput.cpp | 275 + .../tests/Int64IO/Int64InputOutput.txt | 43 + .../tests/MemoryConsumption/execTest.sh | 25 + .../test_MemoryConsumption.cpp | 729 +++ ...nalCool_MemoryConsumption.out.osx103_gcc33 | 127 + ...ool_MemoryConsumption.out.slc3_ia32_gcc323 | 151 + RelationalCool/tests/MyODBCBulkTest/README | 128 + .../MyODBCBulkTest/test_MyODBCBulkOp.cpp | 213 + RelationalCool/tests/MyTest/DO_NOT_DELETE_ME | 0 .../tests/ObjectId/test_ObjectId.cpp | 306 + .../test_PayloadSpecification.cpp | 474 ++ RelationalCool/tests/Performance/Benchmark.h | 52 + .../tests/Performance/performance_test.txt | 67 + .../tests/Performance/test_Performance.cpp | 998 +++ .../tests/PerformanceAV/README.Performance | 242 + .../tests/PerformanceAV/README.sqlTrace | 5 + .../ServerCache/100k-my-cool-first.out | 91 + .../ServerCache/100k-my-cool-next.out | 91 + .../ServerCache/100k-ora-benthic-first.prf | 680 ++ .../ServerCache/100k-ora-benthic-next.prf | 164 + .../ServerCache/100k-ora-cool-first.out | 82 + .../ServerCache/100k-ora-cool-first.prf | 898 +++ .../ServerCache/100k-ora-cool-next.out | 82 + .../ServerCache/100k-ora-cool-next.prf | 246 + .../tests/PerformanceAV/TODO.Performance | 38 + ...ssor-memory.rh73.501MB.oracle.out.ANALYZED | 109 + ...cessor-time.rh73.501MB.oracle.out.ANALYZED | 87 + ...lueAccessor.rh73.501MB.oracle.out.ANALYZED | 4 + ...ssor-memory.rh73.501MB.oracle.out.ANALYZED | 109 + ...cessor-time.rh73.501MB.oracle.out.ANALYZED | 87 + .../execTestNewCopy.rh73.1006MB.out | 5 + .../execTestNewCopy.rh73.501MB.out | 5 + .../execTestNewCopy.slc3.2006MB.out | 5 + .../newCopy-memory.rh73.1006MB.out | 102 + .../TestNewCopy/newCopy-memory.rh73.501MB.out | 102 + .../newCopy-memory.slc3.2006MB.out | 102 + .../TestNewCopy/newCopy-time.rh73.1006MB.out | 82 + .../TestNewCopy/newCopy-time.rh73.501MB.out | 82 + .../TestNewCopy/newCopy-time.slc3.2006MB.out | 82 + .../oldCopy-memory.rh73.1006MB.out | 102 + .../TestNewCopy/oldCopy-memory.rh73.501MB.out | 102 + .../oldCopy-memory.slc3.2006MB.out | 102 + .../TestNewCopy/oldCopy-time.rh73.1006MB.out | 82 + .../TestNewCopy/oldCopy-time.rh73.501MB.out | 82 + .../TestNewCopy/oldCopy-time.slc3.2006MB.out | 82 + .../execTestRalOnly.rh73.501MB.oracle.out | 4 + ...TestRalOnly.rh73.501MB.oracle.out.ANALYZED | 3 + .../ralOnly-memory.rh73.501MB.oracle.out | 103 + .../ralOnly-time.rh73.501MB.oracle.out | 83 + ...alOnly-time.rh73.501MB.oracle.out.ANALYZED | 83 + .../ralOnly-time.rh73.501MB.oracle.prf | 239 + ...alOnly-time.rh73.501MB.oracle.prf.ANALYZED | 239 + .../withCool-memory.rh73.501MB.oracle.out | 103 + .../withCool-time.rh73.501MB.oracle.out | 83 + ...thCool-time.rh73.501MB.oracle.out.ANALYZED | 83 + .../withCool-time.rh73.501MB.oracle.prf | 241 + ...thCool-time.rh73.501MB.oracle.prf.ANALYZED | 239 + ...ableCursor.rh73.1006MB.oracle.out.ANALYZED | 5 + ...ble-memory.rh73.1006MB.oracle.out.ANALYZED | 110 + ...lable-time.rh73.1006MB.oracle.out.ANALYZED | 88 + ...lable-time.rh73.1006MB.oracle.prf.ANALYZED | 239 + ...ble-memory.rh73.1006MB.oracle.out.ANALYZED | 110 + ...lable-time.rh73.1006MB.oracle.out.ANALYZED | 88 + ...lable-time.rh73.1006MB.oracle.prf.ANALYZED | 239 + ...Data-memory.rh73.501MB.oracle.out.ANALYZED | 112 + ...reData-time.rh73.501MB.oracle.out.ANALYZED | 90 + ...reData-time.rh73.501MB.oracle.prf.ANALYZED | 239 + ...areData.out.rh73.501MB.oracle.out.ANALYZED | 5 + ...Data-memory.rh73.501MB.oracle.out.ANALYZED | 112 + ...reData-time.rh73.501MB.oracle.out.ANALYZED | 90 + ...reData-time.rh73.501MB.oracle.prf.ANALYZED | 239 + .../execTestAttributeValueAccessor.csh | 53 + .../tests/PerformanceAV/execTestNewCopy.csh | 38 + .../tests/PerformanceAV/execTestRalOnly.csh | 46 + .../execTestScrollableCursor.csh | 59 + .../tests/PerformanceAV/execTestShareData.csh | 55 + .../tests/PerformanceAV/mySetupMySQL.csh | 2 + .../tests/PerformanceAV/mySetupOracle.csh | 2 + .../tests/PerformanceAV/scaling_mixed.txt | 82 + .../tests/PerformanceAV/scaling_mixed_2.txt | 98 + .../PerformanceAV/test_PerformanceAV.cpp | 477 ++ .../Privileges/out.oracle.slc3_ia32_gcc323 | 186 + .../tests/Privileges/test_Privileges.cpp | 954 +++ .../tests/ProcMemory/test_ProcMemory.cpp | 51 + .../tests/RalDatabase/README.threads | 51 + .../dropDatabaseTest.out.OCI_DEFAULT | 229 + .../dropDatabaseTest.out.OCI_THREADED | 306 + .../tests/RalDatabase/test_RalDatabase.cpp | 3496 ++++++++++ .../RalDatabaseSvc/test_RalDatabaseSvc.cpp | 137 + .../test_RalDatabase_extendedSpec.cpp | 1181 ++++ .../README.segmentationFault | 653 ++ .../tests/RalSequence/test_RalSequence.cpp | 136 + .../test_RelationalDatabaseId.cpp | 195 + .../tests/RelationalFolder/README.tests | 40 + .../out.Windows.doNotAdjustTimeZone | 183 + .../out.Windows.m1.adjustTimeZone | 74 + .../out.Windows.noTest.adjustTimeZone | 183 + .../out.Windows.p1.adjustTimeZone | 29 + .../test_RelationalFolder.cpp | 5604 +++++++++++++++++ .../test_RelationalFolder.cpp.gmtime | 1738 +++++ .../test_RelationalFolderSet.cpp | 332 + .../test_RelationalObjectIterator.cpp | 585 ++ .../test_RelationalObjectMgr.cpp | 4938 +++++++++++++++ .../test_RelationalObjectSet.cpp | 244 + .../test_RelationalObjectTable.cpp | 3002 +++++++++ .../tests/SchemaDump/coolSchemaDump.csh | 150 + .../tests/SchemaDump/oracleRefSchema.html | 2377 +++++++ .../tests/SchemaDump/schemaDump.cpp | 169 + .../tests/SchemaDump/sql/oracleDescTable.sql | 7 + .../SchemaDump/sql/oracleDumpConstraints.sql | 15 + .../SchemaDump/sql/oracleDumpFKColumns.sql | 29 + .../SchemaDump/sql/oracleDumpIndColumns.sql | 20 + .../SchemaDump/sql/oracleDumpIndexes.sql | 18 + .../tests/SchemaDump/sql/oracleDumpTables.sql | 12 + .../tests/SchemaDump/sql/oracleSchemaDump.sql | 35 + .../tests/SchemaDump/sql/oracleShowTables.sql | 6 + .../tests/Skeleton/test_Skeleton.cpp | 52 + .../tests/Skeleton/test_SkeletonDb.cpp | 51 + .../tests/StressTest/stressTest.cpp | 245 + .../test_TransactionHandling.cpp | 282 + .../VersionNumber/test_VersionNumber.cpp | 114 + RelationalCool/tests/authentication.xml | 16 + RelationalCool/tests/dblookup.xml | 124 + RelationalCool/tests/seal.opts | 19 + RelationalCool/tests/seal.opts.error | 19 + RelationalCool/tests/seal.opts.info | 19 + RelationalCool/tests/seal.opts.verbose | 19 + RelationalCool/tests/seal.opts.warning | 19 + RelationalCool/tests/setupLocalTns.csh | 1 + RelationalCool/tests/sqlnet.ora | 2 + RelationalCool/tests/test_SealPluginDump.sh | 183 + RelationalCool/tests/tnsnames.ora | 24 + .../tests/utility_methods/test_utilities.cpp | 347 + .../DBA/oracleCreateGenericReader.sql | 38 + .../utilities/DBA/oracleCreateSchemaOwner.sql | 105 + .../coolAuthentication/coolAuthentication.cpp | 389 ++ .../utilities/coolDropDB/coolDropDB.cpp | 233 + .../coolDumpSchema/coolDumpSchema.cpp | 110 + .../coolEvolveSchema/RalSchemaEvolution.cpp | 2263 +++++++ .../coolEvolveSchema/RalSchemaEvolution.h | 162 + .../coolEvolveSchema/coolEvolveSchema.cpp | 96 + .../coolPrivileges/RalPrivilegeManager.cpp | 510 ++ .../coolPrivileges/RalPrivilegeManager.h | 121 + .../coolPrivileges/coolPrivileges.cpp | 156 + .../coolPrivileges/logs/grantAll-details.txt | 91 + .../coolPrivileges/logs/grantAll.txt | 616 ++ .../coolPrivileges/logs/grantReader.txt | 203 + .../coolPrivileges/logs/grantTagger.txt | 498 ++ .../coolPrivileges/logs/grantWriter.txt | 321 + .../coolPrivileges/logs/revokeAll.txt | 616 ++ .../coolPrivileges/logs/revokeReader.txt | 202 + .../coolPrivileges/logs/revokeTagger.txt | 372 ++ .../coolPrivileges/logs/revokeWriter.txt | 195 + .../coolPrivileges/logs/showTables.txt | 35 + .../utilities/coolReplicateDB/Replication.cpp | 1038 +++ .../utilities/coolReplicateDB/Replication.h | 190 + .../coolReplicateDB/coolReplicateDb.cpp | 73 + .../utilities/coolStat/coolStat.cpp | 57 + RelationalCool/utilities/coolStat/coolStat.py | 41 + .../utilities/coolStat/testBug30859.py | 19 + .../RalSchemaValidation.cpp | 512 ++ .../coolValidateSchema/RalSchemaValidation.h | 101 + .../coolValidateSchema/coolValidateSchema.cpp | 95 + .../coolValidateSchema/test_missingTables.py | 73 + .../test_missingTables_roles.py | 119 + 390 files changed, 94905 insertions(+) create mode 100755 RelationalCool/cmt/requirements create mode 100644 RelationalCool/cmt/version.cmt create mode 100644 RelationalCool/doc/BugReports.txt create mode 100644 RelationalCool/doc/CLEANUP_PLAN.txt create mode 100644 RelationalCool/doc/RAL_feedback.txt create mode 100644 RelationalCool/doc/README.CLOB create mode 100644 RelationalCool/doc/README.gmt create mode 100644 RelationalCool/doc/README.standalone create mode 100644 RelationalCool/doc/TODO.txt create mode 100644 RelationalCool/doc/hvsTagsSpec.txt create mode 100755 RelationalCool/doc/release.notes create mode 100644 RelationalCool/doc/unit_test_log.txt create mode 100755 RelationalCool/doc/userTagsImpl.txt create mode 100644 RelationalCool/doc/userTagsImpl2.txt create mode 100644 RelationalCool/doc/userTagsImpl3.txt create mode 100644 RelationalCool/doc/userTagsSpec.txt create mode 100644 RelationalCool/doc/userTagsSpec2.txt create mode 100644 RelationalCool/doc/userTagsSpec3.txt create mode 100644 RelationalCool/python/CoolAuthentication/__init__.py create mode 100644 RelationalCool/python/CoolDescribeTable/__init__.py create mode 100644 RelationalCool/python/CoolDescribeTable/sql/oracleShowCreateTable.sql create mode 100644 RelationalCool/python/CoolGatherSchemaStats/__init__.py create mode 100644 RelationalCool/python/CoolGatherSchemaStats/sql/oracleGatherSchemaStats.sql create mode 100644 RelationalCool/python/CoolGatherTableStats/__init__.py create mode 100644 RelationalCool/python/CoolGatherTableStats/sql/oracleGatherTableStats.sql create mode 100644 RelationalCool/python/CoolQueryManager/__init__.py create mode 100644 RelationalCool/python/CoolShowTables/__init__.py create mode 100644 RelationalCool/python/CoolShowTables/sql/oracleShowTables.sql create mode 100755 RelationalCool/scripts/coolAuthentication.py create mode 100755 RelationalCool/scripts/coolDescribeTable.py create mode 100755 RelationalCool/scripts/coolExecuteSql.csh create mode 100755 RelationalCool/scripts/coolGatherSchemaStats.py create mode 100755 RelationalCool/scripts/coolGatherTableStats.py create mode 100755 RelationalCool/scripts/coolQueryManager.py create mode 100755 RelationalCool/scripts/coolShowTables.py create mode 100755 RelationalCool/scripts/coolSqlplus.sh create mode 100755 RelationalCool/scripts/scramShowUses create mode 100644 RelationalCool/scripts/scramShowUses.awk create mode 100644 RelationalCool/scripts/sql/oraclePurgeRecycleBin.sql create mode 100644 RelationalCool/scripts/sql/oracleShowTables.sql create mode 100755 RelationalCool/scripts/wineWrap.sh create mode 100644 RelationalCool/src/AttributeTable.h create mode 100644 RelationalCool/src/ConstRelationalObjectAdapter.cpp create mode 100644 RelationalCool/src/ConstRelationalObjectAdapter.h create mode 100644 RelationalCool/src/ConstTimeAdapter.cpp create mode 100644 RelationalCool/src/ConstTimeAdapter.h create mode 100644 RelationalCool/src/CoolChrono.cpp create mode 100644 RelationalCool/src/CoolChrono.h create mode 100644 RelationalCool/src/CoralApplication.cpp create mode 100644 RelationalCool/src/CoralApplication.h create mode 100644 RelationalCool/src/CoralConnectionServiceProxy.cpp create mode 100644 RelationalCool/src/CoralConnectionServiceProxy.h create mode 100644 RelationalCool/src/DummyTransactionMgr.cpp create mode 100644 RelationalCool/src/DummyTransactionMgr.h create mode 100644 RelationalCool/src/HvsPathHandler.cpp create mode 100644 RelationalCool/src/HvsPathHandler.h create mode 100644 RelationalCool/src/HvsPathHandlerException.h create mode 100644 RelationalCool/src/HvsTagRecord.h create mode 100644 RelationalCool/src/IHvsTagMgr.h create mode 100644 RelationalCool/src/IHvsTagRecord.h create mode 100644 RelationalCool/src/IRelationalBulkOperation.h create mode 100644 RelationalCool/src/IRelationalCursor.h create mode 100644 RelationalCool/src/IRelationalQueryDefinition.h create mode 100644 RelationalCool/src/IRelationalTransactionMgr.h create mode 100644 RelationalCool/src/IteratorException.h create mode 100644 RelationalCool/src/ManualTransaction.cpp create mode 100644 RelationalCool/src/ManualTransaction.h create mode 100644 RelationalCool/src/ObjectId.cpp create mode 100644 RelationalCool/src/ObjectId.h create mode 100644 RelationalCool/src/ObjectIteratorCounter.cpp create mode 100644 RelationalCool/src/ObjectIteratorCounter.h create mode 100644 RelationalCool/src/ObjectVectorIterator.cpp create mode 100644 RelationalCool/src/ObjectVectorIterator.h create mode 100644 RelationalCool/src/ProcMemory.h create mode 100644 RelationalCool/src/RalBulkOperation.h create mode 100644 RelationalCool/src/RalCursor.h create mode 100644 RelationalCool/src/RalDatabase.cpp create mode 100644 RelationalCool/src/RalDatabase.h create mode 100644 RelationalCool/src/RalDatabaseSvc.cpp create mode 100644 RelationalCool/src/RalDatabaseSvc.h create mode 100644 RelationalCool/src/RalQueryMgr.cpp create mode 100644 RelationalCool/src/RalQueryMgr.h create mode 100644 RelationalCool/src/RalSchemaMgr.cpp create mode 100644 RelationalCool/src/RalSchemaMgr.h create mode 100644 RelationalCool/src/RalSequenceMgr.cpp create mode 100644 RelationalCool/src/RalSequenceMgr.h create mode 100644 RelationalCool/src/RalSessionMgr.cpp create mode 100644 RelationalCool/src/RalSessionMgr.h create mode 100644 RelationalCool/src/RalTransactionMgr.cpp create mode 100644 RelationalCool/src/RalTransactionMgr.h create mode 100644 RelationalCool/src/RelationalChannelTable.cpp create mode 100644 RelationalCool/src/RelationalChannelTable.h create mode 100644 RelationalCool/src/RelationalChannelTablesTable.cpp create mode 100644 RelationalCool/src/RelationalChannelTablesTable.h create mode 100644 RelationalCool/src/RelationalDatabase.cpp create mode 100644 RelationalCool/src/RelationalDatabase.h create mode 100644 RelationalCool/src/RelationalDatabaseId.cpp create mode 100644 RelationalCool/src/RelationalDatabaseId.h create mode 100644 RelationalCool/src/RelationalDatabasePtr.h create mode 100644 RelationalCool/src/RelationalDatabaseTable.cpp create mode 100644 RelationalCool/src/RelationalDatabaseTable.h create mode 100644 RelationalCool/src/RelationalException.cpp create mode 100644 RelationalCool/src/RelationalException.h create mode 100644 RelationalCool/src/RelationalFolder.cpp create mode 100644 RelationalCool/src/RelationalFolder.h create mode 100644 RelationalCool/src/RelationalFolderSet.cpp create mode 100644 RelationalCool/src/RelationalFolderSet.h create mode 100644 RelationalCool/src/RelationalFolderSetUnsupported.cpp create mode 100644 RelationalCool/src/RelationalFolderSetUnsupported.h create mode 100644 RelationalCool/src/RelationalFolderUnsupported.cpp create mode 100644 RelationalCool/src/RelationalFolderUnsupported.h create mode 100644 RelationalCool/src/RelationalGlobalHeadTagTable.cpp create mode 100644 RelationalCool/src/RelationalGlobalHeadTagTable.h create mode 100644 RelationalCool/src/RelationalGlobalTagTable.cpp create mode 100644 RelationalCool/src/RelationalGlobalTagTable.h create mode 100644 RelationalCool/src/RelationalGlobalUserTagTable.cpp create mode 100644 RelationalCool/src/RelationalGlobalUserTagTable.h create mode 100644 RelationalCool/src/RelationalHvsNode.cpp create mode 100644 RelationalCool/src/RelationalHvsNode.h create mode 100644 RelationalCool/src/RelationalHvsNodeRecord.cpp create mode 100644 RelationalCool/src/RelationalHvsNodeRecord.h create mode 100644 RelationalCool/src/RelationalHvsTagRecord.cpp create mode 100644 RelationalCool/src/RelationalHvsTagRecord.h create mode 100644 RelationalCool/src/RelationalIovSharedSequenceTable.h create mode 100644 RelationalCool/src/RelationalIovTablesTable.cpp create mode 100644 RelationalCool/src/RelationalIovTablesTable.h create mode 100644 RelationalCool/src/RelationalNodeMgr.cpp create mode 100644 RelationalCool/src/RelationalNodeMgr.h create mode 100644 RelationalCool/src/RelationalNodeTable.cpp create mode 100644 RelationalCool/src/RelationalNodeTable.h create mode 100644 RelationalCool/src/RelationalObject.cpp create mode 100644 RelationalCool/src/RelationalObject.h create mode 100644 RelationalCool/src/RelationalObject2TagTable.cpp create mode 100644 RelationalCool/src/RelationalObject2TagTable.h create mode 100644 RelationalCool/src/RelationalObjectIterator.cpp create mode 100644 RelationalCool/src/RelationalObjectIterator.h create mode 100644 RelationalCool/src/RelationalObjectMgr.cpp create mode 100644 RelationalCool/src/RelationalObjectMgr.h create mode 100644 RelationalCool/src/RelationalObjectPtr.h create mode 100644 RelationalCool/src/RelationalObjectTable.cpp create mode 100644 RelationalCool/src/RelationalObjectTable.h create mode 100644 RelationalCool/src/RelationalObjectTableRow.cpp create mode 100644 RelationalCool/src/RelationalObjectTableRow.h create mode 100644 RelationalCool/src/RelationalPayloadQuery.cpp create mode 100644 RelationalCool/src/RelationalPayloadQuery.h create mode 100644 RelationalCool/src/RelationalQueryDefinition.cpp create mode 100644 RelationalCool/src/RelationalQueryDefinition.h create mode 100644 RelationalCool/src/RelationalQueryMgr.cpp create mode 100644 RelationalCool/src/RelationalQueryMgr.h create mode 100644 RelationalCool/src/RelationalSchemaMgr.cpp create mode 100644 RelationalCool/src/RelationalSchemaMgr.h create mode 100644 RelationalCool/src/RelationalSequence.cpp create mode 100644 RelationalCool/src/RelationalSequence.h create mode 100644 RelationalCool/src/RelationalSequenceMgr.cpp create mode 100644 RelationalCool/src/RelationalSequenceMgr.h create mode 100644 RelationalCool/src/RelationalSequenceTable.cpp create mode 100644 RelationalCool/src/RelationalSequenceTable.h create mode 100644 RelationalCool/src/RelationalSharedSequenceTable.cpp create mode 100644 RelationalCool/src/RelationalSharedSequenceTable.h create mode 100644 RelationalCool/src/RelationalTableRow.cpp create mode 100644 RelationalCool/src/RelationalTableRow.h create mode 100644 RelationalCool/src/RelationalTableRowBase.cpp create mode 100644 RelationalCool/src/RelationalTableRowBase.h create mode 100644 RelationalCool/src/RelationalTag2TagTable.cpp create mode 100644 RelationalCool/src/RelationalTag2TagTable.h create mode 100644 RelationalCool/src/RelationalTagMgr.cpp create mode 100644 RelationalCool/src/RelationalTagMgr.h create mode 100644 RelationalCool/src/RelationalTagSequence.h create mode 100644 RelationalCool/src/RelationalTagSharedSequenceTable.h create mode 100644 RelationalCool/src/RelationalTagTable.cpp create mode 100644 RelationalCool/src/RelationalTagTable.h create mode 100644 RelationalCool/src/RelationalTransaction.cpp create mode 100644 RelationalCool/src/RelationalTransaction.h create mode 100644 RelationalCool/src/SealBase_TimeInfo.cpp create mode 100644 RelationalCool/src/SealBase_TimeInfo.h create mode 100644 RelationalCool/src/SealBase_sysapi_TimeInfo.h create mode 100644 RelationalCool/src/SealBase_sysapi_Windows.h create mode 100644 RelationalCool/src/SealUtil_BaseSealChrono.h create mode 100644 RelationalCool/src/SealUtil_SealTimer.cpp create mode 100644 RelationalCool/src/SealUtil_SealTimer.h create mode 100644 RelationalCool/src/SealUtil_TimingItem.cpp create mode 100644 RelationalCool/src/SealUtil_TimingItem.h create mode 100644 RelationalCool/src/SimpleObject.h create mode 100644 RelationalCool/src/TimingReport.cpp create mode 100644 RelationalCool/src/TimingReport.h create mode 100644 RelationalCool/src/TimingReportMgr.cpp create mode 100644 RelationalCool/src/TimingReportMgr.h create mode 100644 RelationalCool/src/VersionInfo.h create mode 100644 RelationalCool/src/VersionNumber.h create mode 100644 RelationalCool/src/attributeListToString.h create mode 100644 RelationalCool/src/new/IHvsNodeMgr.h create mode 100644 RelationalCool/src/new/IHvsNodeRecordMgr.h create mode 100644 RelationalCool/src/new/IHvsTag.h create mode 100644 RelationalCool/src/new/RelationalHvsTagMgr.cpp create mode 100644 RelationalCool/src/new/RelationalHvsTagMgr.h create mode 100644 RelationalCool/src/sigsegv.cpp create mode 100644 RelationalCool/src/sigsegv.h create mode 100644 RelationalCool/src/sleep.h create mode 100644 RelationalCool/src/timeToString.h create mode 100644 RelationalCool/src/uppercaseString.h create mode 100644 RelationalCool/tests/AttributeList/test_AttributeList.cpp create mode 100644 RelationalCool/tests/AttributeListDump/test_AttributeListDump.cpp create mode 100755 RelationalCool/tests/BoolIO/authentication.xml create mode 100644 RelationalCool/tests/BoolIO/boolIO.cpp create mode 100644 RelationalCool/tests/BoolIO/boolIO.txt.MySQL create mode 100644 RelationalCool/tests/BoolIO/boolIO.txt.Oracle create mode 100644 RelationalCool/tests/BuildFile create mode 100644 RelationalCool/tests/CMS_ECAL/README.CMS_ECAL create mode 100644 RelationalCool/tests/CMS_ECAL/testCmsEcal.cpp create mode 100644 RelationalCool/tests/CMS_extRef/extraSQL.sql create mode 100644 RelationalCool/tests/CMS_extRef/testCmsExtRef.cpp create mode 100644 RelationalCool/tests/ChannelSelection/test_ChannelSelection.cpp create mode 100644 RelationalCool/tests/Channels/test_Channels.cpp create mode 100755 RelationalCool/tests/ClobIO/authentication.xml create mode 100755 RelationalCool/tests/ClobIO/clobInputOutput.cpp create mode 100644 RelationalCool/tests/Common/CoolDBUnitTest.h create mode 100644 RelationalCool/tests/Common/CoolUnitTest.h create mode 100644 RelationalCool/tests/Common/CppUnit_headers.h create mode 100644 RelationalCool/tests/Common/CppUnit_testdriver.icpp create mode 100644 RelationalCool/tests/Common/cppunit/TestListener.h create mode 100644 RelationalCool/tests/Common/releaser.h create mode 100644 RelationalCool/tests/CoolCppUnitTestDriver.cpp create mode 100644 RelationalCool/tests/CreateDatabase/createDatabase.cpp create mode 100644 RelationalCool/tests/HvsPathHandler/test_HvsPathHandler.cpp create mode 100644 RelationalCool/tests/HvsTags/test_HvsTags.cpp create mode 100755 RelationalCool/tests/Int64IO/Int64InputOutput.cpp create mode 100644 RelationalCool/tests/Int64IO/Int64InputOutput.txt create mode 100755 RelationalCool/tests/MemoryConsumption/execTest.sh create mode 100755 RelationalCool/tests/MemoryConsumption/test_MemoryConsumption.cpp create mode 100644 RelationalCool/tests/MemoryConsumption/unitTest_RelationalCool_MemoryConsumption.out.osx103_gcc33 create mode 100644 RelationalCool/tests/MemoryConsumption/unitTest_RelationalCool_MemoryConsumption.out.slc3_ia32_gcc323 create mode 100644 RelationalCool/tests/MyODBCBulkTest/README create mode 100755 RelationalCool/tests/MyODBCBulkTest/test_MyODBCBulkOp.cpp create mode 100644 RelationalCool/tests/MyTest/DO_NOT_DELETE_ME create mode 100644 RelationalCool/tests/ObjectId/test_ObjectId.cpp create mode 100644 RelationalCool/tests/PayloadSpecification/test_PayloadSpecification.cpp create mode 100644 RelationalCool/tests/Performance/Benchmark.h create mode 100644 RelationalCool/tests/Performance/performance_test.txt create mode 100644 RelationalCool/tests/Performance/test_Performance.cpp create mode 100644 RelationalCool/tests/PerformanceAV/README.Performance create mode 100644 RelationalCool/tests/PerformanceAV/README.sqlTrace create mode 100644 RelationalCool/tests/PerformanceAV/ServerCache/100k-my-cool-first.out create mode 100644 RelationalCool/tests/PerformanceAV/ServerCache/100k-my-cool-next.out create mode 100644 RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-benthic-first.prf create mode 100644 RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-benthic-next.prf create mode 100644 RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-first.out create mode 100644 RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-first.prf create mode 100644 RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-next.out create mode 100644 RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-next.prf create mode 100644 RelationalCool/tests/PerformanceAV/TODO.Performance create mode 100644 RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/doNotUseAccessor-memory.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/doNotUseAccessor-time.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/execTestAttributeValueAccessor.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/useAccessor-memory.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/useAccessor-time.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.rh73.1006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.rh73.501MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.slc3.2006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.rh73.1006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.rh73.501MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.slc3.2006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.rh73.1006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.rh73.501MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.slc3.2006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.rh73.1006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.rh73.501MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.slc3.2006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.rh73.1006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.rh73.501MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.slc3.2006MB.out create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/execTestRalOnly.rh73.501MB.oracle.out create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/execTestRalOnly.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-memory.rh73.501MB.oracle.out create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.out create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.prf create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.prf.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-memory.rh73.501MB.oracle.out create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.out create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.prf create mode 100644 RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.prf.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestScrollableCursor/execTestScrollableCursor.rh73.1006MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-memory.rh73.1006MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-time.rh73.1006MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-time.rh73.1006MB.oracle.prf.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-memory.rh73.1006MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-time.rh73.1006MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-time.rh73.1006MB.oracle.prf.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-memory.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-time.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-time.rh73.501MB.oracle.prf.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestShareData/execTestShareData.out.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestShareData/shareData-memory.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestShareData/shareData-time.rh73.501MB.oracle.out.ANALYZED create mode 100644 RelationalCool/tests/PerformanceAV/TestShareData/shareData-time.rh73.501MB.oracle.prf.ANALYZED create mode 100755 RelationalCool/tests/PerformanceAV/execTestAttributeValueAccessor.csh create mode 100755 RelationalCool/tests/PerformanceAV/execTestNewCopy.csh create mode 100755 RelationalCool/tests/PerformanceAV/execTestRalOnly.csh create mode 100755 RelationalCool/tests/PerformanceAV/execTestScrollableCursor.csh create mode 100755 RelationalCool/tests/PerformanceAV/execTestShareData.csh create mode 100644 RelationalCool/tests/PerformanceAV/mySetupMySQL.csh create mode 100644 RelationalCool/tests/PerformanceAV/mySetupOracle.csh create mode 100644 RelationalCool/tests/PerformanceAV/scaling_mixed.txt create mode 100644 RelationalCool/tests/PerformanceAV/scaling_mixed_2.txt create mode 100644 RelationalCool/tests/PerformanceAV/test_PerformanceAV.cpp create mode 100644 RelationalCool/tests/Privileges/out.oracle.slc3_ia32_gcc323 create mode 100644 RelationalCool/tests/Privileges/test_Privileges.cpp create mode 100644 RelationalCool/tests/ProcMemory/test_ProcMemory.cpp create mode 100644 RelationalCool/tests/RalDatabase/README.threads create mode 100644 RelationalCool/tests/RalDatabase/dropDatabaseTest.out.OCI_DEFAULT create mode 100644 RelationalCool/tests/RalDatabase/dropDatabaseTest.out.OCI_THREADED create mode 100644 RelationalCool/tests/RalDatabase/test_RalDatabase.cpp create mode 100644 RelationalCool/tests/RalDatabaseSvc/test_RalDatabaseSvc.cpp create mode 100644 RelationalCool/tests/RalDatabase_extendedSpec/test_RalDatabase_extendedSpec.cpp create mode 100644 RelationalCool/tests/RalDatabase_versioning/README.segmentationFault create mode 100644 RelationalCool/tests/RalSequence/test_RalSequence.cpp create mode 100644 RelationalCool/tests/RelationalDatabaseId/test_RelationalDatabaseId.cpp create mode 100755 RelationalCool/tests/RelationalFolder/README.tests create mode 100755 RelationalCool/tests/RelationalFolder/out.Windows.doNotAdjustTimeZone create mode 100755 RelationalCool/tests/RelationalFolder/out.Windows.m1.adjustTimeZone create mode 100755 RelationalCool/tests/RelationalFolder/out.Windows.noTest.adjustTimeZone create mode 100755 RelationalCool/tests/RelationalFolder/out.Windows.p1.adjustTimeZone create mode 100644 RelationalCool/tests/RelationalFolder/test_RelationalFolder.cpp create mode 100755 RelationalCool/tests/RelationalFolder/test_RelationalFolder.cpp.gmtime create mode 100644 RelationalCool/tests/RelationalFolderSet/test_RelationalFolderSet.cpp create mode 100644 RelationalCool/tests/RelationalObjectIterator/test_RelationalObjectIterator.cpp create mode 100644 RelationalCool/tests/RelationalObjectMgr/test_RelationalObjectMgr.cpp create mode 100644 RelationalCool/tests/RelationalObjectSet/test_RelationalObjectSet.cpp create mode 100644 RelationalCool/tests/RelationalObjectTable/test_RelationalObjectTable.cpp create mode 100755 RelationalCool/tests/SchemaDump/coolSchemaDump.csh create mode 100644 RelationalCool/tests/SchemaDump/oracleRefSchema.html create mode 100644 RelationalCool/tests/SchemaDump/schemaDump.cpp create mode 100644 RelationalCool/tests/SchemaDump/sql/oracleDescTable.sql create mode 100755 RelationalCool/tests/SchemaDump/sql/oracleDumpConstraints.sql create mode 100755 RelationalCool/tests/SchemaDump/sql/oracleDumpFKColumns.sql create mode 100755 RelationalCool/tests/SchemaDump/sql/oracleDumpIndColumns.sql create mode 100755 RelationalCool/tests/SchemaDump/sql/oracleDumpIndexes.sql create mode 100755 RelationalCool/tests/SchemaDump/sql/oracleDumpTables.sql create mode 100644 RelationalCool/tests/SchemaDump/sql/oracleSchemaDump.sql create mode 100644 RelationalCool/tests/SchemaDump/sql/oracleShowTables.sql create mode 100644 RelationalCool/tests/Skeleton/test_Skeleton.cpp create mode 100644 RelationalCool/tests/Skeleton/test_SkeletonDb.cpp create mode 100644 RelationalCool/tests/StressTest/stressTest.cpp create mode 100644 RelationalCool/tests/TransactionHandling/test_TransactionHandling.cpp create mode 100644 RelationalCool/tests/VersionNumber/test_VersionNumber.cpp create mode 100755 RelationalCool/tests/authentication.xml create mode 100644 RelationalCool/tests/dblookup.xml create mode 100644 RelationalCool/tests/seal.opts create mode 100644 RelationalCool/tests/seal.opts.error create mode 100644 RelationalCool/tests/seal.opts.info create mode 100644 RelationalCool/tests/seal.opts.verbose create mode 100644 RelationalCool/tests/seal.opts.warning create mode 100644 RelationalCool/tests/setupLocalTns.csh create mode 100644 RelationalCool/tests/sqlnet.ora create mode 100755 RelationalCool/tests/test_SealPluginDump.sh create mode 100644 RelationalCool/tests/tnsnames.ora create mode 100644 RelationalCool/tests/utility_methods/test_utilities.cpp create mode 100644 RelationalCool/utilities/DBA/oracleCreateGenericReader.sql create mode 100644 RelationalCool/utilities/DBA/oracleCreateSchemaOwner.sql create mode 100644 RelationalCool/utilities/coolAuthentication/coolAuthentication.cpp create mode 100644 RelationalCool/utilities/coolDropDB/coolDropDB.cpp create mode 100755 RelationalCool/utilities/coolDumpSchema/coolDumpSchema.cpp create mode 100644 RelationalCool/utilities/coolEvolveSchema/RalSchemaEvolution.cpp create mode 100644 RelationalCool/utilities/coolEvolveSchema/RalSchemaEvolution.h create mode 100644 RelationalCool/utilities/coolEvolveSchema/coolEvolveSchema.cpp create mode 100644 RelationalCool/utilities/coolPrivileges/RalPrivilegeManager.cpp create mode 100644 RelationalCool/utilities/coolPrivileges/RalPrivilegeManager.h create mode 100644 RelationalCool/utilities/coolPrivileges/coolPrivileges.cpp create mode 100644 RelationalCool/utilities/coolPrivileges/logs/grantAll-details.txt create mode 100644 RelationalCool/utilities/coolPrivileges/logs/grantAll.txt create mode 100644 RelationalCool/utilities/coolPrivileges/logs/grantReader.txt create mode 100644 RelationalCool/utilities/coolPrivileges/logs/grantTagger.txt create mode 100644 RelationalCool/utilities/coolPrivileges/logs/grantWriter.txt create mode 100644 RelationalCool/utilities/coolPrivileges/logs/revokeAll.txt create mode 100644 RelationalCool/utilities/coolPrivileges/logs/revokeReader.txt create mode 100644 RelationalCool/utilities/coolPrivileges/logs/revokeTagger.txt create mode 100644 RelationalCool/utilities/coolPrivileges/logs/revokeWriter.txt create mode 100644 RelationalCool/utilities/coolPrivileges/logs/showTables.txt create mode 100644 RelationalCool/utilities/coolReplicateDB/Replication.cpp create mode 100644 RelationalCool/utilities/coolReplicateDB/Replication.h create mode 100644 RelationalCool/utilities/coolReplicateDB/coolReplicateDb.cpp create mode 100644 RelationalCool/utilities/coolStat/coolStat.cpp create mode 100644 RelationalCool/utilities/coolStat/coolStat.py create mode 100644 RelationalCool/utilities/coolStat/testBug30859.py create mode 100644 RelationalCool/utilities/coolValidateSchema/RalSchemaValidation.cpp create mode 100644 RelationalCool/utilities/coolValidateSchema/RalSchemaValidation.h create mode 100644 RelationalCool/utilities/coolValidateSchema/coolValidateSchema.cpp create mode 100644 RelationalCool/utilities/coolValidateSchema/test_missingTables.py create mode 100644 RelationalCool/utilities/coolValidateSchema/test_missingTables_roles.py diff --git a/RelationalCool/cmt/requirements b/RelationalCool/cmt/requirements new file mode 100755 index 000000000..8c80e79aa --- /dev/null +++ b/RelationalCool/cmt/requirements @@ -0,0 +1,144 @@ +#============================================================================ +# $ Id: requirements,v 1.4 2005/08/24 17:31:07 marcocle Exp $ +#============================================================================ +package RelationalCool +#============================================================================ + +#============================================================================ +# Public dependencies +#============================================================================ + +use CoolKernel v* + +#============================================================================ +# Build rules +#============================================================================ + +# Use lcg_plugin_library and add 'use Reflex' to make this a Reflex plugin +# Use lcg_module_library to make this a SEAL plugin (not linked by default) +apply_pattern lcg_shared_library + +include_path none + +#============================================================================ +private +#============================================================================ + +# Link the CORAL relational libraries +apply_tag NEEDS_CORAL_RELATIONAL_ACCESS + +macro_append lcg_RelationalCool_shlibflags ' $(Boost_linkopts_thread)' +macro_append lcg_RelationalCool_shlibflags '' \ + WIN32 ' $(Boost_linkopts_date_time)' +macro_append lcg_RelationalCool_shlibflags '' \ + WIN32 ' PowrProf.lib ' + +#============================================================================ +# Tests and utilities +#============================================================================ + +use CppUnit v* LCG_Interfaces -no_auto_imports + +# For the SEAL signal handler +###use SEAL v* LCG_Interfaces + +#============================================================================ +# Setup the build options for the tests + +# RelationalCool test linkopts +macro_append RelationalCool_testlinkopts " -llcg_RelationalCool " \ + WIN32 " /libpath:../$(CMTCONFIG)/lib lcg_RelationalCool.lib " +macro_append RelationalCool_testlinkopts '' \ + WIN32 ' $(Boost_linkopts_date_time)' + +# RelationalCool utility linkopts +macro_append RelationalCool_utilitylinkopts " -llcg_RelationalCool " \ + WIN32 " /libpath:../$(CMTCONFIG)/lib lcg_RelationalCool.lib" +macro_append RelationalCool_utilitylinkopts '' \ + WIN32 ' $(Boost_linkopts_date_time)' + +#============================================================================ +# Local patterns + +pattern cool_no_db_test \ + apply_pattern lcg_unit_test_application name=<package>_<name> \ + files=../tests/<name>/*.cpp ; \ + macro_append test_<package>_<name>_cppflags ' $(ppcmd)"../tests/Common"' ;\ + macro_remove test_<package>_<name>linkopts '' Darwin '-L$(CMTINSTALLAREA)/$(CMTCONFIG)/tests/lib' + +pattern cool_db_test \ + apply_pattern lcg_unit_test_application name=<package>_<name> \ + files=../tests/<name>/*.cpp ;\ + macro_append test_<package>_<name>_cppflags ' $(ppcmd)"../tests/Common"' ;\ + macro_append test_<package>_<name>linkopts ' $(Boost_linkopts_thread)' ;\ + macro_remove test_<package>_<name>linkopts '' Darwin '-L$(CMTINSTALLAREA)/$(CMTCONFIG)/tests/lib' + +pattern cool_utility \ + application <name> ../utilities/<name>/*.cpp ;\ + macro_append <name>linkopts ' $(RelationalCool_utilitylinkopts) $(Boost_linkopts_thread)' ;\ + macro <name>_dependencies ' lcg_RelationalCool ' + +#============================================================================ +# The tests + +apply_pattern cool_no_db_test name=ChannelSelection +apply_pattern cool_no_db_test name=PayloadSpecification +apply_pattern cool_no_db_test name=VersionNumber +apply_pattern cool_no_db_test name=HvsPathHandler +apply_pattern cool_no_db_test name=RelationalDatabaseId +apply_pattern cool_no_db_test name=ObjectId +apply_pattern cool_no_db_test name=utility_methods + +apply_pattern cool_db_test name=Channels +apply_pattern cool_db_test name=HvsTags +apply_pattern cool_db_test name=RalDatabase +apply_pattern cool_db_test name=RalDatabase_extendedSpec +apply_pattern cool_db_test name=RalDatabaseSvc +apply_pattern cool_db_test name=RalSequence +apply_pattern cool_db_test name=RelationalFolder +apply_pattern cool_db_test name=RelationalFolderSet +apply_pattern cool_db_test name=RelationalObjectIterator +apply_pattern cool_db_test name=RelationalObjectMgr +apply_pattern cool_db_test name=RelationalObjectSet +apply_pattern cool_db_test name=RelationalObjectTable + +# Private tests - not to be installed in the release area +###apply_pattern cool_db_test name=bug30858 +###macro_remove tests_constituents test_RelationalCool_bug30858 +###apply_pattern cool_db_test name=bug33578 +###macro_remove tests_constituents test_RelationalCool_bug33578 + +#============================================================================ +# The utilities + +apply_pattern cool_utility name=coolAuthentication +apply_pattern cool_utility name=coolDropDB +apply_pattern cool_utility name=coolDumpSchema +apply_pattern cool_utility name=coolEvolveSchema +apply_pattern cool_utility name=coolPrivileges +apply_pattern cool_utility name=coolReplicateDB +apply_pattern cool_utility name=coolStat +apply_pattern cool_utility name=coolValidateSchema + +#============================================================================ +# Install the scripts +#============================================================================ + +macro scrdir "$(CMTINSTALLAREA)/$(tag)/bin" \ + WIN32 "$(CMTINSTALLAREA)\$(tag)\bin" +action install_scripts "mkdir -p $(scrdir); cp -r ../scripts/* $(scrdir)/." \ + WIN32 "xcopy /I/S/Y/Q ..\scripts\*.* $(scrdir)\." + +# Append to 'constituents' to execute an action in 'cmt make' +# (append to 'all_constituents' to execute it only in 'cmt make all'). +# Remove the action from cmt_actions_constituents so that the action +# is not executed twice in 'cmt make all_groups' (it executes all actions). +macro_append constituents "install_scripts" +macro_remove cmt_actions_constituents "install_scripts" + +# Fake target for examples +action examples "echo No examples in this package" +macro_remove cmt_actions_constituents "examples" + +# Do not install the header files +macro_remove constituents 'install_includes' diff --git a/RelationalCool/cmt/version.cmt b/RelationalCool/cmt/version.cmt new file mode 100644 index 000000000..626799f0f --- /dev/null +++ b/RelationalCool/cmt/version.cmt @@ -0,0 +1 @@ +v1 diff --git a/RelationalCool/doc/BugReports.txt b/RelationalCool/doc/BugReports.txt new file mode 100644 index 000000000..eff71dadf --- /dev/null +++ b/RelationalCool/doc/BugReports.txt @@ -0,0 +1,8 @@ +2005.02.03 Schema evolution (AV, MC) + +The new software does not allow to delete the old tables. +Long term solutions: provide schema evolution. +Short term solution: provide scripts to clean the schema. + + + diff --git a/RelationalCool/doc/CLEANUP_PLAN.txt b/RelationalCool/doc/CLEANUP_PLAN.txt new file mode 100644 index 000000000..c344d5e3e --- /dev/null +++ b/RelationalCool/doc/CLEANUP_PLAN.txt @@ -0,0 +1,130 @@ +------------------------------------------------ +AV's plan for cleaning up the code - 14.12.2004 +------------------------------------------------ + +General ideas: +- Need three or more types of classes, Relational, Ral, Hvs; + for the moment they can stay all in RelationalCool, then we can move them +- Hvs for the moment is only needed to model transient HVS entities + and factor out functionality that is implemented by CondDB stuff too + (eg HvsNode should be - again - a base clas for RelationalFolder) +- Relational classes should contain all the table and column names + and all the algorithmic logic of the relational implementation +- Ral classes should contain only the code that really does table + creation/dropping and row insertion/update/select/delete: the idea + is that one can provide a MySQL or OCCI direct implementation of + the Relational conddb by JUST replacing the Ral classes +==> Main emphasis of this round of cleanup should be to extract out of + the Ral classes the functionality that belongs to Relational + +Specific points for Ral classes + +- RalDatabaseSvc: OK should remain + +- RalDatabaseSvcFactory: OK for now... eventually may be replaced + by a more general DatabaseSvcFactory, which should understand + IDs of the form "ral::mysql:/" or "mysql::mysql:/" and instantiate + a Ralor MySQL database service to handle the same mysql database.... + +- RalTransaction: should disappear, it should become RelationalTransaction. + The idea is that the user does not manipulate transactions. + All methoids called by the user are encapsulated within a transaction. + Typically, these methods have the form { 1.startTransaction + 2.doSomethingInDb 3.commitTransaction }. Such methods should + go to the Relational classes. In particular, startTransaction and + commitTransaction should be achieved withRelationalTransaction, eg + RelationalFolder::findObject(...){ + RelationalTransaction transaction( m_db ); + m_db->fetchRow(...); + transaction.commit(); + ... interpret the row and return the object ... + } + RelationalTransaction( RelationalDatabase* db ) { + db->startTransaction( this ); + } + The RalDatabase, ie the only Ral aware class, is the one that both + fetches the object and actually starts the transaction: + virtual RelationalDatabase startTransaction( RelationalTransaction t ) = 0; + virtual RelationalDatabase fetchRow(...) = 0; + RalDatabase::startTransaction( RelationalTransaction t ) { + m_session->startTransaction(...); + t.setStarted(); // JUST SETS A FLAG... + } + RalDatabase::fetchRow(...) { + m_session->getCursorForTheQuery..... + } + Forcing the startTransaction method to accept a RelationalTransaction + argument binds the startTransaction to a particular transaction instance, + so that one is not just tempted to call startTransaction instead + of writing "RelationalTransaction t" in the method where t is started. + Eventually, note that RDBMS offer the possibility to start transacions + with a name, so as to have several concurrent isolated transactions + in the same session... passing the argument can just pass the name... + +- RalSequence: this should also change as RelationalSequence. + Again, RalDatabase should take care of doing the actual insert/delete + and so on in the database.... + I would keep this for quite a while, because I am not sure when + RAL will support native sequences, or provide SYSDATE support. + Eventually one may think of having all sequences in the same table, + each sequence in a separate row, to have fewer tables. + +- RalDatabase: this should be the ONLY Ral class (apart from the + databasesvc and its factory) that remains. + NB: for the moment, the methods it is answeriung are of the form + 'fetch object from object table with that order'... + Eventually, this could be refactored slightly so that it offers + much higher level services, eg generic table handling, BUT + - we dont want to reinvent RAL + - somewhere the specific choices of how to write the queries in SQL + (eg the order of inserting the arguments) must be made, + and it should be in the RAL specific class + +Other points: + +- Should make much more uniform the treatment of the various tables + in the code, have a uniform look and feel for defining the column + names and column types. We may think of using typedefs for the + column types (in the static declarations), so that the code is not + forced to make assumptions in setValue/getValue (eg if IValidityKey + is declared as long long but the iovSince column is typedefed + temporarily as long, the code can be written without knowing + that the iovSince is long... it will just force a conversion + from IValidityKey to/from iovSince type, whatever that is) + +- It may be (??) useful to have a table class, and derive all + tables that are present in our code from that class. + But not sure, what would this gain exactly? + Maybe we can let RalDatabase handle the base table, and then automatically + all derived tables by inheritance? + +- Instead/in any case, it may be useful to split out the various + 'namespaces' RelationalObjectTable, RelationalFolderTable and so on + as real classes RelationalObjectTable, RelationalFolderTable, and so on. + Definitely (again!), the look and feel should be more harmonious, + eg column definitions for RelationalObjectTable in file + RelationalObject.h, or RelationalObjectTable.h, not moving + from RalDatabase.h to RelationalDatabase.h and so on... + +AOB + +- Iterators + Eventually these should become real iterators which retrieve rows in bulk, + say 1000 by 1000, but not N millions rows all together if this is what is + in the table and in the iteration loop. For this reason it should + only have forward iteration. "Freezing" of the database + can be achived by only selecting rows whose insertion time, + or update time, is less than the time at which the iterator + was created.... + The number of rows fetched in each roundtrip may be set by the user, + but it may also be an internal detail at the beginning. + That is to say: the initial implementation of the iterator + now returns an ObjectVectorIterator, but eventually + it should return something more complex! + +- Update time + The feature outlined above needs an extra "update time" column + that should be changed when for instance the online columns + has +infinity transformed into a real time. + Note that also in the versioning mode you will have the need + for updating the rows (eg "HEAD unti objectId..." column). diff --git a/RelationalCool/doc/RAL_feedback.txt b/RelationalCool/doc/RAL_feedback.txt new file mode 100644 index 000000000..6ecbe14ae --- /dev/null +++ b/RelationalCool/doc/RAL_feedback.txt @@ -0,0 +1,332 @@ +// $Id: RAL_feedback.txt,v 1.17 2005-03-18 21:33:44 avalassi Exp $ +============================================================================== +PENDING PROBLEMS +============================================================================== +* Altering table to add foreign key constraint should be possible a posteriori + +The functionality needs to be added to IRelationalTableSchemaEditor +(or should be moved from IEditableTableDescription). + +------------------------------------------------------------------------------ +* Need option to switch off /tmp/pool.sql.log + +This huge file is extremely useful for debugging. +But it may decrease performance. Is it possible to switch it off? + +------------------------------------------------------------------------------ +* POOL_2_0_1 does not translate correctly unsigned long for MyODBC + +In POOL_2_0_0 I got the table created with UNSIGNED BIGINT. +In POOL_2_0_1 the type is missing and SQL fails. + +------------------------------------------------------------------------------ +* Tablespace definition via the API + +This is presently only possible via the job options or environment +variables at the domain level. This should be possible ALSO at the table +level (and at the session level) through the API. + +------------------------------------------------------------------------------ +* Support for insert/select statements + +Support 'insert into xxx select * from yyy'. +Needed by Sven for simpler tagging. + +------------------------------------------------------------------------------ +* MySQL plugin internal emulation of bulk retrieval + +The MySQL performance should be better understood and optimized. +If there is a problem with missing bulk operations (so that the choice +is either to go one by one or retrieve ALL rows in a query), it may be +useful to improve the emulation by doing the following +- allow the users to specify a prefetch buffer, eg 10k +- issue a read only transaction +- issue the select statement using an order by clause (either the one + provided by the user, or one on the PK of the table, or throw an + exception if none exists and a prefetch buffer is specified) +- retrieve the first 10k rows +- retrieve the next 10k rows and so on +The read only transaction and order by clause are to be screened behind +the implementation and ensure that the fetching order is reproducible. + +------------------------------------------------------------------------------ +* MySQL API direct implementation + +Priority low. May be a useful alternative to ODBC eventually. + +------------------------------------------------------------------------------ +* Switch to non-scrollable cursors in the MySQL plugin + +Internal change: the default MySQL plugin impleentation should use +forward-only cursors. Although this is not guaranteed to cause a major +performance improvement, this should be tested as it had a major +impact for Oracle (an dthe MySQL implementation is still relatively slow). + +------------------------------------------------------------------------------ +* BLOB support in AttributeList and RAL + +The user should be able to store/retrieve as a database BLOB a raw binary +memory buffer of a given size. + +------------------------------------------------------------------------------ +* Query output type definition + +The defineOutput() method should not require that the size of the +AttributeListSpecification is the same as the one of the output list +as defined with the successive calls to the addToOutput() method. +It should be enough to specify via defineOutput an AttributeListSpecification +that is a superset (ie larger) than all columns queried. + +------------------------------------------------------------------------------ +* MySQL plugin messaging + +In DEBUG mode it should print out the statement that was prepared +in prepareStatement(), just like for Oracle. + +------------------------------------------------------------------------------ +* MySQL plugin support for Windows. + +Presently it is only available under Linux. + +------------------------------------------------------------------------------ +* NULL value insertion. + +Inserting NULL values should be done explicitly. + +The best solution would be to modify AttributeList so that each +attribute in the list has the optionof being NULL/undefined. This +could then be used transaparently in RAL for both insertion and retrieval. + +------------------------------------------------------------------------------ +* String size specification + +The user should be able to specify (and retrieve in the table description) +for a string column its maximum size and whether the latter is variable +or fixed. + +Additionally, RAL should automatically store strings as CLOBs if they are +larger than the maximum VARCHAR size. + +------------------------------------------------------------------------------ +* MySQL plugin handling of multiply-bound variables + +The user should be able to use the same syntax "where xx < :a and :a < yy" +as for Oracle, with a bind variable appearing twice. RAL should take care +of binding the variable twice. + +------------------------------------------------------------------------------ +* MySQL plugin handling of bind variable names + +The user should be able to use the same syntax "where :a<yy" as for Oracle. +Presently this does not work because this is replaced by "?", interpreting +this as the binding of a variable called "a<yy" (ie presently one has to +write ":a <yy" instead of ":a<yy", taking care to leave a space). +RAL should interpret as the bind variable name only letters, numbers and +the "_" character. Any character other than these (eg +,-,<,>,=) should +indicate that the bind variable name is over. + +------------------------------------------------------------------------------ +* MySQL plugin handling of bind variable order + +Presently the MySQL plugin assumes that the order in which attributes +are specified in the AttrinbuteList for a WHERE clause is the same as +the order in which the variables are bound. This should be changed +as it leads to errors that are difficult to trace and debug and +may go unnoticed. The MYSQL plugin should behave like Oracle OCI +and crosscheck names of variables (this would also solve the problem +of doubly dound variable names). + +------------------------------------------------------------------------------ +* SQL_TRACE + +The user should be able to enable SQL_TRACE in a session. +For Oracle, this should issue + alter session set events '10046 trace name context forever, level 12' +Ideally this should be a session property (method of IRelationalSession). +Initially, this can be a domain property, set via the seal opts or +one of the 'hidden' environment variables, eg POOL_ORA_SQL_TRACE. + +------------------------------------------------------------------------------ +* Support for SYSDATE date computed by the server + +1. The user should be able to retrieve into C++ the date on the server. +There should be a simple method to retrieve only the date. This would issue: + Oracle (systimestamp has higher precision - microseconds instead of seconds) + select sysdate from dual; + select systimestamp from dual; + select current_timestamp from dual; + MySQL + select current_timestamp; +The ANSI version current_timestamp works for both but gives different results. +For instance, add a method serverCurrentTimestamp() in the IRelationalSession? +Priority: high. + +2. The user should be able to retrieve the date when retrieving data +from any table. This would issue for instance + Oracle + select [user columns], current_timestamp from [user table]; + MySQL + select [user columns], current_timestamp from [user table]; +For instance, define a reserved keyword CURRENT_TIMESTAMP which can be used +in the IRelationalQuery::addToOutputList() method, without executing the +cross-check whether this exists in the table because it does not? +Priority: lower (if you can at least get the serverCurrentTimestamp +into C++, you can always do this in two steps). + +3. The user should be able to insert the date into a column of a table. +This would issue for instance + insert [user values], current_timestamp into ...; +Priority: lower (if you can at least get the serverCurrentTimestamp +into C++, you can always do this in two steps). + +PS: actually the priority may be a bit higher. +We need to COMPARE date values, presently we are comparing strings... + +Note: presently COOL is working around this problem by using the UPDATE +clause, the only place where free SQL can be used: for instance, +- insert a dummy value into a table +- update the table with the system date +- read it back from the table to know what is the time on the server + +------------------------------------------------------------------------------ +* Support for seal::Time and native Oracle DATE + +The user should be able to create table with DATE columns. +If possible, seal::Time should also be supported in +AttributeList and mapped to DATE SQL types by default. + +------------------------------------------------------------------------------ +* ANALYZE TABLE + +The user should be able to analyze a table from the C++. +Although this is an administration level operation, it is essential +for fast tests where one wants to create a table, insert data and +select from the table at the same time. The table must be analyzed +after data have been inserted and before issuing the select query. + +For instance, add a method analyzeTable to IRelationalTable? +This would issue + analyze table xxx compute statistics (Oracle) + analyze table (MySQL) + +------------------------------------------------------------------------------ +* ORA-01466 + +Oracle readonly transaction uses READ ONLY rather than SERIALIZABLE. +If a table is created and immediately queried, this causes an ORA-01466 error. +This was reported to Oracle, but their answer is that this is a feature +that needs to be better documented, not a bug that will be fixed, +and the workaround is to wait for a few seconds. + +Given this situation, I would suggest the following workaround to apply +within RAL, which would at least prevent the problem from happening within +the same active session: an active OracleSession instance should keep +track of the last date at which it issued any kind of DDL statements. +Whenever a read-only transaction is issued, RAL itself should check +whether at least N seconds have elapsed since the last DDL: if not, + +------------------------------------------------------------------------------ +* Read only transactions (more generally) + +We should review whether Oracle READ ONLY transactions are really +what we need for "read only" mode. SERIALIZABLE transactions look +safer and better than readonly, but they may block +concurrent users from running at the same time. + +------------------------------------------------------------------------------ +* AttributeList copy constructor and assignment operator + +AttributeLists behave differently depending on whether they were built +from a reference or a boost shared pointer specification. +The assignment operator is reliable only in the second case. +The copy constructor gives problems for both. +This was notified to Kuba, Ioannis and Rado. + +------------------------------------------------------------------------------ +* Multi-threading problems with MySQL/ODBC + +I had to disable the -pthread switch on RelationalCool because +the application hangs (only for MySQL). The circumstances are +difficult to explain exactly: it happens in RalSequence when +I try to drop a table and then recreate it again. It does not +happen if the table had been dropped using TOra. + +The problem had already been mentioned to Rado long ago. +Has this been solved in the meantime (by RAL or by the next ODBC driver)? +[In COOL a workaround is presently used in RelationalCoool/BuildFile] + +------------------------------------------------------------------------------ +* Problem inserting rows where all values are NULL + +Bug: when inserting rows where all values are null, this is translated +into non-valid SQL: + INSERT INTO "CONDDB_TEST"."COOLTEST_FOLDERS_SEQ" () VALUES (); +Maybe this has already been fixed? + +------------------------------------------------------------------------------ +* Partitioning and local indexes + +The user should be able to specify that a table should be created +as partitioned and indexese are local. Priority: low. + +============================================================================== +PROBLEMS SOLVED +============================================================================== +* Support for 64-bit integer + +This type could not be defined in an AttributeList or stored using RAL. + +------------------------------------------------------------------------------ +* Set clause syntax for MySQL/ODBC in IRelationalTableDataEditor::updateRows + +The Oracle plugin required ":bindvariable", MySQL/ODBC required "?". +Now both use ":bindvariable". + +------------------------------------------------------------------------------ +* Feature with columnNamesAndTypes() + +If you insert a column via insertColumn( columnName, typeName ) +and then retrieve columnNamesAndTypes(), the types are not guaranteed +to be the same. For instance, insertColumn for "unsigned long" will +return an "unsigned long" on MySQL (as the native type can be mapped), +while it will return "long" on Oracle because this maps to NUMBER(38). +This causes problems if you try to then insert an attribute value via +setValue<type> into the attribute list, pool::attribute_bad_type +will be thrown. + +=> Solution: when filling in the table, do not rely on columnNamesAndTypes(): +instead, keep a local copy of the C++ mapping in the tables or in the +C++ code! This solves the setValue() problem. + +------------------------------------------------------------------------------ +* Feature with IRelationalCursor::currentRow() + +Also in this case the same problem appears: the attribute list returned +has a specification that is read from the table description, ie exactly +the same returned by columnNamesAndTypes(). If the previous problem +appeared for setValue(), this appears for getValue(): it is a priory +impossible to know which C++ should be used for getValue(). The only +safe one is string, but this is not satisfactory! + +=> Solution: you must use defineOutput() to specify the required format! + +------------------------------------------------------------------------------ +* NULL values inserted in MySQL third column (POOL_1_8_0) + +This is fixed in the HEAD of ODBCAccess since december 3. +There was a bug with the use of STL vectors: push_back changes +the internal memory addresses of all vector elements. + +------------------------------------------------------------------------------ +* MyODBC bulk inserter inserts \0-terminated strings + +Check by selecting + select s, length(s) from COOLTEST_F0001_IOVS; + +These two queries gave different results (and only the second works fine!): + select * from COOLTEST_F0001_IOVS where s='Object 1'; + select * from COOLTEST_F0001_IOVS where s='Object 1\0'; +Fixed in POOL_2_0_2. + +------------------------------------------------------------------------------ + diff --git a/RelationalCool/doc/README.CLOB b/RelationalCool/doc/README.CLOB new file mode 100644 index 000000000..70dfa80c8 --- /dev/null +++ b/RelationalCool/doc/README.CLOB @@ -0,0 +1,215 @@ +Various problems with CLOB. Let's start with the most important. + +----------------------------------------------------------------------------- +Problem #1: segmentation fault in reading back CLOB from Oracle (08.04.2005) +----------------------------------------------------------------------------- + +The problem initially appeared in COOL after changing the folder payload spec +column to CLOB. In Oracle, I got a segmentation fault when reading from this table. + +I initially thought this was because I was mixing CLOB and non-CLOB columns +and thought of testing this. So I downloaded the standard clobInputOutput.cpp +test from the POOL OracleAccess test suite. However I realised that even the +standard POOL test failed. I went on to investigate this. + +I thought that this could be an environment problem (the COOL environment mixes +some debug and non-debug libraries, it ALWAYS uses POOL in debug mode to avoid +segmentation faults discovered elsewhere in the code). +I downloaded POOL into a separate project area than COOL. +Using the POOL standard environment everything works fine: +the test executes successfully in non-debug mode. + + cd ~/myLCG/ + rm -rf POOL_2_0_3 + setenv SCRAM_ARCH rh73_gcc323 + scram project POOL POOL_2_0_3 + cd POOL_2_0_3/ + setenv CVSROOT :kserver:pool.cvs.cern.ch:/cvs/POOL + cvs co -r POOL_2_0_3 OracleAccess + cd OracleAccess/tests/CLOBInputOutput/ + mv clobInputOutput.cpp clobInputOutput.cpp.OLD + mv authentication.xml authentication.xml.OLD + cp ~/myLCG/COOL_HEAD/src/RelationalCool/tests/ClobIO/clobInputOutput.cpp . + cp ~/myLCG/COOL_HEAD/src/RelationalCool/tests/ClobIO/authentication.xml . + scram b + which unitTest_OracleAccess_CLOBInputOutput + unitTest_OracleAccess_CLOBInputOutput + +I try again using the debug version. This one causes a segmentation fault! +The POOL debug library causes a segmentation fault when using CLOBs in Oracle. +[Note: scram setup is probably not needed, it does nothing.] + + setenv SCRAM_ARCH rh73_gcc323_dbg + cd ~/myLCG/POOL_2_0_3/src/OracleAccess/tests/CLOBInputOutput > + scram setup + scram b + eval `scram runtime -csh` + which unitTest_OracleAccess_CLOBInputOutput + unitTest_OracleAccess_CLOBInputOutput + +Note that my own modifications to the test only change the debug level and the schema. +I need to change the schema because the POOL default test uses an unknown database. +I tested in any case that changing the message level from Info to Debug is not +what causes the problem. The segmentation fault appears also if the level is Info. + +Changes between the POOL standard test and my test: +==> diff clobInputOutput.cpp clobInputOutput.cpp.OLD +179,180c179 +< //pool::POOLContext::setMessageVerbosityLevel( seal::Msg::Info ); +< pool::POOLContext::setMessageVerbosityLevel( seal::Msg::Verbose ); +--- +> pool::POOLContext::setMessageVerbosityLevel( seal::Msg::Info ); +183,184c182 +< // std::string connectionString = "oracle://test10g/ioannis"; +< std::string connectionString = "oracle://devdb/conddb_test"; +--- +> std::string connectionString = "oracle://test10g/ioannis"; +==> diff authentication.xml authentication.xml.OLD +14,17d13 +< <connection name="oracle://devdb/conddb_test"> +< <parameter name="user" value="conddb_test" /> +< <parameter name="password" value="lcg" /> +< </connection> + +Output from the program (within gdb): +==> gdb unitTest_OracleAccess_CLOBInputOutput +GNU gdb Red Hat Linux (5.2-2) +Copyright 2002 Free Software Foundation, Inc. +GDB is free software, covered by the GNU General Public License, and you are +welcome to change it and/or distribute copies of it under certain conditions. +Type "show copying" to see the conditions. +There is absolutely no warranty for GDB. Type "show warranty" for details. +This GDB was configured as "i386-redhat-linux"... +(gdb) r +Starting program: /afs/cern.ch/user/a/avalassi/myLCG/POOL_2_0_3/rh73_gcc323_dbg/tests/bin/unitTest_OracleAccess_CLOBInputOutput +LOCALRT: /afs/cern.ch/user/a/avalassi/myLCG/POOL_2_0_3 +ORACLE_HOME not set +[New Thread 1024 (LWP 21112)] +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +Connecting... +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +Starting a new transaction +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'CONDDB_TEST'" +Deleting table "DataTable" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "CONDDB_TEST"."DataTable"" +Creating table "DataTable" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "CONDDB_TEST"."DataTable" ( "id" NUMBER(10), "data" CLOB )" +Adding a row into the table +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "CONDDB_TEST"."DataTable" ("id","data") VALUES (:"id",:"data")" +Adding a second row into the table +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "CONDDB_TEST"."DataTable" ("id","data") VALUES (:"id",:"data")" +Committing... +Disconnecting... +Connecting... +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +Starting a new transaction +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'CONDDB_TEST'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "id", "data" FROM "CONDDB_TEST"."DataTable"" +Program received signal SIGSEGV, Segmentation fault. +[Switching to Thread 1024 (LWP 20859)] +0x407ef2cf in kpccld2i () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 + +Stack trace from gdb at this point: +==> (gdb) bt +#0 0x407ef2cf in kpccld2i () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#1 0x407da72b in ttccfpg () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#2 0x407d95b6 in ttcfour () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#3 0x407ceab7 in ttcdrv () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#4 0x4066590d in nioqwa () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#5 0x404e1366 in upirtrc () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#6 0x4047801d in kpurcsc () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#7 0x405824a8 in kpufch0 () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#8 0x405832fb in kpufch () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#9 0x404ab067 in OCIStmtFetch2 () + from /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 +#10 0x400b57fc in pool::OracleAccess::OracleStatement::fetchNext() (this=0x80f4878) + at /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_3/src/OracleAccess/src/OracleStatement.cpp:635 +#11 0x4008e8be in pool::OracleAccess::OracleCursor::next() (this=0x8082af8) + at /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_3/src/OracleAccess/src/OracleCursor.cpp:117 +#12 0x0804f281 in readClob(std::string const&) (connectionString=@0xbfffc0c0) + at /afs/cern.ch/user/a/avalassi/myLCG/POOL_2_0_3/src/OracleAccess/tests/CLOBInputOutput/clobInputOutput.cpp:140 +#13 0x0804faef in main () + at /afs/cern.ch/user/a/avalassi/myLCG/POOL_2_0_3/src/OracleAccess/tests/CLOBInputOutput/clobInputOutput.cpp:189 +#14 0x42017589 in __libc_start_main () from /lib/i686/libc.so.6 + +----------------------------------------------------------------------------- +Problem #2: Feedback about the RAL API (07.04.2005) +----------------------------------------------------------------------------- + +The present RAL interface has some limitations in handling tables where +columns with the same C++ type are stored using different SQL types. +Presently non-default SQL types can only be set at the session level +using the type converter, not on individual table columns. +The present workaround is that columns must be individually altered, or dropped +and recreated using a new SQL type mapping temporarily set at the session level. +A new RAL API is being designed to overcome this problem. + +Feedback for the new RAL design: +1. The RAL interface should allow to specify some kind of SQL-type 'hint' +for individual columns already when creating the table. +2. The "size" of the SQL type should be a part of the hint. For strings, for +instance, RAL should automatically decide that 255-size strings can use VARCHAR2(255) +on Oracle and VARCHAR(255) BINARY on MySQL, but 4000-size strings can use +VARCHAR2(4000) on Oracle and need TEXT on MySQL. +3. The "size" alone is not enough. Strings can be mapped to DATE, for instance. +The RAL interface for creating a table should allow users to specify that a +string is stored as DATE. reserving a special size value for this seems awkward. +Other examples may include CHAR vs VARCHAR2, for instance, with the same size. +4. The "size" should not only be used in creating the table, but also in inserting +(and reading back?) data: for instance, if the type is specified as 4000-size +maximum but is stored as TEXT in MySQL, a 5000-size string could be stored in MySQL. +RAL should throw an exception. This should make sure that data can safely be +transferred to Oracle, where VARCHAR2(4000) would be used. This also means that +an SQL-type hint alone is also not enough (one may indicate TEXT or CLOB but may +also want to indicate a maximum size). +5. The "size" (and eventually maybe also the DATEness or CHAR/VARCHAR) of +each attribute is presently being added in COOL to a wrapper for the POOL +AttributeListSpecification class. It may be useful to review this class +so that an extended AttributeListSpecification with size or other SQL-related +information can be derived from the POOL AttributeListSpecification +and included in POOL. Or maybe this information can simply be added to the +new POOL AttributeListSpecification. + +----------------------------------------------------------------------------- +Problem #3: ALTER TABLE constraints in Oracle (07.04.2005) +----------------------------------------------------------------------------- + +The initial implementation I tried to change the payload specification +column from the RAL default to CLOB was using the ALTER TABLE statement +(via the RAL modifyColumn interface). + +However, changing a VARCHAR to CLOB is not possible (ORA-22858). +Similarly, changing a CLOB to VARCHAR to CLOB is also not possible (ORA-22859). + +Solution: the COOL implementation now drops and recreates columns. +In order not to change the column order, all columns following the first +column whose SQL type needs to be changed are also dropped and recreated. + +----------------------------------------------------------------------------- +Problem #4: modifying column types did not seem to work in MySQL (07.04.2005) +----------------------------------------------------------------------------- + +Both the alter table and the drop/recreate column solution seemed to give +problems also in MySQL. Using DESC table in TOra, the old schema was printed. + +Solution: thanks to Rado, I found out that the reason is that TOra has a schema +cache that it does not refresh. One should use the TOra schema browser for the +specified table to make sure the table schema is refreshed. Another possibility +is to use the SHOW CREATE TABLE statement in MySQL, which is guaranteed +to print out the full correct schema of a table. + diff --git a/RelationalCool/doc/README.gmt b/RelationalCool/doc/README.gmt new file mode 100644 index 000000000..283346141 --- /dev/null +++ b/RelationalCool/doc/README.gmt @@ -0,0 +1,44 @@ +Brief summary of the problem with GMT times which caused Windows +unit tests to fail on the first attempted release of COOL_1-2_0. + +An IOV is stored with a string '13:38 GMT' in the table. +The problem is that tagAsOfDate tries to use the string '12:38 GMT'. + +Let's look at what happens at retrieval after insertion. +1. findObject calls findSingleVersionObject where + - fetchObjectTableRowAtTimeSV retrieves the string in an AttributeList + - RelationalObjectTable::decodeRow transforms AttributeList into IObject +2. RelationalObjectTable::decodeRow + - transforms the string into a seal::Time using stringToTime + - calls the RelationalObject constructor with a seal::Time argument +3. RelationalObject constructor + - transforms seal::Time into nanosec (no 'local' argument needed) + - calls seal::Time constructor from nanosec argument (no 'local' argument) + - stores the date as a seal::Time +4. RelationalObject::insertionTime() + - returns a reference to the seal::Time +5. tag( asOfDate ) + - takes a seal::Time argument + (prints it out to screen using timeToString) + - calls fetchObjectTableRowsForTagging with the same seal::Time argument + (prints it out to screen using timeToString) +6. fetchObjectTableRowsForTagging + - binds the argument as string using timeToString + +In summary, this is what happens: + "13:38 GMT" (stored in IOV) + -> convert to seal::Time by stringToTime in RelationalObjectTable::decodeRow + -> convert to int64 by ns() in RelationalObject constructor + -> convert to seal::Time by constructor in RelationalObject constructor + -> convert to string by timeToString in fetchObjectTableRowsForTagging + +The problem must be either +- in seal::Time::ns() and seal::Time( ns ) +- in timeToString and stringToTime + +PS The bug was identified in the seal::Time constructor. +When converting using GMT times, tm_isdst should be set to 0. +Note that gmtime(timegm(tm)) is always equal to tm on Windows +only if isdst=0: if isdst=+1/-1, a one hour difference is observed +for instance in January/April. Note also that calling timegm +alters the value of the original tm. diff --git a/RelationalCool/doc/README.standalone b/RelationalCool/doc/README.standalone new file mode 100644 index 000000000..e0c4b84f3 --- /dev/null +++ b/RelationalCool/doc/README.standalone @@ -0,0 +1,221 @@ +------------------------------------------------ +Standalone installation on Windows (20.04.2005) +------------------------------------------------ + +Login a bash shell under cywgin. + + bash + +Follow the instructions in + + http://spi.cern.ch/workbook/howto/HowTo-Install-locally-lcg-software.html + +Create a directory /opt/sw/lcg in cygwin. +[In my case, first do 'ln -sf /cygdrive/l /opt' to create it on the L: disk] + + mkdir -p /opt/sw/lcg + +Download the installation script +Change the python version from 2.2 to 2.4 + + cd /opt/sw + wget http://service-spi.web.cern.ch/service-spi/external/distribution//lcg-installation-manager.py + cat lcg-installation-manager.py | sed 's/python2.2/python2.4/' > lcg-installation-manager.py.NEW + \mv lcg-installation-manager.py.NEW lcg-installation-manager.py + chmod +x ./lcg-installation-manager.py + +Download the required packages + + ./lcg-installation-manager.py --project=POOL_2_0_4 \ + --arch=win32_vc71_dbg --prefix=/opt/sw/lcg download + +This does not work! + + fetching file: + /opt/sw/lcg/external/distribution//POOL_2_0_4__LCG_win32_vc71_dbg.info + ERROR: could not download the file : POOL_2_0_4__LCG_win32_vc71_dbg.info + fetching file: /opt/sw/lcg/external/distribution//POOL_2_0_4.scram_output + ERROR: could not download the file : POOL_2_0_4.scram_output + Most probably POOL_2_0_4 is not available in the LCG software repository... + Please report this to LCG SPI + +Andreas confirms that there are some known problems on Windows. +The installation via the python script does not work on Linux, +but other /afs/cern.ch/sw/lcg/app/spi/tools/latest/scripts/ +solutions are possible, for instance one can look at +/afs/cern.ch/sw/lcg/app/spi/tools/latest/scripts/lcg-mirror-externals.bat + +...to be continued... + +------------------------------------------------ +Standalone installation on Windows (21.06.2005) +------------------------------------------------ + +Tried again the same as above, it does not work again. + +Try using the lcg-mirror-externals.bat script. +I tried by myself but failed miserably. + +Finally found some useful doc from SEAL on +http://seal.web.cern.ch/seal/snapshot/workbook/howtorelease.html + +1. Add environment variable AFS with value \\afs in MyComputer->Properties. + +2. Create directory "C:\Documents and Settings\avalassi\mycmt" +as this is needed by CMT. + +3. Copied lcg-mirror-externals.bat and lcg-mirror-externals.py +from /afs/cern.ch/sw/lcg/app/spi/tools/latest/scripts/ +to L:\sw and made them more verbose to debug them. + +4. From a command prompt in L:\sw I execute + lcg-mirror-externals -v 35 -p win32_vc71_dbg -o L:\sw\lcg\external + +But this only copies the LCGCMT package... + +Andreas proposed +/afs/cern.ch/user/p/pfeiffer/public/scripts/syncWinTree.py +but in the meantime I had done my own solution (see below). + +Removed AFS variable from MyComputer at the end. + +------------------------------------------------ +Standalone installation on Windows (21.06.2005) +------------------------------------------------ + +Developed my own script. +This creates a script on Windows, +executed on Linux to create a tar file of AFS, +the tar is then shipped back to Windows. +This is to avoid file copying over AFS on Windows. + +I also use a little script to download POOL locally, +rather than using CVS from Windows directly. +There seems to be a problem with CVS (or the SCRAM +installer using CVS) on Windows, it gets stuck. +Note also that I had to do (like on Mac!) + cp /afs/cern.ch/user/a/avalassi/.cvspass /tmp/79125CVSmodule/.cvspass +(where id gives 79125 for avalassi on cygwin), but this was not enough. + +1. On Windows (cygwin) ~ 1 minute + +From the standard COOL_HEAD using SITENAME=CERN: + +cd ~/myLCG/COOL_HEAD/config +coolMirrorExternals.csh + +2. On lxb0675 ~ 6 + 2 minutes + +cd ~/myLCG/COOL_HEAD/config +./coolMirrorExternals-win32_vc71_dbg.csh +scp /opt/avalassi/coolKit-win32_vc71_dbg/sw/lcg-win32_vc71_dbg.tar \ + avalassi@pcitdb38:/opt/sw + +(NB The archive is ~950 MB if it includes POOL and ~590 MB if it does not) + +3. On Windows (cygwin) ~ 4 minutes + +date +cd /opt/sw +rm -rf /opt/sw/lcg +tar -xvf lcg-win32_vc71_dbg.tar > lcg-win32_vc71_dbg-tar.txt +date + +4. On lxb0675 ~ 2 minutes + +cd ~/myLCG/COOL_HEAD/config +./coolInstallPool.csh +scp /opt/avalassi/poolKit/sw/lcg-POOL_2_1_0.tar \ + avalassi@pcitdb38:/opt/sw + +(NB The archive is ~3 MB) + +5. On Windows (cygwin) ~ few seconds + +cd /opt/sw +rm -rf /opt/sw/lcg/app/releases/POOL +tar -xvf lcg-POOL_2_1_0.tar > lcg-POOL_2_1_0-tar.txt + +6. On Windows (cygwin) + +Stop the AFS service and start a new cygwin window. + +cd /opt/sw/lcg/app/releases/POOL/POOL_2_1_0/ +export SITENAME=STANDALONE +export PATH=/opt/sw/lcg/app/spi/scram:$PATH +scram setup + +cd /opt/sw/lcg/app/releases/POOL/POOL_2_1_0/src +export SITENAME=STANDALONE +export PATH=/opt/sw/lcg/app/spi/scram:$PATH +date +scram b +date + +This is in any case rather slow (~35-40 minutes), +but at least it does work standalone and is faster than with AFS. +The CPU consumption is always around ~50% spread across two CPUs (25% each). +The largest CPU consupmption comes from python (peaks of 40% on one CPU). +Also perl shows up but never with as high CPU peaks as python. +One problem may be that there is not a single python process, +but rather very many python processes that start and finish. +With AFS, a lot of CPU was eaten up by the AFS daemons. + +----------------------------------------------------- +Standalone COOL installation on Windows (21.06.2005) +----------------------------------------------------- + +1. On lxb0675 + +This uses a siple private script to create a tar of the COOL_HEAD. + +cd ~/myLCG +./installCoolHead-local.csh +scp ~/myLCG/coolKit/COOL_HEAD.tar avalassi@pcitdb38:/opt + +2. On Windows (cygwin) + +cd /opt/ +rm -rf /opt/COOL_HEAD +tar -xvf COOL_HEAD.tar > COOL_HEAD-tar.txt + +3. On Windows (cygwin) + +Stop the AFS service and start a new cygwin window. + +cd /opt/COOL_HEAD +export SITENAME=STANDALONE +export PATH=/opt/sw/lcg/app/spi/scram:$PATH +scram setup + +cd /opt/COOL_HEAD/src +export SITENAME=STANDALONE +export PATH=/opt/sw/lcg/app/spi/scram:$PATH +date +scram b +date + +This is a factor ~5 faster than with AFS, +but it is still very slow (~50 minutes!). +Definitely scram is extremely slow (especially) on Windows. +With the CMT VisualStudio plugin things were MUCH faster. +Note that perl shows up more than for POOL, +but still python seems to be the bottleneck. + +NB: HOW TO IMPROVE? +It looks like python is the bottleneck (but maybe not the only one - +perl also shows up significantly in no-op mode on a prebuilt COOL). +1. One idea could be to try to precompile all .py files from the config +area into .pyc files (but should Python not compile them automatically?). +The only file that appears to be compiled as .pyc is unixToWinPath.py, +however other files are used too (I tried to remove all .py and execute +"scram b", the first errors were from other py modules missing. +However I gave a first quick try at this and it does not seem to help +(try also 'python unixToWinPath.py xxx' or 'python unixToWinPath.pyc xxx', +they are both very slow and not very different from each other). +2. Another possibility is to get rid of python and use instead precompiled +C++ programs or even just bash scripts inside the makefile fragments +(for unixToWinPath.py this should be rather easy). +3. However also perl and possibly other problems may show up. +It may be useful to do a no-o dry run of scram and measure where +the time is actually spent. diff --git a/RelationalCool/doc/TODO.txt b/RelationalCool/doc/TODO.txt new file mode 100644 index 000000000..ff83a6407 --- /dev/null +++ b/RelationalCool/doc/TODO.txt @@ -0,0 +1,182 @@ +Dec 2004 + +* Tablespaces +- Set default data and index tablespaces for all data + +Dec 2004 + +* Folder sets, folders, HVS nodes +- Main/Only priority: method to list children of a specific folder set, + possibly with recursion, possibly distibguish folder and folder sets within +- Add various list methods to HvsNode, inherited by folderset: + listChildren, listLeafChildren, listBranchChildren. + Or have a flag to show only leaves/branches? + Flag for recursive listing (or # nested directories to show)? +- Use protected inheritance for RelationalFolder : HvsNode? + For instance can be useful to just rename listLeafChildren + as listFolders... +- Add method getRootFolderSet() to IDatabase: note that listFolders + can then be delegated to this alone +- I would not delegate create/get folder to folder sets though: + use only full paths, no relative paths? Or allow relative paths + to make renaming eventually easier? +- CreateFolder and createFolderSet have a lot in common, + can be factored out +- Better definition of Folder and FolderSet classes: need a separate + IFolderSet or use IFolder to indicate both? I would definitely + use two separate classes, folder handles IOVs, while folderset + handles folders within itself. + +------------------------------------------------------------------------------ +Nov 2004 + +* DatabaseId +- Remove, replace by string in the createDatabase signature + +* RalDatabaseId +- Move to public API of RelationalCool? +- Add constructor from parameters? +- Add url() method to return a string? +- Add automatic conversion to a string + so that it can be passed to createDatabase? + +* Relational vs Ral or MySQL +- Prefix "Relational" for classes that may be both Ral or MySQL? +- Four levels of inheritance (IDatabase, Database, RelationalDatabase, + RalDatabase/MySQLDatabase)? + --> sas: why Database? + +* Group typedefs in types.h? ++ Or rather keep in separate files? eg XXXPtr in XXX.h + --> added types.h. Not intended to be manually included by API clients + (documented accordingly) + +* Define ValidityKey as seal::LongLong typedef ++ sas: done. + +* Add schema version to the management table + +* IOV table schema +- system-inserted IOV id ++ done. channelID, since, until, payload +- system-inserted insertion time + +* Define base Exception class in CoolKernel ++ sas: done. derived from seal::Exception ++ sas: done. derive RelationalException from cool::Exception + +* Clean up the hierarchy and loading of libraries +- RAL hierarchy + 0. Top: IRelationalService -> one singleton (in RelationalAccess) + "POOL/Services/RelationalService" - RelationalService + 1. IRelationalDomain -> three singletons (in three packages) + "POOL/RelationalPlugins/mysql/odbc" - MySqlODBCDomain + "POOL/RelationalPlugins/oracle" - OracleDomain + "POOL/RelationalPlugins/sqlite" - SQLiteDomain + 2. IRelationalSession -> one instance per open session +- in RAL a string only specifies where the data is (different drivers + can exist for MySQL, but the data is always the same, a table with + a given name in MySQL)... for COOL, different implementations may + imply completely different schemas for the data, it is not the same + ==> we should make the names specify the plugin (as Sven was saying) + ==> one possibility: use "ral::oracle::", "ral::mysql::", "mysql::"... + (in this example, ral and mysql would be two plugins) +- for comparison: RAL technology-dependent switch is in RelationalService.cpp + (technology name is directly translated to plugin name by adding a suffix, + e.g. 'oracle' -> IRelationalDomain 'POOL/RelationalPlugins/oracle' ) + +* PROPOSAL + 0. Top: IDatabaseService -> one singleton (in CoolKernel or CoolBase) + "COOL/Services/DatabaseService" - DatabaseService + 1. IDatabaseService -> one singleton per implementation + "COOL/KernelServicePlugins/ral" - RalDatabaseService + "COOL/KernelServicePlugins/mysql" - MySQLDatabaseService + 2. IDatabase -> one instance per open session (i.e. per open database) + +* Centralise all SQL implementation in the database, nothing in the folders +- Session is only needed in the database + +* Replace IDatabase boost pointers by references +- Place ownership of the instances in the RalDatabaseSvc + +* Beware of catch 22 in schema upgrades (sas, 2004-12-10) +- I've just encountered the following situation: +In preparation of the foldersets, the folder table schema changed. Now, when +dropDatabase executes, it uses the folder table to get the object table names. +Due to the schema change, this access failed and the dropDatabase chokes and +returns without dropping any tables. Admittedly, this is a very special case +typically encountered during the early development stages, but we've seen the +problem of dropDatabase not working successfully because it could not delete a +table before. It would be useful in general to make dropDatabase a bit more +robust, i.e. not dependent on obtaining all the management information to +do its job. + +I think dropDatabase should at least assert that the management tables are +dropped, so that a subsequent createDatabase is successful(*). It should report +if it cannot delete the object tables (e.g. due to a read failure in the folder +table) to make the user aware that there are data tables left. + +Folder creation then has to be looked at to decide what to do if a new object +table name clashes with an existing one. The options are: drop and recreate +the table or try with the next ID in the sequence. I think we should aim for +option 2. + +(*) This is what the drop database test currently checks for. + + +* The seal configuration file env variable does not seem to work. The msg +output level is only taken from the file it is in the current working +directory. + + +* [sas 2004-12-13: I wrote the following on the train before finding out that +Andrea had impemented option #2] +sas, 2004-12-10: +Rollback warning. Due do our transaction class doing an automatic rollback +in the destructor, we now get a warning from RAL each time a RalTransaction +goes out of scope: + POOL/RelationalPlugins/oracle Warning No active transaction to roll back +[edit: We still do get some warnings even though Andrea's changes make sure +it's not from our Transaction destructor when there has been a commit. We +get one commit warning per test, so it seems this occurs when the session +object goes out of scope (or something along that line).] + +Even if it doesn't incur a performance penalty it does not look pretty. +Perhaps we should add the following changes: + +RalTransaction::commit() { + m_session->commit(); + m_autocommit = true; +} + +RalTransaction::~RalTransaction() { + if ( m_autocommit ) { + m_session->commit(); + } else { + m_session->rollback(); +} + +or + +RalTransaction::commit() { + m_session->commit(); + m_closed = true; +} + +RalTransaction::~RalTransaction() { + if ( ! m_closed ) { + m_session->rollback(); +} + +The second option has the drawback that we lose the guarantee of not leaving +open transactions, which was the primary purpose of the class. I would go +with the first option, where the RalTransaction is practically switched to +autocommit mode after the first commit by the user. + +Basically the class is intended for single commits, you instantiate it +once, do a commit once and scope it in a way that there's no other SQL handled +by the transaction anyway. It still does provide the safeguard of rollback +should an exception occur before the transaction.commit(). + + + diff --git a/RelationalCool/doc/hvsTagsSpec.txt b/RelationalCool/doc/hvsTagsSpec.txt new file mode 100644 index 000000000..6e8a1d0ab --- /dev/null +++ b/RelationalCool/doc/hvsTagsSpec.txt @@ -0,0 +1,15 @@ +------------------------------------------------------------------------------ + +References: +- http://atlas.web.cern.ch/Atlas/GROUPS/DATABASE/project/doc/HVS.doc +- http://atlas.web.cern.ch/Atlas/GROUPS/DATABASE/detector_description/RALaccess +- http://atlassw1.phy.bnl.gov/cgi-bin/cvsweb.cgi/offline/Database/AthenaPOOL/RDBAccessSvc/src + +Download of Atlas software: +- setenv CVSROOT :kserver:atlas-sw.cern.ch:/atlascvs + cvs co -d RDBAccessSvc offline/Database/AthenaPOOL/RDBAccessSvc + cvs co -d RDBAccessTest offline/AtlasTest/DatabaseTest/RDBAccessTest +- Alternative CVS repository: + /afs/usatlas.bnl.gov/software/cvs/offline/Database/AthenaPOOL/RDBAccessSvc + +------------------------------------------------------------------------------ diff --git a/RelationalCool/doc/release.notes b/RelationalCool/doc/release.notes new file mode 100755 index 000000000..ccf98293d --- /dev/null +++ b/RelationalCool/doc/release.notes @@ -0,0 +1,3019 @@ +Package RelationalCool +Package managers: Andrea Valassi, Sven A. Schmidt and Marco Clemencic +Package contributors: Uli Moosbrugger, Romain Basset. + +============================================================================== +TODO +- Remove RelationalTableRow (replace it by Record) +- Rename defaultSpecification as metadataSpecification +- Rename fetchLastRowXXX as fetchLastRowMetadataXXX +- Add option to select only certain payload columns + +============================================================================== +!2008.11.10 - Andrea + +Internal doc for tag COOL_2_6_0. + +Summary of changes in RelationalCool with respect to COOL_2_6_0-pre6: +- Change API and implementation to replace 'const int f()' by 'int f()' + and get rid of gcc43 compilation warnings (bug #42584, aka task #8261). +- Fix bug #43622 (slow performance: countObjects must not call browseObjects). +- Use the new CORAL API ISession::remoteProperties (sr #103545) to determine + the remote database technology even when forwarded through a CORAL server. + +============================================================================== +!2008.10.21 - Andrea + +*** BRANCH RELEASE NOTES *** + +Tag COOL_2_4_0b. Rebuild of the 2.4.0a release for the LCG_54h configuration. +Add support for Oracle on MacOSX. Bug fixes in CORAL and frontier_client. +No change in the source code. Software version remains "2.4.0". + +NB: None of the _code_ changes in COOL_2_4-branch are released in COOL_2_4_0b! +NB: [there is one minor exception, RelationalCool/tests/RelationalDatabaseId] +NB: Only the _config_ branch changes are released in COOL_2_4_0b! + +Actually, some of the implementation files tagged as COOL_2_4_0b have a +different version number than those tagged as COOL_2_4_0a: they were committed +unchanged to the COOL_2_4_x branch and then retagged as CORAL_2_4_0b. + +============================================================================== +!2008.10.16 - Andrea + +Internal tag COOL_2_6_0-pre5-bis ('2008/10/16 10:00:00'). + +Changes in RelationalCool with respect to COOL_2_6_0-pre5: +- Performance optimization: issue COUNT(*) queries only on demand (task #7971). + This implies a minor backward-incompatible change in the CoolKernel API: + remove const qualifier from IObjectIterator methods size, isEmpty, hasNext. +- Remove '(forcereload=short)' from the aliases in dblookup.xml. + Use the environment variable FRONTIER_FORCERELOAD in QMTEST + to force the immediate refresh of Frontier short-lived cached queries. +- Define CORAL linkopts using the NEEDS_CORAL_BASE macro + (fix for LCGCMT bug #41579: link RelationalAccess only if needed). +- Start the port to gcc4.3. + Add missing STL headers to the implementation code. + Add gcc43 to all .cvsignore files. + +============================================================================== +!2008.09.27 - Andrea + +Internal tag COOL_2_6_0-pre5 (-D '2008/09/27 10:00:00'). + +Changes in RelationalCool with respect to COOL_2_6_0-pre4: +- Major internal cleanup of 'Ral' (CORAL) and 'Relational' (generic) classes. + > Add a generic cool::IRelationalCursor to handle relational queries. + This is returned by new method RelationalQueryMgr::prepareAndExecuteQuery. + Implement it as a RalCursor (wrapper for a CORAL ICursor). + Use it to replace RalObjectIterator by a generic RelationalObjectIterator. + Remove the old commened out COOL210 RalObjectIterator implementation. + Remove the registerIterator method (already commented out). + Replace the RalObjectIterator test by a RelationalObjectIterator test. + > Add static qualifier for RalQueryMgr methods + cursorNext and executeQuery (for TimingReport).</li> + Identify COOL sessions by their IRelationalTransactionMgr + (rather than the RalSessionMgr) in ObjectIteratorCounter. + Add a RelationalQueryMgr::clone() method. + Use a RelationalQueryMgr instead of a RalSessionMgr + in the RelationalObjectIterator constructor. + > Replace RalObjectMgr by generic RelationalObjectMgr. + The browseObjects method now returns a generic RelationalObjectIterator. + Remove the session method (not used). + Remove the sessionMgr method (inline it in implementation). + Remove the objectIdSequence method (inline it in implementation and tests). + Remove the unused storeObjects method (move it to the test); + keep the __storeObjects method (which does not start a transaction). + Replace the RalObjectMgr test by a RelationalObjectMgr test. + > Add RelationalQueryMgr::bulkUpdateTableRows for bulk updates. + Use the cool::RelationalQueryMgr bulk inserter and updater + in the implementation of RelationalObjectMgr. + > Replace RalObjectTable by generic RelationalObjectTable. + Replace the RalObjectTable test by a RelationalObjectTable test. + +============================================================================== +!2008.09.25 - Andrea + +Internal tag COOL_2_6_0-pre4. + +Summary of changes in RelationalCool with respect to COOL_2_6_0-pre3: +- Fix bug #40812 (insertionTimeOfLastObjectInTag for user tags). Add tests. +- Fix bug #41735 (add missing sequence tables to the coolPrivileges tool). +- Fix bug #42101 ("HEAD" tag not accepted for browsing SV folders). Add a test. +- Fix message printouts in log() for RalObjectMgr and RelationalObjectTable. +- Partial fix for bug #17903 (bulk insertion for MV [key,key+1] uses single + row insertion). Alg can be tuned using COOL_MVINSERTION_PREFETCH_MAXROWS. + Better performance observed when inserting over void. Abother improvement + (missing bulk updates) is needed for inserting over existing IOVs. + Add QMTEST tests for both the old and new algorithm. +- Add coolPrivileges logfiles to document the granted privileges (task #7825). + +============================================================================== +!2008.09.11 - Andrea + +Internal tag COOL_2_6_0-pre3. + +Summary of changes in RelationalCool with respect to COOL_2_6_0-pre2: +- Check for any missing tables in the coolValidateSchema tool (task #7691). + Differentiate between warnings, errors and fatal errors in the final dump. + Add a standalone test (using brute force to manually drop a table). +- Add a test for bug #36646 (metadata fields are visible in IObject::payload). +- Remove COOL workaround for CORAL bug #40315, aka COOL bug #40295 (rows not + deleted from coral_sqlite_fk when tables are dropped). Now fixed in CORAL. +- Add link options for Boost date_time after adding /DBOOST_ALL_NO_LIB for vc9. +- Drop inheritance of RelationalTransaction on ITransaction (#ifdef COOL270). +- Include in RelationalCool/tests/dblookup.xml the lcgnight entries from + /afs/cern.ch/sw/lcg/app/pool/db/dblookup.xml, for consistency. + +============================================================================== +!2008.09.01 - Andrea + +Internal tag COOL_2_6_0-pre2. + +Summary of changes in RelationalCool with respect to COOL_2_6_0-pre1: +- Implement addition of IOVs to partially locked tags (task #6541), add tests. +- Fix bug #40353 (do not modify verbosity if COOL_MSGLEVEL is not set). +- Remove the dependency of RelationalCool on CoolApplication. + Keep the dependency of RelationalCool on CoolKernel. + Keep the dependency of CoolApplication on RelationalCool. + Adapt all implementation code and tests. +- Change '#ifdef COOL260' into '#ifdef COOL270'. +- Disable the internal manual transaction handling if COOL270 is not defined. +- Add infrastructure for tests of the Frontier Squid cache (task #3440). + > Update the dblookup.xml file using the complex frontier URL syntax. +- Move RelationalObjectTable methods fetchRowsInTag, fetchRowsInHead, + fetchRowsInPastHead out of src into RalObjectTableTest (task #7646). + +============================================================================== +!2008.08.27 - Andrea + +Internal tag COOL_2_6_0-pre1. + +Summary of changes in RelationalCool with respect to COOL_2_5_0: +- Upgrade software version to COOL 2.6.0. +- Implement payload queries (server-side for FieldSelection and + CompositeSelection, client-side for any other IRecordSelection). + This functionality is protected behind#ifdef COOL260. + > Add class RelationalPayloadQuery. + > Add functional tests for server-side and client-side payload queries + (using a SelectionWrapper test class for the latter). +- Implement manual transaction handling and add test for several use cases. + This functionality is protected behind #ifdef COOL260. + > RelationalTransaction implements ITransaction if COOL260 is defined. + > Add RelationalFolder::maxBufferSize(). + > Add RelationalObjectMgr::__storeObjects. + > Add RalObjectMgr::__storeSingle/MultiVersionObjects. + > Modify the internal transaction manager interface and classes. +- Add virtual destructor for RelationalTransaction. +- Fix bug #22474 (bulk insertion is split across many transactions). Add test. +- Fix bug #38251 (hints ignored in COUNT(*) queries). +- Fix performance for 'SELECT COUNT(*) FROM ( subquery )' queries + by including again the list of selected columns in the subquery, + which had been removed between COOL 2.4.0 and COOL 2.5.0 (task #6482) +- Use the new goToNext API instead of the obsolete hasNext API + in the internal implementation of RalObjectIterator2. +- Enhance the coolAuthentication tool to display all CORAL replicas. + > Add option to display only 1st replica (R/O or R/W) or 1st R/W replica. + > Fix a small memory leak (related to CORAL bug #40507). + > Port the new features to the CoolAuthentication python package too +- Workaround for Windows VC9 bug #40142: #undef symbols 'DELETE' and 'ERROR' +- Workaround for Windows VC9 bug #40143: specify namespace in cool::MSG. +- Remove workaround in the replication tool for SQLiteAccess bug #24867 + (workaround was to avoid dropping and recreating FKs during replication) + > But the SQLiteAccess bug is not fully fixed and COOL tests fail + (see also CORAL bug #40315 and COOL bug #40327) +- Add workaround for CORAL bug #40315 (coral_sqlite_fk not updated when + tables are dropped), aka COOL bug #40295 (error messages for sqlite) +- Implement RelationalObjectTable::fetchRowsInHead using + queryDefinitionGeneric insted of whereDataHead and whereClauseHead. +- Rename RelationalObjectTable::fetchLastRow as fetchLastRowSV and comment + it out (it is only present, commented out, in test_RalObjectTable). +- Remove RelationalObjectTable::fetchRowAtTimeInTag. This was already not + used, except in one test (which has been kept with inlined implementation). +- Remove RelationalObjectTable methods whereClauseHead, whereDataHead, + whereClauseTag, whereDataTag. These were already not used, except in tests. +- Add empty skeleton for RelationalFolder::truncateObjectValidity(). +- Small fix in the schema evolution tool using CORAL msgVerbosity(). +- Temporary workaround for Boost 1.35.0 bug (warnings from Boost headers). +- Get rid of cool::Sleep (use cool::sleep everywhere). +- Add cmt/version.cmt to prepare support for the latest CMT version. +- Remove the old test infrastructure using bash scripts. +- Remove SCRAM configuration fragments. +- Remove SeaUtil_SealTimer.h (keep SealUtil_SealTimer.h). + +============================================================================== +!2008.07.16 - Andrea + +Copy back COOL_2_4_0a code into COOL_2_4-branch. + +This removes a useful bug fix but also some performance improvements we +were not really sure about. Make the COOL_2_4-branch clean to be released. + +============================================================================== +!2008.07.16 - Andrea + +Add workaround for LCGCMT bug #38934 (python module installation is broken +by LCGCMT_55a). This was removed immediately after the LCGCMT bug fix. + +[Changes included by Andrea in COOL_2_4-branch on 2008.07.16] + +============================================================================== +!2008.06.10 - Andrea + +Tag COOL_2_5_0. Production release with API semantic changes, API extensions +and package structure changes to remove the dependency on SEAL. +Upgrade to LCG_55 using the 'de-SEALed' CORAL_2_0_0. + +Summary of changes in RelationalCool with respect to COOL_2_4_0a +(refer to the web release notes for more details): +- CMT package structure changes. +- Remove internal dependency on SEAL + > De-SEAL all tests and utilities. + > Replace seal::TimeInfo::sleep with a sleep function based on Boost. + > Import the SealUtil timing classes (after removing what is not needed). +- Add new internal class CoralConnectionServiceProxy. +- Performance improvements (many many changes). +- There may be more changes that are only documented in the web release notes! + +============================================================================== +!2008.06.04 - Andrea + +*** BRANCH RELEASE NOTES *** + +Tag COOL_2_4_0a. Rebuild of the 2.4.0 release for the LCG_54g configuration. +Port to osx105 and .so shared lib names on MacOSX. Changes in CORAL and ROOT. +No change in the source code. Software version remains "2.4.0". + +NB: None of the _code_ changes in COOL_2_4-branch are released in COOL_2_4_0a! +NB: Only the (osx105) _config_ branch changes are released in COOL_2_4_0a! + +============================================================================== +!2008.05.21 - Marco + +Added a COOL specific implementation of coral::IMsgReporter. +It is activated setting the environment variable USE_COOL_MSGREPORTER, and the +level can be tuned with COOL_MSGLEVEL (by default it is "ERROR"). + +============================================================================== +!2008.04.18 - Marco + +Fixed bug #35734: compilation error on Windows after removeal of SEAL. + +============================================================================== +!2008.04.11 - Marco + +Removed dependency on SEAL. +- De-SEAL all tests and utilities. +- Replace seal::TimeInfo::sleep with a sleep function implemented using Boost. +- Import the SealUtil timing classes (after removing what is not needed). + +============================================================================== +!2008.04.09 - Andrea + +Algorithmic fix: the internal implementation classes exchange a shared pointer +to a connection service proxy (CoralConnectionServiceProxy) rather than a +service reference. The proxy contains a pointer that is reset to null when the +COOL database service is deleted (the CORAL connection service may or may not +continue to exist, but is declared to be unusable). Adapt utilities and tests. + +============================================================================== +!2008.04.10 - Andrea + +Include a modified version of Jaco Kroon's signal handler. +See http://www.tlug.org.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV +and http://cool.cvs.cern.ch/cgi-bin/cool.cgi/cool/contrib/ExternalTests/SignalHandler/src/sigsegv.cpp + +This is enabled only if environment variable COOL_ENABLE_COOLSIGNALHANDLER +is set (this replaces COOL_ENABLE_SEALSIGNALHANDLER and the SEAL handler). + +============================================================================== +!2008.04.09 - Andrea + +Modify some of Marco's changes to remove SEAL. +- In COOL_2_4_0, RalDatabaseSvc could be loaded as a SEAL plugin + (either through CoolApplication or directly from a seal Context). +- In Marco's code, RalDatabaseSvc could be loaded as a Reflex plugin. +- In the present code, RalDatabaseSvc is linked directly to CoolApplication. + +Method IApplication::connectionSvc returns a reference (rather than +a shared pointer) to the coral::IConnectionService. This reference +is exchanged internally between all relevant RelationalCool classes. + +Class Application is implemented by instantiating a CoralApplication +from the RelationalCool library. Class CoralApplication is needed in +RelationalCool to implement tests and utilities: it cannot be in +CoolApplication as otherwise there would be a circular dependency. + +Modify all tests and utilities so that they bootstrap COOL using the +CoralApplication class from RelationalCool rather than the Application +or DatabaseSvcFactory classes from package CoolApplication. +Package CoolApplication is now built after RelationalCool. + +Remove the infrastructure to load RalDatabaseSvc as a Reflex plugin. + +Remove RalDatabaseSvcLabel.h (modules.cpp had already been removed) +because RalDatabaseSvc is not a SEAL plugin anymore. + +Internally replace seal::MessageStream by coral::MessageStream. +- WARNING: changing message verbosity has no effect yet. +- WARNING: retrieving message verbosity is not possible yet. +- WARNING: changing or retrieving message verbosity of an individual + cool::IApplication affects all COOL and CORAL applications because + this is implemented in coral::MessageStreams using static methods. + +Remove the dependency on Reflex, add a (temporary!) dependency on SEAL. +Remove the private dependency of RelationalCool on CoolApplication: +this would imply a circular dependency because now it is CoolApplication +that links the RelationalCool library (which is not a plugin anymore). + +Keep a dependency on CoolApplication headers only (class CoralApplication +implements the IApplication interface defined in package CoolApplication). + +Build the RelationalCool library as an LCG CMT 'shared' library +(not a Reflex 'plugin' library nor a SEAL 'module' library). + +Add build directives to mkdir the bin directory if it does not exist +(else scripts cannot be copied there). + +============================================================================== +!2008.04.03 - Andrea + +Remove lines containing 'Invalid folder node path' from the qmtest XML report. +This is needed in the SEAL-less HEAD version where Error messages +are not filtered out by the new message reporting infrastructure: +line 'ralDb->createFolderSet( "/my\folderset" )' triggers an error +printout with a binary character that fails the XML parsing. +This is not needed in COOL_2_4-branch but it is included for consistency. + +[Changes included by Andrea in COOL_2_4-branch on 2008.04.03] + +============================================================================== +!2008.04.03 - Andrea + +Improve summarizeAll.csh to accept one or more CMTCONFIG values as arguments +when building the qmtest result summaries. + +[Changes included by Andrea in COOL_2_4-branch on 2008.04.03] + +============================================================================== +!2008.04.02 - Andrea + +Created a COOL_2_4 branch off COOL_2_4_1-pre1 for the whole of COOL: + cvs rtag -r COOL_2_4_1-pre1 -b COOL_2_4-branch cool + +============================================================================== +!2008.04.02 - Marco + +Re-enabled LFC support in utilities. + +============================================================================== +!2008.03.20 - Marco + +Removed seal::Context. +cool::RalDatabase can be loaded as a Reflex plug-in. +All the references to seal::MessagesService have been removed and now only +coral::MessageStream is used. + +The tests have been updated, but the utilities are not yet ready. + +============================================================================== +!2008.03.03 - Andrea + +Internal tag COOL_2_4_1-pre1 (bug fixes). +The only changes wrt COOL_2_4_0 are in RelationalCool. + +============================================================================== +!2008.02.29 - Andrea + +Test the parsing of middleTier() in the RelationalDatabaseId class. + +============================================================================== +!2008.02.29 - Andrea + +Remove a few compilation warnings from cppunit the hard way +(remove all uses of CPPUNIT_TEST_EXCEPTION). + +============================================================================== +!2008.02.29 - Sven + +Fix for bug #33989 (setTagDescription should fail if called from wrong node). + +============================================================================== +!2008.02.29 - Andrea + +Test for bug #33989 (setTagDescription should fail if called from wrong node). + +============================================================================== +!2008.02.28 - Andrea + +Tag COOL_2_4_0. Production release with backward compatible API extensions. +Upgrade to LCG_54b using CORAL_1_9_5. + +============================================================================== +!2008.02.27 - Andrea + +Add a test for CORAL bug #33401 as reported by Richard for COOL (ORA-00904). + +============================================================================== +!2008.02.26 - Sven + +Implement IHvsNode::setTagDescription. +This modifies only the global tag table (not the local one). +It can be used to set the description of both IOV and HVS tags. +Add several tests for setTagDescription under various use cases. + +============================================================================== +!2008.02.26 - Andrea + +Prototype support for coralxxx://host:port&... URLs (CORAL server backend). +Add a few tests. + +============================================================================== +!2008.02.25 - Andrea + +Implement userTagOnly argument to IFolder::storeObject (task #6153), to allow +users to avoid the duplication of MV data in the global and user tag HEADs. +Add a few tests. + +============================================================================== +!2008.02.20 - Andrea (changes committed before COOL_2_3_1 but not tagged) + +Change the config: do not install the RelationalCool headers directory +even if it is found (this may happen if cvs co -P is not used). + +============================================================================== +!2008.02.19 - Andrea (changes committed before COOL_2_3_1 but not tagged) + +Upgrade software version to 2.4.0. + +Add two API extensions to be released as COOL_2_4_0: +- add IHvsNode::setTagDescription (task #6394), to allow users to first + create a tag (also as a user tag or HVS tag) and then set its description +- add userTagOnly argument to IFolder::storeObject (task #6153), to allow + users to avoid the duplication of MV data in the global and user tag HEADs + +Remove Sven's IFolder::setTagDescription from the API. +Keep the implementation, but comment it out: this should be moved to +RelationalHvsNode and should not modify the local tag table (to be ignored). +Comment out Sven's tests for setTagDescription. +The implementation of setTagDescription presently throws an exception. +No tests exist to check that this is the case. + +The implementation of storeObject( userTagOnly=true ) throws an exception. +Add a test for storeObject( userTagOnly=true ), checking that it throws. + +============================================================================== +!2008.02.18 - Sven (changes committed before COOL_2_3_1 but not tagged) + +Implement IFolder::setTagDescription. +This modifies both the global and local tag tables. +It cannot be used to set the description of HVS tags for folder sets. +Add several tests for setTagDescription under various use cases. + +============================================================================== +!2008.02.21 - Andrea + +Tag COOL_2_3_1. Bug-fix production release (binary compatible with 2.3.0) +with performance optimizations for multi-version retrieval and insertion. +Upgrade to LCG_54a including bug fixes in ROOT 5.18.00a. + +============================================================================== +!2008.02.13 - Andrea (-D '2008/02/13 19:30:00') + +Internal tag COOL_2_3_1-pre2 (bug fixes and performance optimizations). +Use the default LCG_54 (including ROOT 5.18) on all platforms. + +============================================================================== +!2008.02.13 - Romain and Andrea + +Performance optimization in MV insertion of IOVs with user tags (task #6086). +Part 2 of the optimization: performance improvement for the UPDATE statement. + +When new IOVs are inserted in MV mode, they may overlap with older IOVS that +were previously part of the HEAD: these IOVs need to be updated to mark that +they are not part of the HEAD any longer. The new UPDATE implementation uses +the same 'SELECT MAX(IOV_SINCE)' subquery used in most retrieval use cases +to speed up the lookup of which IOVS need to be updated. + +The latest implementation is enabled by default and reuses almost the same +SQL code that is defined in RelationalObjectTable::queryDefinitionGeneric +(originally developed for MV tag retrieval, task #5820). + +The old COOL_2_3_0 implementation is used by default for MySQL because of +an intrinsic limitation of MySQL (an UPDATE statement cannot update a table +which is also SELECTed from in a subquery of the UPDATE statement). +The old COOL_2_3_0 implementation can also be reenabled for the other +backends if the environment variable COOL_TASK6086_DISABLERBUPDATE is set. + +Limitation of the current implementation: a better SQL statement has been +designed for Oracle, but it cannot be implemented because of missing +support for hints in UPDATE statements in CORAL (sr #103420). + +============================================================================== +!2008.02.08 - Andrea + +Performance optimization in MV insertion of IOVs with user tags (task #5820). +All subqueries which can be rewritten ("merged") as multi-table joins (and +which the Oracle optimizer internally does merge this way) are now +consistently rewritten explicitly as multi-table joins. + +============================================================================== +!2008.02.08 - Andrea + +Performance optimization in MV insertion of IOVs with user tags (task #5820). +A consistent approach is used for naming SQL query blocks and table aliases +in different use cases, making the code much more readable and easier to +maintain and improve. Add several hooks for changing the default query hints +using environment variables for faster performance tests. + +============================================================================== +!2008.02.08 - Andrea + +Performance optimization in MV insertion of IOVs with user tags (task #5820). +When browsing for IOVS between times t1 and t2, the COALESCE function in SQL +is now used consistently (instead of OR or UNION ALL clauses) to concatenate +the IOVS valid at time t1 (since <= t1 < until) with the IOVS starting +between t1 and t2 (t1 < since < t2). + +============================================================================== +!2008.02.05 - Andrea + +Enable the RelationalObjectTable::queryDefinitionGeneric method also for +MV retrieval from standard tags (task #5820). This was previously handled +by method queryDefinitionTag, which now delegates most of its functionality +to the generic method (also used for user tags - task #6086). + +The same method is designed to also handle the SV case (but is not used in +production yet). It can also be adapted for MV HEAD retrieval. + +============================================================================== +!2008.02.05 - Romain and Andrea + +Performance optimization in MV insertion of IOVs with user tags (task #6086). +Part 1 of the optimization: performance improvement for the SELECT statement. + +============================================================================== +!2008.02.04 - Andrea + +Internal tag COOL_2_3_1-pre1 (bug fixes and performance optimizations). +Upgrade COOL software version to 2.3.1. + +============================================================================== +!2008.02.04 - Sven + +Fix for bug #32976 in the replication tool. + +============================================================================== +!2008.01.29 - Andrea + +Performance optimization for MV retrieval from standard HEAD tags (task #5820). +Main change: query the IOV2TAG table instead of the IOV table! +The new strategy is in RelationalObjectTable::queryDefinitionTag. + +============================================================================== +!2008.01.21 - Andrea + +Tag COOL_2_3_0. Production release with backward compatible API extensions. +Upgrade to LCG_54 using Python 2.5, ROOT 5.18 and several other new externals. + +PyCool is not supported on MacOSX because of bug #32770 in ROOT 5.18.00. +The COOL nightlies are all green (except for the PyCool tests on MacOSX). + +============================================================================== +!2008.01.17 - Andrea + +Undo the attempt at performance optimization for task #6086. +There was no clear performance benefit, and some penalty instead. +Keep the new code to be used in the future, but comment it out. + +============================================================================== +!2008.01.17 - Andrea + +Ensure that RelationalCool scripts are installed by 'cmt make all' +and not only by 'cmt make all_groups' (task #5835). + +============================================================================== +!2007.01.16 - Sven + +Fix bug #32610 in the replication tool when replicating databases +where renamePayload or extendPayloadSpecification has been used. + +============================================================================== +!2007.01.15 - Andrea + +Attempt at performance optimization for MV user tag insertion (task #6086). + +Add new RelationalObjectTable::queryDefinitionGeneric method that supports +both the SV and MV user tag cases, with improved queries on since/until. +Use this method in production also for the SV case (remove queryDefinitionSV). +Eventually this can be used in a more general reimplementation of all queries. + +============================================================================== +!2007.01.09 - Andrea + +New signature (record) for IFolder::extendPayloadSpecification (task #5742). +This allows users to add more than one columns at once and to specify +a non-null default value for the additional column of all existing rows. +Remove the old signature (name, type). Add tests for non-null default values. + +Warning: the replication tool has not yet been ported to support the new +IFolder::extendPayloadSpecification functionality (bug #32610). + +============================================================================== +!2008.01.08 - Andrea + +Disable CppUnit header warnings from gcc41 nightlies (task #5837). + +============================================================================== +!2007.12.19 - Andrea + +Internal tag COOL_2_3_0-pre1 (new COOL API extensions on standard LCG_53f). +All CMT tests successful, bash tests not updated. Software version is 2.3.0. + +============================================================================== +!2007.12.17 - Sven + +Complete task #4327 by adding a few new tests in test_RelationalFolder: + + CPPUNIT_TEST( test_findObjects_channelName_SV ); + CPPUNIT_TEST( test_findObjects_channelName_MV ); + CPPUNIT_TEST( test_findObjects_channelName_MV_tag ); + CPPUNIT_TEST( test_findObjects_channelName_MV_userTag ); + CPPUNIT_TEST( test_countObjects_channelName_SV_all ); + CPPUNIT_TEST( test_countObjects_channelName_SV_range ); + CPPUNIT_TEST( test_countObjects_channelName_MV_all ); + CPPUNIT_TEST( test_countObjects_channelName_MV_tag ); + CPPUNIT_TEST( test_countObjects_channelName_MV_userTag ); + +============================================================================== +!2007.12.17 - Andrea + +Centrally maintain credentials for the nightly builds (user lcgspi) in +/afs/cern.ch/sw/lcg/app/pool/db. Files authentication.xml and dblookup.xml +are automatically copied to the private directories on MacOSX and Windows +using Samba. Set CORAL_AUTH_PATH and CORAL_DBLOOKUP_PATH equal to +- /afs/cern.ch/sw/lcg/app/pool/db on Linux +- $HOME/private on MacOSX +- %USERPROFILE%\private on Windows + +Remove dblookup entries for users roiser and pkolet +(the nightly tests are only executed as user lcgspi). + +============================================================================== +!2007.12.16 - Sven + +Implemented channelName based ChannelSelection support for +browseObjects methods. Relevant tests are in test_RelationalFolder: + + CPPUNIT_TEST( test_browseObjects_channelName_SV_all ); + CPPUNIT_TEST( test_browseObjects_channelName_SV_range ); + CPPUNIT_TEST( test_browseObjects_channelName_MV_all ); + CPPUNIT_TEST( test_browseObjects_channelName_MV_tag ); + CPPUNIT_TEST( test_browseObjects_channelName_MV_userTag ); + +These should cover all possible where clauses used by browseObjects code. +The calls findObjects and countObjects also go through browseObjects. + +These changes almost complete task #4327. + +============================================================================== +!2007.12.14 - Andrea + +Upgrade COOL software version to 2.3.0. + +============================================================================== +!2007.12.13 - Andrea + +Split RelationalFolder and Channel tests. Workaround for COOL bug #27650 +(CORAL bug #28547): long tests fail because SQLite file descriptors are not +released (SQLite feature) and the maximum cannot be increased beyond 1024. + +============================================================================== +!2007.12.13 - Andrea + +Added enum value HvsTagLock::PARTIALLYLOCKED (task #4606). + +A PARTIALLYLOCKED tag behaves like a LOCKED tag except in the following cases: +1. It is possible to add a tag relation from a partially locked parent HVS tag +to a tag in a child HVS node (if no tag relation exists for that child node). + +Eventually, one or both of the following functionalities may also be added +(but for the moment, neither of them is implemented yet): +2. It is possible to add IOVs to a partially locked user tag, only if the +newly inserted IOVS have no overlap to those already existing in the user tag. +3. It is possible to retag the HEAD of a folder with a partially locked tag, +only if the retag operation only results in adding new IOVS to the tag. + +============================================================================== +!2007.12.13 - Andrea + +Disable the CORAL connection pool automatic cleanup if the environment +variable COOL_DISABLE_CORALCONNECTIONPOOLCLEANUP is set (bug #30435). +Disable it by default in COOL tests by modifying config/cmt/requirements. + +============================================================================== +!2007.12.13 - Andrea + +Added method IFolder::listChannelsWithNames (task #5868). +Added two tests in the RelationalFolder and RalDatabase test suites. + +Aborted attempts to add method IObject::channelName. The functionality +required by Atlas is provided by IFolder::listChannelsWithNames instead. + +============================================================================== +!2007.12.12 - Andrea + +Added method IFolder::extendPayloadSpecification (task #5742). +Added two tests in the RelationalFolder and RalDatabase test suites. + +============================================================================== +!2007.12.12 - Andrea + +Moved exception DatabaseOpenInReadOnlyMode to the public API (task #5743). +This was previously defined as a RelationalException in RelationalCool. + +============================================================================== +!2007.12.03 - Marco + +Added dblookup entries for uses pkolet and lcgspi for the SPI nightly tests. + +============================================================================== +!2007.11.26 - Sven + +Added channel selection by channel name in the ChannelSelection class. +Implemented channel selection by channel name in RelationalObjectTable.cpp. +Added four tests for the new selections to the ChannelSelection test suite. +Added test_browseObjects_channelName to the RelationalFolder test suite. + +============================================================================== +!2007.11.13 - Andrea + +Tag COOL_2_2_2. Production release (binary compatible with 2.2.0) with many +performance and configuration improvements and bug fixes. New versions of +CORAL and Frontier server (fixing all pending problems in the tests) and ROOT. +This is the first COOL release built by the SPI team (and no SCRAM config). + +============================================================================== +!2007.11.09 - Andrea/Romain + +Reimplement user tags queries using the new RelationalQueryDefinition. +This is needed to implement hints to use the 5d index for task #4381. + +Add the following hint to try and stabilize the execution plan: +/*+ ALL_ROWS FULL(T) INDEX(O (USER_TAG_ID)) LEADING(T O) USE_NL(O)*/. + +============================================================================== +!2007.11.08 - Andrea + +Internal tag COOL_2_2_2-pre2 (using private CORAL192 build and SEAL193 copy). +All CMT tests successful, bash tests not updated. Software version is 2.2.2. + +============================================================================== +!2007.11.07 - Andrea + +Upgrade software version to 2.2.2. + +============================================================================== +!2007.11.07 - Andrea + +Internal tag COOL_2_2_2-pre1 (using private CORAL192 build and SEAL193 copy). +All CMT tests successful (no pending Frontier failures). +Bash tests not updated (Wine failures are expected). + +============================================================================== +!2007.11.06 - Andrea + +Add tests for string and templated methods payloadValue (task #2859). +These methods were not tested anywhere in the C++ test suite before. +Test also FieldIsNull and FieldCppWrong from the templated method. + +============================================================================== +!2007.10.25 - Romain + +Performance improvement in IOV insertion by stabilizing the execution plan +for the 'select last IOV' query (in RalObjectMgr::fetchLastRowsWithNewData, +add hint "/*+ INDEX(C) INDEX_RS_ASC(O) LEADING(C O) USE_NL(C O) */", +replacing the previous "/*+INDEX(O)*/" hint that was not appropriate). + +============================================================================== +!2007.10.30 - Andrea + +Added a fake make target "examples" to please nmake (task #5414). + +============================================================================== +!2007.10.26 - Andrea + +Implement constraints on allowed characters in a node name (task #4371). + +Modified tests for bug #30751 and task #4371: +- test that creation of folder[set] with a trailing space in its name fails +- remove test of creation of two folder[set]s with almost the same name + +All tests are now successful (including MySQL). + +============================================================================== +!2007.10.26 - Andrea/Sven + +Added tests for bug #30751 and task #4371: +- test that creation of folder[set] with a trailing space in its name succeeds +- test creation of two folder[set]s with the same name but for a trailing space + +The second set of tests fails for MySQL because of an intrinsic limitation +of the MySQL 5.0 server ("x" and "x " are indistinguishable, for instance +in enforcing primary keys and in where clauses). + +============================================================================== +!2007.10.26 - Andrea + +Fix schema evolution tool so that UK/FK errors from CORAL are not printed +when the corresponding exception is caught in the normal program flow. + +============================================================================== +!2007.10.26 - Andrea + +Fix in enforcing "folders with schema version 2.0.0 are no longer supported". +Method listAllTables should not fail (we know all tables), else we may +get failures in schema evolution (MySQL was indeed failing... not Oracle?). + +Extend exceptions UnsupportedFolder[Set]Schema to accept any message. +Move UnsupportedFolder[Set]Schema exceptions to file RelationalException.h. + +Add a PanicException for all PANIC situations (asserts). + +Add tests for listAllTables with node schema versions 1.9.9, 2.0.9, 2.9.0 +(panic, success, fail) and with folder schema version 2.0.0 (success). + +============================================================================== +!2007.10.25 - Romain + +Performance improvement in IOV insertion (to be cross-checked) +by stabilizing the execution plan for the 'select last IOV' query +(add the "/*+INDEX(O)*/" hint in RalObjectMgr::fetchLastRowsWithNewData). + +============================================================================== +!2007.10.25 - Andrea + +Fix for performance and functional bug #30431 in MV folders: +in RelationalFolder.cpp, use the channels table for MV existsChannel. + +Fix for functional bug #30443 and performance bug #24448 in MV folders: +in RelationalFolder.cpp, use the channels table for MV listChannels. + +Remove all workarounds for bug #23755, including: +- in RelationalFolder.cpp, remove the old fixes for + bug #24445 (MV setChannelName fails without createChannel), + bug #24449 (MV existsChannel fails without createChannel), + bug #24461 (MV setChannelDesc fails without createChannel) and + bug #24463 (MV channelName fails without createChannel); +- in RalObjectMgr, make channel table manipulation private again; +- in RelationalObjectMgr, dropChannel continues to check also the IOV table + (because this is the semantics: throw if the channel has some IOVs); +- in RelationalObjectTable, remove listChannels (but keep existsChannel). + +These changes complete the fix for bug #23755. + +All RelationalCool and PyCoolUtilities tests are now successful. + +============================================================================== +!2007.10.25 - Andrea + +Folders with schema version 2.0.0 are no longer supported. +This ensures that folders have been evolved to 2.0.1 or higher (i.e. that FK +constraints exist between each IOV table and the corresponding channel table). + +Add tests that using or dropping a 2.0.0 folder fails. +Add tests that dropping a database containing a 2.0.0 folder also fails. + +Rename RelationalFolderNew as RelationalFolderUnsupported. +Rename RelationalFolderSetNew as RelationalFolderSetUnsupported. + +============================================================================== +!2007.10.24 - Andrea + +Add new tool coolValidateSchema to check internal consistency of databases. +Presently this only investigates possible data corruption due to bug #23755, +e.g. due to unenforced FK constraints in sqlite (checks that channels in all +IOV tables are listed in the corresponding channel tables, both MV and SV). + +============================================================================== +!2007.10.24 - Andrea + +Use RelationalQueryDefinition in RalObjectMgr::fetchLastRowsWithNewData +(task #5282 - also see task #5654, will rewrite this query to fix the plan). + +Add the option to define a hint in an IRelationalQueryDefinition +(thanks to Romain for the suggestion - e.g. can be useful for task #5654). + +Clean up result set specification handling for queries executed from an +IRelationalQueryDefinition: the spec is in the query definition, +no need to specify it as an argument to fetchOrderedRows. + +============================================================================== +!2007.10.23 - Andrea + +Add pure virtual methods to RelationalQueryMgr for selecting or counting rows +from a query defined using an IRelationalQueryDefinition (task #5282). + +============================================================================== +!2007.10.23 - Andrea + +Add a new test_SealPluginDump.sh test to the bash test suite (task #5678). +Running the test also makes sure that the COOL plugins are loaded for SCRAM. +The same machinery was implemented by Marco for CMT and QMTEST. + +============================================================================== +!2007.10.23 - Andrea + +Use the MySQL integration cluster itrac424 instead of Marco's pclhcb55 +for Andrea's private tests (task #5412). Not yet done for the nightlies. + +============================================================================== +!2007.10.23 - Andrea + +Fix bug #30500 (wrong exception thrown when attempting to update a database +that is open in read-only mode): add new exception DatabaseOpenInReadOnlyMode, +thrown by both transaction managers and also by RalObjectMgr::storeObjects. + +Add a test for bug #30500 (check that DatabaseOpenInReadOnlyMode is thrown +when attempting to update a database that is open in read-only mode). + +============================================================================== +!2007.10.20 - Sven + +Fix bug #30578 in the replication tool. + +============================================================================== +!2007.10.16 - Andrea + +Add tests for bug #30431 (MV existsChannel) and bug #30443 (MV listChannels). + +============================================================================== +!2007.10.16 - Andrea + +Fix bug #30361 in the schema evolution tool. + +============================================================================== +!2007.10.11 - Andrea + +Tag COOL_2_2_1. Production release (binary compatible with 2.2.0) with many +configuration improvements, feature enhancements and bug fixes. New versions +of CORAL (with important bug fixes for SQLite and Frontier), ROOT and SEAL. +This is the first COOL release with support for MacOSX/Intel platforms. + +============================================================================== +!2007.10.09 - Andrea + +Drop SEAL package granularity in SCRAM as there is no .SCRAM in SEAL_1_9_3. +CoolKernel depends on SEAL and adds link libraries SealBase, PluginManager +and SealKernel by default. SealUtil and SealServices are added where needed. + +============================================================================== +!2007.10.08 - Andrea + +Internal tag COOL_2_2_1-pre5. Last private tag before COOL_2_2_1. +All CMT/SCRAM tests successful on all platforms using a private CORAL191 +(except for the last pending failure RO_02b1 - bug #23368 in FrontierAccess), +including MacOSX/PPC (last build) and gcc41 (not built for official COOL221). +Non-debug osx104_ia32_gcc401 not built, test results copied from debug version. + +Changes in RelationalCool code, tests and test results (none in config): +- Allow back-insertion of non-overlapping IOVS in SV folders (task #3138). + > Add several tests for task #3138, all successful. +- Avoid a few warnings in Windows. +- Reenable tests for sqlite bug #22485, now fixed. +- Add a few timing reports for task #4672. +- Software version is now 2.2.1 +- Update test results for cygwin (.NT) again.. + +============================================================================== +!2007.09.29 - Sven + +Partial implementation of task #3138: allow back-insertion of IOVS +in SV folders as long as there are no IOV overlaps. + +Use case #3 is implemented: back-insertion is possible +if IOVs are inserted one at a time (no bulk insertion). + +Use case #2 is implemented: back-insertion is possible with bulk insertion, +if any back-inserted IOV is the only IOV inserted in its channel (while +many IOVs can be inserted at a time in channels with no back-insertion). + +Use case #3 is not yet implemented: back-insertion is not possible with +bulk insertion if several IOVs are inserted at a time in a channel where +at least one IOV is back-inserted. + +============================================================================== +!2007.09.18 - Marco + +Minor changes to avoid a few warnings on Windows +in RelationalQueryDefinition.cpp and RalQueryMgr.cpp. + +============================================================================== +!2007.09.02 - Andrea + +Add a few more timing reports for task #4672. + +============================================================================== +!2007.08.29 - Andrea (-D '2007/08/29 13:30:00') + +Internal tag COOL_2_2_1-pre4. +First version with successful tests of slc4_ia32_gcc41 on SCRAM/BASH, +including SQLite and Frontier support and complete private config for CMT. + +No changes in RelationalCool code or config. + +Changes in bash test results: +- All OK for slc4_ia32_gcc41 (after enabling SQLite/Frontier). +- Replace 'Skip test' by 'Skip' in existing logfiles for mergeTestOutput. + +============================================================================== +!2007.08.24 - Andrea (-D '2007/08/24 17:15:00') + +Internal tag COOL_2_2_1-pre3. +First version with successful tests of MacOSX Intel on both CMT/QMTEST +and SCRAM/BASH, including PyCool (but still no Oracle support). +First version with successful tests of slc4_ia32_gcc41 on SCRAM/BASH +(but CMT is badly configured, and still no SQLite or Frontier support). + +Implementation bug fixes: +- Fix bug #28189 (missing quotes around table alias in new Oracle queries) +- Fix bug #28787 (segfault if 'live' iterator is not closed) + > fixed by using RalSessionMgr instead of IDatabase to keep track of how many + iterators are open (now allow at most one open iterator per RalSessionMgr) + +Add a test for MySQL bug #24646 (storing 11 blobs with 1000 characters fails). +The test is disabled for MySQL, for the moment it only prints a warning. + +Changes in bash test results: +- New test_payloadSpecOver8000Bytes for bug #24646 is OK (disabled for MySQL). +- Added logfile for slc4_ia32_gcc41 (all tests OK using SCRAM). + +============================================================================== +!2007.08.07 - Andrea (-D '2007/08/07 16:02:00') + +Internal tag COOL_2_2_1-pre2. +First version with all QMTEST tests as successful as bash tests. + +Test config improvements: +- Fix bug #28553 (duplicate entry in dblookup.xml for tests). + +No changes in RelationalCool code or bash test results. + +============================================================================== +!2007.08.02 - Andrea (-D '2007/08/03 14:05:00') + +Internal tag COOL_2_2_1-pre1. + +Changes in bash test results: +- OSX PPC tests for SQLite succeed after adding workaround for bug #27650. +- Added results for OSX Intel (all ok except Oracle that is not supported). + +C++ bug fixes: +- RelationalFolderSetNew inheritance from IFolderSet must be virtual. + +Tool improvements: +- Port CoolQueryManager to Windows (task #5255). +- Improved usage messages from various scripts. + +CMT config improvements: +- Fixes for OSX link warnings. + +============================================================================== +!2007.07.13 - Andrea + +Tag COOL_2_2_0. Production release with many performance optimizations and bug +fixes, also including backward-compatible API extensions and schema changes. +New versions of CMT, CORAL, ROOT/Reflex, oracle, sqlite, frontier_client +and LFC using LCG_53 (with respect to COOL 2.1.1 using LCG_51). + +Main API changes in CoolKernel: +- Added support for Blob16M (task #2197). +- Added reverse order object iterator from browseObjects (task #3430). +- Added goToNext() and currentRef() methods to IObjectIterator to improve the + C++ client performance by avoiding copies of CORAL currentRow (task #4672). +- Removed unnecessary virtual class inheritance from final classes and + unnecessary virtual method inheritance from final methods (task #4879). +- Added IDatabase::databaseName() method (sr #101807). +- Added IFolder::dropChannel() method to delete/drop an existing channel. + +Main schema changes (all included in the coolEvolveSchema tool): +- Fill the channels table for MV folders (fix for bug #23755). +- Added a FK on the IOV table referencing channelId in the channels table: + this is part of the fix for bug #23755 (MV channels table was not filled). + > Note that FKs are parsed but not enforced on SQLite. +- Folder schema is now 2.0.1 (database schema remains 2.0.0). + > For the moment, the code is still able to read the older 2.0.0 schema + (i.e. it does not rely on the fact that the MV channels table is filled). + In other words, schema evolution is recommended but is not necessary. + > Eventually, a future COOL release will require schema evolution, so + that it can assume that the MV channels table is filled. + > Older releases 210 and 211 are able to read/write data in the new 2.0.1 + folders: however, on Oracle and MySQL, where FKs are enforced, IOVs cannot + be inserted into new channels unless these are first manually created using + createChannel (or they have been created using storeObjects on COOL_2_2_0). + > *** WARNING *** Even if COOL210/211 can be used to insert data into + the 2.0.1 folders created by COOL_2_2_0, this is discouraged on SQLite + files as it may lead to data corruption (a 2.0.1 sqlite folder has a + non-enforced FK, so an IOV may exist for a channel that is not registered + in the channels table). This may be solved in the future if FKs are + enforced using triggers in the CORAL SQLIteAccess (sr #102114). +- String255 columns on MySQL are VARCHAR(255) BINARY instead of VARCHAR(255) + > This change is due to the fix in CORAL190 for bug #26484, which was + responsible in COOL for bug #24393 (tag queries were case insensitive). + > Warning: strings longer than 255 characters are still TEXT instead of + BINARY TEXT, hence they are still queried/sorted in a case-insensitive way. +- Schema evolution database attribute is now called "SE_2_2_0". + +Additional implementation improvements over COOL 2_1_1: +- Performance improvements for SV queries (task #4402). + > The query time for all-channel queries is now flat across IOVs. + > SV queries are now handled through a join of the channels and IOV tables. + > New class IRelationalQueryDefinition to encapsulate a generic query + description that can be reused as part of a subquery, eg for COUNT(*). + > Adapt the RelationalQueryMgr to the new IRelationalQueryDefinition. + Table row count is now possible using SELECT COUNT(*) FROM (SELECT...) + where the subquery is the same as the query used to fetch individual rows. + > Add schemaName() and databaseTechnology() to RelationalQueryMgr to handle + backend-dependent SQL injection in subqueries not supported by CORAL. +- Performance improvement for multi-channel bulk insertion (task #2009). + > Also clean up a bit the storeMultiVersionObjects method. +- Performance improvement for SV listChannels (bug #24448): use channels table. +- Drop support for the old RalObjectIterator (use only RalObjectIterator2). +- Progress in cleanup of inheritance. + > Removed unnecessary virtual class inheritance from final classes and + unnecessary virtual method inheritance from final methods (task #4879). + > Renamed RelationalBulkOperation as IRelationalBulkOperation. + > Renamed RelationalTransactionMgr as IRelationalTransactionMgr. + > Remove RalNodeMgr and RalTagMgr (Relational versions are enough). + > Separate getSequence and instantiateSequence metods in sequence manager. + > Bug fix: remove '=0' qualifier from the RelationalObjectTable destructor. +- Fix bug in RalDatabaseSvc (variable redefined in internal {} block) +- Removed workaround for CORAL bug #22453 for BLOB handling + (this is part of the implementation for the Blob16M storage type). +- Fix bug in RelationalNodeTable::tableSpecification() for many COOL releases. + +Additional tool improvements over COOL 2.1.1: +- Support evolution from either 1.3.0 (required) or 2.0.0 schemas (optional). + > The evolution from 2.0.0 schemas always checks all folders, upgrading them + from 2.0.0 to 2.0.1, while leaving the database schema version as 2.0.0. + > The evolution from 2.0.0 schemas also adds the 5d index for user tags + (which was introduced to solve task #4381 in COOL_2_1_1), if not yet there. + > Use two separate tests for evolution from 130 and 200 (in PyCoolUtilities). +- Enable schema evolution from 1.3.0 databases on AMD64. + > On AMD64, use the 32bit mode to create a 1.3.0 schema for evolution tests. +- Fix bug #26509 (coolReplicateDB fails on large databases - out of memory). +- Fix bug in coolPrivileges (add channels table: frontier tests were failing). +- Fix bug #23438 in CoolDescribeTable (invert single/double quotes on Windows). +- Fix bug in CoolDescribeTable (COLLATE syntax was not parsed for MySQL). +- Adapt coolReplicateDB after fixing bug #23755 (MV channel table not filled). +- Adapt coolReplicateDB and coolEvolveSchema to the new channelId FK. +- Add support for LFC to the coolAuthentication, coolDBDiscovery, coolDropDB, + coolDumpSchema, coolEvolveSchema, coolMiniClient, coolPrivileges and + coolReplicateDB tools (task #4326). +- Disabled the CORAL automatic pool clean up thread in coolDropDB and + coolReplicateDB (fix bug #27844 - nightly tests were hanging). +- Add COOLREPLICATION_TIMEOUT environment variable for coolReplicateDB tests. +- Add documentation for the coolReplicateDB tool (task #4328). +- Add support for 'select *' queries in the coolExecuteSql.csh script. +- Add CoolQueryManager python package to issue arbitrary 'select' queries + against a COOL database: this is used in regression and schema evolution + tests to check at the database level that the MV channels table is filled. + +============================================================================== +!2007.07.06 - Marco + +Disabled the CORAL connection pool clean up thread in coolDropDB and +coolReplicateDB (fix for nightly test failures reported as bug #27844). + +============================================================================== +!2007.04.16 - Marco + +Tag COOL_2_1_1. Bug-fix production release (binary compatible with 2.1.0). +New versions of CORAL, ROOT and frontier_client using LCGCMT_51. + +Main bug fixes and improvements over COOL 2.1.0: +- Implement cross-check that only one 'live' iterator can be open at a time. + > This was always claimed in the past, but not yet enforced. + > Added exception TooManyIterators. + > Fix for bug #25151 (abort in concurrent use of iterators). + > Fix for bug #25817 (segfault introduced by new iterator checks). + > Fix for bug #25256 (MySQL test failure introduced by new iterator checks). + > Added tests for read concurrency with live iterators. +- Performance improvements in the C++ client. + > Copy data only once in browseObjects using new RalObjectIterator2 + (can be disabled using COOL_210ITERATOR env variable). + > Construct RelationalObject from coral AttributeList + (rather than from RelationalObjectTableRow). + > Private hacks for PDB stress tests in RalObjectIterator + (controlled by env variable COOL_PDBSTRESSTEST_NBYTES). +- Resurrect TimingReport for performance studies (disabled by default). + > Fix a memory leak (related to bug #9253). + > Can be enabled by COOL_TIMINGREPORT env variable. + > Keep track of time spent in CORAL alone. +- Start a single read-only transaction and preload the nodes table at the + start of read-only connections (task #2816). + > Can be disabled by COOL_READONLYSESSION_MANYTRANSACTIONS env variable. + > New bug (memory leak): the database is never deleted. + > Add methods to read all nodes from the nodes table. + > Use a bool flag always (no more strings) to indicate read-only sessions. + > Added new class DummyTransactionMgr for read-only connections. +- Added goToNext() and currentRef() methods to IObjectIterator API. + > These are presently disabled (#ifdef'ed out)and will be enabled in 2.2.0 + (improve C++ client performance by avoiding copies of CORAL currentRow). + > Added new classes ConstTimeAdapter and ConstRelationalObjectAdapter. +- Fix for bug #24999 in the replication tools. +- Fixes for gcc4.0 in RelationalObjectTableRow. +- Fixes for gcc4.1 in CppUnit tests. +- Fix in coolAuthentication for aliases in frontier (ignore missing password). +- Added test for case sensitivity of tag names in MySQL (bug #24393). + > Bug introduced in COOL2.0.0 by removing BINARY for strings in CORAL. + > Improved tests for special characters such as umlauts. + +============================================================================== +!2007.04.04 - Marco + +Fixed bug #25256. RalObjectIterator2 was registered even if the construction +fails with an exception in the initialization part (before the constructor +body), but in that case was never unregistered. Now it is registered in the +body of the constructor, so an exception in the initialization part will not +cause a mis-balance. Added the class ObjectIteratorCounterWatchDog to spot +when an iterator is not correctly unregistered. + +============================================================================== +!2007.03.26 - Andrea + +C++ performance improvement in RalObjectIterator and RelationalObject: +copy data only once in browseObjects, while previously it was copied twice. +A query time reduction from 0.31s to 0.27s was observed on slc3_ia32_gcc323 +for the benchmark Atlas prompt reconstruction query (retrieve in total +100MB and 100k rows from 100 folders with 1k channels each). + +============================================================================== +!2007.03.24 - Sven + +Fixed replication bug #24999. + +============================================================================== +!2007.03.24 - Andrea + +Tag COOL_2_1_0. Production release with backward-compatible API extensions +and schema changes. New versions of CORAL and ROOT using LCGCMT_50c. + +Summary of backward-compatible API changes in CoolKernel: +- Tag locking functionality (task #3709) + > add IHvsTag::setTagLockStatus and IHvs::tagLockStatus methods + > add TagIsLocked exception +- Fix for bug #23751 in the IFolder::folderSpecification() method. +- Fixes to allow compilation on MacOSX. +- Define int64 as long long also on AMD64, as in CORAL_1_7_2 (task #4357). + +Backward-compatible schema changes: +- Added a 5D index to IOV tables to improve user tag performance (task #4381). + +Configuration changes: +- Prepared infrastructure for private SCRAM builds in parallel to CMT. + +Other improvements and bug fixes in COOL: +- SQL performance improvement for SV SC browseObjects (task #3675). +- Forward compatibility with 2.0.x folder and folder set schemas. +- Added replication test to the PyCoolUtilities test suite (task #4348). +- Completed integration with LFCReplicaSvc and added an example (task #4326). +- Fix for bug #23597 in PyCoolCopy with sqlite files. +- Fix for bug #23610 in RelationalTagMgr::fetchGlobalTagTableRowForInnerNode. +- Fixes for coolReplicateDB bug #23662 (drop/recreate FKs when needed). +- Partial fix for bug #23716 in PyCoolCopy handling of BLOBs. +- Fix for bug #23754 (IFolder::setChannelName should accept current name). +- Fix for bug #24248 in schema evolution test infrastructure for sqlite. +- Partial fix for bug #24392 (missing try/catch in an example). +- Fixes for bug #24445, bug #24449, bug #24461 and bug #24463 in MV channel + management: actually, these are all workarounds for bug #23755 (channels + table is not filled for MV folders). +- Fix for bug #24464 (storeObject should accept payload with fewer fields + than those defined in the folder payload specification). +- Fix for a bug in IFolder::existsUserTag(): the transaction was started twice. +- Fixes in the authentication and statistics tools (moved from C++ to python). +- Fixes for bug #24480, bug #24481 and bug #24555 in C++ test infrastructure. +- Start internal preparation for 3.0.0 schema (task #4307 and task #4396). +- Improvements in PyCool (some of which related to the LFCReplicaSvc). +- Added tool PyCoolDiff to extract the difference between two DBs. + +Improvements from the upgrade to CORAL_1_7_2 (from CORAL_1_7_0): +- Fix for bug #23412 in MySQLAccess SQL syntax for PK creation. +- Fix for bug #24103 in SQLiteAccess handling of unsigned int on AMD64. +- Fix for bug #24642 in MySQLAccess SQL syntax for FK creation. + +Improvements from the upgrade to ROOT 5.14.00d (from 5.14.00b): +- Fix for bug #23807 (abort in boost::shared_ptr<IObject>). +- Fix for bug #24100 in unsigned long long handling in python for AMD64. + +Improvements from the upgrade to LCGCMT_50c (from LCGCMT_50): +- Fix for bug #24052 (missing oracle/mysql binaries in PATH). + +============================================================================== +!2007.03.22 - Marco + +Fixed a bug observed by Richard: the transaction was started twice when +calling RelationalFolder::existsUserTag(). + +============================================================================== +!2007.02.21 - Andrea + +Added TestListener.h replacing the corresponding cppunit header file. +This seemed to be the only way to get rid of compilation warnings with -O2. + +============================================================================== +!2007.02.20 - Andrea + +Apply the performance patch for SV SC browseObjects(key,key+10,chId) that +had been developed by Kristoffer Dahl in 2006. This completes task #3675. + +============================================================================== +!2007.02.19 - Andrea + +Fixes for the tools to gather table and schema statistics. +Move them from csh to py scripts (with associated python packages). + +Minor fix in the CoolAuthentication python package. + +============================================================================== +!2007.02.16 - Andrea + +Add 5d index to IOV tables to improve user tag performance (task #4381). + +Change s/w release version to 2.0.1 (keep db schema version at 2.0.0). + +Change folder schema version to 2.0.1 (mark the existence of the new index). +The 2.0.1 RelationalFolder class can still read (with lower performance) +any 2.0.0 folder where this index is not defined. The 2.0.0 software +release is now forbidden from reading the new 2.0.1 folders to encourage +users to move to 2.0.1 (even if the 2.0.0 code could actually read data +from the new folder with the extra index - even with better performance!). + +Cleanup assigning and checking of folder and folder set schema versions. + +============================================================================== +!2007.02.16 - Andrea + +Added infrastructure to create new tables in 3.0.0 database schema: +- IOVTABLES and CHANNELTABLES tables (task #4307) +- USERTAGS and HEADTAGS tables (tag #4396) +The code has been committed, but must be kept commented out until 3.0.0. + +In order to complete the 3.0.0 db schema, CHECK constraints are needed. +Filed CORAL sr#101506 asking support for this feature. + +Removed schema manipulation methods from RelationalDatabase +(they were already delegated to the schema manager anyway). + +============================================================================== +!2007.02.16 - Andrea + +Adopt for SCRAM the same naming convention used by CMT: +- rename unitTest as test +- rename exampleCool as example_Cool + +============================================================================== +!2007.02.14 - Andrea + +Added a C++ test for CORAL bug #22485 (empty blobs in sqlite). +We now have a failing test in the RelationalCool test suite. + +============================================================================== +!2007.02.14 - Marco + +Fixed bug #23751: "IFolder::folderSpecification() does not work". + +The fix required a fix in IFolder.h (return const IRecordSpecification instead +of const RecordSpecification). It is "semantically" compatible, and should not +break compilation, but it is not strictly the same API. Also added a test. + +============================================================================== +!2007.02.12 - Sven + +Various fixes for the dynamic replication tool. Still not fully functional. + +============================================================================== +!2007.02.08 - Marco + +Fixed bug #23610: rename RelationalTagMgr::fetchGlobalTagTableRowForInnerNode +as fetchGlobalTagTableRowForNode and change all comments accordingly. + +============================================================================== +!2007.02.08 - Andrea + +Minor changes in RelationalTagMgr to remove a warning on MacOSX +(control reaches end of non-void function) - see task #2062. + +============================================================================== +!2007.01.31 - Andrea + +Tag COOL_2_0_0. Major production release with backward-incompatible +API and schema changes. New versions of SEAL, CORAL and frontier_client. + +Summary of main API changes in CoolKernel and CoolApplication: +- Changes in folder specification, payload specification and payload data API + > new StorageType::TypeId enum with associated new typedefs (eg Int64) + > new RecordSpecification class + > new Record and Field classes with validation of storage constraints + > temporary extensions use coral AttributeList for backward compatibility + > new FolderSpecification class accepted by createFolder + > treat empty string "" as NULL +- Stripped API of all SEAL classes + > integer type definitions not based on seal::IntBits + > new class cool::Time replaces seal::Time. + > new SEAL-free API for class cool::Application +- Changes in the support for user-defined payload fields + > added support for BLOB and signed int64 payload data + > constraints on numbers and names of user-defined payload fields + > added cool::IFolder::renamePayload (to change unsupported payload names) + > string payload cannot contain character "\0" (only BLOBs can contain it) +- Renamed methods and removed default channel arguments in IFolder: +- Removed obsolete IDatabaseSvc::dropDatabase(dbId,throwIfDoesNotExist) +- Added the possibility of specifying a CORAL role in the connection string +- Changed default mode for openDatabase from read/write to read/only + +============================================================================== +!2006.01.18 - Marco + +Added the possibility of specifying a CORAL role in the connection string. +The format is now one of: + - alias/DBNAME + - alias(role)/DBNAME + +============================================================================== +!2007.01.17 - Marco + +*** BRANCH RELEASE NOTES *** + +Tag COOL_1_3_4. Production release (backward-compatible bug-fix, +functionality enhancement and LCG_50 configuration upgrade release). +Important fixes in SEAL (component model and multithreading), CORAL and ROOT. + +============================================================================== +!2006.12.12 - Marco + +Removed explicit (hardcoded) reference to XMLAuthenticationService +(let CORAL decide which authentication service should be used). + +Added a warning message if explicit credentials are used (deprecated). + +Small fix in database Id parsing: the separator between coral ID +and cool db name has to be the last '/', not the first. + +[Changes included by Marco in COOL_1_3-branch on 2006.12.12] + +============================================================================== +!2006.12.08 - Andrea + +Remove all default channel=0 or channels=all arguments +from all methods to store, find, browse or count objects. + +Rename browseObjects(time,channelsel) as findObjects, +as otherwise the old browseObjects(5,10) would change +semantics (t=5,ch=10 instead of s=5,u=10,ch=0)! + +Keep the implicit ChannelSelection(id) constructor. +Note that ChannelSelection(id) must be given explicitly in PyCool +(the implicit constructor from an integer does not seem to work). + +These changes represent a fix for bug #14759. + +============================================================================== +!2006.12.07 - Andrea + +Completed internal port to new IRecord and IField API. + +Eased backward compatibility for users by keeping the old +storeObject(..AttributeList&..) method signature in parallel +to the new storeObject(..IRecord&..), for writing, +and via the IRecord::attributeList()method, for reading. + +PyCool still uses only the AttributeList interface +(Marco will port it to the new Record interface). + +All C++ and python tests pass. + +============================================================================== +!2006.11.26 - Andrea + +Moved ReferenceDb tool from RelationalCool tests to PyCoolUtilities as +new package PyCoolReferenceDb (this is a python package based on PyCool). +This ensures that the python package is compiled in the platform-dependent +area, avoiding interference between 32 and 64bit Linux (fix for bug #21391). + +Moved execution of the regression tests based on ReferenceDb tool from +PyCool to PyCoolUtilities. This includes the Frontier regression test. + +[Changes included by Andrea in COOL_1_3-branch on 2006.11.26] + +============================================================================== +!2006.11.24 - Andrea + +Added two python packages CoolAuthentication and CoolDescribeTable +to dump the list of column names and SQL types of any table. +This will be needed for regression tests of column SQL types. + +Added two corresponding tests in RelationalCool/tests/python. + +[Changes included by Andrea in COOL_1_3-branch on 2006.11.26] + +============================================================================== +!2006.11.13 - Marco + +Clean up in RelationalCool test source code (prepare to QMTest). + +============================================================================== +!2006.11.06 - Marco + +Add a check for active transactions in RalSessionMgr::disconnect (bug #21344). + +============================================================================== +!2006.10.30 - Andrea + +*** BRANCH RELEASE NOTES *** + +Tag COOL_1_3_3c. Rebuild of the 1.3.3 release for the LCG_48 configuration. +Important fixes in SEAL (component model and multithreading), CORAL and ROOT. +No change in the source code. Software version remains "1.3.3". + +============================================================================== +!2006.10.16 - Marco + +*** BRANCH RELEASE NOTES *** + +Tag COOL_1_3_3b. Rebuild of the 1.3.3 release for the LCG_47b configuration. +New version of ROOT. Pending bugs in SEAL and ROOT. +Partial support for MySQL on Windows (pending PyCoolUtilities bug #20780). +No change in the source code. Software version remains "1.3.3". + +=============================================================================== +!2006.10.09 - Marco + +Added support (and tests) for coral::Blob. + +============================================================================== +!2006.09.29 - Andrea + +*** BRANCH RELEASE NOTES *** + +Tag COOL_1_3_3a. Rebuild release (bug fixes in CORAL and frontier_client). +Pending bugs in SEAL, new bugs in ROOT. Same source code as COOL_1_3_3. +Only added two Frontier regression tests. Software version remains "1.3.3". + +Upgrade to CORAL_1_6_0 (from CORAL_1_5_4), including the following bug +fixes and enhancements relevant to COOL. +- CORAL bug #19758 (segfault in Frontier QueryDefinition::process) +- CORAL bug #19777 (COOL bug #19753) in Frontier lowercase table aliases +- CORAL sr #101135 (authentication credentials for different roles) + +Upgrade to frontier_client 2.6.0_cms (from 2.5.1_cms): +- Fix frontier_client bug #18359 (COOL bug #18390) in AMD64 data compression + +Upgrade to ROOT 5.13.02 (from ROOT 5.12.00c). This has triggered +the appearance of a new bug that prevents PyCool support on Windows: +- ROOT bug #20133 (COOL bug #20216) for python ROOT on Windows + +No upgrade from SEAL_1_8_1 yet. Pending bugs and thread unsafety +in SEAL component model causing segfaults, assertions and aborts. + +============================================================================== +!2006.09.26 - Andrea + +Fix for bug #20073 - no need to select payload columns for inserting IOVS. +Bug observed in COOL133 but fixed only for COOL200 (as the code has changed). +Bug fixed by adding the option to select only metadata columns in method +RelationalObjectTable::fetchRowForId, which is called by fetchLastRowForTagId +(this was also called by fetchLastRow in COOL133). Also related to task #2266 +(allow users to specify which payload columns should be retrieved). +The problem is not present in RalObjectMgr::fetchLastRowsWithNewData. + +Comment out RelationalObjectTable::fetchLastRow and its RalObjectTable test: +this is not used in the internal implementation as it has been replaced by +fetchLastRowsWithNewData (instead of querying the IOV table for the last +objectid, this is now read off the channels table). Note that fetchLastRow +is still used in COOL133 instead. + +============================================================================== +!2006.09.14 - Andrea + +Added MV retrieval tests to the Regression test suite. +Reproduces FrontierAccess bug #19753 for COOL_1_3_3. + +[Changes included by Andrea in COOL_1_3-branch on 2006.09.13] + +============================================================================== +!2006.08.29 - Andrea + +*** BRANCH RELEASE NOTES *** + +Tag COOL_1_3_3. Production release (backward-compatible bug-fix, +functionality enhancement and configuration upgrade release). +Many important fixes in CORAL and Frontier; pending critical bugs in SEAL. + +Eight supported platforms: win32_vc71_dbg_wine, slc4_ia32_gcc345(_dbg), +slc3_ia32_gcc323(_dbg/_gcov) and slc3_ia32_gcc344(_dbg). +No MySQL support on Windows (no support in CORAL). +No Frontier support on Windows (no client library from FNAL). + +Two AMD64 test platforms: slc4_amd64_gcc345(_dbg). The only pending problem +with AMD64 is the 'long' type ambiguity on 32/64 bit platforms (task #2227); +this is fixed in the new COOL HEAD API, which will be released as COOL140. + +Release built using LCG_46e_2 (upgrade from LCG_46_2). +May become available as LCG_46f_3 (the only difference +with LCG_46e_3 being COOL133 instead of COOL132c). + +Upgrade to ROOT 5.12.00c (from ROOT 5.12.00). + +Upgrade to CORAL_1_5_3 (from CORAL_1_5_1), including the following bug +fixes and enhancements relevant to COOL. In CORAL_1_5_3: +- CORAL bug #19000 (disable OCI_THREADED to prevent OracleAccess hanging) +- CORAL bug #19003 (fix for Oracle 'select from SYS.DUAL') +- CORAL sr #101074 (fix for value returned by updateRows on MySQL) +Already in CORAL_1_5_2: +- CORAL bug #18275 (mismatch between output buffer and result set metadata in + FrontierAccess) - patch contributed by the COOL team (this was responsible + for both COOL bug #18270 and COOL bug #16995) +- CORAL bug #18292 (added plugin checks in case of misconfiguration) +- Added ConnectionService property "PoolCleanUpPeriod" +- Bug fixes in OracleAccess multi-threading (prevent deadlock) +- CORAL sr #100958 (print out the values of SQLite bind variables) +- CORAL bug #18316 (missing double quotes in some SQLite operations) +- Improvements in SQLite file and directory handling + +Upgrade to frontier_client 2.5.1_cms (from 2.4.5_cms): +- Fix frontier_client bug #18359 (COOL bug #18390) in AMD64 data compression + +Upgrade to Frontier server version 3.2 and additional bug fixes: +- Data compression in Frontier server 3.1 (required in 2.4.5_cms client) +- Fix for Frontier server bug #18191 (not yet released) + +No upgrade from SEAL_1_8_1 yet. Pending bugs and thread unsafety +in SEAL component model (workarounds developed by the COOL team exist +for some but not all of these issues): +- SEAL bugs #19019 and #18908): segmentation fault in MessageStream +- SEAL bug #19005 (COOL bug #18910): assertion 'pos != m_children.end ()' +- SEAL bug #18909 (COOL bug #18440): abort (pure virtual method called) +- SEAL bug #18914: segmentation fault in seal::intrusive_ptr_release +- SEAL bug #19360: ConfigurationService is never deleted +- SEAL bug #19004 (COOL bug #18396): assertion 's_trampolines[sig]' +- COOL bug #18225: unhandled/unknown exceptions on Windows + +Enhancements in COOL_1_3_3 with respect to COOL_1_3_2c: +- Change the message level verbosity in PyCool/CoolApplication interactively +- Implement forward compatibility with future releases (task #3426) +- PyCoolUtilities enhancements for HVS +- Warning messages in CoolApplication in case of problems loading plugins. + +Bug fixes in COOL_1_3_3 with respect to COOL_1_3_2c: +- Bug #18116 in RalSequence test (segfault when the password is invalid) +- Bug #18284 in privilege manager (open database in update mode, add tag2tag) +- Bug #18145 in PyCool on AMD64 (no attribute 'data'). +- Bugs in four RelationalCool tests: check connection service in tearDown() +- Bugs in PyCoolCopy tool (preserve payload data type precision in the copy) +- Possible segfault in the use of SEAL components in CoolApplication + +============================================================================== +!2006.08.28 - Andrea + +*** BRANCH RELEASE NOTES *** + +Preparing for COOL_1_3_3. + +Aborted present attempts to fix or workaround bugs in SEAL_1_8_1 +causing random assertions, segmentation faults and aborts. + +Developed fixes and workarounds for several independent bugs in the +SEAL component model, but could not workaround the intrinsic thread +unsafety of SEAL handles based on boost intrusive pointers. + +============================================================================== +!2006.08.23 - Andrea + +Added test for CORAL sr#101074 in RalDatabase test. +Verified that the fix works (will be released in CORAL_1_5_3). + +Remove workaround for CORAL sr#101074 (return value of updateRows +on MySQL is different from Oracle/SQLite) in RalDatabase test. + +[Changes included by Andrea in COOL_1_3-branch on 2006.08.23] + +============================================================================== +!2006.08.22 - Andrea + +Minor bug fix in the RalDatabase_extendedSpec, RalObjectIterator, +RalObjectTable and RelationalFolder tests: check that the connection +service is still alive in tearDown() before using it to purge the pool. + +This prevents a boost shared pointer assertion if RalSessionMgr is changed +to load the ConnectionService in the local database service context. + +[Changes included by Andrea in COOL_1_3-branch on 2006.08.13] + +============================================================================== +!2006.08.15 - Andrea + +Added script wineWrap.sh for running individual commands on Wine (task #3495). + +[Changes included by Andrea in COOL_1_3-branch on 2006.08.15] + +============================================================================== +!2006.07.27 - Andrea + +Implement forward compatibility with future releases using the same schema: +compare data and software schema versions if data release number is newer +than software release number (task #3426). Added the relevant tests. + +[Changes included by Andrea in COOL_1_3-branch on 2006.07.27] + +============================================================================== +!2006.07.27 - Andrea + +Bug fix in common CoolDBUnitTest (check availability of CORAL +connection service in forceDisconnect to prevent program abort). + +[Changes included by Andrea in COOL_1_3-branch on 2006.07.27] + +============================================================================== +!2006.07.24 - Andrea + +*** BRANCH RELEASE NOTES *** + +Prepare for tag COOL_1_3_3 (non-HEAD branch off COOL_1_3_2). +Backward-compatible production release. +A few bug fixes and enhancements with respect to 1.3.2 +for CoolApplication, RelationalCool and PyCool. +Commit PyCoolUtilities logfiles to the new branch too. +Same code as 1.3.2 for CoolKernel, Examples and Utilities. + +Created branch COOL_1_3-branch off COOL_1_3_2. +Initially (2006.05.18) branched all of config, CoolKernel and RelationalCool: + cvs rtag -r COOL_1_3_2 -b COOL_1_3-branch cool/config + cvs rtag -r COOL_1_3_2 -b COOL_1_3-branch cool/CoolKernel + cvs rtag -r COOL_1_3_2 -b COOL_1_3-branch cool/RelationalCool +Later on (2006.05.18) realised it was not necessary to modify CoolKernel: + cvs rtag -d -B COOL_1_3-branch cool/CoolKernel + +Later on still (2006.07.24) realised it was not necessary to modify config, +while it was necessary to branch off also CoolApplication and PyCool. +Eventually branched off also PyCoolUtilities for simpler logfile commits. + cvs rtag -d -B COOL_1_3-branch cool/config + cvs rtag -r COOL_1_3_2 -b COOL_1_3-branch cool/CoolApplication + cvs rtag -r COOL_1_3_2 -b COOL_1_3-branch cool/PyCool + cvs rtag -r COOL_1_3_2 -b COOL_1_3-branch cool/PyCoolUtilities +Note that cool/config COOL_1_3-branch contained a single file +doc/release.notes different from COOL_1_3_2. Untagging cool/config +detached the COOL_1_3-branch from this file but did not delete it. + +============================================================================== +!2006.07.21 - Andrea + +Added handler of SEAL PluginManager feedback to cool::Application. +This will print out warning messages if there are problems loading plugins. + +If environment variable COOL_PLUGINMANAGER_DEBUG is set, +debug information will be printed about the modules being loaded +(otherwise only warnings will be displayed). + +This must be done in package CoolApplication and not in RelationalCool +(so that problems loading the RelationalCool plugin can be disaplayed). + +[Changes included by Andrea in COOL_1_3-branch on 2006.07.24] + +============================================================================== +!2006.07.20 - Andrea + +Set the CORAL connection service pool cleanup period to 1 second +in the seal.opts files. These files should be in config! + +[Changes included by Andrea in COOL_1_3-branch on 2006.07.25] + +============================================================================== +!2006.07.19 - Andrea + +Use Marco's MySQL server instead of Radovan's for Andrea's tests. +This file should be in config! + +[Changes included by Andrea in COOL_1_3-branch on 2006.07.24] + +============================================================================== +!2006.07.18 - Andrea + +Fix for bug #18284: add HVS tag2tag table to privilege manager. + +[Changes included by Andrea in COOL_1_3-branch on 2006.08.29] + +============================================================================== +!2006.07.18 - Andrea + +Added listChannels tests to the Regression test suite +(needed to reproduce FrontierAccess bug #16995). + +[Changes included by Andrea in COOL_1_3-branch on 2006.09.14] + +============================================================================== +!2006.07.14 - Marco + +Enable the usage of dblookup.xml for tests for all users. +Enable frontier tests for Marco. This file should be in config! + +[Changes included by Andrea in COOL_1_3-branch on 2006.07.24] + +============================================================================== +!2006.07.14 - Marco + +Added function cool::IFolder::renamePayloadColumn and tests (task #3609). + +============================================================================== +!2006.07.12 - Marco + +*** BRANCH RELEASE NOTES *** + +Tag COOL_1_3_2c. Rebuild of COOL_1_3_2 for the LCG_46 configuration. +No change in the source code. Software version remains "1.3.2". + +Upgrade to ROOT 5.12.00 (from ROOT 5.11.06a), +including the following fixes for bugs relevant to COOL: +- ROOT bug #17255 (COOL bug #17254) for exception handling on AMD64 +- ROOT bug #17592 for enums in PyCintex +- ROOT bug #18062 for namespaces in PyCintex + +Upgrade to CORAL_1_5_1 (from CORAL_1_5_0), +including the following bug fixes (the first three contributed by the +COOL team) and connection service improvements relevant to COOL: +- CORAL bug #17651 (COOL bug #17624) for missing quotes in SQL on MySQL +- CORAL bugs #14688 and #17787 for SQLite data types on AMD64 +- CORAL bugs #14688 and #17761 for MySQL data types on AMD64 +- CORAL bug #17757 (COOL bug #17755) for Oracle bulk operations on >65k rows +- CORAL bug #17791 for Oracle SELECT FROM DUAL +- CORAL bug #15933 for SQLite named binding +- implementation of automatic purging of the connection pool +- switch to Oracle multi-threaded OCI mode with no mutex locks + +Upgrade to frontier_client 2.4.5_cms (from frontier_client 2.4.4_cms). +COOL_1_3_2b had been tagged and installed before LCG_45 +was redefined to use frontier_client 2.4.5_cms. + +Six supported platforms: win32_vc71_dbg_wine, +slc4_ia32_gcc345(_dbg) and slc3_ia32_gcc323(_dbg/_gcov). +No MySQL support on Windows (no support in CORAL). +No Frontier support on Windows (no client library from FNAL). + +Two test platforms: slc4_amd64_gcc345(_dbg). +A few problems in COOL are still pending on AMD64 +after the ROOT and CORAL bug fixes for this platform. + +Dropped support for slc3_ia32_gcc344(_dbg) +and test builds on slc3_amd64_gcc344(_dbg). + +============================================================================== +!2006.07.11 - Marco + +Add check to prevent segmentation fault in RalSequence test when the +connection fails, e.g. because of wrong username/password (bug #18116). + +[Changes included by Andrea in COOL_1_3-branch on 2006.07.24] + +============================================================================== +!2006.07.11 - Marco + +Added check on the payload column names: +only alphanumeric chars and '_' are allowed. +Throw cool::BadPayloadColumnName if the case of a name like "is-a". +The test in RelationalFolderTest has been updated accordingly. +Still need to add a method to allow users to rename payload columns. + +============================================================================== +!2006.06.29 - Andrea + +Fix for bug in coolPrivileges: open the database in update mode. + +[Changes included by Andrea in COOL_1_3-branch on 2006.08.29] + +============================================================================== +!2006.06.26 - Sven + +Brought back double query strategy using maxIovAtTime() for findObject +in the SV case as it was in COOL 1.3.0 (maxIovAtTime was only used in +SV even then). This required the following minor changes. +- RelationalObjectTable::whereClauseSV now takes since, until parameters +to determine if a 'point in time' (since == until) query is issued. +- RelationalObjectTable::whereDataSV is now non-static, because it needs +to access the non-static methods objectTableName() and maxIovAtTime(). +It was not used in any static contexts anyway. +- In general, the 'old', optimized SV query will be used if since == until +and channels.firstChannel() == channels.lastChannel(). +- Bug fix #16179 is still in place, because it concerns user tags (and +therefore MV code). + +[Changes included by Andrea in COOL_1_3-branch on 2006.07.24] + +============================================================================== +!2006.06.19 - Andrea + +Added a call to purgeConnectionPool inside RalSessionMgr::disconnect(). +This should ensure that closeDatabase() physically drops the connection +if the connection service timeout has been pre-set to 0. To be tested. +This is related to task #3546. [NB NOT committed to COOL_1_3-branch]. + +============================================================================== +!2006.06.19 - Marco + +*** BRANCH RELEASE NOTES *** + +Tag COOL_1_3_2b. Rebuild of COOL_1_3_2 for the LCG_45 configuration. +Upgrade to ROOT/Reflex 5.11.06a and CORAL_1_5_0 using LCG_45 +(from ROOT/Reflex 5.11.02 and CORAL_1_4_3 using LCG_44). +Also implies upgrade to oracle 10.2.0.2 (from 10.2.0.1), +sqlite 3.3.5 (from 3.2.8) and cppunit 1.10.2_p2 (from 1.10.2_p1). + +Upgrade to frontier_client 2.4.4_cms (from frontier_client 2.4.1_cms_p1). +Note that COOL_1_3_2b was tagged and installed before LCG_45 +was redefined to use frontier_client 2.4.5_cms. + +No change in the source code. Software version remains "1.3.2". + +Support for slc4_ia32_gcc323 and slc4_ia32_gcc323_dbg. + +Eight supported platforms: win32_vc71_dbg_wine, slc4_ia32_gcc345(_dbg), +slc3_ia32_gcc323(_dbg/_gcov) and slc3_ia32_gcc344(_dbg). +No MySQL support on Windows (no support in CORAL). +No Frontier support on Windows (no client library from FNAL). + +Four test platforms: slc3_amd64_gcc344(_dbg) and slc4_amd64_gcc345(_dbg). +Pending problems with AMD64 mainly due to 32bit/64bit integer types. + +============================================================================== +!2006.06.16 - Marco + +Added tests for Int64 in RalDatabase_extendedSpec +(UInt64 is ready, but commented out). + +============================================================================== +!2006.06.13 - Sven + +Added LASTMOD_DATE to RelationalObjectTable. Field is updated for SV and MV +storage in RalObjectMgr and accessible through RelationalObjectTableRow. +Added the corresponding tests as well. + +============================================================================== +!2006.06.13 - Marco + +Removed extra transaction in RalObjectMgr.cpp (bug #17376). + +[Changes included by Andrea in COOL_1_3-branch on 2006.07.24] + +============================================================================== +!2006.05.28 - Sven + +API changes. First prototype of channel metadata (channel name and number). + +============================================================================== +!2006.05.19 - Marco (comments by Andrea) + +API changes. First prototype of PayloadSpecification API. No AMD64 port yet. + +TO DO (amongst other things): +- check/validate the changes in the Oracle schema +- in particular, check what happens with Oracle version numbers 8, 9, 10? +- can we really let CORAL choose the SQL types? (else renable the tests!) +- add an enum value for some unsupported types to be supported later? + +Implies changes in the test structure: +[*Note: since a few releases, obsolete tests have been removed using +an "#ifdef NOPORT". A better solution would be to cvs delete the tests.] +- added PayloadSpecification tests +- removed(*) all RelationalDatabase tests, moved to PayloadSpecification tests + > encode/decode spec description + > decode bad specifications (empty spec, no colon, trailing comma) + > decodeOnlyOneColon test removed - new spec expects one colon instead of two +- removed(*) all RelationalTypeConverter tests, obsoleted + > remove all tests to control SQL types (the new implementation lets CORAL + choose SQL types, instead of choosing 9i/10g-dependent SQL types in COOL) + > oracleMajorVersionNumber test removed - use CORAL SQL types + > sqlTypeForCppType_oracle/mysql/sqlite tests removed - use CORAL SQL types + > checkStorageHintCompliance tests removed - no type/hint pairs + (this test was NOT testing that actual attribute values were compliant to + a hint, it was only testing that a given hint was valid for a given type) +- removed some RalDatabase_extended tests, obsoleted + > test_unsupportedTypesXXX - obsolete, it is not possible to specify + an unsupported type, simply because there is no enum value for it + +============================================================================== +!2006.05.19 - Andrea + +Fixed bug #16903 in maxIovAtTime: this was not strictly necessary, as this +is only called by fetchRowAtTimeSV, which is never used by the public API. +Later on, removed both unused methods fetchRowAtTimeSV and maxIovAtTime. + +[Changes included by Andrea in COOL_1_3-branch on 2006.05.19] + +============================================================================== +!2006.05.18 - Andrea + +Created branch COOL_1_3-branch to fix pending bugs in COOL_1_3_2 if required. + cvs rtag -r COOL_1_3_2 -b COOL_1_3-branch cool/config + cvs rtag -r COOL_1_3_2 -b COOL_1_3-branch cool/RelationalCool + +============================================================================== +!2006.05.17 - Sven + +First prototype of channel table to implement multi channel bulk insertion. +No channel metadata yet. + +No API changes. + +============================================================================== +!2006.05.14 - Andrea + +Tag COOL_1_3_2a. Rebuild of the 1.3.2 release for the LCG_44 configuration. +Upgrade to ROOT 5.11.02 using LCG_44 (from ROOT 5.10.00d using LCG_43b_2). + +No change in the source code. Software version remains "1.3.2". + +Six supported platforms: win32_vc71_dbg_wine, +slc3_ia32_gcc323(_dbg/_gcov) and slc3_ia32_gcc344(_dbg). +No MySQL support on Windows (no support in CORAL). +No Frontier support on Windows (no client library from FNAL). + +Six test platforms: slc3_amd64_gcc344(_dbg), +slc4_ia32_gcc345(_dbg) and slc4_amd64_gcc345(_dbg). +Pending problems with slc4_ia32_gcc345(_dbg) only for SQLite. +Pending problems with four AMD64 platforms mainly due to intrinsic +COOL problems with 32bit/64bit integer types (to be solved in COOL_1_4_0). + +============================================================================== +!2006.05.10 - Andrea + +Tag COOL_1_3_2. Production release (backward-compatible +bug-fix and Frontier support release in the 1.3 series). + +Six supported platforms: win32_vc71_dbg_wine, +slc3_ia32_gcc323(_dbg/_gcov) and slc3_ia32_gcc344(_dbg). + +Six test platforms: slc3_amd64_gcc344(_dbg), +slc4_ia32_gcc345(_dbg) and slc4_amd64_gcc345(_dbg). +Pending problems with AMD64 mainly due to 32bit/64bit integer types. +Pending problems with SLC4 mainly due to wrong OracleAccess configuration. + +Upgrade to ROOT 5.10.00d and CORAL_1_4_3 using LCG_43b_2. +Upgrade to ROOT 5.11.02 postponed to LCG44 because not yet requested +(Atlas will build its release 12 using the LCG43 configuration). + +Add David Front's VerificationClient to the COOL release installation. +Keep VerificationClient in its original CVS repository in the contrib area +and install it as a subdirectory of the Utilities package at boostrap time. +The only executable installed in the public PATH is coolVerificationClient. + +============================================================================== +!2006.05.03 - Andrea, Marco, Sven + +Bug fixes in COOL: +- #16566 - IHvsNode::resolveTag() does not work for "local" tags +- #16567 - IHvsNode::listTags() does not work for inner nodes +- bugs in transaction handling (split findTagRecord from __findTagRecord) + +Added basic Frontier support: +- Added frontier_client tool to the SCRAM configuration +- Filed CORAL bug #16617 - authentication.xml user used as Oracle schema owner +- Filed CORAL bug #16621 - success with "COUNT(*)" but failure with "count(*) +- Implemented workarounds in COOL for both CORAL bugs +- SimpleRead example works successfully! +[NB: remember to grant read privileges to PUBLIC from the Oracle account!] + +Prepare for API changes in COOL_1_4_0: +- Prepared tests and examples to switch to read-only default in openDatabase. + Keep read-write as default in API until COOL_1_4_0 (backward compatibility). + +Internal cleanup: +- Move many object-related methods from RalDatabase to RelationalObjectMgr. + +============================================================================== +!2006.04.25 - Andrea, Marco, Sven + +Tag COOL_1_3_1. Production release (backward-compatible +COOL and CORAL bug-fix release in the 1.3 series). + +Bug fixes in COOL_1_3_1: +- #16337 - PyCool assertions on Win (workaround for ROOT bug fixed in 5.11.02) +- #16315 - exceptions not caught in coolDropDb (resulting in Win runtime error) +- #16257 - folderset tag sequence table not created for createParents=true +- #16179 - findObject does not find user tagged objects +- fixed a feature in PyCoolTool that was preventing the use of aliases + +Bug fixes in CORAL_1_4_2 (binary compatible with CORAL_1_4_0): +- #16189 - missing quotes around "order" column name in SQLite table creation + +Minor modifications to transaction handling (split createFolderSet with +transactions from __createFolderSet without transactions). + +Maintained dependency on ROOT 5.10.00c (no upgrade to 5.11.02 yet). +Added configuration infrastructure for SLC4. + +============================================================================== +!2006.04.06 - Andrea + +Tag COOL_1_3_0. Functionality enhancement production release (first +release in the 1.3 series: backward incompatible API and schema changes). + +Main features with respect to COOL_1_2_8 and COOL_1_2_9: +- upgrade to CORAL_1_4_0 using LCG_43_2 +- CORAL-based API, drop all POOL dependencies +- user tags functionality according to spec #1 +- HVS functionality (limitation: the same tag cannot be used for >1 folders) +- schema evolution tool for user tag and HVS schema modifications +- CORAL connection service (including use of connection aliases) +- internal code cleanup (profound changes to the internal class structure) +- performance improvements for SV folders (remove non-uniformity) +- cool::Exception derived from std::exception instead of seal::Exception +- PyCool rewritten from scratch + +Summary of API changes: +- HVS functionality + > new IHvsNode methods: create/delete/findTagRelation and resolveTag + > new HVS exceptions Node/Tag[Relation]NotFound and NodeIsSingleVersion + > split IHvsNodeRecord from IHvsNode + > limitation: the same tag name still cannot be used for more than one folder +- prepare for further HVS features (reuse same tag name for several folders) + > changed std::string tagScope() to IHvsNode::Type tagNameScope() + > added std::vector<std::string> taggedNodes() +- CORAL connection service (URLs can be specified using aliases) +- user tags (storeObject accepts an optional tag name argument) + > added existsUserTag() +- drop all POOL dependencies (API now based on coral::AttributeList) +- cool::Exception derived from std::exception instead of seal::Exception +- const qualifyers added to many methods (not yet complete) + +Summary of schema changes: +- new userTagId column added to all IOV tables (both SV and MV) +- new tag sequence table added for all folder sets +- new global tag2tag table and sequence +- schema evolution rows may exist in the main database table + +Summary of internal changes: +- changes affected well over 50% of the total number of lines of code +- new session manager class for session management +- new query manager class for query and update management +- new schema manager class for schema manipulations +- new sequence manager class for sequence management +- new transaction manager class for sequence management +- new tag and node manager classes for HVS node and tag management +- 50% of RalDatabase code and functionality moved elsewhere +- significantly reduced ratio of CORAL specific Ral to generic Relational code +- progress in clean separation of generic HVS to specific CondDB code +- progress in adding const qualifyers wherever possible +- progress in simplifying forward/backward pointers/references between mgrs +- progress in separating record information (table rows) from active managers +- tool-specific authentication and privilege managers moved to utilities + +============================================================================== +!2006.04.06 - Andrea + +Summary of problems for Windows: +- unknown exception thrown (workaround by Andrea) +- MySQL still not supported by CORAL (COOL script workaround by Andrea) +- os.sysconf not defined in Python (fixed by Marco) +- ROOT window still pops up for Python (pending) + +============================================================================== +!2006.03.22 - Andrea + +Internal tag COOL_1_3_0-pre1 (stable state before COOL_1_3_0). +All C++, PyCool and PyCoolUtilities tests pass for slc3_ia32_gcc323_dbg. + +Main features with respect to COOL_1_2_8 and COOL_1_2_9: +- tests executed using (private version of) CORAL_1_3_1 +- user tags functionality according to spec #1 +- schema evolution tool for user tag schema modifications +- CORAL connection service +- cleanup well advanced: profound changes to the internal class structure +- performance improvements for SV folders (remove non-uniformity) +- std exception +- new PyCool +- CORAL-based API, drop all POOL dependencies +More complete details will follow in the COOL_1_3_0 release notes. + +Still missing on the way to COOL_1_3_0: +- waiting for CORAL_1_4_0 release with ISessionProxy::serverFlavor() +- use CORAL cross-backend connection aliases (dynamically retrieve flavor) +- HVS +- schema evolution tool for HVS + +============================================================================== +!2006.03.03 - Andrea + +Backward-incompatible API change (start adding HVS functionality). + +Change the semantics of the tagScope method in IDatabase: it now returns +whether a tag can be used for inner nodes (folder sets) or leaf nodes +(folders), rather than returning the node name it is used for. In HVS +(following a request from LHCb), the same tag name can be used for only +one folder set or for several folders. There is not anymore a unique node +each tag can be attached to. Also, a tag can be reserved for inner nodes +or leaf nodes without being actually attached to any specific nodes yet. + +No change in relational schema yet. +The schema still forces tags to be assigned to only one folder or folder +set, even if the API assumes that a tag can be assigned to several folders. + +============================================================================== +!2006.03.02 - Uli + +Removed non-uniformity in IOV retrieval for SV folders by implementing +Andrea's proposal for a two-step query strategy - query max(since) +followed by query for since=max(since). + +============================================================================== +!2006.03.01 - Andrea + +Completed internal formal cleanup of IOV table queries. +All IOV table queries have now been moved from RalObjectTable to +RelationalObjectTable and proceed through generic (non-CORAL specific) +methods in RelationalQueryMgr (implemented via CORAL in RalQueryMgr). + +============================================================================== +!2006.03.08 - Marco + +*** BRANCH RELEASE NOTES *** + +Tag COOL_1_2_9 (non-HEAD branch after COOL_1_2_8). +Backward-compatible production release. +Same code as 1.2.8, but compiled against LCG_42_4. + +============================================================================== +!2006.01.27 - Andrea + +Tag COOL_1_2_8. Backward-compatible production release (internal migration +from SEAL Reflex to ROOT Reflex; port to gcc344; attempted port to AMD64). + +Minor API changes ("long" -> "int") to attempt AMD64 port, should be +backward compatible for users on 32bit machines. No added functionalities. + +============================================================================== +!2006.01.27 - Andrea + +Note about the port from Reflection to Reflex: workarounds have been added +because SEAL exceptions are not caught from Cintex. This was already an +issue in COOL_1_2_7 (SEAL Cintex) and remains in COOL_1_2_8 (ROOT Cintex). +This was possible in PyLCGDict2/Reflection but was removed from Cintex/Reflex. +- Bug report (bug #14685): cintex does not catch seal exceptions +- Could be solved by deriving seal::Exception from std::exception (sr #100955) + +============================================================================== +!2006.01.27 - Sven + +Changes in handling of count(*) return type to ensure compatibility with MySQL +server 5.0 : essentially use the default CORAL return type (thanks to Ioannis). + +============================================================================== +!2006.01.27 - Andrea + +Many changes towards completing the AMD64 port (Uli, Sven, Marco, Andrea). +Got rid of "long" wherever possible, replaced by "int". + +Used many #ifdef to disable parts of the code on AMD64 +(essentially the storage of "long", keeping only "int" and "long long"), +but this is not a valid solution: all three types must be analysed, +the solution should be to throw an exception when storing "long". +This should be for 32bit platforms too for portability and will break the +current API for 32bit platforms (users should only store "int", not "long"). + +AMD64 port not completed because of pending bugs in CORAL and POOL: +- AttributeList in CORAL and POOL must analyse all three integers + (segmentation fault for missing integer type - bug #14684) +- MySQLAccess and SQLiteAccess return 4294967295 when 9223372036854775807 + was stored (bug #14688) + +Before completing the AMD64 port, a SEAL feature may also be changed: +- IntBits<64> is long long on 32bit, long on 64bit platforms (bug #14671) + +After solving all problems in SEAL, CORAL and POOL for AMD64, +a few pending issues in COOL also need to be addressed: +- Bug in COOL, at first incorrectly identified as a bug in ROOT (bug #14681) + +============================================================================== +!2006.01.16 - Andrea + +Tag COOL_1_2_7. Backward-compatible production release +(internal migration from RAL to CORAL and from Reflection to seal Reflex). + +All tests successful against Oracle, MySQL and SQLite using CORAL_1_2_1 +(including many CORAL bug fixes contributed by the COOL team). + +Workarounds for problems in PyCool and PyCoolUtilities after Reflex migration: +- disabled tests with mutex lock in boost/PyROOT (all platforms and backends) +- hacked config to have SEAL before ROOT (different/incompatible PyCintex.py) +- manually minimize windows during Windows test execution (ROOT window popup) + +Workaround in Examples for minor MySQLAccess bug (insertion of "'" character). + +First release with MySQL support on Windows (thanks to CORAL migration). + +============================================================================== +!2006.01.11 - Marco + +Complete migration of PyCool from seal Reflection to seal Reflex. +New mutex lock problem observed from boost/PyROOT/Reflex interaction. + +============================================================================== +!2005.12.16 - Marco + +First release candidate for COOL_1_2_7 based on CORAL_1_2_0. +MySQL and SQLite tests still fail. + +============================================================================== +!2005.12.09 - Marco + +Added thin layer to make the public API backward compatible. +Methods returning new CORAL AttributeList +kept as temporary extension, with suffix _new. + +Fixed gcc 3.4.4 compilation (bug #13395) + +============================================================================== +!2005.12.08 - Sven + +Internal reimplementation based on CORAL. +Oracle tests successful. MySQL and SQLite tests fail. + +API not backward compatible: POOL AttributeList +replaced by CORAL AttributeLists in the API. + +============================================================================== +!2005.11.15 - Andrea, Sven + +Internal tag COOL_1_2_7-pre1 (prepare for the CORAL migration). +All C++, PyCool and PyCoolUtilities tests pass for slc3_ia32_gcc323_dbg. + +Fix eight bugs in transaction handling (read-write transactions instead of +read-only transactions were started in RalDatabase). + +New IteratorIsClosed exception. Rename IteratorHasStarted as IteratorIsActive. + +Added IObjectIterator::close() API and implementation. + +============================================================================== +!2005.11.15 - Marco + +Tag COOL_1_2_6. Production release (backward-compatible +SEAL_1_7_6 and POOL_2_2_4 upgrade release in the 1.2 series). + +============================================================================== +!2005.11.09 - Marco + +Change the definition of int64 min/max value constants in types.h. +After upgrading to SEAL_1_7_6, seal::IntTraits<>::Min/Max fail at link time +on Windows. Temporary (?) workaround: use in COOL the same values that are +used in the SEAL IntTraits.cpp implementation (taken from SealBase/LongLong.h). + +============================================================================== +!2005.11.02 - Sven, Andrea + +Added IDatabase::openDatabase() and closeDatabase() API and implemntation. + +Added ObjectNotFound exception to the API. + +Added implicit ChannelSelection constructor from a ChannelId to the API. +Removed IFolder::browseObjects for a single channel (user code is not +broken as it can now use the implicit conversion to ChannelSelection). + +Added IFolder::countObjects API and implementation. + +Added live browsing functionalities for object iteration. +Added IFolder::setPrefetchAll() API and implementation (to choose +whether the browse methods should return a vector or live iterator). + +Added IObjectVector and IObjectVectorPtr type definitions to the API. +Added IObjectIterator::fetchAllAsVector API and implementation +(to retrieve all objects in the iterator as an STL vector). + +First prototype of STL-like iterator interface for object browsing. +Removed from public API, may be reintroduced later on. + +Clean up RalDatabase implementation using session() instead of m_session. + +Start internal reimplementation using new classes Ral/RelationalQueryMgr +and RelationalTableRow to remove some responsibilities from RalDatabase. + +============================================================================== +!2005.10.24 - Andrea, Marco + +Tag COOL_1_2_5. Production release (backward-compatible +SEAL_1_7_5 and POOL_2_2_3 upgrade release in the 1.2 series). + +Retag COOL_1_2_4 code as COOL_1_2_5. +Do not include changes other than those in VersionInfo and related tests. + +============================================================================== +!2005.10.05 - Andrea + +Add scripts for gathering Oracle table/schema statistics. + +============================================================================== +!2005.09.29 - Andrea, Sven, Marco, David, Uli + +Tag COOL_1_2_4. Production release (backward-compatible +bug-fix and POOL_2_2_1 upgrade release in the 1.2 series). + +VersionInfo: +- Release number = 1.2.4 +- Schema version = 1.2.0 +Backward compatibility with data written +using previous releases 1.2.3, 1.2.2, 1.2.1 and 1.2.0. + +All tests pass on all four supported platforms: slc3_ia32_gcc323, +slc3_ia32_gcc323_dbg slc3_ia32_gcc323_gcov and win32_vc71_dbg. + +- Upgrade to POOL_2_2_1 and SEAL_1_7_3 using LCG_37_2a + +- Identified and fixed outstanding memory leaks in COOL and POOL + (in close collaboration between the COOL and POOL teams for POOL) + > memory leak in all three flavours of RAL queries fixed in POOL_2_2_1 + (destructor for Oracle/MySQL/SQLite cursor was not called - note that + protected virtual destructor for IRelationalCursor is still missing) + > memory leak in AttributeList (only observed for osx103) fixed in + POOL_2_2_1 (missing destructors for Attribute[List][Specification]) + > memory leak in COOL fixed by disabling cool::TimingReport + (workaround: the real leak still needs to be identified and removed) + > ported ProcMemory utility class to osx103 and Windows for memory leak + analysis on Mac and Windows + +- Internal implementation changes + > move large fraction of RalDatabase.cpp to new class RelationalObjectTable + +============================================================================== +!2005.08.29 - Andrea, Sven and Marco + +Tag COOL_1_2_3. Production release (backward-compatible +API enhancement and bug-fix release in the 1.2 series). + +VersionInfo: +- Release number = 1.2.3 +- Schema version = 1.2.0 +Backward compatibility with data written +using previous releases 1.2.2, 1.2.1 and 1.2.0. + +All tests pass on all four supported platforms: slc3_ia32_gcc323, +slc3_ia32_gcc323_dbg slc3_ia32_gcc323_gcov and win32_vc71_dbg. + +============================================================================== +!2005.08.26 - Andrea and Sven + +- Move current mechanism for CLOB support from private to TEMPORARY public API + > document it as a TEMPORARY API extension that may be removed in COOL_1_3_0 + +============================================================================== +!2005.08.18 - Andrea and Sven + +- Added IDatabase::tagScope( tagName ) to get the scope of a tag (Andrea) + > returns the name of the node where the tag is defined + > throws TagNotFound if not found and ReservedHeadTag for HEAD tags + +- Added IDatabaseSvc::serviceVersion() to get library release tag (Andrea) + +============================================================================== +!2005.08.10 - Andrea and Sven + +- Added IFolder::folderAttributes() to get backend-specific properties (Andrea) + > for MV folders (3): the names of the IOV, tag and IOV2tag tables + > for SV folders (1): the name of the IOV table + +- Progress in understanding of problems with MyODBC bulk insertion (Marco) + > introduced workaround in COOL to disable MyODBC bulk insertions for all + tables with over 8kb data volume in each row (summed over all columns): + the problem does not affect only CLOBs, for instance bulk insertion into + three characters of 3000 characters would also generate a runtime error + > also understood that "bulk insertion" in MyODBC does not use bind + variables: this may imply a potentially large performance penalty + (which may be enough to motivate a switch from MyODBC to native MySQL API) + +- Internal support for CLOBs - not yet exposed in the public API (Marco) + > enable 'storage hints' for 64K and 16M CLOBs + > add tests of CLOB storage and retrieval using orivate API + +- Bug fixes in tag handling (Andrea) + > deleteGlobalTagTableRow was taking only one tagId argument, but the + PK for the global tag table also includes nodeId + > also correct error message printed out by deleteGlobalTagTableRow + +- API extensions for multi-channel bulk retrieval (Sven) + +- First prototype of infrastructure to create doxygen-based user guide (Andrea) + +============================================================================== +!2005.07.27 - Andrea and Sven + +Tag COOL_1_2_2. Production release (upgrade to SEAL_1_7_1 bug fix release). + +VersionInfo: +- Release number = 1.2.2 +- Schema version = 1.2.0 +Backward compatibility with data written +using previous releases 1.2.1 and 1.2.0. + +All tests pass on all four supported platforms: slc3_ia32_gcc323, +slc3_ia32_gcc323_dbg slc3_ia32_gcc323_gcov and win32_vc71_dbg. + +- Upgrade to POOL_2_1_2 and SEAL_1_7_1 using LCG_36_2a. + No change in the COOL code. + +- Upgrade to POOL_2_1_2 includes bug fix proposed by Marco for CLOBs + in OracleAccess (with extra improvements by Ioannis). + +============================================================================== +!2005.07.20 - Andrea and Sven + +Tag COOL_1_2_1. Production release (backward-compatible +API enhancement and bug-fix release in the 1.2 series). + +VersionInfo: +- Release number = 1.2.1 +- Schema version = 1.2.0 +Backward compatibility with data written using previous release 1.2.0. + +All tests pass on all four supported platforms: slc3_ia32_gcc323, +slc3_ia32_gcc323_dbg slc3_ia32_gcc323_gcov and win32_vc71_dbg. + +- Privilege management + > completed API and tools to grant reader, writer and tagger privileges: + added coolPrivilege command line utility to implemente them; + completed test suite in tests/Privileges (only tested on Oracle!) + > added private relational exceptions TableNotDropped, RowNotUpdated, + RowNotDeleted, RowNotInserted to test exceptions thrown because + of missing database privileges + > still missing for a future release (if needed): test on MySQL + +- Bug fixes in POOL + [available in POOL_HEAD two weeks ago but not included in COOL_1_2_1-pre1] + > "max# of open cursors exceeded" reported by David in Oracle, + identified by Sven in bulk insertion and fixed by Ioannis + [unfortunately this does not help much with memory leak reported by David] + > "pthread_mutex_lock" fixed by Ioannis using Andrea's suggestion to + disable Oracle multithreading (replace OCI_THREADED by OCI_DEFAULT) + [pthread_mutex_lock is indeed solved by removing OCI_THREADED: + cross-checked by running the same test with the ONLY difference + of enabling/disabling OCI_THREADED in a custom private version of POOL] + +- First production release with support for SQLite. + All unit tests pass for SQLite (after upgrade to POOL_2_1_1). + +- Extensive API cleanup for tag handling for HEAD and single-version folders + > add FolderIsSingleVersion exception: this is thrown for SV folders + by IFolder::tag() and internally by RelationalFolder::tagTableName() + and RelationalFolder::object2TagTableName() + > add ReservedHeadTag exception: this is thrown when trying to tag a node + using the "" or "HEAD" tags or trying to delete the "" or "HEAD" tags + > treat "" and "HEAD" (or any case insensitive variant such as "head" or + "Head") as equivalent in all methods: add method IHvsNode::isHeadTag() + method to test if a tag name is a reserved HEAD tag + > except for "HEAD", all other tag names are case sensitive + > IDatabase::existsTag() now returns true for both "" and "HEAD" + > IFolder::findObject() and IFolder::browseObjects() now accept both "" + and "HEAD" to indicate the HEAD tag; for all other tag names, throws + TagNotFound if tag does not exist or folder is a single version folder + > IFolder::tag() throws ReservedHeadTag for "" and "HEAD"; for all other + tag names, throws FolderIsSingleVersion for single version folders + and TagExists if the tag already exists for multi-version folders + > IFolder::deleteTag() throws ReservedHeadTag for "" and "HEAD"; for all + other tag names, throws TagNotFound if tag does not exist or folder is + a single version folder + > IHvsNode::listTags() does NOT list "" or "HEAD"; + it returns an empty list for folder sets and SV folders + > IHvsNode::tagDescription() returns default "HEAD tag" for "" and "HEAD"; + it throws TagNotFound for all other tags in folder sets and SV folders + > IHvsNode::tagInsertionTime() returns node insertion time for "" and "HEAD"; + it throws TagNotFound for all other tags in folder sets and SV folders + +- Further improvements in API for tagging methods + > declare the two tag() methods obsolete (to be removed in COOL_1_3_0) + in IFolder, rename them as tagCurrentHead and tagAsOfDate + [very dangerous in RalDatabase: tag() method with asOfDate argument was + called instead of tag() method with asOfObjectId argument if the latter + was commented out - implicit conversion of unsigned long to seal::Time!] + > add IFolder::tagLastObjectTime method + > use a string reference argument instead of a string argument + in IHvsNode::tagDescription and IHvsNode::tagInsertionTime + +- Internal cleanup of HvsNode, RelationalFolder and RelationalFolderSet + > renamed HvsNode as RelationalHvsNode + > RelationalFolder[Set] derived class inheriting from RelationalHvsNode + (modified listTags, tagDescription and tagInsertionTime accordingly): + this implied some debugging of 'inheritance by dominance' on Windows + and forced the use of inlined constructors for RelationalFolder[Set] + +- Bug fixes + > deleteTag() throws an exception if the number of rows deleted from the + object2tag table is different from the selected COUNT(*) for such rows + (computed using new method countObject2TagTableRows) + > IDatabase::dropNode also deletes any tags associated to the node + (and throws a RelationalException if such tags cannot be deleted) + +- Unit test coverage reports + > added support for slc3_ia32_gcc323_gcov: unit test coverage reports + will be built by the SPI team (thanks to Johanne!) + +============================================================================== +!2005.07.07 - Andrea and Sven + +Tag COOL_1_2_1-pre1. Internal tag. + +- Bug fixes in COOL: + > bug in dropping MV tables (reported by Federico, fixed by Sven) + > uninitialized variable in RelationalTypeConverter (Sven/Andrea) + +- API improvements + > added method IFolder::deleteTag (Sven) + > clarified exceptions thrown by dropDatabase and dropFolder methods, + throwIfDoesNotExist flag in dropDatabase and dropNode declared obsolete: + kept for backward compatibility, will be removed in COOL_1_3_0 (Andrea) + > add isFolderSet/isFolder flag to Folder/FolderSetNotFound exceptions + +- Internal refactoring + > new implementation of fetchObjectTableRows (Sven) + > gmtime tests moved to test_utilities, now included in test suite (Sven) + > add private NodeTableRowNotFound exception to fix inconsistencies (Andrea) + > extensive cleanup of dropDatabase and dropNode (Andrea) + +- Started work on privilege management (Andrea) + > added private class RalPrivilegeManager + > added tests to access database as owner/reader/writer/tagger/nopriv role + +- Bug fixes in POOL (see COOL_1_2_1) available in POOL_HEAD but not yet + included (tests for COOL_1_2_1-pre1 executed using POOL_2_1_0) + +============================================================================== +!2005.06.28 - Andrea and Sven + +Tag COOL_1_2_0. Production release (first release in the 1.2 series). + +VersionInfo: +- Release number = 1.2.0 +- Schema version = 1.2.0 +Backward compatibility with data written using NO previous release. + +All tests pass on all three supported platforms: +slc3_ia32_gcc323, slc3_ia32_gcc323_dbg and win32_vc71_dbg. + +All tests executed also on all RH73 platforms using private POOL_2_1_0 +(this was actually done using the code as of June 20, before some last fixes). +Last release with unit tests run on RH73 (not supported anymore by POOL/AF). +All tests pass on rh73_gcc323, rh73_gcc32 and rh73_gcc32_dbg, but the +RalDatabase unit test HANGS (__pthread_mutex_lock) on rh73_gcc323_dbg. +Commit the log file with failure (after Ctrl-C) fo reference. +Do not attempt to debug the problem, as RH73 is not supported anymore. + +PS: A __pthread_mutex_lock was also observed on SLC (in the same method +as RH73, the first time the unit tests were executed. The problem +disappeared when the unit tests were rerun on another SLC host. +It is likely that the source of the problem has been identified as the use +of multi-threaded OCI in RAL and will be removed in the next release of POOL. + +============================================================================== +!2005.06.28 - Andrea and Sven + +- Workaround for a bug in the seal::Time constructor. + > The bug affected unit tests on Windows (which may or may not fail + depending on local environment such as the summer time clock setting). + +- API enhancements + > Add the setDescription() method to change folder/folderset descriptions + +- Bug fix + > Fix bug reported by Federico: when inserting [20,+inf) over [30,+inf) + in single version mode, the latter was modified to [30,20] + +============================================================================== +!2005.06.17 - Andrea and Sven + +- Payload type handling improvements + > restrict uInt64 user payload to same 63-bit range as IOVs [0, 2^63-1] + +- Internal code cleanup + > tidy up (a bit, not complete!) the fetching of rows from the IOV table + +============================================================================== +!2005.06.13 - Andrea and Sven (with useful contributions from MANY people!) + +Tag COOL_1_2_0-pre1. Internal tag. + +- API changes (backward-incompatible) + > add IFolderSet interface and related methods in IDatabase + > changed IDatabase::dropFolder to dropNode + > removed IDatabase::listFolders + > implementation code has been changed accordingly + +- Performance improvements (pbs reported by DirkD) + > SV insertion: better scalability of query for last IOV by querying max(Id) + > findObject(): factor 2 improvement by removing useless node table lookup + +- Schema improvements (schema changed to 1.1.1) + > store insertion times as GMT with " GMT" appended (pb reported by Torre) + > change name of unique constraint on tag name + > changed index on node full path to unique (pb reported by DavidF) + > prepared simple utility to dump the COOL Oracle schema + +- DatabaseId and authentication improvements + > support POOL XMLAuthenticationService (also support COOL URL syntax) + > hide passwords from all printouts in the implementation code + > support the "host:port[/service]" syntax for Oracle and MySQL + +- Payload type improvements (thanks to Rado and Ioannis for RAL fixes) + > reenabled bool and unsigned char user payload (fixed in POOL HEAD) + > internally replaced maxSizeForCpp by checkStorageHintCompliance + +- Work on SQLite support (thanks to MarcoC and Zhen for many patches) + +All tests pass on rh73_gcc323 (using privately built POOL libraries +from POOL HEAD at -D "2005/06/15 12:00:00", later than POOL_2_1_0-zeta). + +============================================================================== +!2005.05.25 - Andrea and Sven + +Tag COOL_1_1_0. Production release (first release in the 1.1 series). + +VersionInfo: +- Release number = 1.1.0 +- Schema version = 1.0.1 +Backward compatibility with data written using releases 1.0.2 and 1.0.1. + +All tests pass on all seven supported platforms. + +============================================================================== +!2005.05.23 - Andrea and Sven + +Tag COOL_1_1_0-pre1. Internal tag. + +Major code repackaging and API changes +- RelationalCool is a plugin with no public header file +- move technology-independent exceptions from RelationalCool to CoolKernel +- move database service factory (and dependency on SealServices) from + RelationalCool to new package CoolApplication: there are now four tagged + packages in src (CoolKernel, RelationalCool, CoolApplication, Utilities) + +Functionality and performance improvements +- simultaneous bulk insertion into many channels does not throw an exception + any more (but more complete performance optimization will come in later tags) +- internally refactor store[Single/Multi]VersionObjects to use common code + +All tests pass on rh73_gcc323. + +============================================================================== +!2005.05.09 - Andrea and Sven + +Tag COOL_1_0_2. Production release (backward-compatible +API enhancement and bug-fix release in the 1.0 series). + +API enhancements: +- IFolder::listChannels +- IHvsNode::listTags and two related methods + +Bug fixes: +- prevent creation of two folders with the same name from two concurrent jobs + +VersionInfo: +- Release number = 1.0.2 +- Schema version = 1.0.1 +Backward compatibility with data written using release 1.0.1. + +All tests pass on all seven supported platforms. + +First production release using the new COOL CVS repository. + +============================================================================== +!2005.05.02 - Andrea and Sven + +Tag COOL_1_0_2-pre1. + +Internal tag: same code as COOL_1_0_1, using the new COOL CVS repository. + +============================================================================== +!2005.04.25 - Andrea and Sven + +Tag COOL_1_0_1. Production release (bug fix release in the 1.0 series). + +Bug fix: ValidityKey range checks added for MultiVersion folders. + +VersionInfo: +- Release number = 1.0.1 +- Schema version = 1.0.1 +Backward compatibility with data written using NO previous release. + +All tests pass on all seven supported platforms. + +ValidityKey type definition and allowed range unchanged: unsigned int64 +in [0, +9223372036854775807]. Schema version number changed to 1.0.1 +just to enforce that ValidityKey's > +9223372036854775807 are excluded. + +Support for unsigned int64 in user defined folder payload is unchanged. +Users can store also values in [+9223372036854775808, +18446744073709551615], +as long as they are aware how MySQL would interpret any queries on them. +In any case, it is not the responsibility of COOL to implement such queries. + +============================================================================== +!2005.04.22 - Andrea and Sven + +Tag COOL_1_0_0. FIRST PRODUCTION RELEASE! + +Minor change in SQL types: hack to change "RAL default" to NUMBER(10) +for long and unsigned long, and to NUMBER(20) for unsigned long long. + +Small bug fix in the unit tests (check on ValidityKeyMin hardcoded value). + +VersionInfo: +- Release number = 1.0.0 +- Schema version = 1.0.0 + +All tests pass on all seven supported platforms +(rh73_gcc323, rh73_gcc323_dbg, rh73_gcc32, rh73_gcc32_dbg, +slc3_ia32_gcc323, slc3_ia32_gcc323_dbg, win32_vc71_dbg). + +Dropped the idea of reviewing PK, UK and FK constraints and indexes as +it might take too much time. This can still be done in the next release. +Scripts can be provided to upgrade the schema, to add a few missing columns +(e.g. node_id with a fixed value in all folder-specific tables, usertag_id +in the IOV table...) and to drop and recreate indexes and constraints. + +Dropped the idea of providing Mac support and/or of providing scripts +for standalone local installations. These issues will be addressed later. + +============================================================================== +!2005.04.21 - Andrea and Sven + +Tag COOL_1_0_0-pre3 (production release 1.0.0 third internal prerelease). + +Extensive checks of SQL types. +Forced to introduce many workarounds for bugs and features in RAL and Oracle. + +- Problem with signed long long + (OCI-22053 when retrieving LLONG_MIN = -9223372036854775808). + This could be cured by limiting long long to >= -9223372036854775807. + TEMPORARY? More radical approach: get rid of signed long long for now. + Declare that long long in user payload is not supported. + *** Change ValidityKey to unsigned long long, but use only 63 bits *** + *** Change ValidityKeyMin to 0, keep ValidityKeyMax=9223372036854775807 *** + Eventually: rediscuss with the users if they want a signed or unsigned key. + Eventually: implement C++ check that user payload long long >= sInt64Min+1. + +- Problem with bool + (bug in RAL bulk insertion for both Oracle/MySQL, false=0 stored as true=1). + TEMPORARY! Declare that bool is not supported in user payload. + Eventually: bug fixed in OracleAccess-1-5-4 and ODBCAccess-1-1-14. + +- Problem with unsigned char + (no default SQL type in RAL OracleAccess). + TEMPORARY! Declare that unsigned char is not supported in user payload. + Eventually: bug fixed in OracleAccess-1-5-5. + +- Problem with long double + (no default SQL type in RAL MyODBCAccess). + TEMPORARY! Declare that long double is not supported in user payload. + Eventually: bug should be fixed in new MyODBCAccess. + +- Problems with char + (MySql error "String data, right truncated" in reading back 'a' or 'Z') + (Oracle stores and retrieves different values for binary data CHAR_MIN/MAX) + TEMPORARY! Declare that char is not supported in user payload. + Eventually: investigate and fix/workaround the two bugs + (should there be also a check that char is used only for character data?). + +============================================================================== +!2005.04.20 - Andrea and Sven + +Tag COOL_1_0_0-pre2 (production release 1.0.0 second internal prerelease). + +Final bug fixes. All tests pass on all seven supported platforms. + +============================================================================== +!2005.04.16 - Andrea and Sven + +Tag COOL_1_0_0-pre1 (production release 1.0.0 first internal prerelease). + +Code tested on rh73_gcc323 using the current configuration (one failure). +To do before the production release: +- fix the test that failed +- update to latest SEAL/POOL releases +- run tests on all four platforms + +Latest features added: +- Added ExtendedAttributeListSpecification adding one "hint" for each + attribute. This is used to create tables with non-default SQL types + (such as 4000-characters string instead of 255-character). Size + compliance checks are implemented everywhere. Hints (strings) replace the + previous implementation based on unsigned long sizes. + +Updated TODO list of functionalities to add in backward compatible way +(AFTER THE PRODUCTION RELEASE AND ITS DOCUMENTATION!): +- Add tests that folder description and tag description are limited in size +- Expose non-default hint functionality in public API to allow + storage of 4000 character strings +- The same functionality may be extended to store NUMBERS instead + of native BINARY_FLOAT in Oracle if requested for PVSS +- Once the problems with CLOB in Oracle are solved, add CLOB support +- Add methods to browse through the folder set hierarchy +- Add methods to add references to external tables +- Add user tags (this will require adding some columns) +- Review indexes, UK, FK in the relational schemas (this will require + creating methods and/or scripts to drop all indexes and FKs and + recreate new ones) + +============================================================================== +!2005.04.09 - Andrea and Sven + +Intermediate changes towards the production release: +- Renumber object_id encoding schema from 3N+0,1,2 to 6N+0,1,2,3,4,5 + to foresee the future implementation of user tags +- Implement string size checks in some of the tables +- Implement non-default string SQL types for some columns of some tables + +============================================================================== +!2005.04.05 - Andrea and Sven + +Intermediate changes towards production release (up to and including April 5): +- Renumber object_id to keep objects ordered with respect to version 'layers' + (also introduce internal tagAsOfObjectId functionality and unit tests for it) +- Introduce release number comparison (start addressing schema evolution) +- Internal name changes XXX_FOLDERS to XXX_NODES, folderId to nodeId, + FolderTable to NodeTable, FolderExistsException to NodeExistsException etc... +- Various bug fixes (browsing, MV-processing...) + +============================================================================== +!2005.03.20 - Andrea and Sven + +Intermediate tags towards the production release. + +Tag COOL_0_2_0-pre4: +- Final step in int64 IOV implementation: change ValidityKeyMin/Max + to LONG_LONG_MIN/MAX [-9223372036854775808, +9223372036854775807]. + +Tag COOL_0_2_0-pre3: +- Implemented since/until IOV storage type as signed int64. All tests pass. + No change in the accepted min/max boundaries for IOVs yet. +- Bug fix in RelationalFolder: clear storage buffer when storing fails +- This tag requires RelationalAccess-1-5-0 and OracleAccess-1-5-1 or later + (POOL tag does not exist yet, COOL config will be modified and retagged) + +Tag COOL_0_2_0-pre2: +- Name change: rename IValidityKey as ValidityKey and IChannelId as ChannelId + and check that all tests still pass. No change in stored type yet. + +Tag COOL_0_2_0-pre1: +- Minimal change: replace seal::LongLong by seal::IntBits<64>::SLeast + and check that all tests still pass. No change in stored type yet. + +============================================================================== +!2005.03.19 - Andrea and Sven + +Intermediate tags towards the production release. + +Tag COOL_0_1_1-pre2: +- Bypassed segmentation fault and mutex lock by using debug libraries + also on non-debug platforms +- Reenabled all test in RalDatabase_versioning test +- All tests from execUnitTests pass for both Oracle and MySQL on all of + rh73_gcc323, rh73_gcc323_dbg, rh73_gcc32, slc3_ia32_gcc323 +- Last stable tag before starting the implementation of int64 and CLOBs + +Tag COOL_0_1_1-pre1: +- Fixed the problem with tagging in MySQL + (change COOL usage of bind variables to bypass RAL problem) +- Changed online/offline to single/multi version +- Changed till to until consistently +- Changed getters consistently +- Consistently removed NULL values from all database tables + (copying AttributeList's will not work with NULL result sets from RAL) +- Fixed bugs in COOL with MySQL date (%i format and second granularity) and + MySQL bind variables (they need to be in the same order in the AttrList) + and fixed bugs in RAL (as of POOL_2_0_2) with MyODBC '\0' strings +- Move description() method for folders to IHvsNode and return + a string reference consistently to other IHvsNode string methods. +- Add a method to declare that some payload columns reference external payload. + Dummy implementation for the moment. +- Identified a workaround for the segmentation faults and mutex locks found + in RalDatabase_versioning test. Will become default as of next tag. + +============================================================================== +!2005.03.03 - Andrea and Sven + +First complete prototype with the versioning and tagging functionalities. +Tagged as prerelease COOL_0_1_0-pre1. +Tagged as prerelease COOL_0_1_0-pre2 (only configuration changes). + +This pre-release suffers from a known problem with MySQL in RAL +("since < :a and :a < until" will not work): use it only for Oracle. + +============================================================================== +!2005.02.02 - Andrea and Sven + +First version made publicly available for feedback. +Tagged as prerelease COOL_0_0_3-pre1. +Tagged as prerelease COOL_0_0_3-pre2 with Windows support added. + +============================================================================== +!2004.11.21 - Andrea and Sven + +New package. + +This package contains the implementation of the Cool kernel component +using the POOL RelationalAccess layer (RAL). + +============================================================================== diff --git a/RelationalCool/doc/unit_test_log.txt b/RelationalCool/doc/unit_test_log.txt new file mode 100644 index 000000000..35e426799 --- /dev/null +++ b/RelationalCool/doc/unit_test_log.txt @@ -0,0 +1,68 @@ +Passing tests on a given date. Failures in square brackets. + + 2004-11-30 2004-12-01 2004-12-02 2004-12-05 +RalDatabase 4 5 9 12 +RalDatabaseSvc 2 2 2 3 +RelationalDatabase 1 1 1 1 +RelationalFolder 1 2 2 2 + + 2004-12-13 2004-12-15 2004-12-15 +RalDatabase 12 15 19 +RalDatabaseSvc 2 3 3 +RelationalDatabase 1 1 1 +RelationalFolder 1 4 6 + + 2005-01-03 2005-01-14 2005-01-20 2005-01-26 +RalDatabase 20 23 23 23 +RalDatabaseSvc 3 4 4 4 +RelationalDatabase 1 1 1 1 +RelationalFolder 6 6 7 7 + + 2005-02-02 COOL_0_0_3-pre1 2005-02-04 +RalDatabase 29 29 29 +RalDatabaseSvc 4 4 4 +RelationalDatabase 1 1 1 +RelationalFolder 8 8 8 +HvsPathHandler 5 5 5 + + 2005-02-13 2005-02-15 2005-02-21 2005-03-01 +RalDatabase 59 32 32 32 +RalDatabase_versioning 29 29 51 +RalDatabaseSvc 4 4 4 4 +RelationalDatabase 1 1 1 1 +RelationalFolder 8 8 8 8 +HvsPathHandler 5 5 5 5 + + 2005-03-08 2005-03-17 2005-03-27 2005-04-04 +RalDatabase 32 33 33 36 +RalDatabase_versioning 51 51 58 60 +RalDatabaseSvc 4 4 4 4 +RelationalDatabase 1 1 1 1 +RelationalFolder 8 12 17 17 +HvsPathHandler 5 5 5 5 + + 2005-05-06 +RalDatabase 52 +RalDatabase_versioning 61 +RalDatabase_extendedSpec 12 +RalDatabaseSvc 4 +RelationalDatabase 6 +RelationalFolder 23 +HvsPathHandler 5 +ObjectId 11 + + 2005-07-05 +RalDatabase 57 +RalDatabase_versioning 66 +RalDatabase_extendedSpec 11 +RalDatabaseSvc 4 +RelationalDatabase 6 +RelationalFolder 30 +RelationalFolderSet 4 +RelationalTypeConverter 1 +HvsPathHandler 5 +ObjectId 11 +utility_methods 6 +---------------------------- +total 201 + diff --git a/RelationalCool/doc/userTagsImpl.txt b/RelationalCool/doc/userTagsImpl.txt new file mode 100755 index 000000000..2d82331af --- /dev/null +++ b/RelationalCool/doc/userTagsImpl.txt @@ -0,0 +1,451 @@ +=============================================== +User tag example specification (AV 06.04.2005) +=============================================== + +General idea: an IOV can be inserted with one (or more?) associated user tags. +This means that a consistent HEAD version must be kept (within the folder +and the channel) not only for ALL IOVS, but also for EACH subset of IOVS +associated to any given user tag. + +Let's consider two scenarios: +1. Each IOV can be inserted with ZERO or ONE user tags. +2. Each IOV can be inserted with any number of associated tags. + +NB Each tag is independent of each other: it is NOT foreseen that one can +ask for "the HEAD for tag A AND tag B, or the HEAD for tag A OR tag B". +Such a functionality can be implemented in scenario 2 by attaching ALSO +tag A_or_B to any IOV satisfying either tagA or tagB, for instance (any +such operation would be left to the user). + +Example 1 (scenario 1) +---------------------- +1. User inserts P1 payload in [ 0, 100] with NO user tags +2. User inserts P2 payload in [ 10, 50] with user tag #1 +3. User inserts P3 payload in [ 30, 80] with user tag #2 +4. User inserts P4 payload in [ 20, 40] with user tag #1 +5. User inserts P5 payload in [ 30, 70] with user tag #2 + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P2 in [ 10, 20] + P4 in [ 20, 30] + P5 in [ 30, 70] + P3 in [ 70, 80] + P1 in [ 80, 100] + +User tag #1: + P2 in [ 10, 20] + P4 in [ 20, 40] + P2 in [ 40, 50] + +User tag #2: + P5 in [ 30, 70] + P3 in [ 70, 80] + +Example 2 (scenario 2) +---------------------- +1. User inserts P1 payload in [ 0, 100] with NO user tags +2. User inserts P2 payload in [ 10, 50] with user tag #1 +3. User inserts P3 payload in [ 30, 80] with user tag #2 +4. User inserts P4 payload in [ 20, 40] with user tags #1 and #2 +5. User inserts P5 payload in [ 30, 70] with user tag #2 + +The ONLY difference with example 1 is that P4 is ALSO associated to tag #2. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): - no difference with example 1 + P1 in [ 0, 10] + P2 in [ 10, 20] + P4 in [ 20, 30] + P5 in [ 30, 70] + P3 in [ 70, 80] + P1 in [ 80, 100] + +User tag #1: - no difference with example 1 + P2 in [ 10, 20] + P4 in [ 20, 40] + P2 in [ 40, 50] + +User tag #2: + P4 in [ 20, 30] - ONLY difference with respect to example 1 + P5 in [ 30, 70] + P3 in [ 70, 80] + +================================================ +User tag example implementation (AV 06.04.2005) +================================================ + +* Unique identifiers + +The second scenario is more complex to implement than the first one. +The reason is that the unique identifier of each IOV/row is more complex. + +In scenario 1, each IOV is uniquely identified by +- UserId (Andrea's terminology) or 'layer number' (Sven's terminology): + the order in which objects are inserted by the user (irrespective of whether + they are associated to tags or not) +- SystemId which can take exactly one of FIVE values, for instance + > 0: user-inserted + > 1: left system-inserted for the ALL-tag HEAD + > 2: right system-inserted for the ALL-tag HEAD + > 3: left system-inserted for the HEAD of THE user tag + > 4: right system-inserted for the HEAD of THE user tag + +Also, in scenario 1, the IOV table only needs ONE extra column to identify +the user tag associated to each IOV (0 if no tag, tag# if there is one user tag). + +In scenario 2, each IOV is uniquely identified by +- UserId (Andrea's terminology) or 'layer number' (Sven's terminology): + the order in which objects are inserted by the user (irrespective of whether + they are associated to tags or not) - as in scenario 1 +- SystemId which can take exactly one of 3+2*Ntag values (for ntag tags), for instance + > 0: user-inserted + > 1: left system-inserted for the ALL-tag HEAD + > 2: right system-inserted for the ALL-tag HEAD + > 3: left system-inserted for the HEAD of user tag #1 + > 4: right system-inserted for the HEAD of user tag #1 + > 5: left system-inserted for the HEAD of user tag #2 + > 6: right system-inserted for the HEAD of user tag #2 + +Also, in scenario 2, a more complex mechanism is needed to map each IOV to the MANY +possible user tags associated to it. + +* Possible implementations + +As a consequence, the possible implementations of the two scenarios imply the +following modifications to the IOV table schema and storage pattern. + +In scenario 1 (implementation 1a): +- Add one column in the IOV table to hold the user tag ID + Type 0 (user inserted objects) have 0 in this column if no user tag is specified, + or they have the tagID in this column if a user tag is specified. + Type 1/2 (system inserted for ALL TAG) have always 0 in this column. + Type 3/4 (system inserted for the USER TAG) have the user tag in this column. +- SystemId is between 0 and 4 as explained above. +- Unique identifier is layer number + systemId from 0 to 4. + This can also be used to encode (or randomly assign) a surrogate key. +- Disadvantage of the model: assume that usertag must be 0 for sysId=1,2 and it + must be >0 for sysId=3,4 (but this can easily be enforced with a check constraint) + +START - Sven, read this part only if you really have nothing better to do! + +In scenario 2: +- The easiest (not the cleanest) option seems to be to add a single user tag column + (like in the previous case) and duplicate the rows for each user tag. + If an IOV is stored with no user tag, it is stored once with usertag=0 (sysid=0). + If an IOV is stored with user tag #3, it is stored twice, once with usertag=0 + and once with usertag=3 (sysid=0 in both cases). +- SystemId is only 0 (user), 1 (left system), 2 (right system). +- Unique identifier has three pieces, layer number, sysId from 0 to 2, user tag. + This can also be used to encode (or randomly assign) a surrogate key. +- Essentially each usertag is treated as a special "channel". +- Disadvantage: storage overhead, each user object is stored N+1 times if it + has N tags associated. Also (more important): model assumes that all objects with + the same layer number and sysId=0 are identical even if they have different usertags. +- Advantage: everything is contained in the IOV table, no need for a separate + iov2usertag table. + +We do not really care about scenario 2 because users acepted that only scenario 1 +is important. However scenario 2 is interesting as it points out possible +different implementations of scenario 1. + +In scenario 1 (implementation 1b): +- Add one column in the IOV table to hold the user tag ID + Type 0 (user inserted objects) have 0 in this column if no user tag is specified, + or they have the tagID in this column if a user tag is specified. + Type 1/2 (system inserted for ALL TAG) have always 0 in this column. + Type 3/4 (system inserted for the USER TAG) have the user tag in this column. + All as in implementation 1a. +- SystemId is only 0 (user), 1 (left system), 2 (right system). +- Unique identifier has three pieces, layer number, sysId from 0 to 2, user tag. + This can also be used to encode (or randomly assign) a surrogate key. +- Disadvantage of the model: need to enforce (very difficult!) the extra constraint + that layer number is a unique key for rows with sysId=0 (you do not want to + have rows that have the same layer number and sysId=0 but different userTag + values - either a user IOV had a user tag or it id not) + +In scenario 1 (implementation 1c): +- Add one column in the IOV table to hold the user tag ID + Type 0 (user inserted objects) are stoored once (with userTag=0) if no user tag + is specified and are stored twice (once also with userTag not 0) if a user tag + is specified. Type 1/2 (system inserted for ALL TAG) have always 0 in this column. + Type 3/4 (system inserted for the USER TAG) have the user tag in this column. +- SystemId is only 0 (user), 1 (left system), 2 (right system). +- Unique identifier has three pieces, layer number, sysId from 0 to 2, user tag. + This can also be used to encode (or randomly assign) a surrogate key. +- Disadvantage: storage overhead, each user object is stored two times if it + has one tag associated. Also (more important): model assumes that all objects with + the same layer number and sysId=0 are identical even if they have different usertags. + +All in all, the implementation of scenario 1 that seems easiest and safest is 1a. + +END - End of ranting ;-) + +* Possible implementation of example 1 + +Using implementation 1a, example 1 translates to the following table. + +Note that I use the following encoding algorithm for the surrogate key: + objectId = 1 + (layer#-1) * 5 + systemId (0,1,2,3 or 4) +This is similar to the present encoding without user tags, + objectId = 1 + (layer#-1) * 3 + systemId (0,1 or 2) + +Colum explanation: +- ObjectId = 5 * UserId + SystemId (surrogate PK) +- UserId = layer number (first of two fields in PK) +- SytemId = between 0 and 4 (second of two fields in PK) +- UserTag = 0 (no tag) or tagId +- Since, Until = IOV boundaries +- Payload = example payload +- OrigId = originalId as ObjectId and as (UserId, SystemId) +- NewHeadId = newHeadId as ObjectId and as (UserId, SystemId) + +1. User inserts P1 payload in [ 0, 100] with NO user tags +2. User inserts P2 payload in [ 10, 50] with user tag #1 +3. User inserts P3 payload in [ 30, 80] with user tag #2 +4. User inserts P4 payload in [ 20, 40] with user tag #1 +5. User inserts P5 payload in [ 30, 70] with user tag #2 + +ObjId UserId SysId UserTag Since Until Payload OrigId NewHeadId +(5u+s) (layer) (0to4) o(u,s) o(u,s) + +1 1 0 0 0 100 P1 0(0,0) 6(2,0) + +6 2 0 1 10 50 P2 0(0,0) 11(3,0) +7 2 1 0 0 10 P1 1(1,0) 0(0,0) +8 2 2 0 50 100 P1 1(1,0) 11(3,0) + +11 3 0 2 30 80 P3 0(0,0) 0(0,0) +12 3 1 0 10 30 P2 6(2,0) 0(0,0) +13 3 2 0 80 100 P1 8(2,2) 0(0,0) + +16 4 0 1 20 40 P4 0(0,0) 0(0,0) +17 4 1 0 10 20 P2 12(3,1) ARGHHHH +18 4 2 0 40 80 P3 11(3,0) +19 4 3 1 10 20 P2 6(2,0) +20 4 4 1 40 50 P2 6(2,0) + +21 5 0 2 30 70 P5 0(0,0) 0(0,0) +22 5 1 0 20 30 P4 16(4,0) +23 5 2 0 70 80 P3 18(4,2) +25 5 4 2 70 80 P3 11(3,0) + +Still other missing constraints: +- originalId points to null if sysId=0 (check constraint) +- newHeadId is always a user object (any u, s=0) +- newHeadId if userTag>0 points to an object with the same userTag +- originalId if sysId>0 and userTag>0 points to an object with the same userTag + +HEAD versions after last insertion: +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P2 in [ 10, 20] + P4 in [ 20, 30] + P5 in [ 30, 70] + P3 in [ 70, 80] + P1 in [ 80, 100] +User tag #1: + P2 in [ 10, 20] + P4 in [ 20, 40] + P2 in [ 40, 50] +User tag #2: + P5 in [ 30, 70] + P3 in [ 70, 80] + +.............................. INTERRUPT ................................. + +This thinking was very useful: there are many problems pending. + +Problem 1 (user tags) +---------------------- + +Implementation 1a is not enough. + +ONE newHeadId column, which is needed for the tag as of id functionality, +is not enough for user tags. User objects (sysId=0) with a tag +need TWO new heads: one for the no tag case, one for the tag case. + +It looks as if implementation 1c is better than implementation 1a. + +This means that the unique identifier (WITHIN EACH CHANNEL) +must span the layer number, the system id and the user tag. + +Note that in this case we can even accept scenario 2. + +Problem 2 (channels) +--------------------- + +The objectId surrogate key now is unique across channels. +There is no possible sensible encoding (unless we limit the number +of channels to a certain number) to decode into a surrogate ObjectId +unique across channels the totality of (channelId,userTag,layer,sysId). + +PS + +I like implementation 1c better because ++ there is a single newheadid column and ++ you may remove a user tag (remove all data associated to a user tag) ++ you may fit scenario 2 +- disadvantage: storage overhead + +============================================================================== + +Re: URGENT: and the channelId? +From: Andrea Valassi <Andrea.Valassi@cern.ch> +To: Sven A. Schmidt <sas@abstracture.de> +Reply-To: Andrea Valassi <Andrea.Valassi@cern.ch> +Date: Apr 7 2005 - 9:51am + +Hi Sven, + +I will call you on the phone to discuss this, anyway here's my new morning +rants... + +3. ChannelId holes + +You mention that this is not a problem. +In the end I agree, I do not care, for the moment, and not sure I would +care later. I just hope we can at least keep without holes the "this is +the insertionId order in this folder - across different channels". + +Just incidentally, we wuld not have an inflation in the number of sequence +tables. I think the best would be to have a single seqiene table per +folder, with one line per channel. By the way, eventually I think we need +a channel table per folder anyway. But this is FOR MUCH LATER. + +=> Conclusion: ok to keep the holes in each channel. + +2. ObjectId across channelId + +I made such a fuss about it, but in the end I am not sure what changes. I +agree it was good I at least realised that, so that we know the meaning of +the quantities (eg the insertionId we need to know that it spans several +channels). But maybe the queries are correct in the end. We should add +some tests using different channels, thats true. And I think eventually we +should add the possibility to selectively tag only the IOVS in a folder +which belong to a certain channel: in this case the queries should contain +the channelId, but otherwise maybe they would work anyway? + +=> Conclusion: probably not a problem. +We should add some tests across channels and see. + +1. ObjectId and UK. + +As I said, the schema will change with user tags. And having two separate +columns with insertionId and sysId is probably safer. + +NEVERTHELESS: +- I have already quite a good idea bout the schema for user tags +- I would like to change as little as possible now +- I believe we can still keep some encoding (connected to insertionId +unique across channels) +- IF at some oint we change the schema radically, nothing would make sense +anymore anyway: so better plan for now for the minimal changes +that would still be backward compatible + +The schema I propose (I will send you the details) foresees that user tags +"reserve" 3 (or maybe 2, but lets keep 3 for safety) extra ids for the +IOVS related to user tags (2 are the left and right inserted IOV, the +extra third one is the original user inserted iov, that I believe may be +safer to duplicate with a different id - once with usertag=0, once with +usertag=tag#). I would propose to simply keep the same algorithmic we have +now, both for encoding objectIds and obtaining the correct insertionId, +but just change the encoding from 3N+0,1,2 to 6N+0,1,2,3,4,5. For you, +this mainly means you need to "reserve" 5 holes instead of 2. +I think this is the fastest... and it is not so bad, I also keep some +encoding. IF at some point we change things radically, well it will not be +backward compatible anyway. But this intermediate solution leaves us some +space for manuevring. On top, we can ALSO add the two columns, provided +the insertionId makes sense like now, "the order of insertion in the +folder, across different channels": this is what is needed in the queries +anyway. + +By the way, IF we keep this encoding, this allows us to postpone the +addition of the two columns. We can always insert the extra columns later +and just derive them from the objectid. + +=> Conclusions: +- change "reserve 2 holes" to "reserve 5 holes" (Sven) +- change "3N+0,1,2" to "6N+0,1,2,3,4,5" in ObjectId (Sven or Andrea) +- add (but this is less urgent) two extra columns + +4. Tests + +Yes definitely needed + +=> Conclusion: Sven, plese try to devise some tests across channels. + +5. Was this useful? + +Well... I think it was useful thinking. But maybe there is not so much +that needs to be done or that would have caused a disaster, even having +forgotten channels. Or am I stil missing something? + +a. + + +On Wed, 6 Apr 2005, Sven A. Schmidt wrote: +> +> On 06.04.2005, at 18:10, Andrea Valassi wrote: +> +> > To summarise: +> > +> > 1. Please go ahead and add a layer number (I would call it insertionId +> > or userObjectId, see later) and a quantity systemId equal to 0,1,2 for +> > the IOV table. The tagAsOfObjectId should only rely on these columns +> > and not on the surrogate PK. I would keep the present encoding because +> > it does not harm, but we must take into account that things may change +> > in the future. Adding a user tag will mean either that an extra column +> > userTag (on top of channelId, insertionId, systemId) is needed to make +> > up a unique identifier (you may have data with the same ch=15, +> > insId=44 and sysId=1 meaning it is on the left, but different userTag +> > meaning that it was left inserted in the HEAD of ALL HEAD, tag=0, or a +> > specific tag>0), or it will mean that we change the meaning and +> > spectrum of systemId (for instance, sysId=3,4 for system inserted +> > associated to THE user tag). I would say: since it is not clear what +> > the objectId will be in the future, it is dangerous to give it a +> > meaning now. Better to rely on other columns starting now. +> +> Ok, will do. +> +> > 2. Please be aware that the "layer number" we discussed this morning +> > DOES HAVE HOLES. This is because there are several channels in the +> > same folder. This is why I am thinking it is maybe better to call it +> > "insertionId": it is just like an insertion time, but it is a number. +> > Like a ticket when you go to the supermarket and queue up at the +> > cheese shop... The meaning should be "this is the order - with no +> > holes - in which objects were inserted into this folder, to different +> > channels". Any other name suggestion? Calling it layer to me suggests +> > too much an order with no holes. +> +> Yes, ok. +> +> > 3. If you want to get rid of the previous problem, we would need to +> > have one sequence per channel. We could do that eventually... but not +> > now I think. +> +> I don't think it's a problem to have holes with respect to a channel. +> In any case it's much better than having sequence table inflation. The +> code reviewers would flog us around the LEP tunnel if they found out +> that we create an extra table per channel ;) +> +> > 4. It would be good indeed to think of introducing more tests where +> > several channels are mixed. Just to see if our logic works or not. +> > Maybe you can think of some weird cases? +> +> Yes, I'll add more. +> +> > 5. All this said, it seems to me I wasted one day of work. Not sure at +> > all we can keep some schema compatibility with the next schema... even +> > if of course we can try. +> +> I think it was very good you have spotted this. While the mutliversion +> code was not wrong in itself, it did not support the features you had in +> mind (tag atomicity). Had we released like this we'd definitely have to +> introduce backward incompatible changes. I think we still have a chance +> to pull this off. +> + diff --git a/RelationalCool/doc/userTagsImpl2.txt b/RelationalCool/doc/userTagsImpl2.txt new file mode 100644 index 000000000..7e58d3132 --- /dev/null +++ b/RelationalCool/doc/userTagsImpl2.txt @@ -0,0 +1,467 @@ +=============================================== +User tag example specification (AV 28.02.2006) +=============================================== + +General idea: an IOV can be inserted with AT MOST ONE associated user tag. +This means that a consistent HEAD version must be kept (within the folder +and the channel) not only for ALL IOVS, but also for EACH subset of IOVS +associated to any given user tag. + +Two specifications are discussed: +- In the 'old' (April 2005) specification, 'user tags' (those specified + when inserting a new IOV) are different from 'standard tags' (those + specified when tagging the HEAD of existing IOVs) and can NOT be mixed. +- In the 'new' (February 2006) specification, 'user tags' (those specified + when inserting a new IOV) are NOT different from 'standard tags (those + specified when tagging the HEAD of existing IOVs) and can be mixed. + +[NB Each tag is independent of each other: it is NOT foreseen that one can +ask for "the HEAD for tag A AND tag B, or the HEAD for tag A OR tag B".] + +Example 1 +---------- +1. User inserts P1 payload in [ 0, 100] with NO (user) tags +2. User inserts P2 payload in [ 10, 50] with (user) tag #1 +3. User inserts P3 payload in [ 30, 80] with (user) tag #2 +4. User inserts P4 payload in [ 20, 40] with (user) tag #1 +5. User inserts P5 payload in [ 30, 70] with (user) tag #2 + +The following applies both to the old and new specifications. +The only difference is in terminology: in the old specification, +these tags are 'user' tags (different type from 'standard' tags), +while in the new specification they are just 'tags'. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P2 in [ 10, 20] + P4 in [ 20, 30] + P5 in [ 30, 70] + P3 in [ 70, 80] + P1 in [ 80, 100] + +(User) tag #1: + P2 in [ 10, 20] + P4 in [ 20, 40] + P2 in [ 40, 50] + +(User) tag #2: + P5 in [ 30, 70] + P3 in [ 70, 80] + +Example 2 (old specification) +------------------------------ +1. User inserts P1 payload in [ 0, 50] with NO user tags +2. User inserts P2 payload in [ 50, 100] with NO user tags +3. User tags HEAD of folder with tag #2 +4. User inserts P4 payload in [ 10, 50] with user tag #1 +5. User inserts P5 payload in [ 30, 80] with user tag #2 - EXCEPTION +6. User inserts P6 payload in [ 20, 40] with user tag #1 +7. User inserts P7 payload in [ 30, 70] with user tag #2 - EXCEPTION + +In the old specification, step 5 and 7 here throw an exception: tag #2 is +already reserved as a 'standard' tag and cannot be used as a 'user' tag. + +HEAD versions after last insertion (ignoring step 5 and 7): + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P4 in [ 10, 20] + P6 in [ 20, 30] + P7 in [ 30, 70] + P5 in [ 70, 80] + P2 in [ 80, 100] + +Tag #1: + P4 in [ 10, 20] + P6 in [ 20, 40] + P4 in [ 40, 50] + +User tag #2: + P1 in [ 0, 50] + P2 in [ 50, 100] + +Example 2 (new specification) +------------------------------ +1. User inserts P1 payload in [ 0, 50] with NO user tags +2. User inserts P2 payload in [ 50, 100] with NO user tags +3. User tags HEAD of folder with tag #2 +4. User inserts P4 payload in [ 10, 50] with user tag #1 +5. User inserts P5 payload in [ 30, 80] with user tag #2 +6. User inserts P6 payload in [ 20, 40] with user tag #1 +7. User inserts P7 payload in [ 30, 70] with user tag #2 + +In the new specification, no exceptions are thrown. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P4 in [ 10, 20] + P6 in [ 20, 30] + P7 in [ 30, 70] + P5 in [ 70, 80] + P2 in [ 80, 100] + +Tag #1: + P4 in [ 10, 20] + P6 in [ 20, 40] + P4 in [ 40, 50] + +Tag #2: + P1 in [ 0, 30] + P7 in [ 30, 70] + P5 in [ 70, 80] + P2 in [ 80, 100] + +Example 3 (new specification) +------------------------------ + 1. User inserts P1 payload in [ 0, 50] with NO user tags + 2. User inserts P2 payload in [ 50, 100] with NO user tags + 3. User tags HEAD of folder with tag #2 + 4. User inserts P4 payload in [ 10, 50] with user tag #1 + 5. User inserts P5 payload in [ 30, 80] with user tag #2 + 6. User inserts P6 payload in [ 20, 40] with user tag #1 + 7. User inserts P7 payload in [ 30, 70] with user tag #2 + 8. User tags HEAD of folder with tag #2 + 9. User inserts P9 payload in [ 30, 80] with user tag #2 +10. User inserts P10 payload in [ 20, 40] with user tag #1 + +In the new specification, no exceptions are thrown. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P4 in [ 10, 20] + P10 in [ 20, 40] + P9 in [ 40, 80] + P2 in [ 80, 100] + +Tag #1: + P4 in [ 10, 20] + P10 in [ 20, 40] + P4 in [ 40, 50] + +Tag #2: + P1 in [ 0, 10] + P4 in [ 10, 20] + P6 in [ 20, 30] + P9 in [ 30, 80] + P2 in [ 80, 100] + +Essentially, tagging the HEAD (in step 8) with the same tag name +previously used for inserting IOVs with attached tags (e.g. step 5) +logically erases all tag-to-IOV relations defined when inserting +IOVs with attached tags (e.g. the tag attached in step 5 loses meaning). + +=============================================== +User tag implementation (AV 28.02.2006) +=============================================== + +IOV table +---------- + +Each IOV is uniquely identified by an ObjectId that can be built +from three variables: + +- UserId or 'layer number': the order in which objects are inserted by + the user (irrespective of whether they are associated to tags or not) + +- SystemId3 which can take exactly one of THREE values, for instance + > 0: user-inserted + > 1: left system-inserted for the (user tag or global) HEAD + > 2: right system-inserted for the (user tag or global) HEAD + +- HasTagId which can be 0 (not associated to user tag) or 1 + (associated to user tag) + +The combination of SystemId3 and HasTagId gives SystemId6 + SystemId6 = 3*(HasTagId-1) + SystemId3 +which can take exactly one of SIX values, for instance + > 0: user-inserted (NOT marked as belonging to a user tag) + > 1: left system-inserted for the global HEAD (IOVs with any tag or none) + > 2: right system-inserted for the global HEAD (IOVs with any tag or none) + > 3: copy of the user-inserted IOV (marked as belonging to a user tag) + > 4: left system-inserted for the HEAD of the user tag + > 5: right system-inserted for the HEAD of the user tag + +The ObjectId column already exists (COOL128) and the value is + ObjectId = 6*(UserId-1) + 3*(HasTagId-1) + SystemId3 +i.e. + ObjectId = 6*(UserId-1) + SystemId6 + +Instead of a HasTagId column, it is better to add to the IOV table +a TagId column, containing either 0 (no tag) or >0 (the tag id +of the user tag specified at insertion). + +To sum up the implementation: +- Add three columns ObjIdSys3, ObjIdUser and ObjIdTag. +- The ObjIdTag column references as FK the tagId column in the tag table. +- The ObjectId column (surrogate PK) is kept and is equal to + ObjectId = 6*(ObjIdUser-1) + 3*((is ObjIdTag>0?)-1) + ObjIdSys3 + A check constraint can/should be added to impose this. +- ObjIdUser is assigned from an internal sequence-like object. + Note that this corresponds to the global order id + for the insertion into the IOV table, across all channels. +- User inserted IOVs with no associated user tag are inserted only once + with ObjIdSys=0 and ObjIdTag=0. +- User inserted IOVs with an associated user tag tagId are inserted twice: + once with ObjIdSys=0 and ObjIdTag=0, once with ObjIdSys=0 and ObjIdTag=tagId. + This represents a modest storage overhead but simplifies the algorithm. +- System inserted IOVs are inserted with ObjIdSys=1 or 2 and with + ObjIdTag=0 if they refer to the global HEAD, or ObjIdTag=tagId + if they refer to the HEAD within the subset of IOVs tagged as tagId. + +Note that the payload is presently stored inline and is copied +within the IOV table in up to 6 identical copies. +Eventually, when the payload is split from the IOV table, +only a FK reference to a separate payload table needs +to be copied in up to 6 identical copies. + +Note that more complex constraints across separate rows +are imposed by the C++ algorithm but are not imposed on the database. +For instance, pairs of objects with the same ObjUserId and with ObjSysId3=0 +are identical even if one has ObjIdTag=0 and one has ObjIdTag>0. + +IOV2TAG table +-------------- + +1. Old specifcation + +In the 'old' specification, user tags and standard HEAD tags are two +different kinds of tags: all IOV data associated to user tags is +contained in the IOV table, all IOV data associated to standard tags +is contained in the IOV2TAG table. The two types of tags cannot be mixed. + +When storeObject(IOV,tag) is called, rows are inserted and updated +in the IOV table. In order to find/browse IOVs within a user tag, +only the IOV table must be queried. + +When tag(tag) is called, rows are inserted and deleted in the IOV2TAG table. +In order to find/browse IOVs within a standard tag, only the IOV2TAG table +must be queried (joined with the IOV table to retrieve the actual payload). + +As all IOV data associated to user tags is in the IOV table, where rows +can only be inserted or updated but never deleted, note that in the +'old' specification the IOV table may be used to preserve the history +log of all transactions associated to a given user tag. Rows in the +IOV2TAG table, conversely, are deleted and reinserted whenever a +new HEAD tag operation is performed, and the history log associated +to 'standard' tags is lost: only the tag-to-IOV associations defined +by the last tag operation are preserved persistently. + +2. New specification + +In the 'new' specification, the two types of tags can be mixed +and are actually a single type of tag. The IOV data associated +to tags is maintained both in the IOV and IOV2TAG tables. + +For simplicity, and because no user requirement to preserve +the history log of tag modifications has been expressed, the +design will assume that the history log of tag modifications +can be scratched. This implies that rows can/should also be deleted +from the IOV table. + +The IOV2TAG table is in any case maintained always up to date: +in order to find/browse IOVs within a standard tag, only the IOV2TAG table +must be queried (joined with the IOV table to retrieve the actual payload). + +When storeObject(IOV,tag) is called, rows are inserted and updated +in the IOV table. No rows are deleted from the IOV table, they are +only updated. The iov-to-tag associations relevant to the given tag +are ALSO stored by inserting and deleting rows in the IOV2TAG table. + +When tag(tag) is called, rows are inserted and deleted in the IOV2TAG table. +If the tag already existed and had been used to store IOVs in the IOV table +via the storeObject(IOV,tag) method, ALL rows associated to the given tag +(i.e. with ObjIdTag=tagId) are DELETED from the IOV table. This erases +all history of the given tag previous to the last tag(tag) call. + +Note that it is possible to design amn implementation to keep track +of all previous tag modifications. This can be done by never deleting +rows from either the IOV or the IOV2TAG table, and only updating rows +marking them as old (a new column is required in the IOV2TAG table). +But this was not required and will not be implemented. + +Roles and privileges +--------------------- + +In the scenario where obsolete tag data is deleted from the IOV table, +the 'retag' role must be granted the privilege to delete rows from +the IOV table. + +Eventually this role should be improved so that the privilege is only +granted on the appropriate view, for instance on the view selecting +from the IOV table where ObjIdTag>0. This may imply however that also +the C++ code manipulates the same view rather than the underlying table. + +Note also that other roles also need to be improved. For instance +the 'insert' role currently has privileges to update the IOV table, +but it would be safer to restrict this privilege to updating +only the relevant columns in the table. Unless this is done, +granting the delete on IOV table via a view is meaningless +(a nasty person could update the IOV table to set tagId>0 +and then delete the row, or in any case corrupt the IOV table +by randomly updating all rows). +Schema evolution tools +----------------------- + +Schema evolution tools are needed to add the new columns and fill them +with appropriate data. + +Regression tests across different schema/software versions are also needed. + +=============================================== +User tag example implementation (AV 28.02.2006) +=============================================== + +Example 1 +---------- + +1. User inserts P1 payload in [ 0, 100] with NO (user) tags +2. User inserts P2 payload in [ 10, 50] with (user) tag #1 +3. User inserts P3 payload in [ 30, 80] with (user) tag #2 +4. User inserts P4 payload in [ 20, 40] with (user) tag #1 +5. User inserts P5 payload in [ 30, 70] with (user) tag #2 + +IOV table: + +ObjId ObjIdUs ObjIdS3 ObjIdTag Since Until Payload OrigId NewHeadId +o u s o(u,s) o(u,s) + +1 1 0 0 0 100 P1 0(0,0) 7(2,0) + +7 2 0 0 10 50 P2 0(0,0) 13(3,0) +8 2 1 0 0 10 P1 1(1,0) 0(0,0) +9 2 2 0 50 100 P1 1(1,0) 13(3,0) +10 2 0 1 10 50 P2 0(0,0) 19(4,0) + +13 3 0 0 30 80 P3 0(0,0) 19(4,0) +14 3 1 0 10 30 P2 7(2,0) 19(4,0) +15 3 2 0 80 100 P1 9(2,2) 0(0,0) +16 3 0 2 30 80 P3 0(0,0) 25(5,0) + +19 4 0 0 20 40 P4 0(0,0) 25(5,0) +20 4 1 0 10 20 P2 14(3,1) 0(0,0) +21 4 2 0 40 80 P3 13(3,0) 25(5,0) +22 4 0 1 20 40 P4 0(0,0) 0(0,0) +23 4 1 1 10 20 P2 10(2,0) 0(0,0) +24 4 2 1 40 50 P2 10(2,0) 0(0,0) + +25 5 0 0 30 70 P5 0(0,0) 0(0,0) +26 5 1 0 20 30 P4 19(4,0) 0(0,0) +27 5 2 0 70 80 P3 21(4,2) 0(0,0) +28 5 0 2 30 70 P5 0(0,0) 0(0,0) +29 5 2 2 70 80 P3 16(3,0) 0(0,0) + +IOV2TAG table: + +TagId ObjId Since Until +1 23 10 20 +1 22 20 40 +1 24 40 50 +2 28 30 70 +2 25 70 80 + +Example 2 (new specification) +------------------------------ +1. User inserts P1 payload in [ 0, 50] with NO user tags +2. User inserts P2 payload in [ 50, 100] with NO user tags +3. User tags HEAD of folder with tag #2 +4. User inserts P4 payload in [ 10, 50] with user tag #1 +5. User inserts P5 payload in [ 30, 80] with user tag #2 +6. User inserts P6 payload in [ 20, 40] with user tag #1 +7. User inserts P7 payload in [ 30, 70] with user tag #2 + +ObjId ObjIdUs ObjIdS3 ObjIdTag Since Until Payload OrigId NewHeadId +o u s o(u,s) o(u,s) + +1 1 0 0 0 50 P1 0(0,0) 13(3,0) + +7 2 0 0 50 100 P2 0(0,0) 19(4,0) + + --HEAD tagged as tag 2-- + +13 3 0 0 10 50 P4 0(0,0) 19(4,0) +14 3 1 0 0 10 P1 1(1,0) 0(0,0) +16 3 0 1 10 50 P4 0(0,0) 0(0,0) + +19 4 0 0 30 80 P5 0(0,0) 25(5,0) +20 4 1 0 10 30 P4 13(3,0) 25(5,0) +21 4 2 0 80 100 P2 7(2,0) 0(0,0) +22 4 0 2 30 80 P5 0(0,0) 31(6,0) +23 4 1 2 0 30 P1 0(0,0) 0(0,0) +24 4 2 2 80 100 P2 0(0,0) 0(0,0) + +25 5 0 0 20 40 P6 0(0,0) 31(6,0) +26 5 1 0 10 20 P4 20(4,1) 0(0,0) +27 5 2 0 40 80 P5 19(4,0) 31(6,0) +28 5 0 1 20 40 P6 0(0,0) 0(0,0) +29 5 1 1 10 20 P4 16(3,0) 0(0,0) +30 5 2 1 40 50 P4 16(3,0) 0(0,0) + +31 6 0 0 30 70 P7 0(0,0) 0(0,0) +32 6 1 0 20 30 P6 25(5,0) 0(0,0) +33 6 2 0 70 80 P5 27(5,2) 0(0,0) +34 6 0 2 30 70 P7 0(0,0) 0(0,0) +36 6 2 2 70 80 P5 22(4,0) 0(0,0) + +IOV2TAG table: + +TagId ObjId Since Until +1 29 10 20 +1 28 20 40 +1 30 40 50 +2 23 0 30 +2 34 30 70 +2 36 70 80 +2 24 80 100 + +COMMENT 1 +---------- + +The IOV2TAG table is badly needed for performance reasons +in the retrieval of tagged MV data. +[Note that the HEAD tag instead is retrieved directly from the IOV table.] + +Nevertheless, it would be possible in principle to rebuild the +IOV2TAG table starting from the IOV table alone, provided that +for each tag the TAG table stores the value of the last inserted IOV id +at the moment when the last HEAD tag operation was performed. + +In the example above: + tagId headTaggedAsOfId + 1 7 + 2 0 (tag exists but was not used to tag the HEAD so far) + +This value cannot be simply used in a relational query to find/browse +all IOVs in a given tag, but could be used to trigger a C++ verification +of the contents of the IOV2TAG table. + +COMMENT 2 +---------- + +The performance of the standard HEAD query is under investigation. +If this proved to be too slow, it is possible to envisage adding +all HEAD IOVs to the IOV2TAG table too with a reserved tagId of 0. +This would indicate the global HEAD tag. + +This may actually be required in any case if the FK constraint +between the IOV table (ObjIdTag) and the TAG table is imposed, +unless ObjIdTag is left as NULL rather than equal to 0. + +COMMENT 3 +---------- + +In the proposal above the ObjectId column is encripted as + ObjectId = 6*(ObjIdUser-1) + 3*((is ObjIdTag>0?)-1) + ObjIdSys3 +This is consistent with the present (COOL128) numbering, +where user-inserted IOVs are numbered 1,7,13,19... + +An alternative possibility would be to use the encription + ObjectId = 10*(ObjIdUser-1) + 3*((is ObjIdTag>0?)-1) + ObjIdSys3 +so that user-inserted IOVs would be numbered 1,11,21,31... +The advantage would only be that the numbering is more intuitive. + diff --git a/RelationalCool/doc/userTagsImpl3.txt b/RelationalCool/doc/userTagsImpl3.txt new file mode 100644 index 000000000..c7892b70c --- /dev/null +++ b/RelationalCool/doc/userTagsImpl3.txt @@ -0,0 +1,70 @@ +=============================================== +User tag implementation (AV 01.03.2006) +=============================================== + +Just a few brief notes to complement userTagsSpec3.txt and userTagsImpl2.txt. + +With respect to the implementation proposed in userTagsImpl2.txt: +- Drop the constraint that objectId is a function of userId and sysId. + For every userId, more than one tag can be associated, hence there + would be no good constraining scheme. Simply use a sequence with no + holes, describing the order in which rows are inserted in the table. +- This means that more than one user tag can be specified on insertion. +- The newHeadId column must reference the userId column instead + of the objectId column. +- For each tag, a __complete__ parallel branch of IOV HEAD is maintained. + When a HEAD tag is defined, all IOVs are re-inserted into the IOV table + with a new userId (originalId is the old userId) and the relevant tagId. +- The full history of tags is maintained in the IOV table. + This may become very very large. Payloads should be stored externally. + Note that userId could be used as FK reference to the external payload + table: you do not actually need a separate FK column + (one userId <-> one payload). +- The IOV2TAG table is simply a snapshot of the IOV table for the + IOVs currently associated to tags. It does not hold additional + information that cannot be retrieved from the IOV table via simple queries. +- A table (the tag table?) must maintain the history of when HEAD tags + where defined (at which objectId). + +======================================================= +Additional notes after Richard's reply (AV 02.03.2006) +======================================================= + +Richard suggests that we could just implement scenario 2. + +I think in any case that it would be safer to implement this using the same +implementation as scenario 3, with all relevant information in the IOV table, +but throwing away rows from the IOV table as they become obsolete. +This seems safer in the sense that it would in any case allow us to +switch on history logging if required by the users and/or for our own +internal debugging, while the removal of obsolete rows would prevent +the IOV table from growing too big. + +The duplication of information across the IOV and IOV2TAG tables however +should be avoided. One possibility would be to add the extra tagged rows +to the IOV table (ALL associations of IOVs to tags), as suggested for +scenario 3, and get rid of the IOV2TAG table as the IOV table alone +could be enough (and not too large if old data are purged). The alternative +possibility (better?) is to add to the IOV2TAG table ALL columns from the +IOV table (except the payload) and actually have the tagged rows ONLY +in the IOV2TAG table instead of the IOV table, but with the same logic +used in the IOV table. + +In any case, the splitting of payload from IOV table seems unavoidable. +Note that my previous comment was wrong: it is not enough to keep userId +as reference to the payload, because current userId for system inserted +objects is the userId of the new IOV triggering system insertion, while +the originalId for these system objects may be another system inserted +object. One possibility is to add a new column originalUserId which +actually points to the very first user inserted object, i.e. the one which +indeed was inserted with a payload. + +It would be useful to implement an internal 'purge' method taking as +argument a date/objectId before which all obsolete rows can be erased. +The implementation could use this internally periodically, or after +each insertion, in spec#2. To implement spec#3 it would be enough to +switch off its automatic use, and only offer it to users as an +additional functionality. + + + diff --git a/RelationalCool/doc/userTagsSpec.txt b/RelationalCool/doc/userTagsSpec.txt new file mode 100644 index 000000000..891a4c451 --- /dev/null +++ b/RelationalCool/doc/userTagsSpec.txt @@ -0,0 +1,158 @@ +From Andrea.Valassi@cern.ch Wed Apr 6 15:22:28 2005 +Date: Wed, 6 Apr 2005 13:07:43 +0200 (CEST) +From: Andrea Valassi <Andrea.Valassi@cern.ch> +To: David Malon <malon@anl.gov> +Cc: Sven Schmidt <sas@abstracture.de>, + LCG ConditionsDB developers + <project-lcg-peb-conditionsdb-developers@cern.ch> +Subject: ~URGENT: user tags + +Hi David, + +a (hopefully) quick question. We are not going to implement the "user tag" +functionality you requested in the production release. Nevertheless, I +would like to be sure already that I understand EXACTLY what you require, +also because I'd like to foresee in advance the changes this implies to +the IOV table schema, so that the IOV table schema in the production +release is not radically incompatible with that required for implementing +user tags. + +I am including below two simple examples that, in my understanding, +demonstrate your requirement. I am actually including TWO examples for two +slightly different scenarios: 1. when a user can specify AT MOST ONE user +tag with each inserted IOV, and 2. when a user can specify ANY number of +user tags with each inserted IOV. I think that the simpler scenario 1 +should satisfy your needs. I am rather reluctant to go to scenario 2 +because it implies a more complex implementation (which I would solve by +increasing the storage overhead) and especially because it opens the door +to a potential unnecessary inflation in the number of user tags ("I'll +attach 15 different tags to this IOV, just in case I MAY need them +later"), with serious consequences on performance and scalability. +Of course user requirements come first, but I would invite users to ask +for the requirements that are really required :-) + +This is only meant to get a quick reply to get a feeling what you need: +can you please have a quick look and confirm +- whether one of the two scenarios fulfills your requirements, or whether + you actually had in mind something RADICALLY different +- if the first answer is yes, whether the first scenario is indeed + enough or you would need the functionality of the second +Thanks a lot! + +Feedback from anyone else (especially Atlas, since this where the +requirement came from... Richard and Torre, for instance) is of course +welcome! Please answer asap with a first quick feedback (today if you +can?). + +It's not a catastrophe if we dont converge now... but at least I'll +give it a try to get a better idea before the production release. + + Cheers + + Andrea + +Ps Sven, can you please prepare a picture for the two? + +=============================================== +User tag example specification (AV 06.04.2005) +=============================================== + +General idea: an IOV can be inserted with one (or more?) associated user tags. +This means that a consistent HEAD version must be kept (within the folder +and the channel) not only for ALL IOVS, but also for EACH subset of IOVS +associated to any given user tag. + +Let's consider two scenarios: +1. Each IOV can be inserted with ZERO or ONE user tags. +2. Each IOV can be inserted with any number of associated tags. + +NB Each tag is independent of each other: it is NOT foreseen that one can +ask for "the HEAD for tag A AND tag B, or the HEAD for tag A OR tag B". +Such a functionality can be implemented in scenario 2 by attaching ALSO +tag A_or_B to any IOV satisfying either tagA or tagB, for instance (any +such operation would be left to the user). + +Example 1 (scenario 1) +---------------------- +1. User inserts P1 payload in [ 0, 100] with NO user tags +2. User inserts P2 payload in [ 10, 50] with user tag #1 +3. User inserts P3 payload in [ 30, 80] with user tag #2 +4. User inserts P4 payload in [ 20, 40] with user tag #1 +5. User inserts P5 payload in [ 30, 70] with user tag #2 + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P2 in [ 10, 20] + P4 in [ 20, 30] + P5 in [ 30, 70] + P3 in [ 70, 80] + P1 in [ 80, 100] + +User tag #1: + P2 in [ 10, 20] + P4 in [ 20, 40] + P2 in [ 40, 50] + +User tag #2: + P5 in [ 30, 70] + P3 in [ 70, 80] + +Example 2 (scenario 2) +---------------------- +1. User inserts P1 payload in [ 0, 100] with NO user tags +2. User inserts P2 payload in [ 10, 50] with user tag #1 +3. User inserts P3 payload in [ 30, 80] with user tag #2 +4. User inserts P4 payload in [ 20, 40] with user tags #1 and #2 +5. User inserts P5 payload in [ 30, 70] with user tag #2 + +The ONLY difference with example 1 is that P4 is ALSO associated to tag #2. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): - no difference with example 1 + P1 in [ 0, 10] + P2 in [ 10, 20] + P4 in [ 20, 30] + P5 in [ 30, 70] + P3 in [ 70, 80] + P1 in [ 80, 100] + +User tag #1: - no difference with example 1 + P2 in [ 10, 20] + P4 in [ 20, 40] + P2 in [ 40, 50] + +User tag #2: + P4 in [ 20, 30] - ONLY difference with respect to example 1 + P5 in [ 30, 70] + P3 in [ 70, 80] + +------------------------------------------------------------------------------- + +From: RD Schaffer <R.D.Schaffer@cern.ch> +To: Sven A. Schmidt <sas@abstracture.de> +CC: Marco Clemencic <Marco.Clemencic@cern.ch>, + Andrea Valassi <Andrea.Valassi@cern.ch>, + Antoine Pérus <perus@lal.in2p3.fr>, + Richard Hawkings <rhawking@mail.cern.ch> +Date: May 19 2005 - 5:04pm + +Hi there, + + Andrea should respond here. But I believe that his thoughts about +David M.'s request is to provide user tags which are different than +the regular tag. So one could insert with a user tag, and then later +based on a particular user tag, tag a set of objects. This would resolve +the problem of the 'in between' object - it would have a different user +tag if so desired. + + see you, RD + +------------------------------------------------------------------------------- + +For reference: David Malon presented his use case in the presentation +at the 2003 CondDB Workshop: http://agenda.cern.ch/fullAgenda.php?ida=a036470 + + diff --git a/RelationalCool/doc/userTagsSpec2.txt b/RelationalCool/doc/userTagsSpec2.txt new file mode 100644 index 000000000..4c10ec74c --- /dev/null +++ b/RelationalCool/doc/userTagsSpec2.txt @@ -0,0 +1,196 @@ +Dear all, + +following yesterday's discussion with Sven and Richard at the Monday +meeting about the new 'user tag' functionality required for COOL_1_3_0, +I would like to propose to you the following slightly different +(improved) specification and implementation design. + +For reference: the original specification is the one I proposed +in an e-mail message in April last year, which you can also find in +the COOL CVS doc repository in + http://cool.cvs.cern.ch/cgi-bin/cool.cgi/cool/RelationalCool/doc/userTagsSpec.txt + +For the development team: the initial implementation design (later +complemented by more email exchanges with Sven, not included) is also in + http://cool.cvs.cern.ch/cgi-bin/cool.cgi/cool/RelationalCool/doc/userTagsImpl.txt + +Basically, last year's agreement was that users can specify AT MOST ONE +user tag when inserted a new IOV. From yesterday's discussion, I think +we still agree on this point. + +However, last year's proposal also assumed that 'user tags' (those +specified when inserting a new IOV) are different from 'standard tags' +(those specified when tagging the HEAD of existing IOVs). From +yesterday's discussion, this is the point which could still be improved. + +I propose below a new functionality specification that goes in this +direction. I split this in two parts: a summary of last year's proposal, +plus a possible extension. The reason is that I am not sure we can +implement the full picture for COOL_1_3_0. + +Cheers + +Andrea + +=============================================== +User tag example specification (AV 28.02.2006) +=============================================== + +General idea: an IOV can be inserted with AT MOST ONE associated user tag. +This means that a consistent HEAD version must be kept (within the folder +and the channel) not only for ALL IOVS, but also for EACH subset of IOVS +associated to any given user tag. + +Two specifications are discussed: +- In the 'old' (April 2005) specification, 'user tags' (those specified + when inserting a new IOV) are different from 'standard tags' (those + specified when tagging the HEAD of existing IOVs) and can NOT be mixed. +- In the 'new' (February 2006) specification, 'user tags' (those specified + when inserting a new IOV) are NOT different from 'standard tags (those + specified when tagging the HEAD of existing IOVs) and can be mixed. + +[NB Each tag is independent of each other: it is NOT foreseen that one can +ask for "the HEAD for tag A AND tag B, or the HEAD for tag A OR tag B".] + +Example 1 +---------- +1. User inserts P1 payload in [ 0, 100] with NO (user) tags +2. User inserts P2 payload in [ 10, 50] with (user) tag #1 +3. User inserts P3 payload in [ 30, 80] with (user) tag #2 +4. User inserts P4 payload in [ 20, 40] with (user) tag #1 +5. User inserts P5 payload in [ 30, 70] with (user) tag #2 + +The following applies both to the old and new specifications. +The only difference is in terminology: in the old specification, +these tags are 'user' tags (different type from 'standard' tags), +while in the new specification they are just 'tags'. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P2 in [ 10, 20] + P4 in [ 20, 30] + P5 in [ 30, 70] + P3 in [ 70, 80] + P1 in [ 80, 100] + +(User) tag #1: + P2 in [ 10, 20] + P4 in [ 20, 40] + P2 in [ 40, 50] + +(User) tag #2: + P5 in [ 30, 70] + P3 in [ 70, 80] + +Example 2 (old specification) +------------------------------ +1. User inserts P1 payload in [ 0, 50] with NO user tags +2. User inserts P2 payload in [ 50, 100] with NO user tags +3. User tags HEAD of folder with tag #2 +4. User inserts P4 payload in [ 10, 50] with user tag #1 +5. User inserts P5 payload in [ 30, 80] with user tag #2 - EXCEPTION +6. User inserts P6 payload in [ 20, 40] with user tag #1 +7. User inserts P7 payload in [ 30, 70] with user tag #2 - EXCEPTION + +In the old specification, step 5 and 7 here throw an exception: tag #2 is +already reserved as a 'standard' tag and cannot be used as a 'user' tag. + +HEAD versions after last insertion (ignoring step 5 and 7): + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P4 in [ 10, 20] + P6 in [ 20, 30] + P7 in [ 30, 70] + P5 in [ 70, 80] + P2 in [ 80, 100] + +Tag #1: + P4 in [ 10, 20] + P6 in [ 20, 40] + P4 in [ 40, 50] + +User tag #2: + P1 in [ 0, 50] + P2 in [ 50, 100] + +Example 2 (new specification) +------------------------------ +1. User inserts P1 payload in [ 0, 50] with NO user tags +2. User inserts P2 payload in [ 50, 100] with NO user tags +3. User tags HEAD of folder with tag #2 +4. User inserts P4 payload in [ 10, 50] with user tag #1 +5. User inserts P5 payload in [ 30, 80] with user tag #2 +6. User inserts P6 payload in [ 20, 40] with user tag #1 +7. User inserts P7 payload in [ 30, 70] with user tag #2 + +In the new specification, no exceptions are thrown. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P4 in [ 10, 20] + P6 in [ 20, 30] + P7 in [ 30, 70] + P5 in [ 70, 80] + P2 in [ 80, 100] + +Tag #1: + P4 in [ 10, 20] + P6 in [ 20, 40] + P4 in [ 40, 50] + +Tag #2: + P1 in [ 0, 30] + P7 in [ 30, 70] + P5 in [ 70, 80] + P2 in [ 80, 100] + +Example 3 (new specification) +------------------------------ + 1. User inserts P1 payload in [ 0, 50] with NO user tags + 2. User inserts P2 payload in [ 50, 100] with NO user tags + 3. User tags HEAD of folder with tag #2 + 4. User inserts P4 payload in [ 10, 50] with user tag #1 + 5. User inserts P5 payload in [ 30, 80] with user tag #2 + 6. User inserts P6 payload in [ 20, 40] with user tag #1 + 7. User inserts P7 payload in [ 30, 70] with user tag #2 + 8. User tags HEAD of folder with tag #2 + 9. User inserts P9 payload in [ 30, 80] with user tag #2 +10. User inserts P10 payload in [ 20, 40] with user tag #1 + +In the new specification, no exceptions are thrown. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P4 in [ 10, 20] + P10 in [ 20, 40] + P9 in [ 40, 80] + P2 in [ 80, 100] + +Tag #1: + P4 in [ 10, 20] + P10 in [ 20, 40] + P4 in [ 40, 50] + +Tag #2: + P1 in [ 0, 10] + P4 in [ 10, 20] + P6 in [ 20, 30] + P9 in [ 30, 80] + P2 in [ 80, 100] + +Essentially, tagging the HEAD (in step 8) with the same tag name +previously used for inserting IOVs with attached tags (e.g. step 5) +logically erases all tag-to-IOV relations defined when inserting +IOVs with attached tags (e.g. the tag attached in step 5 loses meaning). + +------------------------------------------------------------------------------- + +For reference: David Malon presented his use case in the presentation +at the 2003 CondDB Workshop: http://agenda.cern.ch/fullAgenda.php?ida=a036470 diff --git a/RelationalCool/doc/userTagsSpec3.txt b/RelationalCool/doc/userTagsSpec3.txt new file mode 100644 index 000000000..e13358fae --- /dev/null +++ b/RelationalCool/doc/userTagsSpec3.txt @@ -0,0 +1,335 @@ +From Andrea.Valassi@cern.ch Wed Mar 1 17:46:57 2006 +Date: Wed, 1 Mar 2006 17:46:17 +0100 (CET) +From: Andrea Valassi <Andrea.Valassi@cern.ch> +To: LCG ConditionsDB developers + <project-lcg-peb-conditionsdb-developers@cern.ch> +Subject: User tag functionality specification + +Dear all, + +following Monday's discussion with Sven and Richard at the weekly COOL +meeting about the new 'user tag' functionality required for COOL_1_3_0, +we had some discussion in the development team about the possibility +to extend the specification proposed last year to meet the new requirements +discussed at the meeting. We also discussed the possible implementation +of the additional requirements. + +To cut a long story short: we are working on the additional requirements +presented, and it seems feasible that we could be able to implement +them eventually. However, the planned timescale for user tag implementation +in COOL_1_3_0 by March 21 is too tight to complete the specification +and implementation design. I would therefore propose that we only provide +an implementation of the 'old' specification (spec#1 below) in COOL130. +We can then converge on the discussion of an extended specification +and of its implementation, if required. + +Would this be acceptable, or is it useless to have an implementation +of the 'old' user tag requirement specification (spec#1), and you would +rather wait to have one of the two 'extended' specifications (spec#2 and +spec#3) implemented later on? + +Extensive details of the proposed specification spec#1 for COOL130, +and of its possible future extensions spec#2 and spec#3, follow below. + +The main difference is that in spec#1 standard tags and user tags +are different types of tags that cannot be mixed, while in spec#2 +and spec#3 they are the same single type of tags and can be mixed. +The difference between spec#2 and spec#3 is on the issue whether +the system should/can erase all memory of tag manipulations (spec#2) +or should preserve it (spec#3). + +Please let us know... + +Thanks +Andrea + +=============================================== +User tag specification (AV 01.03.2006) +=============================================== + +For reference: the original specification is the one I proposed +in an e-mail message in April last year, which you may find in +the COOL CVS doc repository in http://cool.cvs.cern.ch/cgi-bin/cool.cgi/cool/RelationalCool/doc/userTagsSpec.txt + +Details of the specifications we are discussing: + +Spec#1 (April 2005) +-------------------- +- Users may attach a (standard) tag to the current HEAD (already in COOL128). +- Users may attach a (standard) tag to the HEAD as it was at a given time + in the past (already in COOL128). +- NEW: Users may attach AT MOST ONE (user) tag to any IOV they are inserting. +- User tags (attached on IOV insertion) and standard tags (attached by + tagging the current or past HEAD) are of two different types and they + cannot be mixed. There are methods to check what type of tag is + a given tag name. If a tag already exists as standard/user tag, + then an exception is thrown on any attempt to use it as the + opposite type user/standard. +- A method to 'tag as tagB all IOVs that were tagged as tagA at time t0 in + the past' has not been explicitly requested and will NOT be implemented, + neither for HEAD tags (as in COOL128), nor in the new user tags. + Nevertheless, the proposed implementation for spec#1 could (to be + confirmed) allow this extra functionality to be added without major + schema changes, both for standard tags and user tags. + +More details about the last point (history of retags, i.e. changes of tags): +- Whenever a current/past HEAD is attached a tag, any memory of previously + assigned tags is erased (this is what happens in COOL128). This is very + clear as the 'retag' functionality is only available to users by first + deleting the tag and then reassigning it. In principle, however, it is + always possible to recover a previously assigned HEAD tag, as long + as one knows the time at which the relevant IOVs were the HEAD. +- User tags are different from standard tags and are implemented in + a different way. The insertion of new IOVs with a user tag attached to + them implies a continuous modification of the set of IOVs with the + user tag attached. However, the proposed implementation of user tags + is a clone of that used for the global HEAD tag, on a separate branch: + in principle, it should be possible to recover the set of IOVs that + were in a certain user tag at a specified time in the past, just like + this is possible for the global HEAD. + +Implementation notes: +- Tag to IOV associations are stored in a separate IOV2TAG table. + The contents of this table, however, are largely redundant with + the IOV table and could easily be rebuilt via simple queries + on the IOV table (as in COOL128). + +Spec#2 (February 2006) +----------------------- +- Users may attach a (standard) tag to the current HEAD (already in COOL128). +- Users may attach a (standard) tag to the HEAD as it was at a given time + in the past (already in COOL128). +- NEW: Users may attach AT MOST ONE (user) tag to any IOV they are inserting. +- User tags (attached on IOV insertion) and standard tags (attached by + tagging the current or past HEAD) are not two different types of tags. + Users can tag a current global HEAD or past global HEAD with a given tag, + then insert a new IOV and attach it to the existing tag. They can also tag + a current global HEAD or past global HEAD with a tag after having inserted + an IOV with that same tag attached. +- The system has NO MEMORY whatsoever of tag manipulations. + A method to 'tag as tagB all IOVs that were tagged as tagA at time t0 in + the past' has not been explicitly requested and CANNOT be implemented. + Whenever the contents of a tag are changed, whether through tagged + IOV insertion or through current/past HEAD tag, all previous associations + of IOVs to tags are ERASED. If users make a mistake in tagging... too bad. + In particular, if a user inserts an IOV with MYTAG, but later tags + a new HEAD as MYTAG, that IOV is kept in the system (and is used in the + determination of the global HEAD), but the information that it had been + inserted with tag MYTAG is ERASED. + +Implementation notes: +- The proposed implementation might (to be confirmed) also make it possible + to attach any number of tags on insertion. This is because an IOV may + in any case be attached to any number of tags via the current/past HEAD + tag functionality. The system is thus forced to maintain as many + separate IOV branches as there are tags defined, whether these were + attached as HEAD tags or on IOV insertion. +- Tag to IOV associations are stored in a separate IOV2TAG table. + The contents of this table CANNOT easily be recovered from simple queries + on the IOV table, because the memory of tag manipulations is missing. + The IOV2TAG table provides a lot of extra information with respect + to that contained in the IOV table. Note that the payload is stored + in the IOV table. + +Spec#3 (March 2006) +-------------------- +- Users may attach a (standard) tag to the current HEAD (already in COOL128). +- Users may attach a (standard) tag to the HEAD as it was at a given time + in the past (already in COOL128). +- NEW: Users may attach AT MOST ONE (user) tag to any IOV they are inserting. +- User tags (attached on IOV insertion) and standard tags (attached by + tagging the current or past HEAD) are not two different types of tags. + Users can tag a current global HEAD or past global HEAD with a given tag, + then insert a new IOV and attach it to the existing tag. They can also tag + a current global HEAD or past global HEAD with a tag after having inserted + an IOV with that same tag attached. +- The system maintains the full memory of tag manipulations. + A method to 'tag as tagB all IOVs that were tagged as tagA at time t0 in + the past' can be implemented. Whenever the contents of a tag are changed, + whether through tagged IOV insertion or through current/past HEAD tag, + tag-to-IOV associations are updated and new ones are inserted, + but none are deleted. Methods are provided to allow users to + erase (or simply archive?) obsolete data from the IOV table if required. + +Implementation notes: +- The proposed implementation might (to be confirmed) also make it possible + to attach any number of tags on insertion. This is because an IOV may + in any case be attached to any number of tags via the current/past HEAD + tag functionality. The system is thus forced to maintain as many + separate IOV branches as there are tags defined, whether these were + attached as HEAD tags or on IOV insertion. +- Tag to IOV associations and their history are stored in the IOV table. + A snapshot of this table containing only the currently tagged IOVs + is stored in the IOV2TAG table for performance reasons. +- The number of rows in the IOV table is roughly proportional to the + number of tags applied, because the full history of tag manipulations + is retained. The need to move the payload to a separate table + becomes much more pressing. + +=============================================== +User tag example specification (AV 01.03.2006) +=============================================== + +Main points of spec#1: +- An IOV can be inserted with AT MOST ONE associated user tag. + This means that a consistent HEAD version must be kept (within the folder + and the channel) not only for ALL IOVS, but also for EACH subset of IOVS + associated to any given user tag. +- Two types of tags exist: 'user tags' (those specified when inserting a + new IOV) are different from 'standard tags' (those specified when tagging + the HEAD of existing IOVs) and can NOT be mixed. + +[NB Each tag is independent of each other: it is NOT foreseen that one can +ask for "the HEAD for tag A AND tag B, or the HEAD for tag A OR tag B".] + +Example 1 +---------- +1. User inserts P1 payload in [ 0, 100] with NO (user) tags +2. User inserts P2 payload in [ 10, 50] with (user) tag #1 +3. User inserts P3 payload in [ 30, 80] with (user) tag #2 +4. User inserts P4 payload in [ 20, 40] with (user) tag #1 +5. User inserts P5 payload in [ 30, 70] with (user) tag #2 + +Note that this example is the same for all of spec#1, spec#2 and spec#3. +The only difference is in terminology: in spec#1 +these tags are 'user' tags (different type from 'standard' tags), +while in spec#2 and spec#3 they are just 'tags'. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P2 in [ 10, 20] + P4 in [ 20, 30] + P5 in [ 30, 70] + P3 in [ 70, 80] + P1 in [ 80, 100] + +(User) tag #1: + P2 in [ 10, 20] + P4 in [ 20, 40] + P2 in [ 40, 50] + +(User) tag #2: + P5 in [ 30, 70] + P3 in [ 70, 80] + +Example 2 (spec #1) +-------------------- +1. User inserts P1 payload in [ 0, 50] with NO user tags +2. User inserts P2 payload in [ 50, 100] with NO user tags +3. User tags HEAD of folder with tag #2 +4. User inserts P4 payload in [ 10, 50] with user tag #1 +5. User inserts P5 payload in [ 30, 80] with user tag #2 - EXCEPTION +6. User inserts P6 payload in [ 20, 40] with user tag #1 +7. User inserts P7 payload in [ 30, 70] with user tag #2 - EXCEPTION + +In spec#1, step 5 and 7 here throw an exception: tag #2 is already reserved +as a 'standard' tag and cannot be used as a 'user' tag. + +HEAD versions after last insertion (ignoring step 5 and 7): + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P4 in [ 10, 20] + P6 in [ 20, 30] + P7 in [ 30, 70] + P5 in [ 70, 80] + P2 in [ 80, 100] + +Tag #1: + P4 in [ 10, 20] + P6 in [ 20, 40] + P4 in [ 40, 50] + +User tag #2: + P1 in [ 0, 50] + P2 in [ 50, 100] + +Example 2 (spec#2 and spec#3) +------------------------------ +1. User inserts P1 payload in [ 0, 50] with NO user tags +2. User inserts P2 payload in [ 50, 100] with NO user tags +3. User tags HEAD of folder with tag #2 +4. User inserts P4 payload in [ 10, 50] with user tag #1 +5. User inserts P5 payload in [ 30, 80] with user tag #2 +6. User inserts P6 payload in [ 20, 40] with user tag #1 +7. User inserts P7 payload in [ 30, 70] with user tag #2 + +In specifications spec#2 and spec#3, no exceptions are thrown. + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P4 in [ 10, 20] + P6 in [ 20, 30] + P7 in [ 30, 70] + P5 in [ 70, 80] + P2 in [ 80, 100] + +Tag #1: + P4 in [ 10, 20] + P6 in [ 20, 40] + P4 in [ 40, 50] + +Tag #2: + P1 in [ 0, 30] + P7 in [ 30, 70] + P5 in [ 70, 80] + P2 in [ 80, 100] + +Example 3 (spec#2 and spec#3) +------------------------------ + 1. User inserts P1 payload in [ 0, 50] with NO user tags + 2. User inserts P2 payload in [ 50, 100] with NO user tags + 3. User tags HEAD of folder with tag #2 + 4. User inserts P4 payload in [ 10, 50] with user tag #1 + 5. User inserts P5 payload in [ 30, 80] with user tag #2 + 6. User inserts P6 payload in [ 20, 40] with user tag #1 + 7. User inserts P7 payload in [ 30, 70] with user tag #2 + 8. User tags HEAD of folder with tag #2 + 9. User inserts P9 payload in [ 30, 80] with user tag #2 +10. User inserts P10 payload in [ 20, 40] with user tag #1 + +In specification spec#1, step 5 throws an exception. +This example mainly shows the differemce between spec#2 and spec#3. + +In spec#2 and spec#3, no exceptions are thrown. +In both specifications the tags after the last insertions are the same: + +HEAD versions after last insertion: + +All IOVS (irrespective of tags): + P1 in [ 0, 10] + P4 in [ 10, 20] + P10 in [ 20, 40] + P9 in [ 40, 80] + P2 in [ 80, 100] + +Tag #1: + P4 in [ 10, 20] + P10 in [ 20, 40] + P4 in [ 40, 50] + +Tag #2: + P1 in [ 0, 10] + P4 in [ 10, 20] + P6 in [ 20, 30] + P9 in [ 30, 80] + P2 in [ 80, 100] + +In spec#2, tagging the HEAD (in step 8) with the same tag name +previously used for inserting IOVs with attached tags (e.g. step 5) +logically erases all tag-to-IOV relations defined when inserting +IOVs with attached tags (e.g. the tag attached in step 5 loses meaning). +That is to say, the memory that P5 and P7 were inserted with tag#2 is lost. +The memory that a HEAD tag was applied at the time of step 3 is also lost. + +In spec#3, the full memory of tag manipulations is retained. + +------------------------------------------------------------------------------- + +For reference: David Malon presented his use case in the presentation +at the 2003 CondDB Workshop: http://agenda.cern.ch/fullAgenda.php?ida=a036470 + diff --git a/RelationalCool/python/CoolAuthentication/__init__.py b/RelationalCool/python/CoolAuthentication/__init__.py new file mode 100644 index 000000000..7bfa861ac --- /dev/null +++ b/RelationalCool/python/CoolAuthentication/__init__.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +import os, sys + +def setNewValueFromTag( oldValue, line, tag ): + if line.startswith( tag ) : + return line[len(tag):len(line)-1].strip(' ').strip('=').strip(' ') + else : + return oldValue + +def getDbIdProperties( dbId, rwOnly=False, debug=False ) : + if rwOnly: + cmd = 'coolAuthentication -1RW "' + dbId + '"' + else: + cmd = 'coolAuthentication -1 "' + dbId + '"' + f = os.popen(cmd) + theCorA = "" + theCorR = "" + theCorM = "" + theTech = "" + theSrvr = "" + theSchm = "" + theUser = "" + thePswd = "" + theDbNm = "" + line = f.readline() + while line : + ###print line + theCorA = setNewValueFromTag( theCorA, line, "==> coralAlias" ) + theCorR = setNewValueFromTag( theCorR, line, "==> coralReplica" ) + theCorM = setNewValueFromTag( theCorM, line, "==> coralMode" ) + theTech = setNewValueFromTag( theTech, line, "==> technology" ) + theSrvr = setNewValueFromTag( theSrvr, line, "==> server" ) + theSchm = setNewValueFromTag( theSchm, line, "==> schema" ) + theUser = setNewValueFromTag( theUser, line, "==> user" ) + thePswd = setNewValueFromTag( thePswd, line, "==> password" ) + theDbNm = setNewValueFromTag( theDbNm, line, "==> dbname" ) #COOL13x + theDbNm = setNewValueFromTag( theDbNm, line, "==> dbName" ) #COOL20x + line = f.readline() + status = f.close() + if status : + # Fix bug #24248: do not fail for sqlite/frontier if there are no + # username/password in authentication.xml (they are dummy anyway!). + # NB: this bug has been fixed in coolAuthentication in COOL200, but + # the schema evolution test uses coolAuthentication from COOL133c. + if theTech == "sqlite" : + ###print "WARNING! Command '" + cmd + "' failed! Status:", status + if theUser == "" : theUser = "DUMMY" + if thePswd == "" : thePswd = "DUMMY" + elif theTech == "frontier" : + ###print "WARNING! Command '" + cmd + "' failed! Status:", status + if theUser == "" : + if theSchm != "" : theUser = theSchm + else : theUser = "DUMMY" + if thePswd == "" : thePswd = "DUMMY" + else : + print "ERROR! Command '" + cmd + "' failed! Status:", status + sys.exit(status) + if debug : + print "CoralAlias: '" + theCorA + "'" + print "CoralReplica: '" + theCorR + "'" + print "CoralMode: '" + theCorM + "'" + print "Technology: '" + theTech + "'" + print "Server: '" + theSrvr + "'" + print "Schema: '" + theSchm + "'" + print "User: '" + theUser + "'" + print "Password: '" + thePswd + "'" + print "DbName: '" + theDbNm + "'" + return [ theTech, theSrvr, theSchm, theUser, thePswd, theDbNm, theCorA, theCorR, theCorM ] + +def technology( dbIdProperties ) : return dbIdProperties[0] + +def server( dbIdProperties ) : return dbIdProperties[1] + +def schema( dbIdProperties ) : return dbIdProperties[2] + +def user( dbIdProperties ) : return dbIdProperties[3] + +def password( dbIdProperties ) : return dbIdProperties[4] + +def dbName( dbIdProperties ) : return dbIdProperties[5] + +def coralAlias( dbIdProperties ) : return dbIdProperties[6] + +def coralReplica( dbIdProperties ) : return dbIdProperties[7] + +def coralMode( dbIdProperties ) : return dbIdProperties[8] + diff --git a/RelationalCool/python/CoolDescribeTable/__init__.py b/RelationalCool/python/CoolDescribeTable/__init__.py new file mode 100644 index 000000000..b1d8f7016 --- /dev/null +++ b/RelationalCool/python/CoolDescribeTable/__init__.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python +# See http://docs.python.org/lib/string-methods.html +import os, sys +import CoolAuthentication + +def myLPartition( text, sep ): + index = text.find(sep) + if index==-1 : return text + else : return text[(index+1):].strip(' ') + +def myRPartition( text, sep ): + index = text.rfind(sep) + if index==-1 : return text + else : return text[:index].strip(' ') + +def mySplit( text ): + nl = text.count('(') + nr = text.count(')') + if nl!=nr : + print "ERROR! Count mismatch for '(' and ')'", nl, nr + sys.exit(-1) + flds = [] + newFld = "" + for fld in text.split(','): + if ( newFld != "" ) : newFld = newFld+"," + newFld = newFld+fld + if newFld.count('(') == newFld.count(')') : + flds.append(newFld) + newFld = "" + return flds + +# See http://dev.mysql.com/doc/refman/4.1/en/create-table.html +def parseCreateTable( txt, debug=False ): + if debug : print "1 - Parse:", txt + # Remove newline characters + txt = txt.replace('\n','') + # Remove actual newline characters + txt = txt.replace('\\n','') + # Parse only the text until the first ";" + while txt != myRPartition(txt,';') : txt = myRPartition(txt,';') + # Assume that the current text is a CREATE TABLE statement + # Parse only the column definition list "( ... , ... )" + txt = myLPartition(txt,'(') + txt = myRPartition(txt,')') + if debug : print "2 - Parse:", txt + # Split the comma-separated fields of "( ... , ... )" + # Do not split a field that contains a comma enclosed by parentheses + columns = [] + for fld in mySplit(txt): + fld = fld.strip(' ').rstrip(' ').split(' ') + if debug : print "3 - Parse:", fld + # Check that there is at least one word in this field + if len(fld)<=1 : break + # Word #0 is a column name if it does not define a constraint + if fld[0] == "CONSTRAINT" : break + if fld[0] == "KEY" : break + if fld[0] == "INDEX" : break + if fld[0] == "PRIMARY" : break + if fld[0] == "FOREIGN" : break + if fld[0] == "UNIQUE" : break + if fld[0] == "FULLTEXT" : break + if fld[0] == "SPATIAL" : break + if fld[0] == "CHECK" : break + name = fld[0] + # Strip off '`' (mysql) + name = name.strip('`').rstrip('`') + # Strip off '"' (sqlite) + name = name.strip('"').rstrip('"') + # Word #1 defines the type + type = fld[1].upper() + # Word #2 may be an UNSIGNED qualifier + if len(fld)>2 \ + and fld[2].upper() == "UNSIGNED" : + type=type+" UNSIGNED" + # Else word #2 may be a BINARY qualifier + elif len(fld)>2 \ + and fld[2].upper() == "BINARY" : + type=type+" BINARY" + # Else words #2-3 may define BINARY as "COLLATE xxx_bin" + elif len(fld)>3 \ + and fld[2].upper() == "COLLATE" \ + and fld[3].upper().endswith('_BIN') : + type=type+" BINARY" + # Else words #5-6 may define BINARY as "COLLATE xxx_bin" + elif len(fld)>6 \ + and fld[2].upper() == "CHARACTER" \ + and fld[3].upper() == "SET" \ + and fld[5].upper() == "COLLATE" \ + and fld[6].upper().endswith('_BIN') : + type=type+" BINARY" + column = [ name, type ] + columns.append(column) + return columns + +def oracleDescribeTable( dbIdProp, table, debug=False ) : + if debug : print "0 - Describe table: " + table + server = CoolAuthentication.server( dbIdProp ) + schema = CoolAuthentication.schema( dbIdProp ).upper() + user = CoolAuthentication.user( dbIdProp ) + password = CoolAuthentication.password( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + sqlDir = __path__[0] + os.sep + 'sql' + sqlFile = sqlDir + os.sep + "oracleShowCreateTable.sql" + if not os.path.exists( sqlFile ) : + print "ERROR! SQL file not found:", sqlFile + sys.exit(-1) + sql = "@" + sqlFile + " " + schema + " " + table + cmd = "sqlplus -S -L " + user + "/" + password + "@" + server + " " + sql + cmd_no_passwd = "sqlplus -S -L " + user + "/" + "***" + "@" + server + " " + sql + columns = [] + ###return columns + f = os.popen(cmd) + line = f.readline() + while line : + if debug : print "1 - Parse: " + line + line = line.replace('\n','') + line = line.replace('\t','') + line = line.strip(' ').rstrip(' ').split() + # There should be exactly two words in this field + if len(line)==1 and line[0]!='': + print "PANIC! Unexpected number of words:", line + sys.exit(-1) + elif len(line)==2 : + name = line[0] + type = line[1].upper() + column = [ name, type ] + columns.append(column) + elif len(line)>2 : + print "PANIC! Unexpected number of words:", line + sys.exit(-1) + line = f.readline() + status = f.close() + if status : + print "ERROR! Command '" + cmd_no_passwd + "' failed! Status code:", status + sys.exit(status) + return columns + +def mysqlDescribeTable( dbIdProp, table, debug=False ) : + if debug : print "0 - Describe table: " + table + server = CoolAuthentication.server( dbIdProp ) + schema = CoolAuthentication.schema( dbIdProp ) + user = CoolAuthentication.user( dbIdProp ) + password = CoolAuthentication.password( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + # A special treatment is needed for the host:port syntax: + # the port number must be parsed out and passed explicitly + index = server.find(':') + if index!=-1 : + host = server[:index] + port = server[index+1:] + server = " -h" + host + " -P" + port + else: + server = " -h" + server + ###sql = "describe " + schema + "." + table + ###sql = "show columns from " + schema + "." + table + sql = "show create table " + schema + "." + table + # This does not work on Windows... (bug #23438) + if os.environ["OS"] != "Windows_NT" : + cmd = "mysql -u"+user + " -p"+password + server + " -B -N -e '"+sql + "'" + cmd_no_passwd = "mysql -u"+user + " -p"+"***" + server + " -B -N -e '"+sql + "'" + # This works on Windows... but it might also work elsewhere + else : + cmd = 'mysql -u'+user + ' -p'+password + server + ' -B -N -e "'+sql + '"' + cmd_no_passwd = 'mysql -u'+user + ' -p'+'***' + server + ' -B -N -e "'+sql + '"' + f = os.popen(cmd) + text = "" + line = f.readline() + while line : + text = text + line + " " + line = f.readline() + status = f.close() + if status : + print "ERROR! Command '" + cmd_no_passwd + "' failed! Status code:", status + sys.exit(status) + return parseCreateTable( text, debug ) + +def sqliteDescribeTable( dbIdProp, table, debug=False ) : + if debug : print "0 - Describe table: " + table + schema = CoolAuthentication.schema( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + if not os.path.exists( schema ) : + print "ERROR! SQLite database file not found:", schema + sys.exit(-1) + sql = ".schema " + table + # This does not work on Windows... (bug #23438) + if os.environ["OS"] != "Windows_NT" : + cmd = "sqlite3 " + schema + " '" + sql + "'" + # This works on Windows... but it might also work elsewhere + else : + cmd = 'sqlite3 ' + schema + ' "' + sql + '"' + f = os.popen(cmd) + text = "" + line = f.readline() + while line : + text = text + line + " " + line = f.readline() + status = f.close() + if status : + print "ERROR! Command '" + cmd + "' failed! Status code:", status + sys.exit(status) + return parseCreateTable( text, debug ) + +def describeTable( dbId, table, debug=False ) : + if debug : print "COOL dbId: '" + dbId + "'" + dbIdProp = CoolAuthentication.getDbIdProperties( dbId, debug ) + tech = CoolAuthentication.technology( dbIdProp ) + if debug : print "Technology: '" + tech + "'" + if debug : print "Describe table: '" + table + "'" + if tech == "oracle" : + columns = oracleDescribeTable( dbIdProp, table, debug ) + elif tech == "mysql" : + columns = mysqlDescribeTable( dbIdProp, table, debug ) + elif tech == "sqlite" : + columns = sqliteDescribeTable( dbIdProp, table, debug ) + else : + print "ERROR! Technology '" + tech + "' is not supported" + sys.exit(-1) + return columns diff --git a/RelationalCool/python/CoolDescribeTable/sql/oracleShowCreateTable.sql b/RelationalCool/python/CoolDescribeTable/sql/oracleShowCreateTable.sql new file mode 100644 index 000000000..9870530a4 --- /dev/null +++ b/RelationalCool/python/CoolDescribeTable/sql/oracleShowCreateTable.sql @@ -0,0 +1,26 @@ +-- NB An interesting alternative could be +-- select dbms_metadata.get_ddl('TABLE','&2','&1') from dual; +-- But this gives ORA-00904 for lcg_cool@cooldev (while it works for +-- avalassi@cooldev or lcg_cool@devdb10: missing privs? old s/w version?) + +-- SELECT shows column values without column names +set heading off; +-- Suppress the display of each line before and after substitution +set verify off; +-- Suppress the display of the number of rows selected +set feedback off; +-- Make sure each table row fits in a single output line +set linesize 10000; +-- Make sure all table rows fit in a single page +set pagesize 1000; +-- Issue the SELECT statement +select name, replace(replace(type,',)',')'),'()') type from ( +select column_name as name, +data_type||'('|| +decode(data_precision, null, null, 0, null, data_precision||',')|| +decode(data_scale, null, null, 0, null, data_scale||',')|| +decode(char_length, null, null, 0, null, char_length)||')' as type +from all_tab_columns where owner='&1' and table_name='&2') +order by name; +-- Exit +exit; diff --git a/RelationalCool/python/CoolGatherSchemaStats/__init__.py b/RelationalCool/python/CoolGatherSchemaStats/__init__.py new file mode 100644 index 000000000..104fe940d --- /dev/null +++ b/RelationalCool/python/CoolGatherSchemaStats/__init__.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +import os, sys +import CoolAuthentication + +def oracleGatherSchemaStats( dbIdProp, debug=False ) : + server = CoolAuthentication.server( dbIdProp ) + schema = CoolAuthentication.schema( dbIdProp ).upper() + user = CoolAuthentication.user( dbIdProp ) + password = CoolAuthentication.password( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + sqlDir = __path__[0] + os.sep + 'sql' + sqlFile = sqlDir + os.sep + "oracleGatherSchemaStats.sql" + if not os.path.exists( sqlFile ) : + print "ERROR! SQL file not found:", sqlFile + sys.exit(-1) + sql = "@" + sqlFile + " " + schema + cmd = "sqlplus -S -L " + user + "/" + password + "@" + server + " " + sql + f = os.system(cmd) + return + +def gatherSchemaStats( dbId, debug=False ) : + print "Gather statistics for schema hosting database '"+dbId+"'" + dbIdProp = CoolAuthentication.getDbIdProperties( dbId, debug ) + tech = CoolAuthentication.technology( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + if debug : print "Technology: '" + tech + "'" + if tech == "oracle" : + columns = oracleGatherSchemaStats( dbIdProp, debug ) + elif tech == "mysql" : + print "WARNING! Statistics tools not implemented for technology "+tech + elif tech == "sqlite" : + print "WARNING! Statistics tools not implemented for technology "+tech + else : + print "ERROR! Technology '" + tech + "' is not supported" + sys.exit(-1) + return diff --git a/RelationalCool/python/CoolGatherSchemaStats/sql/oracleGatherSchemaStats.sql b/RelationalCool/python/CoolGatherSchemaStats/sql/oracleGatherSchemaStats.sql new file mode 100644 index 000000000..b32f6f2df --- /dev/null +++ b/RelationalCool/python/CoolGatherSchemaStats/sql/oracleGatherSchemaStats.sql @@ -0,0 +1,2 @@ +execute DBMS_STATS.GATHER_SCHEMA_STATS( '&1', no_invalidate=>FALSE ); +exit; diff --git a/RelationalCool/python/CoolGatherTableStats/__init__.py b/RelationalCool/python/CoolGatherTableStats/__init__.py new file mode 100644 index 000000000..6881c49a7 --- /dev/null +++ b/RelationalCool/python/CoolGatherTableStats/__init__.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +import os, sys +import CoolAuthentication +from CoolShowTables import showTables + +def oracleGatherTableStats( dbIdProp, tableName, debug=False ) : + server = CoolAuthentication.server( dbIdProp ) + schema = CoolAuthentication.schema( dbIdProp ).upper() + user = CoolAuthentication.user( dbIdProp ) + password = CoolAuthentication.password( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + sqlDir = __path__[0] + os.sep + 'sql' + sqlFile = sqlDir + os.sep + "oracleGatherTableStats.sql" + if not os.path.exists( sqlFile ) : + print "ERROR! SQL file not found:", sqlFile + sys.exit(-1) + sql = "@" + sqlFile + " " + schema + " " + tableName + cmd = "sqlplus -S -L " + user + "/" + password + "@" + server + " " + sql + f = os.system(cmd) + return + +def gatherSingleTableStats( dbIdProp, tableName, debug=False ) : + if tableName=="": + print "ERROR! Table name not specified" + sys.exit(-1) + print "Gather statistics for table '"+tableName+"'" + tech = CoolAuthentication.technology( dbIdProp ) + if tech == "oracle" : + columns = oracleGatherTableStats( dbIdProp, tableName, debug ) + else : + print "ERROR! Technology '" + tech + "' is not supported" + sys.exit(-1) + return + +def gatherTableStats( dbId, tableName, debug=False ) : + dbIdProp = CoolAuthentication.getDbIdProperties( dbId, debug ) + tech = CoolAuthentication.technology( dbIdProp ) + if debug : print "Technology: '" + tech + "'" + if tech == "oracle" : + if tableName=="": + print "Gather statistics for ALL tables in database '" + dbId + "'" + for table in showTables( dbId, debug ): + gatherSingleTableStats( dbIdProp, table, debug ) + else: + print "Gather statistics for table '" + tableName + \ + "' in database '" + dbId + "'" + gatherSingleTableStats( dbIdProp, tableName, debug ) + elif tech == "mysql" : + print "WARNING! Statistics tools not implemented for technology "+tech + elif tech == "sqlite" : + print "WARNING! Statistics tools not implemented for technology "+tech + else : + print "ERROR! Technology '" + tech + "' is not supported" + sys.exit(-1) + diff --git a/RelationalCool/python/CoolGatherTableStats/sql/oracleGatherTableStats.sql b/RelationalCool/python/CoolGatherTableStats/sql/oracleGatherTableStats.sql new file mode 100644 index 000000000..03cbf1d2d --- /dev/null +++ b/RelationalCool/python/CoolGatherTableStats/sql/oracleGatherTableStats.sql @@ -0,0 +1,2 @@ +execute DBMS_STATS.GATHER_TABLE_STATS( '&1', '&2', no_invalidate=>FALSE ); +exit; diff --git a/RelationalCool/python/CoolQueryManager/__init__.py b/RelationalCool/python/CoolQueryManager/__init__.py new file mode 100644 index 000000000..81e13044d --- /dev/null +++ b/RelationalCool/python/CoolQueryManager/__init__.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# See http://docs.python.org/lib/string-methods.html +import os, sys +import CoolAuthentication + +def myLPartition( text, sep ): + index = text.find(sep) + if index==-1 : return text + else : return text[(index+1):].strip(' ') + +def myRPartition( text, sep ): + index = text.rfind(sep) + if index==-1 : return text + else : return text[:index].strip(' ') + +def parseSelect( text, uppercase, debug=False ): + ###if debug : print "0bis - Parse:", text + # Remove newline characters + text = text.replace('\n','') + # Remove actual newline characters + text = text.replace('\\n','') + # Remove tab characters + text = text.replace('\t','') + if debug : print "1 - Parse:", text + if uppercase : + ltr = '<TR>' + rtr = '</TR>' + ltd = '<TD>' + rtd = '</TD>' + else : + ltr = '<tr>' + rtr = '</tr>' + ltd = '<td>' + rtd = '</td>' + ###if debug : print "2a - Parse:", text + text=text.replace(ltr+ltr,ltr) # MySQL has a <TR><TR> for the first row... + text=text.replace(' align="right"','') # Oracle may use <td align="right"> + ###if debug : print "2b - Parse:", text + nl = text.count( ltr ) + nr = text.count( rtr ) + if nl!=nr : + print "ERROR! Count mismatch for '"+ltr+"' and '"+rtr + "' (",\ + nl, nr, ") in '"+text+"'" + sys.exit(-1) + nl = text.count( ltd ) + nr = text.count( rtd ) + if nl!=nr : + print "ERROR! Count mismatch for '"+ltd+"' and '"+rtd + "' (",\ + nl, nr, ") in '"+text+"'" + sys.exit(-1) + rows = [] + for row in text.split( ltr ): + newRow = myRPartition( row, rtr ) + if debug : print "3 - Parse:", newRow + nl = newRow.count( ltd ) + nr = newRow.count( rtd ) + if nl!=nr : + print "ERROR! Count mismatch for '"+ltd+"' and '"+rtd + "' (",\ + nl, nr, ") in '"+newRow+"'" + sys.exit(-1) + elif nl!=0 : + flds = [] + ifld = 0 + for fld in newRow.split( ltd ): + ifld=ifld+1 + if ifld > 1 : + newFld = myRPartition( fld, rtd ) + if debug : print "4 - Parse:", newFld + flds.append( newFld ) + rows.append( flds ) + if debug : print "5 - End parsing" + return rows + +def oracleSelect( dbIdProp, sql, debug=False ) : + if debug : print "0 - Executing SQL: '" + sql + "'" + #if os.environ["OS"] == "Windows_NT" : + # print "ERROR! CoolQueryManager is not supported for technology 'oracle' on OS '" + os.environ["OS"] + "' (on OSTYPE '" + os.environ["OSTYPE"] + "')" + # sys.exit(-1) + server = CoolAuthentication.server( dbIdProp ) + schema = CoolAuthentication.schema( dbIdProp ).upper() + user = CoolAuthentication.user( dbIdProp ) + password = CoolAuthentication.password( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + if os.environ["OS"] != "Windows_NT" : + cmd = 'echo "' + sql + '" | sqlplus -S -L -M "HTML ON" ' + user + '/' + password + '@' + server + cmd_no_passwd = 'echo "' + sql + '" | sqlplus -S -L -M "HTML ON" ' + user + '/***' + '@' + server + ###columns = [] + ###os.system(cmd) + ###return columns + fout = os.popen(cmd) + else : + cmd = 'sqlplus -S -L -M "HTML ON" ' + user + '/' + password + '@' + server + cmd_no_passwd = 'sqlplus -S -L -M "HTML ON" ' + user + '/***' + '@' + server + if debug : print "0 - Open pipe for command: '" + cmd_no_passwd + "'" + index = sql.find('\*') + if index!=-1 : + if debug : print "0 - Replace '\*' by '*' in SQL" + if debug : print "0 - Input to pipe is SQL statement: '" + sql.replace('\*','*') + "'" + # See for instance http://effbot.org/librarybook/popen2.htm + pipe = os.popen2(cmd) + fin=pipe[0] + fout=pipe[1] + fin.write(sql.replace('\*','*')+'\n') + fin.flush() + fin.close() + text = "" + line = fout.readline() + while line : + text = text + line + " " + line = fout.readline() + status = fout.close() + if status : + print "ERROR! Command '" + cmd_no_passwd + "' failed! Status code:", status + sys.exit(status) + uppercase = False + return parseSelect( text, uppercase, debug ) + +def mysqlSelect( dbIdProp, sql, debug=False ) : + if debug : print "0 - Executing SQL: '" + sql + "'" + server = CoolAuthentication.server( dbIdProp ) + schema = CoolAuthentication.schema( dbIdProp ) + user = CoolAuthentication.user( dbIdProp ) + password = CoolAuthentication.password( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + # A special treatment is needed for the host:port syntax: + # the port number must be parsed out and passed explicitly + index = server.find(':') + if index!=-1 : + host = server[:index] + port = server[index+1:] + server = " -h" + host + " -P" + port + else: + server = " -h" + server + cmd = 'mysql --html -u'+user + ' -p'+password + server + ' ' + schema + ' -B -N -e "'+sql + '"' + ###print cmd + cmd_no_passwd = 'mysql --html -u'+user + ' -p***' + server + ' ' + schema + ' -B -N -e "'+sql + '"' + f = os.popen(cmd) + text = "" + line = f.readline() + while line : + text = text + line + " " + line = f.readline() + status = f.close() + if status : + print "ERROR! Command '" + cmd_no_passwd + "' failed! Status code:", status + sys.exit(status) + uppercase = True + return parseSelect( text, uppercase, debug ) + +def sqliteSelect( dbIdProp, sql, debug=False ) : + if debug : print "0 - Executing SQL: '" + sql + "'" + schema = CoolAuthentication.schema( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + if not os.path.exists( schema ) : + print "ERROR! SQLite database file not found:", schema + sys.exit(-1) + cmd = 'sqlite3 -html ' + schema + ' "' + sql + '"' + f = os.popen(cmd) + text = "" + line = f.readline() + while line : + text = text + line + " " + line = f.readline() + status = f.close() + if status : + print "ERROR! Command '" + cmd + "' failed! Status code:", status + sys.exit(status) + uppercase = True + return parseSelect( text, uppercase, debug ) + +def executeSqlSelect( dbId, sql, debug=False ) : + if debug : print "Executing SQL statement: '" + sql + "'" + index = sql.find('select') + if index!=0 : + index = sql.find('SELECT') + if index!=0 : + print "ERROR! Only 'SELECT' SQL statements are supported" + sys.exit(-1) + if debug : print "COOL dbId: '" + dbId + "'" + dbIdProp = CoolAuthentication.getDbIdProperties( dbId, debug ) + tech = CoolAuthentication.technology( dbIdProp ) + if debug : print "Technology: '" + tech + "'" + if tech == "oracle" : + columns = oracleSelect( dbIdProp, sql, debug ) + elif tech == "mysql" : + columns = mysqlSelect( dbIdProp, sql, debug ) + elif tech == "sqlite" : + columns = sqliteSelect( dbIdProp, sql, debug ) + else : + print "ERROR! CoolQueryManager is not supported for technology '" + tech + "'" + sys.exit(-1) + return columns diff --git a/RelationalCool/python/CoolShowTables/__init__.py b/RelationalCool/python/CoolShowTables/__init__.py new file mode 100644 index 000000000..e31bd3264 --- /dev/null +++ b/RelationalCool/python/CoolShowTables/__init__.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# See http://docs.python.org/lib/string-methods.html +import os, sys +import CoolAuthentication + +def oracleShowTables( dbIdProp, debug=False ) : + server = CoolAuthentication.server( dbIdProp ) + schema = CoolAuthentication.schema( dbIdProp ).upper() + user = CoolAuthentication.user( dbIdProp ) + password = CoolAuthentication.password( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + if debug : print "0 - Show tables in database name: " + dbName + sqlDir = __path__[0] + os.sep + 'sql' + sqlFile = sqlDir + os.sep + "oracleShowTables.sql" + if not os.path.exists( sqlFile ) : + print "ERROR! SQL file not found:", sqlFile + sys.exit(-1) + sql = "@" + sqlFile + " " + schema + " " + dbName + cmd = "sqlplus -S -L " + user + "/" + password + "@" + server + " " + sql + tables = [] + ###f = os.system(cmd) + ###return tables + f = os.popen(cmd) + line = f.readline() + while line : + if debug : print "1 - Parse: " + line + line = line.replace('\n','') + line = line.replace('\t','') + line = line.strip(' ').rstrip(' ').split() + # There should be only one field (ignore lines with 0 fields) + if len(line)==1 : + table = line[0] + tables.append(table) + elif len(line)>1 : + print "PANIC! Unexpected number of words:", line + sys.exit(-1) + line = f.readline() + status = f.close() + if status : + print "ERROR! Command '" + cmd + "' failed! Status code:", status + sys.exit(status) + return tables + +def mysqlShowTables( dbIdProp, debug=False ) : + server = CoolAuthentication.server( dbIdProp ) + schema = CoolAuthentication.schema( dbIdProp ) + user = CoolAuthentication.user( dbIdProp ) + password = CoolAuthentication.password( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + if debug : print "0 - Show tables in database name: " + dbName + # A special treatment is needed for the host:port syntax: + # the port number must be parsed out and passed explicitly + index = server.find(':') + if index!=-1 : + host = server[:index] + port = server[index+1:] + server = " -h" + host + " -P" + port + else: + server = " -h" + server + sql = "show tables like \'" + dbName + "%\'" + cmd = "mysql -u"+user + " -p"+password + server + " " + schema \ + + " -B -N -e \"" + sql + "\"" + tables = [] + ###f = os.system(cmd) + ###return tables + f = os.popen(cmd) + line = f.readline() + while line : + if debug : print "1 - Parse: " + line + line = line.replace('\n','') + line = line.replace('\t','') + line = line.strip(' ').rstrip(' ').split() + for table in line : + tables.append(table) + line = f.readline() + status = f.close() + if status : + print "ERROR! Command '" + cmd + "' failed! Status code:", status + sys.exit(status) + tables.sort() + return tables + +def sqliteShowTables( dbIdProp, debug=False ) : + schema = CoolAuthentication.schema( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + if debug : print "0 - Show tables in database name: " + dbName + if not os.path.exists( schema ) : + print "ERROR! SQLite database file not found:", schema + sys.exit(-1) + sql = ".tables " + dbName + cmd = "sqlite3 " + schema + " '" + sql + "'" + tables = [] + ###f = os.system(cmd) + ###return tables + f = os.popen(cmd) + line = f.readline() + while line : + if debug : print "1 - Parse: " + line + line = line.replace('\n','') + line = line.replace('\t','') + line = line.strip(' ').rstrip(' ').split() + for table in line : + tables.append(table) + line = f.readline() + status = f.close() + if status : + print "ERROR! Command '" + cmd + "' failed! Status code:", status + sys.exit(status) + tables.sort() + return tables + +def showTables( dbId, debug=False ) : + if debug : print "COOL dbId: '" + dbId + "'" + dbIdProp = CoolAuthentication.getDbIdProperties( dbId, debug ) + tech = CoolAuthentication.technology( dbIdProp ) + dbName = CoolAuthentication.dbName( dbIdProp ) + if debug : print "Technology: '" + tech + "'" + if debug : print "Show tables for database name: '" + dbName + "'" + if tech == "oracle" : + columns = oracleShowTables( dbIdProp, debug ) + elif tech == "mysql" : + columns = mysqlShowTables( dbIdProp, debug ) + elif tech == "sqlite" : + columns = sqliteShowTables( dbIdProp, debug ) + else : + print "ERROR! Technology '" + tech + "' is not supported" + sys.exit(-1) + return columns diff --git a/RelationalCool/python/CoolShowTables/sql/oracleShowTables.sql b/RelationalCool/python/CoolShowTables/sql/oracleShowTables.sql new file mode 100644 index 000000000..eee6461b5 --- /dev/null +++ b/RelationalCool/python/CoolShowTables/sql/oracleShowTables.sql @@ -0,0 +1,14 @@ +-- SELECT shows column values without column names +set heading off; +-- Suppress the display of each line before and after substitution +set verify off; +-- Suppress the display of the number of rows selected +set feedback off; +-- Make sure each table row fits in a single output line +set linesize 10000; +-- Make sure all table rows fit in a single page +set pagesize 1000; +-- Issue the SELECT statement +select table_name from all_tables where owner='&1' and table_name like '&2%'; +-- Exit +exit; diff --git a/RelationalCool/scripts/coolAuthentication.py b/RelationalCool/scripts/coolAuthentication.py new file mode 100755 index 000000000..019e47db1 --- /dev/null +++ b/RelationalCool/scripts/coolAuthentication.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +import os, sys +from CoolAuthentication import * + +def usage() : + print "Usage: " + os.path.split(sys.argv[0])[1] + " [-RW] dbId" + print "[Option -RW: display only the first R/W replica]" + sys.exit(-1) + +############################################################################## + +if __name__ == '__main__': + if len(sys.argv) == 2 : + rwOnly = False + dbId = sys.argv[1] + elif len(sys.argv) == 3 and sys.argv[1] == "-RW" : + rwOnly = True + dbId = sys.argv[2] + else: + usage() + print "COOL dbId:", dbId + dbIdProp = getDbIdProperties( dbId, rwOnly ) + print "CoralAlias: '" + coralAlias( dbIdProp ) + "'" + print "CoralReplica: '" + coralReplica( dbIdProp ) + "'" + print "CoralMode: '" + coralMode( dbIdProp ) + "'" + print "Technology: '" + technology( dbIdProp ) + "'" + print "Server: '" + server( dbIdProp ) + "'" + print "Schema: '" + schema( dbIdProp ) + "'" + print "User: '" + user( dbIdProp ) + "'" + print "Password: '" + password( dbIdProp ) + "'" + print "DbName: '" + dbName( dbIdProp ) + "'" diff --git a/RelationalCool/scripts/coolDescribeTable.py b/RelationalCool/scripts/coolDescribeTable.py new file mode 100755 index 000000000..21203d27c --- /dev/null +++ b/RelationalCool/scripts/coolDescribeTable.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +import os, sys +from CoolDescribeTable import * + +def myTest1(): + print 'Test myLPartition and myRPartition' + txt = 'abc( def )ghi' + print 'Partition "' + txt + '"' + print '"' + myLPartition(txt,'(') + '"' + print '"' + myLPartition(txt,'z') + '"' + print '"' + myRPartition(txt,')') + '"' + print '"' + myRPartition(txt,'z') + '"' + txt = 'abc(( def ))ghi' + print 'Partition "' + txt + '"' + print '"' + myLPartition(txt,'(') + '"' + print '"' + myLPartition(txt,'z') + '"' + print '"' + myRPartition(txt,')') + '"' + print '"' + myRPartition(txt,'z') + '"' + txt = 'z' + print 'Partition "' + txt + '"' + print '"' + myLPartition(txt,'(') + '"' + print '"' + myLPartition(txt,'z') + '"' + print '"' + myRPartition(txt,')') + '"' + print '"' + myRPartition(txt,'z') + '"' + sys.exit(0) + +def usage() : + if os.environ["OS"] != "Windows_NT" : + cmd = os.path.split(sys.argv[0])[1] + print "Usage: " + cmd + " [-debug] dbId table" + else : + cmd = "wineWrap.sh python " + sys.argv[0] + print "Usage: " + cmd + " [-debug] dbId table" + # Example: wineWrap.sh python ../../RelationalCool/scripts/coolDescribeTable.py -debug \"$COOLTESTDB\" COOLTEST_F0006_IOVS + print "Example: " + cmd + " -debug \\\"$COOLTESTDB\\\" COOLTEST_F0006_IOVS" + sys.exit(-1) + +############################################################################## + +if __name__ == '__main__': + ###myTest1() + if len(sys.argv)<3 : usage() + if sys.argv[1]=="-debug" : + if len(sys.argv)<4 : usage() + debug=True + dbId = sys.argv[2] + table = sys.argv[3] + else: + debug=False + dbId = sys.argv[1] + table = sys.argv[2] + columns = describeTable( dbId, table, debug ) + for column in columns : print column diff --git a/RelationalCool/scripts/coolExecuteSql.csh b/RelationalCool/scripts/coolExecuteSql.csh new file mode 100755 index 000000000..f856d3fbd --- /dev/null +++ b/RelationalCool/scripts/coolExecuteSql.csh @@ -0,0 +1,189 @@ +#!/bin/csh -f + +if ( "$1" != "-html" ) then + set theHtml = OFF + set theArg1 = "$1" + set theArg2 = "$2" + set theArg3 = "$3" +else + set theHtml = ON + set theArg1 = "$2" + set theArg2 = "$3" + set theArg3 = "$4" +endif + +if ( "$theArg2" == "-e" || "$theArg2" == "-eb" ) then + if ( "$theArg2" == "-e" ) then + set theCmd = ON + else + set theCmd = BATCH + endif + set theConnStr = "$theArg1" + set theSqlFile = "$theArg3" +else + set theCmd = OFF + set theConnStr = "$theArg1" + set theSqlFile = "$theArg2" +endif + +#echo "theHtml = $theHtml" +#echo "theCmd = $theCmd" +#echo "theConnStr = $theConnStr" +#echo "theSqlFile = $theSqlFile" + +if ( "$theConnStr" == "" || "$theSqlFile" == "" ) then + echo "Usage: $0 '[-html]' dbId { file.sql | -e 'command' | -eb 'command' }" + echo Example: $0 '"oracle://SERVER;schema=SCHEMA;dbname=DB"' file.sql + echo Example: $0 -html '"oracle://SERVER;schema=SCHEMA;dbname=DB"' file.sql + echo Example: $0 '"mysql://SERVER;schema=SCHEMA;dbname=DB"' -e 'cmd' + echo Example: $0 '"mysql://SERVER;schema=SCHEMA;dbname=DB"' -eb 'cmd' + echo Example: $0 -html '"mysql://SERVER;schema=SCHEMA;dbname=DB"' -eb 'cmd' + exit 1 +endif + +set theAuth = `coolAuthentication "$theConnStr" | & grep '==>'` +set theAuth = `echo "$theAuth ==>"` +#echo "theAuth = $theAuth" + +set theUrl = `echo "$theAuth" | awk '{str=$0; sep="==> urlHidePswd = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; str=substr(str,1,ind); l=length(str); cr=substr(str,l); if (cr=="\r") print substr(str,1,l-1); else print str;}'` +#echo "theUrl = $theUrl" + +if ( "$theUrl" == "" ) then + echo "ERROR! Could not execute SQL script $theSqlFile against COOL database "\""$theConnStr"\" + echo "ERROR! Invalid COOL databaseId or missing authentication credentials" + exit 1 +endif + +if ( "${theHtml}" != ON && "${theCmd}" != BATCH ) then + echo Execute SQL script \""$theSqlFile"\" against COOL database \""$theUrl"\" +endif + +set theTech = `echo "$theAuth" | awk '{str=$0; sep="==> technology = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; str=substr(str,1,ind); l=length(str); cr=substr(str,l); if (cr=="\r") print substr(str,1,l-1); else print str;}'` +set theHost = `echo "$theAuth" | awk '{str=$0; sep="==> server = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; str=substr(str,1,ind); l=length(str); cr=substr(str,l); if (cr=="\r") print substr(str,1,l-1); else print str;}'` +set theSchema = `echo "$theAuth" | awk '{str=$0; sep="==> schema = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; str=substr(str,1,ind); l=length(str); cr=substr(str,l); if (cr=="\r") print substr(str,1,l-1); else print str;}'` +set theUser = `echo "$theAuth" | awk '{str=$0; sep="==> user = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; str=substr(str,1,ind); l=length(str); cr=substr(str,l); if (cr=="\r") print substr(str,1,l-1); else print str;}'` +set thePswd = `echo "$theAuth" | awk '{str=$0; sep="==> password = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; str=substr(str,1,ind); l=length(str); cr=substr(str,l); if (cr=="\r") print substr(str,1,l-1); else print str;}'` +set theDbName = `echo "$theAuth" | awk '{str=$0; sep="==> dbname = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; str=substr(str,1,ind); l=length(str); cr=substr(str,l); if (cr=="\r") print substr(str,1,l-1); else print str;}'` +#echo "theTech = $theTech" +#echo "theHost = $theHost" +#echo "theSchema = $theSchema" +#echo "theUser = $theUser" +#echo "thePswd = $thePswd" +#echo "theDbName = $theDbName" +#exit + +# 2005.06.22 +# Here was a CHARMING bug (introduced by upgrading version of cygwin?). +# For theTech="oracle", on Windows this was actually equal to "oracle\r". +# All of the following returned (7,7) on Windows and (6,0) on SLC. +# echo a | awk -v s=$theTech '{print length(s), index(s,"\15")}' +# echo a | awk -v s=$theTech '{print length(s), index(s,"\015")}' +# echo a | awk -v s=$theTech '{print length(s), index(s,"\r")}' +# As a consequence ( "$theTech" == "oracle" ) was false on Windows. +# Now fixed by explicitly removing "\r" in awk above. +# For Oracle both Windows and SLC return (6,0). + +if ( "$theCmd" == "OFF" ) then + if ( ! -e "$theSqlFile" ) then + echo "ERROR! File not found: '$theSqlFile'" + exit 1 + endif + set theSqlScript = `basename $theSqlFile` + set theSqlDir = `dirname $theSqlFile` + #echo "theSqlScript = $theSqlScript" + #echo "theSqlDir = $theSqlDir" +else + set theSqlDir = . +endif + +# HACK on Windows (limit to the size of file names) +pushd $theSqlDir > /dev/null +set theSqlDir = . +#echo "theSqlDir = $theSqlDir" + +#-------- +# Oracle +#-------- +if ( "$theTech" == "oracle" ) then + + set theSilent="-S" + ###set theSilent="" + + if ( "${theHtml}" == ON ) then + + if ( "$theCmd" == "OFF" ) then + # This format requires "quit;" at the end of the script... + #sqlplus ${theSilent} -L -M "HTML ON" ${theUser}/${thePswd}@${theHost} @${theSqlDir}/${theSqlScript} + # This format does NOT requires "quit;" at the end of the script! + cat ${theSqlDir}/${theSqlScript} | sqlplus ${theSilent} -L -M "HTML ON" ${theUser}/${thePswd}@${theHost} + else + # This format does NOT requires "quit;" at the end of the script! + # Enclose it in quotes to be able to 'select * from table'...! + echo "${theSqlFile}" | sqlplus ${theSilent} -L -M "HTML ON" ${theUser}/${thePswd}@${theHost} + endif + + else + + if ( "$theCmd" == "OFF" ) then + # This format requires "quit;" at the end of the script... + #sqlplus ${theSilent} -L ${theUser}/${thePswd}@${theHost} @${theSqlDir}/${theSqlScript} + # This format does NOT requires "quit;" at the end of the script! + cat ${theSqlDir}/${theSqlScript} | sqlplus ${theSilent} -L ${theUser}/${thePswd}@${theHost} + else + # This format does NOT requires "quit;" at the end of the script! + # Enclose it in quotes to be able to 'select * from table'...! + echo "${theSqlFile}" | sqlplus ${theSilent} -L ${theUser}/${thePswd}@${theHost} + endif + + endif + +#------- +# MySQL +#------- +else if ( "$theTech" == "mysql" ) then + + if ( "${theHtml}" == ON ) then + set theHtml = "--html" + else + set theHtml = "" + endif + + # A special treatment is needed for the host:port syntax: + # the port number must be parsed out and passed explicitly + set thePort = `echo "$theHost" | awk '{str=$0; sep=":"; ind=index(str,sep); if (ind>0) print "-P" substr(str,ind+length(sep)); else print "";};'` + set theHost = `echo "$theHost" | awk '{str=$0; sep=":"; ind=index(str,sep); if (ind>0) print substr(str,0,ind-length(sep)); else print str;};'` + #echo "theHost = $theHost" + #echo "thePort = $thePort" + + if ( "$theCmd" == "OFF" ) then + mysql ${theHtml} -u${theUser} -p${thePswd} -h${theHost} ${thePort} ${theSchema} < ${theSqlDir}/${theSqlScript} + else + if ( "$theCmd" == "BATCH" ) then + mysql ${theHtml} -u${theUser} -p${thePswd} -h${theHost} ${thePort} ${theSchema} -B -N -e "${theSqlFile}" + else + mysql ${theHtml} -u${theUser} -p${thePswd} -h${theHost} ${thePort} ${theSchema} -e "${theSqlFile}" + endif + endif + +#-------- +# SQLite +#-------- +else if ( "$theTech" == "sqlite" ) then + + if ( "${theHtml}" == ON ) then + set theHtml = "-html" + else + set theHtml = "" + endif + + if ( "$theCmd" == "OFF" ) then + sqlite3 ${theHtml} ${theSchema} ".read ${theSqlDir}/${theSqlScript}" + else + sqlite3 ${theHtml} ${theSchema} "${theSqlFile}" + endif + +endif + +# HACK on Windows +popd > /dev/null + diff --git a/RelationalCool/scripts/coolGatherSchemaStats.py b/RelationalCool/scripts/coolGatherSchemaStats.py new file mode 100755 index 000000000..e72b0907a --- /dev/null +++ b/RelationalCool/scripts/coolGatherSchemaStats.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +import os, sys +from CoolGatherSchemaStats import * + +def usage() : + cmd = os.path.split(sys.argv[0])[1] + #print "Usage: " + cmd + " [-debug] dbId" + print "Usage: " + cmd + " dbId" + sys.exit(-1) + +############################################################################## + +if __name__ == '__main__': + if len(sys.argv)==2: + debug=False + dbId = sys.argv[1] + gatherSchemaStats( dbId, debug ) + #elif len(sys.argv)==3: + # if sys.argv[1]!="-debug": usage() + # debug=True + # dbId = sys.argv[2] + # gatherSchemaStats( dbId, debug ) + else: + usage() diff --git a/RelationalCool/scripts/coolGatherTableStats.py b/RelationalCool/scripts/coolGatherTableStats.py new file mode 100755 index 000000000..efc8d2e6f --- /dev/null +++ b/RelationalCool/scripts/coolGatherTableStats.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +import os, sys +from CoolGatherTableStats import * + +def usage() : + cmd = os.path.split(sys.argv[0])[1] + #print "Usage: " + cmd + " [-debug] dbId [tableName]" + print "Usage: " + cmd + " dbId [tableName]" + sys.exit(-1) + +############################################################################## + +if __name__ == '__main__': + if len(sys.argv)==2: + debug=False + dbId = sys.argv[1] + tableName = "" + gatherTableStats( dbId, tableName, debug ) + elif len(sys.argv)==3: + debug=False + dbId = sys.argv[1] + tableName = sys.argv[2] + gatherTableStats( dbId, tableName, debug ) + #elif len(sys.argv)==4: + # if sys.argv[1]!="-debug": usage() + # debug=True + # dbId = sys.argv[2] + # tableName = sys.argv[3] + # gatherTableStats( dbId, tableName, debug ) + else: + usage() diff --git a/RelationalCool/scripts/coolQueryManager.py b/RelationalCool/scripts/coolQueryManager.py new file mode 100755 index 000000000..032561d9f --- /dev/null +++ b/RelationalCool/scripts/coolQueryManager.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +import os, sys +from CoolQueryManager import * + +def usage() : + if os.environ["OS"] != "Windows_NT" : + cmd = os.path.split(sys.argv[0])[1] + print "Usage: " + cmd + " [-debug] dbId \"select... from... where x='y';\"" + else : + cmd = "wineWrap.sh python " + sys.argv[0] + print "Usage: " + cmd + " [-debug] dbId \"select... from... where x='y';\"" + # Example: wineWrap.sh python ../../RelationalCool/scripts/coolQueryManager.py -debug \"$COOLTESTDB\" \""select OBJECT_ID from COOLTEST_F0006_IOVS;"\" + print "Example: " + cmd + " -debug \\\"$COOLTESTDB\\\" \\\"\"select OBJECT_ID from COOLTEST_F0006_IOVS;\"\\\"" + # Example: wineWrap.sh python ../../RelationalCool/scripts/coolQueryManager.py -debug \"$COOLTESTDB\" \""select \* from COOLTEST_DB_ATTRIBUTES;"\" + print "Example: " + cmd + " -debug \\\"$COOLTESTDB\\\" \\\"\"select \\* from COOLTEST_DB_ATTRIBUTES;\"\\\"" + sys.exit(-1) + +############################################################################## + +if __name__ == '__main__': + ###myTest1() + if len(sys.argv)<3 : usage() + if sys.argv[1]=="-debug" : + if len(sys.argv)<4 : usage() + debug=True + dbId = sys.argv[2] + sql = sys.argv[3] + else: + debug=False + dbId = sys.argv[1] + sql = sys.argv[2] + columns = executeSqlSelect( dbId, sql, debug ) + for column in columns : print column diff --git a/RelationalCool/scripts/coolShowTables.py b/RelationalCool/scripts/coolShowTables.py new file mode 100755 index 000000000..18ceef894 --- /dev/null +++ b/RelationalCool/scripts/coolShowTables.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os, sys +from CoolShowTables import * + +def usage() : + cmd = os.path.split(sys.argv[0])[1] + print "Usage: " + cmd + " [-debug] dbId" + sys.exit(-1) + +############################################################################## + +if __name__ == '__main__': + if len(sys.argv)<2 : usage() + if sys.argv[1]=="-debug" : + if len(sys.argv)<3 : usage() + debug=True + dbId = sys.argv[2] + else: + debug=False + dbId = sys.argv[1] + tables = showTables( dbId, debug ) + for table in tables : print table diff --git a/RelationalCool/scripts/coolSqlplus.sh b/RelationalCool/scripts/coolSqlplus.sh new file mode 100755 index 000000000..8b568d176 --- /dev/null +++ b/RelationalCool/scripts/coolSqlplus.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# See https://twiki.cern.ch/twiki/bin/view/PSSGroup/RlWrap +if [ "${SCRAM_ARCH:0:5}" = "win32" ]; then + cmd=`basename $0` + echo "ERROR! $cmd is not supported for $SCRAM_ARCH: use sqlplus instead" + exit 1 +elif [ "${CMTCONFIG:0:5}" = "win32" ]; then + cmd=`basename $0` + echo "ERROR! $cmd is not supported for $CMTCONFIG: use sqlplus instead" + exit 1 +else + rlwrap -h > /dev/null 2&>1 + if [ $? == 0 ]; then + rlwrap \sqlplus $@ + else + \sqlplus $@ + fi +fi + diff --git a/RelationalCool/scripts/scramShowUses b/RelationalCool/scripts/scramShowUses new file mode 100755 index 000000000..b9ffdb620 --- /dev/null +++ b/RelationalCool/scripts/scramShowUses @@ -0,0 +1,2 @@ +#!/bin/tcsh -f +scram -debug b echo_INCLUDE | awk -f `dirname $0`/scramShowUses.awk diff --git a/RelationalCool/scripts/scramShowUses.awk b/RelationalCool/scripts/scramShowUses.awk new file mode 100644 index 000000000..61e04e8e0 --- /dev/null +++ b/RelationalCool/scripts/scramShowUses.awk @@ -0,0 +1,450 @@ +#---------------------------------------------------------------------------- +# +# Title: "scramShowUses.awk" +# Author: Andrea Valassi (Andrea.Valassi@cern.ch) +# Date: 26-MAR-2004 +# +# Purpose: This AWK script is a 'CMT show uses' emulator for SCRAM. +# +# Usage: 'scram -debug b echo_INCLUDE | awk -f scramShowUses.awk' +# +# This command should be issued from a directory where one and only package +# would be built, i.e. a single package BuildFile is parsed by SCRAM. +# Error messages are printed if no package would be built, or if scram +# would process many packages recursively ('About to process:'...). +# The dependency analysis is based from a (almost) dry run of scram +# in debug mode, letting scram parse BuildFiles recursively and feeding +# the resulting output to AWK. Write access to the local release top is +# needed as 'scram b' will rebuild .mk file fragments in tmp. +# +#---------------------------------------------------------------------------- +BEGIN { + status = 0; + # Local top level project and package + thisProjName = ""; + thisLocalRTop = ""; + thisReleaseTop = ""; + thisPkg = ""; + # External tools on which this package depends + nExtTools = 0; + delete extToolVersMap; #vers[name] for all selected tools (even not ref'ed) + delete extToolNameVec; #name[1..n] + extToolRef = "ext" #my alternatives: 'ref' or 'ext' (keep 'use' for pkgs) + # External projects on which this package depends + nExtProjs = 0; + delete extProjPathVec; #path[1..n] + delete extProjNameMap; #name[path] + # External packages on which this package depends + nExtPkgs = 0; + delete extPkgNameVec; #name[1..n] + delete extPkgProjMap; #proj[name] + # Current nesting level of dependencies + currLevel = 0; + currPkg = ""; + delete bfHashVec; #hash[level] + delete bfHashMap; #level[hash] + bfHashVec[0] = ""; + ###print "BEGIN: LEVEL=" currLevel; +} +#---------------------------------------------------------------------------- +{ + if ( $1 == "About" && $2 == "to" && $3 == "process" ) { + print $0; + print "****************************************************************"; + print "* ERROR! *"; + print "* 1. Do not feed 'scram -debug b' to this script: *"; + print "* feed the output of 'scram -debug b echo_INCLUDE' instead! *"; + print "* 2. You cannot process multiple packages using this script: *"; + print "* change directory so that 'scram b' sees a single BuildFile! *"; + print "****************************************************************"; + status=1; exit status; + } +} +#---------------------------------------------------------------------------- +{ + if ( $1 == "Parse" && $2 == "Error" ) { + print $0; + getline; + print $0; + status=1; exit status; + } +} +#---------------------------------------------------------------------------- +{ + # Analysis of nesting level of dependencies proceeds via buildfile hash + # Initially I thought of parsing the BuildFiles but that is error prone! + if (index($1,">BuildSystem::BuildFile(BuildSystem::BuildFile=HASH(")==1) { + if ( bfHashVec[currLevel] != $1 ) { + hash = $1; + # First time a hash value is found - level 0 + if ( currLevel == 0 && bfHashVec[0] == "" ) { + bfHashVec[0] = hash; + bfHashMap[hash] = 0; + } + # Hash value of a previous build file - decrease level accordingly + else if ( hash in bfHashMap ) { + # Decrease until currLevel = bfHashMap[hash] + while ( currLevel != bfHashMap[hash] ) { + delete bfHashMap[bfHashVec[currLevel]]; + delete bfHashVec[currLevel]; + currLevel--; + } + } + # Hash value of a new build file - increase level by 1 + else { + currLevel++; + bfHashVec[currLevel] = hash; + bfHashMap[hash] = currLevel; + # Print the package names as dependencies for levels>=1 + # Leave two extra spaces for all levels>1 + space = ""; + for ( i=1; i<currLevel; i++ ) { space = space ". "; } + currProjName = extProjNameMap[extPkgProjMap[currPkg]]; + print "# "space"use "currProjName"::"currPkg; + ###print "# "space"use "currProjName"::"currPkg" (LEVEL="currLevel")"; + } + ###print "LEVEL=" currLevel; + } + } +} +#---------------------------------------------------------------------------- +{ + # Local and global release top for the project of the top level package + if ( $1 == "->Found" && $2 == "top" ) { + if ( $3 == "" ) { print "ERROR! Null `top`!"; status=1; exit status; } + # Read the project name from its Environment + projEnv = $3 "/.SCRAM/Environment"; + projName = ""; + while ( projName == "" ) { + get = getline record < projEnv; + if ( get == -1 ) { + print "ERROR! Environment not found for project " $3 + status = 1; exit status; + } + else if ( get == 0 ) { + break; #EOF + } + key = "SCRAM_PROJECTNAME"; + i = index( record, key ); + if ( i != 0 ) { projName = substr( record, i+length(key) ); } + while( index(projName," ") == 1 || index(projName,"=") ) { + projName = substr( projName, 2 ); + } + } + # Is this the local or remote release top? + if ( thisLocalRTop == "" ) { + thisLocalRTop = $3; + thisProjName = projName; + print "###############################################################"; + print "# *** PROJECT_NAME: " projName; + print "# *** PROJECT_RTOP_LOCAL: " thisLocalRTop; + extProjNameMap[thisLocalRTop] = thisProjName; + } + else if ( thisReleaseTop == "" ) { + if ( projName != thisProjName ) { + print "ERROR! Project name mismatch!"; + status = 1; exit status; + } + thisReleaseTop = $3; + print "# *** PROJECT_RTOP: " thisReleaseTop; + extProjNameMap[thisReleaseTop] = thisProjName; + } + else { + print "ERROR! Too many release tops!"; + status = 1; exit status; + } + } +} +#---------------------------------------------------------------------------- +{ + # Top level package + if ( $2 == "ParseBuildFile:" ) { + pkg = substr( $4, 1, index($4,"/BuildFile")-1 ); + # Project and release area for this package + if ( index(pkg,thisLocalRTop) == 1 ) { + pkg = substr( pkg, length(thisLocalRTop)+1 ); + } + else { + print "PANIC! ParseBuildFile invoked outside local release top? " $4; + status = 1; exit status; + } + # Package name + while ( index(pkg,"/") == 1 ) { pkg = substr( pkg, 2 ); } + while ( index(pkg,"./") == 1 ) { pkg = substr( pkg, 3 ); } + while ( index(pkg,"/") == 1 ) { pkg = substr( pkg, 2 ); } + while ( index(pkg,"./") == 1 ) { pkg = substr( pkg, 3 ); } + if ( index(pkg,"src/") == 1 ) { pkg = substr( pkg, 5 ); } + while ( index(pkg,"/") == 1 ) { pkg = substr( pkg, 2 ); } + if ( pkg == "" ) { + print "ERROR! Null package! BuildFile: " $4; + status = 1; exit status; + } + # Two BuildFile's are expected here: from config and from the top level pkg + # (AV March 2007: $LOCALRT/config can now be in $LOCALRT/src/config/scram) + # NB The same HASH value defines the environment for both BuildFile's + if ( thisPkg == "" ) { + if ( pkg != "config" && pkg != "config/scram" ) { + print "PANIC! Unknown package (expecting config or config/scram): " $4; + status = 1; exit status; + } + thisPkg = pkg; + print "###############################################################"; + print "# *** PROJECT_CONFIG: " thisPkg; + #print "#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; + currPkg = pkg; + } + else if ( thisPkg == "config" ) { + thisPkg = pkg; + print "###############################################################"; + print "# *** PACKAGE_NAME: " thisProjName"::"thisPkg; + #print "#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; + currPkg = pkg; + } + else { + ###print "PANIC! Unknown package (expecting external ref): " $4; + ###print "PANIC! thisPkg = " thisPkg; + ###status = 1; exit status; + thisPkg = pkg; + print "###############################################################"; + print "# *** SUBPACKAGE_NAME: " thisProjName"::"thisPkg; + #print "#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; + currPkg = pkg; + } + } +} +#---------------------------------------------------------------------------- +{ + # Dependency on an external tool (project-wide) + if ( $3 == "being" && $4 == "Initialised" ) { + toolName = substr($1,3); + toolVers = $2; + print "# select " toolName " " toolVers; + if ( ! ( toolName in extToolVersMap ) ) { + extToolVersMap[toolName] = toolVers; + } + else { + if ( extToolVersMap[toolName] != toolVers ) { + print "ERROR! Tool " toolName " " \ + extToolVersMap[toolName] " already selected!"; + status=1; exit status; + } + print "WARNING! Tool " toolName " " toolVers " already selected!"; + } + } +} +#---------------------------------------------------------------------------- +{ + # Dependency on an external tool (package-specific) + # !!! This requires a modified version of scram !!! + if ( $2 == "External_StartTag:" && $3 == "select" && $4 == "Tool" ) { + toolName = $5; + # Print the tool names as dependencies for levels>=1 + # Leave two extra spaces for all levels>1 + space = ""; + for ( i=1; i<currLevel; i++ ) { space = space ". "; } + # External tool is ALWAYS one level below the current BuildFile! + if ( currLevel>=1 ) space = space ". "; + print "# " space extToolRef " " toolName; + ###print "# " space extToolRef " " toolName " (LEVEL=" currLevel+1 ")"; + # Update tool dependency vector + found = 0; + for ( i=1; i<=nExtTools; i++ ) { + if ( toolName == extToolNameVec[i] ) found = 1; + } + if ( found == 0 ) { + nExtTools++; + extToolNameVec[nExtTools] = toolName; + } + } +} +#---------------------------------------------------------------------------- +{ + # Dependency on an external SCRAM project + if ( $2 == "_pushremoteproject:" ) { + # Handle verbose output from my enhanced test version of SCRAM + # (where an external project can have both a localtop and a releasetop) + # Expect a colon-separated list of paths from _pushremoteproject: this is + # 'backward'-compatible to SCRAM V0_20_0 as it can handle a single path too + npaths = split ( $4, paths, ":" ); + delete projs; + proj = ""; + projEnv = ""; + for ( i=1; i<=npaths; i++ ) { + if ( paths[i] == "" ) { + projs[i] = ""; + } + else { + aProj = paths[i]; + while ( substr(aProj,length(aProj)) == "/" ) { + aProj = substr(aProj,1,length(aProj)-1); + } + if ( substr(aProj,length(aProj)-3) == "/src" ) { + aProj = substr(aProj,1,length(aProj)-4); + } + while ( substr(aProj,length(aProj)) == "/" ) { + aProj = substr(aProj,1,length(aProj)-1); + } + projs[i] = aProj; + aProjEnv = aProj "/.SCRAM/Environment"; + if ( system("ls " aProjEnv " >& /dev/null") == 0 ) { + ###print "FOUND " aProjEnv; + if ( projEnv == "" ) { + projEnv = aProjEnv; + proj = aProj; + } + } + else { + ###print "NOT FOUND " aProjEnv; + if ( projEnv == "" ) { + proj = aProj; + } + }; + } + } + # Read the project name from its Environment + projName = ""; + while ( projName == "" ) { + if ( projEnv == "" ) { + print "ERROR! Environment not found for project " proj; + status = 1; exit status; + } + getStatus = getline record < projEnv; + if ( getStatus == -1 ) { + print "ERROR! Environment not found for project " proj; + status = 1; exit status; + } + else if ( getStatus == 0 ) { + break; #EOF + } + key = "SCRAM_PROJECTNAME"; + i = index( record, key ); + if ( i != 0 ) { projName = substr( record, i+length(key) ); } + while( index(projName," ") == 1 || index(projName,"=") ) { + projName = substr( projName, 2 ); + } + } + # Is this a new project? + for ( i=1; i<=npaths; i++ ) { + aProj = projs[i]; + if ( aProj != "" && ( ! ( aProj in extProjNameMap ) ) ) { + if ( aProj == thisLocalRTop ) { + print "ERROR! Circular dependency on this project (localRT)?"; + status = 1; exit status; + } + if ( aProj == thisReleaseTop ) { + print "ERROR! Circular dependency on this project (releaseTop)?"; + status = 1; exit status; + } + # Add the project to the list + nExtProjs++; + extProjPathVec[nExtProjs] = aProj; + extProjNameMap[aProj] = projName; + ###print "# *** EXTERNAL_PROJECT("nExtProjs"): "projName" (" aProj ")"; + } + } + } +} +#---------------------------------------------------------------------------- +{ + # Dependency on an external SCRAM package + if ( $2 == "ParseBuildFile_Export:" ) { + pkg = substr( $4, 1, index($4,"/BuildFile")-1 ); + # Project and release area for this package + pkgProj = ""; + if ( index(pkg,thisLocalRTop) == 1 ) { + pkg = substr( pkg, length(thisLocalRTop)+1 ); + pkgProj = thisLocalRTop; + } + else if ( thisReleaseTop != "" && index(pkg,thisReleaseTop) == 1 ) { + pkg = substr( pkg, length(thisReleaseTop)+1 ); + pkgProj = thisReleaseTop; + } + else { + for ( proj in extProjNameMap ) { + if ( index(pkg,proj) == 1 ) { + pkg = substr( pkg, length(proj)+1 ); + pkgProj = proj; + } + } + } + if ( pkgProj == "" ) { + print "ERROR! No project associated to package: " $4; + status = 1; exit status; + } + # Package name + while ( index(pkg,"/") == 1 ) { pkg = substr( pkg, 2 ); } + if ( index(pkg,"src/") == 1 ) { pkg = substr( pkg, 5 ); } + while ( index(pkg,"/") == 1 ) { pkg = substr( pkg, 2 ); } + if ( pkg == "" ) { + print "ERROR! Null package! BuildFile: " $4; + status = 1; exit status; + } + ####### Analyse the dependencies of this package + ######system( "cat " $4 "| grep -i use" ); print ""; + # Add the package to the list if this is a new package + if ( ! ( pkg in extPkgProjMap ) ) { + nExtPkgs ++; + extPkgNameVec[nExtPkgs] = pkg; + extPkgProjMap[pkg] = pkgProj; + } + # Pass the package name to be printed out with its level of nesting + currPkg = pkg; + ###print "# " pkg; #THIS LINE IS USEFUL FOR DEBUGGING + } +} +#---------------------------------------------------------------------------- +END { + if ( status == 0 ) { + if ( thisPkg != "" && thisPkg != "config" ) { + #print "#"; + print "###############################################################"; + print "#"; + print "#--------------------"; + print "# TOOL DEPENDENCIES:"; + print "#--------------------"; + if ( nExtTools > 0 ) { + for ( i=1; i<=nExtTools; i++ ) { + toolName = extToolNameVec[i]; + toolVers = extToolVersMap[toolName]; + print extToolRef " " toolName " " toolVers; + } + } + else { + print "*** NONE ***"; + } + print "#"; + print "#-----------------------"; + print "# PACKAGE DEPENDENCIES:"; + print "#-----------------------"; + if ( nExtPkgs > 0 ) { + for ( i=1; i<=nExtPkgs; i++ ) { + pkg = extPkgNameVec[i]; + pkgProj = extPkgProjMap[pkg]; + pkgProjName = extProjNameMap[pkgProj]; + ###print "use " pkgProjName "::" pkg " (" pkgProj ")"; #CMT-like + print "use " pkgProjName "::" pkg; + print " (" pkgProj ")"; + } + } + else { + print "*** NONE ***"; + } + ###print "END: LEVEL=" currLevel; + } + else { + print "****************************************************************"; + print "* ERROR! *"; + print "* 1. You cannot process multiple packages using this script: *"; + print "* change directory so that 'scram b' sees a single BuildFile! *"; + print "* 2. Or maybe, 'scram b' does not see ANY BuildFile from here? *"; + print "****************************************************************"; + } + } +} +#---------------------------------------------------------------------------- +{ + # Print out debug messages from my modifcations to SCRAM + if ( $1 == "__scramShowUses" ) print $0; +} +#---------------------------------------------------------------------------- + diff --git a/RelationalCool/scripts/sql/oraclePurgeRecycleBin.sql b/RelationalCool/scripts/sql/oraclePurgeRecycleBin.sql new file mode 100644 index 000000000..9bfa8c257 --- /dev/null +++ b/RelationalCool/scripts/sql/oraclePurgeRecycleBin.sql @@ -0,0 +1,2 @@ +purge recyclebin; +exit; diff --git a/RelationalCool/scripts/sql/oracleShowTables.sql b/RelationalCool/scripts/sql/oracleShowTables.sql new file mode 100644 index 000000000..878608f79 --- /dev/null +++ b/RelationalCool/scripts/sql/oracleShowTables.sql @@ -0,0 +1,3 @@ +set pagesize 1000; +select table_name from all_tables where owner='&1' and table_name like '&2%'; +exit; diff --git a/RelationalCool/scripts/wineWrap.sh b/RelationalCool/scripts/wineWrap.sh new file mode 100755 index 000000000..621b10ac9 --- /dev/null +++ b/RelationalCool/scripts/wineWrap.sh @@ -0,0 +1,123 @@ +#! /bin/bash + +# Check command line arguments +if [ "$1" = "" ]; then + cmd=`basename $0` + echo "Usage: $cmd command [arguments]" + exit 1 +fi + +# Print out the environment? +if [ "$WINE_WRAP_PRINTENV" != "on" ]; then + export WINE_WRAP_PRINTENV=off +fi + +# Check O/S +if [ "$OS" = "Windows_NT" ]; then + if [ "${SCRAM_ARCH:0:5}" != "win32" ]; then + echo "ERROR! Invalid SCRAM_ARCH $SCRAM_ARCH on $OS for $0" + exit 1 + fi + if [ "$WINE_WRAP_DEBUG" != "" ]; then + debug=1 + else + debug=0 + fi +else + debug=0 +fi + +# Make sure LOCALRT is defined +export LOCALRT= +export PATH=/afs/cern.ch/sw/lcg/app/spi/scram:"${PATH}" +eval `scram runtime -sh` +if [ "$LOCALRT" = "" ] ; then + echo "ERROR! Cannot define LOCALRT - are you in a valid SCRAM directory?" + exit 1 +fi + +# Keep the current SEAL options file if already defined +export SEAL_CONFIGURATION_FILE_OLD=${SEAL_CONFIGURATION_FILE} + +# Load common functions +###echo "DEBUG: load common test functions..." +if [ -r $LOCALRT/config/test_functions.sh ] ; then + . $LOCALRT/config/test_functions.sh +elif [ -r $LOCALRT/src/config/scram/test_functions.sh ] ; then + . $LOCALRT/src/config/scram/test_functions.sh +else + echo "ERROR! Cannot find common test functions" + exit 1 +fi +###echo "DEBUG: load common test functions... DONE" + +## NB: Make sure $HOME/private/authentication.xml contains YOUR credentials! +check_authfile +set_preliminar_env + +## By default ORACLE_HOME is unset +# keepORACLE_HOME=yes +prepare_env + +# Fix the PATHs for specific systems (only if needed) +fix_win_paths + +# Disable POOL trace files +#unset POOL_ORA_SQL_TRACE_ON +#unset POOL_ORA_CERNTRACE_ON + +# Keep the current SEAL options file if already defined +if [ "$SEAL_CONFIGURATION_FILE_OLD" != "" ] ; then + export SEAL_CONFIGURATION_FILE=$SEAL_CONFIGURATION_FILE_OLD +fi + +#---------------------------------------------------------------------------- +# Analyse SCRAM_ARCH and CMTCONFIG to determine if we should use WIN32 +#---------------------------------------------------------------------------- +echo "SCRAM_ARCH: $SCRAM_ARCH" +echo "CMTCONFIG: $CMTCONFIG" +useWin32=0 +if [ "${SCRAM_ARCH:0:5}" = "win32" ]; then + useWin32=1 +elif [ "$SCRAM_ARCH" = "" ] && [ "${CMTCONFIG:0:5}" = "win32" ]; then + useWin32=1 +fi + +#---------------------------------------------------------------------------- +# Unix platform +#---------------------------------------------------------------------------- +if [ "$useWin32" = "0" ]; then + + ###echo "__UNIX Current environment variables: "; env + echo "__UNIX Execute command: " $@ + $@ + +#---------------------------------------------------------------------------- +# Win32 platform +#---------------------------------------------------------------------------- +else + + # Debugging information + ###echo "__WINE Current environment variables: "; env + if [ "$OS" = "Windows_NT" ]; then + echo "__WINE.NT Execute command: " $@ + else + echo "__WINE.WINE Execute command: " $@ + fi + + # Execute the command under Wine + if [ "$debug" = "0" ]; then + cmd_wrapper $@ + status=${?} + else + debug $@ + status=${?} + fi + ###echo status=$status + exit $status + +#---------------------------------------------------------------------------- +# End check on platform +#---------------------------------------------------------------------------- +fi + diff --git a/RelationalCool/src/AttributeTable.h b/RelationalCool/src/AttributeTable.h new file mode 100644 index 000000000..c114f3b1f --- /dev/null +++ b/RelationalCool/src/AttributeTable.h @@ -0,0 +1,94 @@ +// $Id: AttributeTable.h,v 1.6 2008-11-04 11:52:10 avalassi Exp $ +#ifndef RELATIONALCOOL_ATTRIBUTETABLE_H +#define RELATIONALCOOL_ATTRIBUTETABLE_H 1 + +// Include files +#include "AttributeList/AttributeList.h" +#include "AttributeList/AttributeListSpecification.h" + +namespace cool { + + /** @class AttributeTable AttributeTable.h + * + * Implementation of a vector of AttributeList's + * with a single AttributeListSpecification. + * + * Each AttributeList is available to the user only as a reference. + * The lifetime of the references coincides with that of the AttributeTable. + * + * @author Andrea Valassi + * @date 2005-02-01 + */ + + class AttributeTable { + + public: + + /// Constructor from an AttributeListSpecification reference + AttributeTable( const coral::AttributeListSpecification& spec ) { + m_spec = new coral::AttributeListSpecification(); + coral::AttributeListSpecification::const_iterator itSpec; + for ( itSpec = spec.begin(); itSpec != spec.end(); ++itSpec ) { + m_spec->push_back( itSpec->name(), itSpec->type_name() ); + } + } + + /// Destructor + virtual ~AttributeTable() { + std::vector< coral::AttributeList* >::const_iterator itList; + for ( itList = m_lists.begin(); + itList != m_lists.end(); + itList++ ) { + delete (*itList); + } + delete m_spec; + } + + /// Insert a new row from an AttributeList reference + /// Throws a RelationalException if a specification is invalid. + void push_back( const coral::AttributeList& list ) { + if ( list.attributeListSpecification() != *m_spec ) + throw RelationalException + ( "Invalid specification", "AttributeTable" ); + coral::AttributeList* newList( new coral::AttributeList( *m_spec ) ); + coral::AttributeList::const_iterator itList; + for ( itList=list.begin(); itList!=list.end(); ++itList ) { + (*newList)[ itList->spec().name() ].shareData( *itList ); + } + return m_lists.size(); + } + + /// Retrieve a row as an AttributeList reference + coral::AttributeList& operator[] ( unsigned int iRow ) { + return *(m_lists[iRow]); + } + + /// Number of rows in the table (number of AttributeList's) + unsigned int size() const { + return m_lists.size(); + } + + private: + + /// Standard constructor is private + AttributeTable(); + + /// Copy constructor is private + AttributeTable( const AttributeTable& rhs ); + + /// Assignment operator is private + AttributeTable& operator=( const AttributeTable& rhs ); + + private: + + /// The attributeListSpecification for the AttributeTable + const coral::AttributeListSpecification* m_spec; + + /// The vector of AttributeList's + std::vector< coral::AttributeList* > m_lists; + + }; + +} + +#endif // RELATIONALCOOL_ATTRIBUTETABLE_H diff --git a/RelationalCool/src/ConstRelationalObjectAdapter.cpp b/RelationalCool/src/ConstRelationalObjectAdapter.cpp new file mode 100644 index 000000000..8ef479a46 --- /dev/null +++ b/RelationalCool/src/ConstRelationalObjectAdapter.cpp @@ -0,0 +1,223 @@ +// $Id: ConstRelationalObjectAdapter.cpp,v 1.11 2009-02-09 17:53:28 avalassi Exp $ + +// Local include files +//#include "attributeListToString.h" +#include "ConstRelationalObjectAdapter.h" +#include "RelationalException.h" +#include "RelationalObject.h" +#include "RelationalObjectTable.h" +#include "RelationalObjectTableRow.h" +#include "TimingReportMgr.h" +#include "timeToString.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +ConstRelationalObjectAdapter::ConstRelationalObjectAdapter +( const coral::AttributeList& aList, + const IRecordSpecification& payloadSpec ) + : m_isTimingActive( isTimingActive() ) + , m_aList( aList ) + , m_payloadSpec( payloadSpec ) + , m_since( aList[RelationalObjectTable::columnNames::iovSince()] + .data<ValidityKey>() ) + , m_until( aList[RelationalObjectTable::columnNames::iovUntil()] + .data<ValidityKey>() ) + , m_payload( payloadSpec, aList ) + , m_channelId( aList[RelationalObjectTable::columnNames::channelId()] + .data<ChannelId>() ) + , m_insertionTime( aList[RelationalObjectTable::columnNames::sysInsTime()] + .data<std::string>() ) + , m_objectId( aList[RelationalObjectTable::columnNames::objectId()] + .data<unsigned int>() ) +{ + + // This is used for READING back data __WITHOUT ANY DEEP COPY__! + + // Assuming that the RelationalObjectTableRow is a wrapper around + // a reference to a temporary CORAL buffer, this instance can only be + // used as long as the temporary CORAL buffer contains the right data! + + if ( m_isTimingActive ) + TimingReportMgr::stopTimer + ( "cool::ConstRelationalObjectAdapter::ctor" ); + +} + +//----------------------------------------------------------------------------- + +ConstRelationalObjectAdapter::~ConstRelationalObjectAdapter() +{ + //if ( m_isTimingActive ) + // TimingReportMgr::stopTimer + // ( "cool::ConstRelationalObjectAdapter [LIFETIME]" ); +} + +//----------------------------------------------------------------------------- + +bool ConstRelationalObjectAdapter::isTimingActive() const +{ + if ( TimingReportMgr::isActive() ) + { + TimingReportMgr::startTimer + ( "cool::ConstRelationalObjectAdapter::ctor" ); + //TimingReportMgr::startTimer + // ( "cool::ConstRelationalObjectAdapter [LIFETIME]" ); + return true; + } + else return false; +} + +//----------------------------------------------------------------------------- + +IObject* ConstRelationalObjectAdapter::clone() const +{ + //std::cout << "ConstRelationalObjectAdapter::clone" << std::endl; + //std::cout << "DATA: " << attributeListToString(m_aList) << std::endl; + //std::cout << "SPEC: " << Record(m_payloadSpec) << std::endl; + return new RelationalObject( m_aList, m_payloadSpec ); +} + +//----------------------------------------------------------------------------- + +const ValidityKey& ConstRelationalObjectAdapter::since() const +{ + return m_since; +} + +//----------------------------------------------------------------------------- + +const ValidityKey& ConstRelationalObjectAdapter::until() const +{ + return m_until; +} + +//----------------------------------------------------------------------------- + +const IRecord& ConstRelationalObjectAdapter::payload() const +{ + return m_payload; +} + +//----------------------------------------------------------------------------- + +const ChannelId& ConstRelationalObjectAdapter::channelId() const +{ + return m_channelId; +} + +//----------------------------------------------------------------------------- + +/* +const std::string& ConstRelationalObjectAdapter::channelName() const +{ + throw RelationalException + ( "ConstRelationalObjectAdapter::channelName is not implemented yet" ); +} +*/ + +//----------------------------------------------------------------------------- + +bool ConstRelationalObjectAdapter::isStored() const +{ + return true; +} + +//----------------------------------------------------------------------------- + +unsigned int ConstRelationalObjectAdapter::objectId() const +{ + return m_objectId; +} + +//----------------------------------------------------------------------------- + +const ITime& ConstRelationalObjectAdapter::insertionTime() const +{ + return m_insertionTime; +} + +//----------------------------------------------------------------------------- +/* +const ValidityKey& ConstRelationalObjectAdapter::sinceOriginal() const +{ + return m_sinceOriginal; +} + +//----------------------------------------------------------------------------- + +const ValidityKey& ConstRelationalObjectAdapter::untilOriginal() const +{ + return m_untilOriginal; +} + +//----------------------------------------------------------------------------- + +const ITime& ConstRelationalObjectAdapter::insertionTimeOriginal() const +{ + return m_insertionTimeOriginal; +} +*/ +//----------------------------------------------------------------------------- + +std::ostream& ConstRelationalObjectAdapter::print( std::ostream& s ) const +{ + s << "Object: "; + { + unsigned int maxSize = 3; + s << std::setw(maxSize) << objectId(); + } + + s << " "; + + { + unsigned int maxSize = 2; + s << "(" << std::setw(maxSize) << channelId() << ")"; + } + + { // assemble IOV + std::stringstream iov; + iov << " [" << since() << "," ; + if ( until() == ValidityKeyMax ) { + iov << "+inf"; + } else { + iov << until(); + } + iov << "["; + unsigned int maxSize = 10; + s << std::setiosflags(std::ios::left) << std::setw(maxSize); + s << iov.str(); + s << std::resetiosflags(std::ios::left); + } + + s << " "; + + { // assemble payload + std::stringstream p; + p << "["; + bool first = true; + const IRecordSpecification& spec = payload().specification(); + for ( unsigned int i = 0; i < spec.size(); i++ ) { + if ( first ) { + first = false; + p << payload()[i]; + } else { + p << "|" << payload()[i]; + } + } + p << "] "; + + unsigned int maxSize = 20; + s << std::setiosflags(std::ios::left) << std::setw(maxSize); + s << p.str(); + s << std::resetiosflags(std::ios::left); + } + + s << timeToString( insertionTime() ); + return s; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/ConstRelationalObjectAdapter.h b/RelationalCool/src/ConstRelationalObjectAdapter.h new file mode 100644 index 000000000..10afea8af --- /dev/null +++ b/RelationalCool/src/ConstRelationalObjectAdapter.h @@ -0,0 +1,142 @@ +// $Id: ConstRelationalObjectAdapter.h,v 1.11 2008-11-04 10:56:38 avalassi Exp $ +#ifndef RELATIONALCOOL_CONSTRELATIONALOBJECTADAPTER_H +#define RELATIONALCOOL_CONSTRELATIONALOBJECTADAPTER_H + +// Include files +#include "CoolKernel/ConstRecordAdapter.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IRecordSpecification.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/Time.h" + +// Local include files +#include "ConstTimeAdapter.h" + +namespace cool { + + // Forward declarations + class RelationalObjectTableRow; + + /** @class ConstRelationalObjectAdapter ConstRelationalObjectAdapter.h + * + * Read-only wrapper of a constant coral::AttributeList reference, + * implementing the cool::IObject interface. The adapter can only be + * used as long as the AttributeList is alive. The adapter creates + * its own RecordSpecification from one specified at construction time. + * + * @author Andrea Valassi + * @date 2007-03-09 + */ + + class ConstRelationalObjectAdapter : public IObject { + + public: + + /// Constructor from a record spec and a _const_ AttributeList reference. + ConstRelationalObjectAdapter( const coral::AttributeList& aList, + const IRecordSpecification& payloadSpec ); + + /// Destructor + virtual ~ConstRelationalObjectAdapter(); + + /// Clone this IObject by performing a deep copy + virtual IObject* clone() const; + + /// Channel identifier + const ChannelId& channelId() const; + + /// Channel name + //const std::string& channelName() const; + + /// Start of validity interval + /// For stored objects this refers to the visible validity interval + const ValidityKey& since() const; + + /// End of validity interval + /// For stored objects this refers to the visible validity interval + const ValidityKey& until() const; + + /// Data payload + const IRecord& payload() const; + + /// Has the object been stored into the database? + bool isStored() const; + + /// System-assigned object ID + /// Throws an exception if the object has not been stored yet + unsigned int objectId() const; + + /// Insertion time into the database + /// Throws an exception if the object has not been stored yet + const ITime& insertionTime() const; + + /// Start of original validity interval + /// Throws an exception if the object has not been stored yet + //const ValidityKey& sinceOriginal() const; + + /// End of original validity interval + /// Throws an exception if the object has not been stored yet + //const ValidityKey& untilOriginal() const; + + /// Insertion time of the original object into the database + /// Throws an exception if the object has not been stored yet + //const ITime& insertionTimeOriginal() const; + + /// Pretty print to an output stream + std::ostream& print( std::ostream& s ) const; + + private: + + ConstRelationalObjectAdapter(); + + ConstRelationalObjectAdapter( const ConstRelationalObjectAdapter& rhs ); + + ConstRelationalObjectAdapter& + operator=( const ConstRelationalObjectAdapter& rhs ); + + /// Is timing active? (hack to activate it at the beginning of the ctor) + bool isTimingActive() const; + + private: + + /// Is timing active? (hack to activate it at the beginning of the ctor) + bool m_isTimingActive; + + /// The input coral::AttributeList const reference + const coral::AttributeList& m_aList; + + /// The input record specification const reference + const IRecordSpecification& m_payloadSpec; + + /// Beginning of the interval of validity + const ValidityKey& m_since; + + /// End of the interval of validity + const ValidityKey& m_until; + + /// Object payload + const ConstRecordAdapter m_payload; + + /// Channel id + const ChannelId& m_channelId; + + /// Insertion time + const ConstTimeAdapter m_insertionTime; + + /// Object id + const unsigned int& m_objectId; + + /// Beginning of the original interval of validity + //const ValidityKey& m_sinceOriginal; + + /// End of the original interval of validity + //const ValidityKey& m_untilOriginal; + + /// Original insertion time + //const Time& m_insertionTimeOriginal; + + }; + +} + +#endif diff --git a/RelationalCool/src/ConstTimeAdapter.cpp b/RelationalCool/src/ConstTimeAdapter.cpp new file mode 100644 index 000000000..42d7ac841 --- /dev/null +++ b/RelationalCool/src/ConstTimeAdapter.cpp @@ -0,0 +1,94 @@ +// $Id: ConstTimeAdapter.cpp,v 1.2 2008-11-04 10:56:38 avalassi Exp $ + +// Local include files +#include "ConstTimeAdapter.h" +#include "timeToString.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +ConstTimeAdapter::~ConstTimeAdapter() +{ +} + +//----------------------------------------------------------------------------- + +ConstTimeAdapter::ConstTimeAdapter( const std::string& time ) + : m_time( time ) +{ +} + +//----------------------------------------------------------------------------- + +int ConstTimeAdapter::year() const +{ + return stringToTime( m_time ).year(); +} + +//----------------------------------------------------------------------------- + +int ConstTimeAdapter::month() const +{ + return stringToTime( m_time ).month(); +} + +//----------------------------------------------------------------------------- + +int ConstTimeAdapter::day() const +{ + return stringToTime( m_time ).day(); +} + +//----------------------------------------------------------------------------- + +int ConstTimeAdapter::hour() const +{ + return stringToTime( m_time ).hour(); +} + +//----------------------------------------------------------------------------- + +int ConstTimeAdapter::minute() const +{ + return stringToTime( m_time ).minute(); +} + +//----------------------------------------------------------------------------- + +int ConstTimeAdapter::second() const +{ + return stringToTime( m_time ).second(); +} + +//----------------------------------------------------------------------------- + +long ConstTimeAdapter::nanosecond() const +{ + return stringToTime( m_time ).nanosecond(); +} + +//----------------------------------------------------------------------------- + +std::ostream& ConstTimeAdapter::print( std::ostream& os ) const +{ + return stringToTime( m_time ).print( os ); +} + +//----------------------------------------------------------------------------- + +bool ConstTimeAdapter::operator==( const ITime& rhs ) const +{ + return stringToTime( m_time ) == rhs; +} + +//----------------------------------------------------------------------------- + +bool ConstTimeAdapter::operator>( const ITime& rhs ) const +{ + return stringToTime( m_time ) > rhs; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/ConstTimeAdapter.h b/RelationalCool/src/ConstTimeAdapter.h new file mode 100644 index 000000000..9daa31757 --- /dev/null +++ b/RelationalCool/src/ConstTimeAdapter.h @@ -0,0 +1,82 @@ +#ifndef RELATIONALCOOL_CONSTTIMEADAPTER_H +#define RELATIONALCOOL_CONSTTIMEADAPTER_H + +// Include files +#include "CoolKernel/ITime.h" + +namespace cool +{ + + /** @class ConstTimeAdapter ConstTimeAdapter.h + * + * Wrapper of a std::string to the cool::ITime interface. + * + * NB Every method call triggers a string-to-time conversion: + * this is because it is assumed that the string may change + * during the lifetime of the adapter, hence nothing is cached! + * + * @author Andrea Valassi + * @date 2007-03-29 + */ + + class ConstTimeAdapter : public ITime + { + + public: + + /// Destructor. + virtual ~ConstTimeAdapter(); + + /// Constructor from a const std::string reference. + ConstTimeAdapter( const std::string& time ); + + /// Returns the year. + int year() const; + + /// Returns the month [1-12]. + int month() const; + + /// Returns the day [1-31]. + int day() const; + + /// Returns the hour [0-23]. + int hour() const; + + /// Returns the minute [0-59]. + int minute() const; + + /// Returns the second [0-59]. + int second() const; + + /// Returns the nanosecond [0-999999999]. + long nanosecond() const; + + /// Print to an output stream. + std::ostream& print( std::ostream& os ) const; + + /// Comparison operator. + bool operator==( const ITime& rhs ) const; + + /// Comparison operator. + bool operator>( const ITime& rhs ) const; + + private: + + /// Standard constructor + ConstTimeAdapter(); + + /// Copy constructor from another ConstTimeAdapter. + ConstTimeAdapter( const ConstTimeAdapter& rhs ); + + /// Assignment operator from another ConstTimeAdapter. + ConstTimeAdapter& operator=( const ConstTimeAdapter& rhs ); + + private: + + const std::string& m_time; + + }; + +} + +#endif // COOLKERNEL_TIME_H diff --git a/RelationalCool/src/CoolChrono.cpp b/RelationalCool/src/CoolChrono.cpp new file mode 100644 index 000000000..e03b06e16 --- /dev/null +++ b/RelationalCool/src/CoolChrono.cpp @@ -0,0 +1,64 @@ +// Include files +#include <cstdlib> // for getenv + +// Local include files +#include "CoolChrono.h" +#include "ProcMemory.h" +#include "SealBase_TimeInfo.h" + +// Namespace +using namespace cool; + +CoolChrono::CoolChrono() : + m_names(n), + m_values(n), + m_started(false) +{ + + // construct vector of names + m_names[realTime] = "Real Time"; + m_names[userTime] = "User Time"; + m_names[systemTime] = "System Time"; + m_names[cpuTime] = "Cpu Time"; + m_names[idleTime] = "Idle Time"; + m_names[vmSize] = "VmSize incr"; + m_names[vmRss] = "VmRSS incr"; +} + +void CoolChrono::start() +{ + // reset vector + m_values.assign(nTypes(),0); + m_started=true; + // get initial values + seal::TimeInfo::init(); + seal::TimeInfo::processTimes(m_userTime, m_sysTime, m_realTime); + m_cpuTime = seal::TimeInfo::processCpuTime (); + m_idleTime = seal::TimeInfo::processIdleTime (); + // WARNING! Memory monitoring slows down time performance by factors! + if ( getenv ( "COOL_COOLCHRONO_PROCMEMORY" ) ) { + ProcMemory mem; + m_vmSize = mem.getVsz(); + m_vmRss = mem.getRss(); + } +} + +void CoolChrono::stop() +{ + if (!m_started) return; // need to start first + // calculate time differences + m_values[realTime] = seal::TimeInfo::processRealTime() - m_realTime; + m_values[userTime] = seal::TimeInfo::processUserTime() - m_userTime; + m_values[systemTime] = seal::TimeInfo::processSystemTime() - m_sysTime; + m_values[cpuTime] = seal::TimeInfo::processCpuTime() - m_cpuTime; + m_values[idleTime] = seal::TimeInfo::processIdleTime() - m_idleTime; + // WARNING! Memory monitoring slows down time performance by factors! + if ( getenv ( "COOL_COOLCHRONO_PROCMEMORY" ) ) { + // Multiply by 1E9 (no need to go from seconds to nanoseconds! back to kB) + // Divide by 1E3 (from kB to MB) + ProcMemory mem; + m_values[vmSize] = (mem.getVsz() - m_vmSize) * 1000000.; // MB + m_values[vmRss] = (mem.getRss() - m_vmRss) * 1000000.; // MB + } +} + diff --git a/RelationalCool/src/CoolChrono.h b/RelationalCool/src/CoolChrono.h new file mode 100644 index 000000000..5a82e130c --- /dev/null +++ b/RelationalCool/src/CoolChrono.h @@ -0,0 +1,57 @@ +#ifndef RELATIONALCOOL_COOLCHRONO_H +#define RELATIONALCOOL_COOLCHRONO_H 1 + +// Include files +#include <string> +#include <vector> +#include "SealUtil_BaseSealChrono.h" + +namespace cool +{ + + /** + * Time measurement performed using TimeInfo: + * measured Real, CPU (separated by User and System) and idle time + */ + class CoolChrono : public seal::BaseSealChrono + { + + public: + + CoolChrono(); + virtual ~CoolChrono() { /* no op */ } + + typedef double TimeUnit; + + enum { realTime, userTime, systemTime, cpuTime, idleTime, + vmSize, vmRss, n }; + + std::vector<std::string> names() const { return m_names; } + + // return measured value + std::vector<double> values() const { return m_values; } + + unsigned int nTypes() const { return n; } + + void start(); + void stop(); + + private: + + std::vector<std::string> m_names; + std::vector<double> m_values; + bool m_started; + + // initial values + TimeUnit m_realTime; + TimeUnit m_userTime; + TimeUnit m_sysTime; + TimeUnit m_cpuTime; + TimeUnit m_idleTime; + long m_vmSize; + long m_vmRss; + + }; + +} +#endif diff --git a/RelationalCool/src/CoralApplication.cpp b/RelationalCool/src/CoralApplication.cpp new file mode 100644 index 000000000..e1d9c25ad --- /dev/null +++ b/RelationalCool/src/CoralApplication.cpp @@ -0,0 +1,401 @@ +// $Id: CoralApplication.cpp,v 1.25 2009-01-06 11:52:12 avalassi Exp $ + +// Include files +#include <iostream> +#include "CoolKernel/Exception.h" +#include "CoolKernel/IDatabaseSvc.h" +//#include "SealBase/Signal.h" +//#include "SealBase/ProcessInfo.h" +#include "RelationalAccess/ConnectionService.h" + +// Local include files +#include "CoralApplication.h" +#include "RalDatabaseSvc.h" +#ifndef __APPLE__ +#ifndef WIN32 +#include "sigsegv.h" +#endif +#endif + +// Message output +#define COUT std::cout << "__cool::CoralApplication " +#define ENDL std::endl + +// Workaround for Windows (win32_vc9_dbg) +// ERROR seems to be defined in a Windows VC9 header +// See also CoolKernel/CoolKernel/MessageLevels.h +// See also RelationalCool/utilities/coolPrivileges/RalPrivilegeManager.cpp +#ifdef WIN32 +#ifdef ERROR +#undef ERROR +#pragma message ("WARN!NG: in RelationalCool/src/CoralApplication.cpp") +#pragma message ("WARN!NG: 'ERROR' was defined and has been undefined") +#endif +#endif + +//----------------------------------------------------------------------------- + +namespace cool +{ + class MessageReporter: virtual public coral::IMsgReporter + { + + public: + + /// Default constructor + MessageReporter( coral::MsgLevel dummyLvl = coral::Info ): + m_level( dummyLvl ) {} // dummy as it will be changed by setMsgVerbosity + + /// Destructor (called only by sub-classes) + virtual ~MessageReporter() {} + + /// Release reference to reporter + void release() + { + delete this; // only one instance... + } + + /// Access output level + coral::MsgLevel outputLevel() const { return m_level; } + + /// Modify output level + void setOutputLevel( coral::MsgLevel lvl ) { m_level = lvl; } + + /// Report a message + void report( int level, const std::string& src, const std::string& msg ) + { + if ( level >= m_level ) + { + std::ostream& out = std::cout; + const std::string::size_type src_name_maxsize = 36; + if ( src.size() <= src_name_maxsize ) + { + out << src << std::string( src_name_maxsize-src.size(), ' ' ); + } + else + { + out << src.substr( 0, src_name_maxsize-3 ) << "..."; + } + switch ( level ) + { + case 0: out << " Nil "; break; + case 1: out << " Verbose "; break; + case 2: out << " Debug "; break; + case 3: out << " Info "; break; + case 4: out << " Warning "; break; + case 5: out << " Error "; break; + case 6: out << " Fatal "; break; + case 7: out << " Always "; break; + default: out << " Unknown "; break; + } + out << msg << std::endl; + } + } + + private: + + coral::MsgLevel m_level; //< threshold for the messages + + }; +} + +//----------------------------------------------------------------------------- + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +CoralApplication::CoralApplication( coral::IConnectionService* connSvc ) +{ + + //COUT << "CoralApplication(): ** START **" << ENDL; + + try + { + + //-------------------------------------------- + // 1. Create a message stream + //-------------------------------------------- + + // Install the COOL implementation of the message reporter + if ( getenv( "COOL_ENABLE_COOLMSGREPORTER" ) ) + { + coral::MessageStream::installMsgReporter( new cool::MessageReporter() ); + } + + // Set the verbosity for COOL and CORAL if COOL_MSGLEVEL is set + if ( getenv( "COOL_MSGLEVEL" ) ) + { + // Use MSG::ERROR if COOL_MSGLEVEL is set to an invalid value + cool::MSG::Level level = cool::MSG::ERROR; + + // Check only the first char of the environment variable + switch ( *getenv( "COOL_MSGLEVEL" ) ) + { + case '0': + case 'n': + case 'N': level = cool::MSG::NIL; break; + + case '1': + case 'v': + case 'V': level = cool::MSG::VERBOSE; break; + + case '2': + case 'd': + case 'D': level = cool::MSG::DEBUG; break; + + case '3': + case 'i': + case 'I': level = cool::MSG::INFO; break; + + case '4': + case 'w': + case 'W': level = cool::MSG::WARNING; break; + + case '5': + case 'e': + case 'E': level = cool::MSG::ERROR; break; + + case '6': + case 'f': + case 'F': level = cool::MSG::FATAL; break; + + case '7': + case 'a': + case 'A': level = cool::MSG::ALWAYS; break; + + default : break; // keep cool::MSG::ERROR by default + } + + setOutputLevel( level ); + } + else + { + // Do not modify the verbosity if COOL_MSGLEVEL is not set (bug #40353) + } + + // Create a message stream + m_log.reset( new coral::MessageStream( "CoralApplication" ) ); + log() << coral::Info << "Create a cool::CoralApplication..." + << coral::MessageStream::endmsg; + + //-------------------------------------------- + // 2. Install the COOL signal handler + //-------------------------------------------- + +#ifndef WIN32 + // Install the COOL signal handler + if ( getenv( "COOL_ENABLE_COOLSIGNALHANDLER" ) ) + { + log() << coral::Info << "Enable the COOL signal handler" + << coral::MessageStream::endmsg; +#ifndef __APPLE__ + setup_sigsegv(); +#endif + //seal::Signal::handleFatal ( seal::ProcessInfo::argv()[0] ); + //COUT << "CoralApplication(): SignalHandler ok" << ENDL; + } +#endif + + //-------------------------------------------- + // 3. Create the CORAL connection service + //-------------------------------------------- + + if ( connSvc ) + { + log() << coral::Info << "Use the user-provided CORAL connection service" + << coral::MessageStream::endmsg; + m_connSvc = connSvc; + m_ownConnSvc = false; + } + else + { + log() << coral::Info << "Create a new own CORAL connection service" + << coral::MessageStream::endmsg; + m_connSvc = new coral::ConnectionService(); + m_ownConnSvc = true; + } + + //-------------------------------------------- + // 4. Create the COOL database service + //-------------------------------------------- + + log() << coral::Info << "Create the COOL database service" + << coral::MessageStream::endmsg; + m_dbSvc = new RalDatabaseSvc( *m_connSvc ); + + //-------------------------------------------- + + log() << coral::Info << "Create a cool::CoralApplication... DONE" + << coral::MessageStream::endmsg; + + } + + catch( std::exception& e ) + { + COUT << "ERROR! Standard exception: '" << e.what() << "'" << ENDL; + throw e; + } + + catch( ... ) + { + COUT << "ERROR! Unknown exception caught" << ENDL; + throw; + } + + //COUT << "CoralApplication(): *** END ***" << ENDL; + +} + +//----------------------------------------------------------------------------- + +CoralApplication::~CoralApplication() +{ + log() << coral::Info << "Delete the COOL CoralApplication..." + << coral::MessageStream::endmsg; + log() << coral::Info << "Delete the COOL database service" + << coral::MessageStream::endmsg; + delete m_dbSvc; + m_dbSvc = 0; + //log() << coral::Info << "Purge the CORAL connection pool" + // << coral::MessageStream::endmsg; + //m_connSvc->purgeConnectionPool(); + if ( m_ownConnSvc ) + { + log() << coral::Info << "Delete the CORAL connection service" + << coral::MessageStream::endmsg; + coral::ConnectionService* connSvc = + dynamic_cast< coral::ConnectionService* >( m_connSvc ); + if ( connSvc ) + { + // Hack: ~IConnectionService is protected + delete connSvc; + } + else + { + // This can never happen! We know the type of the own m_connSvc! + std::string msg = "PANIC! m_connSvc is not a coral::ConnectionService!"; + log() << coral::Fatal << msg << coral::MessageStream::endmsg; + throw Exception( msg, "CoralApplication::~CoralApplication" ); + } + } + m_connSvc = 0; + log() << coral::Info << "Delete the COOL CoralApplication... DONE" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +IDatabaseSvc& CoralApplication::databaseService() +{ + return *m_dbSvc; +} + +//----------------------------------------------------------------------------- + +cool::MSG::Level CoralApplication::outputLevel() +{ + coral::MsgLevel coralLevel = coral::MessageStream::msgVerbosity(); + switch ( coralLevel ) { + case coral::Nil: return cool::MSG::NIL; break; + case coral::Fatal: return cool::MSG::FATAL; break; + case coral::Error: return cool::MSG::ERROR; break; + case coral::Warning: return cool::MSG::WARNING; break; + case coral::Info: return cool::MSG::INFO; break; + case coral::Debug: return cool::MSG::DEBUG; break; + case coral::Verbose: return cool::MSG::VERBOSE; break; + case coral::Always: return cool::MSG::ALWAYS; break; + case coral::NumLevels: return cool::MSG::NUM_LEVELS; break; + } + throw Exception( "PANIC! Unknown CORAL MsgLevel value", "CoralApplication" ); +} + +//----------------------------------------------------------------------------- + +void CoralApplication::setOutputLevel( const cool::MSG::Level level ) +{ + coral::MsgLevel coralLevel; + switch ( level ) { + case cool::MSG::NIL: coralLevel=coral::Nil; break; + case cool::MSG::FATAL: coralLevel=coral::Fatal; break; + case cool::MSG::ERROR: coralLevel=coral::Error; break; + case cool::MSG::WARNING: coralLevel=coral::Warning; break; + case cool::MSG::INFO: coralLevel=coral::Info; break; + case cool::MSG::DEBUG: coralLevel=coral::Debug; break; + case cool::MSG::VERBOSE: coralLevel=coral::Verbose; break; + case cool::MSG::ALWAYS: coralLevel=coral::Always; break; + case cool::MSG::NUM_LEVELS: coralLevel=coral::NumLevels; break; + default: + throw Exception( "PANIC! Unknown cool::MSG::Level value", + "CoralApplication" ); + } + coral::MessageStream::setMsgVerbosity( coralLevel ); +} + +//----------------------------------------------------------------------------- + +seal::Context* CoralApplication::context() const +{ + std::stringstream msg; + msg << "COOL is not based on SEAL any longer: please upgrade your user code"; + throw Exception( msg.str(), "CoralApplication" ); +} + +//----------------------------------------------------------------------------- + +coral::IConnectionService& CoralApplication::connectionSvc() const +{ + return *m_connSvc; +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& CoralApplication::log() +{ + *m_log << coral::Info; + return *m_log; +} + +//----------------------------------------------------------------------------- + +/* +// Implementation copied from SEAL Foundation/PluginRefresh/src/main.cpp +void CoralApplication::feedback ( seal::PluginManager::FeedbackData data ) +{ + std::string explanation; + if ( data.error ) + explanation = + seal::StringOps::replace( data.error->explain (), '\n', "\n\t" ); + + if ( getenv ( "COOL_PLUGINMANAGER_DEBUG" ) ) { + if ( data.code == seal::PluginManager::StatusLoading ) + COUT << "INFO: Loading module '" << data.scope << "'" << ENDL; + } + + if ( data.code == seal::PluginManager::ErrorLoadFailure ) + COUT << "WARNING! Module '" << data.scope + << "' failed to load for the following reason: \"" + << explanation << "\"" << ENDL; + + else if ( data.code == seal::PluginManager::ErrorBadModule ) + COUT << "WARNING! Module '" << data.scope + << "' ignored until problems with it are fixed" << ENDL; + + else if ( data.code == seal::PluginManager::ErrorBadCacheFile ) + COUT << "WARNING! Cache file '" << data.scope + << "' is corrupted" << ENDL; + + else if ( data.code == seal::PluginManager::ErrorEntryFailure ) + COUT << "WARNING! Module '" << data.scope + << "' does not have the required entry point: \"" + << explanation << "\"" << ENDL; + + else if ( data.code == seal::PluginManager::ErrorNoFactory ) + COUT << "WARNING! Module '" << data.scope + << "' missing one or more factories for plug-ins" << ENDL; +} +*/ + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/CoralApplication.h b/RelationalCool/src/CoralApplication.h new file mode 100644 index 000000000..be9cb89a8 --- /dev/null +++ b/RelationalCool/src/CoralApplication.h @@ -0,0 +1,84 @@ +// $Id: CoralApplication.h,v 1.9 2008-11-04 11:52:10 avalassi Exp $ +#ifndef RELATIONALCOOL_CORALAPPLICATION_H +#define RELATIONALCOOL_CORALAPPLICATION_H 1 + +// Include files +#include <memory> +#include "CoolKernel/IApplication.h" +#include "CoralBase/MessageStream.h" + +namespace cool +{ + + /** @class CoralApplication CoralApplication.h + * + * CORAL-based implementation of a COOL application class. + * + * This class provides a concrete implementation of the public Application + * class, while hiding from the public API all CORAL-based details. + * + * @author Andrea Valassi + * @date 2007-04-08 + * + */ + + class CoralApplication : public IApplication { + + public: + + /// Constructor from a CORAL ConnectionService (if one is provided, + /// the user is responsible to keep it alive until the application is + /// alive; if none is provided, a new own one is created if necessary). + CoralApplication( coral::IConnectionService* connSvc = 0 ); + + /// Destructor + virtual ~CoralApplication(); + + /// Retrieve a reference to the COOL database service. + IDatabaseSvc& databaseService(); + + /// Get the output level threshold for the message service. + /// *** WARNING: this may actually return a shared (static) value. *** + MSG::Level outputLevel(); + + /// Set the output level threshold for the message service. + /// *** WARNING: this may actually change a shared (static) value. *** + void setOutputLevel( MSG::Level level ); + + /// Get the SEAL context (if any) associated with this application. + /// *** WARNING: throws an exception for applications not using SEAL. *** + seal::Context* context() const; + + /// Get the CORAL connection service (if any) used in this application. + /// *** WARNING: throws an exception for applications not using CORAL. *** + coral::IConnectionService& connectionSvc() const; + + private: + + /// Get a CORAL MessageStream + coral::MessageStream& log(); + + /// Handler of SEAL PluginManager feedback + //static void feedback ( seal::PluginManager::FeedbackData data ); + + /// Plugin label for the technology-independent top-level DatabaseService + //static const std::string& databaseServiceLabel(); + + private: + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// CORAL connection service + coral::IConnectionService* m_connSvc; + + /// Own CORAL connection service? + bool m_ownConnSvc; + + /// COOL database service + cool::IDatabaseSvc* m_dbSvc; + + }; + +} +#endif // RELATIONALCOOL_CORALAPPLICATION_H diff --git a/RelationalCool/src/CoralConnectionServiceProxy.cpp b/RelationalCool/src/CoralConnectionServiceProxy.cpp new file mode 100644 index 000000000..918adf6c3 --- /dev/null +++ b/RelationalCool/src/CoralConnectionServiceProxy.cpp @@ -0,0 +1,48 @@ +// $Id: CoralConnectionServiceProxy.cpp,v 1.3 2008-04-14 15:26:06 avalassi Exp $ + +// Local include files +#include "CoralConnectionServiceProxy.h" +#include "RelationalException.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +CoralConnectionServiceProxy::CoralConnectionServiceProxy( coral::IConnectionService* pConnSvc ) + : m_pConnSvc( pConnSvc ) + , m_mutex() +{ + //std::cout << "Create CoralConnectionServiceProxy " << this + // << " -> " << m_pConnSvc << " ***" << std::endl; +} + +//----------------------------------------------------------------------------- + +CoralConnectionServiceProxy::~CoralConnectionServiceProxy() +{ + //std::cout << "Delete CoralConnectionServiceProxy " << this + // << " -> " << m_pConnSvc << " ***" << std::endl; +} + +//----------------------------------------------------------------------------- + +const coral::IConnectionService* CoralConnectionServiceProxy::getICS() const +{ + if ( m_pConnSvc == 0 ) throw RelationalException( "Null pointer in CoralConnectionServiceProxy", + "CoralConnectionServiceProxy::getICS()" ); + //std::cout << "CoralConnectionServiceProxy::getICS " << m_pConnSvc << std::endl; + return m_pConnSvc; +} + +//----------------------------------------------------------------------------- + +coral::IConnectionService* CoralConnectionServiceProxy::getICS() +{ + if ( m_pConnSvc == 0 ) throw RelationalException( "Null pointer in CoralConnectionServiceProxy", + "CoralConnectionServiceProxy::getICS()" ); + //std::cout << "CoralConnectionServiceProxy::getICS " << m_pConnSvc << std::endl; + return m_pConnSvc; +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/CoralConnectionServiceProxy.h b/RelationalCool/src/CoralConnectionServiceProxy.h new file mode 100644 index 000000000..d0e9404e6 --- /dev/null +++ b/RelationalCool/src/CoralConnectionServiceProxy.h @@ -0,0 +1,122 @@ +// $Id: CoralConnectionServiceProxy.h,v 1.4 2009-01-14 18:57:29 avalassi Exp $ +#ifndef CORALCONNECTIONSERVICEPROXY_H +#define CORALCONNECTIONSERVICEPROXY_H 1 + +// Include files +#include <iostream> +#include <boost/shared_ptr.hpp> +#include <boost/thread.hpp> +#include "RelationalAccess/IConnectionService.h" + +namespace cool +{ + + /** @class CoralConnectionServicePtr CoralConnectionServicePtr.h + * + * Sharable thread-safe proxy to a coral::IConnectionService. + * + * @author Andrea Valassi + * @date 2008-04-10 + */ + + class CoralConnectionServiceProxy : virtual public coral::IConnectionService + { + + public: + + /// Constructor + CoralConnectionServiceProxy( coral::IConnectionService* pConnSvc = 0 ); + + /// Destructor + virtual ~CoralConnectionServiceProxy(); + + /// Get the pointer - throws if the pointer is 0. + const coral::IConnectionService* getICS() const; + + /// Get the pointer - throws if the pointer is 0. + coral::IConnectionService* getICS(); + + /// Reset the pointer. + void resetICS( coral::IConnectionService* pConnSvc = 0 ) + { + //std::cout << "CoralConnectionServiceProxy::resetICS" << std::endl; + boost::mutex::scoped_lock lock( m_mutex ); + m_pConnSvc = pConnSvc; + } + + /** + * Returns a session proxy object for the specified connection string + * and access mode. + */ + coral::ISessionProxy* connect( const std::string& connectionName, + coral::AccessMode accessMode = coral::Update ) + { + boost::mutex::scoped_lock lock( m_mutex ); + return getICS()->connect( connectionName, accessMode );; + } + + /** + * Returns a session proxy object for the specified connection string, role + * and access mode. + */ + coral::ISessionProxy* connect( const std::string& connectionName, + const std::string& asRole, + coral::AccessMode accessMode = coral::Update ) + { + boost::mutex::scoped_lock lock( m_mutex ); + return getICS()->connect( connectionName, asRole, accessMode ); + } + + /** + * Returns the configuration object for the service. + */ + coral::IConnectionServiceConfiguration& configuration() + { + boost::mutex::scoped_lock lock( m_mutex ); + return getICS()->configuration(); + } + + /** + * Cleans up the connection pool from the unused connection, according to + * the policy defined in the configuration. + */ + void purgeConnectionPool() + { + //std::cout << "CoralConnectionServiceProxy::purgeConnectionPool" << std::endl; + boost::mutex::scoped_lock lock( m_mutex ); + return getICS()->purgeConnectionPool(); + } + + /** + * Returns the monitoring reporter + */ + const coral::IMonitoringReporter& monitoringReporter() const + { + boost::mutex::scoped_lock lock( m_mutex ); + return getICS()->monitoringReporter(); + } + + /** + * Returns the object which controls the web cache + */ + coral::IWebCacheControl& webCacheControl() + { + boost::mutex::scoped_lock lock( m_mutex ); + return getICS()->webCacheControl(); + } + + private: + + /// The coral::IConnectionService pointer. + coral::IConnectionService* m_pConnSvc; + + /// The mutex lock (mutable because it must be modified in const methods). + mutable boost::mutex m_mutex; + + }; + + // Type definition + typedef boost::shared_ptr<CoralConnectionServiceProxy> CoralConnectionServiceProxyPtr; + +} +#endif // CORALCONNECTIONSERVICEPTR_H diff --git a/RelationalCool/src/DummyTransactionMgr.cpp b/RelationalCool/src/DummyTransactionMgr.cpp new file mode 100644 index 000000000..305a12aa0 --- /dev/null +++ b/RelationalCool/src/DummyTransactionMgr.cpp @@ -0,0 +1,22 @@ +// $Id: DummyTransactionMgr.cpp,v 1.1 2007-03-28 11:35:40 avalassi Exp $ + +// Local include files +#include "DummyTransactionMgr.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +DummyTransactionMgr::DummyTransactionMgr() +{ +} + +//----------------------------------------------------------------------------- + +DummyTransactionMgr::~DummyTransactionMgr() +{ +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/DummyTransactionMgr.h b/RelationalCool/src/DummyTransactionMgr.h new file mode 100644 index 000000000..d56698a1b --- /dev/null +++ b/RelationalCool/src/DummyTransactionMgr.h @@ -0,0 +1,74 @@ +// $Id: DummyTransactionMgr.h,v 1.6 2008-11-04 11:52:10 avalassi Exp $ +#ifndef RELATIONALCOOL_DUMMYTRANSACTIONMGR_H +#define RELATIONALCOOL_DUMMYTRANSACTIONMGR_H + +// Local include files +#include "IRelationalTransactionMgr.h" +#include "RelationalException.h" + +namespace cool { + + /** @class RelationalTransactionMgr RelationalTransactionMgr.h + * + * Dummy manager of relational database transactions. + * + * This manager is only used in read-only connections: the only non-dummy + * operation it performs is to throw if a read-write transaction is open! + * + * @author Andrea Valassi + * @date 2007-03-28 + */ + + class DummyTransactionMgr: public IRelationalTransactionMgr + { + + public: + + /// Destructor + virtual ~DummyTransactionMgr(); + + /// Standard constructor + DummyTransactionMgr(); + + void setAutoTransactions( bool ) {} + bool autoTransactions() const { return true; } + + protected: + + /// Start a transaction + void start( bool readOnly ) + { + if ( !readOnly ) + throw DatabaseOpenInReadOnlyMode( "DummyTransactionManager" ); + m_isActive = true; + }; + + /// Commit a transaction + void commit() + { + m_isActive = false; + }; + + /// Rollback a transaction + void rollback() + { + m_isActive = false; + }; + + /// Is the transaction active? + bool isActive() + { + return m_isActive; + }; + + private: + + /// Is the transaction active? + bool m_isActive; + + }; + +} + +#endif // RELATIONALCOOL_DUMMYTRANSACTIONMGR_H + diff --git a/RelationalCool/src/HvsPathHandler.cpp b/RelationalCool/src/HvsPathHandler.cpp new file mode 100644 index 000000000..5a3c091f4 --- /dev/null +++ b/RelationalCool/src/HvsPathHandler.cpp @@ -0,0 +1,160 @@ +// $Id: HvsPathHandler.cpp,v 1.8 2007-10-30 18:06:25 avalassi Exp $ + +// Include files +#include <sstream> + +// Local include files +#include "HvsPathHandler.h" +#include "HvsPathHandlerException.h" +#include "uppercaseString.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +HvsPathHandler::HvsPathHandler() { +} + +//----------------------------------------------------------------------------- + +HvsPathHandler::~HvsPathHandler() { +} + +//----------------------------------------------------------------------------- + +const std::pair<std::string, std::string> +HvsPathHandler::splitFullPath( const std::string& fullPath ) +{ + if ( fullPath == rootFullPath() ) { + std::ostringstream msg; + msg << "Full path '" << fullPath + << "' is the root path: it has no parent and cannot be split"; + throw HvsPathHandlerException( msg.str() ); + } + if( fullPath != removeTrailingSeparators( fullPath ) ) { + std::ostringstream msg; + msg << "Full path '" << fullPath << "' contains trailing separators"; + throw HvsPathHandlerException( msg.str() ); + } + if( fullPath != removeDoubleSeparators( fullPath ) ) { + std::ostringstream msg; + msg << "Full path '" << fullPath << "' contains double separators"; + throw HvsPathHandlerException( msg.str() ); + } + { + std::string allowedChar = "/ABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890.-"; + const std::string ucName = uppercaseString( fullPath ); + std::string::size_type pos = ucName.find_first_not_of( allowedChar ); + if ( pos != ucName.npos ) + { + std::ostringstream msg; + msg << "Full path '" << fullPath << "' contains invalid character '" + << fullPath.substr( pos, 1 ) << "'"; + throw HvsPathHandlerException( msg.str() ); + } + } + std::string newPath = fullPath; + std::string sep( 1, separator() ); + std::string::size_type lastPos = newPath.rfind( sep ); + if ( lastPos == std::string::npos ) { + std::ostringstream msg; + msg << "Full path '" << fullPath + << "' does not contain the separator character '" << sep << "'"; + throw HvsPathHandlerException( msg.str() ); + } + std::string parent = newPath.substr( 0, lastPos ); + std::string child = newPath.substr( lastPos+1 ); + if( parent == rootUnresolvedName() ) parent=rootFullPath(); + //std::cout << "Split '" << fullPath << "' into '" << parent + // << "' and '" << child << "'" << std::endl; + return std::pair<std::string,std::string>( parent, child ); +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> +HvsPathHandler::decodeFullPath( const std::string& fullPath ) +{ + std::string newPath = fullPath; + std::vector<std::string> nodeRList; + while ( newPath != rootFullPath() ) { + const std::pair<std::string, std::string> + newPair = splitFullPath( newPath ); + newPath = newPair.first; + nodeRList.push_back( newPair.second ); + } + std::vector<std::string> nodeList; + nodeList.push_back( rootUnresolvedName() ); + //std::cout << "Decode '" << fullPath + // << "' into '" << rootUnresolvedName() << "'"; + std::vector<std::string>::reverse_iterator node; + for ( node = nodeRList.rbegin(); node != nodeRList.rend(); node++ ) { + //std::cout << ", '" << *node << "'"; + nodeList.push_back( *node ); + } + //std::cout << std::endl; + return nodeList; +} + +//----------------------------------------------------------------------------- + +const std::string +HvsPathHandler::encodeFullPath( const std::vector<std::string>& nodeList ) +{ + std::string fullPath; + std::vector<std::string>::const_iterator node; + for ( node = nodeList.begin(); node != nodeList.end(); node++ ) { + if ( node == nodeList.begin() ) { + if ( *node != rootUnresolvedName() ) { + std::ostringstream msg; + msg << "The first node name '" << *node + << "' is not the root node name '" << rootUnresolvedName() << "'"; + throw HvsPathHandlerException( msg.str() ); + } + } else { + fullPath += std::string( 1, separator() ); + } + if ( (*node).find(std::string(1,separator())) != std::string::npos ) { + std::ostringstream msg; + msg << "Unresolved node name '" << *node + << "' should not contain the separator '" << separator() << "'"; + throw HvsPathHandlerException( msg.str() ); + } + fullPath += *node; + } + if ( fullPath == rootUnresolvedName() ) fullPath=rootFullPath(); + return fullPath; +} + +//----------------------------------------------------------------------------- + +const std::string +HvsPathHandler::removeTrailingSeparators( const std::string& aString ) +{ + std::string newString = aString; + while ( true ) { + if ( newString.size() <=1 ) return newString; + std::string sep( 1, separator() ); + std::string::size_type lastPos = newString.rfind( sep ); + if ( lastPos != newString.size()-1 ) return newString; + newString = newString.substr( 0, lastPos ); + } +} + +//----------------------------------------------------------------------------- + +const std::string +HvsPathHandler::removeDoubleSeparators( const std::string& aString ) +{ + std::string newString = aString; + std::string doubleSep( 1, separator() ); + doubleSep += doubleSep; + std::string::size_type pos; + while( ( pos = newString.find(doubleSep) ) != std::string::npos ) { + newString = newString.substr( 0, pos ) + newString.substr( pos+1 ); + } + return newString; +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/HvsPathHandler.h b/RelationalCool/src/HvsPathHandler.h new file mode 100644 index 000000000..df3660ab4 --- /dev/null +++ b/RelationalCool/src/HvsPathHandler.h @@ -0,0 +1,102 @@ +// $Id: HvsPathHandler.h,v 1.7 2008-11-04 10:59:47 avalassi Exp $ +#ifndef RELATIONALCOOL_HVSPATHHANDLER_H +#define RELATIONALCOOL_HVSPATHHANDLER_H 1 + +// Include files +#include <map> +#include <string> +#include <vector> + +namespace cool +{ + + /** @class HvsPathHandler HvsPathHandler.h + * + * Handler of hierarchical path names for HVS. + * + * This class is used to encode, decode and validate full path names + * of the form "/node1/node2/node3" in a UNIX-like node hierarchy. + * + * The handler is also used in the COOL conditions database implementation: + * any features specific to COOL may be changed by virtual inheritance. + * + * The documentation for the class is written assuming "/" is the + * separator character, but this is hardcoded in a single clas variable. + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2004-12-09 + */ + + class HvsPathHandler { + + friend class HvsPathHandlerTest; + + public: + + /// Standard constructor. + HvsPathHandler(); + + /// Destructor. + virtual ~HvsPathHandler(); + + /// Return the separator character '/'. + char separator() const + { + return '/'; + } + + /// Return the unresolved root name "". + const std::string rootUnresolvedName() const + { + return ""; + } + + /// Return the full root path "/". + const std::string rootFullPath() const + { + return rootUnresolvedName() + std::string( 1, separator() ); + } + + /// Split a full HVS path into parent full path and child unresolved name, + /// e.g. split "/a/b/c" into "/a/b" and "c". + /// Special case: "/a" is split into "/" and "a". + /// Throw an exception if the path has double or trailing separators. + /// Throw an exception if the path does not start by "/". + /// Throw an exception if the path is the root folder "/". + const std::pair<std::string, std::string> + splitFullPath( const std::string& fullPath ); + + /// Decode a full HVS path into a list of hierarchy node unresolved names, + /// e.g. split "/a/b/c" into "", "a", "b" and "c". + /// Throw an exception if the path has double or trailing separators. + /// Throw an exception if the path does not start by "/" + /// (special case: "/" represents the root folder ""). + const std::vector<std::string> + decodeFullPath( const std::string& fullPath ); + + /// Encode a list of unresolved hierarchy node names into a full HVS path, + /// e.g. encode "", "a", "b", "c" into "/a/b/c". + /// Throw an exception if any node name contains a separator. + /// Throw an exception if the first node is not the root node "". + const std::string + encodeFullPath( const std::vector<std::string>& nodeList ); + + private: + + /// Remove trailing separators from a string, + /// e.g. simplify "/a//b/c/" into "/a//b/c/". + /// Special case: "/" is left as "/". + const std::string + removeTrailingSeparators( const std::string& aString ); + + /// Remove double separators from a string, + /// e.g. simplify "/a//b/c" into "/a/b/c". + const std::string + removeDoubleSeparators( const std::string& aString ); + + }; + +} + +#endif // RELATIONALCOOL_HVSPATHHANDLER_H + diff --git a/RelationalCool/src/HvsPathHandlerException.h b/RelationalCool/src/HvsPathHandlerException.h new file mode 100644 index 000000000..e8ca2bcd4 --- /dev/null +++ b/RelationalCool/src/HvsPathHandlerException.h @@ -0,0 +1,33 @@ +// $Id: HvsPathHandlerException.h,v 1.1 2006-03-21 12:00:18 avalassi Exp $ +#ifndef RELATIONALCOOL_HVSPATHHANDLEREXCEPTION_H +#define RELATIONALCOOL_HVSPATHHANDLEREXCEPTION_H 1 + +// Include files +#include <string> +#include "CoolKernel/Exception.h" + +namespace cool +{ + + /** @class HvsPathHandlerException + * + * Exception thrown by the HvsPathHandler class. + */ + + class HvsPathHandlerException : public Exception { + + public: + + /// Constructor + HvsPathHandlerException( const std::string& message ) + : Exception( message, "HvsPathHandler" ) {} + + /// Destructor + virtual ~HvsPathHandlerException() throw() {} + + }; + +} + +#endif // RELATIONALCOOL_HVSPATHHANDLEREXCEPTION_H + diff --git a/RelationalCool/src/HvsTagRecord.h b/RelationalCool/src/HvsTagRecord.h new file mode 100644 index 000000000..84cd1ce46 --- /dev/null +++ b/RelationalCool/src/HvsTagRecord.h @@ -0,0 +1,131 @@ +// $Id: HvsTagRecord.h,v 1.12 2008-11-04 11:52:10 avalassi Exp $ +#ifndef COOLKERNEL_HVSTAGRECORD_H +#define COOLKERNEL_HVSTAGRECORD_H + +// Include files +#include "CoolKernel/Time.h" +#include "IHvsTagRecord.h" + +// TEMPORARY - debug unknown exception on Windows +//#include <iostream> + +namespace cool { + + /** @class HvsTagRecord HvsTagRecord.h + * + * Concrete implementation of an IHvsTagRecord. + * + * @author Andrea Valassi + * @date 2006-03-24 + */ + + class HvsTagRecord : public IHvsTagRecord { + + public: + + /// Destructor + virtual ~HvsTagRecord() {} + + /// System-assigned tag ID. + UInt32 id() const + { + return m_id; + } + + /// Tag scope: node where the tag is defined. + UInt32 nodeId() const + { + return m_nodeId; + } + + /// Tag name. + const std::string& name() const + { + return m_name; + } + + /// Tag lock status. + HvsTagLock::Status lockStatus() const + { + return m_lockStatus; + } + + /// Tag description. + const std::string& description() const + { + return m_description; + } + + /// Tag insertion time into the database (creation time). + const ITime& insertionTime() const + { + return m_insertionTime; + } + + /// Constructor from all data members. + HvsTagRecord( UInt32 id, + UInt32 nodeId, + const std::string& name, + HvsTagLock::Status lockStatus, + const std::string& description, + const ITime& insertionTime ) + : m_id( id ) + , m_nodeId( nodeId ) + , m_name( name ) + , m_lockStatus( lockStatus ) + , m_description( description ) + , m_insertionTime( insertionTime ) + { + // TEMPORARY - debug unknown exception on Windows + //std::cout << "*** HvsTagRecord - CONSTRUCTOR" << std::endl; + } + + /// Copy constructor. + /// AV - Added IHvsTagRecord to avoid gcc344 warning on copy constructor + /// AV - To be tested: would this solve the unknown Windows exception??? + HvsTagRecord( const HvsTagRecord& rhs ) + : IHvsTagRecord() + , m_id( rhs.m_id ) + , m_nodeId( rhs.m_nodeId ) + , m_name( rhs.m_name ) + , m_lockStatus( rhs.m_lockStatus ) + , m_description( rhs.m_description ) + , m_insertionTime( rhs.m_insertionTime ) + { + // TEMPORARY - debug unknown exception on Windows + //std::cout << "*** HvsTagRecord - COPY CONSTRUCTOR" << std::endl; + } + + private: + + /// Standard constructor is private + HvsTagRecord(); + + /// Assignment operator is private + HvsTagRecord& operator=( const HvsTagRecord& rhs ); + + private: + + /// System-assigned tag ID. + UInt32 m_id; + + /// Tag scope: node where the tag is defined. + UInt32 m_nodeId; + + /// Tag name. + std::string m_name; + + /// Tag lock status. + HvsTagLock::Status m_lockStatus; + + /// Tag description. + std::string m_description; + + /// Insertion time into the database. + Time m_insertionTime; + + }; + +} + +#endif // COOLKERNEL_HVSTAGRECORD_H diff --git a/RelationalCool/src/IHvsTagMgr.h b/RelationalCool/src/IHvsTagMgr.h new file mode 100644 index 000000000..90cf9c07f --- /dev/null +++ b/RelationalCool/src/IHvsTagMgr.h @@ -0,0 +1,207 @@ +// $Id: IHvsTagMgr.h,v 1.7 2008-11-04 11:05:22 avalassi Exp $ +#ifndef COOLKERNEL_IHVSTAGMGR_H +#define COOLKERNEL_IHVSTAGMGR_H + +// Include files +#include <string> +#include <vector> +#include "CoolKernel/IHvsNode.h" + +namespace cool { + + // Forward declarations + class HvsTagRecord; + //class IHvsTag; + //class IHvsTagRecord; + + /** @class IHvsTagMgr IHvsTagMgr.h + * + * Abstract interface for the manager of one HVS tag tree. + * + * An HVS tag represents a tagged version of one HVS node. + * It can be uniquely identified by the tag name and the node name or ID. + * Each tag is also assigned a unique integer ID by the system. + * + * The terms "tag" and "tag name" are NOT equivalent. + * A given tag name can be used either for only one inner node or for any + * number of leaf nodes: the same tag name cannot be used for more than + * one inner node, or for one inner node and one or more leaf nodes. + * Users can reserve the use of a given tag name for either type of node. + * + * TEMPORARY! A tag name cannot be used YET for more than one leaf node! + * + * For inner nodes, an HVS tag represents a collection + * of versions of (some of its) children nodes. + * For leaf nodes, an HVS tag typically represents a collection + * of versions of (some of the) data associated to the leaf node, + * such as a collection of IOVs in a conditions data folder. + * + * When different tags with the same name exist in different leaf nodes, + * they are assigned different integer IDs so that they can be renamed + * independently while keeping their distinct ID and properties. + * + * @author Andrea Valassi + * @date 2006-03-02 + */ + + class IHvsTagMgr { + + public: + + /// Destructor + virtual ~IHvsTagMgr() {}; + + /// This method does not handle transactions. + /// Create a tag in an HVS node. + /// Throws TagExists if the tag already exists (in this or another node). + virtual const HvsTagRecord + createTag( UInt32 nodeId, + const std::string& tagName, + const std::string& description = "" ) const = 0; + + /// This method does not handle transactions. + /// Delete a tag in an HVS node. + virtual void deleteTag( UInt32 nodeId, + const std::string& tagName ) const = 0; + + /* + /// Has this tag name been reserved for a node type? + /// [NB: this may be true even if it is not used in any node.] + /// Tag names, except for "HEAD", are case sensitive. + /// Returns true for the reserved tags "" and "HEAD". + virtual bool existsTagName( const std::string& tagName ) const = 0; + */ + + /// Return the type of node (inner/leaf) where this tag name can be used. + /// Tag names, except for "HEAD", are case sensitive. + /// Throws TagNameNotFound if the tag name does not exist. + virtual IHvsNode::Type tagNameScope( const std::string& tagName ) const = 0; + + /// Does a tag with this name exist (in any node)? + /// Tag names, except for "HEAD", are case sensitive. + /// Returns true for the reserved tags "" and "HEAD". + virtual bool existsTag( const std::string& tagName ) const = 0; + + /* + /// TEMPORARY! A tag name cannot be used YET for more than one leaf node! + /// Return the ID of the node where the tag is defined. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + virtual UInt32 taggedNodeId( const std::string& tagName ) const = 0; + + /// TEMPORARY! A tag name cannot be used YET for more than one leaf node! + /// Return the name of the node where the tag is defined. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + virtual const std::string taggedNode( const std::string& tagName ) const = 0; + + /// Return the IDs of the nodes where the tag is defined. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + virtual const std::vector<UInt32> + taggedNodeIds( const std::string& tagName ) const = 0; + */ + + /// Return the names of the nodes where the tag is defined. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + virtual const std::vector<std::string> + taggedNodes( const std::string& tagName ) const = 0; + + /* + /// Does a tag with this name exist in the given node? + /// Tag names, except for "HEAD", are case sensitive. + /// Returns true for the reserved tags "" and "HEAD". + virtual bool existsTag( const std::string& tagName, + UInt32 nodeId ) = 0; + */ + + /// Find a tag record by nodeId and tag name. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + virtual const HvsTagRecord findTagRecord( UInt32 nodeId, + const std::string& tagName ) const = 0; + + /// Find a tag record by nodeId and tagId. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + virtual const HvsTagRecord findTagRecord( UInt32 nodeId, + UInt32 tagId ) const = 0; + + /* + /// Does a tag with this name exist in the given node? + /// Tag names, except for "HEAD", are case sensitive. + /// Returns true for the reserved tags "" and "HEAD". + virtual bool existsTag( const std::string& tagName, + const std::string& nodeName ) = 0; + + /// Find a tag record by name and node name. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist in the given node. + virtual const IHvsTagRecord + findTagRecord( const std::string& tagName, + const std::string& nodeName ) const = 0; + */ + + /* + /// Find a tag by name and nodeID. + /// Throws TagNotFound if the tag does not exist. + virtual const IHvsTag& findTag( const std::string& tagName, + UInt32 nodeId ) const = 0; + + /// Find a tag by name and node name. + /// Throws TagNotFound if the tag does not exist. + virtual const IHvsTag& findTag( const std::string& tagName, + const std::string& nodeName ) const = 0; + */ + + /// Create a relation between tags for a pair of parent/child nodes. + /// Create the parent tag in the parent node if not defined yet. + /// Create the child tag in the child node if not defined yet. + /// Throws ReservedHeadTag if one of the two tags is a HEAD tag. + /// Throws NodeIsSingleVersion if either node does not support versioning. + /// Throws NodeRelationNotFound if the nodes are not parent and child. + /// Throws TagExists if either tag is already used in another node. + /// Throws TagRelationExists if a relation to a child tag already exists. + virtual void createTagRelation( UInt32 parentNodeId, + const std::string& parentTagName, + UInt32 childNodeId, + const std::string& childTagName ) const = 0; + + /// Delete the relation between a parent tag node and a child tag. + /// Delete the parent tag if not related to another parent/child tag. + /// Delete the child tag if not related to another tag or IOVs. + /// Throws ReservedHeadTag if the parent tag is a HEAD tag. + /// Throws TagNotFound if the parent tag does not exist in the parent node. + /// Throws TagRelationNotFound if the parent tag has no related child tag. + /// TEMPORARY? - returns the tagId of the deleted related child tag + virtual UInt32 deleteTagRelation( UInt32 parentNodeId, + const std::string& parentTagName, + UInt32 childNodeId ) const = 0; + + /// Find the child node tag associated to the given parent node tag. + /// Throws ReservedHeadTag if the parent tag is a HEAD tag. + /// Throws TagNotFound if the parent tag does not exist in the parent node. + /// Throws TagRelationNotFound if the parent tag has no related child tag. + virtual UInt32 findTagRelation( UInt32 parentNodeId, + const std::string& parentTagName, + UInt32 childNodeId ) const = 0; + + /// Main HVS method: determine the descendant node tag that is related to + /// the given ancestor tag (assumed to be defined in an ancestor node). + /// The corresponding ancestor node is also internally determined. + /// The ancestor tag is returned if defined directly in the descendant. + /// Throws ReservedHeadTag if the ancestor tag is a HEAD tag. + /// Throws TagNotFound if the tag does not exist in any inner node. + /// Throws NodeRelationNotFound if the inner node where the ancestor tag + /// is defined is not an ancestor of the descendant node. + /// Throws TagRelationNotFound if no hierarchical tag relation exists. + virtual UInt32 resolveTag( const std::string& ancestorTagName, + UInt32 descendantNodeId ) const = 0; + + }; + +} + +#endif // COOLKERNEL_IHVSTAGMGR_H + diff --git a/RelationalCool/src/IHvsTagRecord.h b/RelationalCool/src/IHvsTagRecord.h new file mode 100644 index 000000000..0b4eb0ee0 --- /dev/null +++ b/RelationalCool/src/IHvsTagRecord.h @@ -0,0 +1,70 @@ +// $Id: IHvsTagRecord.h,v 1.6 2008-11-04 11:52:10 avalassi Exp $ +#ifndef COOLKERNEL_IHVSTAGRECORD_H +#define COOLKERNEL_IHVSTAGRECORD_H + +// Include files +#include <string> +#include "CoolKernel/IHvsNode.h" +#include "CoolKernel/Time.h" + +namespace cool { + + /** @class IHvsTagRecord IHvsTagRecord.h + * + * Read-only abstract interface to one tag in an HVS tag tree. + * + * An HVS tag represents a tagged version of one HVS node. + * It can be uniquely identified by the tag name and the node name or ID. + * Each tag is also assigned a unique integer ID by the system. + * + * The terms "tag" and "tag name" are NOT equivalent. + * A given tag name can be used either for only one inner node or for any + * number of leaf nodes: the same tag name cannot be used for more than + * one inner node, or for one inner node and one or more leaf nodes. + * Users can reserve the use of a given tag name for either type of node. + * + * TEMPORARY! A tag name cannot be used YET for more than one leaf node! + * + * For inner nodes, an HVS tag represents a collection + * of versions of (some of its) children nodes. + * For leaf nodes, an HVS tag typically represents a collection + * of versions of (some of the) data associated to the leaf node, + * such as a collection of IOVs in a conditions data folder. + * + * When different tags with the same name exist in different leaf nodes, + * they are assigned different integer IDs so that they can be renamed + * independently while keeping their distinct ID and properties. + * + * @author Andrea Valassi + * @date 2006-03-03 + */ + + class IHvsTagRecord { + + public: + + /// System-assigned tag ID. + virtual UInt32 id() const = 0; + + /// Tag scope: node where the tag is defined. + virtual UInt32 nodeId() const = 0; + + /// Tag name. + virtual const std::string& name() const = 0; + + /// Tag description. + virtual const std::string& description() const = 0; + + /// Tag insertion time into the database (creation time). + virtual const ITime& insertionTime() const = 0; + + protected: + + /// Destructor. + virtual ~IHvsTagRecord() {} + + }; + +} + +#endif // COOLKERNEL_IHVSTAGRECORD_H diff --git a/RelationalCool/src/IRelationalBulkOperation.h b/RelationalCool/src/IRelationalBulkOperation.h new file mode 100644 index 000000000..c9bdc69cc --- /dev/null +++ b/RelationalCool/src/IRelationalBulkOperation.h @@ -0,0 +1,28 @@ +#ifndef RELATIONALCOOL_IRELATIONALBULKOPERATION_H +#define RELATIONALCOOL_IRELATIONALBULKOPERATION_H + +namespace cool { + + /** + * Class IRelationalBulkOperation + * + * Abstract interface for the execution of bulk operations. + */ + + class IRelationalBulkOperation { + + public: + + /// Destructor + virtual ~IRelationalBulkOperation() {} + + /// Processes the next iteration + virtual void processNextIteration() = 0; + + /// Flushes the data on the client side to the server. + virtual void flush() = 0; + + }; + +} +#endif diff --git a/RelationalCool/src/IRelationalCursor.h b/RelationalCool/src/IRelationalCursor.h new file mode 100644 index 000000000..b3b31823c --- /dev/null +++ b/RelationalCool/src/IRelationalCursor.h @@ -0,0 +1,37 @@ +#ifndef RELATIONALCOOL_IRELATIONALCURSOR_H +#define RELATIONALCOOL_IRELATIONALCURSOR_H + +// Include files +#include "CoralBase/AttributeList.h" + +namespace cool +{ + + /** + * Class IRelationalCursor. + * + * Abstract interface for a query cursor. + */ + + class IRelationalCursor + { + + public: + + /// Destructor + virtual ~IRelationalCursor() {} + + /// Positions the cursor to the next available row in the result set. + /// If there are no more rows in the result set false is returned. + virtual bool next() = 0; + + /// Returns a reference to the output buffer holding the last row fetched. + virtual const coral::AttributeList& currentRow() const = 0; + + /// Explicitly closes the cursor, releasing the resources on the server. + virtual void close() = 0; + + }; + +} +#endif diff --git a/RelationalCool/src/IRelationalQueryDefinition.h b/RelationalCool/src/IRelationalQueryDefinition.h new file mode 100644 index 000000000..fa7d858b2 --- /dev/null +++ b/RelationalCool/src/IRelationalQueryDefinition.h @@ -0,0 +1,135 @@ +// $Id: IRelationalQueryDefinition.h,v 1.7 2008-11-04 11:52:10 avalassi Exp $ +#ifndef RELATIONALCOOL_IRELATIONALQUERYDEFINITION_H +#define RELATIONALCOOL_IRELATIONALQUERYDEFINITION_H + +// Include files +#include <iostream> +#include <string> +#include <vector> +#include "CoolKernel/IRecord.h" + +namespace cool { + + //-------------------------------------------------------------------------- + + /** @class RelationalQueryDefinition RelationalQueryDefinition.h + * + * Abstract interface to a relational query definition. + * + * @author Andrea Valassi + * @date 2007-06-19 + */ + + class IRelationalQueryDefinition { + + public: + + class ISelectItem + { + public: + virtual ~ISelectItem() {} + virtual bool isSubquery() const = 0; + virtual const std::string& expression() const = 0; + //virtual const IRelationalQueryDefinition& subquery() const = 0; + virtual const std::string& alias() const = 0; + virtual const ISelectItem* clone() const = 0; + }; + + class IFromItem + { + public: + virtual ~IFromItem() {} + virtual bool isSubquery() const = 0; + virtual const std::string& expression() const = 0; + virtual const IRelationalQueryDefinition& subquery() const = 0; + virtual const std::string& alias() const = 0; + virtual const IFromItem* clone() const = 0; + }; + + class IGroupItem + { + public: + virtual ~IGroupItem() {} + virtual const std::string& expression() const = 0; + virtual const IGroupItem* clone() const = 0; + }; + + class IOrderItem + { + public: + virtual ~IOrderItem() {} + virtual const std::string& expression() const = 0; // may end in ASC/DESC + virtual const IOrderItem* clone() const = 0; + }; + + /// Destructor. + virtual ~IRelationalQueryDefinition() {} + + /// Clone this query definition. + virtual const IRelationalQueryDefinition* clone() const = 0; + + /// Get the hint in the format "/*+ hints */" + /// ("SELECT /*+ hints */ expr1 alias1, expr2 alias2, ..."). + virtual const std::string& getHint() const = 0; + + /// Get the SELECT list size + /// ("SELECT expr1 alias1, expr2 alias2, ..."). + virtual unsigned getSelectSize() const = 0; + + /// Get a SELECT list item + /// ("SELECT expr1 alias1, expr2 alias2, ..."). + virtual const ISelectItem& getSelectItem( unsigned item ) const = 0; + + /// Get the FROM clause size + /// ("FROM table1 alias1, table2 alias2, ..."). + virtual unsigned getFromSize() const = 0; + + /// Get a FROM clause item + /// ("FROM table1 alias1, table2 alias2, ..."). + virtual const IFromItem& getFromItem( unsigned item ) const = 0; + + /// Get the WHERE clause ("WHERE ..."). + virtual const std::string& getWhereClause() const = 0; + + /// Get the GROUP BY clause size + /// ("GROUP BY expr1, expr2..."). + virtual unsigned getGroupSize() const = 0; + + /// Get a GROUP BY clause item + /// ("GROUP BY expr1, expr2..."). + virtual const IGroupItem& getGroupItem( unsigned item ) const = 0; + + /// Get the ORDER BY clause size + /// ("ORDER BY expr1, expr2..."). + virtual unsigned getOrderSize() const = 0; + + /// Get a ORDER BY clause item + /// ("ORDER BY expr1, expr2..."). + virtual const IOrderItem& getOrderItem( unsigned item ) const = 0; + + /// Get the bind variables. + /// Bind variables are not necessary here if this is a subquery definition. + virtual const IRecord& getBindVariables() const = 0; + + /// Get the result set specification. + /// The result set spec is ignored if this is a subquery definition. + virtual const IRecordSpecification& getResultSetSpecification() const = 0; + + /// Print the relational query definition to an output stream. + virtual std::ostream& print( std::ostream& s ) const = 0; + + }; + + //-------------------------------------------------------------------------- + + inline std::ostream& operator<<( std::ostream& s, + const IRelationalQueryDefinition& def ) + { + return def.print( s ); + } + + //-------------------------------------------------------------------------- + +} + +#endif // RELATIONALCOOL_IRELATIONALQUERYDEFINITION_H diff --git a/RelationalCool/src/IRelationalTransactionMgr.h b/RelationalCool/src/IRelationalTransactionMgr.h new file mode 100644 index 000000000..f4701db67 --- /dev/null +++ b/RelationalCool/src/IRelationalTransactionMgr.h @@ -0,0 +1,46 @@ +// $Id: IRelationalTransactionMgr.h,v 1.3 2008-11-04 11:52:10 avalassi Exp $ +#ifndef RELATIONALCOOL_IRELATIONALTRANSACTIONMGR_H +#define RELATIONALCOOL_IRELATIONALTRANSACTIONMGR_H + +namespace cool { + + /** @class IRelationalTransactionMgr IRelationalTransactionMgr.h + * + * Abstract interface for a manager of relational database transactions. + * + * @author Andrea Valassi + * @date 2006-03-10 + */ + + class IRelationalTransactionMgr { + + friend class RelationalTransaction; + + public: + + /// Destructor + virtual ~IRelationalTransactionMgr() {}; + + /// Is the transaction active? + virtual bool isActive() = 0; + + virtual void setAutoTransactions( bool flag ) = 0; + virtual bool autoTransactions() const = 0; + + //protected: + + /// Start a transaction + virtual void start( bool readOnly ) = 0; + + /// Commit a transaction + virtual void commit() = 0; + + /// Rollback a transaction + virtual void rollback() = 0; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALTRANSACTIONMGR_H + diff --git a/RelationalCool/src/IteratorException.h b/RelationalCool/src/IteratorException.h new file mode 100644 index 000000000..568397a3c --- /dev/null +++ b/RelationalCool/src/IteratorException.h @@ -0,0 +1,150 @@ +// $Id: IteratorException.h,v 1.6 2007-03-30 15:48:15 avalassi Exp $ +#ifndef RELATIONALCOOL_ITERATOREXCEPTION_H +#define RELATIONALCOOL_ITERATOREXCEPTION_H 1 + +// Include files +#include "CoolKernel/Exception.h" + +namespace cool +{ + //-------------------------------------------------------------------------- + + /** @class IteratorHasNotStarted + * + * Exception thrown when an invalid operation is attempted on an iterator + * that has not been started yet. + * + */ + + class IteratorHasNotStarted : public Exception { + + public: + + /// Constructor + explicit IteratorHasNotStarted( const std::string& methodName ) + : Exception( "The iterator has not been started yet", methodName ) {} + + /// Destructor + virtual ~IteratorHasNotStarted() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class IteratorIsActive + * + * Exception thrown when an invalid operation is attempted on an iterator + * that has already retrieved some rows. + * + */ + + class IteratorIsActive : public Exception { + + public: + + /// Constructor + explicit IteratorIsActive( const std::string& methodName ) + : Exception + ( "The iterator has already retrieved some rows and cannot be reused", + methodName ) {} + + /// Destructor + virtual ~IteratorIsActive() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class IteratorIsClosed + * + * Exception thrown when an invalid operation is attempted on an iterator + * that has already ben closed. + * + */ + + class IteratorIsClosed : public Exception { + + public: + + /// Constructor + explicit IteratorIsClosed( const std::string& methodName ) + : Exception( "The iterator has already been closed and cannot be reused", + methodName ) {} + + /// Destructor + virtual ~IteratorIsClosed() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class IteratorHasNoCurrentItem + * + * Exception thrown when attempting to retrieve the current item from an + * iterator with no current item. + * + */ + + class IteratorHasNoCurrentItem : public Exception { + + public: + + /// Constructor + explicit IteratorHasNoCurrentItem( const std::string& methodName ) + : Exception( "The iterator has no current item", methodName ) {} + + /// Destructor + virtual ~IteratorHasNoCurrentItem() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class IteratorHasNoNextItem + * + * Exception thrown when attempting to retrieve the next item from an + * iterator with no next item. + * + */ + + class IteratorHasNoNextItem : public Exception { + + public: + + /// Constructor + explicit IteratorHasNoNextItem( const std::string& methodName ) + : Exception( "The iterator has no next item", methodName ) {} + + /// Destructor + virtual ~IteratorHasNoNextItem() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class TooManyIterators + * + * Exception thrown when attempting to use two 'live' iterators + * at the same time (this would keep two open server cursors). + * + */ + + class TooManyIterators : public Exception { + + public: + + /// Constructor + explicit TooManyIterators( const std::string& methodName ) + : Exception( "An iterator is already open in this IDatabase", + methodName ) {} + + /// Destructor + virtual ~TooManyIterators() throw() {} + + }; + + //-------------------------------------------------------------------------- + +} + +#endif // RELATIONALCOOL_ITERATOREXCEPTION_H diff --git a/RelationalCool/src/ManualTransaction.cpp b/RelationalCool/src/ManualTransaction.cpp new file mode 100644 index 000000000..8082c492e --- /dev/null +++ b/RelationalCool/src/ManualTransaction.cpp @@ -0,0 +1,61 @@ +// $Id: ManualTransaction.cpp,v 1.4 2009-01-06 12:30:07 avalassi Exp $ +#ifdef COOL280 + +// Include files +#include <string> +#include <iostream> + +// Local include files +#include "IRelationalTransactionMgr.h" +#include "ManualTransaction.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +ManualTransaction::ManualTransaction +( const boost::shared_ptr<IRelationalTransactionMgr>& transactionMgr, + bool readOnly ) + : m_transactionMgr( transactionMgr ) +{ + std::string msg; + if( readOnly ) msg = "read-only transaction"; + else msg = "read-write transaction"; + m_transactionMgr->start( readOnly ); +} + +//----------------------------------------------------------------------------- + +ManualTransaction::~ManualTransaction() +{ + rollback(); +} + +//----------------------------------------------------------------------------- + +void ManualTransaction::commit() +{ + // reset the transaction manager to auto-transaction mode -- this needs + // to be done first, because the commit would otherwise be ignored + m_transactionMgr->setAutoTransactions( true ); + if ( m_transactionMgr->isActive() ) { + m_transactionMgr->commit(); + } +} + +//----------------------------------------------------------------------------- + +void ManualTransaction::rollback() +{ + // reset the transaction manager to auto-transaction mode -- this needs + // to be done first, because the rollback would otherwise be ignored + m_transactionMgr->setAutoTransactions( true ); + if ( m_transactionMgr->isActive() ) { + m_transactionMgr->rollback(); + } +} + +//----------------------------------------------------------------------------- + +#endif diff --git a/RelationalCool/src/ManualTransaction.h b/RelationalCool/src/ManualTransaction.h new file mode 100644 index 000000000..4bc24ea65 --- /dev/null +++ b/RelationalCool/src/ManualTransaction.h @@ -0,0 +1,58 @@ +// $Id: ManualTransaction.h,v 1.5 2009-01-06 12:30:07 avalassi Exp $ +#ifndef RELATIONALCOOL_MANUALTRANSACTION_H +#define RELATIONALCOOL_MANUALTRANSACTION_H + +#ifdef COOL280 + +// Include files +#include <boost/shared_ptr.hpp> +#include "CoolKernel/ITransaction.h" + +namespace cool +{ + + // Forward declaration + class IRelationalTransactionMgr; + + class ManualTransaction : public ITransaction + { + + public: + + /// Destructor + virtual ~ManualTransaction(); + + /// Constructor from a IRelationalTransactionMgr + ManualTransaction + ( const boost::shared_ptr<IRelationalTransactionMgr>& transactionMgr, + bool readOnly = false ); + + /// Commit the transaction *and* re-enable auto-transaction mode + void commit(); + + /// Rollback the transaction *and* re-enable auto-transaction mode + void rollback(); + + private: + + /// Standard constructor is private + ManualTransaction(); + + /// Copy constructor is private + ManualTransaction( const ManualTransaction& rhs ); + + /// Assignment operator is private + ManualTransaction& operator=( const ManualTransaction& rhs ); + + private: + + /// Handle to the IRelationalTransactionMgr (shared ownership) + boost::shared_ptr<IRelationalTransactionMgr> m_transactionMgr; + + }; + +} // namespace + +#endif + +#endif diff --git a/RelationalCool/src/ObjectId.cpp b/RelationalCool/src/ObjectId.cpp new file mode 100644 index 000000000..2b6282aaf --- /dev/null +++ b/RelationalCool/src/ObjectId.cpp @@ -0,0 +1,94 @@ +// $Id: ObjectId.cpp,v 1.6 2008-11-04 11:52:10 avalassi Exp $ + +// Include files +#include <sstream> + +// Local include files +#include "ObjectId.h" + +// Namespace +namespace cool { + +//----------------------------------------------------------------------------- + +ObjectId ObjectIdHandler::userObject( const ObjectId& id ) { + return int((id-1)/ObjectIdIncrement)*ObjectIdIncrement+1; +} + +//----------------------------------------------------------------------------- + +ObjectId ObjectIdHandler::lSysObject( const ObjectId& id ) { + ObjectId objId = userObject( id ); + if ( objId <= UINT_MAX -1 ) { + return objId + 1; + } else { + std::ostringstream msg; + msg << "lSysObject for '" << id << "' out of range"; + throw ObjectIdException( msg.str() ); + } +} + +//----------------------------------------------------------------------------- + +ObjectId ObjectIdHandler::rSysObject( const ObjectId& id ) { + ObjectId objId = userObject( id ); + if ( objId <= UINT_MAX -2 ) { + return objId + 2; + } else { + std::ostringstream msg; + msg << "rSysObject for '" << id << "' out of range"; + throw ObjectIdException( msg.str() ); + } +} + +//----------------------------------------------------------------------------- + +bool ObjectIdHandler::isUserObject( const ObjectId& id ) { + return ( id == userObject(id) ); +} + +//----------------------------------------------------------------------------- + +bool ObjectIdHandler::isLSysObject( const ObjectId& id ) { + return ( id == lSysObject(id) ); +} + +//----------------------------------------------------------------------------- + +bool ObjectIdHandler::isRSysObject( const ObjectId& id ) { + return ( id == rSysObject(id) ); +} + +//----------------------------------------------------------------------------- + +bool ObjectIdHandler::isSysObject( const ObjectId& id ) { + return ( isLSysObject(id) || isRSysObject(id) ); +} + +//----------------------------------------------------------------------------- + +ObjectId ObjectIdHandler::nextUserObject( const ObjectId& id ) { + ObjectId objId = userObject( id ); + if ( objId <= UINT_MAX - ObjectIdIncrement ) { + return objId + ObjectIdIncrement; + } else { + std::ostringstream msg; + msg << "next object id for '" << id << "' out of range"; + throw ObjectIdException( msg.str() ); + } +} + +//----------------------------------------------------------------------------- + +ObjectId ObjectIdHandler::prevUserObject( const ObjectId& id ) { + if ( userObject(id) <= ObjectIdIncrement ) { + std::ostringstream msg; + msg << "ObjectId '" << id << "' has no previous user object"; + throw ObjectIdException( msg.str() ); + } + return userObject(id) - ObjectIdIncrement; +} + +//----------------------------------------------------------------------------- + +} // namespace diff --git a/RelationalCool/src/ObjectId.h b/RelationalCool/src/ObjectId.h new file mode 100644 index 000000000..39fe3debd --- /dev/null +++ b/RelationalCool/src/ObjectId.h @@ -0,0 +1,95 @@ +// $Id: ObjectId.h,v 1.9 2008-11-04 11:49:37 avalassi Exp $ +#ifndef RELATIONALCOOL_OBJECTID_H +#define RELATIONALCOOL_OBJECTID_H 1 + +// Include files +#include "CoolKernel/Exception.h" + +namespace cool +{ + + /** @class ObjectId ObjectId.h + * + * This file summarises the objectId numbering scheme assumptions. + * + * Presently ObjectId is typedefed to an unsigned int. + * Eventually ObjectId may be changed to a pair of unsigned int or + * something else. + * + * Presently this is only used in the RalDatabase "tagAsOfObjectId" + * implementation. Eventually this should be used as the unique source + * for the numbering schema. + * + * Presently even the typedef is only used in the RalDatabase + * "tagAsOfObjectId". Eventually all code manipulating objectId's should + * use the typedef. + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2005-04-05 + */ + + typedef unsigned int ObjectId; + + const unsigned int ObjectIdIncrement = 6; + + class ObjectIdTest; + + namespace ObjectIdHandler { + + /// Returns true if the given id belongs to a user object + bool isUserObject( const ObjectId& id ); + + /// Returns true if the given id belongs to a "left inserted" + /// system object + bool isLSysObject( const ObjectId& id ); + + /// Returns true if the given id belongs to a "right inserted" + /// system object + bool isRSysObject( const ObjectId& id ); + + /// Returns true if the given id belongs to a system object + bool isSysObject( const ObjectId& id ); + + /// Transforms a given id into a user object id + ObjectId userObject( const ObjectId& id ); + + /// Transforms a given id into a "left inserted" system object id + /// Throws an ObjectIdExecption if the given id is out of bounds. + ObjectId lSysObject( const ObjectId& id ); + + /// Transforms a given id into a "right inserted" system object id + /// Throws an ObjectIdExecption if the given id is out of bounds. + ObjectId rSysObject( const ObjectId& id ); + + /// Returns a given id's previous user object id + /// Throws an ObjectIdExecption if the given id is out of bounds. + ObjectId prevUserObject( const ObjectId& id ); + + /// Returns a given id's next user object id + /// Throws an ObjectIdExecption if the given id is out of bounds. + ObjectId nextUserObject( const ObjectId& id ); + + } + + + /** @class ObjectIdException + * + * Exception thrown by the ObjectIdHandler. + */ + + class ObjectIdException : public Exception { + + public: + + /// Constructor + ObjectIdException( const std::string& message ) + : Exception( message, "ObjectId" ) {} + + /// Destructor + virtual ~ObjectIdException() throw() {} + + }; + +} + +#endif // RELATIONALCOOL_OBJECTID_H diff --git a/RelationalCool/src/ObjectIteratorCounter.cpp b/RelationalCool/src/ObjectIteratorCounter.cpp new file mode 100644 index 000000000..db3b137d2 --- /dev/null +++ b/RelationalCool/src/ObjectIteratorCounter.cpp @@ -0,0 +1,150 @@ +// $Id: ObjectIteratorCounter.cpp,v 1.9 2008-09-26 23:16:47 avalassi Exp $ + +// Include files +#include <iostream> +#include "CoolKernel/InternalErrorException.h" + +// Local include files +#include "IteratorException.h" +#include "ObjectIteratorCounter.h" + +// Namespace +using namespace cool; + +namespace { + + /// @class wrapper + /// Minimal wrapper class that execute a unary function object + /// to the wrapped class instance on destruction. + /// @author Marco Clemencic + template <class obj_type, class checker_type> + struct wrapper + { + + /// Wrapped instance + obj_type m_obj; + + /// Constructor. Simply create a default wrapped instance. + wrapper():m_obj(){} + + /// Destructor. Call the checker object on the wrapped instance. + ~wrapper() + { + checker_type checker; + checker(m_obj); + } + + /// Return reference to the wrapped instance. + inline obj_type & get() { return m_obj; } + + /// Conversion to the wrapped type. + inline operator obj_type & () { return m_obj; } + + }; + + /// @class ObjectIteratorCounterChecker + /// Checker class that verifies that the ObjectIteratorCounter map is empty + /// (which means all iterators deregistered). + /// The type of the map is in a template because the typedef + /// ObjectIteratorMap is private. + /// @author Marco Clemencic + template <class map_type> + struct ObjectIteratorCounterChecker + { + /// Checks if the ObjectIteratorCounter is empty, if not dump + /// the content to standard error (trigger a failure on QMtest) + void operator () (map_type &the_map) + { + if ( the_map.size() != 0 ) { + std::cerr << "ObjectIteratorCounterWatchDog: " + << the_map.size() + << " sessionMgrs" << std::endl; + typename map_type::iterator i; + for ( i = the_map.begin(); i != the_map.end(); ++i ){ + std::cerr << "-> sessionMgr: " << i->first + << ", iterators: " << i->second.size() << std::endl; + } + } + } + }; +} + +ObjectIteratorCounter::ObjectIteratorMap& +ObjectIteratorCounter::openIterators() +{ + // static ObjectIteratorMap s_openIterators; + static wrapper<ObjectIteratorMap,ObjectIteratorCounterChecker<ObjectIteratorMap> > + s_openIterators; + return s_openIterators; +} + +//----------------------------------------------------------------------------- + +void +ObjectIteratorCounter::registerIterator +( const IObjectIterator* it, + const IRelationalTransactionMgr* sessionMgr ) +{ + //std::cout << "Register iterator " << it << " " << sessionMgr << std::endl; + if ( openIterators().find( sessionMgr ) != openIterators().end() ) + { + //std::cout << "Counter size: " << openIterators().size() << std::endl; + //std::cout << "Vector size: " + // << openIterators()[sessionMgr].size() << std::endl; + throw TooManyIterators( "ObjectIteratorCounter" ); + } + ObjectIteratorVector itVector; + itVector.push_back( it ); + openIterators()[sessionMgr] = itVector; +} + +//----------------------------------------------------------------------------- + +void +ObjectIteratorCounter::unregisterIterator +( const IObjectIterator* it, + const IRelationalTransactionMgr* sessionMgr ) +{ + //std::cout << "Unregister iterator " << it << " " << sessionMgr <<std::endl; + // This sessionMgr is unknown? + if ( openIterators().find( sessionMgr ) == openIterators().end() ) + { + throw InternalErrorException + ( "PANIC! The iterator is not registered" + " (this IRelationalTransactionMgr is unknown)", + "ObjectIteratorCounter" ); + } + ObjectIteratorVector& itVector = openIterators().find( sessionMgr )->second; + + // No iterator for this sessionMgr? + if ( itVector.size() == 0 ) + { + throw InternalErrorException + ( "PANIC! The iterator is not registered" + " (none is registered for this IRelationalTransactionMgr)", + "ObjectIteratorCounter" ); + } + + // More than one iterator for this sessionMgr? + if ( itVector.size() > 1 ) + { + throw InternalErrorException + ( "PANIC! More than one iterator is registered" + " for this IRelationalTransactionMgr", + "ObjectIteratorCounter" ); + } + + // A different iterator is registered for this sessionMgr? + if ( itVector[0] != it ) + { + throw InternalErrorException + ( "PANIC! The iterator is not registered" + " (a different one is registered for this IRelationalTransactionMgr)", + "ObjectIteratorCounter" ); + } + + // OK: this is the only iterator registered for this sessionMgr - remove it + openIterators().erase( openIterators().find( sessionMgr ) ); +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/ObjectIteratorCounter.h b/RelationalCool/src/ObjectIteratorCounter.h new file mode 100644 index 000000000..eecca998d --- /dev/null +++ b/RelationalCool/src/ObjectIteratorCounter.h @@ -0,0 +1,58 @@ +// $Id: ObjectIteratorCounter.h,v 1.6 2008-09-26 23:16:47 avalassi Exp $ +#ifndef OBJECTITERATORCOUNTER_H +#define OBJECTITERATORCOUNTER_H 1 + +// Include files +#include <map> +#include <vector> + +namespace cool +{ + + // Forward declarations + class IRelationalTransactionMgr; + class IObjectIterator; + + /** @class ObjectIteratorCounter ObjectIteratorCounter.h + * + * Static counter of open 'live' iterators. + * + * @author Andrea Valassi + * @date 2007-03-30 + */ + + class ObjectIteratorCounter { + + public: + + // Register an iterator + static void registerIterator( const IObjectIterator* it, + const IRelationalTransactionMgr* trMgr ); + + // Unregister an iterator + static void unregisterIterator( const IObjectIterator* it, + const IRelationalTransactionMgr* trMgr ); + + private: + + virtual ~ObjectIteratorCounter(); + ObjectIteratorCounter(); + ObjectIteratorCounter( const ObjectIteratorCounter& rhs ); + ObjectIteratorCounter& operator=( const ObjectIteratorCounter& rhs ); + + private: + + typedef + std::vector< const IObjectIterator* > ObjectIteratorVector; + + typedef + std::map< const IRelationalTransactionMgr*, + ObjectIteratorVector > ObjectIteratorMap; + + /// List of active 'live' iterators (there should be only one!) + static ObjectIteratorMap& openIterators(); + + }; + +} +#endif // OBJECTITERATORCOUNTER_H diff --git a/RelationalCool/src/ObjectVectorIterator.cpp b/RelationalCool/src/ObjectVectorIterator.cpp new file mode 100644 index 000000000..cbc16578b --- /dev/null +++ b/RelationalCool/src/ObjectVectorIterator.cpp @@ -0,0 +1,92 @@ +// $Id: ObjectVectorIterator.cpp,v 1.18 2008-11-04 11:52:10 avalassi Exp $ + +// Include files +#include "CoolKernel/IObject.h" +#include "CoolKernel/types.h" + +// Local include files +#include "IteratorException.h" +#include "ObjectVectorIterator.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +ObjectVectorIterator::ObjectVectorIterator( const IObjectVectorPtr& objects ) + : m_objects( objects ) + , m_size( objects->size() ) + , m_current1toN( 0 ) + , m_isClosed( false ) +{ +} + +//----------------------------------------------------------------------------- + +ObjectVectorIterator::~ObjectVectorIterator() +{ + close(); +} + +//----------------------------------------------------------------------------- + +bool ObjectVectorIterator::isEmpty() +{ + if ( m_isClosed ) throw IteratorIsClosed( "ObjectVectorIterator" ); + return ( m_size == 0 ); +} + +//----------------------------------------------------------------------------- + +const IObject& ObjectVectorIterator::currentRef() +{ + if ( m_isClosed ) throw IteratorIsClosed( "ObjectVectorIterator" ); + if ( m_current1toN < 1 ) { + throw Exception( "Current position is before the first object in the loop", + "ObjectVectorIterator" ); + } else if ( m_current1toN > m_size ) { + throw Exception( "Current position is after the last object in the loop", + "ObjectVectorIterator" ); + } else { + return *(*m_objects)[m_current1toN-1]; + } +} + +//----------------------------------------------------------------------------- + +bool ObjectVectorIterator::goToNext() +{ + if ( m_isClosed ) throw IteratorIsClosed( "ObjectVectorIterator" ); + if ( ( m_current1toN < m_size ) ) { + m_current1toN++; + return true; + } + return false; +} + +//----------------------------------------------------------------------------- + +unsigned int ObjectVectorIterator::size() +{ + if ( m_isClosed ) throw IteratorIsClosed( "ObjectVectorIterator" ); + return m_size; +} + +//----------------------------------------------------------------------------- + +const IObjectVectorPtr ObjectVectorIterator::fetchAllAsVector() +{ + if ( m_isClosed ) throw IteratorIsClosed( "ObjectVectorIterator" ); + if ( m_current1toN > 0 ) throw IteratorIsActive( "ObjectVectorIterator" ); + return m_objects; +} + +//----------------------------------------------------------------------------- + +void ObjectVectorIterator::close() +{ + m_isClosed = true; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/ObjectVectorIterator.h b/RelationalCool/src/ObjectVectorIterator.h new file mode 100644 index 000000000..616150acb --- /dev/null +++ b/RelationalCool/src/ObjectVectorIterator.h @@ -0,0 +1,85 @@ +// $Id: ObjectVectorIterator.h,v 1.21 2008-11-04 11:52:10 avalassi Exp $ +#ifndef RELATIONALCOOL_OBJECTVECTORITERATOR_H +#define RELATIONALCOOL_OBJECTVECTORITERATOR_H + +// Include files +#include "CoolKernel/IObjectIterator.h" + +namespace cool { + + /** @class ObjectVectorIterator ObjectVectorIterator.h + * + * Vector implementation of a COOL condition database object iterator. + * + * Useful for the simplest implementation of object retrieval from + * the database: retrieving an iterator over the objects in a folder + * immediately retrieves the full vector of objects. + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2004-12-13 + */ + + class ObjectVectorIterator : public IObjectIterator { + + public: + + /// Constructor from a shared pointer to a vector of objects. + /// The iterator is positioned BEFORE its first element. + ObjectVectorIterator( const IObjectVectorPtr& objects ); + + /// Destructor. + virtual ~ObjectVectorIterator(); + + /// Does the iterator have zero objects in the loop? + bool isEmpty(); + + /// Fetch the next object in the iterator loop. + /// Return false if there is no next object. + bool goToNext(); + + /// Retrieve a reference to the current object in the iterator loop. + /// NB The reference is only valid until next() or goToNext() is called! + /// Throw an exception if there is no current object (because the iterator + /// is empty or is positioned before the first object in the loop). + const IObject& currentRef(); + + /// Returns the 'length' of the iterator. + unsigned int size(); + + /// Returns all objects in the iterator as a vector. + const IObjectVectorPtr fetchAllAsVector(); + + /// Close the iterator and release any associated server resources. + /// The iterator cannot be used any more after this method is called. + void close(); + + private: + + /// Standard constructor is private. + ObjectVectorIterator(); + + /// Copy constructor is private + ObjectVectorIterator( const ObjectVectorIterator& rhs ); + + /// Assignment operator is private + ObjectVectorIterator& operator=( const ObjectVectorIterator& rhs ); + + private: + + /// Vector of objects + IObjectVectorPtr m_objects; + + /// Size of the vector of objects + unsigned int m_size; + + /// Current position in the loop + unsigned int m_current1toN; + + /// Has the close() method been called? + bool m_isClosed; + + }; + +} + +#endif //RELATIONALCOOL_OBJECTVECTORITERATOR_H diff --git a/RelationalCool/src/ProcMemory.h b/RelationalCool/src/ProcMemory.h new file mode 100644 index 000000000..a49944bef --- /dev/null +++ b/RelationalCool/src/ProcMemory.h @@ -0,0 +1,197 @@ +// Include files +#include <cstdlib> // for atol +#include <iostream> // for cout +#include <sstream> // for stringstream + +class ProcMemory { + +public: + + ProcMemory() { + m_pid = getProcessId(); + } + + ~ProcMemory() {} + + void printVm(); + + long getProcessId(); + + long getVsz(); + long getRss(); + long getProcStatus( const std::string& key ); + +private: + + int m_pid; + +}; + +//---------------------------------------------------------------------------- + +inline void ProcMemory::printVm() { + long vsz = getVsz(); + long rss = getRss(); + std::cout << "VSZ=" << vsz << " RSS=" << rss << std::endl; +} + +//---------------------------------------------------------------------------- + +// WINDOWS - see http://msdn2.microsoft.com/en-us/library/t2y34y40 +#ifdef WIN32 + +#include <process.h> +inline long ProcMemory::getProcessId() { + return _getpid(); +} + +// OSX and LINUX +#else + +#include <sys/types.h> +#include <unistd.h> +inline long ProcMemory::getProcessId() { + return getpid(); +} + +#endif + +//---------------------------------------------------------------------------- + +// WINDOWS +#ifdef WIN32 + +// For ifstream +#include <fstream> + +inline long ProcMemory::getVsz() { + return getProcStatus( "VmSize" ); +} + +inline long ProcMemory::getRss() { + return getProcStatus( "VmRSS" ); +} + +// NB To get rid of the annoying messages "UNC not supported", +// add a DWORD registry key (hex value 1) called DisableUNCCheck to +// HKCU\Software\Microsoft\Command Processor. +// See http://weblogs.asp.net/kdente/archive/2004/01/30/65232.aspx + +// NB A non-cygwin alternative for Windows could be to use "tlist": +// this is only available after installing the Windows XP Support Tools. +// See http://emea.windowsitpro.com/Article/ArticleID/43569/43569.html?Ad=1 +// See http://www.ss64.com/nt/tlist.html + +// NB Another simple non-cygwin alternative could be to use "tasklist": +// however, this only provides the VmRSS value, which is much less +// interesting than the VmSize value (only VmSize is affected by malloc). + +inline long ProcMemory::getProcStatus( const std::string& key ) { + long value = -1; + std::stringstream cmd; + cmd << "ps | gawk '{if ($4 == " << m_pid + << ") {cmd=\"cat /proc/\"$1\"/status\"; system(cmd)}}'" + << " | grep " << key; + const int kMaxSize = 256; + char line[kMaxSize]; + FILE* input_stream = _popen( cmd.str().c_str(), "r" ); + if ( fgets( line, kMaxSize, input_stream ) == NULL ) { + //std::cout << "Error while getting status" << std::endl; + } else { + //std::cout << "line: " << line << std::endl; + std::string lineStr = line; + if( lineStr.substr(0,key.size()+1) == (key+":") ) { + lineStr = lineStr.substr(key.size()+2,lineStr.size()-key.size()-2-3); + value = atol(lineStr.c_str()); + } + } + _pclose( input_stream ); + return value; +} + +//---------------------------------------------------------------------------- + +// OSX +#elif defined(__APPLE__) + +inline long ProcMemory::getVsz() { + return getProcStatus( "vsz" ); +} + +inline long ProcMemory::getRss() { + return getProcStatus( "rss" ); +} + +inline long ProcMemory::getProcStatus( const std::string& key ) { + const int kMaxSize = 256; + char line[kMaxSize]; + long value = -1; + std::stringstream cmd; + cmd << "ps -p " << m_pid << " -o " << key << "| grep -iv " << key; + FILE* input_stream = popen( cmd.str().c_str(), "r" ); + if ( fgets( line, kMaxSize, input_stream ) == NULL ) { + //std::cout << "Error while getting status" << std::endl; + } else { + //std::cout << "Line: " << line << std::endl; + value = atol( line ); + } + pclose( input_stream ); + return value; +} + +//---------------------------------------------------------------------------- + +// LINUX +#else + +// For getpid() +#include <sys/types.h> +#include <unistd.h> + +// For ifstream +#include <fstream> + +inline long ProcMemory::getVsz() { + return getProcStatus( "VmSize" ); +} + +inline long ProcMemory::getRss() { + return getProcStatus( "VmRSS" ); +} + +inline long ProcMemory::getProcStatus( const std::string& key ) { + long value = -1; + std::stringstream fileName; + fileName << "/proc/" << m_pid << "/status"; + std::ifstream proc( fileName.str().c_str() ); + if( !proc ) { + std::cout << "Error opening " << fileName.str() << std::endl; + } else { + char ch; + std::string line; + while( proc.get(ch) ) { + if ( ch != '\n' ) { + line += ch; + } else { + if( line.substr(0,key.size()+1) == (key+":") ) { + line = line.substr(key.size()+2,line.size()-key.size()-2-3); + //std::cout << "Line: " << line << std::endl; + value = atol(line.c_str()); + } + line = ""; + } + } + if( !proc.eof() ) { + std::cout << "Error while reading " << fileName.str() << std::endl; + } else { + //std::cout << "EOF " << fileName.str() << std::endl; + } + } + //std::cout << key << ": " << value << std::endl; + return value; +} + +#endif + +//---------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RalBulkOperation.h b/RelationalCool/src/RalBulkOperation.h new file mode 100644 index 000000000..33f02c6dc --- /dev/null +++ b/RelationalCool/src/RalBulkOperation.h @@ -0,0 +1,56 @@ +#ifndef RELATIONALCOOL_RALBULKOPERATION_H +#define RELATIONALCOOL_RALBULKOPERATION_H + +// Include files +#include <boost/shared_ptr.hpp> +#include "RelationalAccess/IBulkOperation.h" + +// Local include files +#include "IRelationalBulkOperation.h" + +namespace cool { + + /** + * Class RalBulkOperation + * + * Wrapper for a coral::IBulkOperation. + * + */ + + class RalBulkOperation : public IRelationalBulkOperation { + + public: + + /// Destructor + virtual ~RalBulkOperation() {} + + /// Constructor + RalBulkOperation( const boost::shared_ptr<coral::IBulkOperation> bulkOp ) + : m_bulkOperation( bulkOp ) {} + + /// Processes the next iteration + void processNextIteration() + { + m_bulkOperation->processNextIteration(); + } + + /// Flushes the data on the client side to the server. + void flush() + { + m_bulkOperation->flush(); + } + + private: + + RalBulkOperation(); + RalBulkOperation( const RalBulkOperation& ); + RalBulkOperation& operator=( const RalBulkOperation& ); + + private: + + boost::shared_ptr<coral::IBulkOperation> m_bulkOperation; + + }; + +} +#endif diff --git a/RelationalCool/src/RalCursor.h b/RelationalCool/src/RalCursor.h new file mode 100644 index 000000000..30ebd236e --- /dev/null +++ b/RelationalCool/src/RalCursor.h @@ -0,0 +1,71 @@ +#ifndef RELATIONALCOOL_RALCURSOR_H +#define RELATIONALCOOL_RALCURSOR_H + +// Include files +#include <memory> +#include "RelationalAccess/ICursor.h" +#include "RelationalAccess/IQuery.h" + +// Local include files +#include "IRelationalCursor.h" +//#include "RalQueryMgr.h" // for TimingReport + +namespace cool +{ + + /** + * Class RalCursor + * + * Wrapper for a coral::ICursor. + * + */ + + class RalCursor : public IRelationalCursor { + + public: + + /// Destructor + virtual ~RalCursor() {} + + /// Constructor from a CORAL query. + /// The constructor takes ownership of the query and executes it. + RalCursor( std::auto_ptr<coral::IQuery> query ) + : m_query( query ) + , m_cursor( m_query->execute() ) {} + //, m_cursor( RalQueryMgr::executeQuery(*m_query) ) {} // with TimingReport + + /// Positions the cursor to the next available row in the result set. + /// If there are no more rows in the result set false is returned. + bool next() + { + return m_cursor.next(); + //return RalQueryMgr::cursorNext( m_cursor ); // with TimingReport + } + + /// Returns a reference to the output buffer holding the last row fetched. + const coral::AttributeList& currentRow() const + { + return m_cursor.currentRow(); + } + + /// Explicitly closes the cursor, releasing the resources on the server. + void close() + { + return m_cursor.close(); + } + + private: + + RalCursor(); + RalCursor( const RalCursor& ); + RalCursor& operator=( const RalCursor& ); + + private: + + std::auto_ptr<coral::IQuery> m_query; + coral::ICursor& m_cursor; + + }; + +} +#endif diff --git a/RelationalCool/src/RalDatabase.cpp b/RelationalCool/src/RalDatabase.cpp new file mode 100644 index 000000000..4530672d5 --- /dev/null +++ b/RelationalCool/src/RalDatabase.cpp @@ -0,0 +1,1479 @@ +// $Id: RalDatabase.cpp,v 1.607 2009-01-06 12:30:07 avalassi Exp $ + +// Include files +#include <sstream> +#include "CoolKernel/ChannelSelection.h" +#include "HvsTagRecord.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/ValidityKey.h" +#include "CoralBase/Exception.h" +#include "RelationalAccess/IBulkOperation.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" +#include "RelationalAccess/ITableDataEditor.h" +#include "RelationalAccess/SchemaException.h" + +// Local include files +#include "DummyTransactionMgr.h" +#include "HvsPathHandler.h" +#include "HvsPathHandlerException.h" +#include "ManualTransaction.h" +#include "ObjectId.h" +#include "RalDatabase.h" +#include "RalQueryMgr.h" +#include "RalSchemaMgr.h" +#include "RalSessionMgr.h" +#include "RalTransactionMgr.h" +#include "RelationalChannelTable.h" +#include "RelationalDatabaseId.h" +#include "RelationalDatabaseTable.h" +#include "RelationalException.h" +#include "RelationalFolder.h" +#include "RelationalFolderUnsupported.h" +#include "RelationalFolderSet.h" +#include "RelationalFolderSetUnsupported.h" +#include "RelationalNodeMgr.h" +#include "RelationalNodeTable.h" +#include "RelationalGlobalTagTable.h" +#include "RelationalObject.h" +#include "RelationalObjectMgr.h" +#include "RelationalObjectTable.h" +#include "RelationalObjectTableRow.h" +#include "RelationalObject2TagTable.h" +#include "RelationalSequence.h" +#include "RelationalSequenceMgr.h" +#include "RelationalTableRow.h" +#include "RelationalTagMgr.h" +#include "RelationalTagSequence.h" +#include "RelationalTagTable.h" +#include "RelationalTag2TagTable.h" +#include "RelationalTransaction.h" +#include "SimpleObject.h" +#include "TimingReportMgr.h" +#include "VersionInfo.h" +#include "attributeListToString.h" +#include "sleep.h" +#include "timeToString.h" +#include "uppercaseString.h" + +// Additional VersionInfo specific to RalDatabase.cpp +namespace cool +{ + namespace VersionInfo { + const std::string cvsCheckout = "$Name: not supported by cvs2svn $"; + const std::string cvsCheckin = "$Id: RalDatabase.cpp,v 1.607 2009-01-06 12:30:07 avalassi Exp $"; + } +} + +// Namespace +using namespace cool; + +// Local type definitions +typedef boost::shared_ptr<RelationalSequence> RelationalSequencePtr; + +//----------------------------------------------------------------------------- + +RalDatabase::RalDatabase( CoralConnectionServiceProxyPtr ppConnSvc, + const DatabaseId& dbId, + bool readOnly ) + : RelationalDatabase( dbId ) + , m_useTimeout( true ) + , m_sessionMgr( new RalSessionMgr( ppConnSvc, dbId, readOnly ) ) +{ + std::string ro = ( readOnly ? "R/O" : "R/W" ); + log() << coral::Info << "Instantiate a " << ro << " RalDatabase for '" + << databaseId() << "'" << coral::MessageStream::endmsg; + + // Create a new relational query manager + setQueryMgr( std::auto_ptr<RelationalQueryMgr> + ( new RalQueryMgr( sessionMgr() ) ) ); + + // Create a new relational schema manager + setSchemaMgr( std::auto_ptr<RelationalSchemaMgr> + ( new RalSchemaMgr( *this, sessionMgr() ) ) ); + + // Create a new relational node manager + setNodeMgr( std::auto_ptr<RelationalNodeMgr> + ( new RelationalNodeMgr( *this ) ) ); + + // Create a new relational tag manager + setTagMgr( std::auto_ptr<RelationalTagMgr> + ( new RelationalTagMgr( *this ) ) ); + + // Create a new object manager + setObjectMgr( std::auto_ptr<RelationalObjectMgr> + ( new RelationalObjectMgr( *this ) ) ); + + // Create a new relational transaction manager + // For read-only connections, a single R/O transaction is started + // by the RalSessionMgr for the duration of the database connection: + // all other clients use a dummy transaction manager! + //if ( !readOnly ) + if ( !readOnly || getenv ( "COOL_READONLYSESSION_MANYTRANSACTIONS" ) ) + { + setTransactionMgr( boost::shared_ptr<IRelationalTransactionMgr> + ( new RalTransactionMgr( sessionMgr() ) ) ); + } + else + { + setTransactionMgr( boost::shared_ptr<IRelationalTransactionMgr> + ( new DummyTransactionMgr() ) ); + } + + // Initialize timing reports + if ( getenv ( "COOL_TIMINGREPORT" ) ) + { + TimingReportMgr::initialize(); + TimingReportMgr::startTimer( "TOTAL [cool::RalDatabase]" ); + } +} + +//----------------------------------------------------------------------------- + +RalDatabase::~RalDatabase() +{ + log() << coral::Info << "Delete the RalDatabase for '" + << databaseId() << "'" << coral::MessageStream::endmsg; + + // Loop over all nodes in the node map + for ( std::map<std::string,RelationalTableRow*>::const_iterator + row = m_nodes.begin(); row != m_nodes.end(); ++row ) + { + delete row->second; + } + + // Finalize timing reports + if ( TimingReportMgr::isActive() ) { + TimingReportMgr::stopTimer( "TOTAL [cool::RalDatabase]" ); + TimingReportMgr::finalize(); + } +} + +//----------------------------------------------------------------------------- + +void RalDatabase::createDatabase( const IRecord& dbAttr ) +{ + std::string dbName = databaseName(); + log() << "Create a new database with name " << dbName + << coral::MessageStream::endmsg; + + // Check if the database attribute specification is valid + if ( dbAttr.specification() != databaseAttributesSpecification() ) + throw RelationalException + ( "Invalid database attributes specification", "RalDatabase" ); + m_dbAttr = dbAttr; + + // Add release and schema related attributes + m_dbAttr[RelationalDatabaseTable::attributeNames::release].setValue + <RelationalDatabaseTable::columnTypes::attributeValue> + ( VersionInfo::release ); + m_dbAttr[RelationalDatabaseTable::attributeNames::cvsCheckout].setValue + <RelationalDatabaseTable::columnTypes::attributeValue> + ( VersionInfo::cvsCheckout ); + m_dbAttr[RelationalDatabaseTable::attributeNames::cvsCheckin].setValue + <RelationalDatabaseTable::columnTypes::attributeValue> + ( VersionInfo::cvsCheckin ); + m_dbAttr[RelationalDatabaseTable::attributeNames::schemaVersion].setValue + <RelationalDatabaseTable::columnTypes::attributeValue> + ( VersionInfo::schemaVersion ); + + // TEMPORARY? AV 04.04.2005 + // FIXME: you should check here that the default prefix is not longer + // than 8 characters and is already uppercase. + // FIXME: you should check here that the table names are all uppercase + // and not longer than the maximum allowed Oracle/MySQL limits. + + // Start a read-write transaction + RelationalTransaction transaction( transactionMgr() ); + + // Get the name of the main management table, create it and fill it + schemaMgr().createMainTable( mainTableName() ); + schemaMgr().fillMainTable( mainTableName(), m_dbAttr.attributeList() ); + + /* + // *** START *** 3.0.0 schema extensions (task #4307) + // Get the name of the iovTables table and create it + std::string iovTablesTableName = + dbAttr[RelationalDatabaseTable::attributeNames::iovTablesTableName]. + data<std::string>(); + schemaMgr().createIovTablesTable( iovTablesTableName ); + + // Get the name of the channelTables table and create it + std::string channelTablesTableName = + dbAttr[RelationalDatabaseTable::attributeNames::channelTablesTableName]. + data<std::string>(); + schemaMgr().createChannelTablesTable( channelTablesTableName ); + // **** END **** 3.0.0 schema extensions (task #4307) + */ + + // Get the name of the node table and create it + std::string nodeTableName = + dbAttr[RelationalDatabaseTable::attributeNames::nodeTableName]. + data<std::string>(); + std::string defaultTablePrefix = + dbAttr[RelationalDatabaseTable::attributeNames::defaultTablePrefix]. + data<std::string>(); + schemaMgr().createNodeTable( nodeTableName, defaultTablePrefix ); + + // Get the name of the tag table and create it + std::string tagTableName = + dbAttr[RelationalDatabaseTable::attributeNames::tagTableName]. + data<std::string>(); + schemaMgr().createGlobalTagTable( tagTableName, nodeTableName ); + + /* + // *** START *** 3.0.0 schema extensions (task #4396) + // Get the name of the head tag table and create it + std::string headTagTableName = + dbAttr[RelationalDatabaseTable::attributeNames::headTagTableName]. + data<std::string>(); + schemaMgr().createGlobalHeadTagTable( headTagTableName, tagTableName ); + + // Get the name of the user tag table and create it + std::string userTagTableName = + dbAttr[RelationalDatabaseTable::attributeNames::userTagTableName]. + data<std::string>(); + schemaMgr().createGlobalUserTagTable( userTagTableName, tagTableName ); + // **** END **** 3.0.0 schema extensions (task #4396) + */ + + // Get the name of the tag table and create it + std::string tag2TagTableName = + dbAttr[RelationalDatabaseTable::attributeNames::tag2TagTableName]. + data<std::string>(); + schemaMgr().createTag2TagTable + ( tag2TagTableName, tagTableName, nodeTableName ); + + // Get the name of the tag shared sequence and create it + std::string tagSharedSequenceName = + dbAttr[RelationalDatabaseTable::attributeNames::tagSharedSequenceName]. + data<std::string>(); + schemaMgr().createSharedSequence( tagSharedSequenceName, nodeTableName ); + + // Get the name of the IOV shared sequence and create it + std::string iovSharedSequenceName = + dbAttr[RelationalDatabaseTable::attributeNames::iovSharedSequenceName]. + data<std::string>(); + schemaMgr().createSharedSequence( iovSharedSequenceName, nodeTableName ); + + // Commit the transaction + transaction.commit(); + + // The database is now open + m_isOpen = true; + + // TEMPORARY? Sleep to work around the ORA-01466 problem (Oracle only) + if ( m_sessionMgr->databaseTechnology() == "Oracle" && m_useTimeout ) { + log() << "Sleep to work around the ORA-01466 problem" + << coral::MessageStream::endmsg; + cool::sleep(1); + } + +} + +//----------------------------------------------------------------------------- + +bool RalDatabase::dropDatabase() +{ + log() << coral::Info << "Drop database..." << coral::MessageStream::endmsg; + + // AV 2005-07-07 + // Return true if all database tables are dropped as expected. + // Return false (without throwing any exception) if the database and + // all associated tables do not exist any more on exit from this method, + // but the database or some associated tables did not exist to start with. + bool status = true; + + // Throw a RelationalException if the database or one of its tables + // cannot be dropped (i.e. continues to exist on exit from this method). + // Any exception is thrown as soon as the first problem appears: + // the implementation is based on many individual transactions, + // there is no attempt to go back to the last known state on failure + // (also because technically difficult, Oracle DDL is auto-committed). + + // Enclose the implementation in a try-catch block anyway, + // just to be able to print some debug messages on failures. + try + { + + // For each folder, drop IOV table and sequence and delete the folder row. + // Also delete any tags associated to the folder from the global tag table + // and from the tag2tag table (otherwise FK constraints may be violated) + // Throw an Exception if the schema of one of the nodes in this database + // is more recent than the schema version supported by the current release: + // in this case make sure you do not drop ANY node (throw immediately)! + if ( ! dropAllNodes() ) status = false; + + // Drop the IOV shared sequence + { + std::string tableName = iovSharedSequenceName(); + log() << coral::Debug << "Drop table " << tableName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + + // Drop the tag shared sequence + { + std::string tableName = tagSharedSequenceName(); + log() << coral::Debug << "Drop table " << tableName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + + // Drop the sequence associated to the tag2tag table + { + std::string seqName = + RelationalTag2TagTable::sequenceName( tag2TagTableName() ); + log() << coral::Debug << "Drop sequence " << seqName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! queryMgr().sequenceMgr().existsSequence( seqName ) ) + { + status = false; + } + else + { + queryMgr().sequenceMgr().dropSequence( seqName ); + } + transaction.commit(); + } + + // Drop the tag2tag table + { + std::string tableName = tag2TagTableName(); + log() << coral::Debug << "Drop table " << tableName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + + /* + // *** START *** 3.0.0 schema extensions (task #4396) + // Drop the global user tag table + { + std::string tableName = globalUserTagTableName(); + log() << coral::Debug << "Drop table " << tableName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + + // Drop the global head tag table + { + std::string tableName = globalHeadTagTableName(); + log() << coral::Debug << "Drop table " << tableName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + // **** END **** 3.0.0 schema extensions (task #4396) + */ + + // Drop the global tag table + { + std::string tableName = globalTagTableName(); + log() << coral::Debug << "Drop table " << tableName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + + // Drop the sequence associated to the node table + { + std::string seqName = + RelationalNodeTable::sequenceName( nodeTableName() ); + log() << coral::Debug << "Drop sequence " << seqName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! queryMgr().sequenceMgr().existsSequence( seqName ) ) + { + status = false; + } + else + { + queryMgr().sequenceMgr().dropSequence( seqName ); + } + transaction.commit(); + } + + // Drop the node table + { + std::string tableName = nodeTableName(); + log() << coral::Debug << "Drop table " << tableName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + + /* + // *** START *** 3.0.0 schema extensions (task #4307) + // Drop the channelTables table + { + std::string tableName = channelTablesTableName(); + //log() << coral::Debug << "Drop table " << tableName + // << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + //if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + + // Drop the iovTables table + { + std::string tableName = iovTablesTableName(); + //log() << coral::Debug << "Drop table " << tableName + // << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + //if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + // **** END **** 3.0.0 schema extensions (task #4307) + */ + + // Drop the main table + { + std::string tableName = mainTableName(); + log() << coral::Debug << "Drop table " << tableName + << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr() ); // read-write + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + transaction.commit(); + } + + } + catch ( std::exception& e ) + { + log() << coral::Warning << "Exception caught in dropDatabase(): " + << e.what() << coral::MessageStream::endmsg; + throw; + } + + // Success: the database does not exist anymore + // Return status code 'false' if parts of it were missing already + log() << coral::Info << "Drop database... DONE" + << coral::MessageStream::endmsg; + return status; +} + +//----------------------------------------------------------------------------- + +UInt32 RalDatabase::insertNodeTableRow +( const std::string& fullPath, + const std::string& description, + bool createParents, + bool isLeaf, + const std::string& payloadSpecDesc, + FolderVersioning::Mode versioningMode ) +{ + // Transaction handled in the outer scope + + // This is the maximum number of nodes that can be created + // Note that this limitation is coupled to the folder name + // generation via the pattern F%4.4i_IOVS --> max: F9999_IOVS + // There is no point in working around this limitation at this time + // as the database will not handle several thousands of tables well. + // (At least the MySQL backend has proven to be problematic at this scale.) + unsigned int kMaxNumberOfNodes = 9999; + + log() << "Create a new node with name " << fullPath + << coral::MessageStream::endmsg; + // Cross-check that the database is open + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + /* + // AV 09.05.2005 Move this AFTER locking sequence to fix David Front's bug + // Check if a folder or folder set with this name already exists + if ( existsNode( fullPath ) ) { + throw NodeExists( fullPath, "RalDatabase" ); + } + */ + + // Split the full path + HvsPathHandler pathHandler; + std::pair<std::string, std::string> parentAndChild; + try { + parentAndChild = pathHandler.splitFullPath( fullPath ); + } catch ( HvsPathHandlerException& ) { + log() << coral::Error << "Invalid folder node path '" + << fullPath << "'" << coral::MessageStream::endmsg; + throw; + } + std::string parentFullPath = parentAndChild.first; + std::string unresolvedName = parentAndChild.second; + + // Look for the parent folder set + unsigned int nodeParentId; + try { + RelationalTableRow row = fetchNodeTableRow( parentFullPath ); + bool isLeaf = + row[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + if ( isLeaf ) { + std::stringstream s; + s << "Cannot create node '" << fullPath + << "', because the parent path contains a leaf node"; + throw RelationalException( s.str(), "RalDatabase" ); + } + IFolderSetPtr parent + ( new RelationalFolderSet( relationalDbPtr(), row.data() ) ); + nodeParentId = parent->id(); + } catch ( NodeTableRowNotFound& ) { + if( ! createParents ) throw; + __createFolderSet( parentFullPath, // full path + "", // description + true ); // createParents + RelationalTableRow row = fetchNodeTableRow( parentFullPath ); + IFolderSetPtr parent + ( new RelationalFolderSet( relationalDbPtr(), row.data() ) ); + nodeParentId = parent->id(); + } + + // Get a new folder ID from the sequence + std::string nodeSeqName = + RelationalNodeTable::sequenceName( nodeTableName() ); + RelationalSequencePtr nodeSeq + ( queryMgr().sequenceMgr().getSequence( nodeSeqName ) ); + unsigned int nodeId = nodeSeq->nextVal(); + if ( nodeId > kMaxNumberOfNodes ) + throw RelationalException + ( "Node ID out of boundaries", "RalDatabase" ); + std::string insertionTime = nodeSeq->currDate(); + + // AV 09.05.2005 Move this AFTER locking sequence to fix David Front's bug + // Check if a folder or folder set with this name already exists + if ( existsNode( fullPath ) ) { + /* + // NB Error message only makes sense if first cross-check is also kept + log() << coral::Error + << "Congratulations! You tried to create folder " << fullPath + << " from two separate connections EXACTLY at the same time!" + << coral::MessageStream::endmsg; + */ + throw NodeExists( fullPath, "RalDatabase" ); + } + + // Register the folder in the node table + // AV 14-03-2005 TEMPORARY? Till RAL handles NULL values better + // Do not insert NULL values: insert empty strings instead + const IRecordSpecification& nodeTableSpec = + RelationalNodeTable::tableSpecification( true ); + coral::AttributeList data = Record( nodeTableSpec ).attributeList(); + data[RelationalNodeTable::columnNames::nodeId].setValue + ( nodeId ); + data[RelationalNodeTable::columnNames::nodeParentId].setValue + ( nodeParentId ); + data[RelationalNodeTable::columnNames::nodeName].setValue + ( unresolvedName ); + data[RelationalNodeTable::columnNames::nodeFullPath].setValue + ( fullPath ); + data[RelationalNodeTable::columnNames::nodeDescription].setValue + ( description ); + data[RelationalNodeTable::columnNames::nodeIsLeaf].setValue + ( isLeaf ); + if ( isLeaf ) { + data[RelationalNodeTable::columnNames::nodeSchemaVersion].setValue + ( std::string( RelationalFolder::folderSchemaVersion() ) ); + } + else { + data[RelationalNodeTable::columnNames::nodeSchemaVersion].setValue + ( std::string( RelationalFolderSet::folderSetSchemaVersion() ) ); + } + data[RelationalNodeTable::columnNames::nodeInsertionTime].setValue + ( insertionTime ); + data[RelationalNodeTable::columnNames::lastModDate].setValue + ( insertionTime ); + + if ( isLeaf ) { + // Set the folder specific information + data[RelationalNodeTable::columnNames::folderPayloadSpecDesc].setValue + ( payloadSpecDesc ); + data[RelationalNodeTable::columnNames::folderVersioningMode].setValue + ( (int)versioningMode ); + data[RelationalNodeTable::columnNames::folderObjectTableName].setValue + ( RelationalObjectTable::defaultTableName + ( defaultTablePrefix(), nodeId ) ); + data[RelationalNodeTable::columnNames::folderTagTableName].setValue + ( RelationalTagTable::defaultTableName + ( defaultTablePrefix(), nodeId ) ); + data[RelationalNodeTable::columnNames::folderObject2TagTableName].setValue + ( RelationalObject2TagTable::defaultTableName + ( defaultTablePrefix(), nodeId ) ); + data[RelationalNodeTable::columnNames::folderChannelTableName].setValue + ( RelationalChannelTable::defaultTableName + ( defaultTablePrefix(), nodeId ) ); + } else { + // Insert NULL values for folder sets + data[RelationalNodeTable::columnNames::folderPayloadSpecDesc].setValue + ( std::string( "" ) ); + //( payloadSpecDesc ); + data[RelationalNodeTable::columnNames::folderVersioningMode].setValue + ( (int)FolderVersioning::NONE ); + //( (int)versioningMode ); + data[RelationalNodeTable::columnNames::folderObjectTableName].setValue + ( std::string( "" ) ); + data[RelationalNodeTable::columnNames::folderTagTableName].setValue + ( std::string( "" ) ); + data[RelationalNodeTable::columnNames::folderObject2TagTableName].setValue + ( std::string( "" ) ); + } + + // TEMPORARY? Will RAL do this as well? + // Check that all column values are within their allowed range + nodeTableSpec.validate( data ); + + // Perform the actual db update + queryMgr().insertTableRow( nodeTableName(), data ); + return nodeId; +} + +//----------------------------------------------------------------------------- + +IFolderSetPtr RalDatabase::createFolderSet( const std::string& fullPath, + const std::string& description, + bool createParents ) +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + // Cross-check that we're not in manual transaction more + if ( ! transactionMgr()->autoTransactions() ) { + throw RelationalException("Cannot create folder set in manual " + "transaction mode", "RalDatabase"); + } + RelationalTransaction transaction( transactionMgr() ); // read-write + IFolderSetPtr folderset = + __createFolderSet( fullPath, description, createParents ); + transaction.commit(); + return folderset; +} + +//----------------------------------------------------------------------------- + +IFolderSetPtr RalDatabase::__createFolderSet( const std::string& fullPath, + const std::string& description, + bool createParents ) +{ + log() << coral::Verbose + << "Create folder set " << fullPath << coral::MessageStream::endmsg; + + // Cross-check that the database is open + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + bool isLeaf = false; + std::string payloadSpecDesc = ""; + FolderVersioning::Mode folderVersioningMode = FolderVersioning::NONE; + + unsigned int nodeId = insertNodeTableRow + ( fullPath, description, createParents, isLeaf, + // The "" payloadSpecDesc argument is set to NULL only in the Oracle db + payloadSpecDesc, folderVersioningMode ); + + std::string tagSequenceName = RelationalTagSequence::sequenceName + ( defaultTablePrefix(), nodeId ); + schemaMgr().createTagSequence( tagSequenceName ); + + log() << coral::Verbose + << "Created folder set " << fullPath + << ": now fetch it and return it" << coral::MessageStream::endmsg; + + return __getFolderSet( fullPath ); +} + + +//----------------------------------------------------------------------------- + +IFolderPtr RalDatabase::createFolder +( const std::string& fullPath, + const IRecordSpecification& payloadSpec, + const std::string& description, + FolderVersioning::Mode versioningMode, + bool createParents ) +{ + // Cross-check that the database is open + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + // Cross-check that we're not in manual transaction more + if ( ! transactionMgr()->autoTransactions() ) { + throw RelationalException("Cannot create folder in manual " + "transaction mode", "RalDatabase"); + } + bool readOnly = false; + RelationalTransaction transaction( transactionMgr(), readOnly ); + IFolderPtr folder = + __createFolder( fullPath, payloadSpec, description, + versioningMode, createParents ); + transaction.commit(); + return folder; +} + +//----------------------------------------------------------------------------- + +IFolderPtr RalDatabase::createFolder +( const std::string& fullPath, + const IFolderSpecification& folderSpec, + const std::string& description, + bool createParents ) +{ + // Cross-check that the database is open + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + // Cross-check that we're not in manual transaction more + if ( ! transactionMgr()->autoTransactions() ) { + throw RelationalException("Cannot create folder in manual " + "transaction mode", "RalDatabase"); + } + bool readOnly = false; + FolderVersioning::Mode versioningMode = folderSpec.versioningMode(); + const IRecordSpecification& payloadSpec = folderSpec.payloadSpecification(); + RelationalTransaction transaction( transactionMgr(), readOnly ); + IFolderPtr folder = + __createFolder( fullPath, payloadSpec, description, + versioningMode, createParents ); + transaction.commit(); + return folder; +} + +//----------------------------------------------------------------------------- + +IFolderPtr RalDatabase::__createFolder +( const std::string& fullPath, + const IRecordSpecification& payloadSpec, + const std::string& description, + FolderVersioning::Mode versioningMode, + bool createParents ) +{ + log() << coral::Verbose + << "Create folder " << fullPath << coral::MessageStream::endmsg; + + // Cross-check that the database is open + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + // Validate the payload specification. + // Throws InvalidPayloadSpecification if the payload spec is invalid: + // there can be at most 900 fields, including up to 10 BLOB fields; + // field names must have between 1 and 30 characters (including only + // letters, digits or '_'), must start with a letter and cannot start + // with the "COOL_" prefix (in any lowercase/uppercase combination). + validatePayloadSpecification( payloadSpec ); + + // Register the folder in the node table + std::string payloadSpecDesc = encodeRecordSpecification( payloadSpec ); + + bool isLeaf = true; + unsigned int nodeId = insertNodeTableRow + ( fullPath, description, createParents, + isLeaf, payloadSpecDesc, versioningMode ); + + // Create the IOV table for the folder + std::string objectTableName = RelationalObjectTable::defaultTableName + ( defaultTablePrefix(), nodeId ); + std::string obj2tagTableName = RelationalObject2TagTable::defaultTableName + ( defaultTablePrefix(), nodeId ); + std::string tagTableName = RelationalTagTable::defaultTableName + ( defaultTablePrefix(), nodeId ); + std::string tagSequenceName = RelationalTagSequence::sequenceName + ( defaultTablePrefix(), nodeId ); + std::string channelTableName = + RelationalChannelTable::defaultTableName( defaultTablePrefix(), nodeId ); + + if ( versioningMode == FolderVersioning::SINGLE_VERSION || + versioningMode == FolderVersioning::MULTI_VERSION ) { + + schemaMgr().createChannelTable( channelTableName ); + schemaMgr().createObjectTable + ( objectTableName, channelTableName, payloadSpec, versioningMode ); + if ( versioningMode == FolderVersioning::MULTI_VERSION ) { + schemaMgr().createTagSequence( tagSequenceName ); + schemaMgr().createTagTable( tagTableName ); + schemaMgr().createObject2TagTable + ( obj2tagTableName, objectTableName, tagTableName ); + } + + } else { + std::stringstream s; + s << "Invalid versioning mode specified: " << versioningMode; + throw RelationalException( s.str(), "RalDatabase" ); + } + + // TEMPORARY? Sleep to work around the ORA-01466 problem (Oracle only) + if ( m_sessionMgr->databaseTechnology() == "Oracle" && m_useTimeout ) { + log() << "Sleep to work around the ORA-01466 problem" + << coral::MessageStream::endmsg; + cool::sleep(1); + } + + // Get and return the IFolder instance for the folder that has just been + // created [NB This causes a second round trip to fetch the data that has + // just been written, but performance impact is low because folder creation + // is a relatively rare operation, and it's more modular to use getFolder] + log() << coral::Verbose + << "Created folder " << fullPath + << ": now fetch it and return it" << coral::MessageStream::endmsg; + return __getFolder( fullPath ); + +} + +//----------------------------------------------------------------------------- + +void RalDatabase::updateNodeTableDescription +( const std::string& fullPath, const std::string& description ) const +{ + log() << "Updating node description at path: " + << fullPath << coral::MessageStream::endmsg; + + // Cross-check that the database is open and start a transaction + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + RelationalTransaction transaction( transactionMgr() ); // read-write + + // Define the SET and WHERE clauses for the update using bind variables + coral::AttributeList updateData; + updateData.extend + ( "desc", + typeIdToCoralType(RelationalNodeTable::columnTypeIds::nodeDescription) ); + updateData.extend + ( "path", + typeIdToCoralType(RelationalNodeTable::columnTypeIds::nodeFullPath) ); + updateData["desc"].setValue( description ); + updateData["path"].setValue( fullPath ); + std::string setClause = RelationalNodeTable::columnNames::nodeDescription; + setClause += "= :desc"; + setClause += ", "; + setClause += RelationalNodeTable::columnNames::lastModDate; + setClause += " = " + queryMgr().serverTimeClause(); + std::string whereClause = RelationalNodeTable::columnNames::nodeFullPath; + whereClause += "= :path"; + + // Execute the update + if ( 1 != queryMgr().updateTableRows + ( nodeTableName(), setClause, whereClause, updateData ) ) + throw RowNotUpdated + ( "Could not update a row of the node table", "RalDatabase" ); + + // Commit the transaction + transaction.commit(); +} + +//----------------------------------------------------------------------------- + +IFolderPtr RalDatabase::getFolder( const std::string& fullPath ) +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + bool readOnly = true; + RelationalTransaction transaction( transactionMgr(), readOnly ); + IFolderPtr folder = __getFolder( fullPath ); + transaction.commit(); + return folder; +} + +//----------------------------------------------------------------------------- + +IFolderPtr RalDatabase::__getFolder( const std::string& fullPath ) +{ + if ( TimingReportMgr::isActive() ) + TimingReportMgr::startTimer( "cool::RalDatabase::__getFolder()" ); + + log() << "Get folder with name " << fullPath << coral::MessageStream::endmsg; + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + IFolderPtr folder; + + // For Update connections, fetch each folder every time + if ( !sessionMgr()->isReadOnly() ) + { + try { + RelationalTableRow row = fetchNodeTableRow( fullPath ); + folder = __getFolder( row ); + } catch ( NodeTableRowNotFound& ) { + throw FolderNotFound( fullPath, "RalDatabase" ); + } + } + + // For ReadOnly connections, use the folder cache + else + { + if ( m_nodes.size() == 0 ) __preloadAllNodes(); + if ( m_nodes.find( fullPath ) != m_nodes.end() ) + folder = __getFolder( *m_nodes[fullPath] ); + else + throw FolderNotFound( fullPath, "RalDatabase" ); + } + + if ( TimingReportMgr::isActive() ) + TimingReportMgr::stopTimer( "cool::RalDatabase::__getFolder()" ); + return folder; +} + +//----------------------------------------------------------------------------- + +IFolderPtr RalDatabase::__getFolder( const RelationalTableRow& row ) +{ + std::string fullPath = + row[RelationalNodeTable::columnNames::nodeFullPath].data<std::string>(); + bool isLeaf = + row[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + if ( ! isLeaf ) + throw FolderNotFound( fullPath, "RalDatabase", true ); + VersionNumber schemaVersion = + row[RelationalNodeTable::columnNames::nodeSchemaVersion] + .data<std::string>(); + IFolderPtr folder; + // Handle all well-defined hardcoded folder schema versions supported by + // the RelationalFolder class; return an unusable Unsupported folder + // for folders with schema versions higher than the present s/w release; + // throw a PANIC exception for all other values (should never happen!). + if ( RelationalFolder::isSupportedSchemaVersion( schemaVersion ) ) + { + folder.reset + ( new RelationalFolder( relationalDbPtr(), row.data() ) ); + } + else if ( VersionInfo::release < schemaVersion ) + { + folder.reset + ( new RelationalFolderUnsupported( relationalDbPtr(), row.data() ) ); + } + else if ( schemaVersion == VersionNumber( "2.0.0" ) ) + { + folder.reset + ( new RelationalFolderUnsupported( relationalDbPtr(), row.data() ) ); + //throw UnsupportedFolderSchema + // ( fullPath, schemaVersion, "RelationalFolderUnsupported" ); + } + else + { + std::stringstream s; + s << "PANIC! Cannot get folder '" << fullPath + << "': it appears to have been created using UNKNOWN schema version " + << schemaVersion + << " that is older than (or as old as) the current software release " + << VersionInfo::release; + throw RelationalException( s.str(), "RalDatabase" ); + } + return folder; +} + +//----------------------------------------------------------------------------- + +IFolderSetPtr RalDatabase::getFolderSet( const std::string& fullPath ) +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + RelationalTransaction transaction( transactionMgr(), true ); // read-only + IFolderSetPtr folderset = __getFolderSet( fullPath ); + transaction.commit(); + return folderset; +} + +//----------------------------------------------------------------------------- + +IFolderSetPtr RalDatabase::__getFolderSet( const std::string& fullPath ) +{ + log() << "Get folderset with name " << fullPath + << coral::MessageStream::endmsg; + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + IFolderSetPtr folderSet; + + // For Update connections, fetch each folder every time + if ( !sessionMgr()->isReadOnly() ) + { + try { + RelationalTableRow row = fetchNodeTableRow( fullPath ); + folderSet = __getFolderSet( row ); + } catch ( NodeTableRowNotFound& ) { + throw FolderSetNotFound( fullPath, "RalDatabase" ); + } + } + + // For ReadOnly connections, use the folder cache + else + { + if ( m_nodes.size() == 0 ) __preloadAllNodes(); + if ( m_nodes.find( fullPath ) != m_nodes.end() ) + folderSet = __getFolderSet( *m_nodes[fullPath] ); + else + throw FolderSetNotFound( fullPath, "RalDatabase" ); + } + + return folderSet; +} + +//----------------------------------------------------------------------------- + +IFolderSetPtr RalDatabase::__getFolderSet( const RelationalTableRow& row ) +{ + std::string fullPath = + row[RelationalNodeTable::columnNames::nodeFullPath].data<std::string>(); + bool isLeaf = + row[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + if ( isLeaf ) + throw FolderSetNotFound( fullPath, "RalDatabase", true ); + VersionNumber schemaVersion = + row[RelationalNodeTable::columnNames::nodeSchemaVersion] + .data<std::string>(); + IFolderSetPtr folderSet; + // Handle all well-defined hardcoded folder set schema versions supported by + // the RelationalFolderSet class; return an unusable Unsupported folderSet + // for folder sets with schema versions higher than the present s/w release; + // throw a PANIC exception for all other values (should never happen!). + if ( RelationalFolderSet::isSupportedSchemaVersion( schemaVersion ) ) + { + folderSet.reset + ( new RelationalFolderSet( relationalDbPtr(), row.data() ) ); + } + else if ( VersionInfo::release < schemaVersion ) + { + folderSet.reset + ( new RelationalFolderSetUnsupported( relationalDbPtr(), row.data() ) ); + } + else + { + std::stringstream s; + s << "PANIC! Cannot get folder set '" << fullPath + << "': it appears to have been created using UNKNOWN schema version " + << schemaVersion + << " that is older than (or as old as) the current software release " + << VersionInfo::release; + throw RelationalException( s.str(), "RalDatabase" ); + } + return folderSet; +} + +//----------------------------------------------------------------------------- + +void RalDatabase::__preloadAllNodes() +{ + log() << "Preload all nodes" << coral::MessageStream::endmsg; + + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + if ( m_nodes.size() != 0 ) + throw RelationalException + ( "PANIC! Nodes already preloaded", "RalDatabase" ); + + if ( !sessionMgr()->isReadOnly() ) + throw RelationalException + ( "PANIC! Cannot preload nodes in update mode", "RalDatabase" ); + + std::vector<RelationalTableRow> rows = nodeMgr().fetchAllNodeTableRows(); + + // Loop over all nodes in the node table + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + std::string fullPath = + (*row)[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + + if ( m_nodes.find( fullPath ) != m_nodes.end() ) + { + std::stringstream s; + s << "PANIC! Node '" << fullPath + << "' was found more than once in the node table!"; + throw RelationalException( s.str(), "RalDatabase" ); + } + + m_nodes[fullPath] = new RelationalTableRow( *row ); + + } +} + +//----------------------------------------------------------------------------- + +bool RalDatabase::dropAllNodes() +{ + log() << coral::Info << "Drop all nodes..." << coral::MessageStream::endmsg; + + // AV 2005-07-07 + // Return true if all node, tag and tag2tag rows are deleted and all folder + // tables (for nodes that are folders) are dropped as expected. + // Return false (without throwing any exception) if the node rows and + // any associated tables do not exist any more on exit from this method, + // but some node rows or associated tables did not exist to start with. + bool status = true; + + // Throw an Exception if the schema of one of the nodes in this database + // is more recent than the schema version supported by the current release: + // in this case make sure you do not drop ANY node (throw immediately)! + { + // Start a read-only transaction + RelationalTransaction transaction( transactionMgr(), true ); + + // Iterate over all folders and folder sets and compare schema versions + // to a well-defined hardcoded list supported by this s/w release + coral::AttributeList whereData; // select all + std::string whereClause; // select all + std::vector<RelationalTableRow> rows = + queryMgr().fetchRowsFromTables + ( RelationalQueryMgr::tableList( nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification() ), + whereClause, whereData, "" ); + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); row++ ) + { + const std::string fullPath = + (*row)[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + bool isLeaf = + (*row)[RelationalNodeTable::columnNames::nodeIsLeaf] + .data<bool>(); + const VersionNumber schemaVersion = + (*row)[RelationalNodeTable::columnNames::nodeSchemaVersion] + .data<std::string>(); + bool isSupported = true; + if ( isLeaf ) { + if ( !RelationalFolder::isSupportedSchemaVersion( schemaVersion ) ) + isSupported = false; + } + else { + if ( !RelationalFolderSet::isSupportedSchemaVersion( schemaVersion ) ) + isSupported = false; + } + if ( VersionInfo::release < schemaVersion ) { + std::stringstream s; + s << "Cannot drop database:"; + if ( isLeaf ) s << " folder '"; + else s << " folder set '"; + s << fullPath << " has schema version " << schemaVersion + << " that is newer than this software release " + << VersionInfo::release; + log() << coral::Warning << s.str() << coral::MessageStream::endmsg; + throw RelationalException( s.str(), "RalDatabase" ); + } + else if ( ! isSupported ) { + std::stringstream s; + s << "PANIC! Cannot drop database:"; + if ( isLeaf ) s << " folder '"; + else s << " folder set '"; + s << fullPath + << "' appears to have been created using UNKNOWN schema version " + << schemaVersion + << " that is older than (or as old as) the current software release " + << VersionInfo::release; + throw RelationalException( s.str(), "RalDatabase" ); + } + } + + // Commit the transaction + transaction.commit(); + } + + // Throw a RelationalException if a node row cannot be deleted or one table + // cannot be dropped (i.e. continues to exist on exit from this method). + + // Listing the nodes in reverse order ensures that integrity constraints + // are not violated (children are dropped before their parents) + std::vector<std::string> nodes( listAllNodes( false ) ); + std::vector<std::string>::const_iterator node; + log() << coral::Debug << "Will drop nodes in this order:" + << coral::MessageStream::endmsg; + for ( node = nodes.begin(); node != nodes.end(); node++ ) + { + log() << coral::Debug << "Will drop '" << *node << "'" + << coral::MessageStream::endmsg; + } + for ( node = nodes.begin(); node != nodes.end(); node++ ) + { + log() << coral::Debug << "Now drop '" << *node << "'" + << coral::MessageStream::endmsg; + if ( ! dropNode( *node ) ) status = false; + } + + // Success: the nodes do not exist anymore + // Return status code 'false' if some nodes or tables were missing already + log() << coral::Info << "Drop all nodes... DONE" + << coral::MessageStream::endmsg; + return status; + +} + +//----------------------------------------------------------------------------- + +bool RalDatabase::dropNode( const std::string& fullPath ) +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + log() << coral::Debug << "Drop node '" << fullPath << "' ..." + << coral::MessageStream::endmsg; + + RelationalTransaction transaction( transactionMgr() ); + bool status = __dropNode( fullPath ); + transaction.commit(); + + log() << coral::Debug << "Drop node '" << fullPath << "' ... DONE" + << coral::MessageStream::endmsg; + + return status; +} + +//----------------------------------------------------------------------------- + +bool RalDatabase::__dropNode( const std::string& fullPath ) +{ + log() << "Drop node with full path " << fullPath + << coral::MessageStream::endmsg; + if ( ! isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + // AV 2005-07-07 + // Return true if the node, tag and tag2tag rows for this node are deleted + // and all folder tables (if the node is a folder) are dropped as expected. + // Return false (without throwing any exception) if any such row and + // any associated tables do not exist any more on exit from this method, + // but the node or some associated tables did not exist to start with. + bool status = true; + + // Throw a RelationalException if the node row cannot be deleted or one table + // cannot be dropped (i.e. continues to exist on exit from this method). + // Throw a RelationalException if the node is a non-empty folder set. + // Also deletes any tags and tag2tag associated to the node + // (and throws a RelationalException if such tags cannot be deleted). + + // Fetch the row for this node + RelationalTableRow nodeRow; + try { + nodeRow = fetchNodeTableRow( fullPath ); + } catch ( NodeTableRowNotFound& ) { + // A node with this name does not exist: nothing to drop + log() << coral::Warning << "Node '" << fullPath + << "' cannot be dropped (node not found)" + << coral::MessageStream::endmsg; + return false; + } catch ( coral::QueryException& e ) { + // The query on the node table failed: for instance, the query may fail + // with ORA-00904 if some columns are missing from the node table because + // the process that created the database crashed or was killed while + // altering the node table to change the SQL type of its columns + log() << coral::Warning << "The node table cannot be queried: '" + << e.what() << coral::MessageStream::endmsg; + return false; + } + bool isLeaf = + nodeRow[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + unsigned int nodeId = + nodeRow[RelationalNodeTable::columnNames::nodeId].data<unsigned int>(); + + // Throw TagIsLocked if any tags applied to this node are locked + // (either LOCKED or PARTIALLYLOCKED - both are equivalent here) + { + std::vector<RelationalTableRow> rows = + tagMgr().fetchGlobalTagTableRows( nodeId ); + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + HvsTagLock::Status lockStatus = + HvsTagLock::Status + ( (*row)[RelationalGlobalTagTable::columnNames::tagLockStatus] + .data<UInt16>() ); + if ( lockStatus != HvsTagLock::UNLOCKED ) { + std::string tagName = + (*row)[RelationalGlobalTagTable::columnNames::tagName] + .data<std::string>(); + throw TagIsLocked + ( "Cannot drop node '" + fullPath + + "': tag '" + tagName + "' is locked", "RalDatabase" ); + } + } + } + + // Check that the node schema version is supported by this software release + VersionNumber schemaVersion = + nodeRow[RelationalNodeTable::columnNames::nodeSchemaVersion] + .data<std::string>(); + bool isSupported = true; + if ( isLeaf ) { + if ( !RelationalFolder::isSupportedSchemaVersion( schemaVersion ) ) + isSupported = false; + } + else { + if ( !RelationalFolderSet::isSupportedSchemaVersion( schemaVersion ) ) + isSupported = false; + } + if ( VersionInfo::release < schemaVersion ) + { + std::stringstream s; + s << "Cannot drop node:"; + if ( isLeaf ) s << " folder '"; + else s << " folder set '"; + s << fullPath << " has schema version " << schemaVersion + << " that is newer than this software release " + << VersionInfo::release; + log() << coral::Warning << s.str() << coral::MessageStream::endmsg; + throw RelationalException( s.str(), "RalDatabase" ); + } + else if ( !isSupported ) + { + std::stringstream s; + s << "PANIC! Cannot drop node:"; + if ( isLeaf ) s << " folder '"; + else s << " folder set '"; + s << fullPath + << "' appears to have been created using UNKNOWN schema version " + << schemaVersion + << " that is older than (or as old as) the current software release " + << VersionInfo::release; + throw RelationalException( s.str(), "RalDatabase" ); + } + + // Folder: drop folder-specific tables and sequences + if ( isLeaf ) + { + std::string objectTableName = + RelationalFolder::objectTableName( nodeRow.data() ); + std::string tagTableName = + RelationalFolder::tagTableName( nodeRow.data() ); + std::string object2TagTableName = + RelationalFolder::object2TagTableName( nodeRow.data() ); + FolderVersioning::Mode versioningMode = + RelationalFolder::versioningMode( nodeRow.data() ); + std::string tagSequenceName = RelationalTagSequence::sequenceName + ( defaultTablePrefix(), nodeId ); + std::string tableName; + std::string seqName; + // Drop tables for MV folders + if ( versioningMode == FolderVersioning::MULTI_VERSION ) + { + // Drop iov2tag table first as it has FK constraints on the other tables + tableName = object2TagTableName; + log() << "Drop table " << tableName << coral::MessageStream::endmsg; + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + // Drop local tag table + tableName = tagTableName; + log() << "Drop table " << tableName << coral::MessageStream::endmsg; + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + // Drop local tag sequence + seqName = tagSequenceName; + log() << "Drop sequence " << seqName << coral::MessageStream::endmsg; + if ( ! queryMgr().sequenceMgr().existsSequence( seqName ) ) { + status = false; + } else { + queryMgr().sequenceMgr().dropSequence( seqName ); + } + } + // Drop iov table + tableName = objectTableName; + log() << "Drop table " << tableName << coral::MessageStream::endmsg; + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + // Drop iov sequence + seqName = RelationalObjectTable::sequenceName( objectTableName ); + log() << "Drop sequence " << seqName << coral::MessageStream::endmsg; + if ( ! queryMgr().sequenceMgr().existsSequence( seqName ) ) { + status = false; + } else { + queryMgr().sequenceMgr().dropSequence( seqName ); + } + // Drop channel table last as it is referenced by FKs in the iov table + tableName = + RelationalChannelTable::defaultTableName( defaultTablePrefix(), nodeId ); + log() << "Drop table " << tableName << coral::MessageStream::endmsg; + if ( ! schemaMgr().dropTable( tableName ) ) status = false; + } + + // Folder set: make sure it is empty before deleting it and drop tag sequence + else + { + // Make sure it is empty before deleting it + bool hasFolders = ! ( listNodes( nodeId, true ).empty() ); + bool hasFolderSets = ! ( listNodes( nodeId, false ).empty() ); + if ( hasFolders || hasFolderSets ) { + std::stringstream s; + s << "Cannot drop folderset '" << fullPath + << "', because it is not empty"; + throw RelationalException( s.str(), "RalDatabase" ); + } + // Drop local tag sequence + std::string tagSequenceName = RelationalTagSequence::sequenceName + ( defaultTablePrefix(), nodeId ); + std::string seqName = tagSequenceName; + log() << "Drop sequence " << seqName << coral::MessageStream::endmsg; + if ( ! queryMgr().sequenceMgr().existsSequence( seqName ) ) { + status = false; + } else { + queryMgr().sequenceMgr().dropSequence( seqName ); + } + } + + // Delete all tag2tag relations associated to this node + if ( ! session().nominalSchema().existsTable( tag2TagTableName() ) ) + status = false; + else + tagMgr().deleteTag2TagTableRowsForNode( nodeId ); + + // Delete all global tags associated to this node + if ( ! session().nominalSchema().existsTable( globalTagTableName() ) ) + status = false; + else + tagMgr().deleteGlobalTagTableRowsForNode( nodeId ); + + // Delete the node from the node table + coral::AttributeList whereData; + whereData.extend + ( "fullName", + typeIdToCoralType(RelationalNodeTable::columnTypeIds::nodeFullPath) ); + whereData["fullName"].setValue( fullPath ); + std::string whereClause = RelationalNodeTable::columnNames::nodeFullPath; + whereClause += "= :fullName"; + queryMgr().deleteTableRows + ( nodeTableName(), whereClause, whereData, 1 ); + + // Success: the node does not exist anymore + // Return status code 'false' if the node or some tables were missing already + return status; +} + +//----------------------------------------------------------------------------- + +boost::shared_ptr<RelationalObjectTable> +RalDatabase::relationalObjectTable( const RelationalFolder& folder ) const +{ + boost::shared_ptr<RelationalObjectTable> + objectTable( new RelationalObjectTable( &(queryMgr()), false, folder ) ); + return objectTable; +} + +//----------------------------------------------------------------------------- + +boost::shared_ptr<RalSessionMgr> RalDatabase::sessionMgr() const +{ + return m_sessionMgr; +} + +//----------------------------------------------------------------------------- + +coral::ISessionProxy& RalDatabase::session() const +{ + return m_sessionMgr->session(); +} + +//----------------------------------------------------------------------------- + +bool RalDatabase::isConnected() const +{ + return m_sessionMgr->isConnected(); +} + +//----------------------------------------------------------------------------- + +void RalDatabase::connect() +{ + return m_sessionMgr->connect(); +} + +//----------------------------------------------------------------------------- + +void RalDatabase::disconnect() +{ + return m_sessionMgr->disconnect(); +} + +//----------------------------------------------------------------------------- + +#ifdef COOL280 +ITransactionPtr RalDatabase::startTransaction() +{ + transactionMgr()->setAutoTransactions( false ); + return ITransactionPtr( new ManualTransaction( transactionMgr() ) ); +} +#endif + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RalDatabase.h b/RelationalCool/src/RalDatabase.h new file mode 100644 index 000000000..62465c3b4 --- /dev/null +++ b/RelationalCool/src/RalDatabase.h @@ -0,0 +1,285 @@ +// $Id: RalDatabase.h,v 1.224 2009-01-06 12:30:07 avalassi Exp $ +#ifndef RELATIONALCOOL_RALDATABASE_H +#define RELATIONALCOOL_RALDATABASE_H 1 + +// Include files +#include "RelationalAccess/ISessionProxy.h" + +// Local include files +#include "CoralConnectionServiceProxy.h" +#include "RalSessionMgr.h" +#include "RelationalDatabase.h" + +namespace cool +{ + + // Forward declarations + class RalDatabase; + class RalObjectMgr; + class RelationalObjectTableRow; + class RelationalSequence; + class RelationalTableRow; + class SimpleObject; + + // Type definitions + typedef boost::shared_ptr<RalDatabase> RalDatabasePtr; + + /** @class RalDatabase RalDatabase.h + * + * RAL implementation of one COOL "condition database" instance + * (deployed on a specific physical infrastructure). + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2004-11-09 + */ + + class RalDatabase : public RelationalDatabase + , public boost::enable_shared_from_this<RalDatabase> + { + + friend class MemoryConsumptionTest; + friend class RalDatabaseTest; + friend class RalDatabaseTest_extendedSpec; + friend class RalDatabaseTest_versioning; + friend class RalSequenceTest; + friend class RelationalObjectMgrTest; + friend class RelationalObjectTableTest; + + // Only the RalDatabaseSvc can instantiate or delete a RalDatabase + friend class RalDatabaseSvc; + + // Also the RalSchemaEvolution manager can access all internal methods + friend class RalSchemaEvolution; + + // Only the boost shared pointer can delete a RalDatabase: see + // http://www.boost.org/libs/smart_ptr/sp_techniques.html#preventing_delete + class deleter; + friend class deleter; + + public: + + /// Get a CORAL MessageStream + coral::MessageStream& log() const + { + return RelationalDatabase::log(); + } + + /// Returns the RAL session manager connected to the database. + boost::shared_ptr<RalSessionMgr> sessionMgr() const; + + /// Required access mode to the database. + bool isReadOnly() const + { + return sessionMgr()->isReadOnly(); + } + + /// Returns the database session. + /// Delegated to RalSessionMgr. + coral::ISessionProxy& session() const; + + /// Create a new folder set + /// Starts a transaction + IFolderSetPtr createFolderSet + ( const std::string& fullPath, + const std::string& description = "", + bool createParents = false ); + + /// Create a new folder set + /// Does not start a transaction (prefix __) + IFolderSetPtr __createFolderSet + ( const std::string& fullPath, + const std::string& description = "", + bool createParents = false ); + + /// Retrieve an existing folderset and return the corresponding manager + /// Throw an exception if the folderset does not exist + /// Starts a transaction + IFolderSetPtr getFolderSet( const std::string& fullPath ); + + /// Retrieve an existing folderset and return the corresponding manager + /// Throw an exception if the folderset does not exist + /// Does not start a transaction (prefix __) + IFolderSetPtr __getFolderSet( const std::string& fullPath ); + + /// Return the folderset manager for a given row + /// Does not start a transaction (prefix __) + IFolderSetPtr __getFolderSet( const RelationalTableRow& row ); + + /// Create a new folder and return the corresponding manager. + /// The ownership of the folder manager instance is shared. + /// Throws DatabaseNotOpen if there is no connection to the database. + /// Throws HvsPathHandlerException if the given path has an invalid format. + /// Throws NodeExists if a folder[set] with the same path already exists. + /// Throws an Exception if the max# of folder[set]s (9999) is exceeded. + /// Throws an Exception if an invalid versioning mode has been specified. + IFolderPtr createFolder + ( const std::string& fullPath, + const IFolderSpecification& folderSpec, + const std::string& description = "", + bool createParents = false ); + + /// DEPRECATED: this is likely to be removed in the next major release + /// (similar to the COOL133 API, with IRecordSpecification instead of + /// ExtendedAttributeListSpecification: use IFolderSpecification instead). + IFolderPtr createFolder + ( const std::string& fullPath, + const IRecordSpecification& payloadSpec, + const std::string& description = "", + FolderVersioning::Mode mode = FolderVersioning::SINGLE_VERSION, + bool createParents = false ); + + /// Create a new folder and return the corresponding manager + /// The ownership of the folder manager instance is shared + /// Does not start a transaction (prefix __) + IFolderPtr __createFolder + ( const std::string& fullPath, + const IRecordSpecification& payloadSpec, + const std::string& description = "", + FolderVersioning::Mode mode = FolderVersioning::SINGLE_VERSION, + bool createParents = false ); + + /// Retrieve an existing folder and return the corresponding manager + /// Throw an exception if the folder does not exist + IFolderPtr getFolder( const std::string& fullPath ); + + /// Retrieve an existing folder and return the corresponding manager + /// Throw an exception if the folder does not exist + /// Does not start a transaction (prefix __) + IFolderPtr __getFolder( const std::string& fullPath ); + + /// Return the folder manager for a given row + /// Does not start a transaction (prefix __) + IFolderPtr __getFolder( const RelationalTableRow& row ); + + /// Retrieve all existing folders and folder sets + /// (preload the cache - used for ReadOnly connections only) + /// Does not start a transaction (prefix __) + void __preloadAllNodes(); + + /// Drop an existing node. + bool dropNode( const std::string& fullPath ); + + /// Drop an existing node. + /// Does not start a transaction (prefix __). + bool __dropNode( const std::string& fullPath ); + + /// Get a RelationalObjectTable for the given folder. + /// The concrete class can only be created by the concrete database. + /// The RelationalFolder parameter is only used to obtain + /// the associated table names and is *not* retained. + boost::shared_ptr<RelationalObjectTable> + relationalObjectTable( const RelationalFolder& folder ) const; + + /// Return the RelationalDatabasePtr + RelationalDatabasePtr relationalDbPtr() + { + return shared_from_this(); + } + + /// Return the connection state of the database. + /// This is different from isOpen(): isConnected() refers only to the + /// connection to the server, a prerequisite to the actual opening of + /// a COOL "database" (which implies reading the management tables). + /// Delegated to RalSessionMgr. + bool isConnected() const; + + /// (Re)connect to the database. + /// Delegated to RalSessionMgr. + void connect(); + + /// Close the database connection. + /// Delegated to RalSessionMgr. + void disconnect(); + +#ifdef COOL280 + /// Start a new transaction and enter manual transaction mode + virtual ITransactionPtr startTransaction(); +#endif + + protected: + + /// The following methods are all protected: only a RalDatabaseSvc can + /// instantiate or delete this class and create, drop or open a database + + /// Constructor + /// Throws a RelationalException if the RelationalService handle is NULL. + /// Throws a RelationalException if a connection cannot be established. + RalDatabase( CoralConnectionServiceProxyPtr ppConnSvc, + const DatabaseId& dbId, + bool readOnly ); + + /// Destructor + virtual ~RalDatabase(); + + /// Create a new database with default attributes + /// Default attributes are those specific for a RelationalDatabase + /// Expose in the public API a protected RelationalDatabase method. + void createDatabase() { + return RelationalDatabase::createDatabase(); + } + + /// Create a new database with non-default attributes. + /// Throw a RelationalException if the given attributes are invalid. + void createDatabase( const IRecord& dbAttr ); + + /// Drop the database + bool dropDatabase(); + + private: + + /// Standard constructor is private + RalDatabase(); + + /// Copy constructor is private + RalDatabase( const RalDatabase& rhs ); + + /// Assignment operator is private + RalDatabase& operator=( const RalDatabase& rhs ); + + /// Update the description for the given node + void updateNodeTableDescription( const std::string& fullPath, + const std::string& description ) const; + + /// Drops all folders + bool dropAllNodes(); + + /// Creates a new entry in the folder table + /// Returns the node id of the new entry + UInt32 insertNodeTableRow + ( const std::string& fullPath, + const std::string& description, + bool createParents, + bool isLeaf, + const std::string& payloadSpecDesc, + FolderVersioning::Mode versioningMode ); + + /// Set the useTimeout flag + void setUseTimeout( bool flag ) { m_useTimeout = flag; } + + /// Private deleter class + class deleter + { + public: + void operator()( RalDatabase* pDb ) { + delete pDb; + } + }; + + private: + + /// Map of all nodes (cache - only used for ReadOnly connections) + /// NB Do not use IFolderPtr/IFolderSetPtr: RalDatabase is never deleted! + std::map< std::string, RelationalTableRow* > m_nodes; + + /// Switch on the schema change timeout (ORA-01466 problem) + bool m_useTimeout; + + /// RAL session manager connected to the database + /// (created by this instance, but ownership shared, e.g. with query mgr) + boost::shared_ptr<RalSessionMgr> m_sessionMgr; + + }; + +} + +#endif // RELATIONALCOOL_RALDATABASE_H diff --git a/RelationalCool/src/RalDatabaseSvc.cpp b/RelationalCool/src/RalDatabaseSvc.cpp new file mode 100644 index 000000000..c0cb1f14f --- /dev/null +++ b/RelationalCool/src/RalDatabaseSvc.cpp @@ -0,0 +1,169 @@ +// $Id: RalDatabaseSvc.cpp,v 1.53 2008-11-04 11:52:10 avalassi Exp $ + +// Include files +#include <iostream> + +// Local include files +#include "RalDatabase.h" +#include "RalDatabaseSvc.h" +#include "RelationalException.h" +//#include "TimingReportMgr.h" +#include "VersionInfo.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RalDatabaseSvc::RalDatabaseSvc +( coral::IConnectionService& connSvc ) + : m_log( new coral::MessageStream( "RalDatabaseSvc" ) ) + , m_ppConnSvc( new CoralConnectionServiceProxy( &connSvc ) ) +{ + initialize(); +} + +//----------------------------------------------------------------------------- + +void RalDatabaseSvc::initialize() +{ + log() << coral::Info << "Instantiate the RalDatabaseSvc" + << coral::MessageStream::endmsg; + + // Initialize timing reports + //std::cout << "Initialize timing reports" << std::endl; + //TimingReportMgr::initialize(); + //TimingReportMgr::startTimer( "TOTAL - RalDatabaseSvc" ); +} + +//----------------------------------------------------------------------------- + +RalDatabaseSvc::~RalDatabaseSvc() +{ + log() << coral::Info << "Delete the RalDatabaseSvc..." + << coral::MessageStream::endmsg; + + // Finalize timing reports + // WARNING: RalDatabaseSvc is generally not deleted (eg in PyCool)... + //std::cout << "Finalize timing reports" << std::endl; + //TimingReportMgr::stopTimer( "TOTAL - RalDatabaseSvc" ); + //TimingReportMgr::finalize(); + + log() << coral::Info << "Purge the connection pool" + << coral::MessageStream::endmsg; + m_ppConnSvc->purgeConnectionPool(); + log() << coral::Info << "Reset the ICS pointer" + << coral::MessageStream::endmsg; + m_ppConnSvc->resetICS(); + + log() << coral::Info << "Delete the RalDatabaseSvc... DONE" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RalDatabaseSvc::log() const +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +IDatabasePtr +RalDatabaseSvc::createDatabase( const DatabaseId& dbId ) const +{ + log() << "Create database" << coral::MessageStream::endmsg; + RalDatabase* ralDb = 0; + try { + bool readOnly = false; + ralDb = new RalDatabase( m_ppConnSvc, dbId, readOnly ); + ralDb->createDatabase(); + IDatabasePtr db ( ralDb, RalDatabase::deleter() ); + log() << "Create database - success" << coral::MessageStream::endmsg; + return db; + } catch ( ... ) { + if (ralDb) delete ralDb; + log() << "Create database - failure" << coral::MessageStream::endmsg; + throw; + } +} + +//----------------------------------------------------------------------------- + +/* +IDatabasePtr +RalDatabaseSvc::createDatabase( const DatabaseId& dbId, + const coral::AttributeList& dbAttr ) const +{ + RalDatabase* ralDb = new RalDatabase( localContext(), dbId ); + ralDb->createDatabase( dbAttr ); + IDatabasePtr db ( ralDb ); + return db; +} +*/ + +//----------------------------------------------------------------------------- + +IDatabasePtr RalDatabaseSvc::openDatabase( const DatabaseId& dbId, + bool readOnly ) const +{ + log() << "Open database" << coral::MessageStream::endmsg; + RalDatabase* ralDb = 0; + try { + ralDb = new RalDatabase( m_ppConnSvc, dbId, readOnly ); + ralDb->openDatabase(); + IDatabasePtr db ( ralDb, RalDatabase::deleter() ); + log() << "Open database - success" << coral::MessageStream::endmsg; + return db; + } catch ( ... ) { + if (ralDb) delete ralDb; + log() << "Open database - failure" << coral::MessageStream::endmsg; + throw; + } +} + +//----------------------------------------------------------------------------- + +bool RalDatabaseSvc::dropDatabase( const DatabaseId& dbId ) const +{ + log() << "Drop database" << coral::MessageStream::endmsg; + try { + bool readOnly = false; + RalDatabase db( m_ppConnSvc, dbId, readOnly ); + // Open the database (also check if the database exists) + try { + db.openDatabase(); + } catch ( DatabaseDoesNotExist& /* dummy */ ) { + log() << "Drop database - success (database not found)" + << coral::MessageStream::endmsg; + return false; + } + // The database exists: drop it + bool status = db.dropDatabase(); + log() << "Drop database - success" << coral::MessageStream::endmsg; + return status; + } + // Throw an exception if the database exists but cannot be dropped + catch ( ... ) { + log() << "Drop database - failure" << coral::MessageStream::endmsg; + throw; + } +} + +//----------------------------------------------------------------------------- + +const std::string RalDatabaseSvc::serviceVersion() const +{ + return VersionInfo::release; +} + +//----------------------------------------------------------------------------- + +coral::IConnectionService& RalDatabaseSvc::connectionSvc() const +{ + // Return the CORAL connection service PROXY! + return *m_ppConnSvc; +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RalDatabaseSvc.h b/RelationalCool/src/RalDatabaseSvc.h new file mode 100644 index 000000000..918271744 --- /dev/null +++ b/RelationalCool/src/RalDatabaseSvc.h @@ -0,0 +1,96 @@ +// $Id: RalDatabaseSvc.h,v 1.32 2008-11-04 11:52:10 avalassi Exp $ +#ifndef RELATIONALCOOL_RALDATABASESVC_H +#define RELATIONALCOOL_RALDATABASESVC_H 1 + +// Include files +#include <memory> +#include "CoralBase/AttributeList.h" +#include "CoralBase/MessageStream.h" +#include "CoolKernel/IDatabaseSvc.h" + +// Local include files +#include "CoralConnectionServiceProxy.h" + +namespace cool +{ + + /** @class RalDatabaseSvc RalDatabaseSvc.h + * + * Top-level service to create, drop or open "conditions databases" + * using the RAL implementation of COOL. + * + * Implementation as a SEAL service inspired from RelationalService. + * Many thanks to Rado for his help with the SEAL component model! + * + * This class will typically be used as a singleton in a user application. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2004-11-09 + */ + + class RalDatabaseSvc : public IDatabaseSvc { + + public: + + /// Constructor + RalDatabaseSvc( coral::IConnectionService& connSvc ); + + /// Destructor + virtual ~RalDatabaseSvc(); + + /// Create a new database and return the corresponding manager + /// Use the default database attributes for the relevant implementation + /// The ownership of the database manager instance is shared + IDatabasePtr createDatabase( const DatabaseId& dbId ) const; + + + /* + /// Create a new database and return the corresponding manager + /// Specify non-default database attributes in an attribute list + /// The ownership of the database manager instance is shared + IDatabasePtr createDatabase( const DatabaseId& dbId, + const coral::AttributeList& dbAttr ) const; + */ + + /// Open an existing database and return the corresponding manager + /// The ownership of the database manager instance is shared + IDatabasePtr openDatabase( const DatabaseId& dbId, + bool readOnly ) const; + + /// Drop an existing database. + bool dropDatabase( const DatabaseId& dbId ) const; + + /// Retrieve the version number of the database service software. + const std::string serviceVersion() const; + + /// Get the CORAL connection service used by the application. + coral::IConnectionService& connectionSvc() const; + + /// Get the CORAL connection service used by the application. + CoralConnectionServiceProxyPtr ppConnectionSvc() const + { + return m_ppConnSvc; + }; + + private: + + /// Initialize the service + void initialize(); + + /// Get a CORAL MessageStream + coral::MessageStream& log() const; + + private: + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// Shared pointer to the CORAL connection service pointer. + /// When the database service is deleted, this points to a null pointer. + CoralConnectionServiceProxyPtr m_ppConnSvc; + + }; + +} + +#endif // RELATIONALCOOL_RALDATABASESVC_H diff --git a/RelationalCool/src/RalQueryMgr.cpp b/RelationalCool/src/RalQueryMgr.cpp new file mode 100644 index 000000000..f9f5089f8 --- /dev/null +++ b/RelationalCool/src/RalQueryMgr.cpp @@ -0,0 +1,804 @@ +// $Id: RalQueryMgr.cpp,v 1.100 2008-11-05 14:53:32 avalassi Exp $ + +#include <sstream> + +// Include files (COOL) +#include "CoolKernel/Record.h" + +// Include files (query management) +#include "CoralBase/Attribute.h" +#include "RelationalAccess/ICursor.h" +#include "RelationalAccess/IQuery.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" + +// Include files (update management) +#include "RelationalAccess/ITableDataEditor.h" + +// Local include files +#include "IRelationalQueryDefinition.h" +#include "RalBulkOperation.h" +#include "RalCursor.h" +#include "RalQueryMgr.h" +#include "RalSequenceMgr.h" +#include "RalSessionMgr.h" +#include "RelationalException.h" +#include "RelationalTableRow.h" +#include "TimingReportMgr.h" +//#include "attributeListToString.h" + +// Namespace +using namespace cool; + +//--------------------------------------------------------------------------- + +RalQueryMgr::RalQueryMgr( const boost::shared_ptr<RalSessionMgr>& sessionMgr ) + : RelationalQueryMgr() + , m_sessionMgr( sessionMgr ) +{ + log() << coral::Debug << "Instantiate a RalQueryMgr" + << coral::MessageStream::endmsg; + log() << coral::Debug << "Remote database technology: '" + << databaseTechnology() << "'" + << coral::MessageStream::endmsg; + m_sequenceMgr = new RalSequenceMgr( *this, m_sessionMgr ); +} + +//--------------------------------------------------------------------------- + +RalQueryMgr::~RalQueryMgr() +{ + log() << coral::Debug << "Delete the RalQueryMgr" + << coral::MessageStream::endmsg; + delete m_sequenceMgr; +} + +//--------------------------------------------------------------------------- + +RelationalQueryMgr* RalQueryMgr::clone() const +{ + log() << coral::Debug << "Clone a RalQueryMgr" + << coral::MessageStream::endmsg; + return new RalQueryMgr( m_sessionMgr ); +} + +//--------------------------------------------------------------------------- + +bool RalQueryMgr::existsTable( const std::string& tableName ) const +{ + return m_sessionMgr->session().nominalSchema().existsTable( tableName ); +} + +//--------------------------------------------------------------------------- + +const std::vector<RelationalTableRow> +RalQueryMgr::fetchOrderedRowsFromTables +( const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::vector<std::string>& orderBy, + const std::string& description, + UInt32 nExp, + bool forUpdate ) const +{ + // Prepare the appropriate CORAL query + boost::shared_ptr<coral::AttributeList> dataBuffer; + std::auto_ptr<coral::IQuery> + query( prepareQuery + ( tables, columns, whereClause, whereData, orderBy, dataBuffer ) ); + + // Lock the selected rows for update if required + if ( forUpdate ) query->setForUpdate(); + + // Describe the table list + std::stringstream tableList; + TableNamesWithAliases::const_iterator table; + for ( table = tables.begin(); + table != tables.end(); + table++ ) { + std::string tableName = table->first; + std::string tableAlias = table->second; + if ( tableList.str() != "" ) tableList << ", "; + tableList << tableName; + if ( tableAlias != "" ) tableList << " as " << tableAlias; + } + + // Describe the query + std::string msg = ""; + if ( description != "" ) msg = " ('" + description + "')"; + + // Retrieve the result set into a vector of rows + // If required, check that exactly nExp rows are selected + coral::ICursor& cursor = query->execute(); + std::vector<RelationalTableRow> rows; + //bool cursorHasNext = cursorNext( cursor ); // with TimingReport + bool cursorHasNext = cursor.next(); + while ( cursorHasNext ) { + if ( nExp > 0 && rows.size() > nExp ) { + std::stringstream s; + s << "More than " << nExp << " rows selected from " + << tableList.str() << msg; + log() << coral::Verbose + << "TooManyRowsFound: " << s.str() << coral::MessageStream::endmsg; + throw TooManyRowsFound( s.str(), "RalQueryMgr" ); + } + RelationalTableRow row( cursor.currentRow() ); + rows.push_back( row ); + //cursorHasNext = cursorNext( cursor ); // with TimingReport + cursorHasNext = cursor.next(); + } + if ( nExp > 0 ) { + if ( rows.size() == 0 ) { + std::stringstream s; + s << "No rows selected from " << tableList.str() << msg; + log() << coral::Verbose + << "NoRowsFound: " << s.str() << coral::MessageStream::endmsg; + throw NoRowsFound( s.str(), "RalQueryMgr" ); + } + else if ( rows.size() < nExp ) { + std::stringstream s; + s << "Too few rows selected from " << tableList.str() << msg; + log() << coral::Verbose + << "NoRowsFound: " << s.str() << coral::MessageStream::endmsg; + throw NoRowsFound( s.str(), "RalQueryMgr" ); + } + } + + // Return the rows retrieved from the database + log() << "Successfully fetched " << rows.size() << " table rows" + << msg << coral::MessageStream::endmsg; + //std::vector<RelationalTableRow>::const_iterator rowIt; + //for ( rowIt = rows.begin(); rowIt != rows.end(); rowIt++ ) + // std::cout << attributeListToString( rowIt->data() ) << std::endl; + return rows; + +} + +//--------------------------------------------------------------------------- + +UInt32 RalQueryMgr::countRowsFromTables +( const TableNamesWithAliases& tables, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::string& description ) const +{ + // Create a new CORAL query + std::auto_ptr<coral::IQuery> + query( m_sessionMgr->session().nominalSchema().newQuery() ); + + // Describe the table list + std::stringstream tableList; + TableNamesWithAliases::const_iterator table; + for ( table = tables.begin(); + table != tables.end(); + table++ ) { + std::string tableName = table->first; + std::string tableAlias = table->second; + if ( ! existsTable( tableName ) ) + throw TableNotFound( tableName, "RalQueryMgr" ); + if ( table->second != "" ) + query->addToTableList( table->first, table->second ); + else + query->addToTableList( table->first ); + if ( tableList.str() != "" ) tableList << ", "; + tableList << table->first; + } + + // Define the output + std::string countStar = "COUNT(*)"; // UPPERCASE for CORAL bug #16621 + // TEMPORARY -- working around a bug in the SQLite backend + if ( m_sessionMgr->databaseTechnology() == "SQLite" ) { + query->addToOutputList( countStar ); + // DANGER! CORAL will write the result set into a temporary AttributeList? + coral::AttributeList output; + output.extend( countStar, "unsigned int" ); + query->defineOutput( output ); + } else { + query->addToOutputList( countStar ); + } + + // Set the WHERE clause and bind variables + if ( whereClause != "" ) + query->setCondition( whereClause, whereData ); + + // Retrieve a cursor over the result set + coral::ICursor& cursor = query->execute(); + + // Describe the query + std::string msg = ""; + if ( description != "" ) msg = " ('" + description + "')"; + + // Check that at least one row is selected + { + //bool cursorHasNext = cursorNext( cursor ); // with TimingReport + bool cursorHasNext = cursor.next(); + if ( ! cursorHasNext ) // CORAL bug #16621 appears here + throw NoRowsFound + ( "No rows selected from " + tableList.str() + msg, "RalQueryMgr" ); + } + + // Retrieve the row count from the result set + UInt64 count; + const coral::Attribute& countAttr = cursor.currentRow()[ countStar ]; + if ( m_sessionMgr->databaseTechnology() == "SQLite" ) { + count = countAttr.data<unsigned int>(); + } else { + if ( countAttr.specification().type() == typeid(int) ) + count = countAttr.data<int>(); + else if ( countAttr.specification().type() == typeid(long) ) + count = countAttr.data<long>(); + else if ( countAttr.specification().type() == typeid(double) ) + count = static_cast<Int64>( countAttr.data<double>() ); + else + count = countAttr.data<Int64>(); + } + + // Check that only row is selected + { + //bool cursorHasNext = cursorNext( cursor ); // with TimingReport + bool cursorHasNext = cursor.next(); + if ( cursorHasNext ) + throw TooManyRowsFound + ( "More than one rows selected from " + tableList.str() + msg, + "RalQueryMgr" ); + } + + // Return the row count retrieved from the database + log() << "Table row count successfully fetched" << msg + << ": count=" << count << coral::MessageStream::endmsg; + return static_cast<UInt32>(count); + +} + +//--------------------------------------------------------------------------- + +std::auto_ptr<coral::IQuery> RalQueryMgr::newQuery() const +{ + std::auto_ptr<coral::IQuery> + query( m_sessionMgr->session().nominalSchema().newQuery() ); + return query; +} + +//--------------------------------------------------------------------------- + +std::auto_ptr<coral::IQuery> +RalQueryMgr::prepareQuery +( const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::vector<std::string>& orderBy, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) const +{ + std::auto_ptr<coral::IQuery> query( newQuery() ); + prepareQuery( query.get(), + tables, columns, whereClause, whereData, orderBy, dataBuffer ); + return query; +} + +//--------------------------------------------------------------------------- + +void RalQueryMgr::prepareQuery +( coral::IQuery* query, + const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::vector<std::string>& orderBy, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) const +{ + // Add the table names (with aliases if != "") + TableNamesWithAliases::const_iterator table; + for ( table = tables.begin(); + table != tables.end(); + table++ ) { + std::string tableName = table->first; + std::string tableAlias = table->second; + if ( tableAlias != "THIS_IS_A_SUBQUERY" ) + { + if ( ! existsTable( tableName ) ) + throw TableNotFound( tableName, "RalQueryMgr" ); + } + if ( tableAlias != "" && tableAlias != "THIS_IS_A_SUBQUERY" ) + query->addToTableList( tableName, tableAlias ); + else + query->addToTableList( tableName ); + } + + // Set the list of selected fields in the SELECT statement + const SelectList& selectList = columns.first; + for ( SelectList::const_iterator + col = selectList.begin(); col != selectList.end(); ++col ) { + query->addToOutputList( *col ); + } + + // Set the aliases and C++ types of the selected fields in the result set + // (the AttributeList is used by CORAL as data buffer for the current row) + const RSetSpec& rsetSpec = columns.second; + dataBuffer.reset + ( new coral::AttributeList( Record(rsetSpec).attributeList() ) ); + query->defineOutput( *dataBuffer ); + + // Set the WHERE clause and bind variables + if ( whereClause != "" ) + query->setCondition( whereClause, whereData ); + + // Set the ORDER BY clause + std::vector<std::string>::const_iterator orderByColumn; + for ( orderByColumn = orderBy.begin(); + orderByColumn != orderBy.end(); + orderByColumn++ ) { + query->addToOrderList( *orderByColumn ); + } + + // Set the prefetch row cache size + int newRowCacheSize = 100; + query->setRowCacheSize( newRowCacheSize ); +} + +//--------------------------------------------------------------------------- + +void RalQueryMgr::prepareQueryDefinition +( coral::IQueryDefinition& coralDef, + const IRelationalQueryDefinition& coolDef, + bool countStarSubquery ) const +{ + // Add tables and subqueries in the FROM clause (with aliases if != "") + for ( unsigned item = 0; item < coolDef.getFromSize(); item++ ) + { + const IRelationalQueryDefinition::IFromItem& + fromItem = coolDef.getFromItem( item ); + std::string alias = fromItem.alias(); + if ( !fromItem.isSubquery() ) + { + std::string tableName = fromItem.expression(); + // TODO: fix bug #43528 + // [expression() may be "schema.tableName" and existsTable may fails...] + if ( ! existsTable( tableName ) ) + throw TableNotFound( tableName, "RalQueryMgr" ); + coralDef.addToTableList( tableName, alias ); + } + else + { + coral::IQueryDefinition& coralSQDef = + coralDef.defineSubQuery( alias ); + prepareQueryDefinition( coralSQDef, fromItem.subquery() ); + coralDef.addToTableList( alias ); + } + } + + // Add all columns and subqueries in the SELECT list (with aliases if != "") + // [do this also for 'SELECT COUNT(*) FROM ( subquery )' queries] + for ( unsigned item = 0; item < coolDef.getSelectSize(); item++ ) + { + const IRelationalQueryDefinition::ISelectItem& + selectItem = coolDef.getSelectItem( item ); + std::string alias = selectItem.alias(); + //if ( !selectItem.isSubquery() ) + { + std::string expression = selectItem.expression(); + if ( item == 0 && coolDef.getHint() != "" ) + expression = coolDef.getHint() + " " + expression; + coralDef.addToOutputList( expression, alias ); + } + //else {} + } + + // Set the WHERE clause and bind variables + coralDef.setCondition( coolDef.getWhereClause(), + coolDef.getBindVariables().attributeList() ); + + // Add columns to the GROUP BY clause. + for ( unsigned item = 0; item < coolDef.getGroupSize(); item++ ) + { + const IRelationalQueryDefinition::IGroupItem& + groupItem = coolDef.getGroupItem( item ); + coralDef.groupBy( groupItem.expression() ); + } + + // Add columns to the ORDER BY clause. + // Omit the ORDER BY clause for 'SELECT COUNT(*) FROM ( subquery )' queries. + if ( ! countStarSubquery ) + { + for ( unsigned item = 0; item < coolDef.getOrderSize(); item++ ) + { + const IRelationalQueryDefinition::IOrderItem& + orderItem = coolDef.getOrderItem( item ); + coralDef.addToOrderList( orderItem.expression() ); + } + } + +} + +//--------------------------------------------------------------------------- + +std::auto_ptr<coral::IQuery> +RalQueryMgr::prepareQuery +( const IRelationalQueryDefinition& coolDef, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) const +{ + std::auto_ptr<coral::IQuery> query( newQuery() ); + + // Prepare the query definition + prepareQueryDefinition( *(query.get()), coolDef ); + + // Set the aliases and C++ types of the selected fields in the result set + // (the AttributeList is used by CORAL as data buffer for the current row) + const IRecordSpecification& resultSetSpec = + coolDef.getResultSetSpecification(); + dataBuffer.reset + ( new coral::AttributeList( Record(resultSetSpec).attributeList() ) ); + query->defineOutput( *dataBuffer ); + + // Set the prefetch row cache size + int newRowCacheSize = 100; + query->setRowCacheSize( newRowCacheSize ); + + // Return the query + return query; +} + +//--------------------------------------------------------------------------- + +IRelationalCursor* RalQueryMgr::prepareAndExecuteQuery +( const IRelationalQueryDefinition& coolDef, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) const +{ + std::auto_ptr<coral::IQuery> query( newQuery() ); + + // Prepare the query definition + prepareQueryDefinition( *(query.get()), coolDef ); + + // Set the aliases and C++ types of the selected fields in the result set + // (the AttributeList is used by CORAL as data buffer for the current row) + const IRecordSpecification& resultSetSpec = + coolDef.getResultSetSpecification(); + dataBuffer.reset + ( new coral::AttributeList( Record(resultSetSpec).attributeList() ) ); + query->defineOutput( *dataBuffer ); + + // Set the prefetch row cache size + int newRowCacheSize = 100; + query->setRowCacheSize( newRowCacheSize ); + + // Execute the CORAL query and return the wrapped cursor + return new RalCursor( query ); +} + +//--------------------------------------------------------------------------- + +const std::vector<RelationalTableRow> +RalQueryMgr::fetchOrderedRows +( const IRelationalQueryDefinition& coolDef, + const std::string& description, + UInt32 nExp, + bool forUpdate ) const +{ + // Prepare the appropriate CORAL query + boost::shared_ptr<coral::AttributeList> dataBuffer; + std::auto_ptr<coral::IQuery> query( prepareQuery( coolDef, dataBuffer ) ); + + // Lock the selected rows for update if required + if ( forUpdate ) query->setForUpdate(); + + // Describe the table list + std::stringstream tableList; + for ( unsigned item = 0; item < coolDef.getFromSize(); item++ ) + { + const IRelationalQueryDefinition::IFromItem& + fromItem = coolDef.getFromItem( item ); + std::string tableAlias = fromItem.alias(); + std::string tableName; + if ( !fromItem.isSubquery() ) + tableName = fromItem.expression(); + else + tableName = "(SELECT ... FROM ...)"; + if ( tableList.str() != "" ) tableList << ", "; + tableList << tableName; + if ( tableAlias != "" ) tableList << " as " << tableAlias; + } + + // Describe the query + std::string msg = ""; + if ( description != "" ) msg = " ('" + description + "')"; + + // Retrieve the result set into a vector of rows + // If required, check that exactly nExp rows are selected + coral::ICursor& cursor = query->execute(); + std::vector<RelationalTableRow> rows; + //bool cursorHasNext = cursorNext( cursor ); // with TimingReport + bool cursorHasNext = cursor.next(); + while ( cursorHasNext ) { + if ( nExp > 0 && rows.size() > nExp ) { + std::stringstream s; + s << "More than " << nExp << " rows selected from " + << tableList.str() << msg; + log() << coral::Verbose + << "TooManyRowsFound: " << s.str() << coral::MessageStream::endmsg; + throw TooManyRowsFound( s.str(), "RalQueryMgr" ); + } + RelationalTableRow row( cursor.currentRow() ); + rows.push_back( row ); + //cursorHasNext = cursorNext( cursor ); // with TimingReport + cursorHasNext = cursor.next(); + } + if ( nExp > 0 ) { + if ( rows.size() == 0 ) { + std::stringstream s; + s << "No rows selected from " << tableList.str() << msg; + log() << coral::Verbose + << "NoRowsFound: " << s.str() << coral::MessageStream::endmsg; + throw NoRowsFound( s.str(), "RalQueryMgr" ); + } + else if ( rows.size() < nExp ) { + std::stringstream s; + s << "Too few rows selected from " << tableList.str() << msg; + log() << coral::Verbose + << "NoRowsFound: " << s.str() << coral::MessageStream::endmsg; + throw NoRowsFound( s.str(), "RalQueryMgr" ); + } + } + + // Return the rows retrieved from the database + log() << "Successfully fetched " << rows.size() << " table rows" + << msg << coral::MessageStream::endmsg; + //std::vector<RelationalTableRow>::const_iterator rowIt; + //for ( rowIt = rows.begin(); rowIt != rows.end(); rowIt++ ) + // std::cout << attributeListToString( rowIt->data() ) << std::endl; + return rows; + +} + +//--------------------------------------------------------------------------- + +UInt32 RalQueryMgr::countRows +( const IRelationalQueryDefinition& coolDef, + const std::string& description ) const +{ + // Create a new CORAL query + std::auto_ptr<coral::IQuery> + query( m_sessionMgr->session().nominalSchema().newQuery() ); + + // Define a subquery (strictly needed only if there is a GROUP BY clause) + // Speed this up by removing the original ORDER BY clause [but keep the + // original SELECTed columns - strictly necessary for MAX/SUM aggregates] + coral::IQueryDefinition& subquery = query->defineSubQuery( "subquery" ); + bool countStarSubquery = true; + prepareQueryDefinition( subquery, coolDef, countStarSubquery ); + query->addToTableList( "subquery" ); + + // Describe the table list + std::stringstream tableList; + for ( unsigned item = 0; item < coolDef.getFromSize(); item++ ) + { + const IRelationalQueryDefinition::IFromItem& + fromItem = coolDef.getFromItem( item ); + std::string tableAlias = fromItem.alias(); + std::string tableName; + if ( !fromItem.isSubquery() ) + tableName = fromItem.expression(); + else + tableName = "(SELECT ... FROM ...)"; + if ( tableList.str() != "" ) tableList << ", "; + tableList << tableName; + if ( tableAlias != "" ) tableList << " as " << tableAlias; + } + + // Define the output + std::string countStar = "COUNT(*)"; // UPPERCASE for CORAL bug #16621 + // TEMPORARY -- working around a bug in the SQLite backend + if ( m_sessionMgr->databaseTechnology() == "SQLite" ) { + query->addToOutputList( countStar ); + // DANGER! CORAL will write the result set into a temporary AttributeList? + coral::AttributeList output; + output.extend( countStar, "unsigned int" ); + query->defineOutput( output ); + } else { + query->addToOutputList( countStar ); + } + + // Retrieve a cursor over the result set + coral::ICursor& cursor = query->execute(); + + // Describe the query + std::string msg = ""; + if ( description != "" ) msg = " ('" + description + "')"; + + // Check that at least one row is selected + { + //bool cursorHasNext = cursorNext( cursor ); // with TimingReport + bool cursorHasNext = cursor.next(); + if ( ! cursorHasNext ) // CORAL bug #16621 appears here + throw NoRowsFound + ( "No rows selected from " + tableList.str() + msg, "RalQueryMgr" ); + } + + // Retrieve the row count from the result set + UInt64 count; + const coral::Attribute& countAttr = cursor.currentRow()[ countStar ]; + if ( m_sessionMgr->databaseTechnology() == "SQLite" ) { + count = countAttr.data<unsigned int>(); + } else { + if ( countAttr.specification().type() == typeid(int) ) + count = countAttr.data<int>(); + else if ( countAttr.specification().type() == typeid(long) ) + count = countAttr.data<long>(); + else if ( countAttr.specification().type() == typeid(double) ) + count = static_cast<Int64>( countAttr.data<double>() ); + else + count = countAttr.data<Int64>(); + } + + // Check that only row is selected + { + //bool cursorHasNext = cursorNext( cursor ); // with TimingReport + bool cursorHasNext = cursor.next(); + if ( cursorHasNext ) + throw TooManyRowsFound + ( "More than one rows selected from " + tableList.str() + msg, + "RalQueryMgr" ); + } + + // Return the row count retrieved from the database + log() << "Table row count successfully fetched" << msg + << ": count=" << count << coral::MessageStream::endmsg; + return static_cast<UInt32>(count); + +} + +//--------------------------------------------------------------------------- + +boost::shared_ptr<IRelationalBulkOperation> +RalQueryMgr::bulkInsertTableRows( const std::string& tableName, + const coral::AttributeList& dataBuffer, + int rowCacheSize ) +{ + coral::ITable& table = + m_sessionMgr->session().nominalSchema().tableHandle( tableName ); + boost::shared_ptr<coral::IBulkOperation> coralBulkOperation + ( table.dataEditor().bulkInsert( dataBuffer, rowCacheSize ) ); + boost::shared_ptr<IRelationalBulkOperation> + bulkInserter( new RalBulkOperation( coralBulkOperation ) ); + return bulkInserter; +} + +//--------------------------------------------------------------------------- + +void RalQueryMgr::insertTableRow( const std::string& tableName, + const coral::AttributeList& data ) const +{ + coral::ITable& table = + m_sessionMgr->session().nominalSchema().tableHandle( tableName ); + return table.dataEditor().insertRow( data ); +} + +//--------------------------------------------------------------------------- + +boost::shared_ptr<IRelationalBulkOperation> +RalQueryMgr::bulkUpdateTableRows( const std::string& tableName, + const std::string& setClause, + const std::string& whereClause, + const coral::AttributeList& dataBuffer, + int rowCacheSize ) +{ + coral::ITable& table = + m_sessionMgr->session().nominalSchema().tableHandle( tableName ); + boost::shared_ptr<coral::IBulkOperation> coralBulkOperation + ( table.dataEditor().bulkUpdateRows + ( setClause, whereClause, dataBuffer, rowCacheSize ) ); + boost::shared_ptr<IRelationalBulkOperation> + bulkUpdater( new RalBulkOperation( coralBulkOperation ) ); + return bulkUpdater; +} + +//--------------------------------------------------------------------------- + +UInt32 RalQueryMgr::updateTableRows +( const std::string& tableName, + const std::string& setClause, + const std::string& whereClause, + const coral::AttributeList& updateData, + UInt32 nExp ) const +{ + coral::ITable& table = + m_sessionMgr->session().nominalSchema().tableHandle( tableName ); + UInt32 nRows = + table.dataEditor().updateRows( setClause, whereClause, updateData ); + if ( nExp > 0 ) { + if ( nRows < nExp ) { + std::stringstream s; + s << "Could not update rows in table '" << tableName + << "': updated " << nRows << ", expected " << nExp; + throw RowNotUpdated( s.str(), "RalQueryMgr" ); + } + else if ( nRows > nExp ) { + std::stringstream s; + s << "PANIC! Too many rows updated in table '" << tableName + << "': updated " << nRows << ", expected " << nExp; + throw RelationalException( s.str(), "RalQueryMgr" ); + } + } + return nRows; +} + +//--------------------------------------------------------------------------- + +UInt32 RalQueryMgr::deleteTableRows +( const std::string& tableName, + const std::string& whereClause, + const coral::AttributeList& whereData, + UInt32 nExp ) const +{ + UInt32 nRowsExp; + if ( nExp > 0 ) + nRowsExp = nExp; + else + nRowsExp = countRowsFromTables + ( tableList( tableName ), whereClause, whereData, "" ); + coral::ITable& table = + m_sessionMgr->session().nominalSchema().tableHandle( tableName ); + UInt32 nRows = + table.dataEditor().deleteRows( whereClause, whereData ); + if ( nRows < nRowsExp ) { + std::stringstream s; + s << "Could not delete rows from table '" << tableName + << "': deleted " << nRows << ", expected " << nRowsExp; + throw RowNotDeleted( s.str(), "RalQueryMgr" ); + } + else if ( nRows > nRowsExp ) { + std::stringstream s; + s << "PANIC! Too many rows deleted from table '" << tableName + << "': deleted " << nRows << ", expected " << nRowsExp; + throw RelationalException( s.str(), "RalQueryMgr" ); + } + return nRows; +} + +//--------------------------------------------------------------------------- + +const std::string RalQueryMgr::serverTimeClause() const +{ + return RelationalQueryMgr::serverTimeClause + ( m_sessionMgr->databaseTechnology() ); +} + +//--------------------------------------------------------------------------- + +coral::ICursor& RalQueryMgr::executeQuery( coral::IQuery& query ) +{ + if ( TimingReportMgr::isActive() ) + TimingReportMgr::startTimer( "coral::IQuery::execute()" ); + coral::ICursor& cursor = query.execute(); + if ( TimingReportMgr::isActive() ) + TimingReportMgr::stopTimer( "coral::IQuery::execute()" ); + return cursor; +} + +//--------------------------------------------------------------------------- + +bool RalQueryMgr::cursorNext( coral::ICursor& cursor ) +{ + if ( TimingReportMgr::isActive() ) + TimingReportMgr::startTimer( "coral::ICursor::next()" ); + bool hasNext = cursor.next(); + if ( TimingReportMgr::isActive() ) + TimingReportMgr::stopTimer( "coral::ICursor::next()" ); + return hasNext; +} + +//--------------------------------------------------------------------------- + +const std::string RalQueryMgr::databaseTechnology() const +{ + return m_sessionMgr->databaseTechnology(); +} + +//--------------------------------------------------------------------------- + +const std::string RalQueryMgr::schemaName() const +{ + return m_sessionMgr->schemaName(); +} + +//--------------------------------------------------------------------------- diff --git a/RelationalCool/src/RalQueryMgr.h b/RelationalCool/src/RalQueryMgr.h new file mode 100644 index 000000000..948729ed1 --- /dev/null +++ b/RelationalCool/src/RalQueryMgr.h @@ -0,0 +1,210 @@ +// $Id: RalQueryMgr.h,v 1.67 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RALQUERYMGR_H +#define RELATIONALCOOL_RALQUERYMGR_H + +// Include files +#include "RelationalAccess/IQuery.h" + +// Local include files +#include "RelationalQueryMgr.h" + +namespace cool { + + // Forward declarations + class IRelationalQueryDefinition; + class RalSessionMgr; + + /** @class RalQueryMgr RalQueryMgr.h + * + * Manager of relational queries executed using RAL. + * Manager of relational DML operations executed using RAL. + * + * Transactions are NOT handled by this class. + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2005-10-11 + */ + + class RalQueryMgr : public RelationalQueryMgr { + + public: + + /// Constructor from a RalSessionMgr shared pointer. + RalQueryMgr( const boost::shared_ptr<RalSessionMgr>& sessionMgr ); + + /// Destructor. + virtual ~RalQueryMgr(); + + /// Clone this query manager. + RelationalQueryMgr* clone() const; + + /// Checks if a table exists in the schema. + /// Implements RelationalQueryMgr pure abstract virtual method. + bool existsTable( const std::string& tableName ) const; + + /// Fetch an ordered set of rows from one or more tables as a vector. + /// If nExp>0, throws TooManyRowsFound if more than nExp rows are found. + /// If nExp>0, throws an exception if fewer than nExp rows are found. + /// Implements RelationalQueryMgr pure abstract virtual method. + const std::vector<RelationalTableRow> fetchOrderedRowsFromTables + ( const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::vector<std::string>& orderBy, + const std::string& description = "", + UInt32 nExp = 0, + bool forUpdate = false ) const; + + /// Fetch a "select COUNT(*)" row count from one or more tables. + /// Implements RelationalQueryMgr pure abstract virtual method. + UInt32 countRowsFromTables + ( const TableNamesWithAliases& tables, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::string& description = "" ) const; + + /// Create a new empty CORAL query. + /// This is needed if subqueries must be defined for this query. + std::auto_ptr<coral::IQuery> newQuery() const; + + /// Prepare a CORAL query from one or more tables. + /// A pointer to an AttributeList data must be passed to be overwritten + /// (a new AL with the right spec is created and used as data buffer). + void prepareQuery + ( coral::IQuery* query, + const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::vector<std::string>& orderBy, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) const; + + /// Prepare a CORAL query from one or more tables. + /// A pointer to an AttributeList data must be passed to be overwritten + /// (a new AL with the right spec is created and used as data buffer). + std::auto_ptr<coral::IQuery> prepareQuery + ( const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::vector<std::string>& orderBy, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) const; + + /// -- NEW -- start + /// Prepare a CORAL query definition from one or more tables. + void prepareQueryDefinition + ( coral::IQueryDefinition& coralDef, + const IRelationalQueryDefinition& coolDef, + bool countStarSubquery = false ) const; + /// Prepare a CORAL query from one or more tables. + /// A pointer to an AttributeList data must be passed to be overwritten + /// (a new AL with the right spec is created and used as data buffer). + std::auto_ptr<coral::IQuery> prepareQuery + ( const IRelationalQueryDefinition& coolDef, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) const; + /// Prepare and execute a CORAL query + /// (and start/stop the relevant timing report). + /// The caller becomes the owenr of the returned cursor. + IRelationalCursor* prepareAndExecuteQuery + ( const IRelationalQueryDefinition& coolDef, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) const; + /// Fetch an ordered set of rows from one or more tables as a vector. + /// If nExp>0, throws TooManyRowsFound if more than nExp rows are found. + /// If nExp>0, throws an exception if fewer than nExp rows are found. + /// Implements RelationalQueryMgr pure abstract virtual method. + const std::vector<RelationalTableRow> fetchOrderedRows + ( const IRelationalQueryDefinition& coolDef, + const std::string& description = "", + UInt32 nExp = 0, + bool forUpdate = false ) const; + /// Fetch a "select COUNT(*)" row count from one or more tables. + /// Implements RelationalQueryMgr pure abstract virtual method. + UInt32 countRows + ( const IRelationalQueryDefinition& coolDef, + const std::string& description = "" ) const; + /// -- NEW -- end + + /// Returns a new IRelationalBulkOperation object for performing a bulk + /// insert operation specifying the input data buffer and the number of + /// rows that should be cached on the client. + boost::shared_ptr<IRelationalBulkOperation> + bulkInsertTableRows( const std::string& tableName, + const coral::AttributeList& dataBuffer, + int rowCacheSize ); + + /// Insert one row into one table. + void insertTableRow + ( const std::string& tableName, + const coral::AttributeList& data ) const; + + /// Returns a new IRelationalBulkOperation object for performing a bulk + /// update operation specifying the input data buffer and the number of + /// rows that should be cached on the client. + boost::shared_ptr<IRelationalBulkOperation> + bulkUpdateTableRows( const std::string& tableName, + const std::string& setClause, + const std::string& whereClause, + const coral::AttributeList& dataBuffer, + int rowCacheSize ); + + /// Update rows in one table. + /// If nExp>0, throws an exception if more than nExp rows are updated. + /// If nExp>0, throws an exception if fewer than nExp rows are updated. + /// Implements RelationalQueryMgr pure abstract virtual method. + UInt32 updateTableRows + ( const std::string& tableName, + const std::string& setClause, + const std::string& whereClause, + const coral::AttributeList& updateData, + UInt32 nExp = 0 ) const; + + /// Delete rows from one table. + /// Throws an exception if #rows deleted is different from the expectation + /// (taken from nExp if > 0; queried internally if nExp = 0). + /// Implements RelationalQueryMgr pure abstract virtual method. + UInt32 deleteTableRows + ( const std::string& tableName, + const std::string& whereClause, + const coral::AttributeList& whereData, + UInt32 nExp = 0 ) const; + + /// Get a RelationalSequenceMgr. + /// Implements RelationalQueryMgr pure abstract virtual method. + RelationalSequenceMgr& sequenceMgr() const + { + return *m_sequenceMgr; + } + + /// Build the appropriate backend-specific SQL expression + /// to compute the server-side time in the format used by COOL. + /// Implements RelationalQueryMgr pure abstract virtual method. + const std::string serverTimeClause() const; + + /// Execute a CORAL query (and start/stop the relevant timing report) + static coral::ICursor& executeQuery( coral::IQuery& query ); + + /// Increment a CORAL cursor (and start/stop the relevant timing report) + static bool cursorNext( coral::ICursor& cursor ); + + /// Return the server technology for the current connection. + /// Supported technologies: "Oracle ", "MySQL", "SQLite", "frontier". + const std::string databaseTechnology() const; + + /// Return the schema name for the current connection. + const std::string schemaName() const; + + private: + + /// Handle to the RalSessionMgr (shared ownership) + boost::shared_ptr<RalSessionMgr> m_sessionMgr; + + /// RelationalSequenceMgr (owned by this instance) + RelationalSequenceMgr* m_sequenceMgr; + + }; + +} + +#endif // RELATIONALCOOL_RALQUERYMGR_H + diff --git a/RelationalCool/src/RalSchemaMgr.cpp b/RelationalCool/src/RalSchemaMgr.cpp new file mode 100644 index 000000000..5d6474f5d --- /dev/null +++ b/RelationalCool/src/RalSchemaMgr.cpp @@ -0,0 +1,1033 @@ +// $Id: RalSchemaMgr.cpp,v 1.82 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoolKernel/Record.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeList.h" +#include "CoralBase/AttributeSpecification.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" +#include "RelationalAccess/ITableDataEditor.h" +#include "RelationalAccess/ITypeConverter.h" + +// Local include files +#include "HvsPathHandler.h" +#include "RalSchemaMgr.h" +#include "RalSessionMgr.h" +#include "RelationalChannelTable.h" +#include "RelationalDatabase.h" +#include "RelationalDatabaseTable.h" +#include "RelationalException.h" +#include "RelationalGlobalTagTable.h" +#include "RelationalNodeTable.h" +#include "RelationalObjectTable.h" +#include "RelationalObject2TagTable.h" +#include "RelationalQueryMgr.h" +#include "RelationalSequence.h" +#include "RelationalSharedSequenceTable.h" +#include "RelationalSequenceMgr.h" +#include "RelationalTagSequence.h" +#include "RelationalTagTable.h" +#include "RelationalTag2TagTable.h" +#include "VersionInfo.h" +#include "attributeListToString.h" + +// *** START *** 3.0.0 schema extensions (task #4307, task #4396) +#include "RelationalChannelTablesTable.h" +#include "RelationalGlobalHeadTagTable.h" +#include "RelationalGlobalUserTagTable.h" +#include "RelationalIovTablesTable.h" +// **** END **** 3.0.0 schema extensions (task #4307, task #4396) + +// Namespace +using namespace cool; + +// Local type definitions +typedef boost::shared_ptr<RelationalSequence> RelationalSequencePtr; + +//--------------------------------------------------------------------------- + +void RalSchemaMgr::initialize() +{ + log() << coral::Debug << "Instantiate a RalSchemaMgr" + << coral::MessageStream::endmsg; +} + +//--------------------------------------------------------------------------- + +RalSchemaMgr::~RalSchemaMgr() +{ + log() << coral::Debug << "Delete the RalSchemaMgr" + << coral::MessageStream::endmsg; +} + +//--------------------------------------------------------------------------- + +coral::ISessionProxy& RalSchemaMgr::session() const +{ + return m_sessionMgr->session(); +} + +//--------------------------------------------------------------------------- + +bool RalSchemaMgr::dropTable( const std::string& tableName ) const +{ + if ( ! queryMgr().existsTable( tableName ) ) { + return false; + } else { + session().nominalSchema().dropTable( tableName ); + return true; + } +} + +//--------------------------------------------------------------------------- + +std::auto_ptr<coral::TableDescription> +RalSchemaMgr::createTableDescription( const std::string& tableName, + const IRecordSpecification& spec, + const std::string& primaryKey ) const +{ + log() << "Create the description of table " << tableName + << coral::MessageStream::endmsg; + + std::auto_ptr<coral::TableDescription> + tableDesc( new coral::TableDescription( "cool::RalSchemaMgr" ) ); + + tableDesc->setName( tableName ); + + for ( unsigned int i=0; i<spec.size(); i++ ) { + const IFieldSpecification& field = spec[i]; + if ( ! isValidColumnName( field.name() ) ) + throw InvalidColumnName + ( field.name(), "RalSchemaMgr::createTableDescription"); + bool fixedSize = false; + int maxSize = field.storageType().maxSize(); // No bug #22543 anymore + tableDesc->insertColumn + ( field.name(), + coral::AttributeSpecification::typeNameForId + ( field.storageType().cppType() ), maxSize, fixedSize ); + } + + if ( !primaryKey.empty() ) tableDesc->setPrimaryKey( primaryKey ); + + return tableDesc; +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::createMainTable( const std::string& mainTableName ) const +{ + log() << "Create table " << mainTableName << coral::MessageStream::endmsg; + + // Create the description of the main table. + // Create the PK (attributeName). + std::auto_ptr<coral::TableDescription> mainTableDesc = + createTableDescription + ( mainTableName, + RelationalDatabaseTable::tableSpecification(), + RelationalDatabaseTable::columnNames::attributeName ); + + // Create the main table + session().nominalSchema().createTable( *mainTableDesc ); + log() << "Created table " << mainTableName << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::fillMainTable( const std::string& mainTableName, + const coral::AttributeList& dbAttr ) const +{ + log() << "Fill table " << mainTableName + << " with the following database attributes: " + << attributeListToString( dbAttr ) << coral::MessageStream::endmsg; + + // Store the database attributes in the top-level management table + const IRecordSpecification& spec = + RelationalDatabaseTable::tableSpecification(); + coral::AttributeList data = Record( spec ).attributeList(); + for ( coral::AttributeList::const_iterator + dbAttrIt = dbAttr.begin(); dbAttrIt != dbAttr.end(); ++dbAttrIt ) + { + RelationalDatabaseTable::columnTypes::attributeName attrName = + dbAttrIt->specification().name(); + // Set the attribute name + data[RelationalDatabaseTable::columnNames::attributeName] + .data<RelationalDatabaseTable::columnTypes::attributeName>() = + attrName; + // Set the attribute value + data[RelationalDatabaseTable::columnNames::attributeValue] + .data<RelationalDatabaseTable::columnTypes::attributeValue>() = + dbAttrIt->data<RelationalDatabaseTable::columnTypes::attributeValue>(); + // TEMPORARY? Check that all column values are within their allowed range. + spec.validate(data); + // Insert a new row + log() << "Insert row: " << attributeListToString( data ) + << coral::MessageStream::endmsg; + queryMgr().insertTableRow( mainTableName, data ); + } + log() << "Filled table " << mainTableName << coral::MessageStream::endmsg; + +} + +//----------------------------------------------------------------------------- + +// *** START *** 3.0.0 schema extensions (task #4307) +void RalSchemaMgr::createIovTablesTable +//( const std::string& iovTablesTableName ) const +( const std::string& ) const +{ + // TODO +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::createChannelTablesTable +//( const std::string& channelTablesTableName ) const +( const std::string& ) const +{ + // TODO +} +// **** END **** 3.0.0 schema extensions (task #4307) + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::createNodeTable +( const std::string& nodeTableName, + const std::string& defaultTablePrefix ) const +{ + // Create the description of the node table. + // Create the PK (nodeId). + std::auto_ptr<coral::TableDescription> nodeTableDesc = + createTableDescription( nodeTableName, + RelationalNodeTable::tableSpecification(), + RelationalNodeTable::columnNames::nodeId ); + + // Create the FK reference to itself (parentNodeId -> nodeId). + nodeTableDesc->createForeignKey + ( nodeTableName + "_PARENT_FK", + RelationalNodeTable::columnNames::nodeParentId, + nodeTableName, + RelationalNodeTable::columnNames::nodeId ); + + // Create a UK constraint on (nodeFullPath) + // [NB On Oracle this unique constraint will also create a unique index] + nodeTableDesc->setUniqueConstraint + ( RelationalNodeTable::columnNames::nodeFullPath, + nodeTableName+"_FULLPATH_UK" ); + + // Create a UK constraint on (nodeId, parentNodeId) + // [NB On Oracle this unique constraint will also create a unique index] + // This is needed so that the TAG2TAG table can reference the NODES table + { + std::vector<std::string> ukColumns; + ukColumns.push_back( RelationalNodeTable::columnNames::nodeId ); + ukColumns.push_back( RelationalNodeTable::columnNames::nodeParentId ); + nodeTableDesc->setUniqueConstraint + ( ukColumns, nodeTableName+"_PARENT_UK" ); + } + + // Create the node table + log() << "Create table " << nodeTableName << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *nodeTableDesc ); + + // Create a sequence for the node table PK (will fail if it already exists) + std::string nodeSeqName = + RelationalNodeTable::sequenceName( nodeTableName ); + log() << "Create sequence " << nodeSeqName << coral::MessageStream::endmsg; + RelationalSequencePtr nodeSeq + ( queryMgr().sequenceMgr().createSequence( nodeSeqName ) ); + + // Get the node ID for the root folder set from the sequence + unsigned int nodeId = nodeSeq->nextVal(); + if ( nodeId != 0 ) + throw RelationalException + ( "PANIC! First ID from the sequence not equal to 0?", "RalSchemaMgr" ); + std::string nodeInsTime = nodeSeq->currDate(); + + // Get the name of the root folder set from the HvsPathHandler + HvsPathHandler handler; + std::string nodeUnresolvedName = handler.rootUnresolvedName(); + std::string nodeFullPath = handler.rootFullPath(); + + // Prepare the root folder set row in the node table + const IRecordSpecification& rootSpec = + RelationalNodeTable::tableSpecification( false, false ); + coral::AttributeList rootData = Record( rootSpec ).attributeList(); + rootData[RelationalNodeTable::columnNames::nodeId] + .data<RelationalNodeTable::columnTypes::nodeId>() = nodeId; + rootData[RelationalNodeTable::columnNames::nodeName] + .data<RelationalNodeTable::columnTypes::nodeName>() = nodeUnresolvedName; + rootData[RelationalNodeTable::columnNames::nodeFullPath] + .data<RelationalNodeTable::columnTypes::nodeFullPath>() = nodeFullPath; + rootData[RelationalNodeTable::columnNames::nodeIsLeaf] + .data<RelationalNodeTable::columnTypes::nodeIsLeaf>() = false; + rootData[RelationalNodeTable::columnNames::nodeSchemaVersion] + .data<RelationalNodeTable::columnTypes::nodeSchemaVersion>() = + VersionInfo::schemaVersion; + rootData[RelationalNodeTable::columnNames::nodeInsertionTime] + .data<RelationalNodeTable::columnTypes::nodeInsertionTime>() = nodeInsTime; + rootData[RelationalNodeTable::columnNames::folderVersioningMode] + .data<RelationalNodeTable::columnTypes::folderVersioningMode>() = + FolderVersioning::NONE; + rootData[RelationalNodeTable::columnNames::lastModDate] + .data<RelationalNodeTable::columnTypes::lastModDate>() = nodeInsTime; + + // TEMPORARY? Check that all column values are within their allowed range. + rootSpec.validate(rootData); + + // Insert the root folder set into the node table + queryMgr().insertTableRow( nodeTableName, rootData ); + + // Create the tag sequence for the root folder set + std::string tagSequenceName = RelationalTagSequence::sequenceName + ( defaultTablePrefix, nodeId ); + createTagSequence( tagSequenceName ); +} + +//----------------------------------------------------------------------------- + +void +RalSchemaMgr::createGlobalTagTable( const std::string& globalTagTableName, + const std::string& nodeTableName ) const +{ + // Create the description of the tag table + std::auto_ptr<coral::TableDescription> tableDesc = + createTableDescription + ( globalTagTableName, RelationalGlobalTagTable::tableSpecification() ); + + // Create the PK (nodeId, tagId) + { + std::vector<std::string> pkColumns; + pkColumns.push_back( RelationalGlobalTagTable::columnNames::nodeId ); + pkColumns.push_back( RelationalGlobalTagTable::columnNames::tagId ); + tableDesc->setPrimaryKey( pkColumns ); + } + + /* + // *** START *** 3.0.0 schema extensions (task #4396) + // Create a UK constraint on (nodeId, tagId, tagType) + // [NB On Oracle this unique constraint will also create a unique index] + { + std::vector<std::string> ukColumns; + ukColumns.push_back( RelationalGlobalTagTable::columnNames::nodeId ); + ukColumns.push_back( RelationalGlobalTagTable::columnNames::tagId ); + ukColumns.push_back( RelationalGlobalTagTable::columnNames::tagType ); + tableDesc->setUniqueConstraint + ( ukColumns, globalTagTableName+"_TAGTYPE_UK" ); + } + // Create a NOT NULL constraint on (tagType) + tableDesc->setNotNullConstraint + ( RelationalGlobalTagTable::columnNames::tagType ); + // Create a CHECK constraint on (tagType) = {0,1,2} + // ... waiting for CORAL (sr#101506) ... + // **** END **** 3.0.0 schema extensions (task #4396) + */ + + // Create a UK constraint on (tagName) + // [NB On Oracle this unique constraint will also create a unique index] + tableDesc->setUniqueConstraint + ( RelationalTagTable::columnNames::tagName, + globalTagTableName+"_TAGNAME_UK" ); + + // Create FK reference to the NODES table (nodeId -> nodeId) + tableDesc->createForeignKey + ( globalTagTableName + "_NODEID_FK", + RelationalGlobalTagTable::columnNames::nodeId, + nodeTableName, + RelationalNodeTable::columnNames::nodeId ); + + // Create the table + log() << "Create table " << globalTagTableName + << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *tableDesc ); +} + +//----------------------------------------------------------------------------- + +void +RalSchemaMgr::createGlobalHeadTagTable +( const std::string& globalHeadTagTableName, + const std::string& globalTagTableName ) const +{ + // Create the description of the head tag table + std::auto_ptr<coral::TableDescription> tableDesc = + createTableDescription + ( globalHeadTagTableName, + RelationalGlobalHeadTagTable::tableSpecification() ); + + // Create the PK (nodeId, tagId) + { + std::vector<std::string> pkColumns; + pkColumns.push_back( RelationalGlobalHeadTagTable::columnNames::nodeId ); + pkColumns.push_back( RelationalGlobalHeadTagTable::columnNames::tagId ); + tableDesc->setPrimaryKey( pkColumns ); + } + + // Create FK reference to the TAGS table (nodeId, tagId, tagType) + { + std::vector<std::string> fkColumnsSrc; + fkColumnsSrc.push_back + ( RelationalGlobalHeadTagTable::columnNames::nodeId ); + fkColumnsSrc.push_back + ( RelationalGlobalHeadTagTable::columnNames::tagId ); + fkColumnsSrc.push_back + ( RelationalGlobalHeadTagTable::columnNames::tagType ); + std::vector<std::string> fkColumnsTgt; + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::nodeId ); + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::tagId ); + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::tagType ); + tableDesc->createForeignKey + ( globalHeadTagTableName + "_TAGS_FK", fkColumnsSrc, + globalTagTableName, fkColumnsTgt ); + } + + // Create a CHECK constraint on (tagType) = {1} + // ... waiting for CORAL (sr#101506) ... + + // Create the table + log() << "Create table " << globalHeadTagTableName + << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *tableDesc ); +} + +//----------------------------------------------------------------------------- + +void +RalSchemaMgr::createGlobalUserTagTable +( const std::string& globalUserTagTableName, + const std::string& globalTagTableName ) const +{ + // Create the description of the user tag table + std::auto_ptr<coral::TableDescription> tableDesc = + createTableDescription + ( globalUserTagTableName, + RelationalGlobalUserTagTable::tableSpecification() ); + + // Create the PK (nodeId, tagId) + { + std::vector<std::string> pkColumns; + pkColumns.push_back( RelationalGlobalUserTagTable::columnNames::nodeId ); + pkColumns.push_back( RelationalGlobalUserTagTable::columnNames::tagId ); + tableDesc->setPrimaryKey( pkColumns ); + } + + // Create FK reference to the TAGS table (nodeId, tagId, tagType) + { + std::vector<std::string> fkColumnsSrc; + fkColumnsSrc.push_back + ( RelationalGlobalUserTagTable::columnNames::nodeId ); + fkColumnsSrc.push_back + ( RelationalGlobalUserTagTable::columnNames::tagId ); + fkColumnsSrc.push_back + ( RelationalGlobalUserTagTable::columnNames::tagType ); + std::vector<std::string> fkColumnsTgt; + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::nodeId ); + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::tagId ); + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::tagType ); + tableDesc->createForeignKey + ( globalUserTagTableName + "_TAGS_FK", fkColumnsSrc, + globalTagTableName, fkColumnsTgt ); + } + + // Create a CHECK constraint on (tagType) = {2} + // ... waiting for CORAL (sr#101506) ... + + // Create the table + log() << "Create table " << globalUserTagTableName + << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *tableDesc ); +} + +//----------------------------------------------------------------------------- + +void +RalSchemaMgr::createTag2TagTable( const std::string& tag2TagTableName, + const std::string& globalTagTableName, + const std::string& nodeTableName ) const +{ + // Create the description of the tag2tag table + std::auto_ptr<coral::TableDescription> tableDesc = + createTableDescription + ( tag2TagTableName, RelationalTag2TagTable::tableSpecification() ); + + // Set the primary key + std::vector<std::string> pkColumns; + pkColumns.push_back( RelationalTag2TagTable::columnNames::parentNodeId ); + pkColumns.push_back( RelationalTag2TagTable::columnNames::parentTagId ); + pkColumns.push_back( RelationalTag2TagTable::columnNames::childNodeId ); + tableDesc->setPrimaryKey( pkColumns ); + + // Create FK reference to the NODES table for parent and child nodes + { + std::vector<std::string> fkColumnsSrc; + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::childNodeId ); + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::parentNodeId ); + std::vector<std::string> fkColumnsTgt; + fkColumnsTgt.push_back + ( RelationalNodeTable::columnNames::nodeId ); + fkColumnsTgt.push_back + ( RelationalNodeTable::columnNames::nodeParentId ); + tableDesc->createForeignKey + ( tag2TagTableName + "_NODES_FK", fkColumnsSrc, + nodeTableName, fkColumnsTgt ); + } + + // Create the table + log() << "Create table " << tag2TagTableName << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *tableDesc ); + + // Create FK reference to the TAGS table for the parent tag (nodeId, tagId) + // Create FK reference to the TAGS table for the child tag (nodeId, tagId) + createTag2TagFKs( tag2TagTableName, globalTagTableName ); + + // Create a sequence for the tag2tag table insertion time (not for the PK) + std::string tag2TagSeqName = + RelationalTag2TagTable::sequenceName( tag2TagTableName ); + log() << "Create sequence " << tag2TagSeqName + << coral::MessageStream::endmsg; + queryMgr().sequenceMgr().createSequence( tag2TagSeqName ); +} + +//----------------------------------------------------------------------------- + +void +RalSchemaMgr::createTag2TagFKs( const std::string& tag2TagTableName, + const std::string& globalTagTableName ) const +{ + coral::ITable& tag2TagTable = + session().nominalSchema().tableHandle( tag2TagTableName ); + coral::ITableSchemaEditor& editor = tag2TagTable.schemaEditor(); + // Create FK reference to the TAGS table for the parent tag (nodeId, tagId) + try + { + std::vector<std::string> fkColumnsSrc; + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::parentNodeId ); + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::parentTagId ); + std::vector<std::string> fkColumnsTgt; + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::nodeId ); + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::tagId ); + log() << "Create FK constraint " << tag2TagTableName + "_PTAG_FK" + << " on table " << tag2TagTableName << coral::MessageStream::endmsg; + editor.createForeignKey + ( tag2TagTableName + "_PTAG_FK", fkColumnsSrc, + globalTagTableName, fkColumnsTgt ); + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() + << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create FK constraint " + << tag2TagTableName + "_PTAG_FK" + << " on table " << tag2TagTableName << coral::MessageStream::endmsg; + throw; // Re-throw (see bug #40295) + } + // Create FK reference to the TAGS table for the child tag (nodeId, tagId) + try + { + std::vector<std::string> fkColumnsSrc; + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::childNodeId ); + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::childTagId ); + std::vector<std::string> fkColumnsTgt; + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::nodeId ); + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::tagId ); + log() << "Create FK constraint " << tag2TagTableName + "_CTAG_FK" + << " on table " << tag2TagTableName << coral::MessageStream::endmsg; + editor.createForeignKey + ( tag2TagTableName + "_CTAG_FK", fkColumnsSrc, + globalTagTableName, fkColumnsTgt ); + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" + << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create FK constraint " + << tag2TagTableName + "_CTAG_FK" + << " on table " << tag2TagTableName << coral::MessageStream::endmsg; + throw; // Re-throw (see bug #40295) + } +} + +//----------------------------------------------------------------------------- + +bool +RalSchemaMgr::dropTag2TagFKs( const std::string& tag2TagTableName, + bool verbose ) const +{ + bool status = true; + coral::ITable& tag2TagTable = + session().nominalSchema().tableHandle( tag2TagTableName ); + coral::ITableSchemaEditor& editor = tag2TagTable.schemaEditor(); + // Drop FK reference to the TAGS table for the parent tag (nodeId, tagId) + try + { + log() << "Drop FK constraint " << tag2TagTableName + "_PTAG_FK" + << " on table " << tag2TagTableName << coral::MessageStream::endmsg; + editor.dropForeignKey( tag2TagTableName + "_PTAG_FK" ); + } + catch ( std::exception& e ) + { + if ( verbose ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" + << coral::MessageStream::endmsg; + log() << coral::Error << "Failed to drop FK constraint " + << tag2TagTableName + "_PTAG_FK" + << " on table " << tag2TagTableName + << coral::MessageStream::endmsg; + } + status = false; + } + // Drop FK reference to the TAGS table for the child tag (nodeId, tagId) + try + { + log() << "Drop FK constraint " << tag2TagTableName + "_CTAG_FK" + << " on table " << tag2TagTableName << coral::MessageStream::endmsg; + editor.dropForeignKey( tag2TagTableName + "_CTAG_FK" ); + } + catch ( std::exception& e ) + { + if ( verbose ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" + << coral::MessageStream::endmsg; + log() << coral::Error << "Failed to drop FK constraint " + << tag2TagTableName + "_CTAG_FK" + << " on table " << tag2TagTableName + << coral::MessageStream::endmsg; + } + status = false; + } + return status; +} + +//----------------------------------------------------------------------------- + +void +RalSchemaMgr::createSharedSequence( const std::string& sharedSequenceName, + const std::string& nodeTableName ) const +{ + + // Create the description of the shared sequence table + std::auto_ptr<coral::TableDescription> tableDesc = + createTableDescription + ( sharedSequenceName, + RelationalSharedSequenceTable::tableSpecification(), + RelationalSharedSequenceTable::columnNames::nodeId ); + + // Create FK reference to the NODES table (nodeId -> nodeId) + tableDesc->createForeignKey + ( sharedSequenceName + "_NODEID_FK", + RelationalSharedSequenceTable::columnNames::nodeId, + nodeTableName, + RelationalNodeTable::columnNames::nodeId ); + + // Create the table + log() << "Create table " << sharedSequenceName + << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *tableDesc ); + +} + +//----------------------------------------------------------------------------- + +void +RalSchemaMgr::createObjectTable +( const std::string& objectTableName, + const std::string& channelTableName, + const IRecordSpecification& payloadSpec, + FolderVersioning::Mode versioningMode ) const +{ + // Create the description of the object table + std::auto_ptr<coral::TableDescription> objectTableDesc = + createTableDescription + ( objectTableName, + RelationalObjectTable::tableSpecification( payloadSpec ), + RelationalObjectTable::columnNames::objectId() ); + + // Index on channel ID + // TEMPORARY? In Oracle: one partition per channel?! + //std::vector< std::string > objectIndexCh; + //objectIndexCh.push_back( RelationalObjectTable::columnNames::channelId ); + //objectTableDesc->createIndex + // ( objectTableName+"_C_1INDX", objectIndexCh, false ); + + // Index on channel ID and object ID + // TEMPORARY? In Oracle: primary key on chID+objID, partitioned by chID? + std::vector< std::string > objectIndexChOb; + objectIndexChOb.push_back( RelationalObjectTable::columnNames::channelId() ); + objectIndexChOb.push_back( RelationalObjectTable::columnNames::objectId() ); + objectTableDesc->createIndex( objectTableName+"_CO_2INDX", + objectIndexChOb, + false ); + + // Index on channel ID and since + // TEMPORARY? In Oracle: local index on since within channel partition?! + //std::vector< std::string > objectIndexChSi; + //objectIndexChSi.push_back( RelationalObjectTable::columnNames::channelId ); + //objectIndexChSi.push_back( RelationalObjectTable::columnNames::iovSince ); + //objectTableDesc->createIndex + // ( objectTableName+"_CS_2INDX", objectIndexChSi, false ); + + // Index on channel ID and since and until + // TEMPORARY? In Oracle: local index on since/until within channel partition? + std::vector< std::string > objectIndexChSiUn; + objectIndexChSiUn.push_back + ( RelationalObjectTable::columnNames::channelId() ); + objectIndexChSiUn.push_back + ( RelationalObjectTable::columnNames::iovSince() ); + objectIndexChSiUn.push_back + ( RelationalObjectTable::columnNames::iovUntil() ); + objectTableDesc->createIndex( objectTableName+"_CSU_3INDX", + objectIndexChSiUn, + false ); + + // Index on since and until (new in COOL_1_3_0) + // Suggested by DavidF and LucaC for SV queries with no channel selection + // TEMPORARY? In Oracle: local index on since/until within channel partition? + std::vector< std::string > objectIndexSiUn; + objectIndexSiUn.push_back + ( RelationalObjectTable::columnNames::iovSince() ); + objectIndexSiUn.push_back + ( RelationalObjectTable::columnNames::iovUntil() ); + objectTableDesc->createIndex( objectTableName+"_SU_2INDX", + objectIndexSiUn, + false ); + + // Additional indices for MULTI_VERSION mode + if ( versioningMode == FolderVersioning::MULTI_VERSION ) + { + // TODO: ALSO need to add a UK constraint - different from unique index + // See http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:36858373078604 + { + std::vector<std::string> indColumns; + indColumns.push_back( RelationalObjectTable::columnNames::objectId() ); + indColumns.push_back( RelationalObjectTable::columnNames::channelId() ); + indColumns.push_back( RelationalObjectTable::columnNames::iovSince() ); + indColumns.push_back( RelationalObjectTable::columnNames::iovUntil() ); + bool unique = true; + // We are close to the maximum index name length of 31 characters here! + std::string indexName = objectTableName + "_OCSU_4INDX"; + objectTableDesc->createIndex( indexName, indColumns, unique ); + } + // 5-column index for findObject(userTag) - see task #4381 + { + std::vector<std::string> indColumns; + indColumns.push_back( RelationalObjectTable::columnNames::userTagId() ); + indColumns.push_back( RelationalObjectTable::columnNames::newHeadId() ); + indColumns.push_back( RelationalObjectTable::columnNames::channelId() ); + indColumns.push_back( RelationalObjectTable::columnNames::iovSince() ); + indColumns.push_back( RelationalObjectTable::columnNames::iovUntil() ); + bool unique = true; + std::string indexName = objectTableName + "_UTAG_5INDX"; + objectTableDesc->createIndex( indexName, indColumns, unique ); + } + } + + // Create the object table + log() << "Create table " << objectTableName << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *objectTableDesc ); + + // Create FK reference on channelId from object table to channel table + createObjectChannelFK( objectTableName, channelTableName ); + + // Create a sequence for the IOV table primary key + std::string objectSeqName = + RelationalObjectTable::sequenceName( objectTableName ); + + // Create the sequence (will fail if it already exists) + log() << "Create sequence " << objectSeqName << coral::MessageStream::endmsg; + RelationalSequencePtr objectSeq + ( queryMgr().sequenceMgr().createSequence( objectSeqName ) ); + + // Initialize the sequence: first inserted IOV will have ID=1 (not ID=0) + objectSeq->nextVal(); +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::createObjectChannelFK +( const std::string& objectTableName, + const std::string& channelTableName ) const +{ + coral::ITable& objectTable = + session().nominalSchema().tableHandle( objectTableName ); + coral::ITableSchemaEditor& editor = objectTable.schemaEditor(); + // Create FK reference to the channel table (channelId) + try + { + log() << "Create FK constraint " << objectTableName + "_CHANNEL_FK" + << " on table " << objectTableName << coral::MessageStream::endmsg; + editor.createForeignKey + ( objectTableName + "_CHANNEL_FK", + RelationalObjectTable::columnNames::channelId(), + channelTableName, + RelationalChannelTable::columnNames::channelId() ); + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" + << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create FK constraint " + << objectTableName + "_CHANNEL_FK" + << " on table " << objectTableName << coral::MessageStream::endmsg; + } +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::dropObjectChannelFK +( const std::string& objectTableName ) const +{ + coral::ITable& objectTable = + session().nominalSchema().tableHandle( objectTableName ); + coral::ITableSchemaEditor& editor = objectTable.schemaEditor(); + // Drop FK reference to the channel table (channelId) + try + { + log() << "Drop FK constraint " << objectTableName + "_CHANNEL_FK" + << " on table " << objectTableName << coral::MessageStream::endmsg; + editor.dropForeignKey( objectTableName + "_CHANNEL_FK" ); + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" + << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to drop FK constraint " + << objectTableName + "_CHANNEL_FK" + << " on table " << objectTableName << coral::MessageStream::endmsg; + } +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::createTagTable( const std::string& tagTableName ) const +{ + // Create the description of the local tag table + std::auto_ptr<coral::TableDescription> tableDesc = + createTableDescription( tagTableName, + RelationalTagTable::tableSpecification(), + RelationalTagTable::columnNames::tagId ); + + // Create the table + log() << "Create table " << tagTableName << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *tableDesc ); + + // Create a unique index on (tagName) + // [NB this is a unique index, not a unique constraint] + // [NB this will be obsoleted by the 2.1.0 folder schema] + bool unique = true; + tableDesc->createIndex( tagTableName+"_NAME_UK", + RelationalTagTable::columnNames::tagName, + unique ); +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::createChannelTable( const std::string& tableName ) const +{ + // Create the description of the local channel table + std::auto_ptr<coral::TableDescription> tableDesc = + createTableDescription( tableName, + RelationalChannelTable::tableSpecification(), + RelationalChannelTable::columnNames::channelId() ); + + // Set the unique constraint on the channel name. + // Note that Oracle treats "" and NULL as equivalent: multiple rows can + // be inserted with "" as name, without violating the UK constraint + // (they are all considered as NULL, and many NULLs do not violate a UK). + // For MySQL and SQLite we probably need to make sure a real NULL is + // inserted, instead of an empty string (this would also be nicer for + // consistency across backends, and would help in payload queries too). + // Probably need a hack in the relational query mgr to make sure field="" + // are translated to NULL (note that IField strings are never null - + // this was exactly motivated by the Oracle feature). + bool unique = true; + tableDesc->createIndex( tableName+"_N_UK", + RelationalChannelTable::columnNames::channelName(), + unique ); + + // Create the table + log() << "Create table " << tableName << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *tableDesc ); + +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::createTagSequence( const std::string& seqName ) const +{ + // Create a sequence + log() << "Create sequence " << seqName << coral::MessageStream::endmsg; + RelationalSequencePtr sequence + ( queryMgr().sequenceMgr().createSequence( seqName ) ); + + // Initialize the sequence: first inserted row will have ID=1 (not ID=0) + sequence->nextVal(); +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::createObject2TagTable +( const std::string& obj2tagTableName, + const std::string& objectTableName, + const std::string& tagTableName ) const +{ + // Create the description of the local tag table + std::auto_ptr<coral::TableDescription> tableDesc = + createTableDescription + ( obj2tagTableName, RelationalObject2TagTable::tableSpecification() ); + + // Set the primary key + std::vector<std::string> pkColumns; + pkColumns.push_back( RelationalObject2TagTable::columnNames::tagId ); + pkColumns.push_back( RelationalObject2TagTable::columnNames::objectId ); + tableDesc->setPrimaryKey( pkColumns ); + + // Create 4D index + std::vector<std::string> i4Columns; + i4Columns.push_back( RelationalObject2TagTable::columnNames::tagId ); + i4Columns.push_back( RelationalObject2TagTable::columnNames::channelId ); + i4Columns.push_back( RelationalObject2TagTable::columnNames::iovSince ); + i4Columns.push_back( RelationalObject2TagTable::columnNames::iovUntil ); + // We are close to the maximum index name length of 31 characters here! + // (with a default table name of COOLTEST_F0001_IOV2TAG) + std::string indexName = obj2tagTableName + "_4INDX"; + tableDesc->createIndex( indexName, i4Columns ); + + // Create the foreign key constraints + // TEMPORARY! Disabled: this FK needs a corresponding PK/UK constraint + // (which we don't have yet, just a unique index, which does not suffice) + // Foreign key #1 + /* + std::vector<std::string> fk1Columns; + fk1Columns.push_back( RelationalObject2TagTable::columnNames::objectId ); + fk1Columns.push_back( RelationalObject2TagTable::columnNames::channelId ); + fk1Columns.push_back( RelationalObject2TagTable::columnNames::iovSince ); + fk1Columns.push_back( RelationalObject2TagTable::columnNames::iovUntil ); + std::string fk1TargetTable = objectTableName; + std::vector<std::string> fk1TargetColumns; + fk1TargetColumns.push_back( RelationalObjectTable::columnNames::objectId ); + fk1TargetColumns.push_back( RelationalObjectTable::columnNames::channelId ); + fk1TargetColumns.push_back( RelationalObjectTable::columnNames::iovSince ); + fk1TargetColumns.push_back( RelationalObjectTable::columnNames::iovUntil ); + std::string fk1ConstraintName = tableName + "_OCSU_FK"; + if ( ! tableDesc->createForeignKey + ( fk1ConstraintName, fk1Columns, fk1TargetTable, fk1TargetColumns ) ) + throw RelationalException( "Could not create FK", "RalSchemaMgr" ); + */ + // Foreign key #2 + std::vector<std::string> fk2Columns; + fk2Columns.push_back( RelationalObject2TagTable::columnNames::objectId ); + std::string fk2TargetTable = objectTableName; + std::string fk2ConstraintName = obj2tagTableName + "_O_FK"; + tableDesc->createForeignKey( fk2ConstraintName, + fk2Columns, + fk2TargetTable, + fk2Columns ); + // Foreign key #3 + std::vector<std::string> fk3Columns; + fk3Columns.push_back( RelationalObject2TagTable::columnNames::tagId ); + std::string fk3TargetTable = tagTableName; + std::string fk3ConstraintName = obj2tagTableName + "_T_FK"; + tableDesc->createForeignKey( fk3ConstraintName, + fk3Columns, + fk3TargetTable, + fk3Columns ); + + // Create the table + log() << "Create table " << obj2tagTableName << coral::MessageStream::endmsg; + session().nominalSchema().createTable( *tableDesc ); +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::renameColumnInTable +( const std::string& tableName, + const std::string& oldColumnName, + const std::string& newColumnName ) const +{ + if ( ! isValidColumnName( newColumnName ) ) + throw InvalidColumnName + ( newColumnName, "RalSchemaMgr::renameColumnInTable"); + + coral::ITable& table = + session().nominalSchema().tableHandle( tableName ); + + table.schemaEditor().renameColumn( oldColumnName, newColumnName ); +} + +//----------------------------------------------------------------------------- + +void RalSchemaMgr::addColumnsToTable +( const std::string& tableName, + const IRecord& columns ) const +{ + + // Get a table handle + coral::ITable& table = + session().nominalSchema().tableHandle( tableName ); + + // Prepare the set clause for setting the default values + std::string setClause; + + // Loop over all columns and add them one by one + const IRecordSpecification& spec = columns.specification(); + for ( UInt32 i = 0; i < spec.size(); i++ ) + { + const IField& column = columns[i]; + + const std::string& columnName = column.specification().name(); + const StorageType::TypeId columnTypeId = column.specification().storageType().id(); + + if ( ! isValidColumnName( columnName ) ) + throw InvalidColumnName + ( columnName, "RalSchemaMgr::addColumnToTable"); + + const StorageType& columnType = StorageType::storageType( columnTypeId ); + const std::string columnTypeName = + coral::AttributeSpecification::typeNameForId( columnType.cppType() ); + int maxSize = columnType.maxSize(); + bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, columnTypeName, maxSize, fixedSize ); + + if ( setClause != "" ) setClause += ", "; + setClause += columnName + " = :" + columnName; + + } + + // Set the default values for the new columns in all existing rows + std::string whereClause = ""; + const coral::AttributeList& updateData = columns.attributeList(); + table.dataEditor().updateRows( setClause, whereClause, updateData ); + +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RalSchemaMgr.h b/RelationalCool/src/RalSchemaMgr.h new file mode 100644 index 000000000..1c5be6492 --- /dev/null +++ b/RelationalCool/src/RalSchemaMgr.h @@ -0,0 +1,184 @@ +// $Id: RalSchemaMgr.h,v 1.28 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RALSCHEMAMGR_H +#define RELATIONALCOOL_RALSCHEMAMGR_H + +// Include files +#include <boost/shared_ptr.hpp> +#include "RelationalAccess/ISessionProxy.h" + +// Local include files +#include "RelationalSchemaMgr.h" + +namespace cool { + + // Forward declarations + class RalSessionMgr; + + /** @class RalSchemaMgr RalSchemaMgr.h + * + * CORAL implementation of the manager + * of the COOL relational database schema. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2006-03-10 + */ + + class RalSchemaMgr : public RelationalSchemaMgr + { + + public: + + /// Constructor from a RelationalDatabase and a RalSessionMgr + /// Inlined with the base class non-standard constructor as otherwise + /// the compiler attempts to use the base class standard constructor + /// (Windows compilation error C2248: standard constructor is private) + RalSchemaMgr( const RelationalDatabase& aDb, + const boost::shared_ptr<RalSessionMgr>& sessionMgr ) + : RelationalSchemaMgr( aDb ) + , m_sessionMgr( sessionMgr ) + { + initialize(); + } + + /// Destructor + virtual ~RalSchemaMgr(); + + /// Drop a table (return false if the table does not exist) + bool dropTable( const std::string& tableName ) const; + + /// Creates a CORAL table description from a RecordSpecification + std::auto_ptr<coral::TableDescription> createTableDescription + ( const std::string& tableName, + const IRecordSpecification& payloadSpec, + const std::string& primaryKey = "" ) const; + + /// Creates the main table + void createMainTable( const std::string& tableName ) const; + + /// Fill the main table + void fillMainTable( const std::string& tableName, + const coral::AttributeList& dbAttr ) const; + + /// Creates the iovTables table + void createIovTablesTable + ( const std::string& iovTablesTableName ) const; + + /// Creates the channelTables table + void createChannelTablesTable + ( const std::string& channelTablesTableName ) const; + + /// Creates the node table + /// TEMPORARY - pass the table prefix to create the root fs tag sequence + void createNodeTable( const std::string& nodeTableName, + const std::string& defaultTablePrefix ) const; + + /// Creates the global tag table + void createGlobalTagTable( const std::string& globalTagTableName, + const std::string& nodeTableName ) const; + + /// Creates the global head tag table + void createGlobalHeadTagTable + ( const std::string& globalHeadTagTableName, + const std::string& globalTagTableName ) const; + + /// Creates the global user tag table + void createGlobalUserTagTable + ( const std::string& globalUserTagTableName, + const std::string& globalTagTableName ) const; + + /// Creates the tag2tag HVS table + void createTag2TagTable( const std::string& tag2tagTableName, + const std::string& globalTagTableName, + const std::string& nodeTableName ) const; + + /// Creates the tag2tag HVS table FK references to the tag table + /// *** This is needed by the coolReplicateDB utility *** + void createTag2TagFKs( const std::string& tag2tagTableName, + const std::string& globalTagTableName ) const; + + /// Creates the tag2tag HVS table FK references to the tag table + /// *** This is needed by the coolReplicateDB utility *** + bool dropTag2TagFKs( const std::string& tag2tagTableName, + bool verbose = true ) const; + + /// Creates a shared sequence table + void createSharedSequence( const std::string& sharedSequenceName, + const std::string& nodeTableName ) const; + + /// Creates the tag sequence for a node + void createTagSequence( const std::string& seqName ) const; + + /// Creates the tag table for a leaf node + void createTagTable( const std::string& tableName ) const; + + /// Creates the channel table for a leaf node + void createChannelTable( const std::string& tableName ) const; + + /// Creates the object2tag (iov2tag) table for a leaf node + void createObject2TagTable + ( const std::string& object2tagTableName, + const std::string& objectTableName, + const std::string& tagTableName ) const; + + /// Creates the object (iov) table for a leaf node + void createObjectTable + ( const std::string& objectTableName, + const std::string& channelTableName, + const IRecordSpecification& payloadSpec, + FolderVersioning::Mode versioningMode ) const; + + /// Creates the FK references from the object table to the channel table + /// *** This is needed by the coolReplicateDB utility *** + void createObjectChannelFK( const std::string& objectTableName, + const std::string& channelTableName ) const; + + /// Drops the FK reference from the object table to the channel table + /// *** This is needed by the coolReplicateDB utility *** + void dropObjectChannelFK( const std::string& objectTableName ) const; + + /// Rename a column of the given table + void renameColumnInTable( const std::string& tableName, + const std::string& oldColumnName, + const std::string& newColumnName ) const; + + /// Add columns to the given table + void addColumnsToTable( const std::string& tableName, + const IRecord& columnSpecAndValues ) const; + + private: + + /// Initialize (complete non-standard constructor with non-inlined code) + void initialize(); + + /// Standard constructor is private + RalSchemaMgr(); + + /// Copy constructor is private + RalSchemaMgr( const RalSchemaMgr& rhs ); + + /// Assignment operator is private + RalSchemaMgr& operator=( const RalSchemaMgr& rhs ); + + /// Returns the database session + /// Delegated to RalSessionMgr. + coral::ISessionProxy& session() const; + + /// Return the server technology for the current connection. + /// Delegated to RalSessionMgr. + const std::string& databaseTechnology() const; + + /// Returns the server version for the current connection. + /// Delegated to RalSessionMgr. + const std::string& serverVersion() const; + + private: + + /// Handle to the RalSessionMgr (shared ownership) + boost::shared_ptr<RalSessionMgr> m_sessionMgr; + + }; + +} + +#endif // RELATIONALCOOL_RALSCHEMAMGR_H + diff --git a/RelationalCool/src/RalSequenceMgr.cpp b/RelationalCool/src/RalSequenceMgr.cpp new file mode 100644 index 000000000..2e3845a1b --- /dev/null +++ b/RelationalCool/src/RalSequenceMgr.cpp @@ -0,0 +1,142 @@ +// $Id: RalSequenceMgr.cpp,v 1.20 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoralBase/MessageStream.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeList.h" +//#include "RelationalAccess/ICursor.h" +#include "RelationalAccess/IQuery.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" +#include "RelationalAccess/ITableDataEditor.h" +#include "RelationalAccess/ITransaction.h" +#include "RelationalAccess/TableDescription.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RalSequenceMgr.h" +#include "RalSchemaMgr.h" +#include "RalSessionMgr.h" +#include "RelationalSequence.h" +#include "RelationalSequenceTable.h" +#include "timeToString.h" +#include "uppercaseString.h" + +// Namespace +using namespace cool; + +//--------------------------------------------------------------------------- + +void RalSequenceMgr::initialize() +{ + log() << coral::Debug << "Instantiate a RalSequenceMgr" << coral::MessageStream::endmsg; +} + +//--------------------------------------------------------------------------- + +RalSequenceMgr::~RalSequenceMgr() +{ + log() << coral::Debug << "Delete the RalSequenceMgr" << coral::MessageStream::endmsg; +} + +//--------------------------------------------------------------------------- + +boost::shared_ptr<RelationalSequence> +RalSequenceMgr::createSequence +( const std::string& seqName ) +{ + log() << coral::Verbose << "Create sequence " << seqName << coral::MessageStream::endmsg; + + // Create the description of the sequence table + // TEMPORARY? Add a sequenceName column only to workaround a RAL bug + log() << coral::Verbose + << "Create the description of table " << seqName << coral::MessageStream::endmsg; + coral::TableDescription desc( "cool::RalSequenceMgr" ); + + desc.setName( seqName ); + + const IRecordSpecification& spec = + RelationalSequenceTable::tableSpecification(); + for ( unsigned int i=0; i<spec.size(); i++ ) { + const IFieldSpecification& field = spec[i]; + bool variableSize = false; + desc.insertColumn + ( field.name(), + coral::AttributeSpecification::typeNameForId + ( field.storageType().cppType() ), + field.storageType().maxSize(), variableSize ); + } + desc.setPrimaryKey( RelationalSequenceTable::columnNames::sequenceName ); + + // Create the sequence + log() << coral::Verbose << "Create table " << seqName << coral::MessageStream::endmsg; + coral::ITable& table = + m_sessionMgr->session().nominalSchema().createTable( desc ); + + // Insert into the sequence table one row that has a null value + // (insert an AttributeList where the attribute to set as NULL is absent) + bool seqNameOnly = true; + const IRecordSpecification& dataSpec = + RelationalSequenceTable::tableSpecification( seqNameOnly ); + coral::AttributeList data = Record( dataSpec ).attributeList(); + data[RelationalSequenceTable::columnNames::sequenceName] + .data<RelationalSequenceTable::columnTypes::sequenceName>() = seqName; + + // TEMPORARY? Will RAL do this as well? + // Check that all column values are within their allowed range + dataSpec.validate(data); + + // Insert a new row + table.dataEditor().insertRow( data ); + + // Return the sequence instance + return getSequence( seqName ); +} + +//----------------------------------------------------------------------------- + +bool RalSequenceMgr::existsSequence +( const std::string& name ) +{ + log() << coral::Verbose + << "Check existence of sequence " << name << coral::MessageStream::endmsg; + return m_sessionMgr->session().nominalSchema().existsTable( name ); +} + +//----------------------------------------------------------------------------- + +boost::shared_ptr<RelationalSequence> +RalSequenceMgr::getSequence +( const std::string& name ) +{ + log() << coral::Verbose << "Get sequence " << name << coral::MessageStream::endmsg; + + // TEMPORARY! Store MySQL now() __ AS IS __ ASSUMING IT IS GMT! + // MySQL does not handle timezones until 4.1.3 + //std::cout << "dbTech: " << m_sessionMgr->databaseTechnology() << std::endl; + if ( m_sessionMgr->databaseTechnology() == "MySQL" ) + { + static bool first = true; + if ( first ) { + first = false; + log() << coral::Warning + << "COOL will ASSUME that your MySQL server is configured to use " + << "GMT times" << coral::MessageStream::endmsg; + } + } + + // Return the sequence instance + return RelationalSequenceMgr::instantiateSequence( name ); +} + +//----------------------------------------------------------------------------- + +void RalSequenceMgr::dropSequence +( const std::string& name ) +{ + log() << coral::Verbose << "Drop sequence " << name << coral::MessageStream::endmsg; + m_sessionMgr->session().nominalSchema().dropTable( name ); +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RalSequenceMgr.h b/RelationalCool/src/RalSequenceMgr.h new file mode 100644 index 000000000..083ad61f1 --- /dev/null +++ b/RelationalCool/src/RalSequenceMgr.h @@ -0,0 +1,81 @@ +// $Id: RalSequenceMgr.h,v 1.8 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RALSEQUENCEMGR_H +#define RELATIONALCOOL_RALSEQUENCEMGR_H + +// Local include files +#include "RelationalSequenceMgr.h" + +namespace cool { + + // Forward declarations + class RalSessionMgr; + + /** @class RalSequenceMgr RalSequenceMgr.h + * + * CORAL implementation of a manager of COOL relational 'sequences'. + * + * Transactions are NOT handled by this class. + * + * @author Andrea Valassi and Marco Clemencic + * @date 2006-03-10 + */ + + class RalSequenceMgr : public RelationalSequenceMgr + { + + public: + + /// Constructor from a RelationalQueryMgr and a RalSessionMgr + /// Inlined with the base class non-standard constructor as otherwise + /// the compiler attempts to use the base class standard constructor + /// (Windows compilation error C2248: standard constructor is private) + RalSequenceMgr( const RelationalQueryMgr& aQueryMgr, + const boost::shared_ptr<RalSessionMgr>& sessionMgr ) + : RelationalSequenceMgr( aQueryMgr ) + , m_sessionMgr( sessionMgr ) + { + initialize(); + } + + /// Destructor + virtual ~RalSequenceMgr(); + + /// Create a new sequence (ownership of the C++ instance is shared). + boost::shared_ptr<RelationalSequence> + createSequence( const std::string& name ); + + /// Does this sequence exist? + bool existsSequence( const std::string& name ); + + /// Get an existing sequence (ownership of the C++ instance is shared). + boost::shared_ptr<RelationalSequence> + getSequence( const std::string& name ); + + /// Drop an existing sequence + void dropSequence( const std::string& name ); + + private: + + /// Initialize (complete non-standard constructor with non-inlined code) + void initialize(); + + /// Standard constructor is private + RalSequenceMgr(); + + /// Copy constructor is private + RalSequenceMgr( const RalSequenceMgr& rhs ); + + /// Assignment operator is private + RalSequenceMgr& operator=( const RalSequenceMgr& rhs ); + + private: + + /// Handle to the RalSessionMgr (shared ownership) + boost::shared_ptr<RalSessionMgr> m_sessionMgr; + + }; + +} + +#endif // RELATIONALCOOL_RALSEQUENCEMGR_H + diff --git a/RelationalCool/src/RalSessionMgr.cpp b/RelationalCool/src/RalSessionMgr.cpp new file mode 100644 index 000000000..9880fc2b6 --- /dev/null +++ b/RelationalCool/src/RalSessionMgr.cpp @@ -0,0 +1,349 @@ +// $Id: RalSessionMgr.cpp,v 1.34 2008-11-06 11:18:27 avalassi Exp $ + +// Include files +#include <cstdlib> +#include "RelationalAccess/IConnectionServiceConfiguration.h" +#include "RelationalAccess/IRelationalDomain.h" +#include "RelationalAccess/IRelationalService.h" +#include "RelationalAccess/ITransaction.h" + +// Local include files +#include "RalSessionMgr.h" +#include "RelationalException.h" +#include "TimingReportMgr.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +/// \todo FIX-ME: I do not like this, but it looks like it is the only way +/// of using SQLite if you do not have the appropriate lines in the +/// authentication.xml file. +std::string cool::RalConnectionString( const RelationalDatabaseId& dbId ) +{ + std::string connectString = dbId.middleTier(); + if ( dbId.alias().empty() ) + { + if ( dbId.technology() == "sqlite" ) + connectString += + "sqlite_file:" + dbId.schema(); + else + connectString += + dbId.technology() + "://" + dbId.server() + "/" + dbId.schema(); + } + else + connectString += dbId.alias(); + return connectString; +} + +//----------------------------------------------------------------------------- + +RalSessionMgr::RalSessionMgr( CoralConnectionServiceProxyPtr ppConnSvc, + const DatabaseId& dbId, + bool readOnly ) + : m_ppConnSvc( ppConnSvc ) + , m_relationalDbId( dbId ) + , m_log( new coral::MessageStream( "RalSessionMgr" ) ) + , m_session( 0 ) + , m_readOnly( readOnly ) +{ + std::string ro = ( m_readOnly ? "R/O" : "R/W" ); + log() << coral::Info << "Instantiate a " << ro << " RalSessionMgr for '" + << m_relationalDbId.urlHidePswd() << "'" << coral::MessageStream::endmsg; + + // Create the appropriate RAL session and connect to the database server + connect(); +} + +//----------------------------------------------------------------------------- + +RalSessionMgr::~RalSessionMgr() +{ + + log() << coral::Info << "Delete the RalSessionMgr for '" + << m_relationalDbId.urlHidePswd() << "'" << coral::MessageStream::endmsg; + + // Disconnect from the database server and delete the RAL session + disconnect(); + +} + +//----------------------------------------------------------------------------- + +const std::string RalSessionMgr::databaseTechnology() const +{ +#ifdef NOCORAL210 + return m_session->properties().flavorName(); +#else + return m_session->remoteProperties().flavorName(); +#endif +} + +//----------------------------------------------------------------------------- + +const std::string RalSessionMgr::serverVersion() const +{ +#ifdef NOCORAL210 + return m_session->properties().serverVersion(); +#else + return m_session->remoteProperties().serverVersion(); +#endif +} + +//----------------------------------------------------------------------------- + +bool RalSessionMgr::isConnected() const +{ + return ( m_session != 0 ); +} + +//----------------------------------------------------------------------------- + +coral::IConnectionService& RalSessionMgr::connectionSvc() const +{ + // Disable the CORAL connection pool automatic cleanup if requested + static bool first = true; + if ( first ) + { + first = false; + if ( getenv( "COOL_DISABLE_CORALCONNECTIONPOOLCLEANUP" ) ) + { + m_ppConnSvc->configuration().disablePoolAutomaticCleanUp(); + m_ppConnSvc->configuration().setConnectionTimeOut( 0 ); + } + } + // Return the CORAL connection service PROXY! + return *m_ppConnSvc; +} + +//----------------------------------------------------------------------------- + +inline static int SetEnv( const std::string& name, const std::string& value ) +{ +#ifndef WIN32 + // UNIX version + return value.empty() ? + ::unsetenv(name.c_str()) , 0 : + ::setenv(name.c_str(),value.c_str(), 1); +#else + // Windows version + return ::_putenv((name+"="+value).c_str()); +#endif +} + +//----------------------------------------------------------------------------- + +void RalSessionMgr::connect() +{ + if ( ! isConnected() ) + { + if ( getenv ( "COOL_TIMINGREPORT" ) ) + { + TimingReportMgr::initialize(); + TimingReportMgr::startTimer( "EXTRA cool::RalSessionMgr::connect()" ); + } + + log() << coral::Info + << "Connect to the database server" << coral::MessageStream::endmsg; + + bool environmentAuthenticationUsed = false; + std::auto_ptr<std::string> old_env_content[2]; + + std::string ralConnectString = RalConnectionString( m_relationalDbId ); + // To pass user and password to CORAL ConnectionService we can only + // use the environment + if ( m_relationalDbId.technology() != "sqlite" && + m_relationalDbId.password() != "" && m_relationalDbId.user() != "" ) { + log() << "explicit credentials in the connection string: I use them" + << coral::MessageStream::endmsg; + log() << coral::Warning + << "You are using explicit credentials in the connection string" + << ": this is deprecated" + << ", please use either XML or LFC based authentication" + << coral::MessageStream::endmsg; + + // if the user specified _BOTH_ user name and password, we can use the + // environment variables to pass those values to CORAL + environmentAuthenticationUsed = true; // to know that I have to + // revert to old values + + // keep a copy of the old env values + char *tmp = ::getenv("CORAL_AUTH_USER"); + if (tmp) + old_env_content[0] = + std::auto_ptr<std::string>( new std::string(tmp) ); + tmp = ::getenv("CORAL_AUTH_PASSWORD"); + if (tmp) + old_env_content[1] = + std::auto_ptr<std::string>( new std::string(tmp) ); + + // put new values in the environment variables + if ( SetEnv("CORAL_AUTH_USER", m_relationalDbId.user()) < 0 || + SetEnv("CORAL_AUTH_PASSWORD",m_relationalDbId.password()) < 0 ) { + // something went wrong with the environment :-( + // revert to old values and forget + log() << coral::Warning << + "Problems when trying to set authentication env. variables, ignoring" + " specified credentials." << coral::MessageStream::endmsg; + if ( old_env_content[0].get() ) { + SetEnv("CORAL_AUTH_USER", *(old_env_content[0])); + } else { + SetEnv("CORAL_AUTH_USER", ""); + } + if ( old_env_content[1].get() ) { + SetEnv("CORAL_AUTH_PASSWORD", *(old_env_content[1])); + } else { + SetEnv("CORAL_AUTH_PASSWORD", ""); + } + environmentAuthenticationUsed = false; + } + } + + if ( environmentAuthenticationUsed ) + { + connectionSvc().configuration(). + setAuthenticationService + ( "CORAL/Services/EnvironmentAuthenticationService" ); + } + + // get the session proxy + coral::AccessMode accessMode; + if ( m_readOnly ) accessMode = coral::ReadOnly; + else accessMode = coral::Update; + if ( m_relationalDbId.role().empty() ) { + m_session = connectionSvc().connect( ralConnectString, + accessMode ); + } else { + m_session = connectionSvc().connect( ralConnectString, + m_relationalDbId.role(), + accessMode ); + } + + if ( environmentAuthenticationUsed ) { + // revert to old values + if ( old_env_content[0].get() ) { + SetEnv( "CORAL_AUTH_USER", *( old_env_content[0] ) ); + } else { + SetEnv( "CORAL_AUTH_USER", "" ); + } + if ( old_env_content[1].get() ) { + SetEnv( "CORAL_AUTH_PASSWORD", *(old_env_content[1]) ); + } else { + SetEnv( "CORAL_AUTH_PASSWORD", "" ); + } + } + + if ( !m_session ) { + throw RelationalException( "Failed to connect to the server", + "RalSessionMgr::connect" ); + } + + log() << "Connection established successfully" << coral::MessageStream::endmsg; + + // In ReaOnly mode start a single transaction for the duration of + // the session (all other clients use a dummy transaction manager). + //if ( m_readOnly ) + if ( m_readOnly && !getenv ( "COOL_READONLYSESSION_MANYTRANSACTIONS" ) ) + { + log() << coral::Info + << "Start a read-only transaction active" + << " for the duration of the database connection" << coral::MessageStream::endmsg; + session().transaction().start( m_readOnly ); + } + + if ( TimingReportMgr::isActive() ) + { + TimingReportMgr::stopTimer( "EXTRA cool::RalSessionMgr::connect()" ); + TimingReportMgr::finalize(); + } + + } +} + +//----------------------------------------------------------------------------- + +void RalSessionMgr::disconnect() +{ + if ( getenv ( "COOL_TIMINGREPORT" ) ) + { + TimingReportMgr::initialize(); + TimingReportMgr::startTimer( "EXTRA cool::RalSessionMgr::disconnect()" ); + } + + if ( isConnected() ) { + + // In Update mode there should be no active transactions unless the + // session manager is being killed as a result of an exception thrown. + // Check if there is an open transactaion, and in that case rollback + // (do not rollback all the time, else CORAL will issue a warning!). + if ( ! m_readOnly ) { + if ( session().transaction().isActive() ) + { + log() << coral::Warning + << "Active transactions found while disconnecting" + << " from an Update session will be rolled back" + << coral::MessageStream::endmsg; + session().transaction().rollback(); + } + } + // In ReaOnly mode there should be one active transaction. + else + { + if ( session().transaction().isActive() ) + { + log() << coral::Info + << "Commit the read-only transaction active" + << " for the duration of the database connection" << coral::MessageStream::endmsg; + session().transaction().commit(); + } + else + { + log() << coral::Warning + << "PANIC! No active transactions found while disconnecting" + << " from a ReadOnly session" + << coral::MessageStream::endmsg; + } + } + + // Disconnect from the database server + log() << coral::Info + << "Disconnect from the database server" << coral::MessageStream::endmsg; + delete m_session; + m_session = 0; + + } + + // TEMPORARY? Should/will be done by CORAL inside ~ISessionProxy? + // Purge the CORAL connection pool (see task #3546) to ensure + // that the connection is physically dropped if the timeout is 0 + try { m_ppConnSvc->purgeConnectionPool(); } catch( ... ){ } + + if ( TimingReportMgr::isActive() ) + { + TimingReportMgr::stopTimer( "EXTRA cool::RalSessionMgr::disconnect()" ); + TimingReportMgr::finalize(); + } + +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RalSessionMgr::log() +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +coral::ISessionProxy& RalSessionMgr::session() const +{ + if ( isConnected() ) + return *m_session; + else + throw RelationalException + ( "Not connected to the database server", "RalSessionMgr" ); +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RalSessionMgr.h b/RelationalCool/src/RalSessionMgr.h new file mode 100644 index 000000000..9a26671f1 --- /dev/null +++ b/RelationalCool/src/RalSessionMgr.h @@ -0,0 +1,135 @@ +// $Id: RalSessionMgr.h,v 1.25 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RALSESSIONMGR_H +#define RELATIONALCOOL_RALSESSIONMGR_H + +// Include files +#include <memory> +#include <boost/shared_ptr.hpp> +#include "CoolKernel/DatabaseId.h" +#include "CoralBase/MessageStream.h" +#include "RelationalAccess/AccessMode.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ISessionProxy.h" +#include "RelationalAccess/ISessionProperties.h" + +// Local include files +#include "CoralConnectionServiceProxy.h" +#include "RelationalDatabaseId.h" + +namespace cool { + + std::string RalConnectionString( const RelationalDatabaseId& dbId ); + + /** @class RalSessionMgr RalSessionMgr.h + * + * Manager of relational database connections via a RAL session. + * + * This class knows nothing about COOL tables. + * It is only concerned with relational database connections. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2005-10-24 + */ + + class RalSessionMgr { + + public: + + /// The constructor automatically connects to the database. + RalSessionMgr( CoralConnectionServiceProxyPtr ppConnSvc, + const DatabaseId& dbId, + bool readOnly ); + + /// The destructor automatically disconnects from the database. + virtual ~RalSessionMgr(); + + /// Return the server technology for the current connection. + /// Supported technologies: "Oracle", "MySQL", "SQLite", "frontier". + /// This ultimately corresponds to coral::IDomain::flavorName() + /// (grep m_flavorName in the four XxxAccess/src/Domain.cpp), + /// because it is equal to ConnectionHandle::technologyName(), + /// which is equal to ConnectionParams::technologyName(), which is + /// set to IDomain::flavorName() in ReplicaCatalogue::getReplicas. + /// *** WARNING!!! THIS MAY CHANGE IN LATER VERSIONS OF THE CODE!!! *** + /// New (not for production!): for URLs using a middle tier, this method + /// returns the properties of the remote database, not of the middle tier + const std::string databaseTechnology() const; + + /// Return the server technology version for the current connection. + /// This ultimately corresponds to coral::IConnection::serverVersion() + /// (grep serverVersion in the four XxxAccess/src/Connection.cpp), + /// because it is equal to ConnectionHandle::serverVersion(), + /// which is equal to IConnection::serverVersion(). + /// *** WARNING!!! THIS MAY CHANGE IN LATER VERSIONS OF THE CODE!!! *** + /// New (not for production!): for URLs using a middle tier, this method + /// returns the properties of the remote database, not of the middle tier + const std::string serverVersion() const; + + /// Return the schema name for the current connection. + inline std::string schemaName() const + { + return m_session->nominalSchema().schemaName(); + } + + /// Return the connection state of the database. + /// [Note that this is subtly different from RelationalDatabase::isOpen!] + bool isConnected() const; + + /// (Re)connect to the database. + void connect(); + + /// Close the database connection. + void disconnect(); + + /// Get a reference to the RAL database session. + /// Throw an exception if there is no connection to the database. + coral::ISessionProxy& session() const; + + /// Get a CORAL MessageStream + coral::MessageStream& log(); + + /// Required access mode to the database. + bool isReadOnly() const + { + return m_readOnly; + } + + private: + + /// Standard constructor is private + RalSessionMgr(); + + /// Copy constructor is private + RalSessionMgr( const RalSessionMgr& rhs ); + + /// Assignment operator is private + RalSessionMgr& operator=( const RalSessionMgr& rhs ); + + private: + + /// Get a reference to the CORAL connection service. + coral::IConnectionService& connectionSvc() const; + + /// Shared pointer to the CORAL connection service pointer. + /// When the database service is deleted, this points to a null pointer. + CoralConnectionServiceProxyPtr m_ppConnSvc; + + /// Global identifier of the database + RelationalDatabaseId m_relationalDbId; + + /// SEAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// RAL session (owned by this instance) connected to the database + coral::ISessionProxy* m_session; + + /// Required access mode to the database + bool m_readOnly; + + }; + +} + +#endif // RELATIONALCOOL_RALSESSIONMGR_H + diff --git a/RelationalCool/src/RalTransactionMgr.cpp b/RelationalCool/src/RalTransactionMgr.cpp new file mode 100644 index 000000000..1f431775b --- /dev/null +++ b/RelationalCool/src/RalTransactionMgr.cpp @@ -0,0 +1,114 @@ +// $Id: RalTransactionMgr.cpp,v 1.8 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include <string> +#include "RelationalAccess/ITransaction.h" + +// Local include files +#include "RalSessionMgr.h" +#include "RalTransactionMgr.h" +#include "RelationalException.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RalTransactionMgr::RalTransactionMgr +( const boost::shared_ptr<RalSessionMgr>& sessionMgr, bool autoTransactions ) + : m_sessionMgr( sessionMgr ) + , m_autoTransactions( autoTransactions ) +{ + m_sessionMgr->log() << "Instantiate a RalTransactionMgr" << coral::MessageStream::endmsg; + if ( ! autoTransactions ) { + //std::cout << "auto transation handling disabled" << std::endl; + } +} + +//----------------------------------------------------------------------------- + +RalTransactionMgr::~RalTransactionMgr() +{ + m_sessionMgr->log() << "Delete the RalTransactionMgr" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalTransactionMgr::start +( bool readOnly ) +{ + std::string msg; + if( readOnly ) msg = "read-only transaction"; + else msg = "read-write transaction"; + m_sessionMgr->log() << "Start a new " << msg << coral::MessageStream::endmsg; + if ( !readOnly && m_sessionMgr->isReadOnly() ) + throw DatabaseOpenInReadOnlyMode( "RalTransactionMgr" ); + // in case of manual transactions only initiate a new one if none is active + // (there is no start transaction hook) + if ( autoTransactions() ) { + m_sessionMgr->session().transaction().start( readOnly ); + } else { + //std::cout << "start " << msg << " called in semi-manual mode" << std::endl; + if ( ! isActive() ) { + //std::cout << "starting new " << msg << std::endl; + m_sessionMgr->session().transaction().start( readOnly ); + } else { + if ( isReadOnly() ) { + //std::cout << "read-only transaction already active" << std::endl; + if ( ! readOnly ) { + //std::cout << "starting new " << msg << std::endl; + m_sessionMgr->session().transaction().start( readOnly ); + } + } + } + } + //std::cout << "transaction started" << std::endl; +} + +//----------------------------------------------------------------------------- + +void RalTransactionMgr::commit() +{ + m_sessionMgr->log() << "Commit any open transaction" << coral::MessageStream::endmsg; + if ( isActive() ) { + if ( autoTransactions() ) { + // auto transactions always commit + m_sessionMgr->session().transaction().commit(); + } else if ( isReadOnly() ) { + // semi-manual transactions only commit if they are read-only + // (this is the 'semi' part of manual: only r/w transactions are + // manually committed) + m_sessionMgr->session().transaction().commit(); + } + } +} + +//----------------------------------------------------------------------------- + +void RalTransactionMgr::rollback() +{ + m_sessionMgr->log() << "Rollback any open transaction" << coral::MessageStream::endmsg; + // Better not to check if the transaction is active or not. + // If there is no active transaction, CORAL will issue a warning. + if ( autoTransactions() ) { + m_sessionMgr->session().transaction().rollback(); + //std::cout << "transaction rolled back" << std::endl; + } +} + +//----------------------------------------------------------------------------- + +bool RalTransactionMgr::isActive() +{ + return m_sessionMgr->session().transaction().isActive(); +} + +//----------------------------------------------------------------------------- + +bool RalTransactionMgr::isReadOnly() +{ + return m_sessionMgr->session().transaction().isReadOnly(); +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RalTransactionMgr.h b/RelationalCool/src/RalTransactionMgr.h new file mode 100644 index 000000000..8661fa443 --- /dev/null +++ b/RelationalCool/src/RalTransactionMgr.h @@ -0,0 +1,78 @@ +// $Id: RalTransactionMgr.h,v 1.6 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RALTRANSACTIONMGR_H +#define RELATIONALCOOL_RALTRANSACTIONMGR_H + +// Include files +#include <boost/shared_ptr.hpp> + +// Local include files +#include "IRelationalTransactionMgr.h" + +namespace cool { + + // Forward declarations + class RalSessionMgr; + + /** @class RalTransactionMgr RalTransactionMgr.h + * + * RAL implementation of a manager of relational database transactions. + * + * @author Andrea Valassi + * @date 2006-03-10 + */ + + class RalTransactionMgr : public IRelationalTransactionMgr { + + public: + + /// Destructor + virtual ~RalTransactionMgr(); + + /// Constructor from a RalSessionMgr + RalTransactionMgr( const boost::shared_ptr<RalSessionMgr>& sessionMgr, + bool autoTransactions = true ); + + private: + + /// Standard constructor is private + RalTransactionMgr(); + + /// Copy constructor is private + RalTransactionMgr( const RalTransactionMgr& rhs ); + + /// Assignment operator is private + RalTransactionMgr& operator=( const RalTransactionMgr& rhs ); + + protected: + + /// Start a transaction + void start( bool readOnly ); + + /// Commit a transaction + void commit(); + + /// Rollback a transaction + void rollback(); + + /// Is the transaction active? + bool isActive(); + + /// Is the transaction read-only? + bool isReadOnly(); + + void setAutoTransactions( bool flag ) { m_autoTransactions = flag; } + bool autoTransactions() const { return m_autoTransactions; } + + private: + + /// Handle to the RalSessionMgr (shared ownership) + boost::shared_ptr<RalSessionMgr> m_sessionMgr; + + bool m_autoTransactions; + + }; + +} + +#endif // RELATIONALCOOL_RALTRANSACTIONMGR_H + diff --git a/RelationalCool/src/RelationalChannelTable.cpp b/RelationalCool/src/RelationalChannelTable.cpp new file mode 100644 index 000000000..11243f7b7 --- /dev/null +++ b/RelationalCool/src/RelationalChannelTable.cpp @@ -0,0 +1,188 @@ +// $Id: RelationalChannelTable.cpp,v 1.11 2008-03-20 18:30:19 marcocle Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" +#include "CoralBase/Attribute.h" +//#include "CoralBase/AttributeList.h" + +// Local include files +#include "RelationalChannelTable.h" +#include "RelationalDatabase.h" +#include "RelationalFolder.h" +#include "RelationalQueryMgr.h" +#include "RelationalTableRow.h" + +using namespace cool; + +//--------------------------------------------------------------------------- + +RelationalChannelTable::RelationalChannelTable +( const RelationalDatabase& db, + const RelationalFolder& folder ) + : m_log( new coral::MessageStream( "RelationalChannelTable" ) ) + , m_queryMgr( db.queryMgr() ) + , m_tableName( folder.channelTableName() ) +{ +} + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +RelationalChannelTable::tableSpecification() +{ + + static RecordSpecification spec; + + if ( spec.size() == 0 ) + { + spec.extend( RelationalChannelTable::columnNames::channelId(), + RelationalChannelTable::columnTypeIds::channelId ); + spec.extend( RelationalChannelTable::columnNames::lastObjectId(), + RelationalChannelTable::columnTypeIds::lastObjectId ); + spec.extend( RelationalChannelTable::columnNames::hasNewData(), + RelationalChannelTable::columnTypeIds::hasNewData ); + spec.extend( RelationalChannelTable::columnNames::channelName(), + RelationalChannelTable::columnTypeIds::channelName ); + spec.extend( RelationalChannelTable::columnNames::description(), + RelationalChannelTable::columnTypeIds::description ); + } + + return spec; + +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalChannelTable::fetchRowForId( const ChannelId& channelId ) const +{ + log() << "Fetch channel row from table " << tableName() + << " for channel_id=" << channelId << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend( "channelId", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::channelId) ); + whereData["channelId"].setValue( channelId ); + std::string whereClause = RelationalChannelTable::columnNames::channelId(); + whereClause += "= :channelId"; + + // Delegate the query to the RelationalQueryMgr + std::string desc = ""; + return queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( tableName() ), + RelationalQueryMgr::columnList( tableSpecification() ), + whereClause, whereData, desc ); +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalChannelTable::fetchRowForChannelName +( const std::string& channelName ) const +{ + log() << "Fetch channel row from table " << tableName() + << " for channel_name=" << channelName << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend( "channelName", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::channelName) ); + whereData["channelName"].setValue( channelName ); + std::string whereClause = RelationalChannelTable::columnNames::channelName(); + whereClause += "= :channelName"; + + // Delegate the query to the RelationalQueryMgr + std::string desc = ""; + return queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( tableName() ), + RelationalQueryMgr::columnList( tableSpecification() ), + whereClause, whereData, desc ); +} + +//--------------------------------------------------------------------------- + +const std::vector<ChannelId> RelationalChannelTable::listChannels() const +{ + log() << "List all channels from table " << tableName() << coral::MessageStream::endmsg; + + RecordSpecification rsetSpec; + rsetSpec.extend + ( RelationalChannelTable::columnNames::channelId(), + RelationalChannelTable::columnTypeIds::channelId ); + + std::string whereClause; // empty WHERE clause (all channels) + coral::AttributeList whereData; + + std::vector<std::string> orderBy; + orderBy.push_back + ( RelationalChannelTable::columnNames::channelId() + " ASC" ); + + std::vector<RelationalTableRow> rows = + queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( tableName() ), + RelationalQueryMgr::columnList( rsetSpec ), + whereClause, whereData, orderBy, "" ); + + std::vector<ChannelId> channels; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + ChannelId channel = + ( *row )[ RelationalChannelTable::columnNames::channelId() ] + .data<ChannelId>(); + channels.push_back( channel ); + } + return channels; + +} + +//--------------------------------------------------------------------------- + +const std::map<ChannelId,std::string> +RelationalChannelTable::listChannelsWithNames() const +{ + log() << "List all channels with names from table " + << tableName() << coral::MessageStream::endmsg; + + RecordSpecification rsetSpec; + rsetSpec.extend + ( RelationalChannelTable::columnNames::channelId(), + RelationalChannelTable::columnTypeIds::channelId ); + rsetSpec.extend + ( RelationalChannelTable::columnNames::channelName(), + RelationalChannelTable::columnTypeIds::channelName ); + + std::string whereClause; // empty WHERE clause (all channels) + coral::AttributeList whereData; + + std::vector<std::string> orderBy; + orderBy.push_back + ( RelationalChannelTable::columnNames::channelId() + " ASC" ); + + std::vector<RelationalTableRow> rows = + queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( tableName() ), + RelationalQueryMgr::columnList( rsetSpec ), + whereClause, whereData, orderBy, "" ); + + std::map<ChannelId,std::string> channelsWithNames; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + ChannelId channelId = + ( *row )[ RelationalChannelTable::columnNames::channelId() ] + .data<ChannelId>(); + std::string channelName = + ( *row )[ RelationalChannelTable::columnNames::channelName() ] + .data<std::string>(); + channelsWithNames[channelId]=channelName; + } + return channelsWithNames; + +} + +//--------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalChannelTable.h b/RelationalCool/src/RelationalChannelTable.h new file mode 100644 index 000000000..71b376530 --- /dev/null +++ b/RelationalCool/src/RelationalChannelTable.h @@ -0,0 +1,114 @@ +// $Id: RelationalChannelTable.h,v 1.13 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALCHANNELTABLE_H +#define RELATIONALCOOL_RELATIONALCHANNELTABLE_H + +// Include files +#include <map> +#include <memory> +#include <string> +#include <vector> +#include "CoralBase/MessageStream.h" +#include "CoolKernel/ChannelId.h" +#include "CoolKernel/StorageType.h" + +// Local iclude files +#include "uppercaseString.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + class RelationalDatabase; + class RelationalFolder; + class RelationalQueryMgr; + class RelationalTableRow; + + /** @namespace RelationalChannelTable RelationalChannelTable.h + * + * Relational schema of the table storing COOL channel metadata. + * + * @author Sven A. Schmidt and Marco Clemencic + * @date 2006-04-27 + */ + + class RelationalChannelTable { + + public: + + RelationalChannelTable( const RelationalDatabase& db, + const RelationalFolder& folder ); + + static const std::string defaultTableName + ( const std::string& prefix, unsigned nodeId ) { + char tableName[] = "Fxxxx_CHANNELS"; + sprintf( tableName, "F%4.4i_CHANNELS", nodeId ); + // TEMPORARY? AV 04.04.2005 + // FIXME: presently the input prefix is uppercase anyway... + return uppercaseString( prefix ) + std::string( tableName ); + } + + struct columnNames { + static const std::string channelId() { return "CHANNEL_ID"; } + static const std::string lastObjectId() { return "LAST_OBJECT_ID"; } + static const std::string hasNewData() { return "HAS_NEW_DATA"; } + static const std::string channelName() { return "CHANNEL_NAME"; } + static const std::string description() { return "DESCRIPTION"; } + }; + + struct columnTypeIds { + static const StorageType::TypeId channelId = StorageType::UInt32; + static const StorageType::TypeId lastObjectId = StorageType::UInt32; + static const StorageType::TypeId hasNewData = StorageType::Bool; + static const StorageType::TypeId channelName = StorageType::String255; + static const StorageType::TypeId description = StorageType::String255; + }; + + struct columnTypes { + typedef UInt32 channelId; + typedef UInt32 lastObjectId; + typedef Bool hasNewData; + typedef String255 channelName; + typedef String255 description; + }; + + /// Get the record specification of the channel table + static const IRecordSpecification& tableSpecification(); + + /// Fetches the channel table row for the given channel id. + const RelationalTableRow + fetchRowForId( const ChannelId& channelId ) const; + + /// Fetches the channel table row for the given channel name. + const RelationalTableRow + fetchRowForChannelName( const std::string& channelName ) const; + + /// Lists channels (fetches all rows) + const std::vector<ChannelId> listChannels() const; + + /// Lists channels with names (fetches all rows) + const std::map<ChannelId,std::string> listChannelsWithNames() const; + + /// Returns the table name. + const std::string& tableName() const { return m_tableName; } + + private: + + /// Get a CORAL MessageStream + coral::MessageStream& log() const { return *m_log; } + + /// Get the RelationalQueryMgr associated to this table + RelationalQueryMgr& queryMgr() const { return m_queryMgr; } + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// Relational query manager + RelationalQueryMgr& m_queryMgr; + + /// Channel table name + std::string m_tableName; + + }; + +} +#endif // RELATIONALCOOL_RELATIONALCHANNELTABLE_H diff --git a/RelationalCool/src/RelationalChannelTablesTable.cpp b/RelationalCool/src/RelationalChannelTablesTable.cpp new file mode 100644 index 000000000..316bc1f02 --- /dev/null +++ b/RelationalCool/src/RelationalChannelTablesTable.cpp @@ -0,0 +1,41 @@ +// $Id: RelationalChannelTablesTable.cpp,v 1.1 2007-02-15 14:37:43 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalChannelTablesTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalChannelTablesTable::tableSpecification() +{ + static RecordSpecification spec; + + if ( spec.size() == 0 ) + { + spec.extend + ( RelationalChannelTablesTable::columnNames::chTableName, + RelationalChannelTablesTable::columnTypeIds::chTableName ); + spec.extend + ( RelationalChannelTablesTable::columnNames::chTableSchemaVersion, + RelationalChannelTablesTable::columnTypeIds::chTableSchemaVersion ); + spec.extend + ( RelationalChannelTablesTable::columnNames::chTableVersioningMode, + RelationalChannelTablesTable::columnTypeIds::chTableVersioningMode ); + spec.extend + ( RelationalChannelTablesTable::columnNames::chTableInsertionTime, + RelationalChannelTablesTable::columnTypeIds::chTableInsertionTime ); + spec.extend + ( RelationalChannelTablesTable::columnNames::channelSpecDesc, + RelationalChannelTablesTable::columnTypeIds::channelSpecDesc ); + spec.extend + ( RelationalChannelTablesTable::columnNames::channelExtRef, + RelationalChannelTablesTable::columnTypeIds::channelExtRef ); + } + return spec; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalChannelTablesTable.h b/RelationalCool/src/RelationalChannelTablesTable.h new file mode 100644 index 000000000..8e3e9781b --- /dev/null +++ b/RelationalCool/src/RelationalChannelTablesTable.h @@ -0,0 +1,82 @@ +// $Id: RelationalChannelTablesTable.h,v 1.1 2007-02-15 14:37:43 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALCHANNELTABLESTABLE_H +#define RELATIONALCOOL_RELATIONALCHANNELTABLESTABLE_H 1 + +// Include files +#include "CoolKernel/StorageType.h" + +// Local include files +#include "VersionNumber.h" +#include "uppercaseString.h" + +namespace cool +{ + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalChannelTablesTable RelationalChannelTablesTable.h + * + * Relational schema of the table storing metadata of COOL channel tables. + * + * @author Andrea Valassi + * @date 2007-02-15 + */ + + namespace RelationalChannelTablesTable { + + inline const std::string defaultTableName( const std::string& prefix ) + { + return uppercaseString(prefix) + "CHANNELTABLES"; + } + + namespace columnNames + { + static const + std::string chTableName = "CHANNELTABLE_NAME"; + static const + std::string chTableSchemaVersion = "CHANNELTABLE_SCHEMA_VERSION"; + static const + std::string chTableVersioningMode = "CHANNELTABLE_VERSIONING"; + static const + std::string chTableInsertionTime = "CHANNELTABLE_INSTIME"; + static const + std::string channelSpecDesc = "CHANNEL_SPEC"; + static const + std::string channelExtRef = "CHANNEL_EXTREF"; + } + + namespace columnTypeIds + { + static const + StorageType::TypeId chTableName = StorageType::String255; + static const + StorageType::TypeId chTableSchemaVersion = StorageType::String255; + static const + StorageType::TypeId chTableVersioningMode = StorageType::Int32; + static const + StorageType::TypeId chTableInsertionTime = StorageType::String255; + static const + StorageType::TypeId channelSpecDesc = StorageType::String64k; + static const + StorageType::TypeId channelExtRef = StorageType::String64k; + } + + namespace columnTypes + { + typedef String255 chTableName; + typedef String255 chTableSchemaVersion; + typedef Int32 chTableVersioningMode; + typedef String255 chTableInsertionTime; + typedef String64k channelSpecDesc; + typedef String64k channelExtRef; + } + + /// Get the record specification of the channelTables table. + const IRecordSpecification& tableSpecification(); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALCHANNELTABLESTABLE_H diff --git a/RelationalCool/src/RelationalDatabase.cpp b/RelationalCool/src/RelationalDatabase.cpp new file mode 100644 index 000000000..2b15c4a46 --- /dev/null +++ b/RelationalCool/src/RelationalDatabase.cpp @@ -0,0 +1,1300 @@ +// $Id: RelationalDatabase.cpp,v 1.188 2009-02-09 18:56:15 avalassi Exp $ + +// Include files +#include <map> +#include <vector> +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordException.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeList.h" + +// Local include files +//#include "IRelationalTransactionMgr.h" +#include "RelationalChannelTable.h" +#include "RelationalDatabase.h" +#include "RelationalDatabaseTable.h" +#include "RelationalException.h" +#include "RelationalFolderSet.h" +#include "RelationalGlobalTagTable.h" +#include "RelationalIovSharedSequenceTable.h" +#include "RelationalNodeMgr.h" +#include "RelationalNodeTable.h" +#include "RelationalObjectTable.h" +#include "RelationalObject2TagTable.h" +#include "RelationalObjectMgr.h" +#include "RelationalQueryMgr.h" +#include "RelationalSchemaMgr.h" +#include "RelationalTableRow.h" +#include "RelationalTag2TagTable.h" +#include "RelationalTagSequence.h" +#include "RelationalTagSharedSequenceTable.h" +#include "RelationalTagTable.h" +#include "RelationalTagMgr.h" +#include "RelationalTransaction.h" +#include "VersionInfo.h" + +// *** START *** 3.0.0 schema extensions (task #4307, task #4396) +#include "RelationalChannelTablesTable.h" +#include "RelationalGlobalHeadTagTable.h" +#include "RelationalGlobalUserTagTable.h" +#include "RelationalIovTablesTable.h" +// **** END **** 3.0.0 schema extensions (task #4307, task #4396) + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalDatabase::RelationalDatabase( const DatabaseId& dbId ) + : m_dbAttr() + , m_isOpen( false ) + , m_relationalDbId( dbId ) + , m_log( new coral::MessageStream( "RelationalDatabase" ) ) + , m_queryMgr( 0 ) + , m_schemaMgr( 0 ) + , m_nodeMgr( 0 ) + , m_tagMgr( 0 ) +{ + log() << coral::Debug << "Instantiate a RelationalDatabase for '" + << m_relationalDbId.middleTier() + << databaseId() << "'" << coral::MessageStream::endmsg; + + // Parse the dbId URL as RelationalDatabaseId connection parameters + std::string technology = m_relationalDbId.technology(); + std::string server = m_relationalDbId.server(); + std::string user = m_relationalDbId.user(); + std::string password = m_relationalDbId.password(); + std::string schema = m_relationalDbId.schema(); + std::string dbName = m_relationalDbId.dbName(); + log() << "Technology: '" << technology << "'" << coral::MessageStream::endmsg; + log() << "Server: '" << server << "'" << coral::MessageStream::endmsg; + log() << "User: '" << user << "'" << coral::MessageStream::endmsg; + if ( getenv( "COOL_AUTH_SHOWPASSWORD" ) ) + log() << "Password: '" << password << "'" << coral::MessageStream::endmsg; + else + log() << "Password: '" << "********" << "'" << coral::MessageStream::endmsg; + log() << "Schema: '" << schema << "'" << coral::MessageStream::endmsg; + log() << "Conditions database name: '" << dbName << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalDatabase::~RelationalDatabase() +{ + //*m_pThis = NULL; + //m_pThis.reset(); + log() << coral::Debug << "Delete the RelationalDatabase for '" + << m_relationalDbId.middleTier() + << databaseId() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +const DatabaseId& RelationalDatabase::databaseId() const +{ + return m_relationalDbId.urlHidePswd(); +} + +//----------------------------------------------------------------------------- + +const std::string& RelationalDatabase::databaseName() const +{ + return m_relationalDbId.dbName(); +} + +//----------------------------------------------------------------------------- + +const IRecord& RelationalDatabase::databaseAttributes() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + return m_dbAttr; +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::createDatabase() +{ + // Default attributes + std::string dbName = databaseName(); + Record dbAttr( databaseAttributesSpecification() ); + + std::string defaultTablePrefix = dbName + "_"; + dbAttr[RelationalDatabaseTable::attributeNames::defaultTablePrefix] + .setValue( defaultTablePrefix ); + + /* + // *** START *** 3.0.0 schema extensions (task #4307) + std::string channelTablesTableName = + RelationalChannelTablesTable::defaultTableName( defaultTablePrefix ); + dbAttr[RelationalDatabaseTable::attributeNames::channelTablesTableName] + .setValue( channelTablesTableName ); + + std::string iovTablesTableName = + RelationalIovTablesTable::defaultTableName( defaultTablePrefix ); + dbAttr[RelationalDatabaseTable::attributeNames::iovTablesTableName] + .setValue( iovTablesTableName ); + // **** END **** 3.0.0 schema extensions (task #4307) + */ + + std::string nodeTableName = + RelationalNodeTable::defaultTableName( defaultTablePrefix ); + dbAttr[RelationalDatabaseTable::attributeNames::nodeTableName] + .setValue( nodeTableName ); + + std::string tagTableName = + RelationalGlobalTagTable::defaultTableName( defaultTablePrefix ); + dbAttr[RelationalDatabaseTable::attributeNames::tagTableName] + .setValue( tagTableName ); + + /* + // *** START *** 3.0.0 schema extensions (task #4396) + std::string headTagTableName = + RelationalGlobalHeadTagTable::defaultTableName( defaultTablePrefix ); + dbAttr[RelationalDatabaseTable::attributeNames::headTagTableName] + .setValue( headTagTableName ); + + std::string userTagTableName = + RelationalGlobalUserTagTable::defaultTableName( defaultTablePrefix ); + dbAttr[RelationalDatabaseTable::attributeNames::userTagTableName] + .setValue( userTagTableName ); + // **** END **** 3.0.0 schema extensions (task #4396) + */ + + std::string tag2TagTableName = + RelationalTag2TagTable::defaultTableName( defaultTablePrefix ); + dbAttr[RelationalDatabaseTable::attributeNames::tag2TagTableName] + .setValue( tag2TagTableName ); + + std::string tagSharedSequenceName = + RelationalTagSharedSequenceTable::defaultTableName( defaultTablePrefix ); + dbAttr[RelationalDatabaseTable::attributeNames::tagSharedSequenceName] + .setValue( tagSharedSequenceName ); + + std::string iovSharedSequenceName = + RelationalIovSharedSequenceTable::defaultTableName( defaultTablePrefix ); + dbAttr[RelationalDatabaseTable::attributeNames::iovSharedSequenceName] + .setValue( iovSharedSequenceName ); + + // Create a database with the default attributes + return createDatabase( dbAttr ); +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::openDatabase() +{ + + std::string dbName = databaseName(); + log() << "Open the database with name " << dbName << coral::MessageStream::endmsg; + + // Connect to the backend server if not yet done + if ( ! isConnected() ) connect(); + + // Retrieve the database attributes in the top-level management table + log() << "Fetch database attributes" << coral::MessageStream::endmsg; + RelationalTransaction transaction( transactionMgr(), true ); // r/o + m_dbAttr = fetchDatabaseAttributes(); + transaction.commit(); + log() << "Fetched database attributes: " << m_dbAttr << coral::MessageStream::endmsg; + + // Check that the release number and schema versions of the database are + // compatible with the release number and schema versions of this client + std::string releaseNumber = + m_dbAttr[RelationalDatabaseTable::attributeNames::release]. + data<std::string>(); + std::string schemaVersion = + m_dbAttr[RelationalDatabaseTable::attributeNames::schemaVersion]. + data<std::string>(); + if ( !areReleaseAndSchemaCompatible( releaseNumber, schemaVersion ) ) { + std::stringstream s; + s << "Release number mismatch - SCHEMA EVOLUTION REQUIRED: " + << "database with OLDER release number " << releaseNumber + << " cannot be opened using CURRENT client release number " + << VersionInfo::release; + throw IncompatibleReleaseNumber( s.str(), "RelationalDatabase" ); + } + + // The database is now open + m_isOpen = true; +} + +//----------------------------------------------------------------------------- + +bool +RelationalDatabase::areReleaseAndSchemaCompatible +( const std::string releaseNumber, + const std::string schemaVersion ) const +{ + bool status = true; + // Preliminary check: this release must be 1.2.0 or later + // MAKE SURE THAT 1.2.0 <= THISRELEASE + VersionNumber db_rel_version(releaseNumber); + VersionNumber db_schema_version(schemaVersion); + + if ( VersionInfo::release < "1.2.0" ) + { + std::stringstream s; + s << "PANIC! CURRENT client release number " << VersionInfo::release + << " is older than 1.2.0?"; + throw IncompatibleReleaseNumber( s.str(), "RelationalDatabase" ); + } + // Cannot open databases created with releases earlier than 1.2.0 + // No schema evolution is possible for such database schemas + // DbRelease < 1.2.0 + else if ( db_rel_version < "1.2.0" ) + { + std::stringstream s; + s << "Release number mismatch" + << " - SCHEMA EVOLUTION NOT POSSIBLE: " + << "database with OLDER release number " << db_rel_version + << " (older than 1.2.0)" + << " cannot be opened using CURRENT client release number " + << VersionInfo::release; + throw IncompatibleReleaseNumber( s.str(), "RelationalDatabase" ); + } + // Schema evolution for 1.2.0 <= DbRelease < THISRELEASE + // Open databases created with releases earlier than this release + else if ( db_rel_version < VersionInfo::release ) + { + // This release (2.7.0) can read 2.6.0 + // This release (2.7.0) can read 2.5.0 + // This release (2.7.0) can read 2.4.0 + // This release (2.7.0) can read 2.3.x (including the unreleased 2.3.1) + // This release (2.7.0) can read 2.2.x + // This release (2.7.0) can read 2.1.x + // This release (2.7.0) can read 2.0.0 + if ( ( db_rel_version == "2.6.0" ) || + ( db_rel_version == "2.5.0" ) || + ( db_rel_version == "2.4.0" ) || + ( db_rel_version >= "2.3.0" && db_rel_version <= "2.3.1" ) || + ( db_rel_version >= "2.2.0" && db_rel_version <= "2.2.2" ) || + ( db_rel_version >= "2.1.0" && db_rel_version <= "2.1.1" ) || + ( db_rel_version == "2.0.0" ) ) + { + status = true; + log() << coral::Warning + << "Release number backward compatibility " + << "- NO SCHEMA EVOLUTION REQUIRED: " + << "database with OLDER release number " << releaseNumber + << " will be opened using CURRENT client release number " + << VersionInfo::release << coral::MessageStream::endmsg; + } + else + // This release (2.7.0) needs schema evolution before it can read 1.3.0-4 + if ( db_rel_version >= "1.3.0" && db_rel_version <= "1.3.4" ) + { + status = false; + log() << coral::Warning + << "Release number mismatch" + << " - SCHEMA EVOLUTION REQUIRED: " + << "database with OLDER release number " << db_rel_version + << " cannot be opened using CURRENT client release number " + << VersionInfo::release << coral::MessageStream::endmsg; + } + else + // This release (2.7.0) needs schema evolution before it can read 1.2.0-9 + if ( db_rel_version >= "1.2.0" && db_rel_version <= "1.2.9" ) + { + status = false; + log() << coral::Warning + << "Release number mismatch" + << " - SCHEMA EVOLUTION REQUIRED: " + << "database with OLDER release number " << db_rel_version + << " cannot be opened using CURRENT client release number " + << VersionInfo::release << coral::MessageStream::endmsg; + } + // This release (2.7.0) can NOT read any other previous releases + else + { + std::stringstream s; + s << "PANIC! Release number mismatch: " + << "database with (UNKNOWN!) OLDER release number " << db_rel_version + << " cannot be opened using CURRENT client release number " + << VersionInfo::release; + throw IncompatibleReleaseNumber( s.str(), "RelationalDatabase" ); + } + } + // DbRelease == THISRELEASE + else if ( db_rel_version == VersionInfo::release ) + { + status = true; + log() << coral::Debug + << "Release number match: " + << "database with CURRENT release number " << db_rel_version + << " will be opened using CURRENT client release number " + << VersionInfo::release << coral::MessageStream::endmsg; + } + // Check schema version for dbs created with releases newer than this one! + // THIS_RELEASE < DbRelease + else if ( VersionInfo::release < db_rel_version ) + { + // Cannot open dbs with schema versions newer than that of this release! + // THIS_SCHEMAVERSION < DbSchemaVersion + if ( VersionInfo::schemaVersion < db_schema_version ) + { + std::stringstream s; + s << "Release number and schema version mismatch" + << " - SCHEMA NOT BACKWARD COMPATIBLE: " + << "database with NEWER release number " << db_rel_version + << " and NEWER schema version " << db_schema_version + << " cannot be opened using CURRENT client release number " + << VersionInfo::release + << " (CURRENT schema version " << VersionInfo::schemaVersion << ")"; + throw IncompatibleReleaseNumber( s.str(), "RelationalDatabase" ); + } + // Open databases created using a newer release but the same schema version + // THIS_SCHEMAVERSION == DbSchemaVersion + else if ( VersionInfo::schemaVersion == db_schema_version ) + { + status = true; + log() << coral::Debug + << "Release number mismatch with schema version match: " + << "database with NEWER release number " << db_rel_version + << " and CURRENT schema version " << db_schema_version + << " will be opened using CURRENT client release number " + << VersionInfo::release + << " (CURRENT schema version " + << VersionInfo::schemaVersion << ")" << coral::MessageStream::endmsg; + } + // PANIC! How can it be that a newer release has an older schema? + else if ( VersionInfo::schemaVersion > db_schema_version ) + { + std::stringstream s; + s << "PANIC! Release number and schema version mismatch: " + << "database with NEWER release number " << db_rel_version + << " than CURRENT client release number " << VersionInfo::release + << " has OLDER schema version " << db_schema_version + << " (CURRENT schema version " << VersionInfo::schemaVersion << ")"; + throw IncompatibleReleaseNumber( s.str(), "RelationalDatabase" ); + } + // PANIC! How can it be that none of "<", "==", ">" is true? + else + { + std::stringstream s; + s << "PANIC! Release number and schema version mismatch: " + << "database with NEWER release number " << db_rel_version + << " than CURRENT client release number " << VersionInfo::release + << " has UNKNOWN schema version " << db_schema_version + << " (CURRENT schema version " << VersionInfo::schemaVersion << ")"; + throw IncompatibleReleaseNumber( s.str(), "RelationalDatabase" ); + } + } + // PANIC! How can it be that none of "<", "==", ">" is true? + else + { + std::stringstream s; + s << "PANIC! Release number mismatch: " + << "database with UNKNOWN release number " << db_rel_version + << " cannot be opened using CURRENT client release number " + << VersionInfo::release; + throw IncompatibleReleaseNumber( s.str(), "RelationalDatabase" ); + } + return status; +} + +//----------------------------------------------------------------------------- + +bool RelationalDatabase::isValidPayloadFieldName +( const std::string& name ) +{ + static std::string allowedChar = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890"; + const std::string ucName = uppercaseString( name ); + if ( name.size() < 1 || + name.size() > 30 || + ucName.find_first_not_of( allowedChar ) != ucName.npos || + ucName.find_first_not_of( "_1234567890" ) != 0 || + ucName.find( "COOL_" ) == 0 ) + return false; + else + return true; +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::validatePayloadSpecification +( const IRecordSpecification& spec ) +{ + // Throw PayloadSpecificationTooManyFields if #fields > 900 + if ( spec.size() > 900 ) + throw PayloadSpecificationTooManyFields + ( spec.size(), "RelationalDatabase" ); + + // Throw PayloadSpecificationTooManyBlobFields if #blobFields > 10 + UInt32 nBlobFields = 0; + for ( UInt32 i = 0; i < spec.size(); i++ ) + if ( spec[i].storageType().id() == StorageType::Blob64k || + spec[i].storageType().id() == StorageType::Blob16M ) nBlobFields++; + if ( nBlobFields > 10 ) + throw PayloadSpecificationTooManyBlobFields + ( nBlobFields, "RelationalDatabase" ); + + // Throw PayloadSpecificationTooManyString255Fields if #string255Fields > 200 + UInt32 nSt255Fields = 0; + for ( UInt32 i = 0; i < spec.size(); i++ ) + if ( spec[i].storageType().id() == StorageType::String255 ) nSt255Fields++; + if ( nSt255Fields > 200 ) + throw PayloadSpecificationTooManyString255Fields + ( nSt255Fields, "RelationalDatabase" ); + + // Throw PayloadSpecificationInvalidFieldName if any field names are invalid. + // Names of payload fields must have between 1 and 30 characters (including + // only letters, digits or '_'), must start with a letter and cannot start + // with the "COOL_" prefix (in any lowercase/uppercase combination). + for ( UInt32 i = 0; i < spec.size(); i++ ) { + const std::string& name = spec[i].name(); + if ( ! isValidPayloadFieldName( name ) ) + throw PayloadSpecificationInvalidFieldName( name, "RelationalDatabase" ); + } +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::closeDatabase() +{ + disconnect(); + m_isOpen = false; +} + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::mainTableName() const +{ + return RelationalDatabaseTable::tableName( databaseName() ); +} + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::defaultTablePrefix() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string theDefaultTablePrefix = + dbAttr[RelationalDatabaseTable::attributeNames::defaultTablePrefix] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return theDefaultTablePrefix; +} + +//----------------------------------------------------------------------------- + +// *** START *** 3.0.0 schema extensions (task #4307) +const std::string RelationalDatabase::iovTablesTableName() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string tableName = + dbAttr[RelationalDatabaseTable::attributeNames::iovTablesTableName] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return tableName; +} + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::channelTablesTableName() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string tableName = + dbAttr[RelationalDatabaseTable::attributeNames::channelTablesTableName] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return tableName; +} +// **** END **** 3.0.0 schema extensions (task #4307) + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::nodeTableName() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string theNodeTableName = + dbAttr[RelationalDatabaseTable::attributeNames::nodeTableName] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return theNodeTableName; +} + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::globalTagTableName() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string tableName = + dbAttr[RelationalDatabaseTable::attributeNames::tagTableName] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return tableName; +} + +//----------------------------------------------------------------------------- + +// *** START *** 3.0.0 schema extensions (task #4396) +const std::string RelationalDatabase::globalHeadTagTableName() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string tableName = + dbAttr[RelationalDatabaseTable::attributeNames::headTagTableName] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return tableName; +} + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::globalUserTagTableName() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string tableName = + dbAttr[RelationalDatabaseTable::attributeNames::userTagTableName] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return tableName; +} +// **** END **** 3.0.0 schema extensions (task #4396) + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::tag2TagTableName() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string tableName = + dbAttr[RelationalDatabaseTable::attributeNames::tag2TagTableName] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return tableName; +} + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::tagSharedSequenceName() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string tableName = + dbAttr[RelationalDatabaseTable::attributeNames::tagSharedSequenceName] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return tableName; +} + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::iovSharedSequenceName() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + const IRecord& dbAttr = databaseAttributes(); + std::string tableName = + dbAttr[RelationalDatabaseTable::attributeNames::iovSharedSequenceName] + .data<RelationalDatabaseTable::columnTypes::attributeValue>(); + return tableName; +} + +//----------------------------------------------------------------------------- + +/* +bool RelationalDatabase::isValidAttributeListSpecification +( const coral::AttributeListSpecification& spec ) +{ + coral::AttributeListSpecification::const_iterator it; + for ( it=spec.begin(); it!=spec.end(); ++it ) { + std::string attrName = it->name(); + + // Check that attribute names only contain alphanumeric characters or '_' + static std::string allowedChar = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; + if ( attrName.find_first_not_of(allowedChar) != std::string::npos ) { + log() << coral::Debug << "Invalid character in attribute name: '" + << attrName << "'" << coral::MessageStream::endmsg; + return false; + } + + } + return true; +} +*/ + +//----------------------------------------------------------------------------- + +bool RelationalDatabase::isOpen() const +{ + return m_isOpen; +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RelationalDatabase::log() const +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +RelationalQueryMgr& RelationalDatabase::queryMgr() const +{ + if ( m_queryMgr.get() ) + return *m_queryMgr; + else + throw RelationalException + ( "PANIC! RelationalQueryMgr pointer is null", "RelationalDatabase" ); +} + +//----------------------------------------------------------------------------- + +RelationalSchemaMgr& RelationalDatabase::schemaMgr() const +{ + if ( m_schemaMgr.get() ) + return *m_schemaMgr; + else + throw RelationalException + ( "PANIC! RelationalSchemaMgr pointer is null", "RelationalDatabase" ); +} + +//----------------------------------------------------------------------------- + +RelationalNodeMgr& RelationalDatabase::nodeMgr() const +{ + if ( m_nodeMgr.get() ) + return *m_nodeMgr; + else + throw RelationalException + ( "PANIC! RelationalNodeMgr pointer is null", "RelationalDatabase" ); +} + +//----------------------------------------------------------------------------- + +RelationalTagMgr& RelationalDatabase::tagMgr() const +{ + if ( m_tagMgr.get() ) + return *m_tagMgr; + else + throw RelationalException + ( "PANIC! RelationalTagMgr pointer is null", "RelationalDatabase" ); +} + +//----------------------------------------------------------------------------- + +const RelationalObjectMgr& RelationalDatabase::objectMgr() const +{ + if ( m_objectMgr.get() ) + return *m_objectMgr; + else + throw RelationalException + ( "PANIC! RelationalObjectMgr pointer is null", + "RelationalDatabase" ); +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::setQueryMgr +( std::auto_ptr<RelationalQueryMgr> queryMgr ) +{ + m_queryMgr = queryMgr; +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::setSchemaMgr +( std::auto_ptr<RelationalSchemaMgr> schemaMgr ) +{ + m_schemaMgr = schemaMgr; +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::setNodeMgr( std::auto_ptr<RelationalNodeMgr> nodeMgr ) +{ + m_nodeMgr = nodeMgr; +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::setTagMgr( std::auto_ptr<RelationalTagMgr> tagMgr ) +{ + m_tagMgr = tagMgr; +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::setObjectMgr +( std::auto_ptr<RelationalObjectMgr> objectMgr ) +{ + m_objectMgr = objectMgr; +} + +//----------------------------------------------------------------------------- + +boost::shared_ptr<IRelationalTransactionMgr> +RelationalDatabase::transactionMgr() const +{ + if ( m_transactionMgr.get() ) + return m_transactionMgr; + else + throw RelationalException + ( "PANIC! RelationalTransactionMgr pointer is null", + "RelationalDatabase" ); +} + +//----------------------------------------------------------------------------- + +void RelationalDatabase::setTransactionMgr +( boost::shared_ptr<IRelationalTransactionMgr> transactionMgr ) +{ + m_transactionMgr = transactionMgr; +} + +//----------------------------------------------------------------------------- + +const IRecordSpecification& +RelationalDatabase::databaseAttributesSpecification() +{ + static RecordSpecification s_dbAttrSpec; + + if ( s_dbAttrSpec.size() == 0 ) { + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::defaultTablePrefix, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + /* + // *** START *** 3.0.0 schema extensions (task #4307) + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::iovTablesTableName, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::channelTablesTableName, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + // **** END **** 3.0.0 schema extensions (task #4307) + */ + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::nodeTableName, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + /* + // *** START *** 3.0.0 schema extensions (task #4396) + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::headTagTableName, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::userTagTableName, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + // **** END **** 3.0.0 schema extensions (task #4396) + */ + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::tagTableName, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::tag2TagTableName, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::tagSharedSequenceName, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::iovSharedSequenceName, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::release, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::cvsCheckout, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::cvsCheckin, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + s_dbAttrSpec.extend + ( RelationalDatabaseTable::attributeNames::schemaVersion, + RelationalDatabaseTable::columnTypeIds::attributeValue ); + } + return s_dbAttrSpec; +} + +//----------------------------------------------------------------------------- + +const StorageType& +RelationalDatabase::storageType( const std::string& name ) +{ + if ( name == "Bool" ) + return StorageType::storageType( StorageType::Bool ); + //if ( name == "Char" ) + // return StorageType::storageType( StorageType::Char ); + if ( name == "UChar" ) + return StorageType::storageType( StorageType::UChar ); + if ( name == "Int16" ) + return StorageType::storageType( StorageType::Int16 ); + if ( name == "UInt16" ) + return StorageType::storageType( StorageType::UInt16 ); + if ( name == "Int32" ) + return StorageType::storageType( StorageType::Int32 ); + if ( name == "UInt32" ) + return StorageType::storageType( StorageType::UInt32 ); + if ( name == "UInt63" ) + return StorageType::storageType( StorageType::UInt63 ); + if ( name == "Int64" ) + return StorageType::storageType( StorageType::Int64 ); + //if ( name == "UInt64" ) + // return StorageType::storageType( StorageType::UInt64 ); + if ( name == "Float" ) + return StorageType::storageType( StorageType::Float ); + if ( name == "Double" ) + return StorageType::storageType( StorageType::Double ); + if ( name == "String255" ) + return StorageType::storageType( StorageType::String255 ); + if ( name == "String4k" ) + return StorageType::storageType( StorageType::String4k ); + if ( name == "String64k" ) + return StorageType::storageType( StorageType::String64k ); + if ( name == "String16M" ) + return StorageType::storageType( StorageType::String16M ); + if ( name == "Blob64k" ) + return StorageType::storageType( StorageType::Blob64k ); + if ( name == "Blob16M" ) + return StorageType::storageType( StorageType::Blob16M ); + throw RelationalException + ( "PANIC! No StorageType exists with name " + name, "RelationalDatabase" ); +} + +//----------------------------------------------------------------------------- + +const std::string RelationalDatabase::encodeRecordSpecification +( const IRecordSpecification& recordSpec ) +{ + std::ostringstream out; + for ( unsigned int i=0; i<recordSpec.size(); i++ ) { + const IFieldSpecification& fieldSpec = recordSpec[i]; + if ( i != 0 ) out << ","; + out << fieldSpec.name() + << ":" << fieldSpec.storageType().name(); + } + return out.str(); +} + +//----------------------------------------------------------------------------- + +const RecordSpecification +RelationalDatabase::decodeRecordSpecification( const std::string& encodedSpec ) +{ + RecordSpecification recordSpec; + if ( !encodedSpec.empty() ) { + std::string::size_type pos = 0; + while ( pos != encodedSpec.npos ) { + std::string::size_type newpos = encodedSpec.find( ',', pos ); + std::string item_str; + if ( newpos != encodedSpec.npos ) + item_str = encodedSpec.substr(pos,newpos-pos); + else + item_str = encodedSpec.substr(pos); + std::string::size_type separator_pos = item_str.find(':'); + if ( separator_pos == item_str.npos ) + throw RelationalException + ( std::string + ( "Bad format, ':' not found in encoded RecordSpecification '" ) + + encodedSpec + "'", "RelationalDatabase" ); + recordSpec.extend + ( item_str.substr( 0, separator_pos ), + RelationalDatabase::storageType + ( item_str.substr( separator_pos+1 ) ) ); + pos = ( newpos != encodedSpec.npos ) ? newpos+1 : newpos; + } + } + return recordSpec; +} + +//----------------------------------------------------------------------------- + +RelationalTableRow +RelationalDatabase::fetchTagTableRow( const std::string& tagTableName, + const std::string& tagName ) +{ + log() << "Fetch tag table row for tag " << tagName + << " from table '" << tagTableName << "'" << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend( "tagName", typeIdToCoralType(RelationalTagTable::columnTypeIds::tagName) ); + whereData["tagName"].setValue( tagName ); + std::string whereClause = RelationalTagTable::columnNames::tagName; + whereClause += "= :tagName"; + + // Delegate the query to the RelationalQueryMgr + try { + std::string desc = ""; + return queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( tagTableName ), + RelationalQueryMgr::columnList + ( RelationalTagTable::tableSpecification() ), + whereClause, whereData, desc ); + } catch( NoRowsFound& ) { + throw TagNotFound + ( "Tag '" + tagName + "' not found in local tag table " + tagTableName , + "RelationalDatabase" ); + } +} + +//----------------------------------------------------------------------------- + +const IHvsTagMgr& RelationalDatabase::hvsTagMgr() const +{ + return tagMgr(); +} + +//----------------------------------------------------------------------------- + +const Record RelationalDatabase::fetchDatabaseAttributes() const +{ + // Fetch all rows from the top-level management table + std::vector<RelationalTableRow> rows; + try { + std::string whereClause = ""; + coral::AttributeList whereData; + rows = queryMgr().fetchRowsFromTables + ( RelationalQueryMgr::tableList( mainTableName() ), + RelationalQueryMgr::columnList + ( RelationalDatabaseTable::tableSpecification() ), + whereClause, whereData, "" ); + } catch ( TableNotFound& ) { + log() << coral::Verbose + << "Could not open database - main database table not found" + << coral::MessageStream::endmsg; + throw DatabaseDoesNotExist( "RelationalDatabase" ); + } + + // Create a new database attributes Record from the rows retrieved + // Read ALL rows even if they are not in the default specification + // (e.g. read schema evolution information where present) + // Use a vector instead of a map to keep the order of properties. + std::vector < std::pair<std::string, std::string> > propertyList; + RecordSpecification spec; + const StorageType::TypeId attrTypeId = + RelationalDatabaseTable::columnTypeIds::attributeValue; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + std::string attrName = + (*row)[RelationalDatabaseTable::columnNames::attributeName]. + data<std::string>(); + std::string attrValue = + (*row)[RelationalDatabaseTable::columnNames::attributeValue]. + data<std::string>(); + spec.extend( attrName, attrTypeId ); + std::pair<std::string, std::string> property( attrName, attrValue ); + propertyList.push_back( property ); + } + Record dbAttr( spec ); + for ( std::vector < std::pair<std::string, std::string> >::const_iterator + prop = propertyList.begin(); prop != propertyList.end(); ++prop ) { + dbAttr[prop->first].setValue( prop->second ); + } + + // Return the database attributes + return dbAttr; +} + +//----------------------------------------------------------------------------- + +RelationalTableRow +RelationalDatabase::fetchObject2TagTableRow +( const std::string& object2TagTableName, + unsigned int tagId, + unsigned int objectId ) +{ + // Define the WHERE clause for the selection using bind variables + RecordSpecification whereSpec; + whereSpec.extend + ( "tagId", RelationalObject2TagTable::columnTypeIds::tagId ); + whereSpec.extend + ( "objectId", RelationalObject2TagTable::columnTypeIds::objectId ); + coral::AttributeList whereData = Record( whereSpec ).attributeList(); + whereData["tagId"].setValue( tagId ); + whereData["objectId"].setValue( objectId ); + std::string whereClause = RelationalObject2TagTable::columnNames::tagId; + whereClause += "= :tagId"; + whereClause += " and "; + whereClause += RelationalObject2TagTable::columnNames::objectId; + whereClause += "= :objectId"; + + // Delegate the query to the RelationalQueryMgr + std::stringstream s; + s << "Query object2Tag table row with tag_id=" << tagId + << " and object_id=" << objectId; + return queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( object2TagTableName ), + RelationalQueryMgr::columnList + ( RelationalObject2TagTable::tableSpecification() ), + whereClause, whereData, s.str() ); +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalDatabase::fetchNodeTableRow( const std::string& fullPath ) const +{ + return nodeMgr().fetchNodeTableRow( fullPath ); +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalDatabase::fetchNodeTableRow( unsigned int nodeId ) const +{ + return nodeMgr().fetchNodeTableRow( nodeId ); +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalDatabase::fetchNodeTableRow +( const std::string& whereClause, + const coral::AttributeList& whereData ) const +{ + return nodeMgr().fetchNodeTableRow( whereClause, whereData ); +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> +RelationalDatabase::listNodes( unsigned int nodeId, + bool isLeaf, + bool ascending ) const +{ + return nodeMgr().listNodes( nodeId, isLeaf, ascending ); +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> +RelationalDatabase::listFolders( const RelationalFolderSet* folderset, + bool ascending ) const +{ + // Cross-check that the database is open + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + RelationalTransaction transaction( transactionMgr(), true ); // read-only + + bool isLeaf = true; + std::vector<std::string> + nodes( listNodes( folderset->id(), isLeaf, ascending ) ); + + transaction.commit(); + + return nodes; +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> +RelationalDatabase::listFolderSets( const RelationalFolderSet* folderset, + bool ascending ) const +{ + // Cross-check that the database is open + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + RelationalTransaction transaction( transactionMgr(), true ); // read-only + + bool isLeaf = false; + std::vector<std::string> + nodes( listNodes( folderset->id(), isLeaf, ascending ) ); + + transaction.commit(); + + return nodes; +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> +RelationalDatabase::listAllNodes( bool ascending ) +{ + // Cross-check that the database is open + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + + // Start a read-only transaction + RelationalTransaction transaction( transactionMgr(), true ); + + // Delegate to the node manager + std::vector<std::string> nodeList = nodeMgr().listAllNodes( ascending ); + + // Commit the transaction + transaction.commit(); + + // Return the list of nodes + return nodeList; +} + +//----------------------------------------------------------------------------- + +/* +const std::vector<std::string> +RelationalDatabase::listAllNodes( bool ascending ) +{ + return nodeMgr().listAllNodes( ascending ); +} +*/ + +//----------------------------------------------------------------------------- + +bool RelationalDatabase::existsNode( const std::string& fullPath ) +{ + return nodeMgr().existsNode( fullPath ); +} + +//----------------------------------------------------------------------------- + +bool RelationalDatabase::existsFolderSet( const std::string& fullPath ) +{ + return nodeMgr().existsFolderSet( fullPath ); +} + +//----------------------------------------------------------------------------- + +bool RelationalDatabase::existsFolder( const std::string& fullPath ) +{ + return nodeMgr().existsFolder( fullPath ); +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> RelationalDatabase::listAllTables() const +{ + if ( ! isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + RelationalTransaction transaction( transactionMgr(), true ); // read-only + std::vector<std::string> tables = __listAllTables(); + transaction.commit(); + return tables; +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> RelationalDatabase::__listAllTables() const +{ + std::vector<std::string> tables; + + // Get the database schema version + std::string dbSchemaVersion = + m_dbAttr[RelationalDatabaseTable::attributeNames::schemaVersion]. + data<std::string>(); + + // Add the tables of each node + coral::AttributeList whereData; // no query WHERE clause + std::string whereClause = ""; // no query WHERE clause + std::vector<std::string> orderBy; // no query ORDER clause + std::string desc = ""; // no query description + std::vector<RelationalTableRow> nodes = + queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification + ( VersionNumber( dbSchemaVersion ) ) ), + whereClause, whereData, orderBy, desc ); + std::vector<RelationalTableRow>::const_iterator node; + for ( node = nodes.begin(); node != nodes.end(); node++ ) + { + std::string fullPath = + (*node)[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + bool isLeaf = + (*node)[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + // If the database schema version is 2.0.0 or higher, check that + // the node schema version is supported by this software release + if ( VersionNumber( dbSchemaVersion ) >= VersionNumber( "2.0.0" ) ) + { + VersionNumber schemaVersion = + (*node)[RelationalNodeTable::columnNames::nodeSchemaVersion] + .data<std::string>(); + bool isSupported = true; + if ( isLeaf ) { + if ( !RelationalFolder::isSupportedSchemaVersion( schemaVersion ) ) + { + // Hack: 2.0.0 folders are not supported, but tables can be listed + if ( schemaVersion != VersionNumber( "2.0.0" ) ) + isSupported = false; + } + } + else { + if ( !RelationalFolderSet::isSupportedSchemaVersion( schemaVersion ) ) + isSupported = false; + } + if ( VersionInfo::release < schemaVersion ) + { + std::stringstream s; + s << "Cannot list tables for node:"; + if ( isLeaf ) s << " folder '"; + else s << " folder set '"; + s << fullPath << " has schema version " << schemaVersion + << " that is newer than this software release " + << VersionInfo::release; + log() << coral::Warning << s.str() << coral::MessageStream::endmsg; + if ( isLeaf ) + throw UnsupportedFolderSchema( s.str(), "RelationalDatabase" ); + else + throw UnsupportedFolderSetSchema( s.str(), "RelationalDatabase" ); + } + else if ( !isSupported ) + { + std::stringstream s; + s << "PANIC! Cannot list tables for node:"; + if ( isLeaf ) s << " folder '"; + else s << " folder set '"; + s << fullPath + << "' appears to have been created using UNKNOWN schema version " + << schemaVersion + << " that is older than (or as old as) the current software release " + << VersionInfo::release; + throw PanicException( s.str(), "RalDatabase" ); + } + } + unsigned int nodeId = + (*node)[RelationalNodeTable::columnNames::nodeId].data<unsigned int>(); + // Node is a folder + if ( isLeaf ) + { + // Add tables for MV folders + FolderVersioning::Mode versioningMode = + RelationalFolder::versioningMode( (*node).data() ); + if ( versioningMode == FolderVersioning::MULTI_VERSION ) + { + // Add the IOV2tag table + tables.push_back + ( RelationalFolder::object2TagTableName( (*node).data() ) ); + // Add the local tag sequence + tables.push_back + ( RelationalTagSequence::sequenceName + ( defaultTablePrefix(), nodeId ) ); + // Add the local tag table + tables.push_back + ( RelationalFolder::tagTableName( (*node).data() ) ); + } + // Add the channel table (2.0.0 or higher) + if ( VersionNumber( dbSchemaVersion ) >= VersionNumber( "2.0.0" ) ) + tables.push_back + ( RelationalChannelTable::defaultTableName + ( defaultTablePrefix(), nodeId ) ); + // Add the IOV table and the associated sequence + tables.push_back + ( RelationalObjectTable::sequenceName + ( RelationalFolder::objectTableName((*node).data()) ) ); + tables.push_back + ( RelationalFolder::objectTableName( (*node).data() ) ); + } + // Node is a folder set + else { + // Add the local tag sequence + tables.push_back + ( RelationalTagSequence::sequenceName + ( defaultTablePrefix(), nodeId ) ); + } + } + + // Add the global tag table + tables.push_back( globalTagTableName() ); + + // Add the tag2tag table and its associated sequence + tables.push_back( RelationalTag2TagTable::sequenceName(tag2TagTableName()) ); + tables.push_back( tag2TagTableName() ); + + // Add the node table and its associated sequence + tables.push_back( RelationalNodeTable::sequenceName(nodeTableName()) ); + tables.push_back( nodeTableName() ); + + // Add the main table + tables.push_back( mainTableName() ); + + // Return the full list of tables + return tables; +} + +//----------------------------------------------------------------------------- + + diff --git a/RelationalCool/src/RelationalDatabase.h b/RelationalCool/src/RelationalDatabase.h new file mode 100644 index 000000000..ab4b0fec1 --- /dev/null +++ b/RelationalCool/src/RelationalDatabase.h @@ -0,0 +1,512 @@ +// $Id: RelationalDatabase.h,v 1.211 2009-01-06 12:30:07 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALDATABASE_H +#define RELATIONALCOOL_RELATIONALDATABASE_H 1 + +// Include files +#include <memory> +#include <vector> +#include <boost/enable_shared_from_this.hpp> +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/IDatabase.h" +#ifdef COOL280 +#include "CoolKernel/ITransaction.h" +#endif +#include "CoolKernel/Record.h" +#include "CoolKernel/ValidityKey.h" +#include "CoralBase/AttributeList.h" +#include "CoralBase/MessageStream.h" + +// Local include files +#include "IHvsTagMgr.h" +#include "RelationalDatabaseId.h" +#include "RelationalDatabasePtr.h" +#include "RelationalObjectPtr.h" + +namespace cool +{ + + // Forward declarations + class ChannelSelection; + class IRelationalTransactionMgr; + class RelationalFolder; + class RelationalFolderSet; + class RelationalNodeMgr; + class RelationalObjectMgr; + class RelationalObjectTable; + class RelationalObjectTableRow; + class RelationalQueryMgr; + class RelationalSchemaMgr; + class RelationalTableRow; + class RelationalTagMgr; + + /** @class RelationalDatabase RelationalDatabase.h + * + * Generic relational implementation of one COOL "condition database" + * instance (deployed on a specific physical infrastructure). + * + * Abstract base class for specific relational implementations + * sharing the same relational database schema (RAL, MySQL, ...). + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2004-11-09 + */ + + class RelationalDatabase : public IDatabase + { + + friend class RelationalDatabaseTest; + friend class RalDatabaseTest; + friend class RalDatabaseTest_extendedSpec; + + public: + + // --- Implementation of the IDatabase interface. --- + + /// Return the global identifier of the database + /// [WARNING: any visible passwords are masked out]. + const DatabaseId& databaseId() const; + + /// Return the 'attributes' of the database + /// (implementation-specific properties not exposed in the API). + /// Throws DatabaseNotOpen if the database is not open. + const IRecord& databaseAttributes() const; + + /* + /// Does the database support this payload specification? + bool isValidPayloadSpecification( const IRecordSpecification& spec ); + */ + + /* + /// Does the database support this channel specification? + bool isValidChannelSpecification( const IRecordSpecification& spec ); + */ + + /// Create a new folder set and return the corresponding manager. + /// The ownership of the folderset manager instance is shared. + /// Throws DatabaseNotOpen if the database is not open. + /// Throws HvsPathHandlerException if the given path has an invalid format. + /// Throws NodeExists if a folder[set] with the same path already exists. + /// Throws an Exception if the max# of folder[set]s (9999) is exceeded. + /// Throws an Exception if an invalid versioning mode has been specified. + /// Throws an Exception if the user does not have writer privileges. + /// PURE VIRTUAL method implemented in subclasses. + virtual IFolderSetPtr createFolderSet + ( const std::string& fullPath, + const std::string& description = "", + bool createParents = false ) = 0; + + /// Does this folder set exist? + /// Throws DatabaseNotOpen if the database is not open. + /// Throws HvsPathHandlerException if the given path has an invalid format. + bool existsFolderSet( const std::string& folderSetName ); + + /// Retrieve an existing folderset and return the corresponding manager. + /// The ownership of the folderset manager instance is shared. + /// Throws DatabaseNotOpen if the database is not open. + /// Throws HvsPathHandlerException if the given path has an invalid format. + /// Throws FolderSetNotFound if the folderset does not exist. + /// PURE VIRTUAL method implemented in subclasses. + virtual IFolderSetPtr getFolderSet( const std::string& fullPath ) = 0; + + /// Create a new folder and return the corresponding manager. + /// The ownership of the folder manager instance is shared. + /// Throws DatabaseNotOpen if the database is not open. + /// Throws HvsPathHandlerException if the given path has an invalid format. + /// Throws NodeExists if a folder[set] with the same path already exists. + /// Throws an Exception if the max# of folder[set]s (9999) is exceeded. + /// Throws an Exception if an invalid versioning mode has been specified. + /// Throws an Exception if the user does not have writer privileges. + /// PURE VIRTUAL method implemented in subclasses. + virtual IFolderPtr createFolder + ( const std::string& fullPath, + const IFolderSpecification& folderSpec, + const std::string& description = "", + bool createParents = false ) = 0; + + /// DEPRECATED: use IFolderSpecification instead of IRecordSpecification! + /// This is similar to the COOL1.3.3 API (with IRecordSpecification + /// instead of ExtendedAttributeListSpecification), for easier porting of + /// user code, but it is likely to be removed in a future COOL release. + /// PURE VIRTUAL method implemented in subclasses. + virtual IFolderPtr createFolder + ( const std::string& fullPath, + const IRecordSpecification& payloadSpec, + const std::string& description = "", + FolderVersioning::Mode mode = FolderVersioning::SINGLE_VERSION, + bool createParents = false ) = 0; + + /// Does this folder exist? + /// Throws DatabaseNotOpen if the database is not open. + /// Throws HvsPathHandlerException if the given path has an invalid format. + bool existsFolder( const std::string& fullPath ); + + /// Retrieve an existing folder and return the corresponding manager. + /// The ownership of the folder manager instance is shared. + /// Throws DatabaseNotOpen if the database is not open. + /// Throws HvsPathHandlerException if the given path has an invalid format. + /// Throws FolderNotFound if the folder does not exist. + /// PURE VIRTUAL method implemented in subclasses. + virtual IFolderPtr getFolder( const std::string& fullPath ) = 0; + + /// Return the list of existing nodes + /// (in ascending/descending alphabetical order). + const std::vector<std::string> listAllNodes( bool ascending = true ); + + /// Drop an existing node (folder or folder set). + /// Also delete any tags associated to the node. + /// Return true if the node and all its structures are dropped as expected. + /// Return false (without throwing any exception) if the node and + /// all its structures do not exist any more on exit from this method, + /// but the node or some of its structures did not exist to start with. + /// Throw an Exception if the node schema version is more recent than + /// the schema version supported by the current COOL software release. + /// Throw an Exception if the node or one of its structures cannot + /// be dropped (i.e. continue to exist on exit from this method). + /// Throw an Exception if the node is a non-empty folder set. + /// Throw an Exception if any associated tags cannot be deleted. + /// PURE VIRTUAL method implemented in subclasses. + virtual bool dropNode( const std::string& fullPath ) = 0; + + /// HVS: does this tag exist? + /// Tag names, except for "HEAD", are case sensitive. + /// Returns true for the reserved tags "" and "HEAD". + bool existsTag( const std::string& tagName ) const + { + return hvsTagMgr().existsTag( tagName ); + } + + /// HVS: return the node type (inner/leaf) where this tag name can be used. + /// Tag names, except for "HEAD", are case sensitive. + /// Throws TagNotFound if the tag does not exist. + IHvsNode::Type tagNameScope( const std::string& tagName ) const + { + return hvsTagMgr().tagNameScope( tagName ); + } + + /// HVS: return the names of the nodes where this tag is defined. + /// Tag names, except for "HEAD", are case sensitive. + /// Throws TagNotFound if the tag does not exist. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + const std::vector<std::string> + taggedNodes( const std::string& tagName ) const + { + return hvsTagMgr().taggedNodes( tagName ); + } + + /// Is the database 'open'? + /// NB Note the difference between 'open' and 'connected': the database + /// is 'connected' if the connection to the database backend has been + /// established; it is 'open' if the management table has been read. + bool isOpen() const; + + /// (Re)opens the database. + void openDatabase(); + + /// Closes the database. + void closeDatabase(); + + /// Return the "COOL database name". + const std::string& databaseName() const; + +#ifdef COOL280 + /// Start a new transaction and enter manual transaction mode + virtual ITransactionPtr startTransaction() = 0; +#endif + + // --- Other public methods. --- + + /// Return the list of folders inside the given folderset + /// (in ascending/descending alphabetical order). + const std::vector<std::string> + listFolders( const RelationalFolderSet* folderset, + bool ascending = true ) const; + + /// Return the list of foldersets inside the given folderset + /// (in ascending/descending alphabetical order). + const std::vector<std::string> + listFolderSets( const RelationalFolderSet* folderset, + bool ascending = true ) const; + + /// Get a constant reference to the HVS tag manager + const IHvsTagMgr& hvsTagMgr() const; + + /// Return the RelationalDatabasePtr + /// PURE VIRTUAL method implemented in subclasses. + virtual boost::shared_ptr<RelationalDatabase> relationalDbPtr() = 0; + + /// Return the default table prefix (from the database attributes) + const std::string defaultTablePrefix() const; + + /// Return the name of the main table (from the db name) + const std::string mainTableName() const; + + // *** START *** 3.0.0 schema extensions (task #4307) + /// Return the name of the iovTables table (from the db attributes) + const std::string iovTablesTableName() const; + + /// Return the name of the channelTables table (from the db attributes) + const std::string channelTablesTableName() const; + // **** END **** 3.0.0 schema extensions (task #4307) + + /// Return the name of the folder table (from the db attributes) + const std::string nodeTableName() const; + + /// Return the name of the global tag table (from the db attributes) + const std::string globalTagTableName() const; + + // *** START *** 3.0.0 schema extensions (task #4396) + /// Return the name of the global head tag table (from the db attributes) + const std::string globalHeadTagTableName() const; + + /// Return the name of the global user tag table (from the db attributes) + const std::string globalUserTagTableName() const; + // **** END **** 3.0.0 schema extensions (task #4396) + + /// Return the name of the tag2tag table (from the db attributes) + const std::string tag2TagTableName() const; + + /// Return the name of the tag shared sequence (from the db attributes) + const std::string tagSharedSequenceName() const; + + /// Return the name of the IOV shared sequence (from the db attributes) + const std::string iovSharedSequenceName() const; + + /// Get a RelationalObjectTable for the given folder. + /// The concrete class can only be created by the concrete database. + /// The RelationalFolder parameter is only used to obtain + /// the associated table names and is *not* retained. + /// PURE VIRTUAL method implemented in subclasses. + virtual boost::shared_ptr<RelationalObjectTable> + relationalObjectTable( const RelationalFolder& folder ) const = 0; + + /// Update the description for the given node + /// PURE VIRTUAL method implemented in subclasses. + virtual void updateNodeTableDescription + ( const std::string& fullPath, + const std::string& description ) const = 0; + + /// Get the IRelationalTransactionMgr + boost::shared_ptr<IRelationalTransactionMgr> transactionMgr() const; + + /// Return the StorageType singleton for the given type name. + /// Throw a RelationalException if no storage type exists with that name. + static const StorageType& storageType( const std::string& name ); + + /// Get a string representation of a RecordSpecification + static const std::string + encodeRecordSpecification( const IRecordSpecification& recordSpec ); + + /// Decode a RecordSpecification from its string representation + static const RecordSpecification + decodeRecordSpecification( const std::string& encodedSpec ); + + /// Get the RelationalQueryMgr + RelationalQueryMgr& queryMgr() const; + + /// Get the RelationalSchemaMgr + RelationalSchemaMgr& schemaMgr() const; + + /// Get the RelationalNodeMgr + RelationalNodeMgr& nodeMgr() const; + + /// Get the RelationalTagMgr + RelationalTagMgr& tagMgr() const; + + /// Get the RelationalObjectMgr + const RelationalObjectMgr& objectMgr() const; + + /// Is this a valid name for a payload field of a folder? + /// Payload field names must have between 1 and 30 characters (including + /// only letters, digits or '_'), must start with a letter and cannot start + /// with the "COOL_" prefix (in any lowercase/uppercase combination). + static bool isValidPayloadFieldName( const std::string& name ); + + /// Return the list of all existing tables (within a transaction) + const std::vector<std::string> listAllTables() const; + + /// Return the list of all existing tables (no transaction) + const std::vector<std::string> __listAllTables() const; + + /// Required access mode to the database. + /// Delegated to RalSessionMgr. + virtual bool isReadOnly() const = 0; + + protected: + + /// The following methods are all protected: only subclasses can + /// instantiate or delete this class and create, drop or open a database + + /// Destructor + virtual ~RelationalDatabase(); + + /// Constructor + RelationalDatabase( const DatabaseId& dbId ); + + /// Create a new database with default attributes. + /// Default attributes are those specific for a RelationalDatabase. + void createDatabase(); + + /// Create a new database with non-default attributes. + /// PURE VIRTUAL method implemented in subclasses. + virtual void createDatabase( const IRecord& dbAttr ) = 0; + + /// Drop the database. + /// PURE VIRTUAL method implemented in subclasses. + virtual bool dropDatabase() = 0; + + /// Fetch the database attributes (fetch all rows from the main table). + const Record fetchDatabaseAttributes() const; + + /// AV - TO BE REMOVED + /// Fetch one node row (lookup by 1 node fullPath) + const RelationalTableRow + fetchNodeTableRow( const std::string& fullPath ) const; + + /// AV - TO BE REMOVED + /// Fetch one node row (lookup by 1 nodeId) + const RelationalTableRow + fetchNodeTableRow( unsigned int nodeId ) const; + + /// AV - TO BE REMOVED + /// Fetch one node row (lookup with given WHERE clause and bind variables) + const RelationalTableRow + fetchNodeTableRow( const std::string& whereClause, + const coral::AttributeList& whereData ) const; + + /// WARNING: UNUSED! (AV) + /// Fetch the tag table row for the given tagname in the given tag table + RelationalTableRow + fetchTagTableRow( const std::string& tagTableName, + const std::string& tagName ); + + /// WARNING: UNUSED! (AV) + /// Fetch the object2Tag table row for the given tagId, objectId + RelationalTableRow + fetchObject2TagTableRow( const std::string& tagTableName, + unsigned int tagId, + unsigned int objectId ); + + /// Does this node exist? + bool existsNode( const std::string& fullPath ); + + /// Return the list of nodes inside the given nodeId with the attribute + /// isLeaf as specified (ordered by name asc/desc) + const std::vector<std::string> + listNodes( unsigned int nodeId, + bool isLeaf, + bool ascending = true ) const; + + /// Get a CORAL MessageStream + coral::MessageStream& log() const; + + /// Set the RelationalQueryMgr (transfer ownership) + void setQueryMgr( std::auto_ptr<RelationalQueryMgr> queryMgr ); + + /// Set the RelationalSchemaMgr (transfer ownership) + void setSchemaMgr( std::auto_ptr<RelationalSchemaMgr> schemaMgr ); + + /// Set the RelationalNodeMgr (transfer ownership) + void setNodeMgr( std::auto_ptr<RelationalNodeMgr> nodeMgr ); + + /// Set the RelationalTagMgr (transfer ownership) + void setTagMgr( std::auto_ptr<RelationalTagMgr> tagMgr ); + + /// Set the RelationalObjectMgr (transfer ownership) + void setObjectMgr( std::auto_ptr<RelationalObjectMgr> objectMgr ); + + /// Set the IRelationalTransactionMgr (shared ownership) + void setTransactionMgr + ( boost::shared_ptr<IRelationalTransactionMgr> mgr ); + + /// Database attribute specification for the RelationalDatabase class + static + const IRecordSpecification& databaseAttributesSpecification(); + + /// Check whether this software library can read the given schema. + /// Returns true if the schema can be read without schema evolution. + /// Returns false if the schema requires schema evolution. + /// Throws an IncompatibleReleaseNumber if the schema is newer than + /// this software library or no schema evolution is possible. + bool areReleaseAndSchemaCompatible + ( const std::string releaseNumber, + const std::string schemaVersion ) const; + + /// Validate the payload specification. + /// Throws InvalidPayloadSpecification if the payload specification is + /// invalid: there can be at most 900 fields, including up to 10 BLOB + /// fields and up to 200 String255 fields; field names must be between + /// 1 and 30 characters (including only letters, digits or '_'), must + /// start with a letter and cannot start with the "COOL_" prefix (in any + /// combination of lowercase and uppercase letters). + void validatePayloadSpecification( const IRecordSpecification& spec ); + + private: + + /// Is the database 'connected'? + /// Delegated to RalSessionMgr. + /// [NB Note the difference between 'open' and 'connected': the database + /// is 'connected' if the connection to the database backend has been + /// established; it is 'open' if the management table has been read]. + /// PURE VIRTUAL method implemented in subclasses. + virtual bool isConnected() const = 0; + + /// (Re)connect to the database. + /// Delegated to RalSessionMgr. + /// PURE VIRTUAL method implemented in subclasses. + virtual void connect() = 0; + + /// Disconnect from the database. + /// Delegated to RalSessionMgr. + /// PURE VIRTUAL method implemented in subclasses. + virtual void disconnect() = 0; + + private: + + /// Standard constructor is private + RelationalDatabase(); + + /// Copy constructor is private + RelationalDatabase( const RelationalDatabase& rhs ); + + /// Assignment operator is private + RelationalDatabase& operator=( const RelationalDatabase& rhs ); + + protected: + + /// Attributes of the database + Record m_dbAttr; + + /// Is the database open? + bool m_isOpen; + + /// Global identifier of the database + RelationalDatabaseId m_relationalDbId; + + private: + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// RelationalQueryMgr (owned by this instance) + std::auto_ptr<RelationalQueryMgr> m_queryMgr; + + /// RelationalSchemaMgr (owned by this instance) + std::auto_ptr<RelationalSchemaMgr> m_schemaMgr; + + /// RelationalNodeMgr (owned by this instance) + std::auto_ptr<RelationalNodeMgr> m_nodeMgr; + + /// RelationalTagMgr (owned by this instance) + std::auto_ptr<RelationalTagMgr> m_tagMgr; + + /// RelationalObjectMgr (owned by this instance) + std::auto_ptr<RelationalObjectMgr> m_objectMgr; + + /// IRelationalTransactionMgr (shared ownership) + boost::shared_ptr<IRelationalTransactionMgr> m_transactionMgr; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALDATABASE_H diff --git a/RelationalCool/src/RelationalDatabaseId.cpp b/RelationalCool/src/RelationalDatabaseId.cpp new file mode 100644 index 000000000..feb4c81cc --- /dev/null +++ b/RelationalCool/src/RelationalDatabaseId.cpp @@ -0,0 +1,334 @@ +// $Id: RelationalDatabaseId.cpp,v 1.30 2009-02-04 10:57:57 avalassi Exp $ + +// Include files +#include <sstream> + +// Local include files +#include "RelationalDatabaseId.h" +#include "RelationalException.h" +#include "uppercaseString.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalDatabaseId::RelationalDatabaseId( const std::string& url ) + : m_middleTier ( "" ) + , m_technology ( "" ) + , m_server ( "" ) + , m_schema ( "" ) + , m_dbName ( "" ) + , m_user ( "" ) + , m_password ( "" ) + , m_alias ( "" ) + , m_role ( "" ) + , m_url ( "" ) + , m_urlHidePswd ( "" ) + , m_urlNoDbname ( "" ) +{ + + i_parseUrl( url ); + + // Debug output + /* + std::cout << "__RelationalDatabaseId Parsing URL: " + << url << std::endl; + std::cout << "__RelationalDatabaseId MiddleTier: " + << m_middleTier << std::endl; + std::cout << "__RelationalDatabaseId Technology: " + << m_technology << std::endl; + std::cout << "__RelationalDatabaseId Server: " + << m_server << std::endl; + std::cout << "__RelationalDatabaseId Schema: " + << m_schema << std::endl; + std::cout << "__RelationalDatabaseId DbName: " + << m_dbName << std::endl; + std::cout << "__RelationalDatabaseId User: " + << m_user << std::endl; + std::cout << "__RelationalDatabaseId Password: " + << m_password << std::endl; + std::cout << "__RelationalDatabaseId URL: " + << m_url << std::endl; + std::cout << "__RelationalDatabaseId URL with password hidden: " + << m_urlHidePswd << std::endl; + std::cout << "__RelationalDatabaseId URL with no dbname: " + << m_urlNoDbname << std::endl; + */ + + i_validate(); + +} + +//----------------------------------------------------------------------------- + +void RelationalDatabaseId::i_validate() { + + // Check that the schema name is not empty + if ( m_schema.empty() && m_alias.empty() ) + throw RelationalException + ( "Invalid COOL database URL '" + m_url + + "': no schema and no alias specified", + "RelationalDatabaseId" ); + + // Check that the database name is not empty + if ( m_dbName.empty() ) + throw RelationalException + ( "Invalid COOL database URL '" + m_url + + "': no database name specified", + "RelationalDatabaseId" ); + + // Check that the database name is at most 8 characters long + unsigned int dbNameMaxLength = 8; + if ( m_dbName.size() > dbNameMaxLength ) { + std::stringstream s; + s << "Invalid COOL database name '" << m_dbName + << "': the database name length must not exceed " + << dbNameMaxLength << " characters"; + throw RelationalException( s.str(), "RelationalDatabaseId" ); + } + + // Check that the database name is uppercase + if ( m_dbName != uppercaseString(m_dbName) ) { + std::stringstream s; + s << "Invalid COOL database name '" << m_dbName + << "': the database name must be UPPERCASE"; + throw RelationalException( s.str(), "RelationalDatabaseId" ); + } + + // Check that the database name contains only letters, numbers or '_' + static std::string allowedChar = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890"; + if ( m_dbName.find_first_not_of(allowedChar) != m_dbName.npos ) { + std::stringstream s; + s << "Invalid COOL database name '" << m_dbName + << "': the database name must contain only letters, numbers" + << " or the '_' character"; + throw RelationalException( s.str(), "RelationalDatabaseId" ); + } + + // Check that the database name starts with a letter + static std::string allowedFirstChar = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if ( m_dbName.find_first_of(allowedFirstChar) != 0 ) { + std::stringstream s; + s << "Invalid COOL database name '" << m_dbName + << "': the database name must start with a letter"; + throw RelationalException( s.str(), "RelationalDatabaseId" ); + } + +} + +//----------------------------------------------------------------------------- + +RelationalDatabaseId::RelationalDatabaseId( const std::string& technology, + const std::string& server, + const std::string& schema, + const std::string& dbName, + const std::string& user, + const std::string& password ) + : m_middleTier ( "" ) +{ + std::string url = technology + "://" + server; + url += std::string( ";schema=" ) + schema; + url += std::string( ";dbname=" ) + dbName; + if ( user != "" ) + url += std::string( ";user=" ) + user; + if ( password != "" ) + url += std::string( ";password=" ) + password; + i_parseUrl( url ); + i_validate(); +} + +//----------------------------------------------------------------------------- + +RelationalDatabaseId::RelationalDatabaseId( const std::string& alias, + const std::string& dbName, + const std::string& dbRole ) + : m_middleTier ( "" ) +{ + if ( dbRole.empty() ){ + i_parseUrl( alias + "/" + dbName ); + } else { + i_parseUrl( alias + "(" + dbRole + ")/" + dbName ); + } + i_validate(); +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalDatabaseId::extractOption( const std::string& url, + const std::string& inputOption ) +{ + std::string option = inputOption; + if (option[option.size()-1] != '=') option += '='; + size_t pos1 = url.find(option); + size_t pos2; + if ( pos1 != url.npos ) { + pos1 += option.size(); // move to the end of the occurence of "option" + pos2 = url.find(";",pos1); + if ( pos2 == url.npos ) + return url.substr(pos1); + else + return url.substr(pos1,pos2-pos1); + } + return ""; +} + +//----------------------------------------------------------------------------- + +void RelationalDatabaseId::i_parseUrl( const std::string& fullUrl ) +{ + + // URL formats: + // + // <technology>://<server>;schema=<schema>;dbname=<dbname>[;user=<user>;password=<password>] + // + // <alias>/<dbname> + // + // coral[...]://host:port&<technology>://<server>;schema=<schema>;dbname=<dbname>[;user=<user>;password=<password>] + // + // coral[...]://host:port&<alias>/<dbname> + // + + // distinguish between the four types + std::string url = fullUrl; + + // Third or fourth format + if ( url.find("://") != url.npos ) + { + + std::string sep = "&"; + size_t pos = url.find(sep); + if ( pos != url.npos ) + { + if ( url.find("coral") != 0 ) + throw RelationalException + ( "Middle tier prefix '..." +sep + "' does not start with 'coral'", + "RelationalDatabaseId" ); + m_middleTier = url.substr(0,pos+1); + url = url.substr(pos+1); + } + + } + + // First or third format + if ( url.find("://") != url.npos ) + { + + // find technology + size_t pos = url.find("://"); + m_technology = url.substr(0,pos); + // check technology + if ( m_technology != "oracle" && + m_technology != "mysql" && + m_technology != "sqlite" && + m_technology != "frontier" ) { + throw RelationalException + ( "Unknown technology '" + m_technology + + "' in input URL '" + url + "'", "RelationalDatabaseId" ); + } + + // find server + pos += 3; // mo to the end of "://" + size_t pos2 = url.find(";",pos); + if ( pos2 == url.npos ) { /// \todo FIX-ME: this should not be allowed + m_server = url.substr(pos); + } else { + m_server = url.substr(pos,pos2-pos); + } + + // extract options + m_schema = extractOption(url,"schema"); + m_dbName = extractOption(url,"dbname"); + m_user = extractOption(url,"user"); + m_password = extractOption(url,"password"); + + m_alias = ""; + + // set commodity strings + m_url = m_urlHidePswd = m_urlNoDbname = m_technology + "://" + m_server; + + if (!m_schema.empty()) { + std::string schema = ";schema=" + m_schema; + m_url += schema; + m_urlHidePswd += schema; + m_urlNoDbname += schema; + } + + if (!m_dbName.empty()) { + std::string dbName = ";dbname=" + m_dbName; + m_url += dbName; + m_urlHidePswd += dbName; + } + + if (!m_user.empty()) { + std::string user = ";user=" + m_user; + m_url += user; + m_urlHidePswd += user; + m_urlNoDbname += user; + } + + if (!m_password.empty()) { + std::string password = ";password=" + m_password; + m_url += password; + m_urlHidePswd += std::string(";password=") + "********"; + m_urlNoDbname += password; + } + + } + + // Second or fourth format + else + { + + size_t pos = url.find_last_of('/'); + + if ( pos == url.npos ) { + throw RelationalException + ( "Invalid COOL database URL '" + url + + "': no '/' character found", + "RelationalDatabaseId" ); + } + + m_alias = url.substr(0,pos); + m_dbName = url.substr(pos+1); + + if ( m_alias[m_alias.size()-1] == ')' ) { + // role explicetely defined + pos = url.find_last_of('('); + if ( pos == url.npos ) { + throw RelationalException + ( "Invalid COOL database URL: '" + url + + "': no matching '(' character found", + "RelationalDatabaseId" ); + } + m_role = m_alias.substr(pos+1,m_alias.size()-2-pos); + m_alias = m_alias.substr(0,pos); + } + + m_user = m_password = ""; + // Check if the URL starts with "sqlite_file:" + if ( m_alias.substr(0,12) == "sqlite_file:" ) { + m_technology = "sqlite"; + m_schema = m_alias.substr(12); + } else { + m_technology = ""; + m_schema = ""; + } + + // set commodity strings + if (m_role.empty()) { + m_url = m_urlHidePswd = m_alias + "/" + m_dbName; + m_urlNoDbname = m_alias; + } else { + m_url = m_urlHidePswd = m_alias + "(" + m_role + ")/" + m_dbName; + m_urlNoDbname = m_alias + "(" + m_role + ")"; + } + } + +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalDatabaseId.h b/RelationalCool/src/RelationalDatabaseId.h new file mode 100644 index 000000000..71431d7fb --- /dev/null +++ b/RelationalCool/src/RelationalDatabaseId.h @@ -0,0 +1,175 @@ +// $Id: RelationalDatabaseId.h,v 1.18 2009-02-09 18:56:15 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALALDATABASEID_H +#define RELATIONALCOOL_RELATIONALALDATABASEID_H 1 + +// Include files +#include <string> +#include <map> + +namespace cool { + + /** @class RelationalDatabaseId RelationalDatabaseId.h + * + * Lookup information for a relational COOL conditions database + * implemented using the RelationalAccess layer (CORAL). + * + * A RelationalDatabaseID can be constructed from a string URL. + * The URL is parsed assuming the following syntax + * - "alias[(role)]/dbname" + * - "technology://server;schema=xx;dbname=xx[;user=xx][;password=xx]" + * (<i>deprecated</i>) + * + * The first format uses CORAL ConnectionService. "alias" is the + * CORAL logical database name and the optional parameter "role" is + * the CORAL role. + * + * Options "schema", "dbname", "user" and "password" can be entered + * in any given order. Any other options are presently ignored. + * + * Parameter "technology": required. + * Specifies the relational backend technology. + * Supported values: "oracle", "mysql", "sqlite" and "frontier". + * + * Parameter "server": required. + * Specifies the Internet address of the relational database server. + * Supported values: + * - oracle: TNS ("devdb10") or EasyConnect ("oradev10[.cern.ch]:10520/D10") + * - mysql: host[:port] ("pcitdb59[.cern.ch][:3306]") + * - sqlite: none ("none"), sqlite uses files on the local client + * - frontier: oracle EasyConnect ("frontier3d[.cern.ch]:8080/Frontier") + * + * Parameter "schema": required. + * Specifies the namespace to be used as a prefix for accessing COOL + * tables, according to the SQL syntax "select * from namespace.table". + * Supported values: + * - oracle: user name (name of table owner) + * - mysql: 'database' name + * - sqlite: 'database' name (see http://www.sqlite.org/lang_attach.html) + * - frontier: oracle user name (name of table owner) + * + * Parameter "dbname": required. + * Restrictions: "dbname" must be uppercase and 1 to 8 characters long; + * it may contain letters, numbers or '_', but it must start with a letter. + * Specifies a unique identifier of a COOL "database" within a given schema + * (for instance, it may indicate the name of a top-level management table, + * or a primary key entry in a top-level management table of predefined + * name, or a string prefixed to predefined table names). + * Presently, a COOL database "dbname" can be bootstrapped from the single + * table "dbname"_DB_ATTRIBUTES, which contains the names of all other + * tables or table prefixes for that database; actually, all tables are + * created by default with a "dbname_" prefix, but this is not assumed + * at lookup time. + * + * Parameter "password": optional. + * Specifies the password to connect to the given server as the given user + * (an exception is thrown if "password" is specified but "user" is not). + * If "password" is absent, a database connection using an authentication + * service is attempted (presently, the password is looked up in an XML + * file, eventually grid certificates or Kerberos tokens may be used). + * + * Parameter "user": optional. + * Specifies the user name to connect to the given server (the password may + * be either passed in the URL or looked up via the authentication service). + * If "user" is absent, the default user and password for the given server + * and schema [and dbname] are looked up via the authentication service. + * For mysql and sqlite, connections with no user/password are possible. + * + * Examples: + * "oracle://devdb10;schema=aSch;dbname=aDb;user=aUser;password=aPswd" + * "oracle://oradev10:10520/D10;schema=aSc;dbname=aDb;user=aUs" + * "mysql://pcitdb59;schema=aSch;dbname=aDb;user=aUser;password=aPswd" + * "sqlite://none;schema=myFile.db;dbname=aDb" + * "frontier://frontier3d.cern.ch:8080/Frontier;schema=aSch;dbname=aDb" + * + * *** WARNING!!! THIS MAY CHANGE IN LATER VERSIONS OF THE CODE!!! *** + * New (not for production!): an optional prefix "coral[...]://host:port&" + * indicates that COOL should connect to a CORAL server. Any prefix that + * begins with "coral" will be interpreted this way (eg "coral", "corals"). + * Both explicit URLs and aliases are supported, e.g. + * "coral://host:port&oracle://server;schema=x;dbname=y;user=w;password=z" + * "coral://host:port&alias/dbname" + * *** WARNING!!! THIS MAY CHANGE IN LATER VERSIONS OF THE CODE!!! *** + * + * @author Sven A. Schmidt, Andrea Valassi and Marco Clemencic + * @date 2004-08-23 + */ + + class RelationalDatabaseId { + + public: + + /// Construct a RelationalDatabaseId from a string URL + RelationalDatabaseId( const std::string& url ); + + /// Construct a RelationalDatabaseId from explicit parameters + RelationalDatabaseId( const std::string& technology, + const std::string& server, + const std::string& schema, + const std::string& dbName, + const std::string& user = "", + const std::string& password = "" ); + + /// Construct a RelationalDatabaseId from explicit parameters + RelationalDatabaseId( const std::string& alias, + const std::string& dbName, + const std::string& dbRole = "" ); + + /// Destructor + virtual ~RelationalDatabaseId(){} + + const std::string& middleTier() const { return m_middleTier; } + + const std::string& technology() const { return m_technology; } + const std::string& server() const { return m_server; } + const std::string& schema() const { return m_schema; } + const std::string& dbName() const { return m_dbName; } + const std::string& user() const { return m_user; } + const std::string& password() const { return m_password; } + + const std::string& alias() const { return m_alias; } + const std::string& role() const { return m_role; } + + const std::string& url() const { return m_url; } + const std::string& urlHidePswd() const { return m_urlHidePswd; } + const std::string& urlNoDbname() const { return m_urlNoDbname; } + + private: + + /// Standard constructor is private + RelationalDatabaseId(); + + /// Validate the parameters specified in the constructor + void i_validate(); + + /// Parse a URL and set the connection parameters accordingly + void i_parseUrl( const std::string& url ); + + /// Extract from a given string containing a sub-string + /// like "option=*****;" the part between '=' and ';' + /// (or the end of the string if ';' is not present). + static const std::string + extractOption( const std::string& url, const std::string& option ); + + private: + + std::string m_middleTier; // Example: "coral[...]://host:port&" + + std::string m_technology; + std::string m_server; + std::string m_schema; + std::string m_dbName; + std::string m_user; + std::string m_password; + + std::string m_alias; + std::string m_role; + + std::string m_url; + std::string m_urlHidePswd; + std::string m_urlNoDbname; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALALDATABASEID_H diff --git a/RelationalCool/src/RelationalDatabasePtr.h b/RelationalCool/src/RelationalDatabasePtr.h new file mode 100644 index 000000000..758e53302 --- /dev/null +++ b/RelationalCool/src/RelationalDatabasePtr.h @@ -0,0 +1,19 @@ +// $Id: RelationalDatabasePtr.h,v 1.1 2006-03-10 11:52:39 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALDATABASEPTR_H +#define RELATIONALCOOL_RELATIONALDATABASEPTR_H + +// Include files +#include <boost/shared_ptr.hpp> + +namespace cool { + + // Forward declarations + class RelationalDatabase; + + /// Shared pointer to a RelationalObject + typedef boost::shared_ptr<RelationalDatabase> RelationalDatabasePtr; + +} + +#endif + diff --git a/RelationalCool/src/RelationalDatabaseTable.cpp b/RelationalCool/src/RelationalDatabaseTable.cpp new file mode 100644 index 000000000..48a8b9c7f --- /dev/null +++ b/RelationalCool/src/RelationalDatabaseTable.cpp @@ -0,0 +1,26 @@ +// $Id: RelationalDatabaseTable.cpp,v 1.7 2006-09-28 12:49:29 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalDatabaseTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalDatabaseTable::tableSpecification() +{ + static cool::RecordSpecification spec; + if ( spec.size() == 0 ) { + spec.extend + ( cool::RelationalDatabaseTable::columnNames::attributeName, + cool::RelationalDatabaseTable::columnTypeIds::attributeName ); + spec.extend + ( cool::RelationalDatabaseTable::columnNames::attributeValue, + cool::RelationalDatabaseTable::columnTypeIds::attributeValue ); + } + return spec; +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalDatabaseTable.h b/RelationalCool/src/RelationalDatabaseTable.h new file mode 100644 index 000000000..0738b088c --- /dev/null +++ b/RelationalCool/src/RelationalDatabaseTable.h @@ -0,0 +1,110 @@ +// $Id: RelationalDatabaseTable.h,v 1.28 2007-02-16 16:53:29 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALDATABASETABLE_H +#define RELATIONALCOOL_RELATIONALDATABASETABLE_H 1 + +// Include files +#include "CoolKernel/StorageType.h" + +// Local include files +#include "uppercaseString.h" + +namespace cool +{ + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalDatabaseTable RelationalDatabaseTable.h + * + * Relational schema of the main table for a COOL conditions "database". + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2004-12-16 + */ + + namespace RelationalDatabaseTable + { + + /// The name of the main table for the given "conditions database name". + /// This is the only hardcoded mapping that cannot be changed by the user. + inline const std::string tableName( const std::string& dbName ) + { + // TEMPORARY? AV 04.04.2005 + // The RelationalDatabaseId constructor throws an exception if dbname + // is not uppercase: this is meant to prevent users from believing that + // dbnames are case-sensitive (e.g., from believing that "myDb", "mydb" + // and "MYDB" are three different databases). Eventually, case-sensitive + // dbnames may be supported by mapping them to different case-sensitive + // table names (such as "myDb_DB_ATTRIBUTES" or "MYDB_DB_ATTRIBUTES"). + // Note that ALL tables are presently uppercase: if we decide to go for + // case-sensitive table names, all other Table classes must be changed! + // FIXME: presently the dbname is uppercase anyway... + return uppercaseString(dbName) + "_DB_ATTRIBUTES"; + } + + namespace columnNames + { + static const std::string attributeName = "DB_ATTRIBUTE_NAME"; + static const std::string attributeValue = "DB_ATTRIBUTE_VALUE"; + } + + namespace columnTypeIds + { + static const StorageType::TypeId attributeName = StorageType::String255; + static const StorageType::TypeId attributeValue = StorageType::String4k; + } + + namespace columnTypes + { + typedef String255 attributeName; + typedef String4k attributeValue; + } + + namespace attributeNames + { + static const + std::string defaultTablePrefix = "DEFAULT_TABLE_PREFIX"; + // *** START *** 3.0.0 schema extensions (task #4307) + static const + std::string iovTablesTableName = "IOVTABLES_TABLE_NAME"; + static const + std::string channelTablesTableName = "CHANNELTABLES_TABLE_NAME"; + // **** END **** 3.0.0 schema extensions (task #4307) + static const + std::string nodeTableName = "NODE_TABLE_NAME"; + static const + std::string tagTableName = "TAG_TABLE_NAME"; + // *** START *** 3.0.0 schema extensions (task #4396) + static const + std::string headTagTableName = "HEADTAG_TABLE_NAME"; + static const + std::string userTagTableName = "USERTAG_TABLE_NAME"; + // **** END **** 3.0.0 schema extensions (task #4396) + static const + std::string tag2TagTableName = "TAG2TAG_TABLE_NAME"; + static const + std::string tagSharedSequenceName = "TAG_SHAREDSEQ_NAME"; + static const + std::string iovSharedSequenceName = "IOV_SHAREDSEQ_NAME"; + static const + std::string release = "RELEASE"; + static const + std::string cvsCheckout = "CVS_CHECKOUT"; + static const + std::string cvsCheckin = "CVS_CHECKIN"; + static const + std::string schemaVersion = "SCHEMA_VERSION"; + static const + std::string lastReplication = "LAST_REPLICATION"; + static const + std::string lastReplicationSource = "LAST_REPLICATION_SOURCE"; + } + + /// Get the record specification of the main database table. + const cool::IRecordSpecification& tableSpecification(); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALDATABASETABLE_H diff --git a/RelationalCool/src/RelationalException.cpp b/RelationalCool/src/RelationalException.cpp new file mode 100644 index 000000000..192ce66b5 --- /dev/null +++ b/RelationalCool/src/RelationalException.cpp @@ -0,0 +1,38 @@ +// $Id: RelationalException.cpp,v 1.8 2006-02-28 10:43:41 avalassi Exp $ + +// Local include files +#include "RelationalException.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalException::RelationalException( const std::string& message, + const std::string& methodName ) + : Exception( message, methodName ) +{ + //std::cout << "Construct new RelationalException from: " + // << "message='" << message << "', " + // << "method='" << methodName << "'" << std::endl; +} + +//----------------------------------------------------------------------------- + +RelationalException::RelationalException( const RelationalException& rhs ) + : Exception( static_cast< const Exception& >( rhs ) ) +{ + //std::cout << "Copy construct RelationalException from: '" + // << rhs.what() << "'" << std::endl; +} + +//----------------------------------------------------------------------------- + +RelationalException::~RelationalException() throw() +{ + //std::cout << "Destroy RelationalException: '" + // << what() << "'" << std::endl; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalException.h b/RelationalCool/src/RelationalException.h new file mode 100644 index 000000000..79e8b5b22 --- /dev/null +++ b/RelationalCool/src/RelationalException.h @@ -0,0 +1,446 @@ +// $Id: RelationalException.h,v 1.39 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALEXCEPTION_H +#define RELATIONALCOOL_RELATIONALEXCEPTION_H 1 + +// Include files +#include "CoolKernel/Exception.h" + +// Local include files +#include "VersionInfo.h" + +namespace cool +{ + + //-------------------------------------------------------------------------- + + /** @class RelationalException RelationalException.h + * + * Base exception class for the relational implementations of COOL. + * Derived from SEAL Exception just like the POOL RelationalException. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2004-11-10 + */ + + class RelationalException : public Exception { + + public: + + /// Constructor + RelationalException( const std::string& message, + const std::string& methodName = "" ); + + /// Copy constructor + RelationalException( const RelationalException& rhs ); + + /// Destructor + virtual ~RelationalException() throw(); + + }; + + //-------------------------------------------------------------------------- + + /** @class PanicException PanicException.h + * + * Exception class for PANIC situations (asserts). + * These are situations which should not normally happen in user code: + * their meaning is that the code must be extended to cover new use cases. + * + * @author Andrea Valassi + * @date 2007-10-26 + */ + + class PanicException : public RelationalException { + + public: + + /// Constructor + explicit PanicException( const std::string& message, + const std::string& domain ) + : RelationalException( message, domain ) + { + } + + /// Destructor + virtual ~PanicException() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class NodeTableRowNotFound + * + * Exception thrown when the row for a node with a given name + * or nodeId cannot be found in the node table. + */ + + class NodeTableRowNotFound : public RelationalException { + + public: + + /// Constructor + explicit NodeTableRowNotFound( const std::string& methodName ) + : RelationalException( "Table row for specified node not found", + methodName ) {} + + /// Constructor + explicit NodeTableRowNotFound( const std::string& fullPath, + const std::string& methodName ) + : RelationalException( "Table row for node with name=" + fullPath + + " not found", methodName ) {} + + /// Constructor + explicit NodeTableRowNotFound( unsigned int nodeId, + const std::string& methodName ) + : RelationalException( "", methodName ) + { + std::stringstream msg; + msg << "Table row for node with nodeId=" << nodeId << " not found"; + setMessage( msg.str() ); + } + + /// Destructor + virtual ~NodeTableRowNotFound() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class FolderSpecificTableNotFound + * + * Exception thrown when a folder-specific table (object table, + * tag table, object2tag table) cannot be found, even if its name + * was retrieved from the corresponding node table row: this may + * indicate either data corruption or DDL changes by another process + * during the job lifetime (folder has been dropped in the meantime). + * + */ + + class FolderSpecificTableNotFound : public RelationalException { + + public: + + /// Constructor + explicit FolderSpecificTableNotFound( const std::string& fullPath, + const std::string& methodName ) + : RelationalException( "", methodName ) + { + std::stringstream msg; + msg << "PANIC! Folder-specific table " + << "not found for folder " << fullPath << ": this indicates" + << " either data corruption (if node table row exists)" + << " or DDL changes by another process during your job lifetime"; + setMessage( msg.str() ); + } + + /// Destructor + virtual ~FolderSpecificTableNotFound() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class TableNotFound + * + * Exception thrown when a table cannot be found. + * This is generally a "PANIC" situation where the name of the table + * was retrieved from the database and should exist: this may indicate + * either data corruption or DDL changes by another process during the + * job lifetime (e.g., one folder has been dropped in the meantime). + * + */ + + class TableNotFound : public RelationalException { + + public: + + /// Constructor + explicit TableNotFound( const std::string& tableName, + const std::string& methodName ) + : RelationalException( "", methodName ) + { + std::stringstream msg; + msg << "Table " << tableName << " not found:" + << " this may indicate a PANIC situation with data corruption" + << " or DDL changes by another process during your job lifetime"; + setMessage( msg.str() ); + } + + /// Destructor + virtual ~TableNotFound() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class TableNotDropped + * + * Exception thrown when a table cannot be dropped. + * + */ + + class TableNotDropped : public RelationalException { + + public: + + /// Constructor + explicit TableNotDropped( const std::string& table, + const std::string& methodName ) + : RelationalException( "Could not drop table/sequence '" + table + "'", + methodName ) {} + + /// Destructor + virtual ~TableNotDropped() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class RowNotDeleted + * + * Exception thrown when a table row cannot be deleted. + * + */ + + class RowNotDeleted : public RelationalException { + + public: + + /// Constructor + explicit RowNotDeleted( const std::string& message, + const std::string& methodName ) + : RelationalException( message, methodName ) {} + + /// Destructor + virtual ~RowNotDeleted() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class RowNotUpdated + * + * Exception thrown when a table row cannot be updated. + * + */ + + class RowNotUpdated : public RelationalException { + + public: + + /// Constructor + explicit RowNotUpdated( const std::string& message, + const std::string& methodName ) + : RelationalException( message, methodName ) {} + + /// Destructor + virtual ~RowNotUpdated() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class RowNotInserted + * + * Exception thrown when a table row cannot be inserted. + * + */ + + class RowNotInserted : public RelationalException { + + public: + + /// Constructor + explicit RowNotInserted( const std::string& message, + const std::string& methodName ) + : RelationalException( message, methodName ) {} + + /// Destructor + virtual ~RowNotInserted() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class NoRowsFound + * + * Exception thrown when a query returns zero table rows + * and at least one was expected. + * + */ + + class NoRowsFound : public RelationalException { + + public: + + /// Constructor + explicit NoRowsFound( const std::string& message, + const std::string& methodName ) + : RelationalException( message, methodName ) {} + + /// Destructor + virtual ~NoRowsFound() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class TooManyRowsFound + * + * Exception thrown when a query returns more table rows than expected. + * + */ + + class TooManyRowsFound : public RelationalException { + + public: + + /// Constructor + explicit TooManyRowsFound( const std::string& message, + const std::string& methodName ) + : RelationalException( message, methodName ) {} + + /// Destructor + virtual ~TooManyRowsFound() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class IncompatibleReleaseNumber + * + * Exception thrown when the software library release number is not + * compatible with the database schema it is attempting to handle. + * + */ + + class IncompatibleReleaseNumber : public RelationalException + { + + public: + + /// Constructor + explicit IncompatibleReleaseNumber + ( const std::string& message, + const std::string& methodName ) + : RelationalException + ( "IncompatibleReleaseNumber exception. " + message, methodName ) {} + + /// Destructor + virtual ~IncompatibleReleaseNumber() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class InvalidColumnName + * + * Exception thrown when attempting to create or rename a column + * of a relational table using an invalid name. + * + * Names of column must have between 1 and 30 characters (including only + * letters, digits or the '_' character ) and must start with a letter. + * + */ + + class InvalidColumnName : public RelationalException + { + + public: + + /// Constructor + explicit InvalidColumnName( const std::string& name, + const std::string& methodName ) + : RelationalException + ( "Invalid column name '" + name + "'", methodName ) {} + + /// Destructor + virtual ~InvalidColumnName() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class UnsupportedFolderSchema + * + * Exception thrown when attempting to open a folder whose schema + * version is newer than that supported by the present software + * release (or has been obsoleted and is no longer supported). + */ + + class UnsupportedFolderSchema : public RelationalException + { + + public: + + /// Constructor + explicit UnsupportedFolderSchema( const std::string& fullPath, + const VersionNumber& schemaVersion, + const std::string& domain ) + : RelationalException( "", domain ) + { + std::stringstream msg; + msg << "Schema version " << schemaVersion << " of folder '" + << fullPath << "' is not supported by this software release " + << VersionInfo::release << " (using default database schema version " + << VersionInfo::schemaVersion << ")"; + setMessage( msg.str() ); + } + + /// Constructor + explicit UnsupportedFolderSchema( const std::string& message, + const std::string& domain ) + : RelationalException( message, domain ) + { + } + + /// Destructor + virtual ~UnsupportedFolderSchema() throw() {} + + }; + + //-------------------------------------------------------------------------- + + /** @class UnsupportedFolderSetSchema + * + * Exception thrown when attempting to open a folder set whose schema + * version is newer than that supported by the present software + * release (or has been obsoleted and is no longer supported). + */ + + class UnsupportedFolderSetSchema : public RelationalException + { + + public: + + /// Constructor + explicit UnsupportedFolderSetSchema( const std::string& fullPath, + const VersionNumber& schemaVersion, + const std::string& domain ) + : RelationalException( "", domain ) + { + std::stringstream msg; + msg << "Schema version " << schemaVersion << " of folder set '" + << fullPath << "' is not supported by this software release " + << VersionInfo::release << " (using default database schema version " + << VersionInfo::schemaVersion << ")"; + setMessage( msg.str() ); + } + + /// Constructor + explicit UnsupportedFolderSetSchema( const std::string& message, + const std::string& domain ) + : RelationalException( message, domain ) + { + } + + /// Destructor + virtual ~UnsupportedFolderSetSchema() throw() {} + + }; + + //-------------------------------------------------------------------------- + +} + +#endif // RELATIONALCOOL_RELATIONALEXCEPTION_H diff --git a/RelationalCool/src/RelationalFolder.cpp b/RelationalCool/src/RelationalFolder.cpp new file mode 100644 index 000000000..b75abb227 --- /dev/null +++ b/RelationalCool/src/RelationalFolder.cpp @@ -0,0 +1,1731 @@ +// $Id: RelationalFolder.cpp,v 1.231 2009-01-13 19:13:09 avalassi Exp $ + +// Include files +#include <list> +#include "CoralBase/MessageStream.h" +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/ConstRecordAdapter.h" +#include "CoolKernel/Record.h" +#include "CoralBase/Attribute.h" +//#include "CoralBase/AttributeList.h" +#include "CoralBase/AttributeSpecification.h" + +// Local include files +#include "HvsPathHandler.h" +#include "HvsTagRecord.h" +#include "IRelationalBulkOperation.h" +#include "IRelationalTransactionMgr.h" +#include "ObjectVectorIterator.h" +#include "RelationalChannelTable.h" +#include "RelationalDatabase.h" +#include "RelationalException.h" +#include "RelationalFolder.h" +#include "RelationalGlobalTagTable.h" +#include "RelationalNodeTable.h" +#include "RelationalObject.h" +#include "RelationalObjectMgr.h" +#include "RelationalObjectTable.h" +#include "RelationalObjectTableRow.h" +#include "RelationalObject2TagTable.h" +#include "RelationalPayloadQuery.h" +#include "RelationalQueryMgr.h" +#include "RelationalSequence.h" +#include "RelationalSequenceMgr.h" +#include "RelationalSchemaMgr.h" +#include "RelationalTableRow.h" +#include "RelationalTagMgr.h" +#include "RelationalTagTable.h" +#include "RelationalTag2TagTable.h" +#include "RelationalTransaction.h" +#include "TimingReportMgr.h" +//#include "UrlParser.h" +#include "timeToString.h" + +// Namespace +using namespace cool; + +// Local type definitions +typedef boost::shared_ptr<RelationalSequence> RelationalSequencePtr; + +//----------------------------------------------------------------------------- + +bool RelationalFolder::isSupportedSchemaVersion +( const VersionNumber& rhs ) +{ + VersionNumber lhs = folderSchemaVersion(); + // 1. Hardcoded requirement: folder schema must be >= 2.0.1 (bug #23755) + if ( rhs < VersionNumber( "2.0.1" ) ) return false; + // 2. In general: 2.0.x (x>=1) is supported if this software supports 2.0.y + return + ( lhs.majorVersion() == rhs.majorVersion() ) + && ( lhs.minorVersion() == rhs.minorVersion() ); + //&& ( lhs.patchVersion() <= rhs.patchVersion() ); +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::initialize( const coral::AttributeList& row ) +{ + m_prefetchAll = true; // Keep the API semantics of COOL_1_2_5 + m_useBuffer = false; + m_userTagOnly = false; + m_objectTableName = RelationalFolder::objectTableName( row ); + //m_folderSpec = FolderSpecification( versioningMode( row ), payloadSpecification( row ) ); + if ( m_folderSpec.versioningMode() == FolderVersioning::MULTI_VERSION ) + { + m_tagTableName = RelationalFolder::tagTableName( row ); + m_object2TagTableName = RelationalFolder::object2TagTableName( row ); + } + else + { + m_tagTableName = ""; + m_object2TagTableName = ""; + } + m_channelTableName = RelationalFolder::channelTableName( row ); + const IRecordSpecification& spec = + folderAttributesSpecification( m_folderSpec.versioningMode() ); + m_publicFolderAttributes = Record( spec, row ); + log() << coral::Debug << "Instantiate a RelationalFolder for '" + << fullPath() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalFolder::~RelationalFolder() +{ + log() << coral::Debug << "Delete the RelationalFolder for '" + << fullPath() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RelationalFolder::log() const +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +const IRecord& RelationalFolder::folderAttributes() const { + return m_publicFolderAttributes; +} + +//----------------------------------------------------------------------------- + +const RecordSpecification& +RelationalFolder::folderAttributesSpecification +( FolderVersioning::Mode versioningMode ) +{ + if ( versioningMode == FolderVersioning::MULTI_VERSION ) { + + static RecordSpecification s_folderAttrSpec_MV; + if ( s_folderAttrSpec_MV.size() == 0 ) { + s_folderAttrSpec_MV.extend + ( RelationalNodeTable::columnNames::nodeSchemaVersion, + RelationalNodeTable::columnTypeIds::nodeSchemaVersion ); + s_folderAttrSpec_MV.extend + ( RelationalNodeTable::columnNames::folderObjectTableName, + RelationalNodeTable::columnTypeIds::folderObjectTableName ); + s_folderAttrSpec_MV.extend + ( RelationalNodeTable::columnNames::folderTagTableName, + RelationalNodeTable::columnTypeIds::folderTagTableName ); + s_folderAttrSpec_MV.extend + ( RelationalNodeTable::columnNames::folderObject2TagTableName, + RelationalNodeTable::columnTypeIds::folderObject2TagTableName ); + s_folderAttrSpec_MV.extend + ( RelationalNodeTable::columnNames::folderChannelTableName, + RelationalNodeTable::columnTypeIds::folderChannelTableName ); + } + return s_folderAttrSpec_MV; + + } else { + + static RecordSpecification s_folderAttrSpec_SV; + if ( s_folderAttrSpec_SV.size() == 0 ) { + s_folderAttrSpec_SV.extend + ( RelationalNodeTable::columnNames::nodeSchemaVersion, + RelationalNodeTable::columnTypeIds::nodeSchemaVersion ); + s_folderAttrSpec_SV.extend + ( RelationalNodeTable::columnNames::folderObjectTableName, + RelationalNodeTable::columnTypeIds::folderObjectTableName ); + s_folderAttrSpec_SV.extend + ( RelationalNodeTable::columnNames::folderChannelTableName, + RelationalNodeTable::columnTypeIds::folderChannelTableName ); + } + return s_folderAttrSpec_SV; + + } +} + +//----------------------------------------------------------------------------- + +/* +bool RelationalFolder::declareExternalReference +( const std::string& name, + const std::vector< std::string >& attributes, + const std::string& referencedEntity, + const std::vector< std::string >& referencedAttributes ) +{ + // Check if the reference already exists + std::map< std::string, IFolder::ExternalReference >::const_iterator + ref = m_externalReferences.find( name ); + if ( ref != m_externalReferences.end() ) { + std::string errMsg = + "External reference constraint '" + name + + "' already exists for folder '" + fullPath() + "'"; + throw RelationalException( errMsg, "RelationalFolder" ); + } + + // Check that the number of referenced and referencing attributes match + if ( attributes.size() != referencedAttributes.size() ) { + std::string errMsg = + "External reference constraint '" + name + + "' could not be declared for folder '" + fullPath() + + "': mismatch in the number of referenced and referencing attributes"; + throw RelationalException( errMsg, "RelationalFolder" ); + } + + // Check that each referencing attribute is used only once + std::list<std::string> uniqueAttributes; + std::vector<std::string>::const_iterator attr; + for ( attr = attributes.begin(); attr != attributes.end(); attr++ ) { + uniqueAttributes.push_back( *attr ); + } + uniqueAttributes.unique(); + if ( uniqueAttributes.size() != attributes.size() ) { + std::string errMsg = + "External reference constraint '" + name + + "' could not be declared for folder '" + fullPath() + + "': one or more referencing attributes appear more than once"; + throw RelationalException( errMsg, "RelationalFolder" ); + } + + // Check that the referencing attributes are part of the user payload + for ( attr = attributes.begin(); attr != attributes.end(); attr++ ) { + try { + extendedRecordSpecification()[ *attr ]; + } catch (...) { + std::string errMsg = + "External reference constraint '" + name + + "' could not be declared for folder '" + fullPath() + + "': attribute '" + *attr + "' not in folder payload specification"; + throw RelationalException( errMsg, "RelationalFolder" ); + } + } + + // Check that the syntax of the referenced entity URL is supported + // Example: "local://schema=USERNAME;table=TABLENAME". + std::string url = referencedEntity; + static const std::string s_localPrefix = "local://"; + std::string foreignSchema = ""; + std::string foreignTable = ""; + bool supportedUrl = true; + if ( UrlParser::urlStartsWith( url, s_localPrefix ) ) { + //std::cout << "URL = '" << url << "'" << std::endl; + url = url.substr( s_localPrefix.size() ) + ";"; + //std::cout << "URL = '" << url << "'" << std::endl; + unsigned int semicolonPos = url.find( ";" ); + while ( semicolonPos != std::string::npos ) { + std::string optionString = url.substr( 0, semicolonPos ); + //std::cout << "option = '" << optionString << "'" << std::endl; + url = url.substr( optionString.size()+1 ); + //std::cout << "URL = '" << url << "'" << std::endl; + semicolonPos = url.find( ";" ); + UrlParser::Option option = UrlParser::parseOptionString( optionString ); + if ( option.first == "schema" ) { + if ( foreignSchema != "" ) supportedUrl = false; //duplicate key + foreignSchema = option.second; + } + if ( option.first == "table" ) { + if ( foreignTable != "" ) supportedUrl = false; //duplicate key + foreignTable = option.second; + } + } + } + if ( ! supportedUrl || foreignSchema == "" || foreignTable == "" ) { + std::string errMsg = + "External reference constraint '" + name + + "' could not be declared for folder '" + fullPath() + + "': unsupported referenced entity URL '" + + referencedEntity + "'"; + throw RelationalException( errMsg, "RelationalFolder" ); + } + // DUMMY IMPLEMENTATION FOR THE MOMENT: DO NOTHING + + // Add the external reference constraint to the list of constraints + IFolder::ExternalReference reference; + reference.name = name; + reference.attributes = attributes; + reference.referencedEntity = referencedEntity; + reference.referencedAttributes = referencedAttributes; + m_externalReferences[ name ] = reference; + return true; + +} + +//----------------------------------------------------------------------------- + +const std::vector< std::string > RelationalFolder::externalReferences() const +{ + std::vector< std::string > references; + std::map< std::string, IFolder::ExternalReference >::const_iterator ref; + for ( ref = m_externalReferences.begin(); + ref != m_externalReferences.end(); + ref++ ) { + references.push_back( ref->first ); + } + return references; +} + +//----------------------------------------------------------------------------- + +const IFolder::ExternalReference& +RelationalFolder::externalReference( const std::string& name ) const +{ + std::map< std::string, IFolder::ExternalReference >::const_iterator + ref = m_externalReferences.find( name ); + if ( ref != m_externalReferences.end() ) { + return ref->second; + } else { + std::string errMsg = + "External reference constraint '" + name + + "' not found for folder '" + fullPath() + "'"; + throw RelationalException( errMsg, "RelationalFolder" ); + } +} +*/ + +//----------------------------------------------------------------------------- + +void RelationalFolder::setupStorageBuffer( bool useBuffer ) +{ + if ( ( !useBuffer ) && m_useBuffer && ( !m_objectBuffer.empty() ) ) + flushStorageBuffer(); + m_useBuffer = useBuffer; +} + +//----------------------------------------------------------------------------- + +unsigned RelationalFolder::maxBufferSize() +{ + // AV 18.01.2004 TEMPORARY? + // Oracle - use 50k: workaround for ORA-24381 error if buffer>65535 + // MySQL -use 10k: this makes writing faster on MySQL + //unsigned s_maxBufferSize = 0; + unsigned s_maxBufferSize = 10000; + return s_maxBufferSize; +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::flushStorageBuffer() +{ + log() << "Flushing storage buffer for folder " << fullPath() << coral::MessageStream::endmsg; + if ( m_objectBuffer.empty() ) + { + log() << coral::Warning << "Nothing to flush for folder " + << fullPath() << ": buffer is empty" << coral::MessageStream::endmsg; + } + else + { + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + if ( db().transactionMgr()->isActive() ) + { + if ( db().isReadOnly() ) { + throw DatabaseOpenInReadOnlyMode( "RalDatabase" ); + } else { + if ( db().transactionMgr()->autoTransactions() ) { + throw RelationalException + ( "Cannot start a concurrent write transaction", "RalDatabase" ); + } + } + } + RelationalTransaction transaction( db().transactionMgr() ); // r/w + //db().__storeObjects( this, m_objectBuffer, m_userTagOnly ); + //m_objectBuffer.erase( m_objectBuffer.begin(), m_objectBuffer.end() ); + // AV 18.01.2004 TEMPORARY? + unsigned theMaxBufferSize = maxBufferSize(); + try + { + if ( theMaxBufferSize == 0 ) + { + log() << "Store all objects (max buffer size = 0)" + << coral::MessageStream::endmsg; + db().objectMgr().__storeObjects( this, m_objectBuffer, m_userTagOnly ); + m_objectBuffer.clear(); + } + // AV - here could also avoid copy if buffer size is already < MAX + else + { + log() << "Store at most " << theMaxBufferSize << " objects at a time" + << coral::MessageStream::endmsg; + /* + // AV Access violation on vc9 (bug #45839) + std::vector<RelationalObjectPtr>::iterator begin = + m_objectBuffer.begin(); + std::vector<RelationalObjectPtr>::iterator end = + begin + theMaxBufferSize < m_objectBuffer.end() ? + begin + theMaxBufferSize : + m_objectBuffer.end(); + while( begin < m_objectBuffer.end() ) + { + // we should avoid this copy by adding an overloaded "storeObjects": + // db().__storeObjects( m_objectBuffer, begin, end, m_userTagOnly ) + std::vector<RelationalObjectPtr> buffer; + copy( begin, end, std::back_inserter( buffer ) ); + db().objectMgr().__storeObjects( this, buffer, m_userTagOnly ); + begin = end; + end = ( end + theMaxBufferSize ) < m_objectBuffer.end() ? + end + theMaxBufferSize : + m_objectBuffer.end(); + } + */ + // AV Fix access violation on vc9 (bug #45839) + unsigned int size = m_objectBuffer.size(); + unsigned int begin = 0; + unsigned int end = ( theMaxBufferSize<size ? + theMaxBufferSize-1 : + size-1 ); + while( begin < size ) + { + // we should avoid this copy by adding an overloaded "storeObjects": + // db().__storeObjects( m_objectBuffer, begin, end, m_userTagOnly ) + std::vector<RelationalObjectPtr> buffer; + for ( unsigned int index = begin; index <= end; index++ ) + buffer.push_back( m_objectBuffer[index] ); + db().objectMgr().__storeObjects( this, buffer, m_userTagOnly ); + begin = end+1; + end = ( end+theMaxBufferSize < size-1 ? + end+theMaxBufferSize : + size-1 ); + } + m_objectBuffer.clear(); + } + } + catch (...) + { + // No need to print a warning if only the invalid IOV is discarded + if ( m_objectBuffer.size() > 1 ) + log() << coral::Warning + << "Exception caught while bulk-inserting IOVs" + << ": NONE of the IOVs in the bulk insertion will be stored" + << coral::MessageStream::endmsg; + m_objectBuffer.clear(); + throw; + } + transaction.commit(); + } + +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::storeObject( const ValidityKey& since, + const ValidityKey& until, + const IRecord& payload, + const ChannelId& channelId, + const std::string& userTagName, + bool userTagOnly ) +{ + log() << "Store into folder " << fullPath() + << " the following IOV: since=" << since << " until=" << until + << coral::MessageStream::endmsg; + + // Check that userTagOnly is the same for all objects in a bulk insertion + if ( m_objectBuffer.size() > 0 ) + { + if ( userTagOnly != m_userTagOnly ) + { + std::stringstream msg; + msg << "Conflicting values of userTagOnly in the same bulk insertion"; + throw RelationalException( msg.str(), "RelationalFolder::storeObject" ); + } + } + else + { + m_userTagOnly = userTagOnly; + } + + // Check that userTagName != "" if userTagOnly is true + if ( userTagOnly && userTagName == "" ) + { + std::stringstream msg; + msg << "A user tag must be specified if userTagOnly is true"; + throw RelationalException( msg.str(), "RelationalFolder::storeObject" ); + } + + // TODO - cross check payload against folder payload spec (bug #24464)? + + // Instantiate a RelationalObject corresponding to the input arguments + // Add it to the storage buffer + RelationalObjectPtr object + ( new RelationalObject( since, until, payload, channelId, userTagName ) ); + m_objectBuffer.push_back( object ); + + // Store the object immediately if bulk insertion is not active + if ( ! m_useBuffer ) flushStorageBuffer(); + +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::storeObject( const ValidityKey& since, + const ValidityKey& until, + const coral::AttributeList& payload, + const ChannelId& channelId, + const std::string& userTagName, + bool userTagOnly ) +{ + //log() << "Store object using the AttributeList API" + // << coral::MessageStream::endmsg; + ConstRecordAdapter record( payloadSpecification(), payload ); + //log() << "Store ConstRecordAdapter using the new API " + // << coral::MessageStream::endmsg; + storeObject( since, until, record, channelId, userTagName, userTagOnly ); +} + +//----------------------------------------------------------------------------- + +int +RelationalFolder::truncateObjectValidity( const ValidityKey& until, + const ChannelSelection& channels ) +{ + return db().objectMgr().truncateObjectValidity( this, until, channels ); +} + +//----------------------------------------------------------------------------- + +IObjectPtr RelationalFolder::findObject( const ValidityKey& pointInTime, + const ChannelId& channelId, + const std::string& tagName ) const +{ + IObjectPtr obj + ( db().objectMgr().findObject( this, pointInTime, channelId, tagName ) ); + return obj; +} + +//----------------------------------------------------------------------------- + +IObjectIteratorPtr +RelationalFolder::browseObjects( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + bool prefetchAll, + const IRecordSelection* payloadQuery ) const +{ + log() << "Browse objects in folder " << fullPath() + << " between since=" << since << " and until=" << until + << coral::MessageStream::endmsg; + + if ( TimingReportMgr::isActive() ) + TimingReportMgr::startTimer( "cool::RelationalFolder::browseObjects()" ); + IObjectIteratorPtr browserIt; + + if ( payloadQuery != 0 && !payloadQuery->canSelect(payloadSpecification()) ) + throw RelationalException + ( "Invalid payload query for this folder (wrong payload specification)", + "RelationalFolder::browseObject" ); + browserIt = db().objectMgr().browseObjects + ( this, since, until, channels, tagName, payloadQuery ); + + if ( prefetchAll ) + { + if ( TimingReportMgr::isActive() ) + TimingReportMgr::startTimer + ( "cool::RelationalFolder::browseObjects(V)" ); + IObjectIteratorPtr vectorIt + ( new ObjectVectorIterator( browserIt->fetchAllAsVector() ) ); + browserIt = vectorIt; + if ( TimingReportMgr::isActive() ) + TimingReportMgr::stopTimer + ( "cool::RelationalFolder::browseObjects(V)" ); + } + + if ( TimingReportMgr::isActive() ) + TimingReportMgr::stopTimer( "cool::RelationalFolder::browseObjects()" ); + if (payloadQuery !=0 ) + log() << "Browse objects will return an iterator with a payloadQuery" + << coral::MessageStream::endmsg; + else + if ( prefetchAll) + log() << "Browse objects will return a vector iterator with " + << browserIt->size() << " objects" << coral::MessageStream::endmsg; + else + log() << "Browse objects will return a vector iterator of unknown size" + << coral::MessageStream::endmsg; + + return browserIt; +} + +//----------------------------------------------------------------------------- + +IObjectIteratorPtr +RelationalFolder::browseObjects( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + const IRecordSelection* payloadQuery ) const +{ + /* + // AV Move this code fragment where it belongs (RalObjectMgr?...) + if ( payloadQuery != 0 ) + { + bool trusted = false; + if ( typeid( *payloadQuery ) == typeid ( FieldRangeSelection ) ) + trusted = true; + // If trusted -> append describe() to the SQL WHERE clause + // If not trusted -> scan locally using the select() method + } + */ + return browseObjects + ( since, until, channels, tagName, m_prefetchAll, payloadQuery ); +} + +//----------------------------------------------------------------------------- + +IObjectIteratorPtr +RelationalFolder::findObjects( const ValidityKey& pointInTime, + const ChannelSelection& channels, + const std::string& tagName ) const +{ + ValidityKey since = pointInTime; + ValidityKey until = pointInTime; + return browseObjects( since, until, channels, tagName, m_prefetchAll, 0 ); +} + +//----------------------------------------------------------------------------- + +IObjectVectorPtr +RelationalFolder::fetchObjectsInRange( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName ) const +{ + //return db().fetchObjects( this, since, until, channels, tagName ); + return browseObjects + ( since, until, channels, tagName, m_prefetchAll, 0 )->fetchAllAsVector(); +} + +//----------------------------------------------------------------------------- + +IObjectVectorPtr +RelationalFolder::fetchObjectsAtTime( const ValidityKey& pointInTime, + const ChannelSelection& channels, + const std::string& tagName ) const +{ + ValidityKey since = pointInTime; + ValidityKey until = pointInTime; + return fetchObjectsInRange( since, until, channels, tagName ); +} + +//----------------------------------------------------------------------------- + +unsigned int +RelationalFolder::countObjects( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + const IRecordSelection* payloadQuery ) const +{ + if ( payloadQuery != 0 && !payloadQuery->canSelect(payloadSpecification()) ) + throw RelationalException + ( "Invalid payload query for this folder (wrong payload specification)", + "RelationalFolder::browseObject" ); + bool countOnly = true; + unsigned int count = db().objectMgr().browseObjects + ( this, since, until, channels, tagName, payloadQuery, countOnly )->size(); + return count; +} + +//----------------------------------------------------------------------------- + +const std::vector<ChannelId> +RelationalFolder::listChannels() const +{ + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + // Use the channels table for both SV and MV folders. + // Fix performance bug #24448 for SV folders in COOL_2_2_0. + // Fix functional and performance bug #30443 for MV folders in COOL_2_2_2 + // (remove workaround for bug #23755 - MV channels table not filled). + RelationalChannelTable channelTable( db(), *this ); + std::vector<ChannelId> channels = channelTable.listChannels(); + transaction.commit(); + return channels; +} + +//----------------------------------------------------------------------------- + +const std::map<ChannelId,std::string> +RelationalFolder::listChannelsWithNames() const +{ + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + // Use the channels table for both SV and MV folders. + RelationalChannelTable channelTable( db(), *this ); + const std::map<ChannelId,std::string> channelsWithNames = + channelTable.listChannelsWithNames(); + transaction.commit(); + return channelsWithNames; +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::createChannel( const ChannelId& channelId, + const std::string& channelName, + const std::string& description ) +{ + db().objectMgr().createChannel( this, channelId, channelName, description ); +} + +//----------------------------------------------------------------------------- + +bool RelationalFolder::dropChannel( const ChannelId& channelId ) +{ + return db().objectMgr().dropChannel( this, channelId ); +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::setChannelName( const ChannelId& channelId, + const std::string& channelName ) +{ + log() << "Modify channel #" << channelId + << " in folder '" << fullPath() + << "': set name equal to '" << channelName << "'" + << coral::MessageStream::endmsg; + + // Start a read-write transaction + bool readOnly = false; + RelationalTransaction transaction( db().transactionMgr(), readOnly ); + + // Throw if a channel with the given name already exists + // (unless it is the name of this channel - fix for bug #23754) + try { + RelationalChannelTable table( db(), *this ); + RelationalTableRow row = table.fetchRowForChannelName( channelName ); + if ( channelId != + row[RelationalChannelTable::columnNames::channelId()] + .data<ChannelId>() ) + throw ChannelExists( fullPath(), channelName, "RelationalFolder" ); + } catch ( NoRowsFound& ) {} + + // Define the SET and WHERE clauses for the update using bind variables + coral::AttributeList updateData; + updateData.extend( "channelName", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::channelName) ); + updateData.extend( "channel", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::channelId) ); + updateData["channelName"].setValue( channelName ); + if ( channelName != "" ) + updateData["channelName"].setValue( channelName ); + else + updateData["channelName"].setNull(); + updateData["channel"].setValue( channelId ); + std::string setClause = RelationalChannelTable::columnNames::channelName(); + setClause += "= :channelName"; + std::string whereClause = RelationalChannelTable::columnNames::channelId(); + whereClause += "= :channel"; + + // Execute the update + UInt32 updatedRows = db().queryMgr().updateTableRows + ( channelTableName(), setClause, whereClause, updateData ); + + // Remove workaround for bug #23755 (MV channels table not filled) and + // old fix for bug #24445 (MV setChannelName fails without createChannel): + // 'create' the channel row in the channel table if the channel exists + // (i.e. contains some IOVs) but it has no associated channel table row + /* + // Was the channel name updated? + if ( updatedRows != 1 ) { + if ( m_folderSpec.versioningMode() == FolderVersioning::MULTI_VERSION ) { + if ( db().relationalObjectTable( *this )->existsChannel( channelId ) ) { + unsigned int lastObjectId = 0; // this is not maintained for MV folders + bool hasNewData = false; + std::string description = ""; + db().objectMgr().insertChannelTableRow( this->channelTableName(), + channelId, + lastObjectId, + hasNewData, + channelName, + description ); + updatedRows = 1; // hack - workaround for bug #23755 + } + } + } + */ + + // Commit the transaction + transaction.commit(); + + // Was the channel name updated? + if ( updatedRows != 1 ) { + throw ChannelNotFound( channelId, "RalDatabase" ); + } + +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::setChannelDescription +( const ChannelId& channelId, + const std::string& description ) +{ + log() << "Update in table " << channelTableName() + << " for channel " << channelId << coral::MessageStream::endmsg; + + // Define the SET and WHERE clauses for the update using bind variables + coral::AttributeList updateData; + updateData.extend( "description", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::description) ); + updateData.extend( "channel", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::channelId) ); + updateData["description"].setValue( description ); + updateData["channel"].setValue( channelId ); + std::string setClause = RelationalChannelTable::columnNames::description(); + setClause += "= :description"; + std::string whereClause = RelationalChannelTable::columnNames::channelId(); + whereClause += "= :channel"; + + bool readOnly = false; + RelationalTransaction transaction( db().transactionMgr(), readOnly ); + + // Execute the update + UInt32 updatedRows = db().queryMgr().updateTableRows + ( channelTableName(), setClause, whereClause, updateData ); + + // Remove workaround for bug #23755 (MV channels table not filled) and + // old fix for bug #24461 (MV setChannelDesc fails without createChannel): + // 'create' the channel row in the channel table if the channel exists + // (i.e. contains some IOVs) but it has no associated channel table row + /* + // Was the channel name updated? + if ( updatedRows != 1 ) { + if ( m_folderSpec.versioningMode() == FolderVersioning::MULTI_VERSION ) { + if ( db().relationalObjectTable( *this )->existsChannel( channelId ) ) { + unsigned int lastObjectId = 0; // this is not maintained for MV folders + bool hasNewData = false; + std::string channelName = ""; + db().objectMgr().insertChannelTableRow( this->channelTableName(), + channelId, + lastObjectId, + hasNewData, + channelName, + description ); + updatedRows = 1; // hack - workaround for bug #23755 + } + } + } + */ + + // Commit the transaction + transaction.commit(); + + // Was the channel name updated? + if ( updatedRows != 1 ) { + throw ChannelNotFound( channelId, "RalDatabase" ); + } + +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalFolder::channelName( const ChannelId& channelId ) const +{ + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + bool exists = false; + std::string channelName = ""; + try { + RelationalChannelTable table( db(), *this ); + RelationalTableRow row = table.fetchRowForId( channelId ); + channelName = row[RelationalChannelTable::columnNames::channelName()]. + data<std::string>(); + exists = true; + } catch ( NoRowsFound& ) { + // Remove workaround for bug #23755 (MV channels table not filled) and + // old fix for bug #24463 (MV channelName fails without createChannel) + //exists = db().relationalObjectTable( *this )->existsChannel( channelId ); + exists = false; + } + transaction.commit(); + if ( exists ) return channelName; + else throw ChannelNotFound( channelId, "RelationalFolder" ); +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalFolder::channelDescription( const ChannelId& channelId ) const +{ + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + bool exists = false; + std::string description = ""; + try { + RelationalChannelTable table( db(), *this ); + RelationalTableRow row = table.fetchRowForId( channelId ); + description = row[RelationalChannelTable::columnNames::description()]. + data<std::string>(); + exists = true; + } catch ( NoRowsFound& ) { + // Remove workaround for bug #23755 (MV channels table not filled) and old + // fix for bug #24463 (MV channelDescription fails without createChannel) + //exists = db().relationalObjectTable( *this )->existsChannel( channelId ); + exists = false; + } + transaction.commit(); + if ( exists ) return description; + else throw ChannelNotFound( channelId, "RelationalFolder" ); +} + +//----------------------------------------------------------------------------- + +ChannelId +RelationalFolder::channelId( const std::string& channelName ) const +{ + try { + bool readOnly = true; + RelationalTransaction transaction( db().transactionMgr(), readOnly ); + RelationalChannelTable table( db(), *this ); + RelationalTableRow row = table.fetchRowForChannelName( channelName ); + transaction.commit(); + return row[RelationalChannelTable::columnNames::channelId()]. + data<ChannelId>(); + } catch ( NoRowsFound& ) { + throw ChannelNotFound( channelName, "RelationalFolder" ); + } +} + +//----------------------------------------------------------------------------- + +bool +RelationalFolder::existsChannel( const std::string& channelName ) const +{ + try { + bool readOnly = true; + RelationalTransaction transaction( db().transactionMgr(), readOnly ); + RelationalChannelTable table( db(), *this ); + table.fetchRowForChannelName( channelName ); + transaction.commit(); + return true; + } catch ( NoRowsFound& ) { + return false; + } +} + +//----------------------------------------------------------------------------- + +bool +RelationalFolder::existsChannel( const ChannelId& channelId ) const +{ + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + bool exists; + // Use the channels table for both SV and MV folders. + // Fix functional and performance bug #30431 for MV folders in COOL_2_2_2 + // (remove workaround for bug #23755 - MV channels table not filled - and + // old fix for bug #24449 - MV existsChannel fails without createChannel). + try { + RelationalChannelTable table( db(), *this ); + table.fetchRowForId( channelId ); + exists = true; + } catch ( NoRowsFound& ) { + exists= false; + } + transaction.commit(); + return exists; +} + +//----------------------------------------------------------------------------- + +const std::string& RelationalFolder::objectTableName() const +{ + return m_objectTableName; +} + +//----------------------------------------------------------------------------- + +const std::string& RelationalFolder::tagTableName() const +{ + if ( m_folderSpec.versioningMode() == FolderVersioning::MULTI_VERSION ) + return m_tagTableName; + else + throw FolderIsSingleVersion + ( fullPath(), " Tag table does not exist", "RalDatabase" ); +} + +//----------------------------------------------------------------------------- + +const std::string& RelationalFolder::object2TagTableName() const +{ + if ( m_folderSpec.versioningMode() == FolderVersioning::MULTI_VERSION ) + return m_object2TagTableName; + else + throw FolderIsSingleVersion + ( fullPath(), " Object2Tag table does not exist", "RalDatabase" ); +} + +//----------------------------------------------------------------------------- + +const RecordSpecification +RelationalFolder::payloadSpecification +( const coral::AttributeList& folderRow ) +{ + std::string value = + folderRow[RelationalNodeTable::columnNames::folderPayloadSpecDesc] + .data<std::string>(); + return RelationalDatabase::decodeRecordSpecification( value ); +} + +//----------------------------------------------------------------------------- + +FolderVersioning::Mode +RelationalFolder::versioningMode( const coral::AttributeList& folderRow ) +{ + int value = + folderRow[RelationalNodeTable::columnNames::folderVersioningMode] + .data<int>(); + return FolderVersioning::Mode( value ); +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalFolder::objectTableName( const coral::AttributeList& folderRow ) +{ + std::string value = + folderRow[RelationalNodeTable::columnNames::folderObjectTableName] + .data<std::string>(); + return value; +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalFolder::tagTableName( const coral::AttributeList& folderRow ) +{ + std::string value = + folderRow[RelationalNodeTable::columnNames::folderTagTableName] + .data<std::string>(); + return value; +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalFolder::object2TagTableName( const coral::AttributeList& folderRow ) +{ + std::string value = + folderRow[RelationalNodeTable::columnNames::folderObject2TagTableName] + .data<std::string>(); + return value; +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalFolder::channelTableName( const coral::AttributeList& folderRow ) +{ + std::string value = + folderRow[RelationalNodeTable::columnNames::folderChannelTableName] + .data<std::string>(); + return value; +} + +//----------------------------------------------------------------------------- + +const std::string& RelationalFolder::channelTableName() const { + return m_channelTableName; +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::tagCurrentHead( const std::string& tagName, + const std::string& description ) const +{ + log() << "Tag current HEAD of folder '" << this->fullPath() + << "' with tag '" << tagName << "'" << coral::MessageStream::endmsg; + + if ( m_folderSpec.versioningMode() != FolderVersioning::MULTI_VERSION ) + throw FolderIsSingleVersion( fullPath(), "RelationalFolder" ); + + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalFolder" ); + + // HEAD tag for SV folders and MV folders + if ( IHvsNode::isHeadTag( tagName ) ) + throw ReservedHeadTag( tagName, "RelationalFolder" ); + + // MV folder - identify which objects are to be tagged and tag them + else { + RelationalTransaction transaction( db().transactionMgr() ); // r/w + std::vector<RelationalObjectTableRow> objs = + db().relationalObjectTable( *this )->fetchRowsForTaggingCurrentHead(); + tagObjectList( tagName, description, objs ); + transaction.commit(); + log() << "Tagged " << objs.size() << " objects with tag '" << tagName + << "'" << coral::MessageStream::endmsg; + } + +} + +//----------------------------------------------------------------------------- + +void +RelationalFolder::cloneTagAsUserTag( const std::string& tagName, + const std::string& tagClone, + const std::string& description, + bool forceOverwriteTag ) +{ + log() << "Clone current HEAD of folder '" << this->fullPath() + << "' with tag '" << tagName << "'" << coral::MessageStream::endmsg; + + if ( m_folderSpec.versioningMode() != FolderVersioning::MULTI_VERSION ) + throw FolderIsSingleVersion( fullPath(), "RelationalFolder" ); + + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalFolder" ); + + // HEAD tag for SV folders and MV folders + if ( IHvsNode::isHeadTag( tagClone ) ) + throw ReservedHeadTag( tagClone, "RelationalFolder" ); + + // tagClone should not exist as a tag unless forceOverwriteTag is true + if ( !forceOverwriteTag && db().existsTag(tagClone) ) + throw TagExists( tagName, "RelationalFolder" ); + + // MV folder - identify which objects are to be cloned and clone them + IObjectIteratorPtr objIter = browseObjects( ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all(), + tagName, + true, + 0 ); + bool m_useBuffer_sav = m_useBuffer; + setupStorageBuffer( true ); + while ( objIter->goToNext() ) + { + const IObject& object = objIter->currentRef(); + storeObject( object.since(), + object.until(), + object.payload(), + object.channelId(), + tagClone, + true ); + } + flushStorageBuffer(); + // restore original m_useBuffer setting + setupStorageBuffer( m_useBuffer_sav ); + + if ( description != "" ) setTagDescription( tagClone, description ); + + log() << "Reinserted " << objIter->size() << " objects with tag '" << tagName + << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::tagHeadAsOfDate( const ITime& asOfDate, + const std::string& tagName, + const std::string& description ) const +{ + log() << "Tag HEAD as of date '" << timeToString(asOfDate) + << "' of folder '" << this->fullPath() + << "' with tag '" << tagName << "'" << coral::MessageStream::endmsg; + + if ( m_folderSpec.versioningMode() != FolderVersioning::MULTI_VERSION ) + throw FolderIsSingleVersion( fullPath(), "RelationalFolder" ); + + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalFolder" ); + + // HEAD tag for SV folders and MV folders + if ( IHvsNode::isHeadTag( tagName ) ) + throw ReservedHeadTag( tagName, "RelationalFolder" ); + + // MV folder - identify which objects are to be tagged and tag them + else { + RelationalTransaction transaction( db().transactionMgr() ); // r/w + std::vector<RelationalObjectTableRow> objs = + db().relationalObjectTable( *this ) + ->fetchRowsForTaggingHeadAsOfDate( asOfDate ); + tagObjectList( tagName, description, objs ); + log() << "Tagged " << objs.size() << " objects with tag '" << tagName + << "'" << coral::MessageStream::endmsg; + transaction.commit(); + } + +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::tagHeadAsOfObjectId( unsigned int asOfObjectId, + const std::string& tagName, + const std::string& description ) +{ + RelationalTransaction transaction( db().transactionMgr() ); // r/w + + // Identify which objects are to be tagged + std::vector<RelationalObjectTableRow> objs = + db().relationalObjectTable( *this ) + ->fetchRowsForTaggingHeadAsOfObjectId( asOfObjectId ); + + // Tag the objecs + tagObjectList( tagName, description, objs ); + + transaction.commit(); +} + +//----------------------------------------------------------------------------- + +const Time +RelationalFolder::insertionTimeOfLastObjectInTag +( const std::string& tagName ) const +{ + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + + // SV folders don't have tags, can't determine a tagTime + if ( this->versioningMode() == FolderVersioning::SINGLE_VERSION ) + throw RelationalException( "tagTime not applicable in " + "SingleVersion mode", "RelationalFolder" ); + + // Retrieve the tag insertion time from the folder's tag table + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + + RelationalTableRow + row( db().tagMgr().fetchGlobalTagTableRow( this->id(), tagName ) ); + + unsigned int tagId = + row[RelationalTagTable::columnNames::tagId].data<unsigned int>(); + + RelationalObjectTableRow objRow + ( db().relationalObjectTable( *this )->fetchLastRowForTagId( tagId ) ); + + transaction.commit(); + + return objRow.insertionTime(); +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::tagObjectList +( const std::string& tagName, + const std::string& description, + const std::vector<RelationalObjectTableRow>& objects ) const +{ + // Throw TagNotCreated if object list is empty + if ( objects.size() == 0 ) + throw RelationalException + ( "Tag '" + tagName + "' not created: no IOVs in the tag", + "RelationalFolder" ); + + // Transaction and cross-checks handled in outer scope + UInt32 tagId; + std::string insertionTime; + + // Tag already exists - check if created by HVS or by IOV tags + try { + HvsTagRecord tag = db().tagMgr().__findTagRecord( this->id(), tagName ); + tagId = tag.id(); + // Tag was created by IOV or user tags - cannot reuse it + if ( RelationalFolder::existsUserTagInObjectTable + ( db().queryMgr(), tagId, this->objectTableName() ) || + RelationalFolder::existsTagInObject2TagTable + ( db().queryMgr(), tagId, this->object2TagTableName() ) ) + throw TagExists( tagName, "RalDatabase" ); + // Else tag must have been created by HVS (should we check for PANIC?) + // TODO! change the description of the tag according to what was provided + + // Throw TagIsLocked if the tag is locked + // TODO: differentiate between LOCKED and PARTIALLYLOCKED? + // This method is only used for standard 'HEAD' tags, not user tags: + // if 'partial locks' are full locks for HEAD tags, then nothing to do. + if ( tag.lockStatus() != HvsTagLock::UNLOCKED ) + throw TagIsLocked + ( "Cannot tag objects with tag '" + tagName + + "': tag is locked", "RelationalFolder" ); + + // TEMPORARY! Get the new insertion time from tag2tagseq used as CLOCK! + const std::string seqName = + RelationalTag2TagTable::sequenceName( db().tag2TagTableName() ); + RelationalSequencePtr sequence + ( db().queryMgr().sequenceMgr().getSequence( seqName ) ); + sequence->nextVal(); // TEMPORARY! value not used: need non-sequence clock! + insertionTime = sequence->currDate(); + } + + // Tag does not exist - get a new ID and insert the tag in the two tag tables + catch ( TagNotFound& ) { + //tag = tagMgr().createTag( folder->id(), tagName, description ); + HvsTagRecord tag = db().tagMgr().createTagAndLocalTag + ( this->id(), tagName, description, this->tagTableName() ); + tagId = tag.id(); + insertionTime = timeToString( tag.insertionTime() ); + } + + // Insert the object ids into the object2Tag table + insertObject2TagTableRows + ( this->object2TagTableName(), tagId, insertionTime, objects ); +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::deleteTag( const std::string& tagName ) +{ + + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + // HEAD tag for SV folders and MV folders + if ( IHvsNode::isHeadTag( tagName ) ) + throw ReservedHeadTag( tagName, "RalDatabase" ); + + // SV folder + if ( this->versioningMode() != FolderVersioning::MULTI_VERSION ) { + throw FolderIsSingleVersion( this->fullPath(), "RelationalFolder" ); + } + + // MV folder - get the tagId for tagName from the global tag table + else { + RelationalTransaction transaction( db().transactionMgr() ); // r/w + RelationalTableRow tagTableRow + ( db().tagMgr().fetchGlobalTagTableRow( this->id(), tagName ) ); + // Throw TagIsLocked if the tag is locked + // (either LOCKED or PARTIALLYLOCKED - both are equivalent here) + HvsTagLock::Status lockStatus = + HvsTagLock::Status + ( tagTableRow[RelationalGlobalTagTable::columnNames::tagLockStatus] + .data<UInt16>() ); + if ( lockStatus != HvsTagLock::UNLOCKED ) + throw TagIsLocked + ( "Cannot delete tag '" + tagName + "': tag is locked", + "RelationalFolder" ); + unsigned int tagId = + tagTableRow[RelationalGlobalTagTable::columnNames::tagId] + .data<unsigned int>(); + deleteObject2TagTableRows( this->object2TagTableName(), tagId ); + deleteObjectTableRowsForUserTag( this->objectTableName(), tagId ); + if ( !db().tagMgr().existsTagInTag2TagTable( this->id(), tagId ) ) { + db().tagMgr().deleteTagTableRow( this->tagTableName(), tagId ); + db().tagMgr().deleteGlobalTagTableRow( this->id(), tagId ); + } + transaction.commit(); + } + +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::insertObject2TagTableRows +( const std::string& object2TagTableName, + unsigned int tagId, + const std::string& insertionTime, + const std::vector<RelationalObjectTableRow>& rows ) const +{ + // Transaction handled in the outer scope + + // Check that there are >0 rows to insert + unsigned int nRows = rows.size(); + if ( nRows == 0 ) { + log() << "No rows to store into table " + << object2TagTableName << coral::MessageStream::endmsg; + return; + } + log() << "Bulk inserting " << nRows << " rows into table " + << object2TagTableName << coral::MessageStream::endmsg; + + // Get a handle to the table + //coral::ITable& table = + // session().nominalSchema().tableHandle( object2TagTableName ); + + // Setup the relational table bulk inserter + const IRecordSpecification& dataSpec = + RelationalObject2TagTable::tableSpecification(); + coral::AttributeList data = Record( dataSpec ).attributeList(); + //std::auto_ptr<coral::IBulkOperation> + // bulkInserter( table.dataEditor().bulkInsert( data, nRows ) ); + boost::shared_ptr<IRelationalBulkOperation> + bulkInserter( db().queryMgr().bulkInsertTableRows + ( object2TagTableName, data, nRows ) ); + + // Iterate through the objects and register them for insertion + for ( std::vector<RelationalObjectTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + + // Set all fields in the spec + data[RelationalObject2TagTable::columnNames::tagId].setValue + ( tagId ); + data[RelationalObject2TagTable::columnNames::objectId].setValue + ( row->objectId() ); + data[RelationalObject2TagTable::columnNames::channelId].setValue + ( row->channelId() ); + data[RelationalObject2TagTable::columnNames::iovSince].setValue + ( row->since() ); + data[RelationalObject2TagTable::columnNames::iovUntil].setValue + ( row->until() ); + // TEMPORARY! sysInsTime as string rather than DATE + data[RelationalObject2TagTable::columnNames::sysInsTime].setValue + ( insertionTime ); + + // Verbose printout: print out the full row being inserted into the db + // TEMPORARY? Speed up tagging by disabling the streaming to MsgStream + /* + std::ostringstream dataStream; + data.print( dataStream ); + log() << "Insert into the object2tag table the following AttributeList: " + << dataStream.str() << coral::MessageStream::endmsg; + */ + + // TEMPORARY? Will RAL do this as well? + // Check that all column values are within their allowed range + dataSpec.validate( data ); + + // Insert the new object in the object2tag table + bulkInserter->processNextIteration(); + + } + + // Flush the bulk inserter + bulkInserter->flush(); + +} + +//----------------------------------------------------------------------------- + +unsigned int RelationalFolder::deleteObject2TagTableRows +( const std::string& object2TagTableName, + unsigned int tagId ) const +{ + // Transaction handled in the outer scope + coral::AttributeList whereData; + whereData.extend + ( "tagId", typeIdToCoralType(RelationalTagTable::columnTypeIds::tagId) ); + whereData["tagId"].setValue( tagId ); + std::string whereClause = RelationalTagTable::columnNames::tagId; + whereClause += "= :tagId"; + return db().queryMgr().deleteTableRows + ( object2TagTableName, whereClause, whereData ); +} + +//----------------------------------------------------------------------------- + +unsigned int RelationalFolder::deleteObjectTableRowsForUserTag +( const std::string& objectTableName, + unsigned int tagId ) const +{ + // Transaction handled in the outer scope + coral::AttributeList whereData; + whereData.extend + ( "userTagId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::userTagId) ); + whereData["userTagId"].setValue( tagId ); + std::string whereClause = RelationalObjectTable::columnNames::userTagId(); + whereClause += "= :userTagId"; + return db().queryMgr().deleteTableRows + ( objectTableName, whereClause, whereData ); +} + +//----------------------------------------------------------------------------- + +bool +RelationalFolder::existsUserTag( const std::string& userTagName ) const +{ + // HEAD tag + if ( IHvsNode::isHeadTag( userTagName ) ) + { + return false; + } + + // Not a HEAD tag + else + { + bool status; + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + status = __existsUserTag( userTagName ); + transaction.commit(); + return status; + } +} + +//----------------------------------------------------------------------------- + +bool +RelationalFolder::__existsUserTag( const std::string& userTagName ) const +{ + /* + User tags are a special kind of tag. They are recorded mainly in the IOV + table (although their name and description is also stored in the folder + and global tag tables). + + The difference between a normal tag and a user tag is that the user tagId + is referenced in the colum 'tag_id' of the iov table. Therefore in order + to find out if a user tag has been assigned, a COUNT(*) on the iov table + is made with a contraint tagId = userTagId. + + The userTagId is obtained from the folder's tag table tag_id. If no row + exists for tagName then no user tag by that name has been assigned. + + Even though this requires two queries to perform this check I don't think + we want to add an extra column 'isUserTag' to the tag table just to + implement the (temporary, at least for this specification) user tag. + */ + + // HEAD tag + if ( IHvsNode::isHeadTag( userTagName ) ) + { + return false; + } + + // Not a HEAD tag + else + { + try { + unsigned int userTagId = + db().tagMgr().fetchGlobalTagTableRow( id(), userTagName ) + [RelationalTagTable::columnNames::tagId].data<unsigned int>(); + bool status = existsUserTagInObjectTable + ( db().queryMgr(), userTagId, objectTableName() ); + return status; + } + catch ( TagNotFound& ) { + return false; + } + } +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::renamePayload( const std::string& oldName, + const std::string& newName ) +{ + // Preliminary checks + if ( ! payloadSpecification().exists( oldName ) ) + throw RelationalException + ( "Cannot rename payload field " + oldName + ": it does not exist", + "RelationalFolder" ); + if ( payloadSpecification().exists( newName ) ) + throw RelationalException + ( "Cannot rename payload field to " + newName + ": it already exists", + "RelationalFolder" ); + if ( ! RelationalDatabase::isValidPayloadFieldName( newName ) ) + throw RelationalException + ( "Cannot rename payload field to " + newName + ": invalid name", + "RelationalFolder" ); + // Cross-check that we're not in manual transaction more + if ( ! db().transactionMgr()->autoTransactions() ) { + throw RelationalException("Cannot rename payload fields in manual " + "transaction mode", "RalDatabase"); + } + + RelationalTransaction transaction( db().transactionMgr(), false ); // r/w + + __renamePayload( oldName, newName ); + + transaction.commit(); +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::__renamePayload( const std::string& oldName, + const std::string& newName ) +{ + // Prepare the new specification + RecordSpecification newRecordSpecification; + for ( unsigned int i = 0; i < payloadSpecification().size(); i++ ) { + const IFieldSpecification& field = payloadSpecification()[i]; + if ( field.name() == oldName ) { + newRecordSpecification.extend( newName, field.storageType() ); + } + else { + newRecordSpecification.extend( field.name(), field.storageType() ); + } + } + + // Rename column + db().schemaMgr().renameColumnInTable(m_objectTableName,oldName,newName); + + // Prepare to update the folder description + RecordSpecification dataSpec; + dataSpec.extend("newSpec", + RelationalNodeTable::columnTypeIds::folderPayloadSpecDesc); + dataSpec.extend("nodeId", + RelationalNodeTable::columnTypeIds::nodeId); + + Record data( dataSpec ); + data["newSpec"] + .setValue<RelationalNodeTable::columnTypes::folderPayloadSpecDesc> + ( db().encodeRecordSpecification( newRecordSpecification ) ); + data["nodeId"] + .setValue<RelationalNodeTable::columnTypes::nodeId>( id() ); + + std::string setClause = + RelationalNodeTable::columnNames::folderPayloadSpecDesc; + setClause += " = :newSpec, "; + setClause += RelationalNodeTable::columnNames::lastModDate; + setClause += " = " + db().queryMgr().serverTimeClause(); + + std::string whereClause = RelationalNodeTable::columnNames::nodeId; + whereClause += "= :nodeId"; + + db().queryMgr().updateTableRows( db().nodeTableName(), + setClause, + whereClause, + data.attributeList() ); + + // Set the new specification + m_folderSpec.payloadSpecification() = newRecordSpecification; +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::extendPayloadSpecification( const IRecord& record ) +{ + if ( record.specification().size() == 0 ) return; + + // Cross-check that we're not in manual transaction more + if ( ! db().transactionMgr()->autoTransactions() ) { + throw RelationalException("Cannot extend payload specification in manual " + "transaction mode", "RalDatabase"); + } + + // Start a transaction + RelationalTransaction transaction( db().transactionMgr(), false ); // r/w + + __extendPayloadSpecification( record ); + + // Commit the transaction + transaction.commit(); + +} + +//----------------------------------------------------------------------------- + +void RelationalFolder::__extendPayloadSpecification( const IRecord& record ) +{ + // Loop over all fields in the record + const IRecordSpecification& spec = record.specification(); + for ( UInt32 i = 0; i < spec.size(); i++ ) + { + // Preliminary checks + const std::string& name = spec[i].name(); + if ( payloadSpecification().exists( name ) ) + throw RelationalException + ( "Cannot add payload field " + name + ": it already exists", + "RelationalFolder" ); + if ( ! RelationalDatabase::isValidPayloadFieldName( name ) ) + throw RelationalException + ( "Cannot add payload field " + name + ": invalid name", + "RelationalFolder" ); + } + + // Add columns (and set the values for all existing rows) + db().schemaMgr().addColumnsToTable( m_objectTableName, record ); + + // Prepare the new specification + RecordSpecification newRecordSpecification = payloadSpecification(); + newRecordSpecification.extend( spec ); + + // Update the folder description + RecordSpecification dataSpec; + dataSpec.extend("newSpec", + RelationalNodeTable::columnTypeIds::folderPayloadSpecDesc); + dataSpec.extend("nodeId", + RelationalNodeTable::columnTypeIds::nodeId); + + Record data( dataSpec ); + data["newSpec"] + .setValue<RelationalNodeTable::columnTypes::folderPayloadSpecDesc> + ( db().encodeRecordSpecification( newRecordSpecification ) ); + data["nodeId"] + .setValue<RelationalNodeTable::columnTypes::nodeId>( id() ); + + std::string setClause = + RelationalNodeTable::columnNames::folderPayloadSpecDesc; + setClause += " = :newSpec, "; + setClause += RelationalNodeTable::columnNames::lastModDate; + setClause += " = " + db().queryMgr().serverTimeClause(); + + std::string whereClause = RelationalNodeTable::columnNames::nodeId; + whereClause += "= :nodeId"; + + db().queryMgr().updateTableRows( db().nodeTableName(), + setClause, + whereClause, + data.attributeList() ); + + // Set the new specification + m_folderSpec.payloadSpecification() = newRecordSpecification; + +} + +//----------------------------------------------------------------------------- + +bool +RelationalFolder::existsUserTagInObjectTable +( const RelationalQueryMgr& queryMgr, + UInt32 userTagId, + const std::string& objectTableName ) +{ + coral::AttributeList whereData; + whereData.extend + ( "userTagId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::userTagId) ); + whereData["userTagId"].setValue( userTagId ); + std::string whereClause = + RelationalObjectTable::columnNames::userTagId(); + whereClause += "=:userTagId"; + unsigned int rowCount = queryMgr.countRowsFromTables + ( RelationalQueryMgr::tableList( objectTableName ), + whereClause, whereData, "" ); + return rowCount > 0; +} + +//----------------------------------------------------------------------------- + +bool +RelationalFolder::existsTagInObject2TagTable +( const RelationalQueryMgr& queryMgr, + UInt32 tagId, + const std::string& object2TagTableName ) +{ + coral::AttributeList whereData; + whereData.extend + ( "tagId", + typeIdToCoralType(RelationalObject2TagTable::columnTypeIds::tagId) ); + whereData["tagId"].setValue( tagId ); + std::string whereClause = + RelationalObject2TagTable::columnNames::tagId; + whereClause += "=:tagId"; + unsigned int rowCount = queryMgr.countRowsFromTables + ( RelationalQueryMgr::tableList( object2TagTableName ), + whereClause, whereData, "" ); + return rowCount > 0; +} + +//----------------------------------------------------------------------------- +/* +bool RelationalFolder::isTagUsed( UInt32 tagId ) const +{ + // Is the tag referenced in the TAG2TAG table? + if ( RelationalHvsNode::isTagUsed( tagId ) ) { + return true; + } + // Is the tag used as user tag in the IOV table? + else if ( existsUserTagInObjectTable( tagId ) ) { + return true; + } + // Is the tag used in the IOV2TAG table? + else { + return existsTagInObject2TagTable( tagId ); + } +} +*/ +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalFolder.h b/RelationalCool/src/RelationalFolder.h new file mode 100644 index 000000000..1524680bf --- /dev/null +++ b/RelationalCool/src/RelationalFolder.h @@ -0,0 +1,539 @@ +// $Id: RelationalFolder.h,v 1.158 2009-01-06 12:36:25 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALFOLDER_H +#define RELATIONALCOOL_RELATIONALFOLDER_H + +// Disable warning C4250 on Windows (inheritance via dominance) +// Copied from SEAL (Dictionary/Reflection/src/Tools.h) +#ifdef WIN32 +#pragma warning ( disable : 4250 ) +#endif + +// Include files +#include <memory> +#include <vector> +#include "CoralBase/MessageStream.h" +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/FolderSpecification.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalDatabase.h" +#include "RelationalHvsNode.h" +#include "VersionNumber.h" + +namespace cool { + + /** @class RelationalFolder RelationalFolder.h + * + * Relational implementation of a COOL condition database "folder". + * + * Also represents implementation within COOL of an HVS leaf node. + * Multiple virtual inheritance from IFolder and RelationalHvsNode + * (diamond virtual inheritance of IHvsNodeRecord abstract interface). + * + * @author Sven A. Schmidt, Andrea Valassi and Marco Clemencic + * @date 2004-11-24 + */ + + class RelationalFolder : virtual public IFolder, + virtual public RelationalHvsNode + { + + public: + + // Folder schema version for this class + static const VersionNumber folderSchemaVersion() + { + // Summary of changes since software release COOL_2_0_0: + // - COOL_2_0 creates '2.0.0' folders. + // - COOL_2_1 still creates '2.0.0' folders (as agreed with users), + // even if these actually have an additional 5D index in the IOV table + // with respect to those created using COOL_2_0_0. + // - COOL_2_2 creates '2.0.1' folders: these have a FK on channelId + // from the IOV to the channels table (only enforced on Oracle/MySQL); + // also, the MySQL default type for VARCHAR(255) is now BINARY. + // COOL_2_2 continues to read data using the 2.0.0 folder queries. + // - COOL_2_3/2_4/2_5/2_6/2_7 create '2.0.1' folders just like COOL_2_2. + return "2.0.1"; + } + + // Check if a folder schema version is supported by this class + static bool isSupportedSchemaVersion( const VersionNumber& schemaVersion ); + + /// Constructor to create a RelationalFolder from a node table row + /// Inlined with the base class non-standard constructors as otherwise + /// the compiler attempts to use the base class standard constructors + /// (Windows compilation error C2248: standard constructors are private) + RelationalFolder( const RelationalDatabasePtr& db, + const coral::AttributeList& row ) + : RelationalHvsNodeRecord( row ) + , RelationalHvsNode( db, row ) + , m_log( new coral::MessageStream( "RelationalFolder" ) ) + , m_folderSpec( versioningMode( row ), payloadSpecification( row ) ) + , m_publicFolderAttributes() // fill it in initialize + { + initialize( row ); + } + + /// Destructor. + virtual ~RelationalFolder(); + + public: + + /// Return the folder specification. + const IFolderSpecification& folderSpecification() const { + return m_folderSpec; + } + + /// Return the payload specification of the folder. + const IRecordSpecification& payloadSpecification() const { + return folderSpecification().payloadSpecification(); + } + + /// Return the folder versioning mode. + FolderVersioning::Mode versioningMode() const { + return folderSpecification().versioningMode(); + } + + /// Return the 'attributes' of the folder + /// (implementation-specific properties not exposed in the API). + const IRecord& folderAttributes() const; + + /* + /// Declare that some payload columns reference external payload. + /// The referencedEntity URL contains the path to the external container. + /// Only FKs to relational tables within the same database are supported + /// so far with the syntax "local://schema=USERNAME;table=TABLENAME". + /// Non-relational implementation of CoolKernel should throw an exception. + /// Returns true in case of success, false in case of any error. + bool declareExternalReference + ( const std::string& name, + const std::vector< std::string >& attributes, + const std::string& referencedEntity, + const std::vector< std::string >& referencedAttributes ); + + /// List the external reference constraints. + const std::vector< std::string > externalReferences() const; + + /// Retrieve the properties of an external reference constraint + const IFolder::ExternalReference& + externalReference( const std::string& name ) const; + */ + + /// Activate/deactivate a storage buffer for bulk insertion of objects. + /// If the buffer was used and is deactivated, flush the buffer. + void setupStorageBuffer( bool useBuffer = true ); + + /// Flush the storage buffer (execute the bulk insertion of objects). + /// If the buffer is not used, ignore this command. + void flushStorageBuffer(); + + /// Store an object in a given channel with the given IOV and data payload. + /// If the buffer is used, only register the object for later storage. + void storeObject( const ValidityKey& since, + const ValidityKey& until, + const IRecord& payload, + const ChannelId& channelId, + const std::string& userTagName = "", + bool userTagOnly = false ); + + // OBSOLETE - kept for backward compatibility + void storeObject( const ValidityKey& since, + const ValidityKey& until, + const coral::AttributeList& payload, + const ChannelId& channelId, + const std::string& userTagName = "", + bool userTagOnly = false ); + + /// Set a new finite end-of-validity value for all SV objects in a given + /// channel selection whose end-of-validity is currently infinite. + /// The channel selection is specified through a ChannelSelection object. + /// Throws an Exception if called on a MV folder, or if any of the + /// selected channels contains a not open ended IOV at the point until. + /// Returns the number of actually truncated IOVs. + virtual int truncateObjectValidity( const ValidityKey& until, + const ChannelSelection& channels ); + + /// Find the ONE object in a given channel valid at the given point in time + /// in the given tag ("" and "HEAD" both indicate the folder HEAD). + /// Tag names, except for "HEAD", are case sensitive. + /// If the buffer is used, it must be flushed first (else throw exception). + /// Throws an ObjectNotFound exception if no such object exists. + /// For single version folders, the tag must be either "" or "HEAD", + /// otherwise a TagNotFound exception is thrown. + IObjectPtr findObject( const ValidityKey& pointInTime, + const ChannelId& channelId, + const std::string& tagName="" ) const; + + /// Find the objects for a given channel selection at the given point + /// in time in the given tag ("" and "HEAD" both indicate the folder HEAD). + /// Tag names, except for "HEAD", are case sensitive. + /// The channel selection is specified through a ChannelSelection object. + /// The iterator will retrieve only ONE object for each selected channel + /// (or none if there is no valid IOV at pointInTime in the channel). + /// The iterator returns objects ordered by channel: the order clause + /// optionally specified in the ChannelSelection object is ignored. + /// For single version folders, the tag must be either "" or "HEAD", + /// otherwise a TagNotFound exception is thrown. + IObjectIteratorPtr + findObjects( const ValidityKey& pointInTime, + const ChannelSelection& channels, + const std::string& tagName = "" ) const; + + /// Browse the objects for a given channel selection within the given time + /// range in the given tag ("" and "HEAD" both indicate the folder HEAD). + /// Tag names, except for "HEAD", are case sensitive. + /// The validity range is inclusive at both ends as well, i.e. + /// since = t1, until = t2 will select an object with since = t2. + /// The channel selection is specified through a ChannelSelection object. + /// The iterator will retrieve only ONE object at any given validity point + /// for a given channel. The default order is channel, since. + /// For single version folders, the tag must be either "" or "HEAD", + /// otherwise a TagNotFound exception is thrown. + IObjectIteratorPtr + browseObjects( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName = "", + const IRecordSelection* payloadQuery = 0 ) const; + + /// Internal method + IObjectIteratorPtr + browseObjects( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + bool prefetchAll, + const IRecordSelection* payloadQuery ) const; + + /// Return the object count for the given selection. The selection + /// parameters are the same as for browseObjects (as is the actual + /// selection). + unsigned int countObjects( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName = "", + const IRecordSelection* payloadQuery = 0 ) const; + + /// Change the object prefetch policy (default is prefetchAll=true). + /// If prefetchAll is true, the browse() methods prefetch all IOVs and + /// return IObjectIterator's that are wrappers to IObjectPtr vectors. + /// If prefetchAll is false, the browse() methods prefetch only a few + /// IOVs at a time and return IObjectIterator's that are wrappers to + /// server-side cursors: a transaction and the cursor are opened when + /// the iterator is created, and these are only closed when the iterator + /// is explicitly deleted (or the shared pointer goes out of scope). + /// No other query against the database can be performed during that time. + void setPrefetchAll( bool prefetchAll ) { + m_prefetchAll = prefetchAll; + } + + /// to be documented + /// new browseObjects methods returning IObjectVector + IObjectVectorPtr fetchObjectsAtTime( const ValidityKey& pointInTime, + const ChannelSelection& channels, + const std::string& tagName = "" ) const; + + /// to be documented + /// new browseObjects methods returning IObjectVector + IObjectVectorPtr fetchObjectsInRange( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName = "" ) const; + + /// Associates the objects that are the current HEAD + /// with the given tag name and tag description. + void tagCurrentHead( const std::string& tagName, + const std::string& description = "" ) const; + + /// Clones the tag "tagName" as user tag "tagClone" by reinserting + /// the IOVs with the user tag. Does not modify the current head. + /// This method is non-const because it sets m_useBuffer to use bulk + /// insertion and eventually restores the original setting of m_useBuffer. + void cloneTagAsUserTag( const std::string& tagName, + const std::string& tagClone, + const std::string& description = "", + bool forceOverwriteTag = false ); + + /// Associates the objects that were the HEAD at 'asOfDate' + /// with the given tag name and tag description. + void tagHeadAsOfDate( const ITime& asOfDate, + const std::string& tagName, + const std::string& description = "" ) const; + + /// TEMPORARY? Can be commented out until included in the public API? + /// Tags the objects in the given folder + /// that were at the HEAD at 'asOfObjectId', at the time the object with + /// id 'asOfObjectId' was inserted (and including that object) + /// with the given tagName and description. Throws a TagExists + /// exception if a tag by that name already exists. + void tagHeadAsOfObjectId( unsigned int asOfObjectId, + const std::string& tagName, + const std::string& description ); + + /// Tags the given objects of the given folder. Throws a TagExists + /// exception if a tag by that name already exists. + void tagObjectList( const std::string& tagName, + const std::string& description, + const std::vector<RelationalObjectTableRow>& objects ) const; + + /// Inserts the given objects for the given tag id in the given + /// object2Tag table + void insertObject2TagTableRows + ( const std::string& object2TagTableName, + unsigned int tagId, + const std::string& insertionTime, + const std::vector<RelationalObjectTableRow>& objects ) const; + + /// Delete rows with tagId from the object2tag table. + /// Returns the number of deleted rows. + unsigned int + deleteObject2TagTableRows( const std::string& object2TagTableName, + unsigned int tagId ) const; + + /// Delete rows with tagId from the object table. + /// Returns the number of deleted rows. + unsigned int + deleteObjectTableRowsForUserTag( const std::string& objectTableName, + unsigned int tagId ) const; + + /// Insertion time of the last inserted IOV in a tag defined for this node. + const Time + insertionTimeOfLastObjectInTag( const std::string& tagName ) const; + + /// Deletes a tag from this folder and from the global "tag namespace". + /// The tag name is available for tagging again afterwards. + void deleteTag( const std::string& tagName ); + + /// Does this user tag exist? - This starts a transaction + /// Tag names are case sensitive. + bool existsUserTag( const std::string& userTagName ) const; + + /// Does this user tag exist? - This does not start a transaction + /// Tag names are case sensitive. + bool __existsUserTag( const std::string& userTagName ) const; + + /// Rename a payload item + void renamePayload( const std::string& oldName, + const std::string& newName ); + + /// Rename a payload item - This does not start a transaction + void __renamePayload( const std::string& oldName, + const std::string& newName ); + + /// Add new payload fields with the given names and storage types, + /// setting their values for all existing IOVS to the given values. + void extendPayloadSpecification( const IRecord& record ); + + /// Add new payload fields with the given names and storage types, + /// setting their values for all existing IOVS to the given values. + /// - This does not start a transaction + void __extendPayloadSpecification( const IRecord& record ); + + /* + /// Does this user tag exist in the object table? + /// THIS DOES NOT START A TRANSACTION + bool existsUserTagInObjectTable( UInt32 userTagId ) const; + + /// Does this user tag exist in the object2tag table? + /// THIS DOES NOT START A TRANSACTION + bool existsTagInObject2TagTable( UInt32 userTagId ) const; + */ + + /* + /// Does this tag defined in this node have any relation (i.e. does + /// it reference a parent tag or is it referenced by any children)? + /// Returns false if this tag does not exist in this node. + /// OVERLOADED RelationalHvsNode method. + bool isTagUsed( UInt32 tagId ) const; + */ + + /// Does this user tag exist in the object table? + /// THIS DOES NOT START A TRANSACTION + static bool existsUserTagInObjectTable( const RelationalQueryMgr& queryMgr, + UInt32 userTagId, + const std::string& objectTableName ); + + /// Does this user tag exist in the object2tag table? + /// THIS DOES NOT START A TRANSACTION + static bool existsTagInObject2TagTable( const RelationalQueryMgr& queryMgr, + UInt32 tagId, + const std::string& object2TagTableName ); + + public: + + // ----- CHANNEL MANAGEMENT ----- + + /// Return the list of existing channels (ordered by ascending channelId). + const std::vector<ChannelId> listChannels() const; + + /// Return the map of id->name for all existing channels. + const std::map<ChannelId,std::string> listChannelsWithNames() const; + + /// Create a new channel with the given id, name and description. + /// Throw ChannelExists if the id/name is already used by another channel. + /// Throw InvalidChannelName if the channel name is invalid: all valid + /// channel names must be between 1 and 255 characters long; they must + /// start with a letter and must contain only letters, numbers or the '_' + /// character (these constraints may be relaxed in a future COOL release). + /// Throw an Exception if the description is longer than 255 characters. + void createChannel( const ChannelId& channelId, + const std::string& channelName, + const std::string& description = "" ); + + /// Drop (delete) an existing channel, given its id. + /// Return true if the channel is dropped as expected. Return false + /// (without throwing any exception) if the channel does not exist any + /// more on exit from this method, but it did not exist to start with. + /// Throw an Exception if the channel cannot be dropped. + /// NB: in the COOL_2_2_0 API, a channel can only be dropped if it exists + /// in the channel table but contains no IOVs (an exception is thrown if + /// it does contain IOVs); in later COOL releases, the semantics of this + /// method may change to mean 'drop the channel and any IOVs it contains'. + bool dropChannel( const ChannelId& channelId ); + + /// Set the name of a channel, given its id. + /// Throw ChannelNotFound if no channel exists with this id. + /// Throw InvalidChannelName if the channel name is invalid (see above). + /// Throw ChannelExists if the name is already used by another channel. + void setChannelName( const ChannelId& channelId, + const std::string& channelName ); + + /// Return the name of a channel, given its id. + /// Throw ChannelNotFound if no channel exists with this id. + const std::string channelName( const ChannelId& channelId ) const; + + /// Return the id of a channel, given its name. + /// Throw InvalidChannelName if the channel name is invalid (see above). + /// Throw ChannelNotFound if no channel exists with this name. + ChannelId channelId( const std::string& channelName ) const; + + /// Does a channel with this id exist? + bool existsChannel( const ChannelId& channelId ) const; + + /// Does a channel with this name exist? + /// Throw InvalidChannelName if the channel name is invalid (see above). + bool existsChannel( const std::string& channelName ) const; + + /// Set the description of a channel, given its id. + /// Throw ChannelNotFound if no channel exists with this id. + /// Throw InvalidChannelName if the channel name is invalid (see above). + /// Throw an Exception if the description is longer than 255 characters. + void setChannelDescription( const ChannelId& channelId, + const std::string& description ); + + /// Return the description of a channel, given its id. + /// Throw ChannelNotFound if no channel exists with this id. + const std::string channelDescription( const ChannelId& channelId ) const; + + public: + + /// Return the IOV table name for this folder. + const std::string& objectTableName() const; + + /// Return the tag table name for this folder. + const std::string& tagTableName() const; + + /// Return the IOV2tag table name for this folder. + const std::string& object2TagTableName() const; + + /// Return the channel table name for this folder. + const std::string& channelTableName() const; + + public: + + /// Get the extended payload specification from the given folder row + static const RecordSpecification + payloadSpecification( const coral::AttributeList& folderRow ); + + /// Get the versioning mode from the given folder row + static FolderVersioning::Mode + versioningMode( const coral::AttributeList& folderRow ); + + /// Get the object table name from the given folder row + static const std::string objectTableName + ( const coral::AttributeList& folderRow ); + + /// Get the tag table name from the given folder row + static const std::string tagTableName + ( const coral::AttributeList& folderRow ); + + /// Get the object2tag table name from the given folder row + static const std::string object2TagTableName + ( const coral::AttributeList& folderRow ); + + /// Get the channel table name from the given folder row + static const std::string channelTableName + ( const coral::AttributeList& folderRow ); + + /// Buffer size for bulk insertion + static unsigned maxBufferSize(); + + private: + + /// Initialize (complete non-standard constructor with non-inlined code) + void initialize( const coral::AttributeList& row ); + + /// Standard constructor is private + RelationalFolder(); + + /// Copy constructor is private + RelationalFolder( const RelationalFolder& rhs ); + + /// Assignment operator is private + RelationalFolder& operator=( const RelationalFolder& rhs ); + + private: + + /// Get a CORAL MessageStream + coral::MessageStream& log() const; + + /// Folder attribute specification for the RelationalFolder class + static const RecordSpecification& folderAttributesSpecification + ( FolderVersioning::Mode versioningMode ); + + private: + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// Folder specification + FolderSpecification m_folderSpec; + + /// External reference constraint map + //std::map< std::string, IFolder::ExternalReference > m_externalReferences; + + /// Use a storage buffer? + bool m_useBuffer; + + /// Object storage buffer + std::vector<RelationalObjectPtr> m_objectBuffer; + + /// Insert into the user tag branch only? + bool m_userTagOnly; + + /// IOV table name + std::string m_objectTableName; + + /// Tag table name + std::string m_tagTableName; + + /// IOV2tag table name + std::string m_object2TagTableName; + + /// Channel table name + std::string m_channelTableName; + + /// Public attributes of the folder + Record m_publicFolderAttributes; + + /// Prefetch all objects into vectors? + bool m_prefetchAll; + + }; + +} + +#endif + diff --git a/RelationalCool/src/RelationalFolderSet.cpp b/RelationalCool/src/RelationalFolderSet.cpp new file mode 100644 index 000000000..1bc6e22cd --- /dev/null +++ b/RelationalCool/src/RelationalFolderSet.cpp @@ -0,0 +1,91 @@ +// $Id: RelationalFolderSet.cpp,v 1.16 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoolKernel/Exception.h" + +// Local include files +#include "RelationalDatabase.h" +#include "RelationalFolderSet.h" +#include "RelationalNodeTable.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +bool RelationalFolderSet::isSupportedSchemaVersion +( const VersionNumber& rhs ) +{ + VersionNumber lhs = folderSetSchemaVersion(); + return + ( lhs.majorVersion() == rhs.majorVersion() ) + && ( lhs.minorVersion() == rhs.minorVersion() ); + //&& ( lhs.patchVersion() <= rhs.patchVersion() ); +} + +//----------------------------------------------------------------------------- + +void RelationalFolderSet::initialize( const coral::AttributeList& row ) +{ + const IRecordSpecification& spec = folderSetAttributesSpecification(); + m_publicFolderSetAttributes = Record( spec, row ); + log() << coral::Debug << "Instantiate a RelationalFolderSet for '" + << fullPath() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalFolderSet::~RelationalFolderSet() +{ + log() << coral::Debug << "Delete the RelationalFolderSet for '" + << fullPath() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RelationalFolderSet::log() +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +std::vector<std::string> +RelationalFolderSet::listFolders( bool ascending ) +{ + return db().listFolders( this, ascending ); +} + + +//----------------------------------------------------------------------------- + +std::vector<std::string> +RelationalFolderSet::listFolderSets( bool ascending ) +{ + return db().listFolderSets( this, ascending ); +} + +//----------------------------------------------------------------------------- + +const IRecord& RelationalFolderSet::folderSetAttributes() const +{ + return m_publicFolderSetAttributes; +} + +//----------------------------------------------------------------------------- + +const RecordSpecification& +RelationalFolderSet::folderSetAttributesSpecification() +{ + static RecordSpecification s_folderSetAttrSpec; + if ( s_folderSetAttrSpec.size() == 0 ) { + s_folderSetAttrSpec.extend + ( RelationalNodeTable::columnNames::nodeSchemaVersion, + RelationalNodeTable::columnTypeIds::nodeSchemaVersion ); + } + return s_folderSetAttrSpec; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalFolderSet.h b/RelationalCool/src/RelationalFolderSet.h new file mode 100644 index 000000000..a26b65fd5 --- /dev/null +++ b/RelationalCool/src/RelationalFolderSet.h @@ -0,0 +1,111 @@ +// $Id: RelationalFolderSet.h,v 1.28 2008-11-04 11:30:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALFOLDERSET_H +#define RELATIONALCOOL_RELATIONALFOLDERSET_H + +// Disable warning C4250 on Windows (inheritance via dominance) +// Copied from SEAL (Dictionary/Reflection/src/Tools.h) +#ifdef WIN32 +#pragma warning ( disable : 4250 ) +#endif + +// Include files +#include <memory> +#include "CoolKernel/IFolderSet.h" +#include "CoralBase/MessageStream.h" + +// Local include files +#include "RelationalDatabasePtr.h" +#include "RelationalHvsNode.h" + +namespace cool { + + /** @class RelationalFolderSet RelationalFolderSet.h + * + * Relational implementation of a COOL condition database "folderset". + * + * Also represents implementation within COOL of an HVS leaf node. + * Multiple virtual inheritance from IFolder and RelationalHvsNode + * (diamond virtual inheritance of IHvsNodeRecord abstract interface). + * + * @author Sven A. Schmidt and Andrea Valassi + * @date 2005-06-07 + */ + + class RelationalFolderSet : virtual public IFolderSet, + virtual public RelationalHvsNode + { + + public: + + // Folder set schema version for this class + static const VersionNumber folderSetSchemaVersion() + { + return "2.0.0"; + } + + // Check if a folder set schema version is supported by this class + static bool isSupportedSchemaVersion( const VersionNumber& schemaVersion ); + + /// Constructor to create a RelationalFolderSet from a node table row + /// Inlined with the base class non-standard constructors as otherwise + /// the compiler attempts to use the base class standard constructors + /// (Windows compilation error C2248: standard constructors are private) + RelationalFolderSet( const RelationalDatabasePtr& db, + const coral::AttributeList& row ) + : RelationalHvsNodeRecord( row ) + , RelationalHvsNode( db, row ) + , m_log( new coral::MessageStream( "RelationalFolderSet" ) ) + , m_publicFolderSetAttributes() // fill it in initialize + { + initialize( row ); + } + + /// Destructor. + virtual ~RelationalFolderSet(); + + /// Lists all folders at this level in the node hierarchy + std::vector<std::string> listFolders( bool ascending = true ); + + /// Lists all foldersets at this level in the node hierarchy + std::vector<std::string> listFolderSets( bool ascending = true ); + + /// Return the 'attributes' of the folderset + /// (implementation-specific properties not exposed in the API). + const IRecord& folderSetAttributes() const; + + private: + + /// Initialize (complete non-standard constructor with non-inlined code) + void initialize( const coral::AttributeList& row ); + + /// Standard constructor is private + RelationalFolderSet(); + + /// Copy constructor is private + RelationalFolderSet( const RelationalFolderSet& rhs ); + + /// Assignment operator is private + RelationalFolderSet& operator=( const RelationalFolderSet& rhs ); + + private: + + /// Get a CORAL MessageStream + coral::MessageStream& log(); + + /// Folderset attribute specification for the RelationalFolderSetNew class + static const RecordSpecification& folderSetAttributesSpecification(); + + private: + + /// SEAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// Public attributes of the folderset + Record m_publicFolderSetAttributes; + + }; + +} + +#endif + diff --git a/RelationalCool/src/RelationalFolderSetUnsupported.cpp b/RelationalCool/src/RelationalFolderSetUnsupported.cpp new file mode 100644 index 000000000..6c42f4ed9 --- /dev/null +++ b/RelationalCool/src/RelationalFolderSetUnsupported.cpp @@ -0,0 +1,62 @@ +// $Id: RelationalFolderSetUnsupported.cpp,v 1.3 2008-03-20 18:30:20 marcocle Exp $ + +// Local include files +#include "RelationalDatabase.h" +#include "RelationalFolderSetUnsupported.h" +#include "RelationalNodeTable.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +void +RelationalFolderSetUnsupported::initialize( const coral::AttributeList& row ) +{ + const IRecordSpecification& spec = folderSetAttributesSpecification(); + m_publicFolderSetAttributes = Record( spec, row ); + log() << coral::Debug + << "Instantiate a RelationalFolderSetUnsupported for '" + << fullPath() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalFolderSetUnsupported::~RelationalFolderSetUnsupported() +{ + log() << coral::Debug + << "Delete the RelationalFolderSetUnsupported for '" + << fullPath() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RelationalFolderSetUnsupported::log() +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +const IRecord& RelationalFolderSetUnsupported::folderSetAttributes() const +{ + return m_publicFolderSetAttributes; +} + +//----------------------------------------------------------------------------- + +const RecordSpecification& +RelationalFolderSetUnsupported::folderSetAttributesSpecification() +{ + static RecordSpecification s_folderSetAttrSpec; + if ( s_folderSetAttrSpec.size() == 0 ) { + s_folderSetAttrSpec.extend + ( RelationalNodeTable::columnNames::nodeSchemaVersion, + RelationalNodeTable::columnTypeIds::nodeSchemaVersion ); + } + return s_folderSetAttrSpec; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalFolderSetUnsupported.h b/RelationalCool/src/RelationalFolderSetUnsupported.h new file mode 100644 index 000000000..266c99686 --- /dev/null +++ b/RelationalCool/src/RelationalFolderSetUnsupported.h @@ -0,0 +1,124 @@ +// $Id: RelationalFolderSetUnsupported.h,v 1.7 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALFOLDERSETUNSUPPORTED_H +#define RELATIONALCOOL_RELATIONALFOLDERSETUNSUPPORTED_H + +// Disable warning C4250 on Windows (inheritance via dominance) +// Copied from SEAL (Dictionary/Reflection/src/Tools.h) +#ifdef WIN32 +#pragma warning ( disable : 4250 ) +#endif + +// Include files +#include <memory> +#include "CoolKernel/IFolderSet.h" +#include "CoralBase/MessageStream.h" + +// Local include files +#include "RelationalDatabase.h" +#include "RelationalException.h" +#include "RelationalHvsNode.h" + +namespace cool { + + //-------------------------------------------------------------------------- + + /** @class RelationalFolderSetUnsupported RelationalFolderSetUnsupported.h + * + * UNSUPPORTED relational implementation of a COOL condition db "folderset". + * + * Also represents implementation within COOL of an HVS leaf node. + * Multiple virtual inheritance from IFolder and RelationalHvsNode + * (diamond virtual inheritance of IHvsNodeRecord abstract interface). + * + * Within the COOL 2.0 software, this represents a handle to a folder set + * created using the COOL 2.1 software and implementing the new 2.1 schema. + * Such a folder set cannot be opened for reading or writing using the 2.0 + * software (its contents cannot be read or modified): only its generic + * properties (those retrieved from the node table) can be queried. + * + * @author Andrea Valassi + * @date 2007-01-09 + */ + + class RelationalFolderSetUnsupported : virtual public IFolderSet, + virtual public RelationalHvsNode { + + public: + + /// Ctor to create a RelationalFolderSetUnsupported from a node table row + /// Inlined with the base class non-standard constructors as otherwise + /// the compiler attempts to use the base class standard constructors + /// (Windows compilation error C2248: standard constructors are private) + RelationalFolderSetUnsupported( const RelationalDatabasePtr& db, + const coral::AttributeList& row ) + : RelationalHvsNodeRecord( row ) + , RelationalHvsNode( db, row ) + , m_log( new coral::MessageStream( "RelationalFolderSetUnsupported" ) ) + , m_publicFolderSetAttributes() // fill it in initialize + { + initialize( row ); + } + + /// Destructor. + virtual ~RelationalFolderSetUnsupported(); + + /// Return the 'attributes' of the folderset + /// (implementation-specific properties not exposed in the API). + const IRecord& folderSetAttributes() const; + + public: + + // -- THE FOLLOWING METHODS ALL THROW -- + + /// Lists all folders at this level in the node hierarchy + std::vector<std::string> listFolders( bool /*ascending = true*/ ) + { + throw UnsupportedFolderSetSchema + ( fullPath(), schemaVersion(), "RelationalFolderSetUnsupported" ); + }; + + /// Lists all foldersets at this level in the node hierarchy + std::vector<std::string> listFolderSets( bool /*ascending = true*/ ) + { + throw UnsupportedFolderSetSchema + ( fullPath(), schemaVersion(), "RelationalFolderSetUnsupported" ); + }; + + private: + + /// Initialize (complete non-standard constructor with non-inlined code) + void initialize( const coral::AttributeList& row ); + + /// Standard constructor is private + RelationalFolderSetUnsupported(); + + /// Copy constructor is private + RelationalFolderSetUnsupported + ( const RelationalFolderSetUnsupported& rhs ); + + /// Assignment operator is private + RelationalFolderSetUnsupported& + operator=( const RelationalFolderSetUnsupported& rhs ); + + private: + + /// Get a CORAL MessageStream + coral::MessageStream& log(); + + /// Folderset attribute spec for the RelationalFolderSetUnsupported class + static const RecordSpecification& folderSetAttributesSpecification(); + + private: + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// Public attributes of the folderset + Record m_publicFolderSetAttributes; + + }; + +} + +#endif + diff --git a/RelationalCool/src/RelationalFolderUnsupported.cpp b/RelationalCool/src/RelationalFolderUnsupported.cpp new file mode 100644 index 000000000..a509c0602 --- /dev/null +++ b/RelationalCool/src/RelationalFolderUnsupported.cpp @@ -0,0 +1,59 @@ +// $Id: RelationalFolderUnsupported.cpp,v 1.2 2008-03-20 18:30:19 marcocle Exp $ + +// Local include files +#include "RelationalFolderUnsupported.h" +#include "RelationalNodeTable.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +void RelationalFolderUnsupported::initialize( const coral::AttributeList& row ) +{ + const IRecordSpecification& spec = folderAttributesSpecification(); + m_publicFolderAttributes = Record( spec, row ); + log() << coral::Debug + << "Instantiate a RelationalFolderUnsupported for '" + << fullPath() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalFolderUnsupported::~RelationalFolderUnsupported() +{ + log() << coral::Debug << "Delete the RelationalFolderUnsupported for '" + << fullPath() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RelationalFolderUnsupported::log() const +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +const IRecord& RelationalFolderUnsupported::folderAttributes() const +{ + return m_publicFolderAttributes; +} + +//----------------------------------------------------------------------------- + +const RecordSpecification& +RelationalFolderUnsupported::folderAttributesSpecification() +{ + static RecordSpecification s_folderAttrSpec; + if ( s_folderAttrSpec.size() == 0 ) { + s_folderAttrSpec.extend + ( RelationalNodeTable::columnNames::nodeSchemaVersion, + RelationalNodeTable::columnTypeIds::nodeSchemaVersion ); + } + return s_folderAttrSpec; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalFolderUnsupported.h b/RelationalCool/src/RelationalFolderUnsupported.h new file mode 100644 index 000000000..69334d136 --- /dev/null +++ b/RelationalCool/src/RelationalFolderUnsupported.h @@ -0,0 +1,388 @@ +// $Id: RelationalFolderUnsupported.h,v 1.24 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALFOLDERUNSUPPORTED_H +#define RELATIONALCOOL_RELATIONALFOLDERUNSUPPORTED_H + +// Disable warning C4250 on Windows (inheritance via dominance) +// Copied from SEAL (Dictionary/Reflection/src/Tools.h) +#ifdef WIN32 +#pragma warning ( disable : 4250 ) +#endif + +// Include files +#include <memory> +#include "CoralBase/MessageStream.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/Time.h" + +// Local include files +#include "RelationalDatabase.h" +#include "RelationalException.h" +#include "RelationalHvsNode.h" + +namespace cool { + + //-------------------------------------------------------------------------- + + /** @class RelationalFolderUnsupported RelationalFolderUnsupported.h + * + * UNSUPPORTED relational implementation of a COOL condition db "folder". + * + * Also represents implementation within COOL of an HVS leaf node. + * Multiple virtual inheritance from IFolder and RelationalHvsNode + * (diamond virtual inheritance of IHvsNodeRecord abstract interface). + * + * Within the COOL 2.0 software, this represents a handle to a folder + * created using the COOL 2.1 software and implementing the new 2.1 schema. + * Such a folder cannot be opened for reading or writing using the 2.0 + * software (its contents cannot be read or modified): only its generic + * properties (those retrieved from the node table) can be queried. + * + * Within the COOL 2.2.2 software, this may also represent a handle + * to a folder with schema version 2.0.0, that is no longer supported. + * + * @author Andrea Valassi + * @date 2007-01-09 + */ + + class RelationalFolderUnsupported : virtual public IFolder, + virtual public RelationalHvsNode { + + public: + + /// Ctor to create a RelationalFolderUnsupported from a node table row + /// Inlined with the base class non-standard constructors as otherwise + /// the compiler attempts to use the base class standard constructors + /// (Windows compilation error C2248: standard constructors are private) + RelationalFolderUnsupported( const RelationalDatabasePtr& db, + const coral::AttributeList& row ) + : RelationalHvsNodeRecord( row ) + , RelationalHvsNode( db, row ) + , m_log + ( new coral::MessageStream( "RelationalFolderUnsupported" ) ) + , m_publicFolderAttributes() // fill it in initialize + { + initialize( row ); + } + + /// Destructor. + virtual ~RelationalFolderUnsupported(); + + /// Return the 'attributes' of the folder + /// (implementation-specific properties not exposed in the API). + const IRecord& folderAttributes() const; + + public: + + // -- THE FOLLOWING METHODS ALL THROW -- + + /// Return the folder specification. + const IFolderSpecification& folderSpecification() const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Return the payload specification of the folder. + const IRecordSpecification& payloadSpecification() const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Return the folder versioning mode. + FolderVersioning::Mode versioningMode() const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Activate/deactivate a storage buffer for bulk insertion of objects. + /// If the buffer was used and is deactivated, flush the buffer. + void setupStorageBuffer( bool /*useBuffer*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Flush the storage buffer (execute the bulk insertion of objects). + /// If the buffer is not used, ignore this command. + void flushStorageBuffer() + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Store an object in a given channel with the given IOV and data payload. + void storeObject( const ValidityKey& /*since*/, + const ValidityKey& /*until*/, + const IRecord& /*payload*/, + const ChannelId& /*channelId*/, + const std::string& /*userTagName*/, + bool /*userTagOnly*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// DEPRECATED - added for easier compatibility with COOL 1.3 + /// (this is likely to be removed in a future COOL release). + void storeObject( const ValidityKey& /*since*/, + const ValidityKey& /*until*/, + const coral::AttributeList& /*payload*/, + const ChannelId& /*channelId*/, + const std::string& /*userTagName = ""*/, + bool /*userTagOnly*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Set a new finite end-of-validity value for all SV objects in a given + /// channel selection whose end-of-validity is currently infinite. + int truncateObjectValidity( const ValidityKey& /*until*/, + const ChannelSelection& /*channels*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Find the ONE object in a given channel valid at the given point in time + /// in the given tag ("" and "HEAD" both indicate the folder HEAD). + IObjectPtr findObject( const ValidityKey& /*pointInTime*/, + const ChannelId& /*channelId*/, + const std::string& /*tagName*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Find the objects for a given channel selection at the given point + /// in time in the given tag ("" and "HEAD" both indicate the folder HEAD). + IObjectIteratorPtr findObjects( const ValidityKey& /*pointInTime*/, + const ChannelSelection& /*channels*/, + const std::string& /*tagName*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Browse the objects for a given channel selection within the given time + /// range in the given tag ("" and "HEAD" both indicate the folder HEAD). + IObjectIteratorPtr browseObjects( const ValidityKey& /*since*/, + const ValidityKey& /*until*/, + const ChannelSelection& /*channels*/, + const std::string& /*tagName*/, + const IRecordSelection* /*payloadQuery*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Rename a payload item + void renamePayload( const std::string& /*oldName*/, + const std::string& /*newName*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Add new payload fields with the given names and storage types, + /// setting their values for all existing IOVS to the given values. + void extendPayloadSpecification( const IRecord& /*record*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Count the number of objects that would be returned by the + /// browseObjects method for the same selection parameters. + unsigned int countObjects( const ValidityKey& /*since*/, + const ValidityKey& /*until*/, + const ChannelSelection& /*channels*/, + const std::string& /*tagName = ""*/, + const IRecordSelection* /*payloadQuery = 0*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Change the object prefetch policy (default is prefetchAll=true). + void setPrefetchAll( bool /*prefetchAll*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Associates the objects that are the current HEAD + /// with the given tag name and tag description. + void tagCurrentHead( const std::string& /*tagName*/, + const std::string& /*description = ""*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Clones the tag "tagName" as user tag "tagClone" by reinserting + /// the IOVs with the user tag. Does not modify the current head. + void cloneTagAsUserTag( const std::string& /*tagName*/, + const std::string& /*tagClone*/, + const std::string& /*description = ""*/, + bool /*forceOverwrite = false*/) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Associates the objects that were the HEAD at 'asOfDate' + /// with the given tag name and tag description. + void tagHeadAsOfDate( const ITime& /*asOfDate*/, + const std::string& /*tagName*/, + const std::string& /*description = ""*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Insertion time of the last inserted IOV in a tag defined for this node. + const Time + insertionTimeOfLastObjectInTag( const std::string& /*tagName*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Deletes a tag from this folder and from the global "tag namespace". + void deleteTag( const std::string& /*tagName*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Does this user tag exist? + bool existsUserTag( const std::string& /*userTagName*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Return the list of existing channels (ordered by ascending channelId). + const std::vector<ChannelId> listChannels() const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Return the map of id->name for all existing channels. + const std::map<ChannelId,std::string> listChannelsWithNames() const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Create a new channel with the given id, name and description. + void createChannel( const ChannelId& /*channelId*/, + const std::string& /*channelName*/, + const std::string& /*description = ""*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + + /// Drop a channel with the given id + bool dropChannel( const ChannelId& /*channelId*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + + /// Set the name of a channel, given its id. + void setChannelName( const ChannelId& /*channelId*/, + const std::string& /*channelName*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Return the name of a channel, given its id. + const std::string channelName( const ChannelId& /*channelId*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Return the id of a channel, given its name. + ChannelId channelId( const std::string& /*channelName*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Does a channel with this id exist? + bool existsChannel( const ChannelId& /*channelId*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Does a channel with this name exist? + bool existsChannel( const std::string& /*channelName*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Set the description of a channel, given its id. + void setChannelDescription( const ChannelId& /*channelId*/, + const std::string& /*description*/ ) + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + /// Return the description of a channel, given its id. + const std::string + channelDescription( const ChannelId& /*channelId*/ ) const + { + throw UnsupportedFolderSchema + ( fullPath(), schemaVersion(), "RelationalFolderUnsupported" ); + }; + + private: + + /// Initialize (complete non-standard constructor with non-inlined code) + void initialize( const coral::AttributeList& row ); + + /// Standard constructor is private + RelationalFolderUnsupported(); + + /// Copy constructor is private + RelationalFolderUnsupported( const RelationalFolderUnsupported& rhs ); + + /// Assignment operator is private + RelationalFolderUnsupported& + operator=( const RelationalFolderUnsupported& rhs ); + + private: + + /// Get a CORAL MessageStream + coral::MessageStream& log() const; + + /// Folder attribute spec for the RelationalFolderUnsupported class + static const RecordSpecification& folderAttributesSpecification(); + + private: + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// Public attributes of the folder + Record m_publicFolderAttributes; + + }; + +} + +#endif + diff --git a/RelationalCool/src/RelationalGlobalHeadTagTable.cpp b/RelationalCool/src/RelationalGlobalHeadTagTable.cpp new file mode 100644 index 000000000..e44ef888c --- /dev/null +++ b/RelationalCool/src/RelationalGlobalHeadTagTable.cpp @@ -0,0 +1,29 @@ +// $Id: RelationalGlobalHeadTagTable.cpp,v 1.1 2007-02-16 14:54:18 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalGlobalHeadTagTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalGlobalHeadTagTable::tableSpecification() +{ + static RecordSpecification spec; + + if ( spec.size() == 0 ) + { + spec.extend( RelationalGlobalHeadTagTable::columnNames::nodeId, + RelationalGlobalHeadTagTable::columnTypeIds::nodeId ); + spec.extend( RelationalGlobalHeadTagTable::columnNames::tagId, + RelationalGlobalHeadTagTable::columnTypeIds::tagId ); + spec.extend( RelationalGlobalHeadTagTable::columnNames::tagType, + RelationalGlobalHeadTagTable::columnTypeIds::tagType ); + } + return spec; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalGlobalHeadTagTable.h b/RelationalCool/src/RelationalGlobalHeadTagTable.h new file mode 100644 index 000000000..a2667081f --- /dev/null +++ b/RelationalCool/src/RelationalGlobalHeadTagTable.h @@ -0,0 +1,61 @@ +// $Id: RelationalGlobalHeadTagTable.h,v 1.2 2007-02-16 14:59:48 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALGLOBALHEADTAGTABLE_H +#define RELATIONALCOOL_RELATIONALGLOBALHEADTAGTABLE_H + +// Include files +#include "CoolKernel/StorageType.h" + +// Local include files +#include "uppercaseString.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalGlobalHeadTagTable RelationalGlobalHeadTagTable.h + * + * Relational schema of the table storing COOL global HEAD tags. + * + * @author Andrea Valassi + * @date 2007-02-15 + */ + + namespace RelationalGlobalHeadTagTable { + + inline const std::string defaultTableName( const std::string& prefix ) + { + return uppercaseString(prefix) + "HEADTAGS"; + } + + namespace columnNames + { + static const std::string nodeId = "NODE_ID"; + static const std::string tagId = "TAG_ID"; + // Tag type (NOT NULL): 0(unknown), 1(head), 2(user) + // Tag type must be equal to 1 (CHECK constraint) for the head tag table + static const std::string tagType = "TAG_TYPE"; + } + + namespace columnTypeIds + { + static const StorageType::TypeId nodeId = StorageType::UInt32; + static const StorageType::TypeId tagId = StorageType::UInt32; + static const StorageType::TypeId tagType = StorageType::UInt16; + } + + namespace columnTypes + { + typedef UInt32 nodeId; + typedef UInt32 tagId; + typedef UInt16 tagType; + } + + /// Get the record specification of the global user tag table + const IRecordSpecification& tableSpecification(); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALGLOBALHEADTAGTABLE_H diff --git a/RelationalCool/src/RelationalGlobalTagTable.cpp b/RelationalCool/src/RelationalGlobalTagTable.cpp new file mode 100644 index 000000000..cc3be30e7 --- /dev/null +++ b/RelationalCool/src/RelationalGlobalTagTable.cpp @@ -0,0 +1,40 @@ +// $Id: RelationalGlobalTagTable.cpp,v 1.13 2007-02-16 16:53:29 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalGlobalTagTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalGlobalTagTable::tableSpecification() +{ + static RecordSpecification spec; + + if ( spec.size() == 0 ) { + spec.extend( RelationalGlobalTagTable::columnNames::nodeId, + RelationalGlobalTagTable::columnTypeIds::nodeId ); + spec.extend( RelationalGlobalTagTable::columnNames::tagId, + RelationalGlobalTagTable::columnTypeIds::tagId ); + spec.extend( RelationalGlobalTagTable::columnNames::tagName, + RelationalGlobalTagTable::columnTypeIds::tagName ); + spec.extend( RelationalGlobalTagTable::columnNames::tagLockStatus, + RelationalGlobalTagTable::columnTypeIds::tagLockStatus ); + spec.extend( RelationalGlobalTagTable::columnNames::tagDescription, + RelationalGlobalTagTable::columnTypeIds::tagDescription ); + /* + // *** START *** 3.0.0 schema extensions (task #4396) + spec.extend( RelationalGlobalTagTable::columnNames::tagType, + RelationalGlobalTagTable::columnTypeIds::tagType ); + // **** END **** 3.0.0 schema extensions (task #4396) + */ + spec.extend( RelationalGlobalTagTable::columnNames::sysInsTime, + RelationalGlobalTagTable::columnTypeIds::sysInsTime ); + } + return spec; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalGlobalTagTable.h b/RelationalCool/src/RelationalGlobalTagTable.h new file mode 100644 index 000000000..cfe8242de --- /dev/null +++ b/RelationalCool/src/RelationalGlobalTagTable.h @@ -0,0 +1,78 @@ +// $Id: RelationalGlobalTagTable.h,v 1.19 2007-02-16 16:06:23 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALGLOBALTAGTABLE_H +#define RELATIONALCOOL_RELATIONALGLOBALTAGTABLE_H + +// Include files +#include "CoolKernel/StorageType.h" + +// Local include files +#include "uppercaseString.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalGlobalTagTable RelationalGlobalTagTable.h + * + * Relational schema of the table storing COOL global tags. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2005-03-01 + */ + + namespace RelationalGlobalTagTable { + + inline const std::string defaultTableName( const std::string& prefix ) + { + return uppercaseString(prefix) + "TAGS"; + } + + namespace columnNames + { + static const std::string nodeId = "NODE_ID"; + static const std::string tagId = "TAG_ID"; + static const std::string tagName = "TAG_NAME"; + static const std::string tagLockStatus = "TAG_LOCK_STATUS"; + static const std::string tagDescription = "TAG_DESCRIPTION"; + // *** START *** 3.0.0 schema extensions (task #4396) + // Tag type (NOT NULL): 0(unknown), 1(head), 2(user) + static const std::string tagType = "TAG_TYPE"; + // **** END **** 3.0.0 schema extensions (task #4396) + static const std::string sysInsTime = "SYS_INSTIME"; + } + + namespace columnTypeIds + { + static const StorageType::TypeId nodeId = StorageType::UInt32; + static const StorageType::TypeId tagId = StorageType::UInt32; + static const StorageType::TypeId tagName = StorageType::String255; + static const StorageType::TypeId tagLockStatus = StorageType::UInt16; + static const StorageType::TypeId tagDescription = StorageType::String255; + // *** START *** 3.0.0 schema extensions (task #4396) + static const StorageType::TypeId tagType = StorageType::UInt16; + // **** END **** 3.0.0 schema extensions (task #4396) + static const StorageType::TypeId sysInsTime = StorageType::String255; + } + + namespace columnTypes + { + typedef UInt32 nodeId; + typedef UInt32 tagId; + typedef String255 tagName; + typedef UInt16 tagLockStatus; + typedef String255 tagDescription; + // *** START *** 3.0.0 schema extensions (task #4396) + typedef UInt16 tagType; + // **** END **** 3.0.0 schema extensions (task #4396) + typedef String255 sysInsTime; + } + + /// Get the record specification of the global tag table + const IRecordSpecification& tableSpecification(); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALGLOBALTAGTABLE_H diff --git a/RelationalCool/src/RelationalGlobalUserTagTable.cpp b/RelationalCool/src/RelationalGlobalUserTagTable.cpp new file mode 100644 index 000000000..97bd08068 --- /dev/null +++ b/RelationalCool/src/RelationalGlobalUserTagTable.cpp @@ -0,0 +1,29 @@ +// $Id: RelationalGlobalUserTagTable.cpp,v 1.2 2007-02-16 14:54:18 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalGlobalUserTagTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalGlobalUserTagTable::tableSpecification() +{ + static RecordSpecification spec; + + if ( spec.size() == 0 ) + { + spec.extend( RelationalGlobalUserTagTable::columnNames::nodeId, + RelationalGlobalUserTagTable::columnTypeIds::nodeId ); + spec.extend( RelationalGlobalUserTagTable::columnNames::tagId, + RelationalGlobalUserTagTable::columnTypeIds::tagId ); + spec.extend( RelationalGlobalUserTagTable::columnNames::tagType, + RelationalGlobalUserTagTable::columnTypeIds::tagType ); + } + return spec; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalGlobalUserTagTable.h b/RelationalCool/src/RelationalGlobalUserTagTable.h new file mode 100644 index 000000000..7a6e20cfe --- /dev/null +++ b/RelationalCool/src/RelationalGlobalUserTagTable.h @@ -0,0 +1,61 @@ +// $Id: RelationalGlobalUserTagTable.h,v 1.4 2007-02-16 14:59:48 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALGLOBALUSERTAGTABLE_H +#define RELATIONALCOOL_RELATIONALGLOBALUSERTAGTABLE_H + +// Include files +#include "CoolKernel/StorageType.h" + +// Local include files +#include "uppercaseString.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalGlobalUserTagTable RelationalGlobalUserTagTable.h + * + * Relational schema of the table storing COOL global user tags. + * + * @author Andrea Valassi + * @date 2007-02-15 + */ + + namespace RelationalGlobalUserTagTable { + + inline const std::string defaultTableName( const std::string& prefix ) + { + return uppercaseString(prefix) + "USERTAGS"; + } + + namespace columnNames + { + static const std::string nodeId = "NODE_ID"; + static const std::string tagId = "TAG_ID"; + // Tag type (NOT NULL): 0(unknown), 1(head), 2(user) + // Tag type must be equal to 2 (CHECK constraint) for the user tag table + static const std::string tagType = "TAG_TYPE"; + } + + namespace columnTypeIds + { + static const StorageType::TypeId nodeId = StorageType::UInt32; + static const StorageType::TypeId tagId = StorageType::UInt32; + static const StorageType::TypeId tagType = StorageType::UInt16; + } + + namespace columnTypes + { + typedef UInt32 nodeId; + typedef UInt32 tagId; + typedef UInt16 tagType; + } + + /// Get the record specification of the global user tag table + const IRecordSpecification& tableSpecification(); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALGLOBALUSERTAGTABLE_H diff --git a/RelationalCool/src/RelationalHvsNode.cpp b/RelationalCool/src/RelationalHvsNode.cpp new file mode 100644 index 000000000..9673244ca --- /dev/null +++ b/RelationalCool/src/RelationalHvsNode.cpp @@ -0,0 +1,170 @@ +// $Id: RelationalHvsNode.cpp,v 1.35 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +//#include "CoolKernel/HvsTagRecord.h" +#include "HvsTagRecord.h" +#include "CoralBase/Attribute.h" + +// Local include files +//#include "IRelationalTransactionMgr.h" +#include "RelationalDatabase.h" +#include "RelationalGlobalTagTable.h" +#include "RelationalHvsNode.h" +#include "RelationalTableRow.h" +#include "RelationalTagMgr.h" +#include "RelationalTransaction.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalHvsNode::RelationalHvsNode +( const RelationalDatabasePtr& db, + const coral::AttributeList& nodeTableRow ) + : RelationalHvsNodeRecord( nodeTableRow ) + , m_db( db ) +{ +} + +//----------------------------------------------------------------------------- + +RelationalHvsNode::~RelationalHvsNode() +{ +} + +//----------------------------------------------------------------------------- + +void RelationalHvsNode::setDescription( const std::string& description ) +{ + db().updateNodeTableDescription( fullPath(), description ); + RelationalHvsNodeRecord::setDescription( description ); +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> RelationalHvsNode::listTags() const +{ + //return db().listTags( this ); + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + std::vector<std::string> tags; + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + std::vector<RelationalTableRow> rows = + db().tagMgr().fetchGlobalTagTableRows( id() ); + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + std::string tagName = + (*row)[RelationalGlobalTagTable::columnNames::tagName] + .data<std::string>(); + tags.push_back( tagName ); + } + transaction.commit(); + return tags; +} + +//----------------------------------------------------------------------------- + +const Time +RelationalHvsNode::tagInsertionTime( const std::string& tagName ) const +{ + return db().tagMgr().tagInsertionTime( this, tagName ); +} + +//----------------------------------------------------------------------------- + +void +RelationalHvsNode::setTagDescription( const std::string& tagName, + const std::string& description ) +{ + return db().tagMgr().setTagDescription( this, tagName, description ); +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalHvsNode::tagDescription( const std::string& tagName ) const +{ + return db().tagMgr().tagDescription( this, tagName ); +} + +//----------------------------------------------------------------------------- + +void +RelationalHvsNode::setTagLockStatus( const std::string& tagName, + HvsTagLock::Status tagLockStatus ) +{ + return db().tagMgr().setTagLockStatus( this, tagName, tagLockStatus ); +} + +//----------------------------------------------------------------------------- + +HvsTagLock::Status +RelationalHvsNode::tagLockStatus( const std::string& tagName ) const +{ + return db().tagMgr().tagLockStatus( this, tagName ); +} + +//----------------------------------------------------------------------------- + +void +RelationalHvsNode::createTagRelation( const std::string& parentTagName, + const std::string& tagName ) const +{ + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalHvsNode" ); + RelationalTransaction transaction( db().transactionMgr(), false ); // r/w + db().tagMgr().createTagRelation( parentId(), parentTagName, id(), tagName ); + transaction.commit(); +} + +//----------------------------------------------------------------------------- + +void +RelationalHvsNode::deleteTagRelation( const std::string& parentTagName ) const +{ + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalHvsNode" ); + RelationalTransaction transaction( db().transactionMgr(), false ); // r/w + // TEMPORARY - START + //db().tagMgr().deleteTagRelation( parentId(), parentTagName, id() ); + db().tagMgr().deleteTagRelation( *this, parentTagName ); + // TEMPORARY - END + transaction.commit(); +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalHvsNode::findTagRelation( const std::string& parentTagName ) const +{ + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalHvsNode" ); + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + UInt32 tagId = + db().tagMgr().findTagRelation( parentId(), parentTagName, id() ); + std::string tag = db().tagMgr().__findTagRecord( id(), tagId ).name(); + transaction.commit(); + return tag; +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalHvsNode::resolveTag( const std::string& ancestorTagName ) const +{ + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalHvsNode" ); + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + UInt32 tagId = + db().tagMgr().resolveTag( ancestorTagName, id() ); + std::string tag = db().tagMgr().__findTagRecord( id(), tagId ).name(); + transaction.commit(); + return tag; +} + +//----------------------------------------------------------------------------- +/* +bool +RelationalHvsNode::isTagUsed( UInt32 tagId ) const +{ + // Is the tag referenced in the TAG2TAG table? + return db().tagMgr().existsTagInTag2TagTable( id(), tagId ); +} +*/ +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalHvsNode.h b/RelationalCool/src/RelationalHvsNode.h new file mode 100644 index 000000000..3dd401df2 --- /dev/null +++ b/RelationalCool/src/RelationalHvsNode.h @@ -0,0 +1,156 @@ +// $Id: RelationalHvsNode.h,v 1.30 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALHVSNODE_H +#define RELATIONALCOOL_RELATIONALHVSNODE_H + +// Disable warning C4250 on Windows (inheritance via dominance) +// Copied from SEAL (Dictionary/Reflection/src/Tools.h) +#ifdef WIN32 +#pragma warning ( disable : 4250 ) +#endif + +// Include files +#include "CoolKernel/IHvsNode.h" + +// Local include files +#include "RelationalDatabasePtr.h" +#include "RelationalHvsNodeRecord.h" + +namespace cool { + + /** @class RelationalHvsNode RelationalHvsNode.h + * + * Relational implementation of one node in an HVS node tree. + * Multiple virtual inheritance from IHvsNode and RelationalHvsNodeRecord + * (diamond virtual inheritance of IHvsNodeRecord abstract interface). + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2004-12-10 + */ + + class RelationalHvsNode : virtual public IHvsNode, + virtual public RelationalHvsNodeRecord { + + public: + + /// Destructor + virtual ~RelationalHvsNode(); + + /// Set the node description + void setDescription( const std::string& description ); + + /// Lists all tags defined for this node (ordered alphabetically) + const std::vector<std::string> listTags() const; + + /// Insertion time of a tag defined for this node + /// (i.e. the time when the tag was first assigned to this node) + const Time tagInsertionTime( const std::string& tagName ) const; + + /// Set the description of a tag. + /// Throws TagNotFound the tag does not exist. + /// Throws an Exception if the description is longer than 255 characters. + void setTagDescription( const std::string& tagName, + const std::string& description ); + + /// Description of a tag defined for this node + const std::string tagDescription( const std::string& tagName ) const; + + /// Set the persistent lock status of a tag defined for this node. + void setTagLockStatus( const std::string& tagName, + HvsTagLock::Status tagLockStatus ); + + /// Get the persistent lock status of a tag defined for this node. + HvsTagLock::Status tagLockStatus( const std::string& tagName ) const; + + /// Create a relation between a parent node tag and a tag in this node. + /// Create the parent node tag if not defined yet. + /// Create the tag in this node if not defined yet. + /// Throws ReservedHeadTag if one of the two tags is a HEAD tag. + /// Throws NodeIsSingleVersion if either node does not support versioning. + /// Throws TagExists if either tag is already used in another node. + /// Throws TagRelationExists if a relation to a child tag already exists. + void createTagRelation( const std::string& parentTagName, + const std::string& tagName ) const; + + /// Delete the relation between a parent tag node and a tag in this node. + /// Delete the parent tag if not related to another parent/child tag. + /// Delete the tag in this node if not related to another tag or IOVs. + /// Throws TagNotFound if the parent tag does not exist in the parent node. + /// Throws TagRelationNotFound if the parent tag has no related child tag. + void deleteTagRelation( const std::string& parentTagName ) const; + + /// Show the tag in this node associated to the given parent node tag. + /// Throws ReservedHeadTag if the parent tag is a HEAD tag. + /// Throws TagNotFound if the parent tag does not exist in the parent node. + /// Throws TagRelationNotFound if the parent tag has no related child tag. + const std::string + findTagRelation( const std::string& parentTagName ) const; + + /// Main HVS method: determine the tag in this node that is related to the + /// given ancestor tag (assumed to be defined in an ancestor of this node). + /// The corresponding ancestor node is also internally determined. + /// The ancestor tag is returned if defined directly in the descendant. + /// Throws ReservedHeadTag if the ancestor tag is a HEAD tag. + /// Throws TagNotFound if the tag does not exist in any inner node. + /// Throws NodeRelationNotFound if the inner node where the ancestor tag + /// is defined is not an ancestor of the descendant node. + /// Throws TagRelationNotFound if no hierarchical tag relation exists. + const std::string resolveTag( const std::string& ancestorTagName ) const; + + /* + /// Does this tag exist in this node (independently of whether + /// it references a parent tag or is referenced by any children)? + /// Throws ReservedHeadTag if this is the HEAD tag. + bool existsTag( const std::string& tagName ) const; + + /// Does this tag defined in this node have any relation (i.e. does + /// it reference a parent tag or is it referenced by any children)? + /// Throws ReservedHeadTag if this is the HEAD tag. + /// Throws TagNotFound if this tag does not exist in this node. + bool isTagUsed( const std::string& tagName ) const; + */ + + /* + /// Does this tag defined in this node have any relation (i.e. does + /// it reference a parent tag or is it referenced by any children)? + /// Returns false if this tag does not exist in this node. + bool isTagUsed( UInt32 tagId ) const; + */ + + /// Get a RelationalDatabase reference + const RelationalDatabase& db() const { return *m_db; } + + protected: + + /// Constructor from a relational row retrieved from persistent storage + /// This constructor is protected, hence no need to inline with base class + /// non-standard constructors to prevent Windows compilation error C2248 + RelationalHvsNode( const RelationalDatabasePtr& db, + const coral::AttributeList& nodeTableRow ); + + /* + /// Constructor from a RelationalHvsNodeRecord + RelationalHvsNode( const RelationalDatabasePtr& db, + const RelationalHvsNodeRecord& nodeRecord ); + */ + + private: + + /// Standard constructor is private + RelationalHvsNode(); + + /// Copy constructor is private + RelationalHvsNode( const RelationalHvsNode& rhs ); + + /// Assignment operator is private + RelationalHvsNode& operator=( const RelationalHvsNode& rhs ); + + private: + + /// Backward pointer to the parent RelationalDatabase + RelationalDatabasePtr m_db; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALHVSNODE_H diff --git a/RelationalCool/src/RelationalHvsNodeRecord.cpp b/RelationalCool/src/RelationalHvsNodeRecord.cpp new file mode 100644 index 000000000..a2e8b7148 --- /dev/null +++ b/RelationalCool/src/RelationalHvsNodeRecord.cpp @@ -0,0 +1,116 @@ +// $Id: RelationalHvsNodeRecord.cpp,v 1.6 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoralBase/Attribute.h" + +// Local include files +#include "HvsPathHandler.h" +#include "RelationalHvsNodeRecord.h" +#include "RelationalNodeTable.h" +#include "timeToString.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalHvsNodeRecord::RelationalHvsNodeRecord +( const coral::AttributeList& row ) + : m_schemaVersion( row[RelationalNodeTable::columnNames::nodeSchemaVersion] + .data<std::string>() ) + , m_nodeAttributes() +{ + // TODO: use COOL typedefs instead of explicit <T> like <std::string>... + + m_id = row[RelationalNodeTable::columnNames::nodeId] + .data<unsigned int>(); + + m_fullPath = row[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + + // TEMPORARY! CHECK IF nodeId==0 TO ASSUME ROOT FOLDER SET + // EVENTUALLY: fetch METHODS SHOULD RETURN LIST OF NULL ATTRIBUTES + HvsPathHandler handler; + if( m_fullPath == handler.rootFullPath() ) { + m_parentId = m_id; + } else { + m_parentId = row[RelationalNodeTable::columnNames::nodeParentId] + .data<unsigned int>(); + } + + m_description = row[RelationalNodeTable::columnNames::nodeDescription] + .data<std::string>(); + + m_isLeaf = row[RelationalNodeTable::columnNames::nodeIsLeaf] + .data<bool>(); + + // No default constructor for VersionNumber + //m_schemaVersion = row[RelationalNodeTable::columnNames::nodeSchemaVersion] + // .data<std::string>(); + + std::string time = row[RelationalNodeTable::columnNames::nodeInsertionTime] + .data<std::string>(); + m_insertionTime = stringToTime( time ); +} + +//----------------------------------------------------------------------------- + +const std::string& RelationalHvsNodeRecord::fullPath() const +{ + return m_fullPath; +} + +//----------------------------------------------------------------------------- + +const std::string& RelationalHvsNodeRecord::description() const +{ + return m_description; +} + +//----------------------------------------------------------------------------- + +bool RelationalHvsNodeRecord::isLeaf() const +{ + return m_isLeaf; +} + +//----------------------------------------------------------------------------- + +const VersionNumber& RelationalHvsNodeRecord::schemaVersion() const +{ + return m_schemaVersion; +} + +//----------------------------------------------------------------------------- + +const ITime& RelationalHvsNodeRecord::insertionTime() const +{ + return m_insertionTime; +} + +//----------------------------------------------------------------------------- + +unsigned int RelationalHvsNodeRecord::id() const +{ + return m_id; +} + +//----------------------------------------------------------------------------- + +unsigned int RelationalHvsNodeRecord::parentId() const +{ + return m_parentId; +} + +//----------------------------------------------------------------------------- + +const IRecord& RelationalHvsNodeRecord::nodeAttributes() const +{ + /// Avoid link time error: 'liblcg_RelationalCool.so: undefined reference to + /// `virtual thunk to cool::RelationalHvsNodeRecord::nodeAttributes() const' + ///return (const IRecord&)m_nodeAttributes; + const Record& attr = m_nodeAttributes; + return attr; +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalHvsNodeRecord.h b/RelationalCool/src/RelationalHvsNodeRecord.h new file mode 100644 index 000000000..9f3b1fe6d --- /dev/null +++ b/RelationalCool/src/RelationalHvsNodeRecord.h @@ -0,0 +1,115 @@ +// $Id: RelationalHvsNodeRecord.h,v 1.7 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALHVSNODERECORD_H +#define RELATIONALCOOL_RELATIONALHVSNODERECORD_H + +// Include files +#include "CoolKernel/Record.h" +#include "CoolKernel/Time.h" +#include "CoolKernel/IHvsNodeRecord.h" + +// Local include files +#include "VersionNumber.h" + +namespace cool { + + /** @class RelationalHvsNodeRecord RelationalHvsNodeRecord.h + * + * Relational read-only implementation of one node in an HVS node tree. + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2004-12-10 + */ + + class RelationalHvsNodeRecord : virtual public IHvsNodeRecord { + + public: + + /// Destructor + virtual ~RelationalHvsNodeRecord() {} + + /// Node full path name in the HVS hierarchy + /// (this is always unique within a database) + const std::string& fullPath() const; + + /// Node description + const std::string& description() const; + + /// Is this a leaf node? + bool isLeaf() const; + + /// Has this node been stored into the database? + bool isStored() const { return true; } + + /// Schema version for this node + const VersionNumber& schemaVersion() const; + + /// Insertion time into the database + /// Throws an exception if the node has not been stored yet + const ITime& insertionTime() const; + + /// System-assigned node ID + /// Throws an exception if the node has not been stored yet + unsigned int id() const; + + /// System-assigned ID of the parent node + /// Throws an exception if the node has not been stored yet + /// Convention: parentId() = id() if the node has no parent (root node) + unsigned int parentId() const; + + protected: + + /// Return additional 'attributes' of the HVS node + /// (implementation-specific attributes not exposed in the API) + const IRecord& nodeAttributes() const; + + /// Constructor from a relational row retrieved from persistent storage + RelationalHvsNodeRecord( const coral::AttributeList& nodeTableRow ); + + /// Change the node description + void setDescription( const std::string& description ) + { + m_description = description; + } + + private: + + /// Standard constructor is private + RelationalHvsNodeRecord(); + + /// Copy constructor is private + RelationalHvsNodeRecord( const RelationalHvsNodeRecord& rhs ); + + /// Assignment operator is private + RelationalHvsNodeRecord& operator=( const RelationalHvsNodeRecord& rhs ); + + private: + + /// System-assigned node ID + unsigned int m_id; + + /// System-assigned ID of the parent node + unsigned int m_parentId; + + /// Node full path name in the HVS hierarchy + std::string m_fullPath; + + /// Node description + std::string m_description; + + /// Is this a leaf node? + bool m_isLeaf; + + /// Schema version for this node + VersionNumber m_schemaVersion; + + /// Insertion time into the database + Time m_insertionTime; + + /// Additional implementation-specific 'attributes' of the HVS node + Record m_nodeAttributes; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALHVSNODERECORD_H diff --git a/RelationalCool/src/RelationalHvsTagRecord.cpp b/RelationalCool/src/RelationalHvsTagRecord.cpp new file mode 100644 index 000000000..d65f1d721 --- /dev/null +++ b/RelationalCool/src/RelationalHvsTagRecord.cpp @@ -0,0 +1,93 @@ +// $Id: RelationalHvsTagRecord.cpp,v 1.12 2007-03-20 19:03:43 avalassi Exp $ + +// Include files +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeList.h" + +// Local include files +#include "RelationalHvsTagRecord.h" +#include "RelationalGlobalTagTable.h" +#include "timeToString.h" + +// TEMPORARY - debug unknown exception on Windows +//#include <iostream> + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +const HvsTagRecord +RelationalHvsTagRecord::fromRow( const coral::AttributeList& row ) +{ + //std::cout << "*** RelationalHvsTagRecord::fromRow - START" << std::endl; + + try { + + //std::cout << "*** Windows will throw UNKNOWN exception?" << std::endl; + // AV - The following line throws an unknown exception on Windows + // [only if fromRow is called from the RelationalHvsTagRecord constructor] + //std::cout << "*** RelationalHvsTagRecord::fromRow - input AL size: " + // << row.size() << std::endl; + //std::cout << "*** Windows has thrown UNKNOWN exception?" << std::endl; + + //std::stringstream msg; + //row.toOutputStream( msg ); + + //std::cout << "*** RelationalHvsTagRecord::fromRow - input AL: " + // << msg.str() << std::endl; + + UInt32 id = + row[RelationalGlobalTagTable::columnNames::tagId].data<UInt32>(); + + UInt32 nodeId = + row[RelationalGlobalTagTable::columnNames::nodeId].data<UInt32>(); + + std::string name = + row[RelationalGlobalTagTable::columnNames::tagName].data<std::string>(); + + HvsTagLock::Status lockStatus = + HvsTagLock::Status + ( row[RelationalGlobalTagTable::columnNames::tagLockStatus] + .data<UInt16>() ); + + std::string description = + row[RelationalGlobalTagTable::columnNames::tagDescription] + .data<std::string>(); + + std::string time = + row[RelationalGlobalTagTable::columnNames::sysInsTime] + .data<std::string>(); + Time insertionTime = stringToTime( time ); + + //std::cout << "*** RelationalHvsTagRecord::fromRow - END" << std::endl; + + return HvsTagRecord + ( id, nodeId, name, lockStatus, description, insertionTime ); + + } catch ( std::exception& /*e*/ ) { + //std::cout << "*** PANIC! RelationalHvsTagRecord::fromRow - " + // << "Exception caught: " << e.what() << std::endl; + throw; + } catch ( ... ) { + std::cout << "*** PANIC! RelationalHvsTagRecord::fromRow - " + << "UNKNOWN exception caught" << std::endl; + throw; + } +} + +//----------------------------------------------------------------------------- +/* +const coral::AttributeList& RelationalHvsTagRecord::tagAttributes() const +{ + return m_tagAttributes; +} +*/ +//----------------------------------------------------------------------------- +/* +void RelationalHvsTagRecord::setDescription( const std::string& description ) +{ + m_description = description; +} +*/ +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalHvsTagRecord.h b/RelationalCool/src/RelationalHvsTagRecord.h new file mode 100644 index 000000000..5bdebd439 --- /dev/null +++ b/RelationalCool/src/RelationalHvsTagRecord.h @@ -0,0 +1,79 @@ +// $Id: RelationalHvsTagRecord.h,v 1.14 2007-07-05 11:50:02 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALHVSTAGRECORD_H +#define RELATIONALCOOL_RELATIONALHVSTAGRECORD_H + +// Include files +//#include "CoolKernel/HvsTagRecord.h" +#include "HvsTagRecord.h" + +namespace cool { + + /** @class RelationalHvsTagRecord RelationalHvsTagRecord.h + * + * Relational read-only implementation of one tag in an HVS tag tree + * (i.e. transient representation of one row in the HVS tag table). + * + * @author Andrea Valassi + * @date 2006-03-07 + */ + + class RelationalHvsTagRecord : public HvsTagRecord { + + public: + + /// Reinterpret a relational row retrieved from persistent storage + static const HvsTagRecord fromRow( const coral::AttributeList& tableRow ); + + /// Destructor + virtual ~RelationalHvsTagRecord() {} + + /// AV - This throws an unknown exception within fromRow on Windows + /// [as soon as the tableRow AL argument is accessed within fromRow] + /// Constructor from a relational row retrieved from persistent storage + /* + RelationalHvsTagRecord( const coral::AttributeList& tableRow ) + : HvsTagRecord( fromRow( tableRow ) ) {} + */ + + /// Copy constructor + /// AV - Added IHvsTagRecord to avoid gcc344 warning on copy constructor + /// AV - To be tested: would this solve the unknown Windows exception??? + RelationalHvsTagRecord( const RelationalHvsTagRecord& rhs ) + : HvsTagRecord( rhs ) {} + + /// AV - The following is a workaround (WHY???) + /// Constructor from an HvsTagRecord + RelationalHvsTagRecord( const HvsTagRecord& rhs ) + : HvsTagRecord( rhs ) {} + + /* + /// Return additional 'attributes' of the HVS tag + /// (implementation-specific attributes not exposed in the API) + const coral::AttributeList& tagAttributes() const; + */ + + /* + /// Change the tag description (transient - no persistent change!) + void setDescription( const std::string& description ); + */ + + private: + + /// Standard constructor is private + RelationalHvsTagRecord(); + + /// Assignment operator is private + RelationalHvsTagRecord& operator=( const RelationalHvsTagRecord& rhs ); + + private: + + /* + /// Additional implementation-specific 'attributes' of the HVS tag + coral::AttributeList m_tagAttributes; + */ + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALHVSTAGRECORD_H diff --git a/RelationalCool/src/RelationalIovSharedSequenceTable.h b/RelationalCool/src/RelationalIovSharedSequenceTable.h new file mode 100644 index 000000000..704486797 --- /dev/null +++ b/RelationalCool/src/RelationalIovSharedSequenceTable.h @@ -0,0 +1,30 @@ +// $Id: RelationalIovSharedSequenceTable.h,v 1.1 2007-02-01 00:28:33 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALIOVSHAREDSEQUENCETABLE_H +#define RELATIONALCOOL_RELATIONALIOVSHAREDSEQUENCETABLE_H + +// Local include files +#include "uppercaseString.h" + +namespace cool { + + /** @namespace cool::RelationalIovSharedSequenceTable RelationalIovSharedSequenceTable.h + * + * Relational schema of the shared 'sequence table' for IOV PKs. + * + * @author Andrea Valassi + * @date 2007-01-31 + */ + + namespace RelationalIovSharedSequenceTable + { + + inline const std::string defaultTableName( const std::string& prefix ) + { + // Note: presently the input prefix is uppercase anyway... + return uppercaseString(prefix) + "IOVS_SEQ"; + } + + } + +} +#endif // RELATIONALCOOL_RELATIONALIOVSHAREDSEQUENCETABLE_H diff --git a/RelationalCool/src/RelationalIovTablesTable.cpp b/RelationalCool/src/RelationalIovTablesTable.cpp new file mode 100644 index 000000000..da7dbf0e2 --- /dev/null +++ b/RelationalCool/src/RelationalIovTablesTable.cpp @@ -0,0 +1,44 @@ +// $Id: RelationalIovTablesTable.cpp,v 1.1 2007-02-15 14:37:43 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalIovTablesTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalIovTablesTable::tableSpecification() +{ + static RecordSpecification spec; + + if ( spec.size() == 0 ) + { + spec.extend + ( RelationalIovTablesTable::columnNames::iovTableName, + RelationalIovTablesTable::columnTypeIds::iovTableName ); + spec.extend + ( RelationalIovTablesTable::columnNames::iovTableSchemaVersion, + RelationalIovTablesTable::columnTypeIds::iovTableSchemaVersion ); + spec.extend + ( RelationalIovTablesTable::columnNames::iovTableVersioningMode, + RelationalIovTablesTable::columnTypeIds::iovTableVersioningMode ); + spec.extend + ( RelationalIovTablesTable::columnNames::iovTableInsertionTime, + RelationalIovTablesTable::columnTypeIds::iovTableInsertionTime ); + spec.extend + ( RelationalIovTablesTable::columnNames::payloadSpecDesc, + RelationalIovTablesTable::columnTypeIds::payloadSpecDesc ); + spec.extend + ( RelationalIovTablesTable::columnNames::payloadInline, + RelationalIovTablesTable::columnTypeIds::payloadInline ); + spec.extend + ( RelationalIovTablesTable::columnNames::payloadExtRef, + RelationalIovTablesTable::columnTypeIds::payloadExtRef ); + } + return spec; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalIovTablesTable.h b/RelationalCool/src/RelationalIovTablesTable.h new file mode 100644 index 000000000..bc8f2648c --- /dev/null +++ b/RelationalCool/src/RelationalIovTablesTable.h @@ -0,0 +1,87 @@ +// $Id: RelationalIovTablesTable.h,v 1.1 2007-02-15 14:37:43 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALIOVTABLESTABLE_H +#define RELATIONALCOOL_RELATIONALIOVTABLESTABLE_H 1 + +// Include files +#include "CoolKernel/StorageType.h" + +// Local include files +#include "VersionNumber.h" +#include "uppercaseString.h" + +namespace cool +{ + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalIovTablesTable RelationalIovTablesTable.h + * + * Relational schema of the table storing metadata of COOL IOV tables. + * + * @author Andrea Valassi + * @date 2007-02-15 + */ + + namespace RelationalIovTablesTable { + + inline const std::string defaultTableName( const std::string& prefix ) + { + return uppercaseString(prefix) + "IOVTABLES"; + } + + namespace columnNames + { + static const + std::string iovTableName = "IOVTABLE_NAME"; + static const + std::string iovTableSchemaVersion = "IOVTABLE_SCHEMA_VERSION"; + static const + std::string iovTableVersioningMode = "IOVTABLE_VERSIONING"; + static const + std::string iovTableInsertionTime = "IOVTABLE_INSTIME"; + static const + std::string payloadSpecDesc = "PAYLOAD_SPEC"; + static const + std::string payloadInline = "PAYLOAD_INLINE"; + static const + std::string payloadExtRef = "PAYLOAD_EXTREF"; + } + + namespace columnTypeIds + { + static const + StorageType::TypeId iovTableName = StorageType::String255; + static const + StorageType::TypeId iovTableSchemaVersion = StorageType::String255; + static const + StorageType::TypeId iovTableVersioningMode = StorageType::Int32; + static const + StorageType::TypeId iovTableInsertionTime = StorageType::String255; + static const + StorageType::TypeId payloadSpecDesc = StorageType::String64k; + static const + StorageType::TypeId payloadInline = StorageType::UInt16; + static const + StorageType::TypeId payloadExtRef = StorageType::String64k; + } + + namespace columnTypes + { + typedef String255 iovTableName; + typedef String255 iovTableSchemaVersion; + typedef Int32 iovTableVersioningMode; + typedef String255 iovTableInsertionTime; + typedef String64k payloadSpecDesc; + typedef UInt16 payloadInline; + typedef String64k payloadExtRef; + } + + /// Get the record specification of the iovTables table. + const IRecordSpecification& tableSpecification(); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALIOVTABLESTABLE_H diff --git a/RelationalCool/src/RelationalNodeMgr.cpp b/RelationalCool/src/RelationalNodeMgr.cpp new file mode 100644 index 000000000..b99899b71 --- /dev/null +++ b/RelationalCool/src/RelationalNodeMgr.cpp @@ -0,0 +1,324 @@ +// $Id: RelationalNodeMgr.cpp,v 1.22 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoralBase/Attribute.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalDatabase.h" +#include "RelationalException.h" +#include "RelationalNodeMgr.h" +#include "RelationalNodeTable.h" +#include "RelationalQueryMgr.h" +#include "RelationalTableRow.h" +#include "RelationalTransaction.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalNodeMgr::RelationalNodeMgr( const RelationalDatabase& aDb ) + : m_db( aDb ) + , m_log( new coral::MessageStream( "RelationalNodeMgr" ) ) +{ + log() << coral::Debug << "Instantiate a RelationalNodeMgr" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalNodeMgr::~RelationalNodeMgr() +{ + log() << coral::Debug << "Delete the RelationalNodeMgr" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalQueryMgr& RelationalNodeMgr::queryMgr() const +{ + return db().queryMgr(); +} + +//----------------------------------------------------------------------------- + +bool RelationalNodeMgr::existsNode( const std::string& fullPath ) +{ + // Transaction handled in the outer scope + try { + fetchNodeTableRow( fullPath ); + return true; + } catch ( NodeTableRowNotFound& ) { + return false; + } +} + +//----------------------------------------------------------------------------- + +bool RelationalNodeMgr::existsFolderSet( const std::string& fullPath ) +{ + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalTagMgr" ); + + try { + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + RelationalTableRow row = fetchNodeTableRow( fullPath ); + bool isLeaf = + row[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + transaction.commit(); + return (!isLeaf); + } catch ( NodeTableRowNotFound& ) { + return false; + } +} + +//----------------------------------------------------------------------------- + +bool RelationalNodeMgr::existsFolder( const std::string& fullPath ) +{ + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalTagMgr" ); + + try { + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + RelationalTableRow row = fetchNodeTableRow( fullPath ); + bool isLeaf = + row[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + transaction.commit(); + return isLeaf; + } catch ( NodeTableRowNotFound& ) { + return false; + } +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> +RelationalNodeMgr::listNodes( unsigned int nodeId, + bool isLeaf, + bool ascending ) +{ + // Transaction handled in the outer scope + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + + // Define the WHERE clause for the selection using bind variables + // NB: Oracle execution plan -- still to be tested + RecordSpecification spec; + spec.extend("parentId", RelationalNodeTable::columnTypeIds::nodeParentId); + spec.extend("isLeaf", RelationalNodeTable::columnTypeIds::nodeIsLeaf); + coral::AttributeList whereData = Record( spec ).attributeList(); + whereData["parentId"].setValue( nodeId ); + whereData["isLeaf"].setValue( isLeaf ); + std::string whereClause = RelationalNodeTable::columnNames::nodeParentId; + whereClause += "= :parentId"; + whereClause += " and "; + whereClause += RelationalNodeTable::columnNames::nodeIsLeaf; + whereClause += "= :isLeaf"; + + /// Define the ORDER BY clause for the selection + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeFullPath; + if ( ascending ) orderClause += " ASC"; + else orderClause += " DESC"; + orderBy.push_back( orderClause ); + + // Delegate the query to the RalQueryMgr + std::string desc = ""; + std::vector<RelationalTableRow> rows = + queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db().nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + // Loop over all rows and copy folder names into a string vector + std::vector<std::string> folderList; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + std::string fullPath = + (*row)[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + folderList.push_back( fullPath ); + } + return folderList; +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> +RelationalNodeMgr::listAllNodes( bool ascending ) +{ + // Loop over all rows and copy folder names into a string vector + std::vector<RelationalTableRow> rows = + fetchAllNodeTableRows( ascending ); + std::vector<std::string> folderList; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + std::string fullPath = + (*row)[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + folderList.push_back( fullPath ); + } + + // Return the list of folders + return folderList; +} + +//----------------------------------------------------------------------------- + +const std::vector<RelationalTableRow> +RelationalNodeMgr::fetchAllNodeTableRows( bool ascending ) const +{ + log() << "Fetch all nodes in the database" << coral::MessageStream::endmsg; + + // Transaction handled in the outer scope + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalDatabase" ); + + // Define the WHERE clause for the selection - empty! + coral::AttributeList whereData; + std::string whereClause = ""; + + // Define the ORDER BY clause for the selection + // NB: Oracle execution plan, from interactive Benthic test, uses + // => ASCENDING: fast access via the 1D primary key index on nodeId + // (SELECT STATEMENT, TABLE ACCESS BY INDEX ROWID, INDEX FULL SCAN) + // => DESCENDING: ? + // NB: the above applies to previous ordering by nodeId + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeFullPath; + if ( ascending ) orderClause += " ASC"; + else orderClause += " DESC"; + orderBy.push_back( orderClause ); + + // Delegate the query to the RalQueryMgr + std::string desc = ""; + std::vector<RelationalTableRow> rows = + queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db().nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + // Return the list of folders + return rows; +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalNodeMgr::fetchNodeTableRow( const std::string& fullPath ) const +{ + log() << "Fetch table row for folder[set] with fullPath=" + << fullPath << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + // NB: Oracle execution plan, from interactive Benthic test, uses + // fast access via the 1D index on fullPath + // (SELECT STATEMENT, TABLE ACCESS BY INDEX ROWID, INDEX RANGE SCAN) + coral::AttributeList whereData; + whereData.extend + ( "fullName", + typeIdToCoralType(RelationalNodeTable::columnTypeIds::nodeFullPath) ); + whereData["fullName"].setValue( fullPath ); + std::string whereClause = RelationalNodeTable::columnNames::nodeFullPath; + whereClause += "= :fullName"; + + // Execute the query + try { + return fetchNodeTableRow( whereClause, whereData ); + } catch( NodeTableRowNotFound& /* dummy */ ) { + throw NodeTableRowNotFound( fullPath, "RelationalNodeMgr" ); + } +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalNodeMgr::fetchNodeTableRow( unsigned int nodeId ) const +{ + log() << "Fetch table row for folder[set] with nodeId=" + << nodeId << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + // NB: Oracle execution plan -- still to be tested + coral::AttributeList whereData; + whereData.extend + ( "nodeId", typeIdToCoralType(RelationalNodeTable::columnTypeIds::nodeId) ); + whereData["nodeId"].setValue( nodeId ); + std::string whereClause = RelationalNodeTable::columnNames::nodeId; + whereClause += "= :nodeId"; + + // Execute the query + try { + return fetchNodeTableRow( whereClause, whereData ); + } catch( NodeTableRowNotFound& /* dummy */ ) { + throw NodeTableRowNotFound( nodeId, "RelationalNodeMgr" ); + } +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalNodeMgr::fetchNodeTableRow +( const std::string& whereClause, + const coral::AttributeList& whereData ) const +{ + try { + std::string desc = ""; + return queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( db().nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification() ), + whereClause, whereData, desc ); + } catch( NoRowsFound& ) { + throw NodeTableRowNotFound( "RelationalNodeMgr" ); + } +} + +//----------------------------------------------------------------------------- + +const std::vector<UInt32> +RelationalNodeMgr::resolveNodeHierarchy( UInt32 ancestorNodeId, + UInt32 descendantNodeId ) const +{ + log() << "Find all descendants of node #" << ancestorNodeId + << " until node #" << descendantNodeId << " included" << coral::MessageStream::endmsg; + if ( ancestorNodeId == descendantNodeId ) + throw NodeRelationNotFound + ( ancestorNodeId, descendantNodeId, "RelationalNodeMgr" ); + std::vector<UInt32> nodes; + UInt32 nodeId = descendantNodeId; + while ( true ) { + RelationalTableRow row = fetchNodeTableRow( nodeId ); + UInt32 parentId = + row[RelationalNodeTable::columnNames::nodeParentId].data<UInt32>(); + if ( parentId == nodeId ) + { + // End of the loop: root node - node hierarchy not resolved + throw NodeRelationNotFound + ( ancestorNodeId, descendantNodeId, "RelationalNodeMgr" ); + } + else if ( parentId == ancestorNodeId ) + { + // End of the loop: ancestor found - node hierarchy resolved + std::vector<UInt32> revNodes; + for ( std::vector<UInt32>::reverse_iterator + node = nodes.rbegin(); node != nodes.rend(); ++node ) + revNodes.push_back( *node ); + revNodes. push_back( descendantNodeId ); + return revNodes; + } + else + { + // Continue the loop + nodes.push_back( parentId ); + nodeId = parentId; + } + } +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalNodeMgr.h b/RelationalCool/src/RelationalNodeMgr.h new file mode 100644 index 000000000..67acc1bfa --- /dev/null +++ b/RelationalCool/src/RelationalNodeMgr.h @@ -0,0 +1,114 @@ +// $Id: RelationalNodeMgr.h,v 1.21 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALNODEMGR_H +#define RELATIONALCOOL_RELATIONALNODEMGR_H + +// Include files +#include <memory> +#include "CoolKernel/types.h" +#include "CoralBase/AttributeList.h" +#include "CoralBase/MessageStream.h" + +namespace cool { + + // Forward declarations + class RelationalDatabase; + class RelationalQueryMgr; + class RelationalTableRow; + + /** @class RelationalNodeMgr RelationalNodeMgr.h + * + * Abstract base class for a manager of a hierarchy + * of conditions database nodes stored in a relational database. + * + * @author Andrea Valassi and Marco Clemencic + * @date 2006-03-02 + */ + + class RelationalNodeMgr { + + public: + + /// Destructor + virtual ~RelationalNodeMgr(); + + /// Constructor from a RelationalDatabase reference + RelationalNodeMgr( const RelationalDatabase& db ); + + /// Does this node exist? + bool existsNode( const std::string& fullPath ); + + /// Does this folder set exist? + bool existsFolderSet( const std::string& folderSetName ); + + /// Does this folder exist? + bool existsFolder( const std::string& folderSetName ); + + /// Return the list of existing nodes (ordered alphabetically + /// ascending/descending) + const std::vector<std::string> listAllNodes( bool ascending = true ); + + /// Return the list of nodes inside the given nodeId with the attribute + /// isLeaf as specified (ordered by name asc/desc) + const std::vector<std::string> listNodes( unsigned int nodeId, + bool isLeaf, + bool ascending = true ); + + /// Fetch all node rows + const std::vector<RelationalTableRow> + fetchAllNodeTableRows( bool ascending = true ) const; + + /// Fetch one node row (lookup by 1 node fullPath) + const RelationalTableRow + fetchNodeTableRow( const std::string& fullPath ) const; + + /// Fetch one node row (lookup by 1 nodeId) + const RelationalTableRow + fetchNodeTableRow( unsigned int nodeId ) const; + + /// Fetch one node row (lookup with given WHERE clause and bind variables) + const RelationalTableRow + fetchNodeTableRow( const std::string& whereClause, + const coral::AttributeList& whereData ) const; + + /// List all nodes in the hierarchy line between ancestor and descendant + /// (ordered from the ancestor's child to the descendant itself included) + const std::vector<UInt32> + resolveNodeHierarchy( UInt32 ancestorNodeId, + UInt32 descendantNodeId ) const; + + protected: + + /// Get the RelationalDatabase reference + const RelationalDatabase& db() const { return m_db; } + + /// Get a CORAL MessageStream + coral::MessageStream& log() const { return *m_log; } + + /// Get a relational query manager + RelationalQueryMgr& queryMgr() const; + + private: + + /// Standard constructor is private + RelationalNodeMgr(); + + /// Copy constructor is private + RelationalNodeMgr( const RelationalNodeMgr& rhs ); + + /// Assignment operator is private + RelationalNodeMgr& operator=( const RelationalNodeMgr& rhs ); + + protected: + + /// Reference to the RelationalDatabase + const RelationalDatabase& m_db; + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALNODEMGR_H + diff --git a/RelationalCool/src/RelationalNodeTable.cpp b/RelationalCool/src/RelationalNodeTable.cpp new file mode 100644 index 000000000..270d154cf --- /dev/null +++ b/RelationalCool/src/RelationalNodeTable.cpp @@ -0,0 +1,114 @@ +// $Id: RelationalNodeTable.cpp,v 1.30 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include <map> +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalNodeTable.h" +#include "RelationalException.h" +#include "VersionInfo.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalNodeTable::tableSpecification( bool isLeaf, + bool hasParent ) +{ + return tableSpecification + ( VersionInfo::schemaVersion, isLeaf, hasParent ); +} + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalNodeTable::tableSpecification +( const VersionNumber& dbSchemaVersion, + bool isLeaf, + bool hasParent ) +{ + static std::map< VersionNumber, RecordSpecification> specs_leaf; + static std::map< VersionNumber, RecordSpecification> specs_inner; + static std::map< VersionNumber, RecordSpecification> specs_inner_noparent; + + // Consistency check: the only node with no parent is a folder set + if ( !hasParent && isLeaf ) { + std::string msg = "Invalid arguments to tableSpecification"; + msg += ": a folder always has parents"; + throw RelationalException( msg, "RelationalNodeTable" ); + } + + std::map< VersionNumber, RecordSpecification>& specs = + isLeaf ? specs_leaf : ( hasParent ? specs_inner : specs_inner_noparent ); + + RecordSpecification& spec = specs[dbSchemaVersion]; + if ( spec.size() == 0 ) + { + // Default columns for both folder sets and folders + spec.extend( RelationalNodeTable::columnNames::nodeId, + RelationalNodeTable::columnTypeIds::nodeId ); + if ( hasParent ) + spec.extend( RelationalNodeTable::columnNames::nodeParentId, + RelationalNodeTable::columnTypeIds::nodeParentId ); + spec.extend( RelationalNodeTable::columnNames::nodeName, + RelationalNodeTable::columnTypeIds::nodeName ); + spec.extend( RelationalNodeTable::columnNames::nodeFullPath, + RelationalNodeTable::columnTypeIds::nodeFullPath ); + spec.extend( RelationalNodeTable::columnNames::nodeDescription, + RelationalNodeTable::columnTypeIds::nodeDescription ); + spec.extend( RelationalNodeTable::columnNames::nodeIsLeaf, + RelationalNodeTable::columnTypeIds::nodeIsLeaf ); + if ( dbSchemaVersion >= VersionNumber( "2.0.0" ) ) + spec.extend( RelationalNodeTable::columnNames::nodeSchemaVersion, + RelationalNodeTable::columnTypeIds::nodeSchemaVersion ); + spec.extend( RelationalNodeTable::columnNames::nodeInsertionTime, + RelationalNodeTable::columnTypeIds::nodeInsertionTime ); + if ( dbSchemaVersion >= VersionNumber( "2.0.0" ) ) + spec.extend( RelationalNodeTable::columnNames::lastModDate, + RelationalNodeTable::columnTypeIds::lastModDate ); + spec.extend + ( RelationalNodeTable::columnNames::folderVersioningMode, + RelationalNodeTable::columnTypeIds::folderVersioningMode ); + + // Default columns for folders only + if ( isLeaf ) + { + spec.extend + ( RelationalNodeTable::columnNames::folderPayloadSpecDesc, + RelationalNodeTable::columnTypeIds::folderPayloadSpecDesc ); + if ( dbSchemaVersion >= VersionNumber( "2.0.0" ) ) + { + spec.extend + ( RelationalNodeTable::columnNames::folderPayloadInline, + RelationalNodeTable::columnTypeIds::folderPayloadInline ); + spec.extend + ( RelationalNodeTable::columnNames::folderPayloadExtRef, + RelationalNodeTable::columnTypeIds::folderPayloadExtRef ); + spec.extend + ( RelationalNodeTable::columnNames::folderChannelSpecDesc, + RelationalNodeTable::columnTypeIds::folderChannelSpecDesc ); + spec.extend + ( RelationalNodeTable::columnNames::folderChannelExtRef, + RelationalNodeTable::columnTypeIds::folderChannelExtRef ); + } + spec.extend + ( RelationalNodeTable::columnNames::folderObjectTableName, + RelationalNodeTable::columnTypeIds::folderObjectTableName ); + spec.extend + ( RelationalNodeTable::columnNames::folderTagTableName, + RelationalNodeTable::columnTypeIds::folderTagTableName ); + spec.extend + ( RelationalNodeTable::columnNames::folderObject2TagTableName, + RelationalNodeTable::columnTypeIds::folderObject2TagTableName ); + if ( dbSchemaVersion >= VersionNumber( "2.0.0" ) ) + spec.extend + ( RelationalNodeTable::columnNames::folderChannelTableName, + RelationalNodeTable::columnTypeIds::folderChannelTableName ); + } + } + + return spec; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalNodeTable.h b/RelationalCool/src/RelationalNodeTable.h new file mode 100644 index 000000000..75684639a --- /dev/null +++ b/RelationalCool/src/RelationalNodeTable.h @@ -0,0 +1,172 @@ +// $Id: RelationalNodeTable.h,v 1.38 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALNODETABLE_H +#define RELATIONALCOOL_RELATIONALNODETABLE_H 1 + +// Include files +#include "CoolKernel/StorageType.h" + +// Local include files +#include "VersionNumber.h" +#include "uppercaseString.h" + +namespace cool +{ + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalNodeTable RelationalNodeTable.h + * + * Relational schema of the table storing COOL HVS "nodes" + * (conditions database "folders" and "folder sets"). + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2004-12-16 + */ + + namespace RelationalNodeTable { + + inline const std::string defaultTableName( const std::string& prefix ) + { + // TEMPORARY? AV 04.04.2005 + // FIXME: presently the input prefix is uppercase anyway... + return uppercaseString(prefix) + "NODES"; + } + + inline const std::string sequenceName( const std::string& tableName ) + { + // TEMPORARY? AV 04.04.2005 + // FIXME: presently the input table name is uppercase anyway... + return uppercaseString(tableName) + "_SEQ"; + } + + namespace columnNames + { + static const + std::string nodeId = "NODE_ID"; + static const + std::string nodeParentId = "NODE_PARENTID"; + static const + std::string nodeName = "NODE_NAME"; + static const + std::string nodeFullPath = "NODE_FULLPATH"; + static const + std::string nodeDescription = "NODE_DESCRIPTION"; + static const + std::string nodeIsLeaf = "NODE_ISLEAF"; + static const + std::string nodeSchemaVersion = "NODE_SCHEMA_VERSION"; + static const + std::string nodeInsertionTime = "NODE_INSTIME"; + static const + std::string lastModDate = "LASTMOD_DATE"; + static const + std::string folderPayloadSpecDesc = "FOLDER_PAYLOADSPEC"; + static const + std::string folderPayloadInline = "FOLDER_PAYLOAD_INLINE"; + static const + std::string folderPayloadExtRef = "FOLDER_PAYLOAD_EXTREF"; + static const + std::string folderChannelSpecDesc = "FOLDER_CHANNELSPEC"; + static const + std::string folderChannelExtRef = "FOLDER_CHANNEL_EXTREF"; + static const + std::string folderVersioningMode = "FOLDER_VERSIONING"; + static const + std::string folderObjectTableName = "FOLDER_IOVTABLENAME"; + static const + std::string folderTagTableName = "FOLDER_TAGTABLENAME"; + static const + std::string folderObject2TagTableName = "FOLDER_IOV2TAGTABLENAME"; + static const + std::string folderChannelTableName = "FOLDER_CHANNELTABLENAME"; + } + + namespace columnTypeIds + { + static const + StorageType::TypeId nodeId = StorageType::UInt32; + static const + StorageType::TypeId nodeParentId = StorageType::UInt32; + static const + StorageType::TypeId nodeName = StorageType::String255; + static const + StorageType::TypeId nodeFullPath = StorageType::String255; + static const + StorageType::TypeId nodeDescription = StorageType::String255; + static const + StorageType::TypeId nodeIsLeaf = StorageType::Bool; + static const + StorageType::TypeId nodeSchemaVersion = StorageType::String255; + static const + StorageType::TypeId nodeInsertionTime = StorageType::String255; + static const + StorageType::TypeId lastModDate = StorageType::String255; + static const + StorageType::TypeId folderPayloadSpecDesc = StorageType::String64k; + static const + StorageType::TypeId folderPayloadInline = StorageType::UInt16; + static const + StorageType::TypeId folderPayloadExtRef = StorageType::String64k; + static const + StorageType::TypeId folderChannelSpecDesc = StorageType::String64k; + static const + StorageType::TypeId folderChannelExtRef = StorageType::String64k; + static const + StorageType::TypeId folderVersioningMode = StorageType::Int32; + static const + StorageType::TypeId folderObjectTableName = StorageType::String255; + static const + StorageType::TypeId folderTagTableName = StorageType::String255; + static const + StorageType::TypeId folderObject2TagTableName = StorageType::String255; + static const + StorageType::TypeId folderChannelTableName = StorageType::String255; + } + + namespace columnTypes + { + typedef UInt32 nodeId; + typedef UInt32 nodeParentId; + typedef String255 nodeName; + typedef String255 nodeFullPath; + typedef String255 nodeDescription; + typedef Bool nodeIsLeaf; + typedef String255 nodeSchemaVersion; + typedef String255 nodeInsertionTime; + typedef String255 lastModDate; + typedef String64k folderPayloadSpecDesc; + typedef UInt16 folderPayloadInline; + typedef String64k folderPayloadExtRef; + typedef String64k folderChannelSpecDesc; + typedef String64k folderChannelExtRef; + typedef Int32 folderVersioningMode; + typedef String255 folderObjectTableName; + typedef String255 folderTagTableName; + typedef String255 folderObject2TagTableName; + typedef String255 folderChannelTableName; + } + + /// Get the record specification of the folder table for a given + /// COOL release (this is needed by the schema evolution tools). + /// Folder-specific columns that are not relevant for folder sets + /// are included by default unless the isLeaf flag is set to false. + /// The parentId column may be excluded for the root folder set. + const IRecordSpecification& + tableSpecification( const VersionNumber& dbSchemaVersion, + bool isLeaf = true, + bool hasParents = true ); + + /// Get the record specification of the folder table for this COOL release. + /// Folder-specific columns that are not relevant for folder sets + /// are included by default unless the isLeaf flag is set to false. + /// The parentId column may be excluded for the root folder set. + const IRecordSpecification& + tableSpecification( bool isLeaf = true, + bool hasParents = true ); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALNODETABLE_H diff --git a/RelationalCool/src/RelationalObject.cpp b/RelationalCool/src/RelationalObject.cpp new file mode 100644 index 000000000..59a9b9c04 --- /dev/null +++ b/RelationalCool/src/RelationalObject.cpp @@ -0,0 +1,284 @@ +// $Id: RelationalObject.cpp,v 1.46 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoolKernel/ConstRecordAdapter.h" + +// Local include files +#include "RelationalException.h" +#include "RelationalObject.h" +#include "RelationalObjectTable.h" +#include "RelationalObjectTableRow.h" +#include "TimingReportMgr.h" +#include "timeToString.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalObject::RelationalObject( const ValidityKey& since, + const ValidityKey& until, + const IRecord& payload, + const ChannelId& channelId, + const std::string& userTagName ) + : m_since( since ) + , m_until( until ) + , m_payload( payload ) + , m_channelId( channelId ) + , m_userTagName( userTagName ) + , m_objectId( 0 ) + , m_userTagId( 0 ) +{ + + // This is used for WRITING data. + + // NB The input IRecord& payload is the one specified by the user + // in IFolder::storeObject: the user owns it and control its lifetime, + // hence the data must be copied at least once (here using copy ctor), + // __IF__ COOL is meant to ultimately own the data (as in COOL 133). + + // On the other hand, the COOL133 code was not optimal because the data + // owned by the user could be directly stored into the database via CORAL! + + // Need TWO separate implementations for writing (data owned by the user + // and not copied) and reading (data owned by COOL)? + + // Bulk insertion - MUST copy... + +} + +//----------------------------------------------------------------------------- + +IObject* RelationalObject::clone() const +{ + RelationalObject *ret= new RelationalObject(m_since, m_until, m_payload, + m_channelId, m_userTagName ); + ret->m_objectId = m_objectId; + ret->m_userTagId = m_userTagId; + ret->m_insertionTime = m_insertionTime; + + return ret; +} +//----------------------------------------------------------------------------- + +/* +RelationalObject::RelationalObject +( RelationalObjectTableRow& row, + const IRecordSpecification& payloadSpec ) + : m_since( row.since() ) + , m_until( row.until() ) + , m_payload() + //, m_payload( ConstRecordAdapter( payloadSpec, row.data() ) // later + , m_channelId( row.channelId() ) + , m_userTagName( "" ) + , m_insertionTime( row.insertionTime() ) + , m_objectId( row.objectId() ) + , m_userTagId( row.userTagId() ) +{ + + // This is used for READING back data. + + // ASSUME (check...) that RelationalObjectTableRow is a wrapper around + // a reference to a temporary CORAL buffer: here you must do a DEEP copy! + + // CHECK: is this copying 'fast' enough? + ConstRecordAdapter rec( payloadSpec, row.data() ); + m_payload = rec; + +} +*/ + +//----------------------------------------------------------------------------- + +RelationalObject::RelationalObject +( const coral::AttributeList& aList, + const IRecordSpecification& payloadSpec ) + : m_since( aList[RelationalObjectTable::columnNames::iovSince()] + .data<ValidityKey>() ) + , m_until( aList[RelationalObjectTable::columnNames::iovUntil()] + .data<ValidityKey>() ) + , m_payload() + , m_channelId( aList[RelationalObjectTable::columnNames::channelId()] + .data<ChannelId>() ) + , m_userTagName( "" ) + , m_insertionTime( stringToTime + ( aList[RelationalObjectTable::columnNames::sysInsTime()] + .data<std::string>() ) ) + , m_objectId( aList[RelationalObjectTable::columnNames::objectId()] + .data<unsigned int>() ) + , m_userTagId( aList[RelationalObjectTable::columnNames::userTagId()] + .data<unsigned int>() ) +{ + + // This is used for READING back data. + + // ASSUME (check...) that RelationalObjectTableRow is a wrapper around + // a reference to a temporary CORAL buffer: here you must do a DEEP copy! + + if ( TimingReportMgr::isActive() ) + TimingReportMgr::startTimer( "cool::RelationalObject::ctor" ); + + // CHECK: is this copying 'fast' enough? + ConstRecordAdapter rec( payloadSpec, aList ); + m_payload = rec; + + if ( TimingReportMgr::isActive() ) + TimingReportMgr::stopTimer( "cool::RelationalObject::ctor" ); + +} + +//----------------------------------------------------------------------------- + +const ValidityKey& RelationalObject::since() const +{ + return m_since; +} + +//----------------------------------------------------------------------------- + +const ValidityKey& RelationalObject::until() const +{ + return m_until; +} + +//----------------------------------------------------------------------------- + +const IRecord& RelationalObject::payload() const +{ + return m_payload; +} + +//----------------------------------------------------------------------------- + +const ChannelId& RelationalObject::channelId() const +{ + return m_channelId; +} + +//----------------------------------------------------------------------------- + +/* +const std::string& RelationalObject::channelName() const +{ + throw RelationalException + ( "RelationalObject::channelName is not implemented yet" ); +} +*/ + +//----------------------------------------------------------------------------- + +const std::string& RelationalObject::userTagName() const +{ + return m_userTagName; +} + +//----------------------------------------------------------------------------- + +unsigned int RelationalObject::userTagId() const +{ + return m_userTagId; +} + +//----------------------------------------------------------------------------- + +bool RelationalObject::isStored() const +{ + return true; +} + +//----------------------------------------------------------------------------- + +unsigned int RelationalObject::objectId() const +{ + return m_objectId; +} + +//----------------------------------------------------------------------------- + +const ITime& RelationalObject::insertionTime() const +{ + return m_insertionTime; +} + +//----------------------------------------------------------------------------- +/* +const ValidityKey& RelationalObject::sinceOriginal() const +{ + return m_sinceOriginal; +} + +//----------------------------------------------------------------------------- + +const ValidityKey& RelationalObject::untilOriginal() const +{ + return m_untilOriginal; +} + +//----------------------------------------------------------------------------- + +const ITime& RelationalObject::insertionTimeOriginal() const +{ + return m_insertionTimeOriginal; +} +*/ +//----------------------------------------------------------------------------- + +std::ostream& RelationalObject::print( std::ostream& s ) const +{ + s << "Object: "; + { + unsigned int maxSize = 3; + s << std::setw(maxSize) << objectId(); + } + + s << " "; + + { + unsigned int maxSize = 2; + s << "(" << std::setw(maxSize) << channelId() << ")"; + } + + { // assemble IOV + std::stringstream iov; + iov << " [" << since() << "," ; + if ( until() == ValidityKeyMax ) { + iov << "+inf"; + } else { + iov << until(); + } + iov << "["; + unsigned int maxSize = 10; + s << std::setiosflags(std::ios::left) << std::setw(maxSize); + s << iov.str(); + s << std::resetiosflags(std::ios::left); + } + + s << " "; + + { // assemble payload + std::stringstream p; + p << "["; + bool first = true; + const IRecordSpecification& spec = payload().specification(); + for ( unsigned int i = 0; i < spec.size(); i++ ) { + if ( first ) { + first = false; + p << payload()[i]; + } else { + p << "|" << payload()[i]; + } + } + p << "] "; + + unsigned int maxSize = 20; + s << std::setiosflags(std::ios::left) << std::setw(maxSize); + s << p.str(); + s << std::resetiosflags(std::ios::left); + } + + s << timeToString( insertionTime() ); + return s; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalObject.h b/RelationalCool/src/RelationalObject.h new file mode 100644 index 000000000..adf8e2e42 --- /dev/null +++ b/RelationalCool/src/RelationalObject.h @@ -0,0 +1,155 @@ +// $Id: RelationalObject.h,v 1.40 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALOBJECT_H +#define RELATIONALCOOL_RELATIONALOBJECT_H + +// Include files +#include "CoolKernel/IObject.h" +#include "CoolKernel/IRecordSpecification.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/Time.h" + +namespace cool { + + // Forward declarations + class RelationalObjectTableRow; + + /** @class RelationalObject RelationalObject.h + * + * Generic relational implementation of a COOL condition database "object" + * + * @author Sven A. Schmidt, Andrea Valassi and Marco Clemencic + * @date 2004-11-30 + */ + + class RelationalObject : public IObject { + + public: + + /// Constructor of an object scheduled to be stored persistently + RelationalObject( const ValidityKey& since, + const ValidityKey& until, + const IRecord& payload, + const ChannelId& channelId, + const std::string& userTagName = "" ); + + /* + /// Constructor of an object retrieved from persistent storage + /// Note: the row can not be const, because the attributes are shared + /// TEMPORARY? A simple ALS is enough in input: an extended ALS would + /// be needed only if COOL had to check that data read back from the + /// database passes the size checks. For the moment we choose to only + /// implement size checks when WRITING the data into the database + /// (and if data is only inserted through the C++ API, no checks are + /// needed in reading back anyway...) + RelationalObject + ( RelationalObjectTableRow& row, + const IRecordSpecification& payloadSpec ); + */ + + /// Constructor of an object retrieved from persistent storage + /// AV 2007.03.26 Use a coral::AttributeList to make this faster. + /// Observed query time reduction from 0.31s to 0.27s on slc3_ia32_gcc323 + /// for the benchmark Atlas prompt reconstruction query (100MB, 100k rows). + RelationalObject + ( const coral::AttributeList& aList, + const IRecordSpecification& payloadSpec ); + + /// Destructor + virtual ~RelationalObject() {} + + /// deep copy clone + virtual IObject* clone() const; + + /// Channel identifier + const ChannelId& channelId() const; + + /// Channel name + //const std::string& channelName() const; + + /// Start of validity interval + /// For stored objects this refers to the visible validity interval + const ValidityKey& since() const; + + /// End of validity interval + /// For stored objects this refers to the visible validity interval + const ValidityKey& until() const; + + /// Data payload + const IRecord& payload() const; + + /// The user tag id + unsigned int userTagId() const; + + /// The user tag name this objects has been assigned to + const std::string& userTagName() const; + + /// Has the object been stored into the database? + bool isStored() const; + + /// System-assigned object ID + /// Throws an exception if the object has not been stored yet + unsigned int objectId() const; + + /// Insertion time into the database + /// Throws an exception if the object has not been stored yet + const ITime& insertionTime() const; + + /// Start of original validity interval + /// Throws an exception if the object has not been stored yet + //const ValidityKey& sinceOriginal() const; + + /// End of original validity interval + /// Throws an exception if the object has not been stored yet + //const ValidityKey& untilOriginal() const; + + /// Insertion time of the original object into the database + /// Throws an exception if the object has not been stored yet + //const ITime& insertionTimeOriginal() const; + + /// Pretty print to an output stream + std::ostream& print( std::ostream& s ) const; + + private: + + RelationalObject(); + RelationalObject( const RelationalObject& rhs ); + RelationalObject& operator=( const RelationalObject& rhs ); + + /// Beginning of the interval of validity + ValidityKey m_since; + + /// End of the interval of validity + ValidityKey m_until; + + /// Object payload - this is always owned by the RelationalObject + Record m_payload; + + /// Channel id + ChannelId m_channelId; + + /// User tag name + std::string m_userTagName; + + /// Insertion time + Time m_insertionTime; + + /// Object id + unsigned int m_objectId; + + /// User tag id + unsigned int m_userTagId; + + /// Beginning of the original interval of validity + //ValidityKey m_sinceOriginal; + + /// End of the original interval of validity + //ValidityKey m_untilOriginal; + + /// Original insertion time + //Time m_insertionTimeOriginal; + + }; + +} + +#endif diff --git a/RelationalCool/src/RelationalObject2TagTable.cpp b/RelationalCool/src/RelationalObject2TagTable.cpp new file mode 100644 index 000000000..8f8340da4 --- /dev/null +++ b/RelationalCool/src/RelationalObject2TagTable.cpp @@ -0,0 +1,35 @@ +// $Id: RelationalObject2TagTable.cpp,v 1.9 2006-09-28 12:49:29 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalObject2TagTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalObject2TagTable::tableSpecification() +{ + + static RecordSpecification spec; + if ( spec.size() == 0 ) { + spec.extend( RelationalObject2TagTable::columnNames::tagId, + RelationalObject2TagTable::columnTypeIds::tagId ); + spec.extend( RelationalObject2TagTable::columnNames::objectId, + RelationalObject2TagTable::columnTypeIds::objectId ); + spec.extend( RelationalObject2TagTable::columnNames::channelId, + RelationalObject2TagTable::columnTypeIds::channelId ); + spec.extend( RelationalObject2TagTable::columnNames::iovSince, + RelationalObject2TagTable::columnTypeIds::iovSince ); + spec.extend( RelationalObject2TagTable::columnNames::iovUntil, + RelationalObject2TagTable::columnTypeIds::iovUntil ); + spec.extend( RelationalObject2TagTable::columnNames::sysInsTime, + RelationalObject2TagTable::columnTypeIds::sysInsTime ); + } + return spec; + +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalObject2TagTable.h b/RelationalCool/src/RelationalObject2TagTable.h new file mode 100644 index 000000000..15fada44a --- /dev/null +++ b/RelationalCool/src/RelationalObject2TagTable.h @@ -0,0 +1,71 @@ +// $Id: RelationalObject2TagTable.h,v 1.19 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALOBJECT2TAGTABLE_H +#define RELATIONALCOOL_RELATIONALOBJECT2TAGTABLE_H + +// Include files +#include "CoolKernel/StorageType.h" + +// Local include files +#include "uppercaseString.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalObject2TagTable RelationalObject2TagTable.h + * + * Relational schema of the table storing COOL tag <--> object relations. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2005-02-06 + */ + + namespace RelationalObject2TagTable { + + inline const std::string defaultTableName + ( const std::string& prefix, unsigned nodeId ) { + char tableName[] = "Fxxxx_IOV2TAG"; + sprintf( tableName, "F%4.4i_IOV2TAG", nodeId ); + // TEMPORARY? AV 04.04.2005 + // FIXME: presently the input prefix is uppercase anyway... + return uppercaseString( prefix ) + std::string( tableName ); + } + + namespace columnNames { + static const std::string tagId = "TAG_ID"; + static const std::string objectId = "OBJECT_ID"; + static const std::string channelId = "CHANNEL_ID"; + static const std::string iovSince = "IOV_SINCE"; + static const std::string iovUntil = "IOV_UNTIL"; + static const std::string sysInsTime = "SYS_INSTIME"; + } + + namespace columnTypeIds { + static const StorageType::TypeId tagId = StorageType::UInt32; + static const StorageType::TypeId objectId = StorageType::UInt32; + static const StorageType::TypeId channelId = StorageType::UInt32; + static const StorageType::TypeId iovSince = StorageType::UInt63; + static const StorageType::TypeId iovUntil = StorageType::UInt63; + // TEMPORARY! Should be Time? + static const StorageType::TypeId sysInsTime = StorageType::String255; + } + + namespace columnTypes { + typedef UInt32 tagId; + typedef UInt32 objectId; + typedef UInt32 channelId; + typedef UInt63 iovSince; + typedef UInt63 iovUntil; + // TEMPORARY! Should be Time? + typedef String255 sysInsTime; + } + + /// Get the RecordSpecification of the tag table + const IRecordSpecification& tableSpecification(); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALOBJECT2TAGTABLE_H diff --git a/RelationalCool/src/RelationalObjectIterator.cpp b/RelationalCool/src/RelationalObjectIterator.cpp new file mode 100644 index 000000000..0b97c95f1 --- /dev/null +++ b/RelationalCool/src/RelationalObjectIterator.cpp @@ -0,0 +1,457 @@ +// $Id: RelationalObjectIterator.cpp,v 1.13 2008-11-06 18:50:04 avalassi Exp $ + +// Include files +#include "CoolKernel/InternalErrorException.h" +#include "CoolKernel/types.h" +#include "RelationalAccess/ICursor.h" +#include "RelationalAccess/IQuery.h" +#include "RelationalAccess/IQueryDefinition.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" + +// Local include files +#include "HvsTagRecord.h" +#include "IRelationalCursor.h" +#include "IRelationalQueryDefinition.h" +#include "IteratorException.h" +#include "ObjectIteratorCounter.h" +#include "RelationalObjectIterator.h" +#include "RelationalException.h" +#include "RelationalFolder.h" +#include "RelationalObject.h" +#include "RelationalObjectTable.h" +#include "RelationalObjectTableRow.h" +#include "RelationalQueryMgr.h" +#include "RelationalTagMgr.h" +#include "RelationalTransaction.h" +#include "TimingReportMgr.h" + +// Namespace +using namespace cool; + +//--------------------------------------------------------------------------- + +RelationalObjectIterator::RelationalObjectIterator +( const RelationalQueryMgr& queryMgr, + const boost::shared_ptr<IRelationalTransactionMgr>& transactionMgr, + const RelationalTagMgr& tagMgr, + const RelationalFolder& folder, + const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + bool isUserTag, + const IRecordSelection* payloadQuery, + const bool countOnly ) + : m_isTimingActive( isTimingActive() ) + , m_transactionMgr( transactionMgr.get() ) + , m_isRegistered( false ) + , m_queryMgr( queryMgr.clone() ) + , m_objectTable( new RelationalObjectTable(m_queryMgr.get(), false, folder) ) + , m_versioningMode( folder.versioningMode() ) + , m_transaction( new RelationalTransaction( transactionMgr, true ) ) // r/o + , m_dataBuffer( new coral::AttributeList() ) + , m_since(since) + , m_until(until) + , m_channels(channels) + , m_tagName(tagName) + , m_isUserTag(isUserTag) + , m_selection( payloadQuery != 0 ? payloadQuery->clone() : 0 ) + , m_pq( payloadQuery != 0 ? + new RelationalPayloadQuery( *m_selection.get() ) : 0 ) + , m_queryDef( ( m_selection.get() !=0 && m_pq->isTrusted() ) ? + getQueryDefinition( since, until, channels, tagName, isUserTag, m_selection.get() ) : + getQueryDefinition( since, until, channels, tagName, isUserTag, 0 ) ) + , m_size_known( false ) + , m_size( 0 ) + , m_currentObject( 0 ) +{ + //std::cout << "RelationalObjectIterator ctor " << this << std::endl; + + if ( countOnly ) + { + m_state = COUNTONLY; + } + else + { + m_cursor.reset( m_queryMgr->prepareAndExecuteQuery( *m_queryDef, m_dataBuffer ) ); + m_currentRowAdapter.reset( new ConstRelationalObjectAdapter( *m_dataBuffer, folder.payloadSpecification() ) ); + m_state = ACTIVE; + } + + // Marco: this needs to be here to avoid the registration of the iterator + // if an exception occurs in the initialization statements (bug #25256). + ObjectIteratorCounter::registerIterator( this, m_transactionMgr ); + m_isRegistered = true; + + // After starting the transaction, check that the tag exists + // Throw TagNotFound if the tag does not exist in this folder + if ( ! IHvsNode::isHeadTag( tagName ) ) + { + try + { + // Throws TagNotFound if tag does not exist + tagMgr.__findTagRecord( folder.id(), tagName ); + } + catch ( ... ) + { + // Release any associated server resources and unregister the iterator + bool rollback = true; + close( rollback ); + throw; + } + } + + if ( m_isTimingActive ) + TimingReportMgr::stopTimer + ( "cool::RelationalObjectIterator::ctor" ); +} + +//--------------------------------------------------------------------------- + +RelationalObjectIterator::~RelationalObjectIterator() +{ + //std::cout << "RelationalObjectIterator dtor " << this << std::endl; + + // Move the iterator into the Closed state. + close(); + + //if ( m_isTimingActive ) + // TimingReportMgr::stopTimer + // ( "cool::RelationalObjectIterator [LIFETIME]" ); +} + +//--------------------------------------------------------------------------- + +bool RelationalObjectIterator::isTimingActive() const +{ + if ( TimingReportMgr::isActive() ) + { + TimingReportMgr::startTimer + ( "cool::RelationalObjectIterator::ctor" ); + //TimingReportMgr::startTimer + // ( "cool::RelationalObjectIterator [LIFETIME]" ); + return true; + } + else return false; +} + +//----------------------------------------------------------------------------- + +bool RelationalObjectIterator::isEmpty() +{ + if ( m_currentObject > 0 ) return false; + return size() == 0; +} + +//--------------------------------------------------------------------------- + +const IObject& RelationalObjectIterator::currentRef() +{ + // Iterator is in the CountOnly state + if ( m_state == COUNTONLY ) + { + throw InternalErrorException( "PANIC! Iterator can be used only for counting", + "RelationalObjectIterator" ); + } + + // Iterator is in the Closed state + else if ( m_state == CLOSED ) + { + throw IteratorIsClosed( "RelationalObjectIterator" ); + } + + // Iterator is in the Started state + // [next() has not been called yet and/or the iterator is empty]. + else if ( m_currentObject == 0 || m_state == END_OF_ROWS ) + { + throw IteratorHasNoCurrentItem( "RelationalObjectIterator" ); + } + + // Iterator is in the Active state + else + { + if ( m_isTimingActive ) { + TimingReportMgr::startTimer + ( "cool::RelationalObjectIterator::currentRef" ); + TimingReportMgr::stopTimer + ( "cool::RelationalObjectIterator::currentRef" ); + } + return *m_currentRowAdapter; + } + +} + +//--------------------------------------------------------------------------- + +bool RelationalObjectIterator::goToNext() +{ + if ( m_state == COUNTONLY ) + throw InternalErrorException( "PANIC! Iterator can be used only for counting", + "RelationalObjectIterator" ); + + if ( m_isTimingActive ) + TimingReportMgr::startTimer + ( "cool::RelationalObjectIterator::goToNext()" ); + + // Iterator is in the Closed state + if ( m_state == CLOSED ) { + if ( m_isTimingActive ) + TimingReportMgr::stopTimer + ( "cool::RelationalObjectIterator::goToNext()" ); + throw IteratorIsClosed( "RelationalObjectIterator" ); + } + + // Iterator (Started or Active) has a non-null next object + else + { + bool client_side_pq = m_selection.get()!=0 && !m_pq->isTrusted(); + // If there is a payload selection (m_selection), fetch objects + // until one satisfies the selection or we have no more objects + + bool gotNext = false; + do { + m_currentObject++; + } + while ( ( gotNext = fetchNext() ) == true + && client_side_pq + && !m_selection->select( currentRef().payload() ) ); + if (!gotNext) + m_state = END_OF_ROWS; + + if ( m_isTimingActive ) + TimingReportMgr::stopTimer + ( "cool::RelationalObjectIterator::goToNext()" ); + + return gotNext; + } +} + + +//--------------------------------------------------------------------------- + +unsigned int RelationalObjectIterator::size() +{ + //std::cout << "RelationalObjectIterator::size()" << std::endl; + // Iterator is in the Closed state + if ( m_state == CLOSED ) { + throw IteratorIsClosed( "RelationalObjectIterator" ); + } + else if ( m_selection.get()!=0 && !m_pq->isTrusted() ) + { + // NB This makes sense also for COUNTONLY iterators... + throw RelationalException + ( "Size is not known since the payload query is not trusted", + "RelationalObjectIterator" ); + } + // Iterator is in the NotStarted, Started or Active state + else if ( !m_size_known ) + { + // size is requested for the first time, so fetch it + m_size_known=true; + m_size=getSize + ( m_since, m_until, m_channels, m_tagName, m_isUserTag, m_selection.get() ); + } + //std::cout << "RelationalObjectIterator::size() is " << m_size << std::endl; + return m_size; +} + +//--------------------------------------------------------------------------- + +const IObjectVectorPtr RelationalObjectIterator::fetchAllAsVector() +{ + if ( m_state == COUNTONLY ) + throw InternalErrorException( "PANIC! Iterator can be used only for counting", + "RelationalObjectIterator" ); + + // Iterator is in the Closed state + if ( m_state == CLOSED ) { + throw IteratorIsClosed( "RelationalObjectIterator" ); + } + + // Iterator is in the Started state + else if ( m_currentObject == 0 ) { + IObjectVectorPtr objects( new IObjectVector() ); + if ( m_isTimingActive ) + TimingReportMgr::startTimer + ( "cool::RelationalObjectIterator::fetchAllAsVec()" ); + while( goToNext() ) { + objects->push_back( IObjectPtr( currentRef().clone() ) ); + } + if ( m_isTimingActive ) + TimingReportMgr::stopTimer + ( "cool::RelationalObjectIterator::fetchAllAsVec()" ); + return objects; + } + + // Iterator is in the Active state + else { + throw IteratorIsActive( "RelationalObjectIterator" ); + } +} + +//--------------------------------------------------------------------------- + +void RelationalObjectIterator::close( bool rollback ) +{ + //std::cout << "RelationalObjectIterator close() " << this << std::endl; + + // Iterator is not already in the Closed state + if ( m_state != CLOSED ) { + + // Delete the cursor and release all associated database resources + std::auto_ptr<IRelationalCursor> nullCursor; + m_cursor = nullCursor; + + // Commit and delete the read-only transaction + if ( m_transaction ) { + if ( ! rollback ) m_transaction->commit(); + else m_transaction->rollback(); + delete m_transaction; + m_transaction = 0; + } + + // Move the iterator into the Closed state + m_state = CLOSED; + + // Unregister the iterator + ObjectIteratorCounter::unregisterIterator( this, m_transactionMgr ); + } +} + +//--------------------------------------------------------------------------- + +unsigned int +RelationalObjectIterator::getSize( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + bool isUserTag, + const IRecordSelection* payloadQuery ) const +{ + unsigned int size; + if ( m_versioningMode == FolderVersioning::SINGLE_VERSION ) + { + if ( ! IHvsNode::isHeadTag( tagName ) ) + throw RelationalException + ( "Single version folder: browsing within a non-null tag '" + + tagName + "' makes no sense", "RelationalObjectIterator" ); + const std::auto_ptr<IRelationalQueryDefinition> + def( m_objectTable->queryDefinitionSV + ( since, until, channels, payloadQuery ) ); + size = m_queryMgr->countRows( *def, "SV object count" ); + } + else if ( m_versioningMode == FolderVersioning::MULTI_VERSION ) + { + if ( isUserTag ) + { + const std::auto_ptr<IRelationalQueryDefinition> + def( m_objectTable->queryDefinitionHeadAndUserTag + ( since, until, channels, tagName, payloadQuery ) ); + size = m_queryMgr->countRows( *def, "MV userTag object count" ); + } + else if ( IHvsNode::isHeadTag( tagName ) ) + { + const std::auto_ptr<IRelationalQueryDefinition> + def( m_objectTable->queryDefinitionHeadAndUserTag + ( since, until, channels, tagName, payloadQuery ) ); + size = m_queryMgr->countRows( *def, "MV headTag object count" ); + } + else + { + const std::auto_ptr<IRelationalQueryDefinition> + def( m_objectTable->queryDefinitionTag + ( since, until, channels, tagName, payloadQuery ) ); + size = m_queryMgr->countRows( *def, "MV tag object count" ); + } + } + else + { + std::stringstream s; + s << "Object count not supported for this folder type: " + << m_versioningMode; + throw RelationalException( s.str(), "RelationalObjectIterator" ); + } + return size; +} + +//--------------------------------------------------------------------------- + +std::auto_ptr<IRelationalQueryDefinition> +RelationalObjectIterator::getQueryDefinition( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + bool isUserTag, + const IRecordSelection* payloadQuery ) +{ + + // --- SINGLE VERSION --- + + if ( m_versioningMode == FolderVersioning::SINGLE_VERSION ) + { + if ( ! IHvsNode::isHeadTag( tagName ) ) + throw RelationalException + ( "Single version folder: browsing within a non-null tag '" + + tagName + "' makes no sense", "RelationalObjectIterator" ); + std::auto_ptr<IRelationalQueryDefinition> + def( m_objectTable->queryDefinitionSV + ( since, until, channels, payloadQuery ) ); + return def; + } + + // --- MULTI VERSION --- + + else + { + if ( IHvsNode::isHeadTag( tagName ) ) + { // MV HEAD + std::auto_ptr<IRelationalQueryDefinition> + def( m_objectTable->queryDefinitionHeadAndUserTag + ( since, until, channels, "HEAD", payloadQuery ) ); + return def; + } + else if ( isUserTag ) + { // MV User Tag + std::auto_ptr<IRelationalQueryDefinition> + def( m_objectTable->queryDefinitionHeadAndUserTag + ( since, until, channels, tagName, payloadQuery ) ); + return def; + } + else + { // MV Tag + std::auto_ptr<IRelationalQueryDefinition> + def( m_objectTable->queryDefinitionTag + ( since, until, channels, tagName, payloadQuery ) ); + return def; + } + } +} + +//--------------------------------------------------------------------------- + +bool RelationalObjectIterator::fetchNext() +{ + if ( m_state == COUNTONLY ) + throw InternalErrorException( "PANIC! Iterator can be used only for counting", + "RelationalObjectIterator" ); + + // Iterator is in the Closed state (???) + if ( m_state == CLOSED ) + throw InternalErrorException( "PANIC! The iterator is closed!?", + "RelationalObjectIterator" ); + + // Fetch the next row from the RAL cursor + if ( m_cursor->next() ) + { + // The currentRow() contains a reference to the current row + return true; + } else { + // The currentRow() should not be used + return false; + } + +} + +//--------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalObjectIterator.h b/RelationalCool/src/RelationalObjectIterator.h new file mode 100644 index 000000000..bc2dba2fb --- /dev/null +++ b/RelationalCool/src/RelationalObjectIterator.h @@ -0,0 +1,198 @@ +// $Id: RelationalObjectIterator.h,v 1.12 2008-11-06 15:43:02 avalassi Exp $ +#ifndef COOLKERNEL_RELATIONALOBJECTITERATOR_H +#define COOLKERNEL_RELATIONALOBJECTITERATOR_H + +// Include files +#include <memory> +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/FolderVersioning.h" + +// Local include files +#include "ConstRelationalObjectAdapter.h" +#include "RelationalPayloadQuery.h" + +namespace cool +{ + + // Forward declarations + class IRecordSelection; + class IRelationalCursor; + class IRelationalQueryDefinition; + class IRelationalTransactionMgr; + class RelationalFolder; + class RelationalObjectTable; + class RelationalQueryMgr; + class RelationalTagMgr; + class RelationalTransaction; + + /** @class RelationalObjectIterator RelationalObjectIterator.h + * + * RAL implementation of an object iterator. + * + * The iterator can be used only ONCE to forward-iterate over a result set. + * + * During its whole lifetime, the iterator is associated to a read-only RAL + * transaction (started in the constructor), a RAL query (created in the + * constructor) and a RAL cursor reference (obtained by processing this + * query in the constructor). All these resources are released in the + * destructor by a call to the close() method, which commits and deletes + * the transaction, and deletes the query. The close() method can also be + * called explicitly in the user code to release the resources: this moves + * the iterator to the Closed state, from which it cannot be reused. + * + * For perfomance reasons the iterator doesn't query the number of rows, + * unless size() or isEmpty() are called. + * + * @author Andrea Valassi + * @date 2007-03-29 + */ + + class RelationalObjectIterator : public IObjectIterator { + + public: + + /// Destructor + virtual ~RelationalObjectIterator(); + + /// Constructor from all relevant query parameters + RelationalObjectIterator + ( const RelationalQueryMgr& queryMgr, + const boost::shared_ptr<IRelationalTransactionMgr>& transactionMgr, + const RelationalTagMgr& tagMgr, + const RelationalFolder& folder, + const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + bool isUserTag, + const IRecordSelection* payloadQuery = 0, + const bool countOnly = false ); + + /// Does the iterator have zero objects in the loop? + bool isEmpty(); + + /// Fetch the next object in the iterator loop. + /// Return false if there is no next object. + bool goToNext(); + + /// Retrieve a reference to the current object in the iterator loop. + /// NB The reference is only valid until goToNext() is called! + /// Throw an exception if there is no current object (because the iterator + /// is empty or is positioned before the first object in the loop). + const IObject& currentRef(); + + /// Returns the 'length' of the iterator + unsigned int size(); + + /// Returns all objects in the iterator as a vector. + /// Throws an exception if goToNext() has already retrieved one object: + /// this method can only be called INSTEAD of the loop using goToNext(). + const IObjectVectorPtr fetchAllAsVector(); + + /// Close the iterator and release any associated server resources. + /// The iterator cannot be used any more after this method is called. + void close() + { + bool rollback = false; + close( rollback ); + } + + private: + + /// Prefetch the number of rows that the iterator will return + unsigned int getSize( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + bool isUserTag, + const IRecordSelection* payloadQuery = 0 ) const; + + /// Get the appropriate query definition for this iterator + std::auto_ptr<IRelationalQueryDefinition> + getQueryDefinition( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + bool isUserTag, + const IRecordSelection* payloadQuery = 0 ); + + /// Fetch the next object from the CORAL cursor + bool fetchNext(); + + /// Is timing active? (hack to activate it at beginning of ctor) + bool isTimingActive() const; + + /// Close the iterator and release any associated server resources. + /// The iterator cannot be used any more after this method is called. + /// Commit/rollback the open transaction in case of success/failure. + void close( bool rollback ); + + private: + + /// Is timing active? (hack to activate it at beginning of ctor) + bool m_isTimingActive; + + /// The IRelationalTransactionMgr referenced in the iterator counter + /// NB This is only used as an index - you don't even need the header! + const IRelationalTransactionMgr* m_transactionMgr; + + /// Is this iterator registered? (hack to do it at beginning of ctor) + bool m_isRegistered; + + /// Relational query manager + std::auto_ptr<RelationalQueryMgr> m_queryMgr; + + /// Object table for the relevant folder + std::auto_ptr<RelationalObjectTable> m_objectTable; + + /// Versioning mode for the relevant folder + FolderVersioning::Mode m_versioningMode; + + /// Active relational transaction + RelationalTransaction* m_transaction; + + /// Data buffer used by the active cursor + boost::shared_ptr<coral::AttributeList> m_dataBuffer; + + /// details about the query, needed to fetch the size of the vector + /// if demanded. + const ValidityKey m_since; + const ValidityKey m_until; + const ChannelSelection m_channels; + const std::string m_tagName; + bool m_isUserTag; + + /// Record selection for this iterator + std::auto_ptr<IRecordSelection> m_selection; + + /// Payload query for this iterator + std::auto_ptr<RelationalPayloadQuery> m_pq; + + /// Relational query definition + std::auto_ptr<IRelationalQueryDefinition> m_queryDef; + + /// is m_size known + bool m_size_known; + + /// number of rows that the iterator will return + /// queried on demand by the size() method + unsigned int m_size; + + /// FSM - current object in RelationalObjectIterator private cache + unsigned int m_currentObject; + + /// Active cursor + std::auto_ptr<IRelationalCursor> m_cursor; + + /// Adapter of const AttributeList& currentRow() to the IObject interface. + std::auto_ptr<ConstRelationalObjectAdapter> m_currentRowAdapter; + + /// state of the iterator (active, end of rows reached, closed; or countonly) + enum { ACTIVE, END_OF_ROWS, CLOSED, COUNTONLY } m_state; + + }; + +} + +#endif diff --git a/RelationalCool/src/RelationalObjectMgr.cpp b/RelationalCool/src/RelationalObjectMgr.cpp new file mode 100644 index 000000000..e566e4588 --- /dev/null +++ b/RelationalCool/src/RelationalObjectMgr.cpp @@ -0,0 +1,1895 @@ +// $Id: RelationalObjectMgr.cpp,v 1.38 2009-01-13 18:30:10 avalassi Exp $ + +// Include files +#include <boost/scoped_array.hpp> +#include "CoolKernel/InternalErrorException.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoralBase/Attribute.h" +#include "RelationalAccess/SchemaException.h" + +// Local include files +#include "HvsTagRecord.h" +#include "IRelationalBulkOperation.h" +#include "RelationalChannelTable.h" +#include "RelationalException.h" +#include "RelationalGlobalTagTable.h" +#include "RelationalObject.h" +#include "RelationalObjectIterator.h" +#include "RelationalObjectMgr.h" +#include "RelationalObjectTable.h" +#include "RelationalObjectTableRow.h" +#include "RelationalQueryDefinition.h" +#include "RelationalSequence.h" +#include "RelationalSequenceMgr.h" +#include "RelationalTableRow.h" +#include "RelationalTagMgr.h" +#include "RelationalTagTable.h" +#include "RelationalTransaction.h" +#include "SimpleObject.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalObjectMgr::RelationalObjectMgr( const RelationalDatabase& db ) + : m_db( db ) + , m_log( new coral::MessageStream( "RelationalObjectMgr" ) ) +{ +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RelationalObjectMgr::log() const +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +IObjectPtr +RelationalObjectMgr::findObject( const RelationalFolder* folder, + const ValidityKey& pointInTime, + const ChannelId& channelId, + const std::string& tagName ) const +{ + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + IObjectIteratorPtr objs = browseObjects( folder, + pointInTime, + pointInTime, + ChannelSelection( channelId ), + tagName ); + + if ( ! objs->goToNext() ) + { + std::stringstream s; + s << pointInTime; + throw ObjectNotFound( s.str(), folder->fullPath() ); + } + IObjectPtr obj( objs->currentRef().clone() ); + if ( objs->goToNext() ) + throw InternalErrorException + ( "PANIC! More than one object in findObject query", "RalDatabase" ); + return obj; +} + +//----------------------------------------------------------------------------- + +IObjectIteratorPtr +RelationalObjectMgr::browseObjects +( const RelationalFolder* folder, + const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + const IRecordSelection* payloadQuery, + const bool countOnly ) const +{ + IObjectIteratorPtr iterator; + + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RalDatabase" ); + + FolderVersioning::Mode versioningMode = folder->versioningMode(); + try + { + // Throw TagNotFound if the tag does not exist in this folder + // [this is delegated to the RelationalObjectIterator constructor] + + if ( versioningMode == FolderVersioning::SINGLE_VERSION ) + { + bool isUserTag = false; + iterator.reset + ( new RelationalObjectIterator + ( queryMgr(), transactionMgr(), tagMgr(), + *folder, since, until, channels, tagName, isUserTag, + payloadQuery, countOnly )); + } + else if ( versioningMode == FolderVersioning::MULTI_VERSION ) + { + bool isUserTag = folder->existsUserTag( tagName ); + iterator.reset + ( new RelationalObjectIterator + ( queryMgr(), transactionMgr(), tagMgr(), + *folder, since, until, channels, tagName, isUserTag, + payloadQuery, countOnly )); + } + else + { + std::stringstream s; + s << "Unsupported folder versioning mode: " + << versioningMode; + throw RelationalException( s.str(), "RalDatabase" ); + } + } + catch ( coral::TableNotExistingException& ) + { + // Guard against a dropped folder and provide meaningful feedback + // (minor issue: catch CORAL exception in a generic Relational class...) + throw FolderSpecificTableNotFound( folder->fullPath(), "RalDatabase" ); + } + return iterator; +} + +//----------------------------------------------------------------------------- + +bool +RelationalObjectMgr::dropChannel( const RelationalFolder* folder, + const ChannelId& channelId ) const +{ + bool readOnly = false; + RelationalTransaction transaction( transactionMgr(), readOnly ); + const std::string folderName = folder->fullPath(); + // FIRST check if there are any IOVs for this channel + // (throw an exception if there are any - this is the semantics + // of the dropChannel method, it is NOT a workaround for bug #23755). + if ( db().relationalObjectTable( *folder )->existsChannel( channelId ) ) + { + std::ostringstream s; + s << "Cannot drop channel with id=" << channelId + << " in folder '" << folder->fullPath() + << "': the channel contains some IOVs"; + throw RelationalException( s.str(), "RelationalObjectMgr" ); + } + // THEN check if the channel exists (only) in the channel table + RelationalChannelTable table( db(), *folder ); + try + { + table.fetchRowForId( channelId ); + } + catch ( NoRowsFound& ) + { + transaction.commit(); + return false; + } + std::string whereClause = RelationalChannelTable::columnNames::channelId(); + whereClause += "= :channel"; + coral::AttributeList whereData; + whereData.extend + ( "channel", + typeIdToCoralType(RelationalChannelTable::columnTypeIds::channelId) ); + whereData["channel"].setValue( channelId ); + // Rely on the queryMgr to throw an exception if the DELETE goes wrong + queryMgr().deleteTableRows( table.tableName(), whereClause, whereData, 1 ); + // Commit the transaction + transaction.commit(); + return true; +} + +//----------------------------------------------------------------------------- + +void +RelationalObjectMgr::createChannel( const RelationalFolder* folder, + const ChannelId& channelId, + const std::string& channelName, + const std::string& description ) const +{ + bool readOnly = false; + RelationalTransaction transaction( transactionMgr(), readOnly ); + const std::string folderName = folder->fullPath(); + // Check if a channel with the given ID already exists + try + { + RelationalChannelTable table( db(), *folder ); + table.fetchRowForId( channelId ); + throw ChannelExists( folderName, channelId, "RelationalObjectMgr" ); + } + catch ( NoRowsFound& ) {} + // Check if a channel with the given name already exists + try + { + RelationalChannelTable table( db(), *folder ); + table.fetchRowForChannelName( channelName ); + throw ChannelExists( folderName, channelName, "RelationalObjectMgr" ); + } catch ( NoRowsFound& ) {} + // Create a new channel with the given ID and name + unsigned int lastObjectId = 0; + bool hasNewData = false; + insertChannelTableRow( folder->channelTableName(), + channelId, + lastObjectId, + hasNewData, + channelName, + description ); + // Commit the transaction + transaction.commit(); +} + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::insertChannelTableRow +( const std::string& channelTableName, + const ChannelId& channelId, + unsigned int lastObjectId, + bool hasNewData, + const std::string& channelName, + const std::string& description ) const +{ + coral::AttributeList data = + Record( RelationalChannelTable::tableSpecification() ).attributeList(); + data[RelationalChannelTable::columnNames::channelId()].setValue + ( channelId ); + data[RelationalChannelTable::columnNames::lastObjectId()].setValue + ( lastObjectId ); + data[RelationalChannelTable::columnNames::hasNewData()].setValue + ( hasNewData ); + if ( channelName != "" ) + data[RelationalChannelTable::columnNames::channelName()].setValue + ( channelName ); + else + data[RelationalChannelTable::columnNames::channelName()].setNull(); + data[RelationalChannelTable::columnNames::description()].setValue + ( description ); + queryMgr().insertTableRow( channelTableName, data ); +} + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::updateChannelTable +( const std::string& channelTableName, + const ChannelId& channelId, + unsigned int lastObjectId, + bool hasNewData ) const +{ + log() << "Update in table " << channelTableName + << " for channel " << channelId << coral::MessageStream::endmsg; + + // Update the lastObjectId column only if hasNewData is false + // Enforce that lastObjectId should be 0 otherwise + bool updateLastObjectId = (!hasNewData); + if ( !updateLastObjectId && lastObjectId != 0 ) + throw RelationalException + ( "PANIC! Unexpected arguments to updateChannelTable", "RelationalObjectMgr" ); + + // Define the SET and WHERE clauses for the update using bind variables + coral::AttributeList updateData; + if ( updateLastObjectId ) + updateData.extend( "lastObjectId", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::lastObjectId) ); + updateData.extend( "hasNewData", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::hasNewData) ); + updateData.extend( "channel", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::channelId) ); + if ( updateLastObjectId ) + updateData["lastObjectId"].setValue( lastObjectId ); + updateData["hasNewData"].setValue( hasNewData ); + updateData["channel"].setValue( channelId ); + std::string setClause; + if ( updateLastObjectId ) + { + setClause += RelationalChannelTable::columnNames::lastObjectId(); + setClause += " = :lastObjectId"; + setClause += ", "; + } + setClause += RelationalChannelTable::columnNames::hasNewData(); + setClause += "= :hasNewData"; + std::string whereClause = RelationalChannelTable::columnNames::channelId(); + whereClause += "= :channel"; + + // Execute the update + UInt32 updatedRows = queryMgr().updateTableRows + ( channelTableName, setClause, whereClause, updateData ); + + if ( updatedRows == 0 ) { + // it's a new channel + coral::AttributeList data = + Record( RelationalChannelTable::tableSpecification() ).attributeList(); + data[RelationalChannelTable::columnNames::channelId()].setValue + ( channelId ); + data[RelationalChannelTable::columnNames::lastObjectId()].setValue + ( lastObjectId ); + data[RelationalChannelTable::columnNames::hasNewData()].setValue + ( hasNewData ); + //data[RelationalChannelTable::columnNames::channelName()].setValue + // ( std::string("") ); + data[RelationalChannelTable::columnNames::channelName()].setNull(); // UK! + queryMgr().insertTableRow( channelTableName, data ); + } else if ( updatedRows != 1 ) { + throw RowNotUpdated + ( "Could not update a row of the channels table", "RalDatabase" ); + } +} + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::bulkUpdateChannelTable +( const std::string& channelTableName, + const std::map< ChannelId, unsigned int >& updateDataMap, + bool hasNewData ) const +{ + log() << "Bulk update channel table " << channelTableName + << coral::MessageStream::endmsg; + + if ( updateDataMap.empty() ) { + log() << "Nothing to update" << coral::MessageStream::endmsg; + return; + } + + // Update the lastObjectId column only if hasNewData is false + bool updateLastObjectId = (!hasNewData); + + // ATTEMPT BULK UPDATE + { + // Define the SET and WHERE clauses for the update using bind variables + coral::AttributeList updateData; + if ( updateLastObjectId ) + updateData.extend + ( "lastObjectId", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::lastObjectId) ); + updateData.extend + ( "hasNewData", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::hasNewData) ); + updateData.extend + ( "channel", + typeIdToCoralType + (RelationalChannelTable::columnTypeIds::channelId) ); + std::string setClause; + if ( updateLastObjectId ) + { + setClause += RelationalChannelTable::columnNames::lastObjectId(); + setClause += " = :lastObjectId"; + setClause += ", "; + } + setClause += RelationalChannelTable::columnNames::hasNewData(); + setClause += "= :hasNewData"; + std::string whereClause = RelationalChannelTable::columnNames::channelId(); + whereClause += "= :channel"; + + int dataCacheSize = 1000; // rows + boost::shared_ptr<IRelationalBulkOperation> query = + db().queryMgr().bulkUpdateTableRows + ( channelTableName, setClause, whereClause, updateData, dataCacheSize ); + + for ( std::map< ChannelId, unsigned int >::const_iterator + i = updateDataMap.begin(); i != updateDataMap.end(); ++i ) + { + updateData["channel"].setValue( i->first ); + if ( updateLastObjectId ) + updateData["lastObjectId"].setValue( i->second ); + updateData["hasNewData"].setValue( hasNewData ); + query->processNextIteration(); + } + query->flush(); + + } + + // CHECK BULK UPDATE - ELSE SINGLE ROW INSERT/UPDATE + // (NB THIS CAN ONLY BE DONE IF HASNEWDATA IS TRUE!) + if ( hasNewData ) + { + // Get updated row count + RelationalQueryDefinition def; + //def.addSelectItems(...); // None - SELECT COUNT(*) FROM ( SELECT * ... ) + def.addFromItem( channelTableName, "" ); + std::string whereClause = + RelationalChannelTable::columnNames::hasNewData() + " = :hasNewData"; + def.setWhereClause( whereClause ); + RecordSpecification whereDataSpec; + whereDataSpec.extend( "hasNewData", StorageType::Bool ); + Record whereData( whereDataSpec ); + whereData["hasNewData"].setValue( hasNewData ); + def.setBindVariables( whereData ); + UInt32 rowCount = queryMgr().countRows( def ); + + // If the row count differs from what is expected, + // insert/update channels one by one in the table + if ( rowCount != updateDataMap.size() ) + { + log() << "Bulk update failed (rows updated=" << rowCount + << ", rows to be updated=" << updateDataMap.size() + << "): use single row insert/update" + << coral::MessageStream::endmsg; + + // Fall back to the non-bulk channel update + for ( std::map< ChannelId, unsigned int >::const_iterator + i = updateDataMap.begin(); i != updateDataMap.end(); ++i ) + { + ChannelId channel = i->first; + log() << "Insert or update channel " << channel + << coral::MessageStream::endmsg; + updateChannelTable + ( channelTableName, channel, i->second, hasNewData ); + } + } + } + +} + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::bulkUpdateObjectTableIov +( const std::string& objectTableName, + const std::map<unsigned int,ValidityKey>& objectIdNewUntil ) const +{ + log() << "Bulk update IOVs in table " << objectTableName + << coral::MessageStream::endmsg; + + if ( objectIdNewUntil.empty() ) { + log() << "Nothing to update" << coral::MessageStream::endmsg; + return; + } + + // Define the SET and WHERE clauses for the update using bind variables + // NB: Oracle execution plan, from interactive Benthic test, uses + // fast access via the 1D index on objectId + // (UPDATE STATEMENT, UPDATE, INDEX UNIQUE SCAN) + coral::AttributeList updateData; + updateData.extend + ( "until", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::iovUntil) ); + updateData.extend + ( "objId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::objectId) ); + std::string setClause = RelationalObjectTable::columnNames::iovUntil(); + setClause += "= :until"; + setClause += ", "; + setClause += RelationalObjectTable::columnNames::lastModDate(); + setClause += " = " + queryMgr().serverTimeClause(); + std::string whereClause = RelationalObjectTable::columnNames::objectId(); + whereClause += "= :objId"; + + int dataCacheSize = 100; // rows + boost::shared_ptr<IRelationalBulkOperation> query = + db().queryMgr().bulkUpdateTableRows + ( objectTableName, setClause, whereClause, updateData, dataCacheSize ); + + for ( std::map<unsigned int,ValidityKey>::const_iterator + i = objectIdNewUntil.begin(); i != objectIdNewUntil.end(); ++i ) { + updateData["objId"].setValue( i->first ); + updateData["until"].setValue( i->second ); + query->processNextIteration(); + } + query->flush(); + +} + +//----------------------------------------------------------------------------- + +// TODO Andrea/Romain: do we really need channelId here? +// Roman noted that the 'SELECT IN' query could be rewritten without the +// loop on the channel table... but maybe actually what needs to be done +// is to keep the loop on the channels table and remove the selection +// on channelId in the WHERE clause (update all channels in bulk)? + +bool RelationalObjectMgr::bulkUpdateObjectTableNewHeadId +( const std::string& objectTableName, + const std::string& channelTableName, + const SOVector& updateNewHeads, + unsigned int userTagId ) const +{ + log() << "Bulk update IOV table" << coral::MessageStream::endmsg; + + // Bind variable values for the SET and WHERE clauses + coral::AttributeList updateData; + updateData.extend + ( "newHeadId", + typeIdToCoralType( RelationalObjectTable::columnTypeIds::newHeadId ) ); + updateData.extend + ( "channel", + typeIdToCoralType( RelationalObjectTable::columnTypeIds::channelId ) ); + updateData.extend + ( "userTagId", + typeIdToCoralType( RelationalObjectTable::columnTypeIds::userTagId ) ); + updateData.extend + ( "userTagId1", + typeIdToCoralType( RelationalObjectTable::columnTypeIds::userTagId ) ); + updateData.extend + ( "since1", + typeIdToCoralType( RelationalObjectTable::columnTypeIds::iovSince ) ); + updateData.extend + ( "since2", + typeIdToCoralType( RelationalObjectTable::columnTypeIds::iovSince ) ); + updateData.extend + ( "until1", + typeIdToCoralType( RelationalObjectTable::columnTypeIds::iovUntil ) ); + updateData.extend + ( "since3", + typeIdToCoralType( RelationalObjectTable::columnTypeIds::iovSince ) ); + + // Prepare the SET clause + std::string setClause = RelationalObjectTable::columnNames::newHeadId(); + setClause += "= :newHeadId"; + setClause += ", "; + setClause += RelationalObjectTable::columnNames::lastModDate(); + setClause += " = " + queryMgr().serverTimeClause(); + + // Prepare the WHERE clause + std::string whereClause; + if ( queryMgr().databaseTechnology() == "MySQL" || + getenv( "COOL_TASK6086_DISABLERBUPDATE" ) ) + { + // Prepare the WHERE clause (COOL230 all backends and COOL231 MySQL) + whereClause = RelationalObjectTable::columnNames::channelId(); + whereClause += "= :channel"; + whereClause += " AND "; + whereClause += RelationalObjectTable::columnNames::userTagId(); + whereClause += "= :userTagId"; + whereClause += " AND "; + whereClause += RelationalObjectTable::columnNames::newHeadId(); + whereClause += "= 0"; + whereClause += " AND "; + // Also see SimpleObject::overlaps for this clause + std::string s = RelationalObjectTable::columnNames::iovSince(); + std::string u = RelationalObjectTable::columnNames::iovUntil(); + whereClause += "("; + whereClause += "( ( " + s + " <= :since1 ) AND ( :since2 < " +u+ " ) )"; + whereClause += " OR ( ( :since3 <= " +s+ " ) AND ( " +s+ " < :until1 ) )"; + whereClause += ")"; + } + else + { + std::string schemaPrefix = ""; + if ( queryMgr().schemaName() != "" ) + schemaPrefix = queryMgr().schemaName() + "."; + + // Prepare the WHERE clause (COOL231 Oracle/Frontier/SQLite by Romain) + // Latest change by Andrea: MERGE subqueries to simplify the SQL query: + // result is very similar to RelationaObjectTable::queryDefinitionGeneric + whereClause = RelationalObjectTable::columnNames::objectId(); + whereClause += " IN ( SELECT "; + whereClause += "/*+ QB_NAME(BROWSE3) "; + if ( queryMgr().databaseTechnology() == "Oracle" || + queryMgr().databaseTechnology() == "frontier" ) + { + whereClause += "INDEX_RS_ASC(@BROWSE3 COOL_I3@BROWSE3 (USER_TAG_ID "; + whereClause += "NEW_HEAD_ID CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + whereClause += "LEADING(@BROWSE3 COOL_C2@BROWSE3 COOL_I3@BROWSE3) "; + whereClause += "USE_NL(@BROWSE3 COOL_I3@BROWSE3) "; + whereClause += "INDEX(@MAX1 COOL_I1@MAX1 (USER_TAG_ID "; + whereClause += "NEW_HEAD_ID CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + } + whereClause += "*/ "; + whereClause += "COOL_I3."; + whereClause += RelationalObjectTable::columnNames::objectId(); + whereClause += " FROM " ; + whereClause += schemaPrefix + channelTableName + " COOL_C2, "; + whereClause += schemaPrefix + objectTableName + " COOL_I3 "; + whereClause += "WHERE COOL_C2.CHANNEL_ID=:channel "; + whereClause += "AND COOL_I3.USER_TAG_ID=:userTagId "; + whereClause += "AND COOL_I3.NEW_HEAD_ID=0 "; + whereClause += "AND COOL_I3.CHANNEL_ID=COOL_C2.CHANNEL_ID "; + whereClause += "AND COOL_I3.IOV_SINCE>= " ; + whereClause += "COALESCE( "; + whereClause += "( SELECT /*+ QB_NAME(MAX1) */ "; + whereClause += "MAX(COOL_I1.IOV_SINCE) FROM "; + whereClause += schemaPrefix + objectTableName + " COOL_I1 "; + whereClause += "WHERE "; + whereClause += "COOL_I1.USER_TAG_ID= :userTagId1 AND "; + whereClause += "COOL_I1.NEW_HEAD_ID=0 AND "; + whereClause += "COOL_I1.CHANNEL_ID=COOL_C2.CHANNEL_ID AND "; + whereClause += "COOL_I1.IOV_SINCE<=:since1 ) "; + whereClause += ",:since2) "; + whereClause += "AND COOL_I3.IOV_SINCE<:until1 "; + whereClause += "AND COOL_I3.IOV_UNTIL>:since3 "; + whereClause += " ) "; + } + + int dataCacheSize = 100; // rows + boost::shared_ptr<IRelationalBulkOperation> query = + db().queryMgr().bulkUpdateTableRows + ( objectTableName, setClause, whereClause, updateData, dataCacheSize ); + //std::cout << "*** setClause: " << setClause << std::endl; + //std::cout << "*** whereClause: " << whereClause << std::endl; + + ObjectId minNewHeadId = 0; + for ( SOIterator interval = updateNewHeads.begin(); + interval != updateNewHeads.end(); + ++interval) + { + // where data + updateData["channel"].setValue( (unsigned int) interval->channelId ); + updateData["userTagId"].setValue( userTagId ); + updateData["userTagId1"].setValue( userTagId ); + updateData["since1"].setValue( interval->since ); + updateData["since2"].setValue( interval->since ); + updateData["since3"].setValue( interval->since ); + updateData["until1"].setValue( interval->until ); + // set data + updateData["newHeadId"].setValue( interval->objectId ); + if ( minNewHeadId == 0 || interval->objectId < minNewHeadId ) + minNewHeadId = interval->objectId; + //std::cout << " [ " << interval->since + // << ", " << interval->until << " [ oID " + // << interval->objectId << std::endl; + query->processNextIteration(); + } + query->flush(); + + // Check if any rows have been updated + bool updated = false; + { + RelationalQueryDefinition checkDef; + // This triggers bug #43528 + //std::string schemaPrefix = ""; + //if ( queryMgr().schemaName() != "" ) + // schemaPrefix = queryMgr().schemaName() + "."; + //checkDef.addFromItem( schemaPrefix + objectTableName ); + checkDef.addFromItem( objectTableName ); + checkDef.setWhereClause + ( RelationalObjectTable::columnNames::userTagId() + "=:userTagId AND " + + RelationalObjectTable::columnNames::newHeadId() + ">=:minNewHeadId" ); + RecordSpecification checkDataSpec; + checkDataSpec.extend + ( "userTagId", RelationalObjectTable::columnTypeIds::userTagId ); + checkDataSpec.extend + ( "minNewHeadId", RelationalObjectTable::columnTypeIds::newHeadId ); + Record checkData( checkDataSpec ); + checkData["userTagId"].setValue( userTagId ); + checkData["minNewHeadId"].setValue( minNewHeadId ); + checkDef.setBindVariables( checkData ); + UInt32 updatedRows = queryMgr().countRows( checkDef ); + if ( updatedRows > 0 ) updated = true; + //std::cout << "Number of updated rows: " << updatedRows << std::endl; + } + return updated; +} + +//----------------------------------------------------------------------------- + +int RelationalObjectMgr::truncateObjectValidity +( const RelationalFolder* folder, + const ValidityKey& until, + const ChannelSelection& channels ) const +{ + if ( folder->versioningMode() != FolderVersioning::SINGLE_VERSION ) + throw RelationalException("Truncating of IOVs is only supported for " + "single version Folders.", + "RelationalObjectMgr"); + + bool readOnly = false; + RelationalTransaction transaction( transactionMgr(), readOnly ); + RelationalObjectTable objectTable( &(queryMgr()), false, *folder ); + std::map<unsigned int,ValidityKey> objectIdNewUntil; + int count=0; + + // get all rows in [until, until[ + const std::auto_ptr<IRelationalQueryDefinition> + def( objectTable.queryDefinitionSV( until, until, channels ) ); + std::vector<RelationalTableRow> result = queryMgr().fetchOrderedRows( *def, + "SV truncate object validity"); + + // Process the result set + for ( std::vector<RelationalTableRow>::const_iterator + i = result.begin(); i != result.end(); ++i ) { + RelationalObjectTableRow obj( *i ); + if ( obj.until() == ValidityKeyMax ) { + objectIdNewUntil[ obj.objectId() ] = until; + count++; + } else + throw RelationalException("Truncating IOVs is only allowed for " + "until +inf IOVs", "RelationalObjectMgr"); + } + + // Bulk update the rows with open IOVs + bulkUpdateObjectTableIov( folder->objectTableName(), objectIdNewUntil ); + transaction.commit(); + return count; +} + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::bulkInsertObjectTableRows +( const std::string& objectTableName, + const std::vector<RelationalObjectTableRow>& rows, + const RecordSpecification& rowSpec ) const +{ + // Check that there are >0 rows to store + unsigned int nRows = rows.size(); + if ( nRows == 0 ) { + log() << "No rows to store into table " + << objectTableName << coral::MessageStream::endmsg; + return; + } + log() << "Bulk inserting " << nRows << " rows into table " + << objectTableName << coral::MessageStream::endmsg; + + // Get a new IOV ID from the sequence + // Get also the corresponding database server system date + boost::shared_ptr<RelationalSequence> objectIdSeq + ( queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName( objectTableName ) ) ); + std::string sysDate = objectIdSeq->currDate(); + + bool useBulkInserter = true; + // Setup the relational table bulk inserter + + // AV 07.03.2007 - fix for bug #24464 + // (record to be stored may have fewer fields and in a different order!) + // [NB - this may lead to C++ performance degradations] + //coral::AttributeList data( rows[0].data() ); + RecordSpecification tableSpec = + RelationalObjectTable::tableSpecification( rowSpec ); + coral::AttributeList data( Record( tableSpec ).attributeList() ); + + boost::shared_ptr<IRelationalBulkOperation> bulkInserter; + if ( useBulkInserter ) + bulkInserter = db().queryMgr().bulkInsertTableRows + ( objectTableName, data, nRows ); + + // Iterate through the objects and register them for insertion + std::vector<RelationalObjectTableRow>::const_iterator row; + for ( row = rows.begin(); row != rows.end(); ++row ) { + + // AV 30.11.2006 - fast is not the fastest! we should use share? + //data.fastCopyData( row->data() ); + + // AV 07.03.2007 - fix for bug #24464 + // (record to be stored may have fewer fields and in a different order!) + for ( coral::AttributeList::iterator + iAtt = data.begin(); iAtt != data.end(); ++iAtt ) + iAtt->setNull(); + for ( coral::AttributeList::const_iterator + iAtt = row->data().begin(); iAtt != row->data().end(); ++iAtt ) + { + const std::string& name = iAtt->specification().name(); + try { + data[name].fastCopy( *iAtt ); + } + catch ( coral::AttributeListException& ) { + throw RelationalException + ( "A field with name '" + name + + "' does not exist in the folder payload specification", + "RelationalObjectMgr" ); + } + } + + // TEMPORARY! sysInsTime and lastUpdate as string rather than DATE + data[RelationalObjectTable::columnNames::sysInsTime()] + .setValue( sysDate ); + data[RelationalObjectTable::columnNames::lastModDate()] + .setValue( sysDate ); + + // Verbose printout: print the full row that is being inserted into the DB + // TEMPORARY? Speed up insertion by disabling IOV streaming to MsgStream + /* + std::ostringstream dataStream; + data.print( dataStream ); + log() << "Insert into the IOV table the following AttributeList: " + << dataStream.str() << coral::MessageStream::endmsg; + */ + + // TEMPORARY? Will RAL do this as well? + // Check that all column values are within their allowed range + rowSpec.validate( data, false ); // data only ( no spec size ) + + // Insert the new object in the IOV table + if ( useBulkInserter ){ + bulkInserter->processNextIteration(); + } else { + queryMgr().insertTableRow( objectTableName, data ); + } + } + + // Flush the bulk inserter + if ( useBulkInserter ) + bulkInserter->flush(); + +} + +//----------------------------------------------------------------------------- + +/// Channel comparison functor to compare RelationalObjectPtrs +class eq_channel + : public std::unary_function<RelationalObjectPtr, bool> +{ +public: + eq_channel( const ChannelId& channel ) : m_channelid( channel ) {} + bool operator()( const RelationalObjectPtr& obj ) const + { + return ( obj->channelId() == m_channelid ); + } +private: + ChannelId m_channelid; +}; + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::updateSingleVersionIovs +( RelationalFolder* folder, + const std::pair<ChannelIdValidityKeyMap,ChannelIdObjectIdMap>& intersectors, + const std::vector<RelationalObjectPtr>& objects ) const +{ + RelationalObjectTable objectTable( &(queryMgr()), false, *folder ); + log() << "Update SV IOVs" << coral::MessageStream::endmsg; + + // The first map contains the new 'since' per channel for update in the + // channel table + const ChannelIdValidityKeyMap& channelSince = intersectors.first; + // The second map contains the new 'lastObjectId' per channel for update in + // the channel table. We make a copy, because it potentially has to be + // modified in the 'back-insertion' algorithm. + ChannelIdObjectIdMap channelLastObjectId = intersectors.second; + + // Flag the channels that have new data for the later join + + + // Implementation of task #2009, comment #13: + // Try the bulk insertion first, check by counting if the expected number + // of channels has been flagged in the channels table and if so proceed + // with the bulk insertion. + // If the count is not what expected, fall back to single update version. + { + // Flag the channels in need of an update in the channels table + bool hasNewData = true; + unsigned int lastObjectId = 0; // dummy - ignored + std::map< ChannelId, unsigned int > updateDataMap; + for ( ChannelIdValidityKeyMap::const_iterator + i = channelSince.begin(); i != channelSince.end(); ++i ) + { + const ChannelId& channel = i->first; + updateDataMap[channel] = lastObjectId; + } + bulkUpdateChannelTable + ( folder->channelTableName(), updateDataMap, hasNewData ); + } + + // Fetch the 'last row' for each channel with new data + std::vector<RelationalObjectTableRow> lastRows; + fetchLastRowsWithNewData( folder, lastRows ); + + // This map records the object ids in need of an until update + std::map<unsigned int,ValidityKey> objectIdNewUntil; + + // Update the IOVs of the last rows if required + for ( std::vector<RelationalObjectTableRow>::const_iterator + row = lastRows.begin(); row != lastRows.end(); ++row ) { + // check IOV + // bulk update if necessary + ChannelId channel = row->channelId(); + ChannelIdValidityKeyMap::const_iterator + intersector = channelSince.find( channel ); + ValidityKey newUntil = + intersector != channelSince.end() + ? intersector->second + : // this can't possibly happen as we only select rows that have + // previously been marked from this very map. This throw only + // completes the code path. + throw RelationalException( "Channel without corresponding " + "intersector", "RalDatabase" ); + if ( row->until() == ValidityKeyMax && + row->since() < newUntil ) { + // Record this object id for IOV update + objectIdNewUntil[row->objectId()] = newUntil; + } else if ( newUntil < row->until() ) { + // task #3138: Change SV requirement to "do not overlap" + // instead of "do not backinsert" + + // Prepare a channel comparator to filer on the current channel + eq_channel channel_cmp( channel ); + + // Find all objects in the current channel and count them + std::vector<RelationalObjectPtr>::const_iterator + i = find_if( objects.begin(), objects.end(), channel_cmp ); + int count = 0; + RelationalObjectPtr obj = *i; + if ( i != objects.end() ) { + ++count; + if ( find_if( ++i, objects.end(), channel_cmp ) != objects.end() ) { + ++count; + } + } + + // We can do back-insertion only if there's no more than one IOV in + // this channel + if ( count == 1 ) { + // Select [since, until[ and check for 0 iovs -- otherwise we have + // an overlap + ValidityKey until = obj->until(); + // We want to select [since, until[ but the countRows method selects + // [since, until] (i.e. including the upper bound. Therefore we need + // to decrement the until value. This might seem dodgy but: + // 1. it allows us to reuse the count query instead of writing a new + // one with :until < iov_until instead of '<=' + // 2. it is safe as long as the ValidityKey type defines operator--. + // Currently it's an integer type and therefore safe. A note + // regarding this has been added to the type definition. The only + // foreseeable problem with this change is if ValidityKey should + // ever turn into an 'non-decrementable' type, e.g. a float. + // If that should happen, implementing operator-- will not be + // possible and the warning placed at ValidityKey's place of + // definition will lead to this place. + --until; + // Count the objects in [since, until[ + const std::auto_ptr<IRelationalQueryDefinition> + def( objectTable.queryDefinitionSV( obj->since(), until, channel ) ); + //const std::auto_ptr<IRelationalQueryDefinition> + // def( objectTable.queryDefinitionGeneric + // ( obj->since(), until, channel ) ); + int count = queryMgr().countRows( *def, "SV object count" ); + if ( count != 0 ) { + // We have a collision + log() << coral::Verbose + << "Exception - overlapping intervals: new until = " + << newUntil << ", last until = " + << row->until() << coral::MessageStream::endmsg; + throw RelationalException + ( "Back-insertion collision: " + "overlapping intervals not allowed in SINGLE_VERSION mode", + "RalDatabase" ); + } + // No collision, we can back-insert. We also have to update the + // 'lastObjectId' update map for this channel, because it currently + // has the newly (back-inserted) object id recorded for this channel. + // Since we're back-inserted it's not the true 'lastObjectId'. This + // is actually the 'row' object (the current iterator of lastRows in + // this loop) which has been fetched via 'fetchLastRowsWithNewData'. + channelLastObjectId[channel] = row->objectId(); + } else { + log() << coral::Verbose + << "Exception - overlapping intervals: new until = " + << newUntil << ", last until = " << row->until() + << coral::MessageStream::endmsg; + throw RelationalException + ( "Back-insertion not possible due to multiple objects in channel" ); + } + } + } + + // Bulk update the rows with open IOVs + bulkUpdateObjectTableIov( folder->objectTableName(), objectIdNewUntil ); + + // Bulk update the channel table data + bool hasNewData = false; + std::map< ChannelId, unsigned int > updateDataMap; + for ( ChannelIdObjectIdMap::const_iterator + i = channelLastObjectId.begin(); i != channelLastObjectId.end(); ++i ) + { + const ChannelId& channel = i->first; + const unsigned int& lastObjectId = i->second; + updateDataMap[channel] = lastObjectId; + } + bulkUpdateChannelTable + ( folder->channelTableName(), updateDataMap, hasNewData ); + +} + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::fetchLastRowsWithNewData +( RelationalFolder* folder, + std::vector<RelationalObjectTableRow>& rows ) const +{ + // NEW (with RelationalQueryDefinition) + RelationalQueryDefinition def; + + // Use a hint to stabilize the execution plan (task #5654) + def.setHint( "/*+ INDEX(C) INDEX_RS_ASC(O) LEADING(C O) USE_NL(C O) */" ); + //def.setHint( "/*+ INDEX(O) */" ); // BAD (Oracle bug 4323868) + //def.setHint( "/*+ LEADING(C O) USE_HASH(C O) */" ); // BAD (as COOL_2_2_1) + + RelationalObjectTable objectTable( &(queryMgr()), false, *folder ); + def.addSelectItems( objectTable.tableSpecification(), "O." ); + def.setResultSetSpecification( objectTable.tableSpecification() ); + + def.addFromItem( folder->objectTableName(), "O" ); + def.addFromItem( folder->channelTableName(), "C" ); + + std::string whereClause; + whereClause += + "C." + RelationalChannelTable::columnNames::hasNewData() + + " = :hasNewData"; + whereClause += " AND "; + whereClause += + "C." + RelationalChannelTable::columnNames::lastObjectId() + " = " + "O." + RelationalObjectTable::columnNames::objectId(); + def.setWhereClause( whereClause ); + + def.addOrderItem + ( "C." + RelationalChannelTable::columnNames::channelId() + " ASC" ); + + RecordSpecification whereDataSpec; + whereDataSpec.extend( "hasNewData", StorageType::Bool ); + Record whereData( whereDataSpec ); + whereData["hasNewData"].setValue( true ); + def.setBindVariables( whereData ); + + std::vector<RelationalTableRow> result = queryMgr().fetchOrderedRows( def ); + + // Process the result set + for ( std::vector<RelationalTableRow>::const_iterator + i = result.begin(); i != result.end(); ++i ) { + rows.push_back( RelationalObjectTableRow( *i ) ); + } + +} + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::__storeObjects +( RelationalFolder* folder, + const std::vector<RelationalObjectPtr>& objects, + bool userTagOnly ) const +{ + log() << "Store " << objects.size() << " objects into folder " + << folder->fullPath() << coral::MessageStream::endmsg; + FolderVersioning::Mode versioningMode = folder->versioningMode(); + if ( versioningMode == FolderVersioning::SINGLE_VERSION ) + { + if ( userTagOnly ) + { + std::stringstream msg; + msg << "Single version folder: userTagOnly is meaningless"; + throw RelationalException( msg.str(), + "RelationalObjectMgr::storeObjects" ); + } + __storeSingleVersionObjects( folder, objects ); + } + else if ( versioningMode == FolderVersioning::MULTI_VERSION ) + { + __storeMultiVersionObjects( folder, objects, userTagOnly ); + } + else + { + std::stringstream s; + s << "invalid versioning mode: " << versioningMode; + throw RelationalException( s.str(), "RalDatabase" ); + } +} + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::__storeSingleVersionObjects +( RelationalFolder* folder, + const std::vector<RelationalObjectPtr>& objects ) const +{ + log() << "Store " << objects.size() << " SV Objects into folder '" + << folder->fullPath() << "'" << coral::MessageStream::endmsg; + + if ( objects.empty() ) return; + // check for a user tag being specified + for ( std::vector<RelationalObjectPtr>::const_iterator + i = objects.begin(); i != objects.end(); ++i ) { + if ( (*i)->userTagName() != "" ) { + std::stringstream s; + s << "Cannot store a SV object with user tag: " << (*i)->userTagName(); + throw FolderIsSingleVersion + ( folder->fullPath(), s.str(), "RalDatabase" ); + } + } + + RecordSpecification rowSpec = folder->payloadSpecification(); + + std::vector<RelationalObjectTableRow> rows; + + // Set the objectIdOffset: We start from the current sequence value +1 + boost::shared_ptr<RelationalSequence> objectIdSeq + ( queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName( folder->objectTableName() ) ) ); + unsigned int objectIdOffset = objectIdSeq->currVal() +1; + objectIdSeq->nextVal( objects.size() ); + + std::pair<ChannelIdValidityKeyMap,ChannelIdObjectIdMap> + intersectors( processSingleVersionObjects + ( objects, rows, objectIdOffset ) ); + + updateSingleVersionIovs( folder, intersectors, objects ); + + bulkInsertObjectTableRows( folder->objectTableName(), rows, rowSpec ); +} + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::__storeMultiVersionObjects +( RelationalFolder* folder, + const std::vector<RelationalObjectPtr>& objects, + bool userTagOnly ) const +{ + log() << "Store " << objects.size() << " MV Objects into folder '" + << folder->fullPath() << "'" << coral::MessageStream::endmsg; + + if ( objects.empty() ) return; + + // confirm that all objects have the same tagName (if any) + std::string userTagName( objects[0]->userTagName() ); + for ( std::vector<RelationalObjectPtr>::const_iterator + i = objects.begin(); i != objects.end(); ++i ) + { + if ( (*i)->userTagName() != userTagName ) + { + std::stringstream s; + s << "Conflicting tag '" << (*i)->userTagName() << "' specified " + << "during bulk insertion"; + throw RelationalException( s.str(), "RalDatabase" ); + } + } + + // Determine user tag id (by fetching or creation) + // Any HEAD tag ("", "head", "HEAD", "Head"...) -> no user tag (userTagId=0) + // NB Cannot make a difference between "" and "HEAD"!!! + unsigned int userTagId; + bool partiallyLocked=false; + if ( IHvsNode::isHeadTag( userTagName ) ) + { + userTagId = 0; + } + + // Proper user tag - check if tag exists or must be created + else + { + bool createTag = false; + if ( ! tagMgr().existsTag( userTagName ) ) + { + // Tag does not exist in any folder - create it + createTag = true; + } + else + { + try + { + // Tag exists in this folder - check if user tag or standard (HEAD) tag + RelationalTableRow tagRow = + tagMgr().fetchGlobalTagTableRow( folder->id(), userTagName ); + userTagId = + tagRow[RelationalTagTable::columnNames::tagId] + .data<unsigned int>(); + // Throw TagIsLocked if the tag is locked + HvsTagLock::Status lockStatus = + HvsTagLock::Status + ( tagRow[RelationalGlobalTagTable::columnNames::tagLockStatus] + .data<UInt16>() ); + if ( lockStatus == HvsTagLock::LOCKED ) + throw TagIsLocked + ( "Cannot store objects with user tag '" + userTagName + + "': tag is locked", "RelationalObjectMgr" ); + if ( lockStatus == HvsTagLock::PARTIALLYLOCKED ) + partiallyLocked=true; + + // Tag is a standard tag in this folder - throw TagExists (can't mix!) + // TODO - performance (see task #4381) + if ( RelationalFolder::existsTagInObject2TagTable + ( queryMgr(), userTagId, folder->object2TagTableName() ) ) + throw TagExists( userTagName, "RalDatabase" ); + // Else tag exists already either because of user tag or HVS + // (should we check and throw a PANIC exception otherwise?) + } + catch ( TagNotFound& ) + { + // TEMPORARY! Eventually can use same tag in several folders! + // Tag exists in another folder - throw TagExists + throw TagExists( userTagName, "RalDatabase" ); + } + } + if ( createTag ) + { + // Get a new tag ID and insert the new tag in the global tag table + // PERFORMANCE WARNING - createTag() will query existsTag() a 2nd time + std::string description = ""; + HvsTagRecord userTag = + //tagMgr().createTag( folder->id(), userTagName, description ); + tagMgr().createTagAndLocalTag + ( folder->id(), userTagName, description, folder->tagTableName() ); + userTagId = userTag.id(); + } + } + + log() << "All MV Objects have the same user tag '" + << userTagName << "' (tagId=" << userTagId << ")" + << coral::MessageStream::endmsg; + + // Set the objectIdOffset: We start from the current sequence value +1 + boost::shared_ptr<RelationalSequence> objectIdSeq + ( queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName( folder->objectTableName() ) ) ); + unsigned int objectIdOffset = objectIdSeq->currVal() +1; + // Reserve ids for two system objects in addition to the user object + // and also leave room for the user tag ids: + // therefore 6*size() + objectIdSeq->nextVal( ObjectIdIncrement * objects.size() ); + + std::vector<RelationalObjectTableRow> rows; + std::map<unsigned int, unsigned int> idToIndex; + + // Insert global head objects + // (append the global head rows to the 'rows' vector) + if ( ! userTagOnly ) + { + std::vector<SimpleObject> + intersectors( processMultiVersionObjects + ( objects, rows, objectIdOffset, idToIndex ) ); + mergeWithHead( folder, intersectors, rows, idToIndex ); + } + + // Insert user tag head objects + // (append the user tag rows to the 'rows' vector) + if ( ! IHvsNode::isHeadTag( userTagName ) ) + { + std::vector<RelationalObjectTableRow> userTagRows; + std::map<unsigned int, unsigned int> idToIndexUserTagRows; + + std::vector<SimpleObject> userTagIntersectors + ( processMultiVersionObjects( objects, + userTagRows, + objectIdOffset, + idToIndexUserTagRows, + userTagId, + partiallyLocked ) ); + + // Compute the user tag head rows (to be appended to the 'rows' vector) + mergeWithHead( folder, userTagIntersectors, userTagRows, + idToIndexUserTagRows, userTagId, partiallyLocked ); + + // Append user tag head rows into the 'rows' vector + std::copy( userTagRows.begin(), + userTagRows.end(), + std::back_inserter( rows ) ); + + } + + // Fill the channel table for MV folders (fix bug #23755). + // Analyse the 'rows' vector to extract the channels that need an update. + // BulkUpdate must be called twice - first with hasNewData==true (so that + // the single row update/insert can work) and then with hasNewData==false. + // For the first execution, lastObjectId must be set to 0 + // (just use the map to indicate which channels are updated). + std::map< ChannelId, unsigned int > updateDataMap; + std::vector<RelationalObjectTableRow>::const_iterator row; + for ( row = rows.begin(); row != rows.end(); ++row ) + { + const ChannelId& channel = row->channelId(); + updateDataMap[channel] = 0; + } + bool hasNewData = true; + bulkUpdateChannelTable + ( folder->channelTableName(), updateDataMap, hasNewData ); + // For the second execution, compute the highest objectId in each channel + for ( row = rows.begin(); row != rows.end(); ++row ) + { + const ChannelId& channel = row->channelId(); + const unsigned int& objectId = row->objectId(); + if ( updateDataMap[channel] < objectId ) + updateDataMap[channel] = objectId; + } + hasNewData = false; + bulkUpdateChannelTable + ( folder->channelTableName(), updateDataMap, hasNewData ); + + // Now write all head rows from the 'rows' vector into the database + // (both the global head rows and the user tag rows) + bulkInsertObjectTableRows( folder->objectTableName(), + rows, + folder->payloadSpecification() ); +} + +//----------------------------------------------------------------------------- + +std::pair<ChannelIdValidityKeyMap, ChannelIdObjectIdMap> +RelationalObjectMgr::processSingleVersionObjects +( const std::vector<RelationalObjectPtr>& objects, + std::vector<RelationalObjectTableRow>& rows, + unsigned int objectIdOffset ) const +{ + // records the lowest 'since' per channel + ChannelIdValidityKeyMap lowestSince; + // records the last object id per channel + ChannelIdObjectIdMap lastObjectIds; + // records the last object id from the 'objects' stack that has been + // validated in a given channel + std::map<ChannelId,unsigned int> prevObjects; + rows.reserve( objects.size() ); + + for ( unsigned int object_index = 0; + object_index < objects.size(); ++object_index ) { + + RelationalObjectPtr obj = objects[ object_index ]; + + RelationalObjectTableRow row( obj ); + row.setObjectId( object_index + objectIdOffset ); + + ValidityKey since = row.since(); + ValidityKey until = row.until(); + + // Internal consistency check: since<until (NB: since=until NOT ALLOWED!) + if ( since >= until ) + throw ValidityIntervalBackwards( since, until, "RalDatabase" ); + + // Validity key checks + if ( since > ValidityKeyMax ) + throw ValidityKeyOutOfBoundaries( since, "RalDatabase" ); + if ( until > ValidityKeyMax ) + throw ValidityKeyOutOfBoundaries( until, "RalDatabase" ); + + std::map<ChannelId,unsigned int>::iterator + prevObj = prevObjects.find( row.channelId() ); + if ( prevObj != prevObjects.end() ) { + + unsigned int index = prevObj->second; + + RelationalObjectTableRow& prevRow( rows[ index ] ); + + if ( prevRow.until() == ValidityKeyMax && + prevRow.since() < row.since() ) { + prevRow.setUntil( row.since() ); + } else if ( prevRow.until() > row.since() ) { + log() << coral::Verbose + << "Exception - overlapping intervals: new since = " + << row.since() << ", last until = " + << prevRow.until() << coral::MessageStream::endmsg; + throw RelationalException + ( "Overlapping intervals not allowed in SINGLE_VERSION mode", + "RalDatabase" ); + } + } + + prevObjects[ obj->channelId() ] = object_index; + + // update lowestSince map if there's no entry yet + if ( lowestSince.find( row.channelId() ) == lowestSince.end() ) { + lowestSince[ row.channelId() ] = row.since(); + } + // update last object id + lastObjectIds[ row.channelId() ] = row.objectId(); + + rows.push_back( row ); + } + + return std::make_pair( lowestSince, lastObjectIds ); +} + +//----------------------------------------------------------------------------- + +std::vector<SimpleObject> +RelationalObjectMgr::processMultiVersionObjects +( const std::vector<RelationalObjectPtr>& objects, + std::vector<RelationalObjectTableRow>& rows, + unsigned int objectIdOffset, + std::map<unsigned int, unsigned int>& idToIndex, + unsigned int userTagId, + bool partiallyLocked ) const +{ + + rows.reserve( objects.size() ); + + // The head is the current top layer of the object stack + std::vector<SimpleObject> head; + + // The bottom is the list of object intervals as seen from 'below' + // -- think of it as the head if you invert the layers. + std::vector<SimpleObject> bottom; + + for ( unsigned int object_index = 0; + object_index < objects.size(); ++object_index ) { + + RelationalObjectPtr obj = objects[ object_index ]; + + // Validity key checks + if ( obj->since() > ValidityKeyMax ) + throw ValidityKeyOutOfBoundaries( obj->since(), "RalDatabase" ); + if ( obj->until() > ValidityKeyMax ) + throw ValidityKeyOutOfBoundaries( obj->until(), "RalDatabase" ); + + // Objects in the rows vector are inserted with an + // object_id == 6*object_index + objectIdOffset + // to reserve object_ids that are possibly needed for system objecs + // created by mergeWithHead (maximum of two system objects per user object) + // Additional room is reserved for ids need by user tags in the future + // The object_id 0 is reserved for 'null' references + // (objectIdOffset is > 0) + RelationalObjectTableRow currentRow( obj ); + if ( userTagId == 0 ) { + currentRow.setObjectId + ( ObjectIdIncrement * object_index + objectIdOffset ); + } else { + // user tag objects have an objectId offset of 3 + currentRow.setObjectId + ( ObjectIdIncrement * object_index + objectIdOffset +3 ); + } + currentRow.setUserTagId( userTagId ); + idToIndex[ currentRow.objectId() ] = rows.size(); + rows.push_back( currentRow ); + + SimpleObject currentObject( currentRow.objectId(), + currentRow.channelId(), + currentRow.since(), + currentRow.until() ); + + // Check which objects in the head are affected + std::vector<SimpleObject> affectedObjs = currentObject.intersect( head ); + + if ( partiallyLocked && affectedObjs.size()!=0) + throw TagIsLocked + ( "Cannot store objects with user tag: " + "tag is partially locked " + "and there are overlapping IOVs in bulk insert", + "RelationalObjectMgr" ); + + // Add the current object to the head and, if it 'falls through' the + // current head, i.e. does not intersect with it, also to the bottom + head.push_back( currentObject ); + if ( affectedObjs.empty() ) bottom.push_back( currentObject ); + + for ( std::vector<SimpleObject>::const_iterator + headObj = affectedObjs.begin(); + headObj != affectedObjs.end(); + ++headObj ) { + + unsigned int headObjIndex = idToIndex[ headObj->objectId ]; + + // Update the newHeadId of the intersected head object and remove + // it from the head + rows[headObjIndex].setNewHeadId( currentObject.objectId ); + head.erase( remove( head.begin(), head.end(), *headObj ) ); + + // Cut the examined headObj with the currentObject. Create system + // objects from the intervals (one or two), set their originalId + // and add them to the head and the rows. + SOVector topVisibleIntervals = currentObject.filter( *headObj ); + for ( SOIterator interval = topVisibleIntervals.begin(); + interval != topVisibleIntervals.end(); + ++interval ) { + // assign the object id in a fixed order: + // [ sysobj: id+1 ][ userobj: id ][ sysobj: id+2 ] + unsigned int objectId = interval->since < currentObject.since + ? currentObject.objectId +1 + : currentObject.objectId +2; + idToIndex[ objectId ] = rows.size(); + log() << "Create system object: [" + << interval->since << "," << interval->until << "]" + << coral::MessageStream::endmsg; + RelationalObjectTableRow + sysObjRow = createSystemObjectRow + ( rows[headObjIndex], objectId, interval->since, interval->until ); + sysObjRow.setNewHeadId( 0 ); + rows.push_back( sysObjRow ); + SimpleObject sysObj( sysObjRow.objectId(), + sysObjRow.channelId(), + sysObjRow.since(), + sysObjRow.until() ); + head.push_back( sysObj ); + // Sort the head to ensure a reproducible order of system objects, + // such that the lower end system object always comes before the + // upper end system object. One could perhaps avoid the sort and + // bookkeep the indexes but sort is most likely not a performance + // problem. + sort( head.begin(), head.end(), lt_since() ); + } + + // Check which parts of the current object 'fall through' the current + // bottom -- i.e. which parts are visible from below -- + // and add them to the head. + SOVector visibleIntervals = currentObject.visibleThrough( bottom ); + bottom.insert + ( bottom.end(), visibleIntervals.begin(), visibleIntervals.end() ); + + } // for ( affectedObjs.begin() ) + + } // for ( objects.begin() + + return bottom; +} + +//----------------------------------------------------------------------------- + +// Types used in mergeWithHead +struct sIOV +{ + ValidityKey since; + ValidityKey until; + unsigned int count; +}; +typedef std::map<ValidityKey,RelationalObjectTableRow*> keyRowMap; + +//----------------------------------------------------------------------------- + +void RelationalObjectMgr::mergeWithHead +( RelationalFolder* folder, + const std::vector<SimpleObject> splitters, + std::vector<RelationalObjectTableRow>& rows, + std::map<unsigned int, unsigned int>& idToIndex, + unsigned int userTagId, + bool partiallyLocked ) const +{ + log() << "Merge with HEAD" << coral::MessageStream::endmsg; + + // The transient head is a list of head objects created from intersecting + // the persistent head with the 'splitters' intervals + SOVector transHead; + RelationalObjectTable objectTable( &(queryMgr()), false, *folder ); + + // load relevant objects of the persistent head into a map which + // can be accessed by channel -> iov_since + // there are now overlaps, so by this we can easily find the IOV + // which corresponds to a point in time + std::map<ChannelId, keyRowMap > channelIovRowMap; + + // owner of the row vectors! + // they are automatically deleted when the method is finished + boost::scoped_array< std::auto_ptr< std::vector<RelationalObjectTableRow> > > + channelsPersHead( 0 ); + + // find min and max IOV for each channel + std::map<ChannelId, sIOV> channelIov; + for ( SOIterator splitter = splitters.begin(); + splitter != splitters.end(); + ++splitter ) { + std::map<ChannelId, sIOV>::iterator it= + channelIov.find(splitter->channelId); + + if ( it == channelIov.end() ) { + // channel doesn't exist + struct sIOV iov; + iov.since=splitter->since; + iov.until=splitter->until; + iov.count=1; + channelIov[splitter->channelId]=iov; + } else { + if ( it->second.since > splitter->since ) + it->second.since = splitter->since; + if ( it->second.until < splitter->until ) + it->second.until = splitter->until; + ++it->second.count; + } + } + + // allocate array of auto_ptrs to vectors + channelsPersHead.reset + ( new std::auto_ptr< std::vector<RelationalObjectTableRow> > + [ channelIov.size() ]() ); + + // maximum number of rows that will be prefetched + unsigned int maxRows=1000; + if ( getenv("COOL_MVINSERTION_PREFETCH_MAXROWS") ) { + + std::stringstream rows( getenv("COOL_MVINSERTION_PREFETCH_MAXROWS" ) ); + rows >> maxRows; + if (rows.fail()) + log() << coral::Error << "setting MV insertion prefetch maxRows to '" + << getenv("COOL_MVINSERTION_PREFETCH_MAXROWS" ) + <<"' failed. Current maxRows value: " << maxRows + << coral::MessageStream::endmsg; + else + log() << coral::Info << "setting MV insertion prefetch maxRows to " + << maxRows << coral::MessageStream::endmsg; + log() << coral::Debug; + } + + int idx=0; + // load IOVs for all channels for which splitter exits + for (std::map<ChannelId, sIOV>::iterator + it = channelIov.begin(); + it != channelIov.end() && maxRows>0; + ++it, ++idx ) { + ChannelId cId=it->first; + + // don't prefetch channels with only one or less splitters + if (it->second.count <= 1) { + continue; + } + log() <<"loading persistent head for Channel " << cId + << " ["<< it->second.since << ", "<< it->second.until + << " [ splitter count "<< it->second.count + << " maxRows "<< maxRows << coral::MessageStream::endmsg; + + // load IOVs which are in the current head + // return 0 if more than maxRows rows would be loaded + channelsPersHead[idx] = objectTable.fetchRowsBtTimesInHead + ( it->second.since, it->second.until, cId, userTagId, maxRows ); + + // if channel contained too many to be overwritten IOVs skip this channel + if ( channelsPersHead[idx].get() == 0) { + log() << coral::Info + << "MV insertion maxRows limit reached. Not prefetching " + << "more IOVs" << coral::MessageStream::endmsg; + log() << coral::Debug; + continue; + } + maxRows-=channelsPersHead[idx]->size(); + + std::vector<RelationalObjectTableRow>& + currChannelRows( *(channelsPersHead[idx]) ); + + // fill map for channel with the rows + keyRowMap& IovMap=channelIovRowMap[cId]; + for (std::vector<RelationalObjectTableRow>::iterator + row=currChannelRows.begin(); row!=currChannelRows.end(); ++row) + { + IovMap[row->since()]=&(*row); + } + } + + // Vector to hold all splitters which require an update of the newHeadID + // of the persistent head. + SOVector newHeadUpdaters; + + log() << "Loop over splitters - begin" << coral::MessageStream::endmsg; + for ( SOIterator splitter = splitters.begin(); + splitter != splitters.end(); + ++splitter ) { + + log() << "Process splitter [" << splitter->since + << "," << splitter->until << "]" << coral::MessageStream::endmsg; + // Find affected objects from intersecting the transient head with splitter + SOVector affectedObjs = splitter->intersect( transHead ); + SOVector bottomVisibleIntervals = splitter->visibleThrough( transHead ); + + if ( partiallyLocked && affectedObjs.size() !=0 ) + throw RelationalException + ( "PANIC! Tag is partially locked and transHead is not empty!", + "RelationalObjectMgr" ); + + for ( SOIterator headObj = affectedObjs.begin(); + headObj != affectedObjs.end(); + ++headObj ) { + unsigned int headObjIndex = idToIndex[ headObj->objectId ]; + + // Update the newHeadId of the intersected head object and remove + // it from the transient head + rows[headObjIndex].setNewHeadId( splitter->objectId ); + transHead.erase + ( remove( transHead.begin(), transHead.end(), *headObj ) ); + + // Cut the examined headObj with the splitter. Create system + // objects from the intervals (one or two), set their originalId + // and add them to the transient head and the rows. + SOVector topVisibleIntervals = splitter->filter( *headObj ); + for ( SOIterator interval = topVisibleIntervals.begin(); + interval != topVisibleIntervals.end(); + ++interval ) { + unsigned int objectId = interval->since < splitter->since + ? splitter->objectId +1 + : splitter->objectId +2; + idToIndex[ objectId ] = rows.size(); + log() << "Create system object (intersecting transient HEAD): [" + << interval->since << "," << interval->until << "]" + << coral::MessageStream::endmsg; + RelationalObjectTableRow + sysObjRow = createSystemObjectRow + ( rows[headObjIndex], objectId, interval->since, interval->until ); + sysObjRow.setNewHeadId( 0 ); + rows.push_back( sysObjRow ); + SimpleObject sysObj( sysObjRow.objectId(), + sysObjRow.channelId(), + sysObjRow.since(), + sysObjRow.until() ); + transHead.push_back( sysObj ); + // Sort the head to ensure a reproducible order of system objects, + // such that the lower end system object always comes before the + // upper end system object. + sort( transHead.begin(), transHead.end(), lt_since() ); + } + + } // for ( affectedObjs.begin() ... ) + + // Now that the transient head has been examined we have to check + // which parts of the splitter have not been 'absorbed' by it and + // 'fall through' to the persistent head. + //SOVector bottomVisibleIntervals = splitter->visibleThrough( transHead ); + + for ( SOIterator interval = bottomVisibleIntervals.begin(); + interval != bottomVisibleIntervals.end(); + ++interval ) { + bool sortHead = false; + + try { // Check if we need to create a system object at the lower end + keyRowMap::iterator obj; + bool prefetched=false; + if ( channelIovRowMap.find(interval->channelId) != + channelIovRowMap.end() ) + { + // we have prefetched IOVs for this channel + prefetched=true; + keyRowMap& IovMap=channelIovRowMap[interval->channelId]; + obj=IovMap.upper_bound(interval->since); + // upper bound returns the next greater IOV, but we want the + // IOV just bevore interval->since + if ( obj != IovMap.begin() ) + --obj; + if ( obj == IovMap.end() ) + // no object at point interval->since + throw ObjectNotFound("temporary","mergeWithHead"); + } + RelationalObjectTableRow lowerEnd = + prefetched ? + *(obj->second) : + objectTable.fetchRowAtTimeInHead( interval->since, + interval->channelId, + userTagId ); + ValidityKey sysObjSince = lowerEnd.since(); + ValidityKey sysObjUntil = interval->since; + if ( lowerEnd.until()>interval->since && + lowerEnd.since()<interval->since && + sysObjUntil > sysObjSince // avoid 0 length IOVs + ) { + // will not be reached if no intersecting object + if ( partiallyLocked ) + throw TagIsLocked + ( "Cannot store objects with user tag: " + "tag is partially locked and the IOVs are overlapping with " + "tag head (IOV start)", + "RelationalObjectMgr" ); + + unsigned int objectId = interval->objectId +1; + idToIndex[ objectId ] = rows.size(); + log() << "Create system object (intersecting persistent HEAD" + << " at low end): [" << sysObjSince + << "," << sysObjUntil << "]" << coral::MessageStream::endmsg; + RelationalObjectTableRow + sysObjRow = createSystemObjectRow( lowerEnd, objectId, + sysObjSince, + sysObjUntil ); + sysObjRow.setNewHeadId( 0 ); + rows.push_back( sysObjRow ); + SimpleObject sysObj( sysObjRow.objectId(), + sysObjRow.channelId(), + sysObjRow.since(), + sysObjRow.until() ); + transHead.push_back( sysObj ); + sortHead = true; + } + + + } catch ( ObjectNotFound& /* ignored */ ) { } + + try { // Check if we need to create a system object at the upper end + keyRowMap::iterator obj; + bool prefetched=false; + if ( channelIovRowMap.find(interval->channelId) != + channelIovRowMap.end() ) + { + // we have prefetched IOVs for this channel + prefetched=true; + keyRowMap& IovMap=channelIovRowMap[interval->channelId]; + obj=IovMap.upper_bound(interval->until); + // upper bound returns the next greater IOV, but we want the + // IOV just bevore interval->since + if ( obj != IovMap.begin() ) + --obj; + if ( obj == IovMap.end() ) + // channel map is empty + throw ObjectNotFound("temporary","mergeWithHead"); + } + RelationalObjectTableRow upperEnd = + prefetched ? + *(obj->second) : + objectTable.fetchRowAtTimeInHead( interval->until, + interval->channelId, + userTagId ); + ValidityKey sysObjSince = interval->until; + ValidityKey sysObjUntil = upperEnd.until(); + if ( + upperEnd.since()<interval->until && + upperEnd.until()>interval->until && + + sysObjUntil > sysObjSince + // avoid 0 length IOVs + && + interval->until != upperEnd.since() + // needed because + // fetchObjectTableRowHead at pointInTime "interval->until" + // will fetch an object that *starts* at "interval->until" + // but we actually only want objects up to + // "interval->until - epsilon" + // Instead of using "interval->until -1" as point in time + // (which would assume granularity of 1 in IOVs) we select at + // "interval->until" and discard objects that start exactly at + // "interval->until", i.e. [a,b[ = [a,b] - [b] + ) + { + + // will not be reached if no intersecting object + if ( partiallyLocked ) + throw TagIsLocked + ( "Cannot store objects with user tag: " + "tag is partially locked and the IOVs are overlapping with " + "tag head (IOV end)", + "RelationalObjectMgr" ); + + unsigned int objectId = interval->objectId +2; + idToIndex[ objectId ] = rows.size(); + log() << "Create system object (intersecting persistent HEAD" + << " at high end): [" << sysObjSince + << "," << sysObjUntil << "]" << coral::MessageStream::endmsg; + RelationalObjectTableRow + sysObjRow = createSystemObjectRow( upperEnd, + objectId, + sysObjSince, + sysObjUntil ); + sysObjRow.setNewHeadId( 0 ); + rows.push_back( sysObjRow ); + SimpleObject sysObj( sysObjRow.objectId(), + sysObjRow.channelId(), + sysObjRow.since(), + sysObjRow.until() ); + transHead.push_back( sysObj ); + sortHead = true; + } + } catch ( ObjectNotFound& /* ignored */ ) { } + + // See above why we sort + if ( sortHead ) sort( transHead.begin(), transHead.end(), lt_since() ); + + // Update the newHeadIds of all overlapped head rows + keyRowMap::iterator obj; + bool callUpdate=true; + if ( channelIovRowMap.find(interval->channelId) != + channelIovRowMap.end() ) + { + // we have prefetched IOVs for this channel + keyRowMap& IovMap=channelIovRowMap[interval->channelId]; + obj=IovMap.upper_bound(interval->since); + // upper bound returns the next greater IOV, but we want the + // IOV just bevore interval->since + if ( obj != IovMap.begin() ) + --obj; + while (obj!=IovMap.end() && obj->second->until()<=interval->since ) + ++obj; + // check if in the prefetched row there is at least one + // which is covered by this splitter + if (obj==IovMap.end() || obj->second->since()>interval->until ) + callUpdate=false; + } + if ( callUpdate ) + newHeadUpdaters.insert(newHeadUpdaters.end(),*interval); + } // for ( bottomVisibleIntervals.begin() ... ) + + } // for ( splitters.begin() ... ) + if ( newHeadUpdaters.size()>0 ) + { + bool updated = bulkUpdateObjectTableNewHeadId( folder->objectTableName(), + folder->channelTableName(), + newHeadUpdaters, + userTagId ); + if ( partiallyLocked && updated ) + { + // Inserted IOV covers existing ivos + //std::cout << "ERROR: tag is partially locked and " + // << updated << " IOVS need to be updated" << std::endl; + throw TagIsLocked + ( "Cannot store objects with user tag: " + "tag is partially locked and the IOVs are overlapping " + "with tag head (covering existing IOV)", + "RelationalObjectMgr" ); + } + } + log() << "Loop over splitters - end" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalObjectTableRow +RelationalObjectMgr::createSystemObjectRow +( const RelationalObjectTableRow& origRow, + unsigned int objectId, + const ValidityKey& since, + const ValidityKey& until ) const +{ + RelationalObjectTableRow row( origRow ); + + // Update some fields + row.setObjectId( objectId ); + row.setSince( since); + row.setUntil( until ); + row.setOriginalId( origRow.objectId() ); + + return row; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalObjectMgr.h b/RelationalCool/src/RelationalObjectMgr.h new file mode 100644 index 000000000..eba9cd67e --- /dev/null +++ b/RelationalCool/src/RelationalObjectMgr.h @@ -0,0 +1,288 @@ +// $Id: RelationalObjectMgr.h,v 1.38 2008-11-06 15:43:02 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALOBJECTMGR_H +#define RELATIONALCOOL_RELATIONALOBJECTMGR_H + +// Include files +#include <memory> +#include "CoralBase/MessageStream.h" + +// Local include files +#include "ObjectId.h" +#include "RelationalFolder.h" +#include "RelationalObjectPtr.h" +#include "SimpleObject.h" + +namespace cool +{ + + // Forward declarations + class RelationalDatabase; + class RelationalQueryMgr; + class RelationalTagMgr; + class SimpleObject; + + // Type definitions + typedef std::map< ChannelId, ValidityKey > ChannelIdValidityKeyMap; + typedef std::map< ChannelId, ObjectId > ChannelIdObjectIdMap; + + /// @class RelationalObjectMgr RelationalObjectMgr.h + /// + /// RelationalObjectMgr handles object queries of a COOL database instance. + /// + /// @author Sven A. Schmidt + /// @date 2006-04-19 + /// + class RelationalObjectMgr + { + + friend class RelationalObjectMgrTest; + + public: + + // Virtual destructor + virtual ~RelationalObjectMgr() {} + + /// Constructor from a RelationalDatabase reference. + RelationalObjectMgr( const RelationalDatabase& db ); + + /// Find THE conditions object valid at the given point in time + IObjectPtr findObject( const RelationalFolder* folder, + const ValidityKey& pointInTime, + const ChannelId& channelId, + const std::string& tagName="" ) const; + + /// Browse the objects in a given folder for a given + /// channel selection within the given tag. + /// The iterator will retrieve only ONE object at any given validity point + /// for a given channel. The default order is channel, since if a channel + /// range is specified. + /// For SINGLE_VERSION folders, throw exception if tag != "" is specified. + IObjectIteratorPtr + browseObjects( const RelationalFolder* folder, + const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName = "", + const IRecordSelection* payloadQuery = 0, + const bool countOnly = false ) const; + + /// Store a list of conditions objects in the specified order + /// Do not start a transaction + void __storeObjects + ( RelationalFolder* folder, + const std::vector<RelationalObjectPtr> & objects, + bool userTagOnly = false ) const; + + /// Set a new finite end-of-validity value for all SV objects in a given + /// channel selection whose end-of-validity is currently infinite. + /// Throws an Exception if called on a MV folder, or if any of the + /// selected channels contains a not open ended IOV at the point until. + /// Returns the number of actually truncated IOVs. + int truncateObjectValidity( const RelationalFolder* folder, + const ValidityKey& until, + const ChannelSelection& channels ) const; + + /// Create a new channel + void createChannel( const RelationalFolder* folder, + const ChannelId& channelId, + const std::string& channelName, + const std::string& description="" ) const; + + /// Drop a channel + bool dropChannel( const RelationalFolder* folder, + const ChannelId& channelId ) const; + + /// Get the RelationalDatabase + const RelationalDatabase& db() const + { + return m_db; + } + + /// Get the RelationalQueryMgr + RelationalQueryMgr& queryMgr() const + { + return db().queryMgr(); + } + + /// Get the RelationalTagMgr + RelationalTagMgr& tagMgr() const + { + return db().tagMgr(); + } + + /// Get the IRelationalTransactionMgr + boost::shared_ptr<IRelationalTransactionMgr> transactionMgr() const + { + return db().transactionMgr(); + } + + protected: + + /// Get a CORAL MessageStream + coral::MessageStream& log() const; + + /// Insert a new channel table row. + void insertChannelTableRow( const std::string& channelTableName, + const ChannelId& channelId, + unsigned int lastObjectId, + bool hasNewData, + const std::string& channelName, + const std::string& description ) const; + + /// Updates lastObjectId and hasNewData for the given channel. + /// Column lastObjectId is updated only if hasNewData is false; if + /// hasNewData is true, the input lastObjectId must be 0 (else exception). + /// Check that lastObjectId is expected to be 0 if hasNewData is false. + /// If the channel does not exist, create it with the given metadata. + void updateChannelTable( const std::string& channelTableName, + const ChannelId& channelId, + unsigned int lastObjectId, + bool hasNewData ) const; + + /// Bulk update lastObjectId and hasNewData for the given channels + /// (but lastObjectId is updated only if hasNewData is false). + /// If hasNewData is true, also check whether bulk update fails because + /// some channels are missing, and in that case use single row update and + /// create any missing channels (NB this relies on hasNewData being + /// different from false in the database only while updating/inserting). + void bulkUpdateChannelTable + ( const std::string& channelTableName, + const std::map< ChannelId, unsigned int >& updateDataMap, + bool hasNewData ) const; + + /// Bulk update the IOV until values in the object table row with the + /// given ids in the objectIdNewUntil map. + void bulkUpdateObjectTableIov + ( const std::string& objectTableName, + const std::map<unsigned int,ValidityKey>& objectIdNewUntil ) const; + + /// Update the newHeadId value in the object table rows overlapping with + /// the given since, until interval. + /// Returns true if some rows have been updated. + bool + bulkUpdateObjectTableNewHeadId( const std::string& objectTableName, + const std::string& channelTableName, + const SOVector& updateNewHeads, + unsigned int userTagId ) const; + + /// Stores the given list of rows in the given iov table + /// NB: This method assumes that the objectIds of the rows are set + /// externally and that the objectId sequence is advanced. Since SV and MV + /// use different objectId assignment, this is necessary to be able to use + /// the some storage method for both. Only the insertionTime is updated + /// before flushing the rows to the database. + void bulkInsertObjectTableRows + ( const std::string& objectTableName, + const std::vector<RelationalObjectTableRow>& rows, + const RecordSpecification& rowSpec ) const; + + /// Updates open-ended IOVs for the given vector of intersectors. This list + /// is expected to contain one ValidityKey 'since' per channel indicating + /// the potential 'closing' IOV. + /// Throws an exception if any object with an until > since is found \e + /// unless this until is equal to ValidityKeyMax. + void updateSingleVersionIovs + ( RelationalFolder* folder, + const std::pair<ChannelIdValidityKeyMap, ChannelIdObjectIdMap>& + intersectors, + const std::vector<RelationalObjectPtr>& objects ) const; + + /// Fetches all object table rows for channels that have new data. + /// This method is used in multi channel bulk insertion and selects + /// the rows in (potential) need of open IOV updating. + void fetchLastRowsWithNewData + ( RelationalFolder* folder, + std::vector<RelationalObjectTableRow>& rows ) const; + + /// Stores objects in 'SingleVersion' mode + /// This does not start a transaction + void __storeSingleVersionObjects + ( RelationalFolder* folder, + const std::vector<RelationalObjectPtr>& objects ) const; + + /// Stores objects in 'MultiVersion' mode + /// This does not start a transaction + void __storeMultiVersionObjects + ( RelationalFolder* folder, + const std::vector<RelationalObjectPtr>& objects, + bool userTagOnly = false ) const; + + /// Validates the given objects for SV storage (with respect to overlapping + /// IOVs). Returns a map of channelIds with the lowest IOV per channel + /// of the objects for updating open-ended IOVs in the persistent store + /// and validating the insertion and a map of the last object ids per + /// channel which is used to update the channel table. + std::pair<ChannelIdValidityKeyMap, ChannelIdObjectIdMap> + processSingleVersionObjects + ( const std::vector<RelationalObjectPtr>& objects, + std::vector<RelationalObjectTableRow>& rows, + unsigned int objectIdOffset ) const; + + /// Processes 'MultiVersion' objects for bulk insertion: + /// - analyse the objects and insert system objects if required + /// - find and return potential 'intersections' from the given + /// objects that might cause splitting in the HEAD + /// - create consistent references references (original_id, + /// new_head_id) among the objects. In order to do this without + /// having to access the objectId sequence for each new system + /// object being inserted, the objectIdOffset is used and the + /// objectIds inside processMultiVersionObjects are created from this + /// offset. + /// - idToIndex is used to bookkeep the object id to 'rows' index + /// mapping. This is subsequently used by mergeWithHead to know + /// where to insert further system objects. + /// Throws an TagIsLocked exception if partiallyLocked==true and the IOVs + /// of the objects overlap + std::vector<SimpleObject> processMultiVersionObjects // OUT + ( const std::vector<RelationalObjectPtr>& objects, // IN + std::vector<RelationalObjectTableRow>& rows, // OUT + unsigned int objectIdOffset, // IN + std::map<unsigned int, unsigned int>& idToIndex, // OUT + unsigned int userTagId = 0, // IN + bool partiallyLocked = false ) const; // IN + + /// Merges the previously processed 'MultiVersion' objects (by + /// processMultiVersionObjects()) with the persistent head + /// Throws TagIsLocked exception if partiallyLocked==true and + /// there are overlapping IOVs + void mergeWithHead( RelationalFolder* folder, + const std::vector<SimpleObject> splitters, + std::vector<RelationalObjectTableRow>& rows, + std::map<unsigned int, unsigned int>& idToIndex, + unsigned int userTagId = 0, + bool partiallyLocked = false ) const; + + /// Creates a system object row templated from the given row + /// The iov and the object id are updated with the given values, + /// original_id is set to the original row's object_id + RelationalObjectTableRow + createSystemObjectRow( const RelationalObjectTableRow& origRow, + unsigned int objectId, + const ValidityKey& since, + const ValidityKey& until ) const; + + private: + + /// Standard constructor is private + RelationalObjectMgr(); + + /// Copy constructor is private + RelationalObjectMgr( const RelationalObjectMgr& rhs ); + + /// Assignment operator is private + RelationalObjectMgr& operator=( const RelationalObjectMgr& rhs ); + + private: + + /// The RelationalDatabase reference + const RelationalDatabase& m_db; + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + }; + +} // namespace + + +#endif // RELATIONALCOOL_RELATIONALOBJECTMGR_H diff --git a/RelationalCool/src/RelationalObjectPtr.h b/RelationalCool/src/RelationalObjectPtr.h new file mode 100644 index 000000000..d5048ccd7 --- /dev/null +++ b/RelationalCool/src/RelationalObjectPtr.h @@ -0,0 +1,19 @@ +// $Id: RelationalObjectPtr.h,v 1.1 2006-03-10 11:52:40 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALOBJECTPTR_H +#define RELATIONALCOOL_RELATIONALOBJECTPTR_H + +// Include files +#include <boost/shared_ptr.hpp> + +namespace cool { + + // Forward declarations + class RelationalObject; + + /// Shared pointer to a RelationalObject + typedef boost::shared_ptr<RelationalObject> RelationalObjectPtr; + +} + +#endif + diff --git a/RelationalCool/src/RelationalObjectTable.cpp b/RelationalCool/src/RelationalObjectTable.cpp new file mode 100644 index 000000000..af822bd87 --- /dev/null +++ b/RelationalCool/src/RelationalObjectTable.cpp @@ -0,0 +1,1509 @@ +// $Id: RelationalObjectTable.cpp,v 1.190 2009-01-08 13:55:50 avalassi Exp $ + +// Include files +#include "CoralBase/AttributeSpecification.h" +#include "CoralBase/Attribute.h" + +// Local include files +#include "HvsTagRecord.h" +#include "ObjectId.h" +#include "RelationalChannelTable.h" +#include "RelationalException.h" +#include "RelationalFolder.h" +#include "RelationalObject.h" +#include "RelationalObjectTable.h" +#include "RelationalObjectTableRow.h" +#include "RelationalObject2TagTable.h" +#include "RelationalPayloadQuery.h" +#include "RelationalQueryDefinition.h" +#include "RelationalQueryMgr.h" +#include "RelationalTagMgr.h" +#include "RelationalTagTable.h" +#include "timeToString.h" + +// Namespace +using namespace cool; + +//--------------------------------------------------------------------------- + +RelationalObjectTable::RelationalObjectTable +( RelationalQueryMgr* pQueryMgr, + bool ownQueryMgr, + const RelationalFolder& folder ) + : m_log( new coral::MessageStream( "RelationalObjectTable" ) ) + , m_pQueryMgr( pQueryMgr ) + , m_ownQueryMgr( ownQueryMgr ) + , m_tagMgr( folder.db().tagMgr() ) + , m_payloadSpecification( folder.payloadSpecification() ) + , m_tableSpecification( tableSpecification( folder.payloadSpecification() ) ) + , m_nodeId( folder.id() ) +{ + m_objectTableName = folder.objectTableName(); + if ( folder.versioningMode() == FolderVersioning::MULTI_VERSION ) { + m_tagTableName = folder.tagTableName(); + m_object2TagTableName = folder.object2TagTableName(); + } else { + m_tagTableName = ""; + m_object2TagTableName = ""; + } + m_channelTableName = folder.channelTableName(); +} + +//--------------------------------------------------------------------------- + +coral::MessageStream& RelationalObjectTable::log() const +{ + *m_log << coral::Verbose; + return *m_log; +} + +//--------------------------------------------------------------------------- + +RelationalObjectTable::~RelationalObjectTable() +{ + if ( m_ownQueryMgr && m_pQueryMgr ) + { + delete m_pQueryMgr; + m_pQueryMgr = 0; + } +} + +//--------------------------------------------------------------------------- + +const IRecordSpecification& +RelationalObjectTable::defaultSpecification() +{ + static RecordSpecification spec; + + if ( spec.size() == 0 ) { + spec.extend( RelationalObjectTable::columnNames::objectId(), + RelationalObjectTable::columnTypeIds::objectId ); + spec.extend( RelationalObjectTable::columnNames::channelId(), + RelationalObjectTable::columnTypeIds::channelId ); + spec.extend( RelationalObjectTable::columnNames::iovSince(), + RelationalObjectTable::columnTypeIds::iovSince ); + spec.extend( RelationalObjectTable::columnNames::iovUntil(), + RelationalObjectTable::columnTypeIds::iovUntil ); + spec.extend( RelationalObjectTable::columnNames::userTagId(), + RelationalObjectTable::columnTypeIds::userTagId ); + spec.extend( RelationalObjectTable::columnNames::sysInsTime(), + RelationalObjectTable::columnTypeIds::sysInsTime ); + spec.extend( RelationalObjectTable::columnNames::lastModDate(), + RelationalObjectTable::columnTypeIds::lastModDate ); + + // Management columns for 'MultiVersion' folders + spec.extend( RelationalObjectTable::columnNames::originalId(), + RelationalObjectTable::columnTypeIds::originalId ); + spec.extend( RelationalObjectTable::columnNames::newHeadId(), + RelationalObjectTable::columnTypeIds::newHeadId ); + } + + return spec; +} + +//--------------------------------------------------------------------------- + +const RecordSpecification +RelationalObjectTable::tableSpecification +( const IRecordSpecification& payloadSpec ) +{ + RecordSpecification spec; + for ( unsigned int i=0; i<defaultSpecification().size(); i++ ) { + const IFieldSpecification& field = defaultSpecification()[i]; + spec.extend( field.name(), field.storageType() ); + } + for ( unsigned int i=0; i<payloadSpec.size(); i++ ) { + const IFieldSpecification& field = payloadSpec[i]; + spec.extend( field.name(), field.storageType() ); + } + return spec; +} + +//--------------------------------------------------------------------------- + +const coral::AttributeList +RelationalObjectTable::rowAttributeList +( const coral::AttributeList& payload ) +{ + coral::AttributeList al = Record( defaultSpecification() ).attributeList(); + + // User-defined payload columns + for ( coral::AttributeList::const_iterator + i = payload.begin(); i != payload.end(); ++i ) { + al.extend( i->specification().name(), i->specification().typeName() ); + } + + return al; +} + +//----------------------------------------------------------------------------- + +const RelationalObjectTableRow +RelationalObjectTable::fetchRowForId( unsigned int objectId, + bool fetchPayload ) const +{ + log() << "Fetch object row from table " << objectTableName() + << " for object_id=" << objectId << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend + ( "objectId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::objectId) ); + whereData["objectId"].setValue( objectId ); + std::string whereClause = RelationalObjectTable::columnNames::objectId(); + whereClause += "= :objectId"; + + // Delegate the query to the RelationalQueryMgr + try { + std::string desc = ""; + // Fetch both the IOV metadata and the payload + if ( fetchPayload ) + return RelationalObjectTableRow + ( queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( objectTableName() ), + RelationalQueryMgr::columnList( tableSpecification() ), + whereClause, whereData, desc ) ); + // Fetch only the IOV metadata, not the payload + else + return RelationalObjectTableRow + ( queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( objectTableName() ), + RelationalQueryMgr::columnList( defaultSpecification() ), + whereClause, whereData, desc ) ); + } catch( NoRowsFound& ) { + std::stringstream s; + s << "object_id: " << objectId; + throw ObjectNotFound + ( s.str(), objectTableName(), "RelationalObjectTable" ); + } +} + +//--------------------------------------------------------------------------- + +const std::vector<std::string> +RelationalObjectTable::orderByClause( const ChannelSelection& channels, + const std::string& objectTableName ) +{ + // Create a prefix if an objectTableName was specified + std::string prefix = ""; + if ( objectTableName != "" ) prefix = objectTableName + "."; + + // Define the ORDER BY clause for the selection + // + // sas 2005-08-09: I'm not sure if we even have to make the following + // distinction of single/multi channel selection or should just + // generally have "channelId, iovSince" or vice versa ordering. The fact + // that we have a 3D index might make this superfluous. + std::vector<std::string> orderBy; + if ( ! channels.isNumeric() + || ( channels.isNumeric() && + ( channels.firstChannel() == channels.lastChannel() ) ) + ) { + // Only one channel, skip 'channelId' in order clause + if ( channels.order() == ChannelSelection::channelBeforeSince || + channels.order() == ChannelSelection::sinceBeforeChannel ) { + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::iovSince() + " ASC" ); + } + else { + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::iovSince() + " DESC" ); + } + } else { + if ( channels.order() == ChannelSelection::channelBeforeSince ) { + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::channelId() + " ASC" ); + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::iovSince() + " ASC" ); + } + else if ( channels.order() == ChannelSelection::sinceBeforeChannel ){ + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::iovSince() + " ASC" ); + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::channelId() + " ASC" ); + } + else if ( channels.order() == ChannelSelection::channelBeforeSinceDesc ){ + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::channelId() + " ASC" ); + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::iovSince() + " DESC" ); + } + else if ( channels.order() == ChannelSelection::sinceDescBeforeChannel ){ + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::iovSince() + " DESC" ); + orderBy.push_back + ( prefix + RelationalObjectTable::columnNames::channelId() + " ASC" ); + } + } + return orderBy; +} + +//--------------------------------------------------------------------------- + +/* +/// TEMPORARY! This is ONLY needed by David's VerificationClient +RelationalObjectTableRow +RelationalObjectTable::fetchLastRowSV( const ChannelId& channelId, + bool fetchPayload ) +{ + log() << "Fetch last object row from table " << objectTableName() + << coral::MessageStream::endmsg; + + // The "last object" inserted in each channel of a SV folder is retrieved + // as the object with the highest objectId in that channel (two possible + // alternatives could be to use the highest iovSince or iovUntil). + // The present algorithm uses two queries: + // 1. First, select MAX(objectId) in the given channel + // 2. Then, retrieve the full row for the object wih id=maxId + + // QUERY 1: select MAX(objectId) for the given channel + std::string maxObjectIdName = + std::string("MAX(") + RelationalObjectTable::columnNames::objectId() + ")"; + + RecordSpecification spec; + spec.extend( maxObjectIdName, + RelationalObjectTable::columnTypeIds::objectId ); + coral::AttributeList whereData; + whereData.extend + ( "channel", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::channelId) ); + whereData["channel"] + .data<RelationalObjectTable::columnTypes::channelId>() = channelId; + std::string whereClause = RelationalObjectTable::columnNames::channelId(); + whereClause += "= :channel"; + + // Delegate the query to the RalQueryMgr + ObjectId maxObjectId; + try { + std::string desc = ""; + RelationalTableRow maxObjectIdRow = queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( objectTableName() ), + RelationalQueryMgr::columnList( spec ), + whereClause, whereData, desc ); + maxObjectId = maxObjectIdRow[ maxObjectIdName ].data<ObjectId>(); + } catch( NoRowsFound& ) { + throw ObjectNotFound + ( "MAX(objectId)", objectTableName(), "RelationalObjectTable" ); + } + + // QUERY 2: select * for objectId = MAX(objectId) + return + fetchRowForId( maxObjectId, fetchPayload ); + +} +*/ + +//--------------------------------------------------------------------------- + +const RelationalObjectTableRow +RelationalObjectTable::fetchLastRowForTagId( unsigned int tagId, + bool fetchPayload ) const +{ + log() << "Fetch last object row from table " << objectTableName() + << " for tagId " << tagId << coral::MessageStream::endmsg; + ObjectId maxObjectId=0; + bool isUserTag=true; + + // QUERY 1: select MAX(objectId) for the given tag + std::string maxObjectIdName = + std::string("MAX(") + RelationalObjectTable::columnNames::objectId() + ")"; + RecordSpecification spec; + spec.extend( maxObjectIdName, + RelationalObjectTable::columnTypeIds::objectId ); + + // first guess: it is a user tag + coral::AttributeList whereData; + whereData.extend + ( "userTagId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::userTagId) ); + whereData["userTagId"].setValue( tagId ); + std::string whereClause = + RelationalObjectTable::columnNames::userTagId(); + whereClause += "=:userTagId"; + + try { + std::string desc = ""; + RelationalTableRow maxObjectIdRow = queryMgr().fetchRowFromTables( + RelationalQueryMgr::tableList( objectTableName() ), + RelationalQueryMgr::columnList( spec ), + whereClause, whereData, desc ); + if (maxObjectIdRow[ maxObjectIdName ].isNull()) + isUserTag=false; + else maxObjectId = maxObjectIdRow[ maxObjectIdName ].data<ObjectId>(); + } catch (NoRowsFound & ) { + isUserTag=false; + } + if ( !isUserTag) { + // no user tag + coral::AttributeList whereData; + whereData.extend( "tagId", + typeIdToCoralType(RelationalObject2TagTable::columnTypeIds::tagId) ); + whereData["tagId"].setValue( tagId ); + std::string whereClause = RelationalObject2TagTable::columnNames::tagId; + whereClause += "= :tagId"; + + // Delegate the query to the RalQueryMgr + try { + std::string desc = ""; + RelationalTableRow maxObjectIdRow = queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( object2TagTableName() ), + RelationalQueryMgr::columnList( spec ), + whereClause, whereData, desc ); + maxObjectId = maxObjectIdRow[ maxObjectIdName ].data<ObjectId>(); + } catch( NoRowsFound& ) { + throw ObjectNotFound + ( "MAX(objectId)", object2TagTableName(), "RelationalObjectTable" ); + } + } + + // QUERY 2: select * for objectId = MAX(objectId) + return + fetchRowForId( maxObjectId, fetchPayload ); + +} + +//--------------------------------------------------------------------------- + +const RelationalObjectTableRow RelationalObjectTable::fetchRowAtTimeInHead +( const ValidityKey& pointInTime, + const ChannelId& channelId, + unsigned int userTagId ) +{ + log() << "Fetch object row HEAD from table " << objectTableName() + << " for channel=" << channelId + << " at time=" << pointInTime + << " (with user tag=" << userTagId << ")" + << coral::MessageStream::endmsg; + + const std::auto_ptr<IRelationalQueryDefinition> + def( queryDefinitionGeneric + ( pointInTime, pointInTime, channelId, &userTagId ) ); + + // Delegate the query to the RalQueryMgr + try { + std::string desc = ""; + const std::vector<RelationalTableRow> rows + ( queryMgr().fetchOrderedRows( *def, desc, 1 ) ); + return RelationalObjectTableRow( rows[0] ); + } catch( NoRowsFound& ) { + std::stringstream s; + s << pointInTime; + throw ObjectNotFound + ( s.str(), objectTableName(), "RelationalObjectTable" ); + } +} +//--------------------------------------------------------------------------- + +std::auto_ptr< std::vector<RelationalObjectTableRow> > +RelationalObjectTable::fetchRowsBtTimesInHead +( const ValidityKey& since, + const ValidityKey& until, + const ChannelId& channelId, + unsigned int userTagId, + unsigned int maxRows ) +{ + log() << "Fetch object row HEAD from table " << objectTableName() + << " for channel=" << channelId + << " bt times=" << since + << ", " << until + << " (with user tag=" << userTagId << ")" + << coral::MessageStream::endmsg; + + const std::auto_ptr<IRelationalQueryDefinition> + def( queryDefinitionGeneric + ( since, until, channelId, &userTagId ) ); + + // Delegate the query to the RalQueryMgr + try { + std::string desc = ""; + + // return a auto_ptr to 0 if maxRow count is exceeded + unsigned int count=queryMgr().countRows( *def, desc ); + if ( count > maxRows ) + return std::auto_ptr< std::vector< RelationalObjectTableRow > >( 0 ); + + const std::vector<RelationalTableRow> rows + ( queryMgr().fetchOrderedRows( *def, desc ) ); + + std::auto_ptr< std::vector<RelationalObjectTableRow> > objectRows( + new std::vector<RelationalObjectTableRow>( ) ); + + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + RelationalObjectTableRow objectRow( *row ); + objectRows->push_back( objectRow ); + } + + return objectRows; + } catch( NoRowsFound& ) { + std::stringstream s; + s << since << ", " << until; + throw ObjectNotFound + ( s.str(), objectTableName(), "RelationalObjectTable" ); + } +} + +//--------------------------------------------------------------------------- + +/* +RelationalObjectTableRow RelationalObjectTable::fetchRowAtTimeInTag +( const ValidityKey& pointInTime, + const ChannelId& channelId, + const std::string& tagName ) +{ + log() << "Fetch object row in tag from table " << objectTableName() + << " for channel=" << channelId + << " at time=" << pointInTime + << " with tag=" << tagName + << coral::MessageStream::endmsg; + + const std::auto_ptr<IRelationalQueryDefinition> + def( queryDefinitionTag + ( pointInTime, pointInTime, channelId, tagName ) ); + + // Delegate the query to the RalQueryMgr + try { + std::string desc = ""; + const std::vector<RelationalTableRow> rows + ( queryMgr().fetchOrderedRows( *def, desc, 1 ) ); + return RelationalObjectTableRow( rows[0] ); + } catch( NoRowsFound& ) { + std::stringstream s; + s << pointInTime; + throw ObjectNotFound + ( s.str(), objectTableName(), "RelationalObjectTable" ); + } +} +*/ + +//--------------------------------------------------------------------------- + +std::vector<RelationalObjectTableRow> +RelationalObjectTable::fetchRowsForTaggingCurrentHead() +{ + + // Add 'meta data' columns to the output list and define the output format + RecordSpecification spec; + spec.extend( RelationalObjectTable::columnNames::objectId(), + RelationalObjectTable::columnTypeIds::objectId ); + spec.extend( RelationalObjectTable::columnNames::channelId(), + RelationalObjectTable::columnTypeIds::channelId ); + spec.extend( RelationalObjectTable::columnNames::iovSince(), + RelationalObjectTable::columnTypeIds::iovSince ); + spec.extend( RelationalObjectTable::columnNames::iovUntil(), + RelationalObjectTable::columnTypeIds::iovUntil ); + spec.extend( RelationalObjectTable::columnNames::userTagId(), + RelationalObjectTable::columnTypeIds::userTagId ); + spec.extend( RelationalObjectTable::columnNames::sysInsTime(), + RelationalObjectTable::columnTypeIds::sysInsTime ); + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend + ( "newHeadId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::newHeadId) ); + whereData.extend + ( "userTagId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::userTagId) ); + whereData["newHeadId"].setValue( 0u ); + whereData["userTagId"].setValue( 0u ); + std::string whereClause = RelationalObjectTable::columnNames::newHeadId(); + whereClause += "= :newHeadId"; + whereClause += " AND "; + whereClause += RelationalObjectTable::columnNames::userTagId(); + whereClause += "= :userTagId"; + + /// Results are ordered by ascending values of the "since" start of IOV + std::vector<std::string> orderBy; + orderBy.push_back( RelationalObjectTable::columnNames::objectId() + " ASC" ); + + // Delegate the query to the RalQueryMgr + std::string desc = ""; + std::vector<RelationalTableRow> rows = + queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( objectTableName() ), + RelationalQueryMgr::columnList( spec ), + whereClause, whereData, orderBy, desc ); + + // TEMPORARY? Conversion to RelationalObjectTableRow + std::vector<RelationalObjectTableRow> objectRows; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + RelationalObjectTableRow objectRow( *row ); + objectRows.push_back( objectRow ); + } + + // Return the results + return objectRows; + +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalObjectTableRow> +RelationalObjectTable::fetchRowsForTaggingHeadAsOfDate( const ITime& asOfDate ) +{ + log() << "Fetch IOV rows from table '" << objectTableName() + << "' for tagging as of date '" << timeToString(asOfDate) + << "'" << coral::MessageStream::endmsg; + + // Ideally, this methods query should be merged with fetchObjectTableRows, + // but it is not so easy due the output column specifications + + // Define the list of tables to query + // NB Use UPPERCASE table aliases for Frontier (see task #3536) + RelationalQueryMgr::TableNamesWithAliases tables; + tables.push_back + ( RelationalQueryMgr::TableNameWithAlias( objectTableName(), "I" ) ); + tables.push_back + ( RelationalQueryMgr::TableNameWithAlias( objectTableName(), "O" ) ); + + // Add 'meta data' columns to the output list and define the output format + RecordSpecification spec; + spec.extend( RelationalObjectTable::columnNames::objectId(), + RelationalObjectTable::columnTypeIds::objectId ); + spec.extend( RelationalObjectTable::columnNames::channelId(), + RelationalObjectTable::columnTypeIds::channelId ); + spec.extend( RelationalObjectTable::columnNames::iovSince(), + RelationalObjectTable::columnTypeIds::iovSince ); + spec.extend( RelationalObjectTable::columnNames::iovUntil(), + RelationalObjectTable::columnTypeIds::iovUntil ); + spec.extend( RelationalObjectTable::columnNames::userTagId(), + RelationalObjectTable::columnTypeIds::userTagId ); + spec.extend( RelationalObjectTable::columnNames::sysInsTime(), + RelationalObjectTable::columnTypeIds::sysInsTime ); + RelationalQueryMgr::SelectListWithRSetSpec columns = + RelationalQueryMgr::columnList( spec, "I." ); + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend + ( "asOfDate1", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::sysInsTime) ); + whereData.extend + ( "userTagId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::userTagId) ); + whereData.extend + ( "newHeadId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::newHeadId) ); + whereData.extend + ( "asOfDate2", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::sysInsTime) ); + + whereData["asOfDate1"].setValue( timeToString( asOfDate ) ); + whereData["userTagId"].setValue( 0u ); + whereData["newHeadId"].setValue( 0u ); + whereData["asOfDate2"].setValue( timeToString( asOfDate ) ); + std::string ins = RelationalObjectTable::columnNames::sysInsTime(); + std::string oid = RelationalObjectTable::columnNames::objectId(); + std::string nhid = RelationalObjectTable::columnNames::newHeadId(); + std::string whereClause = "I." + ins + " <= :asOfDate1"; + whereClause += " AND "; + whereClause += "I." + RelationalObjectTable::columnNames::userTagId(); + whereClause += "= :userTagId"; + whereClause += " AND ( "; + whereClause += "( I." + nhid + " = :newHeadId"; + whereClause += " AND I." + oid + " = O." + oid; // constrains self join + whereClause += " ) "; + whereClause += " OR "; + whereClause += "( I." + nhid + " = O." + oid; + whereClause += " AND O." + ins + " > :asOfDate2"; + whereClause += " ) "; + whereClause += ")"; + + /// Results are ordered by ascending values of the "since" start of IOV + std::vector<std::string> orderBy; + orderBy.push_back( std::string("I.") + + RelationalObjectTable::columnNames::objectId() + " ASC" ); + + // Delegate the query to the RalQueryMgr + std::string desc = ""; + std::vector<RelationalTableRow> rows = + queryMgr().fetchOrderedRowsFromTables + ( tables, columns, whereClause, whereData, orderBy, desc ); + + // TEMPORARY? Conversion to RelationalObjectTableRow + std::vector<RelationalObjectTableRow> objectRows; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + RelationalObjectTableRow objectRow( *row ); + objectRows.push_back( objectRow ); + } + + // Return the results + return objectRows; + +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalObjectTableRow> +RelationalObjectTable::fetchRowsForTaggingHeadAsOfObjectId +( unsigned int asOfObjectId ) +{ + + // Add 'meta data' columns to the output list and define the output format + RecordSpecification spec; + spec.extend( RelationalObjectTable::columnNames::objectId(), + RelationalObjectTable::columnTypeIds::objectId ); + spec.extend( RelationalObjectTable::columnNames::channelId(), + RelationalObjectTable::columnTypeIds::channelId ); + spec.extend( RelationalObjectTable::columnNames::iovSince(), + RelationalObjectTable::columnTypeIds::iovSince ); + spec.extend( RelationalObjectTable::columnNames::iovUntil(), + RelationalObjectTable::columnTypeIds::iovUntil ); + spec.extend( RelationalObjectTable::columnNames::userTagId(), + RelationalObjectTable::columnTypeIds::userTagId ); + spec.extend( RelationalObjectTable::columnNames::sysInsTime(), + RelationalObjectTable::columnTypeIds::sysInsTime ); + + // AV 05.04.2005 Bug fix + // The asOfObjectId argument must first be mapped into current user object + // Also change algorithm so that next (rather than current) user obj is used + ObjectId nextUserObjectId = ObjectIdHandler::nextUserObject( asOfObjectId ); + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend + ( "userTagId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::userTagId) ); + whereData.extend + ( "oid1", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::objectId) ); + whereData.extend + ( "oid2", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::objectId) ); + + whereData["userTagId"].setValue( 0u ); + whereData["oid1"].setValue( nextUserObjectId ); + whereData["oid2"].setValue( nextUserObjectId ); + std::string oid = RelationalObjectTable::columnNames::objectId(); + std::string nhid = RelationalObjectTable::columnNames::newHeadId(); + std::string whereClause = RelationalObjectTable::columnNames::userTagId(); + whereClause += "= :userTagId"; + whereClause += " AND "; + whereClause += oid + " < :oid1"; + whereClause += " AND ( "; + whereClause += + " " + nhid + " = 0 or"; // AV 05.04.2005 No need to bind 0 (constant) + whereClause += " " + nhid + " >= :oid2"; + whereClause += " )"; + + /// Results are ordered by ascending values of the "since" start of IOV + std::vector<std::string> orderBy; + orderBy.push_back( RelationalObjectTable::columnNames::objectId() + " ASC" ); + + // Delegate the query to the RalQueryMgr + std::string desc = ""; + std::vector<RelationalTableRow> rows = + queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( objectTableName() ), + RelationalQueryMgr::columnList( spec ), + whereClause, whereData, orderBy, desc ); + + // TEMPORARY? Conversion to RelationalObjectTableRow + std::vector<RelationalObjectTableRow> objectRows; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + RelationalObjectTableRow objectRow( *row ); + objectRows.push_back( objectRow ); + } + + // Return the results + return objectRows; + +} + +//--------------------------------------------------------------------------- + +bool +RelationalObjectTable::existsChannel( const ChannelId& channelId ) const +{ + std::string whereClause = RelationalObjectTable::columnNames::channelId(); + whereClause += "= :channelId"; + coral::AttributeList whereData; + whereData.extend + ( "channelId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::channelId) ); + whereData["channelId"].setValue( channelId ); + UInt32 nRows = + queryMgr().countRowsFromTables + ( RelationalQueryMgr::tableList( this->objectTableName() ), + whereClause, whereData, "" ); + return ( nRows > 0 ); +} + +//--------------------------------------------------------------------------- + +std::auto_ptr<IRelationalQueryDefinition> +RelationalObjectTable::queryDefinitionSV +( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const IRecordSelection* payloadQuery ) +{ + // Delegate to queryDefinitionGeneric + const unsigned int* pTagId = 0; + bool isUserTag = true; + return queryDefinitionGeneric( since, until, channels, pTagId, isUserTag, payloadQuery ); +} + +//--------------------------------------------------------------------------- + +std::auto_ptr<IRelationalQueryDefinition> +RelationalObjectTable::queryDefinitionHeadAndUserTag +( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& userTagName, + const IRecordSelection* payloadQuery ) +{ + // TEMPORARY? Could provide tagName and do the tagName->tagId + // mapping in the same join: here I assume we retrieve it before + unsigned int tagId = 0; + if (!IHvsNode::isHeadTag( userTagName )) + try + { + tagId = m_tagMgr.__findTagRecord( m_nodeId, userTagName ).id(); + //std::cout << "Tag '" << tagName << "' has tagId=" << tagId << std::endl; + } + catch(...) + { + //std::cout << "Tag '" << tagName + // << "' does not exist - use a dummy value tagId=0" << std::endl; + } + + // Delegate to queryDefinitionGeneric + bool isUserTag = true; + return queryDefinitionGeneric( since, until, channels, &tagId, isUserTag, payloadQuery ); +} + +//--------------------------------------------------------------------------- + +std::auto_ptr<IRelationalQueryDefinition> +RelationalObjectTable::queryDefinitionTag +( //const std::string& objectTableName, + const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName, + const IRecordSelection* payloadQuery ) +{ + // TEMPORARY? Could provide tagName and do the tagName->tagId + // mapping in the same join: here I assume we retrieve it before + unsigned int tagId = 0; + try + { + tagId = m_tagMgr.__findTagRecord( m_nodeId, tagName ).id(); + //std::cout << "Tag '" << tagName << "' has tagId=" << tagId << std::endl; + } + catch(...) + { + //std::cout << "Tag '" << tagName + // << "' does not exist - use a dummy value tagId=0" << std::endl; + } + + // Delegate to queryDefinitionGeneric + bool isUserTag = false; + return queryDefinitionGeneric( since, until, channels, &tagId, isUserTag, payloadQuery ); +} +//--------------------------------------------------------------------------- + +// NEW IMPLEMENTATION - IMPLEMENT TWO VIEW MERGES DIRECTLY! +std::auto_ptr<IRelationalQueryDefinition> +RelationalObjectTable::queryDefinitionGeneric +( //const std::string& objectTableName, + const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const unsigned int* pTagId, // pTagId=0 means SV, (*pTagId)==0 means HEAD + bool isUserTag, // ignored for SV and HEAD, used only for (*pTagId)!=0 + const IRecordSelection* payloadQuery ) +{ + // TEMPORARY? This method could accept a tag name as an argument instead + // of a pointer to a tagID (in which case we would need to retrieve the + // tagID inside this method, for instance using a join with the tag table - + // which we may already have in some cases). The present implementation + // assumes instead that we retrieve it before (or that we do not need it, + // for instance for insertion...). + + // TEMPORARY - this method should be moved elsewhere + // and table names should be provided as arguments... + const std::string& objectTableName = m_objectTableName; + const std::string& object2TagTableName = m_object2TagTableName; + + // Add double quotes for all techologies except SQLite + std::string quotes = ""; + if ( queryMgr().databaseTechnology() == "Oracle" || + queryMgr().databaseTechnology() == "MySQL" || + queryMgr().databaseTechnology() == "frontier" ) quotes = "\""; + + // Create the hint prefix and suffix without interefering with C++ comments + std::string hintPrefix = std::string("/") + std::string("*"); + std::string hintSuffix = std::string(" *") + std::string("/"); + + // --- SQL QUERY STRATEGY: 'external OR' vs. 'coalesce'/'internal OR' --- + + // Choose the SQL query strategy (externalOR vs. internalOR/coalesce) + // DEFAULT: internalOR (userTagMV)/coalesce(SV/tagMV) + bool useExternalOr = false; + // Override the SQL strategy using environment variables + if ( getenv( "COOL_QUERYDEFGEN_EXTERNALOR" ) ) + { + std::cout << "__COOL alternative SQL strategy EXTERNALOR" << std::endl; + useExternalOr = true; + } + + // --- SQL QUERY STRATEGY: 'coalesce' vs. 'internal OR' --- + + // Choose the SQL query strategy (internalOR vs. coalesce) + // DEFAULT: coalesce for all (SV/tagMV/userTagMV) + bool useCoalesce = true; + /* + if ( pTagId == 0 ) + { + // Default for SV: use coalesce + useCoalesce = true; + } + else + { + if ( isUserTag ) + { + // Default for MV user tags: use coalesce + useCoalesce = true; + } + else + { + // Default for MV tags: do not use coalesce + useCoalesce = true; + } + } + */ + // Override the SQL strategy using environment variables + if ( getenv( "COOL_QUERYDEFGEN_COALESCE" ) ) + { + useCoalesce = true; + std::cout << "__COOL alternative SQL strategy COALESCE" << std::endl; + } + else if ( getenv( "COOL_QUERYDEFGEN_NOCOALESCE" ) ) + { + useCoalesce = false; + std::cout << "__COOL alternative SQL strategy NOCOALESCE" << std::endl; + } + + // --- MV WHERE CLAUSES --- + + // If pTagId == 0, this is SV: no additional tagWhereClause. + // If pTagId != 0, this is MV: prepare the additional tagWhereClause. + std::string whereClauseTag1; + Record whereDataTag1; + std::string whereClauseTag3; + Record whereDataTag3; + std::string whereClauseTag3b; + Record whereDataTag3b; + //std::cout << "pTagId=" << pTagId << std::endl; + //std::cout << "isUserTag=" << ( isUserTag?"T":"F") << std::endl; + if ( pTagId != 0 ) + { + unsigned int tagId = *pTagId; + if ( isUserTag ) + { + const std::string iovUtagIdName = + RelationalObjectTable::columnNames::userTagId(); + const std::string iovNewHIdName = + RelationalObjectTable::columnNames::newHeadId(); + const StorageType::TypeId iovUtagIdTyId = + RelationalObjectTable::columnTypeIds::userTagId; + // Use the 5D indx on userTagId, newHeadId, channelId, iovSince, iovUntil + // that was originally introduced for findObject(userTag) in task #4381 + // Clause and data for subquery1 (max) + { + whereClauseTag1 += "COOL_I1." + iovUtagIdName; + whereClauseTag1 += "=:" + quotes+"utagid1"+quotes; + whereClauseTag1 += " AND "; + whereClauseTag1 += iovNewHIdName + "=0"; + whereClauseTag1 += " AND "; + RecordSpecification spec; + spec.extend( "utagid1", iovUtagIdTyId ); + Record rec( spec ); + rec["utagid1"].setValue( tagId ); + whereDataTag1.extend( rec ); + } + // Clause and data for subquery3 (browse) + { + whereClauseTag3 += "COOL_I3." + iovUtagIdName; + whereClauseTag3 += "=:" + quotes+"utagid3"+quotes; + whereClauseTag3 += " AND "; + whereClauseTag3 += iovNewHIdName + "=0"; + whereClauseTag3 += " AND "; + RecordSpecification spec; + spec.extend( "utagid3", iovUtagIdTyId ); + Record rec( spec ); + rec["utagid3"].setValue( tagId ); + whereDataTag3.extend( rec ); + } + // Clause and data for subquery3b (browse) - ONLY FOR EXTERNAL OR + { + whereClauseTag3b += "COOL_I3." + iovUtagIdName; + whereClauseTag3b += "=:" + quotes+"utagid3b"+quotes; + whereClauseTag3b += " AND "; + whereClauseTag3b += iovNewHIdName + "=0"; + whereClauseTag3b += " AND "; + RecordSpecification spec; + spec.extend( "utagid3b", iovUtagIdTyId ); + Record rec( spec ); + rec["utagid3b"].setValue( tagId ); + whereDataTag3b.extend( rec ); + } + } + else + { + const std::string i2tTagName = + RelationalObject2TagTable::columnNames::tagId; + const StorageType::TypeId i2tTagTyId = + RelationalObject2TagTable::columnTypeIds::tagId; + // Use the 4D index on tagId, channelId, iovSince, iovUntil + // Clause and data for subquery1 (max) + { + whereClauseTag1 += "COOL_I1." + i2tTagName; + whereClauseTag1 += "=:" + quotes+"tagid1"+quotes; + whereClauseTag1 += " AND "; + RecordSpecification spec; + spec.extend( "tagid1", i2tTagTyId ); + Record rec( spec ); + rec["tagid1"].setValue( tagId ); + whereDataTag1.extend( rec ); + } + // Clause and data for subquery3 (browse) + { + whereClauseTag3 += "COOL_I3." + i2tTagName; + whereClauseTag3 += "=:" + quotes+"tagid3"+quotes; + whereClauseTag3 += " AND "; + RecordSpecification spec; + spec.extend( "tagid3", i2tTagTyId ); + Record rec( spec ); + rec["tagid3"].setValue( tagId ); + whereDataTag3.extend( rec ); + } + // Clause and data for subquery3b (browse) - ONLY FOR EXTERNAL OR + { + whereClauseTag3b += "COOL_I3." + i2tTagName; + whereClauseTag3b += "=:" + quotes+"tagid3b"+quotes; + whereClauseTag3b += " AND "; + RecordSpecification spec; + spec.extend( "tagid3b", i2tTagTyId ); + Record rec( spec ); + rec["tagid3b"].setValue( tagId ); + whereDataTag3b.extend( rec ); + } + } + } + + // --- SCHEMA ELEMENTS FOR SUBQUERY 1/2 (max) and SUBQUERY 3 (browse) --- + + std::string iovTable13; + std::string iovSince13Name; + std::string iovUntil13Name; + std::string iovObjId13Name; + std::string iovChnId13Name; + StorageType::TypeId iovSince13TyId; + StorageType::TypeId iovUntil13TyId; + StorageType::TypeId iovObjId13TyId; + if ( pTagId == 0 || isUserTag ) + { + iovTable13 = objectTableName; + iovSince13Name = RelationalObjectTable::columnNames::iovSince(); + iovUntil13Name = RelationalObjectTable::columnNames::iovUntil(); + iovObjId13Name = RelationalObjectTable::columnNames::objectId(); + iovChnId13Name = RelationalObjectTable::columnNames::channelId(); + iovSince13TyId = RelationalObjectTable::columnTypeIds::iovSince; + iovUntil13TyId = RelationalObjectTable::columnTypeIds::iovUntil; + iovObjId13TyId = RelationalObjectTable::columnTypeIds::objectId; + } + else + { + iovTable13 = object2TagTableName; + iovSince13Name = RelationalObject2TagTable::columnNames::iovSince; + iovUntil13Name = RelationalObject2TagTable::columnNames::iovUntil; + iovObjId13Name = RelationalObject2TagTable::columnNames::objectId; + iovChnId13Name = RelationalObject2TagTable::columnNames::channelId; + iovSince13TyId = RelationalObject2TagTable::columnTypeIds::iovSince; + iovUntil13TyId = RelationalObject2TagTable::columnTypeIds::iovUntil; + iovObjId13TyId = RelationalObject2TagTable::columnTypeIds::objectId; + } + std::string chnChnId13Name; + std::string chnChnNm13Name; + StorageType::TypeId chnChnId13TyId; + StorageType::TypeId chnChnNm13TyId; + chnChnId13Name = RelationalChannelTable::columnNames::channelId(); + chnChnNm13Name = RelationalChannelTable::columnNames::channelName(); + chnChnId13TyId = RelationalChannelTable::columnTypeIds::channelId; + chnChnNm13TyId = RelationalChannelTable::columnTypeIds::channelName; + + // --- SUBQUERY 1 (max1: max for one channel) --- + + std::string subQuery1; + Record whereDataSQ1; + { + std::string schemaPrefix; + if ( queryMgr().schemaName() != "" ) + schemaPrefix = queryMgr().schemaName() + "."; + // Hint for subquery1 + std::string hint = hintPrefix + "+ QB_NAME(MAX1) "; + if ( getenv( "COOL_QUERYDEFGEN_HINTMAX1" ) ) + { + hint += getenv( "COOL_QUERYDEFGEN_HINTMAX1" ); + } + hint = hint + hintSuffix; + // Clause for subquery1 + subQuery1 += "( SELECT "+hint+" "; + subQuery1 += "MAX(COOL_I1." + iovSince13Name + ")"; + subQuery1 += " FROM " + schemaPrefix + iovTable13 + " COOL_I1"; + subQuery1 += " WHERE "; + subQuery1 += whereClauseTag1; + subQuery1 += "COOL_I1."+iovChnId13Name + "=COOL_C2." + chnChnId13Name; + subQuery1 += " AND "; + subQuery1 += "COOL_I1."+iovSince13Name + "<=:" + quotes+"since1"+quotes; + subQuery1 += " )"; + // Data for subquery1 + { + whereDataSQ1.extend( whereDataTag1 ); + RecordSpecification spec; + spec.extend( "since1", iovSince13TyId ); + Record rec( spec ); + rec["since1"].setValue( since ); + whereDataSQ1.extend( rec ); + } + } + + // --- MAIN QUERY --- + + std::auto_ptr<RelationalQueryDefinition> pMainQuery + ( new RelationalQueryDefinition() ); + RelationalQueryDefinition& mainQuery = *pMainQuery; + Record whereDataMQ; + std::string whereClauseMQ; + + // --- Formerly SUBQUERY 3 (browse) --- + // --- There is no SUBQUERY2 (it is already merged with SQ3!) --- + // --- This is the main query for SV and MV user tags (no extra join) --- + // --- There is no SUBQUERY3 (it is already merged with MAIN!) --- + // --- There is an extra join for MV user tags (no extra join) --- + + { + RelationalQueryDefinition& subQuery3 = mainQuery; + Record& whereDataSQ3 = whereDataMQ; + std::string& whereClauseSQ3 = whereClauseMQ; + // FROM ... + subQuery3.addFromItem( m_channelTableName, "COOL_C2" ); + subQuery3.addFromItem( iovTable13, "COOL_I3" ); + // WHERE ... + if ( ! channels.allChannels() ) + { + std::string whereClauseSQ2; + Record whereDataSQ2; + unsigned int maxNonContiguousRanges = 50; + if ( channels.isNumeric() ) + { + if ( channels.firstChannel() == channels.lastChannel() ) + { + whereClauseSQ2 += "COOL_C2."+chnChnId13Name; + whereClauseSQ2 += "=:" + quotes+"chid"+quotes; + RecordSpecification spec; + spec.extend( "chid", chnChnId13TyId ); + Record rec( spec ); + rec["chid"].setValue( channels.firstChannel() ); + whereDataSQ2.extend( rec ); + } + else if ( channels.isContiguous() ) + { + whereClauseSQ2 += "COOL_C2."+chnChnId13Name; + whereClauseSQ2 += ">=:" + quotes+"chmin"+quotes; + whereClauseSQ2 += " AND "; + whereClauseSQ2 += "COOL_C2."+chnChnId13Name; + whereClauseSQ2 += "<=:" + quotes+"chmax"+quotes; + RecordSpecification spec; + spec.extend( "chmin", chnChnId13TyId ); + spec.extend( "chmax", chnChnId13TyId ); + Record rec( spec ); + rec["chmin"].setValue( channels.firstChannel() ); + rec["chmax"].setValue( channels.lastChannel() ); + whereDataSQ2.extend( rec ); + } + else if (channels.rangeCount() <= maxNonContiguousRanges ) + { + whereClauseSQ2 += "("; + unsigned int index = 0; + for (std::vector<ChannelSelection::ChannelRange>::const_iterator + i = channels.begin(); i != channels.end(); ++i) + { + if (index > 0) whereClauseSQ2 += " OR "; + + std::stringstream chmin; + chmin << "chmin" << index; + std::stringstream chmax; + chmax << "chmax" << index; + + whereClauseSQ2 += "COOL_C2."+chnChnId13Name; + whereClauseSQ2 += ">=:" + quotes+chmin.str()+quotes; + whereClauseSQ2 += " AND "; + whereClauseSQ2 += "COOL_C2."+chnChnId13Name; + whereClauseSQ2 += "<=:" + quotes+chmax.str()+quotes; + RecordSpecification spec; + spec.extend( chmin.str(), chnChnId13TyId ); + spec.extend( chmax.str(), chnChnId13TyId ); + Record rec( spec ); + rec[chmin.str()].setValue( i->firstChannel() ); + rec[chmax.str()].setValue( i->lastChannel() ); + whereDataSQ2.extend( rec ); + + ++index; + } + whereClauseSQ2 += ")"; + } + else + { + std::stringstream s; + s << "Non-contiguous channel selection only supported for up to " + << maxNonContiguousRanges << " ranges"; + throw RelationalException(s.str(), "RelationalObjectTable"); + } + } + else + { + whereClauseSQ2 += "COOL_C2."+chnChnNm13Name; + whereClauseSQ2 += "=:" + quotes+"chname"+quotes; + RecordSpecification spec; + spec.extend( "chname", chnChnNm13TyId ); + Record rec( spec ); + rec["chname"].setValue( channels.channelName() ); + whereDataSQ2.extend( rec ); + } + whereClauseSQ3 += whereClauseSQ2 + " AND "; + whereDataSQ3.extend( whereDataSQ2 ); + } + // Do not use a subquery for MySQL + // (Romain - MySQL performance is bad if there are subqueries) + if ( queryMgr().databaseTechnology() == "MySQL" ) + { + whereClauseSQ3 += whereClauseTag3; + whereClauseSQ3 += "COOL_I3."+iovChnId13Name+"=COOL_C2."+iovChnId13Name; + whereClauseSQ3 += " AND "; + { + whereDataSQ3.extend( whereDataTag3 ); + } + whereClauseSQ3 += "( "; + whereClauseSQ3 += "( "; + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += "<=:" + quotes+"sinc3"+ quotes; + whereClauseSQ3 += " AND "; + whereClauseSQ3 += "COOL_I3."+iovUntil13Name; + whereClauseSQ3 += ">:" + quotes+"sinc3u"+ quotes; + whereClauseSQ3 += " )"; + { + whereDataSQ3.extend( whereDataSQ1 ); + RecordSpecification spec; + spec.extend( "sinc3u", iovUntil13TyId ); + spec.extend( "sinc3", iovUntil13TyId ); + Record rec( spec ); + rec["sinc3u"].setValue( since ); + rec["sinc3"].setValue( since ); + whereDataSQ3.extend( rec ); + } + whereClauseSQ3 += " OR "; + whereClauseSQ3 += "( "; + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += ">=:" + quotes+"sinc3s"+quotes; + whereClauseSQ3 += " AND "; + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += "<=:" + quotes+"until3"+quotes; + whereClauseSQ3 += " )"; + whereClauseSQ3 += " )"; + { + RecordSpecification spec; + spec.extend( "sinc3s", iovSince13TyId ); + spec.extend( "until3", iovSince13TyId ); + Record rec( spec ); + rec["sinc3s"].setValue( since ); + rec["until3"].setValue( until ); + whereDataSQ3.extend( rec ); + } + } + else + { + // Use the chosen SQL query strategy (externalOr vs. internalOr/coalesce) + if ( useExternalOr ) + { + //std::cout << "__COOL using EXTERNALOR" << std::endl; + // 1. Implementation with external OR + whereClauseSQ3 += "( "; + whereClauseSQ3 += "( "; + whereClauseSQ3 += whereClauseTag3; + whereClauseSQ3 += "COOL_I3."+iovChnId13Name+"=COOL_C2."+iovChnId13Name; + whereClauseSQ3 += " AND "; + { + whereDataSQ3.extend( whereDataTag3 ); + } + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += "=" + subQuery1; + whereClauseSQ3 += " AND "; + whereClauseSQ3 += "COOL_I3."+iovUntil13Name; + whereClauseSQ3 += ">:" + quotes+"sinc3u"+ quotes; + { + whereDataSQ3.extend( whereDataSQ1 ); + RecordSpecification spec; + spec.extend( "sinc3u", iovUntil13TyId ); + Record rec( spec ); + rec["sinc3u"].setValue( since ); + whereDataSQ3.extend( rec ); + } + whereClauseSQ3 += " ) OR ( "; + whereClauseSQ3 += whereClauseTag3b; + whereClauseSQ3 += "COOL_I3."+iovChnId13Name+"=COOL_C2."+iovChnId13Name; + whereClauseSQ3 += " AND "; + { + whereDataSQ3.extend( whereDataTag3b ); + } + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += ">=:" + quotes+"sinc3s"+quotes; + whereClauseSQ3 += " AND "; + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += "<=:" + quotes+"until3"+quotes; + { + RecordSpecification spec; + spec.extend( "sinc3s", iovSince13TyId ); + spec.extend( "until3", iovSince13TyId ); + Record rec( spec ); + rec["sinc3s"].setValue( since ); + rec["until3"].setValue( until ); + whereDataSQ3.extend( rec ); + } + whereClauseSQ3 += " )"; + whereClauseSQ3 += " )"; + } + else + { + whereClauseSQ3 += whereClauseTag3; + whereClauseSQ3 += "COOL_I3."+iovChnId13Name+"=COOL_C2."+iovChnId13Name; + whereClauseSQ3 += " AND "; + { + whereDataSQ3.extend( whereDataTag3 ); + } + // Use the chosen SQL query strategy (internalOr vs. coalesce) + if ( useCoalesce ) + { + //std::cout << "__COOL using COALESCE" << std::endl; + // 2. Implementation with COALESCE + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += ">=COALESCE("+ subQuery1; + whereClauseSQ3 += ",:" + quotes+"sinc3s"+quotes + ")"; + whereClauseSQ3 += " AND "; + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += "<=:" + quotes+"until3"+quotes; + whereClauseSQ3 += " AND "; + whereClauseSQ3 += "COOL_I3."+iovUntil13Name; + whereClauseSQ3 += ">:" + quotes+"sinc3u"+ quotes; + { + whereDataSQ3.extend( whereDataSQ1 ); + RecordSpecification spec; + spec.extend( "sinc3s", iovSince13TyId ); + spec.extend( "until3", iovSince13TyId ); + spec.extend( "sinc3u", iovUntil13TyId ); + Record rec( spec ); + rec["sinc3s"].setValue( since ); + rec["until3"].setValue( until ); + rec["sinc3u"].setValue( since ); + whereDataSQ3.extend( rec ); + } + } + else + { + //std::cout << "__COOL using INTERNALOR" << std::endl; + // 3. Implementation with internal OR (without COALESCE) + whereClauseSQ3 += "( "; + whereClauseSQ3 += "( "; + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += "=" + subQuery1; + whereClauseSQ3 += " AND "; + whereClauseSQ3 += "COOL_I3."+iovUntil13Name; + whereClauseSQ3 += ">:" + quotes+"sinc3u"+ quotes; + whereClauseSQ3 += " )"; + { + whereDataSQ3.extend( whereDataSQ1 ); + RecordSpecification spec; + spec.extend( "sinc3u", iovUntil13TyId ); + Record rec( spec ); + rec["sinc3u"].setValue( since ); + whereDataSQ3.extend( rec ); + } + whereClauseSQ3 += " OR "; + whereClauseSQ3 += "( "; + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += ">=:" + quotes+"sinc3s"+quotes; + whereClauseSQ3 += " AND "; + whereClauseSQ3 += "COOL_I3."+iovSince13Name; + whereClauseSQ3 += "<=:" + quotes+"until3"+quotes; + whereClauseSQ3 += " )"; + whereClauseSQ3 += " )"; + { + RecordSpecification spec; + spec.extend( "sinc3s", iovSince13TyId ); + spec.extend( "until3", iovSince13TyId ); + Record rec( spec ); + rec["sinc3s"].setValue( since ); + rec["until3"].setValue( until ); + whereDataSQ3.extend( rec ); + } + } + } + } + } + + // --- MAIN QUERY FOR SV AND MV USER TAGS --- + + std::string cool_i_main; + if ( pTagId == 0 || isUserTag ) + { + cool_i_main = "COOL_I3."; + } + + // --- MAIN QUERY FOR MV TAGS --- + + else + { + cool_i_main = "COOL_I4."; + // --- MAIN QUERY FOR MV TAGS --- + mainQuery.addFromItem( objectTableName, "COOL_I4" ); + // WHERE ... + const std::string iovObjIdName = + RelationalObjectTable::columnNames::objectId(); + whereClauseMQ += " AND COOL_I4."+iovObjIdName; + whereClauseMQ += "=COOL_I3."+iovObjIdName; + } + + // --- MAIN QUERY (COMMON TO ALL CASES) --- + + { + // SELECT ... + for ( unsigned int i=0; i<tableSpecification().size(); i++ ) + { + std::string expression = tableSpecification()[i].name(); + // AV PDBSTRESSTEST - START + static bool first = true; + if ( getenv( "COOL_PDBSTRESSTEST_NBYTES" ) ) + { + if ( expression == "S" ) + { + expression = std::string( "SUBSTR(S,1," ) + + getenv( "COOL_PDBSTRESSTEST_NBYTES" ) + ")"; + //expression = std::string + // ( "SUBSTR(REPLACE(S,SUBSTR(S,100,1),SUBSTR(S,101,1)),1," ) + + // getenv( "COOL_PDBSTRESSTEST_NBYTES" ) + ")"; + if ( first ) + { + std::cout << "__COOL_PDBSTRESSTEST Hack: will select " + << expression << std::endl; + first = false; + } + } + } + // AV PDBSTRESSTEST - END + expression = cool_i_main + expression; + mainQuery.addSelectItem( expression ); + } + mainQuery.setResultSetSpecification( tableSpecification() ); + // SELECT / * + HINT * / ... + if ( queryMgr().databaseTechnology() == "Oracle" || + queryMgr().databaseTechnology() == "frontier" ) + { + // These hints force Oracle to use always the same execution plan: + // 1. For different bind variable values (otherwise bind variable + // peeking may result in a plan that is good only for some values). + // Alternatively one may disable bind variable peeking at the session + // level via ALTER SESSION SET "_OPTIM_PEEK_USER_BINDS" = FALSE. + // Bind variable peeking cannot be disabled at the statement level + // because hint OPT_PARAM('_OPTIM_PEEK_USER_BINDS','FALSE') does not + // work (it's essentially ignored, bind variables are peeked anyway). + // 2. Whether or not statistics have been computed. + std::string hint = hintPrefix+"+ QB_NAME(MAIN) "; + if ( getenv( "COOL_QUERYDEFGEN_HINTMAIN" ) ) + { + hint += getenv( "COOL_QUERYDEFGEN_HINTMAIN" ); + } + else if ( pTagId != 0 && *pTagId == 0 && !isUserTag ) + { + // Hints from Romain in task #5821 (current head IOV retrieval) + hint += "INDEX(@MAIN COOL_C2@MAIN (CHANNEL_ID)) "; // depends... + hint += "INDEX(COOL_I3@MAIN (USER_TAG_ID NEW_HEAD_ID CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + hint += "LEADING(@MAIN COOL_C2@MAIN COOL_I3@MAIN) "; + hint += "USE_NL(COOL_I3@MAIN) "; + hint += "INDEX(@MAX1 COOL_I1@MAX1 (USER_TAG_ID NEW_HEAD_ID CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + } + else if ( pTagId != 0 && !isUserTag ) + { + // Hints from task #5820 (standard tag IOV retrieval) + //hint += "INDEX(@MAIN COOL_C2@MAIN (CHANNEL_ID)) "; // depends... + hint += "INDEX_RS_ASC(@MAIN COOL_I3@MAIN (TAG_ID CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + hint += "INDEX_RS_ASC(@MAIN COOL_I4@MAIN (OBJECT_ID)) "; + hint += "LEADING(@MAIN COOL_C2@MAIN COOL_I3@MAIN COOL_I4@MAIN) "; + hint += "USE_NL(@MAIN COOL_I3@MAIN) "; + hint += "USE_NL(@MAIN COOL_I4@MAIN) "; + hint += "INDEX(@MAX1 COOL_I1@MAX1 (TAG_ID CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + } + else if ( pTagId != 0 && isUserTag ) + { + // Hints from Romain in task #6086 (user tag IOV insertion) + // Hints apply also to task #4381 (user tag IOV retrieval) + //hint += "INDEX(@MAIN COOL_C2@MAIN (CHANNEL_ID)) "; // depends... + hint += "INDEX_RS_ASC(@MAIN COOL_I3@MAIN (USER_TAG_ID NEW_HEAD_ID CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + hint += "LEADING(@MAIN COOL_C2@MAIN COOL_I3@MAIN) "; + hint += "USE_NL(COOL_I3@MAIN) "; + hint += "INDEX(@MAX1 COOL_I1@MAX1 (USER_TAG_ID NEW_HEAD_ID CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + } + else if ( pTagId == 0 ) + { + // Hints for SV IOV retrieval (task #2223, task #3675, task #4402) + hint += "INDEX(COOL_C2@MAIN (CHANNEL_ID)) "; + hint += "INDEX(COOL_I3@MAIN (CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + hint += "LEADING(COOL_C2@MAIN COOL_I3@MAIN) "; + hint += "USE_NL(COOL_I3@MAIN) "; + hint += "INDEX(@MAX1 COOL_I1@MAX1 (CHANNEL_ID IOV_SINCE IOV_UNTIL)) "; + } + hint += hintSuffix; + mainQuery.setHint( hint ); + } + if ( payloadQuery !=0 ) + { + RelationalPayloadQuery pq(*payloadQuery, cool_i_main, + queryMgr().databaseTechnology()); + + if ( pq.isTrusted() ) { + whereClauseMQ+=" AND ( "+pq.whereClause()+" )"; + whereDataMQ.extend( pq.whereData() ); + } + //std::cout <<"where clause "<< whereClauseMQ << std::endl; + } + // WHERE... + mainQuery.setWhereClause( whereClauseMQ ); + //std::cout << "Bind variables: " << whereDataMQ << std::endl; + mainQuery.setBindVariables( whereDataMQ ); + // ORDER BY ... + std::vector<std::string> orderBy = orderByClause( channels ); + for ( std::vector<std::string>::const_iterator + it = orderBy.begin(); it != orderBy.end(); it++ ) + { + // TODO: Optimise? Use cool_c2.channel_id, cool_i3.iov_since? + //mainQuery.addOrderItem( cool_i_main + *it ); // no good?... + mainQuery.addOrderItem( "COOL_I3." + *it ); // better... + } + } + + // --- RETURN THE MAIN QUERY DEFINITION --- + //log() << "Prepared generic query definition: " + // << *pMainQuery << coral::MessageStream::endmsg; + return std::auto_ptr<IRelationalQueryDefinition>( pMainQuery.release() ); + +} + +//--------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalObjectTable.h b/RelationalCool/src/RelationalObjectTable.h new file mode 100644 index 000000000..488745b96 --- /dev/null +++ b/RelationalCool/src/RelationalObjectTable.h @@ -0,0 +1,327 @@ +// $Id: RelationalObjectTable.h,v 1.109 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALOBJECTTABLE_H +#define RELATIONALCOOL_RELATIONALOBJECTTABLE_H + +// Include files +#include <memory> +#include "CoralBase/AttributeSpecification.h" +#include "CoralBase/MessageStream.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoolKernel/ValidityKey.h" +#include "CoolKernel/IRecordSelection.h" + +// Local include files +#include "RelationalQueryMgr.h" +#include "uppercaseString.h" + +namespace cool { + + // Forward declarations + class ChannelSelection; + class IRelationalQueryDefinition; + class RelationalFolder; + class RelationalObjectTableRow; + class RelationalTagMgr; + + /** @class RelationalObjectTable RelationalObjectTable.h + * + * Relational schema of the table storing COOL conditions "objects" + * + * Relational implementation of the object table queries + * in termns of the RelationalQueryMgr. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2004-12-16 + */ + + class RelationalObjectTable + { + + friend class RelationalObjectMgrTest; + friend class RelationalObjectTableTest; + + public: + + static const std::string defaultTableName + ( const std::string& prefix, unsigned nodeId ) { + char tableName[] = "Fxxxx_IOVS"; + sprintf( tableName, "F%4.4i_IOVS", nodeId ); + // TEMPORARY? AV 04.04.2005 + // FIXME: presently the prefix is uppercase anyway... + return uppercaseString( prefix ) + std::string( tableName ); + } + + static const std::string sequenceName( const std::string& tableName ) { + // TEMPORARY? AV 04.04.2005 + // FIXME: presently the input table name is uppercase anyway... + return uppercaseString(tableName) + "_SEQ"; + } + + struct columnNames { + static const std::string objectId() { return "OBJECT_ID"; } + static const std::string channelId() { return "CHANNEL_ID"; } + static const std::string iovSince() { return "IOV_SINCE"; } + static const std::string iovUntil() { return "IOV_UNTIL"; } + static const std::string userTagId() { return "USER_TAG_ID"; } + static const std::string sysInsTime() { return "SYS_INSTIME"; } + static const std::string lastModDate() { return "LASTMOD_DATE"; } + static const std::string originalId() { return "ORIGINAL_ID"; } + static const std::string newHeadId() { return "NEW_HEAD_ID"; } + }; + + struct columnTypeIds { + static const StorageType::TypeId objectId = StorageType::UInt32; + static const StorageType::TypeId channelId = StorageType::UInt32; + static const StorageType::TypeId iovSince = StorageType::UInt63; + static const StorageType::TypeId iovUntil = StorageType::UInt63; + static const StorageType::TypeId userTagId = StorageType::UInt32; + // TEMPORARY! Should be Time? + static const StorageType::TypeId sysInsTime = StorageType::String255; + // TEMPORARY! Should be Time? + static const StorageType::TypeId lastModDate = StorageType::String255; + static const StorageType::TypeId originalId = StorageType::UInt32; + static const StorageType::TypeId newHeadId = StorageType::UInt32; + }; + + struct columnTypes { + typedef UInt32 objectId; + typedef UInt32 channelId; + typedef UInt63 iovSince; + typedef UInt63 iovUntil; + typedef UInt32 userTagId; + // TEMPORARY! Should be Time? + typedef String255 sysInsTime; + // TEMPORARY! Should be Time? + typedef String255 lastModDate; + typedef UInt32 originalId; + typedef UInt32 newHeadId; + }; + + public: + + // Destructor + virtual ~RelationalObjectTable(); + + /// Constructor + RelationalObjectTable + ( RelationalQueryMgr* pQueryMgr, + bool ownQueryMgr, + const RelationalFolder& folder ); + + const IRecordSpecification& payloadSpecification() const { + return m_payloadSpecification; + } + + const IRecordSpecification& tableSpecification() const { + return m_tableSpecification; + } + + /// Returns the table specification for the given payload columns + static const RecordSpecification tableSpecification + ( const IRecordSpecification& payloadSpec ); + + /// Returns an AttributeList for the given payload columns + static const coral::AttributeList rowAttributeList + ( const coral::AttributeList& payload ); + + /// Define the ORDER clause for the SV, MV HEAD and MV Tag selections. + static const + std::vector<std::string> orderByClause + ( const ChannelSelection& channels, + const std::string& objectTableName = "" ); + + /// Define the query for the SV selection. + std::auto_ptr<IRelationalQueryDefinition> + queryDefinitionSV( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const IRecordSelection* payloadQuery = 0 ); + + /// Define the query for the MV user tag and HEAD selection; + /// user tags are assumed unless isHeadTag(userTagName) is true. + std::auto_ptr<IRelationalQueryDefinition> + queryDefinitionHeadAndUserTag( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& userTagName, + const IRecordSelection* payloadQuery = 0 ); + + /// Define the query for the MV tag selection. + std::auto_ptr<IRelationalQueryDefinition> + queryDefinitionTag( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + //unsigned int tagId ); + const std::string& tagName, + const IRecordSelection* payloadQuery = 0 ); + + /// Define the query for all four: SV, MV user tag, MV HEAD and MV tag. + /// By default this defines the SV query (pTagId==0, isUserTag is ignored). + /// The HEAD case is triggered if (*pTagId)==0 (isUserTag is ignored). + std::auto_ptr<IRelationalQueryDefinition> + queryDefinitionGeneric( const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const unsigned int* pTagId = 0, + bool isUserTag = true, + const IRecordSelection* payloadQuery = 0 ); + + public: + + /// Returns the table name. + const std::string& objectTableName() const { return m_objectTableName; } + + /// Returns the associated tag table name. + const std::string& tagTableName() const { return m_tagTableName; } + + /// Returns the associated IOV2tag table name. + const std::string& object2TagTableName() const { + return m_object2TagTableName; } + + /// Returns the associated channel table name. + const std::string& channelTableName() const { return m_channelTableName; } + + /* + /// TEMPORARY! This is ONLY needed by David's VerificationClient + /// Fetch one IOV row (lookup for last inserted row in 1 channel - SV) + /// [Rows are inserted with strictly ascending objectIds: this method + /// fetches the row with the highest objectId in the given channel] + RelationalObjectTableRow fetchLastRowSV( const ChannelId& channelId, + bool fetchPayload = false ); + */ + + /// Fetch the last row in a given tag (the highest object_id) + const RelationalObjectTableRow + fetchLastRowForTagId( unsigned int tagId, + bool fetchPayload = false ) const; + + /// Fetch one IOV row (lookup at 1 time in 1 channel in HEAD tag - MV) + /// \todo TODO sas 2006-04-11 - this method was mainly used in findObject + /// which is now using browseObjects instead. There's one other use + /// (apart from tests) in RalDatabase that could be eliminated. + const RelationalObjectTableRow fetchRowAtTimeInHead + ( const ValidityKey& pointInTime, + const ChannelId& channelId, + unsigned int userTagId = 0 ); + + /* + /// Fetch one IOV row (lookup at 1 time in 1 channel in 1 tag - MV) + /// \todo TODO sas 2006-04-11 - this method was mainly used in findObject + /// which is now using browseObjects instead. There's no other use + /// (apart from tests). + RelationalObjectTableRow fetchRowAtTimeInTag + ( const ValidityKey& pointInTime, + const ChannelId& channelId, + const std::string& tagName ); + */ + + std::auto_ptr< std::vector<RelationalObjectTableRow> > + fetchRowsBtTimesInHead + ( const ValidityKey& since, + const ValidityKey& until, + const ChannelId& channelId, + unsigned int userTagId, + unsigned int maxRows ); + + /// Utility method to fetch the HEAD object table rows for tagging + /// The query only fetches the meta data (object_id, since, until,...) + /// in order to avoid reading the payload and be more lightweight. + /// Therefore the normal fetchObjectTableRows method is not used. + std::vector<RelationalObjectTableRow> fetchRowsForTaggingCurrentHead(); + + /// Utility method to fetch the object table rows 'asOfDate' for tagging. + /// The query only fetches the meta data (object_id, since, until,...) + /// in order to avoid reading the payload and be more lightweight. + /// Therefore the normal fetchObjectTableRows method is not used. + std::vector<RelationalObjectTableRow> fetchRowsForTaggingHeadAsOfDate + ( const ITime& asOfDate ); + + /// Utility method to fetch the object table rows 'asOfObjectId' + /// for tagging. The object with id 'objectId' is included. + /// The query only fetches the meta data (object_id, since, until,...) + /// in order to avoid reading the payload and be more lightweight. + /// Therefore the normal fetchObjectTableRows method is not used. + std::vector<RelationalObjectTableRow> fetchRowsForTaggingHeadAsOfObjectId + ( unsigned int asOfObjectId ); + + /// Returns the name of the object_id sequence associated with this table. + const std::string sequenceName() { + // TEMPORARY? AV 04.04.2005 + // FIXME: presently the input table name is uppercase anyway... + return uppercaseString( objectTableName() ) + "_SEQ"; + } + + /// Returns the table specification for the given payload columns + static const IRecordSpecification& defaultSpecification(); + + /// Does a channel with this id exist? + /// This is needed by dropChannel (throw if the channel has any IOVs). + bool existsChannel( const ChannelId& channelId ) const; + + protected: + + /// Get a CORAL MessageStream + coral::MessageStream& log() const; + + /// Get the RelationalQueryMgr associated to this table + RelationalQueryMgr& queryMgr() const { return *m_pQueryMgr; } + + /// Fetch one IOV row (lookup by 1 objectId - SV and MV) + const RelationalObjectTableRow + fetchRowForId( unsigned int objectId, + bool fetchPayload = false ) const; + + private: + + /// Copy constructor is private + RelationalObjectTable( const RelationalObjectTable& rhs ); + + /// Assignment operator is private + RelationalObjectTable& operator=( const RelationalObjectTable& rhs ); + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// Relational query manager + RelationalQueryMgr* m_pQueryMgr; + + /// Does this instance own the relational query manager? + bool m_ownQueryMgr; + + protected: // TEMPORARY? For the RelationalObjectTableTest friend only + + /// Relational tag manager + RelationalTagMgr& m_tagMgr; + + private: + + /// Payload specification + RecordSpecification m_payloadSpecification; + + /// Full table specification + RecordSpecification m_tableSpecification; + + /// IOV table name + std::string m_objectTableName; + + /// Tag table name + std::string m_tagTableName; + + /// IOV2tag table name + std::string m_object2TagTableName; + + /// Channel table name + std::string m_channelTableName; + + protected: // TEMPORARY? For the RelationalObjectTableTest friend only + + /// Node id for this node + unsigned int m_nodeId; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALOBJECTTABLE_H diff --git a/RelationalCool/src/RelationalObjectTableRow.cpp b/RelationalCool/src/RelationalObjectTableRow.cpp new file mode 100644 index 000000000..39e295ff6 --- /dev/null +++ b/RelationalCool/src/RelationalObjectTableRow.cpp @@ -0,0 +1,237 @@ +// $Id: RelationalObjectTableRow.cpp,v 1.25 2008-11-04 11:52:11 avalassi Exp $ + +#include "CoralBase/AttributeSpecification.h" + +// Local include files +#include "RelationalObjectTable.h" +#include "RelationalObjectTableRow.h" +#include "timeToString.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalObjectTableRow::~RelationalObjectTableRow() +{ +} + +//----------------------------------------------------------------------------- + +RelationalObjectTableRow::RelationalObjectTableRow +( const coral::AttributeList& data ) + : RelationalTableRowBase( data ) +{ +} + +//----------------------------------------------------------------------------- + +RelationalObjectTableRow::RelationalObjectTableRow( const IObjectPtr& object ) + : RelationalTableRowBase( RelationalObjectTable::rowAttributeList + ( object->payload().attributeList() ) ) +{ + + m_data[RelationalObjectTable::columnNames::objectId()].setValue + ( object->objectId() ); + + m_data[RelationalObjectTable::columnNames::channelId()].setValue + ( object->channelId() ); + + m_data[RelationalObjectTable::columnNames::iovSince()].setValue + ( object->since() ); + + m_data[RelationalObjectTable::columnNames::iovUntil()].setValue + ( object->until() ); + + m_data[RelationalObjectTable::columnNames::sysInsTime()].setValue + ( std::string("") ); + + m_data[RelationalObjectTable::columnNames::lastModDate()].setValue + ( std::string("") ); + + m_data[RelationalObjectTable::columnNames::originalId()].setValue( 0u ); + + m_data[RelationalObjectTable::columnNames::newHeadId()].setValue( 0u ); + + // Add the data payload columns + const coral::AttributeList& payload = object->payload().attributeList(); + for ( coral::AttributeList::const_iterator attr = payload.begin(); + attr != payload.end(); + ++attr ) { + // share data instead of copying + m_data[ attr->specification().name() ].shareData( *attr ); + // copy + //coral::AttributeValueAccessor + //( (*m_data)[ attr->spec().name() ] ).setValueFromData + //( coral::AttributeValueAccessor( *attr ).getMemoryAddress() ); + } + +} + +//----------------------------------------------------------------------------- + +RelationalObjectTableRow::RelationalObjectTableRow +( const RelationalTableRow& row ) + : RelationalTableRowBase( row.data() ) +{ +} + +//----------------------------------------------------------------------------- + +RelationalObjectTableRow::RelationalObjectTableRow +( const RelationalObjectTableRow& aRow ) + : RelationalTableRowBase( aRow ) +{ +} + +//----------------------------------------------------------------------------- + +RelationalObjectTableRow& +RelationalObjectTableRow::operator=( const RelationalObjectTableRow& rhs ) +{ + m_data = rhs.m_data; + return *this; +} + +//----------------------------------------------------------------------------- +/* +const RelationalObjectTableRow& +RelationalObjectTableRow::operator=( const RelationalObjectTableRow& rhs ) { + m_spec = rhs.m_spec; + m_data = AttrListPtr( new coral::AttributeList( m_spec ) ); + + // Copy the individual Attribute values + coral::AttributeList::const_iterator sourceAttr; + coral::AttributeList::iterator targetAttr = m_data->begin(); + for ( sourceAttr = rhs.m_data->begin(); + sourceAttr != rhs.m_data->end(); + sourceAttr++, targetAttr++ ) { + + coral::AttributeValueAccessor( *targetAttr ).setValueFromData + ( coral::AttributeValueAccessor( *sourceAttr ).getMemoryAddress() ); + + } + + return *this; +} +*/ +//----------------------------------------------------------------------------- + +unsigned int RelationalObjectTableRow::objectId() const +{ + return + m_data[RelationalObjectTable::columnNames::objectId()].data<unsigned int>(); +} + +//----------------------------------------------------------------------------- + +ValidityKey RelationalObjectTableRow::since() const +{ + return + m_data[RelationalObjectTable::columnNames::iovSince()].data<ValidityKey>(); +} + +//----------------------------------------------------------------------------- + +ValidityKey RelationalObjectTableRow::until() const +{ + return + m_data[RelationalObjectTable::columnNames::iovUntil()].data<ValidityKey>(); +} + +//----------------------------------------------------------------------------- + +ChannelId RelationalObjectTableRow::channelId() const +{ + return + m_data[RelationalObjectTable::columnNames::channelId()].data<ChannelId>(); +} + +//----------------------------------------------------------------------------- + +unsigned int RelationalObjectTableRow::userTagId() const +{ + return + m_data[RelationalObjectTable::columnNames::userTagId()].data<unsigned int>(); +} + +//----------------------------------------------------------------------------- + +unsigned int RelationalObjectTableRow::originalId() const +{ + return + m_data[RelationalObjectTable::columnNames::originalId()] + .data<unsigned int>(); +} + +//----------------------------------------------------------------------------- + +unsigned int RelationalObjectTableRow::newHeadId() const +{ + return + m_data[RelationalObjectTable::columnNames::newHeadId()].data<unsigned int>(); +} + +//----------------------------------------------------------------------------- + +Time RelationalObjectTableRow::insertionTime() const +{ + std::string value = + m_data[RelationalObjectTable::columnNames::sysInsTime()].data<std::string>(); + return stringToTime( value ); +} + +//----------------------------------------------------------------------------- + +Time RelationalObjectTableRow::lastModDate() const +{ + std::string value = + m_data[RelationalObjectTable::columnNames::lastModDate()] + .data<std::string>(); + return stringToTime( value ); +} + +//----------------------------------------------------------------------------- + +void RelationalObjectTableRow::setObjectId( unsigned int objectId ) +{ + m_data[RelationalObjectTable::columnNames::objectId()].setValue( objectId ); +} + +//----------------------------------------------------------------------------- + +void RelationalObjectTableRow::setSince( const ValidityKey& since ) +{ + m_data[RelationalObjectTable::columnNames::iovSince()].setValue( since ); +} + +//----------------------------------------------------------------------------- + +void RelationalObjectTableRow::setUntil( const ValidityKey& until ) +{ + m_data[RelationalObjectTable::columnNames::iovUntil()].setValue( until ); +} + +//----------------------------------------------------------------------------- + +void RelationalObjectTableRow::setUserTagId( unsigned int userTagId ) +{ + m_data[RelationalObjectTable::columnNames::userTagId()].setValue( userTagId ); +} + +//----------------------------------------------------------------------------- + +void RelationalObjectTableRow::setOriginalId( unsigned int value ) +{ + m_data[RelationalObjectTable::columnNames::originalId()].setValue( value ); +} + +//----------------------------------------------------------------------------- + +void RelationalObjectTableRow::setNewHeadId( unsigned int value ) +{ + m_data[RelationalObjectTable::columnNames::newHeadId()].setValue( value ); +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalObjectTableRow.h b/RelationalCool/src/RelationalObjectTableRow.h new file mode 100644 index 000000000..9e5044a41 --- /dev/null +++ b/RelationalCool/src/RelationalObjectTableRow.h @@ -0,0 +1,177 @@ +// $Id: RelationalObjectTableRow.h,v 1.31 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALOBJECTTABLEROW_H +#define RELATIONALCOOL_RELATIONALOBJECTTABLEROW_H + +// Include files +#include "CoolKernel/IObject.h" +#include "CoolKernel/Time.h" +#include "CoolKernel/ValidityKey.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeListException.h" + +// Local include files +#include "RelationalTableRow.h" +#include "RelationalTableRowBase.h" + +namespace cool { + + /** @class RelationalObjectTableRow RelationalObjectTableRow.h + * + * Representation of a RelationalObject as a row in the object table. + * Used internally to read/write data from/into persistent storage. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2005-02-09 + */ + + class RelationalObjectTableRow : public RelationalTableRowBase + { + + public: + + /// Destructor + virtual ~RelationalObjectTableRow(); + + /// Constructor from an AttributeList. + /// Performs a deep copy of the AttributeList values. + explicit RelationalObjectTableRow( const coral::AttributeList& data ); + + /// Constructor from an IObjectPtr. + /// For performance reasons, only copies references to the object payload: + /// a row is expected to never outlive the object it originated from. + explicit RelationalObjectTableRow( const IObjectPtr& object ); + + /// Constructor from a RelationalTableRow. + /// This constructor is used to 'reinterpret' a generic table row as + /// obtained from fetch methods as a RelationalObjectTableRow. + explicit RelationalObjectTableRow( const RelationalTableRow& row ); + + /// Copy constructor + /// Performs a deep copy of the AttributeList values. + RelationalObjectTableRow( const RelationalObjectTableRow& aRow ); + + /// Assignment operator. + /// Performs a deep copy of the AttributeList values. + RelationalObjectTableRow& operator=( const RelationalObjectTableRow& rhs ); + + /// Comparison operator -- only takes into account object_id + bool operator==( const RelationalObjectTableRow& rhs ) + { + return objectId() == rhs.objectId(); + } + + /// Returns true if the given point in time lies in the row's IOV + bool contains( const ValidityKey& pointInTime ) + { + return since() <= pointInTime && pointInTime < until(); + } + + /// Returns the object id + unsigned int objectId() const; + + /// Returns the beginning of the IOV + ValidityKey since() const; + + /// Returns the beginning of the IOV + ValidityKey until() const; + + /// Returns the channel id + ChannelId channelId() const; + + /// Returns the user tag id + unsigned int userTagId() const; + + /// Returns the original id + unsigned int originalId() const; + + /// Returns the new head id + unsigned int newHeadId() const; + + /// Returns the insertion time + Time insertionTime() const; + + /// Returns the last modification date + Time lastModDate() const; + + /// Sets the object id + void setObjectId( unsigned int objectId ); + + /// Sets the beginning of the IOV + void setSince( const ValidityKey& since ); + + /// Sets the end of the IOV + void setUntil( const ValidityKey& until ); + + /// Sets the user tag id + void setUserTagId( unsigned int userTagId ); + + /// Sets the original id + void setOriginalId( unsigned int value ); + + /// Sets the new head id + void setNewHeadId( unsigned int value ); + + /// Data payload value for a specific payload item - returned as true type + template<class T> const T& payloadValue( const std::string& name ) const + { + // AV 19.06.2006 Old version that works for Linux gcc323 + //return m_data[name].data(); + // SAS 19.06.2006 changed for linux gcc403 but fails for Linux gcc323 + //return m_data[name].data<T>(); + // MCl 28.03.2006 this one works on gcc 4.x and 3.2 + return m_data[name].template data<T>(); + } + + private: + + /// Standard constructor is private. + RelationalObjectTableRow(); + + }; + + /// Streamer for RelationalObjectTableRow objects + inline std::ostream &operator<< + ( std::ostream& s, const RelationalObjectTableRow& r ) + { + s << r.objectId() << " [" << r.since() << "," << r.until() << "] "; + s << "["; + bool first = true; + for ( coral::AttributeList::const_iterator attr = r.begin(); + attr != r.end(); ++attr ) { + if ( first ) { + first = false; + } else { + s << "|"; + } + attr->toOutputStream( s ); + } + s << "] "; + try { + s << r.originalId() << " " << r.newHeadId(); + } catch ( coral::AttributeListException& ) { /* ignored */ } + return s; + } + + /// Comparison functor to compare RelationalObjectTableRow by their objectId + struct eq_objectId : + public std::binary_function<RelationalObjectTableRow, unsigned int, bool> + { + bool operator()( const RelationalObjectTableRow& r, + unsigned int objectId ) const { + return r.objectId() == objectId; } + }; + + /// Less than comparison functor to compare RelationalObjectTableRow + /// by their objectId + struct lt_objectId : + public std::binary_function< RelationalObjectTableRow, + RelationalObjectTableRow, bool> + { + bool operator()( const RelationalObjectTableRow& lhs, + const RelationalObjectTableRow& rhs ) const { + return lhs.objectId() < rhs.objectId(); } + }; + +} + +#endif // RELATIONALCOOL_RELATIONALOBJECTTABLEROW_H diff --git a/RelationalCool/src/RelationalPayloadQuery.cpp b/RelationalCool/src/RelationalPayloadQuery.cpp new file mode 100644 index 000000000..385b7c6e7 --- /dev/null +++ b/RelationalCool/src/RelationalPayloadQuery.cpp @@ -0,0 +1,315 @@ +// $Id: RelationalPayloadQuery.cpp,v 1.13 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include <typeinfo> +#include "CoolKernel/InternalErrorException.h" + +// Local include files +#include "RelationalException.h" +#include "RelationalPayloadQuery.h" + +// Namespace +using namespace cool; + +//--------------------------------------------------------------------------- + +RelationalPayloadQuery::~RelationalPayloadQuery() +{ +} + +//--------------------------------------------------------------------------- + +RelationalPayloadQuery::RelationalPayloadQuery( const IRecordSelection& sel, + const std::string& tableName, + const std::string& technology ) + : m_tableName( tableName ) + , m_technology( technology ) +{ + if ( m_technology != "" && + m_technology != "Oracle" && + m_technology != "MySQL" && + m_technology != "SQLite" && + m_technology != "Frontier" ) + throw RelationalException( "Unknown technology '" + technology + "'", + "RelationalPayloadQuery" ); + + // Build the WHERE clause and WHERE data for the selection + m_isTrusted = addSelection( sel, m_whereClause, m_whereData ); + + // Reset WHERE clause and WHERE data if the query is not trusted + if ( !m_isTrusted ) + { + m_whereClause = ""; + m_whereData = Record(); + } + +} + +//--------------------------------------------------------------------------- + +const std::string& RelationalPayloadQuery::whereClause() const +{ + if ( !m_isTrusted ) + throw RelationalException( "Query is not trusted", + "RelationalPayloadQuery" ); + return m_whereClause; +} + +//--------------------------------------------------------------------------- + +const IRecord& RelationalPayloadQuery::whereData() const +{ + if ( !m_isTrusted ) + throw RelationalException( "Query is not trusted", + "RelationalPayloadQuery" ); + return m_whereData; +} + +//--------------------------------------------------------------------------- + +const std::string +RelationalPayloadQuery::bindVariableName( unsigned ibv ) const +{ + if ( ibv >= 10000 ) + throw RelationalException( "Too many bind variables!", + "RelationalPayloadQuery" ); + char cName[] = "pqbv0001"; + int cSize = std::string(cName).size(); + if ( sprintf( cName, "pqbv%4.4d", ibv ) != cSize ) + throw InternalErrorException( "PANIC! Error encoding bind variable name", + "RelationalPayloadQuery" ); + std::string sName( cName ); + return sName; +} + +//--------------------------------------------------------------------------- + +bool +RelationalPayloadQuery::addSelection( const IRecordSelection& sel, + std::string& whereClause, + Record& whereData ) const +{ + // Loop over trusted query classes + const std::type_info& selType = typeid( sel ); + + // Is the query a FieldSelection? + if ( selType == typeid( FieldSelection ) ) + { + const FieldSelection* pSel = + dynamic_cast<const FieldSelection*>( &sel ); + if ( !pSel ) + throw InternalErrorException + ( "PANIC! Cannot dynamic cast to FieldSelection*", + "RelationalPayloadQuery" ); + // Add the WHERE clause and WHERE data for a FieldSelection + return addFieldSelection( *pSel, whereClause, whereData ); + } + + // Is the query a CompositeSelection? + else if ( selType == typeid( CompositeSelection ) ) + { + const CompositeSelection* pSel = + dynamic_cast<const CompositeSelection*>( &sel ); + if ( !pSel ) + throw InternalErrorException + ( "PANIC! Cannot dynamic cast to CompositeSelection*", + "RelationalPayloadQuery" ); + // Add the WHERE clause and WHERE data for a CompositeSelection + return addCompositeSelection( *pSel, whereClause, whereData ); + } + + // UNKNOWN query (user-supplied query) + else + { + return false; + } + +} + +//--------------------------------------------------------------------------- + +bool +RelationalPayloadQuery::addFieldSelection( const FieldSelection& sel, + std::string& whereClause, + Record& whereData ) const +{ + FieldSelection::Relation rel = sel.relation(); + const IField& ref = sel.referenceValue(); + + // FieldSelection is a comparison to NULL (either IS_NULL or IS_NOT_NULL) + if ( ref.isNull() ) + { + FieldSelection::Nullness nul = sel.nullness(); + // No path to here if ref is a string: ref.isNull() is always false! + if ( ref.specification().storageType().id() == StorageType::String255 || + ref.specification().storageType().id() == StorageType::String4k || + ref.specification().storageType().id() == StorageType::String64k || + ref.specification().storageType().id() == StorageType::String16M ) + throw InternalErrorException + ( "PANIC! isNull() cannot be true for string fields", + "RelationalPayloadQuery" ); + // Add the WHERE clause (no WHERE data to add) + if ( m_tableName != "" ) whereClause += m_tableName; + whereClause += ref.specification().name(); + whereClause += " "; + whereClause += FieldSelection::describe( nul ); // IS_NULL or IS_NOT_NULL + } + + // FieldSelection is NOT a comparison to NULL + // (but it could still be a comparison to the '' string) + else + { + // Special handling for strings + if ( ref.specification().storageType().id() == StorageType::String255 || + ref.specification().storageType().id() == StorageType::String4k || + ref.specification().storageType().id() == StorageType::String64k || + ref.specification().storageType().id() == StorageType::String16M ) + { + if ( rel != FieldSelection::EQ && rel != FieldSelection::NE ) + throw InternalErrorException + ( "PANIC! Relation other than EQ or NE for strings", + "RelationalPayloadQuery" ); + // Comparison to empty string '' + if ( ref.data<std::string>() == "" ) + { + // Oracle: do not compare to '', use IS NULL and IS NOT NULL instead + // [Oracle non-Boolean logic: "S=''" is NULL, neither true nor false] + // => S EQ '' uses "S IS NULL" + // => S NE '' uses "S IS NOT NULL" + if ( m_technology == "Oracle" || m_technology == "Frontier" ) + { + // Add WHERE clause + if ( m_tableName != "" ) whereClause += m_tableName; + whereClause += ref.specification().name(); + whereClause += " "; + if ( rel == FieldSelection::EQ ) + { + whereClause += + FieldSelection::describe( FieldSelection::IS_NULL ); + } + else + { + whereClause += + FieldSelection::describe( FieldSelection::IS_NOT_NULL ); + } + } + // Other backends: compare to '' and also to NULL + // => S EQ '' uses "S IS NULL OR S=''" + // => S NE '' uses "S IS NOT NULL AND S!=''" + else + { + // Add WHERE clause + if ( m_tableName != "" ) whereClause += m_tableName; + whereClause += ref.specification().name(); + whereClause += " "; + if ( rel == FieldSelection::EQ ) + { + whereClause += + FieldSelection::describe( FieldSelection::IS_NULL ); + whereClause += " OR "; + } + else + { + whereClause += + FieldSelection::describe( FieldSelection::IS_NOT_NULL ); + whereClause += " AND "; + } + if ( m_tableName != "" ) whereClause += m_tableName; + whereClause += ref.specification().name(); + whereClause += " "; + whereClause += FieldSelection::describe( rel ); + whereClause += " ''"; // No bind variables (more readable SQL) + } + } + // Comparison to non-empty string 'XXX' + else + { + // Same for Oracle and others + // => S EQ 'XXX' uses "S IS NOT NULL AND S='XXX'" + // => S NE 'XXX' uses "S IS NULL OR S!='XXX'" + { + // Get the next available bind variable name + unsigned ibv = whereData.size() + 1; + std::string bvName = bindVariableName( ibv ); + // Add the WHERE clause + if ( m_tableName != "" ) whereClause += m_tableName; + whereClause += ref.specification().name(); + whereClause += " "; + if ( rel == FieldSelection::EQ ) + { + whereClause += + FieldSelection::describe( FieldSelection::IS_NOT_NULL ); + whereClause += " AND "; + } + else + { + whereClause += + FieldSelection::describe( FieldSelection::IS_NULL ); + whereClause += " OR "; + } + if ( m_tableName != "" ) whereClause += m_tableName; + whereClause += ref.specification().name(); + whereClause += " "; + whereClause += FieldSelection::describe( rel ); + whereClause += " :" + bvName; + // Add the WHERE data + RecordSpecification rspec; + rspec.extend( bvName, ref.specification().storageType() ); + Record rec( rspec ); + rec[0].setValue( ref ); + whereData.extend( rec ); + } + } + } + // All types other than strings + else + { + // Get the next available bind variable name + unsigned ibv = whereData.size() + 1; + std::string bvName = bindVariableName( ibv ); + // Add the WHERE clause + if ( m_tableName != "" ) whereClause += m_tableName; + whereClause += ref.specification().name(); + whereClause += " "; + whereClause += FieldSelection::describe( rel ); + whereClause += " :" + bvName; + // Add the WHERE data + RecordSpecification rspec; + rspec.extend( bvName, ref.specification().storageType() ); + Record rec( rspec ); + rec[0].setValue( ref ); + whereData.extend( rec ); + } + } + + // Success - selection is trusted + return true; +} + +//--------------------------------------------------------------------------- + +bool +RelationalPayloadQuery::addCompositeSelection( const CompositeSelection& sel, + std::string& whereClause, + Record& whereData ) const +{ + // Loop over the connected selections + for ( unsigned int iSel = 0; iSel < sel.size(); iSel++ ) + { + if ( iSel > 0 ) + { + whereClause += " "; + whereClause += CompositeSelection::describe( sel.connective() ); + whereClause += " "; + } + whereClause += "( "; + if ( !addSelection( *(sel[iSel]), whereClause, whereData ) ) return false; + whereClause += " )"; + } + + // Success - selection is trusted + return true; +} + +//--------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalPayloadQuery.h b/RelationalCool/src/RelationalPayloadQuery.h new file mode 100644 index 000000000..0a5ad23ef --- /dev/null +++ b/RelationalCool/src/RelationalPayloadQuery.h @@ -0,0 +1,129 @@ +// $Id: RelationalPayloadQuery.h,v 1.9 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALPAYLOADQUERY_H +#define RELATIONALCOOL_RELATIONALPAYLOADQUERY_H + +// Include files +//#include <memory> +#include "CoolKernel/CompositeSelection.h" +#include "CoolKernel/FieldSelection.h" +#include "CoolKernel/IRecordSelection.h" +#include "CoolKernel/Record.h" + +namespace cool { + + /** @class RelationalPayloadQuery RelationalPayloadQuery.h + * + * @author Andrea Valassi, Martin Wache + * @date 2008-07-29 + */ + + // AV Inheritance is probably not needed here? + class RelationalPayloadQuery //: virtual public IRecordSelection + { + + public: + + /// Destructor + virtual ~RelationalPayloadQuery(); + + /// Constructor from an IRecordSelection. + /// Parameter tableName should already contain the trailing '.' so that it + /// can be prepended directly to column names (e.g. 'table.' + 'column'). + RelationalPayloadQuery( const IRecordSelection& selection, + const std::string& tableName = "", + const std::string& technology = "" ); + + /* + /// Can the selection be applied to a record with the given specification? + bool canSelect( const IRecordSpecification& spec ) const + { + return m_selection->canSelect( spec ); + } + + /// Apply the selection to the given record. + bool select( const IRecord& record ) const + { + return m_selection->canSelect( spec ); + } + + /// Clone the record selection (and any objects referenced therein). + IRecordSelection* clone() const; + */ + + /// Is this payload query trusted? + bool isTrusted() const + { + return m_isTrusted; + } + + /// Return the WHERE clause. + /// Throw an exception if this payload query is not trusted. + const std::string& whereClause() const; + + /// Return the WHERE data (bind variables). + /// Throw an exception if this payload query is not trusted. + const IRecord& whereData() const; + + private: + + /// Copy constructor is private + RelationalPayloadQuery( const RelationalPayloadQuery& rhs ); + + /// Assignment operator is private + RelationalPayloadQuery& operator=( const RelationalPayloadQuery& rhs ); + + /// Bind variable name for the i-th bind variable (i>0) + const std::string bindVariableName( unsigned ibv ) const; + + /// Add WHERE clause and WHERE data for a generic IRecordSelection. + /// The return value (true on success, false on failure) + /// indicates whether the input record selection can be trusted. + /// Keep track of how many variables have been used already. + bool addSelection( const IRecordSelection& sel, + std::string& whereClause, + Record& whereData ) const; + + /// Add WHERE clause and WHERE data for a FieldSelection. + /// The return value (true on success, false on failure) + /// indicates whether the input record selection can be trusted. + /// Keep track of how many variables have been used already. + bool addFieldSelection( const FieldSelection& sel, + std::string& whereClause, + Record& whereData ) const; + + /// Add WHERE clause and WHERE data for a CompositeSelection. + /// The return value (true on success, false on failure) + /// indicates whether the input record selection can be trusted. + /// Keep track of how many variables have been used already. + bool addCompositeSelection( const CompositeSelection& sel, + std::string& whereClause, + Record& whereData ) const; + + private: + + /* + // AV The clone is probably not needed here with no inheritance? + /// Private clone of the user-supplied record selection + std::auto_ptr<IRecordSelection> m_selection; + */ + + /// Table name + const std::string m_tableName; + + /// Technology + const std::string m_technology; + + /// Is this payload query truested? + bool m_isTrusted; + + /// The WHERE clause (SQL fragment) + std::string m_whereClause; + + /// The WHERE data (bind variables) + Record m_whereData; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALPAYLOADQUERY_H diff --git a/RelationalCool/src/RelationalQueryDefinition.cpp b/RelationalCool/src/RelationalQueryDefinition.cpp new file mode 100644 index 000000000..9aab9ffee --- /dev/null +++ b/RelationalCool/src/RelationalQueryDefinition.cpp @@ -0,0 +1,445 @@ +// $Id: RelationalQueryDefinition.cpp,v 1.8 2008-11-04 11:52:11 avalassi Exp $ + +// Local include files +#include "RelationalException.h" +#include "RelationalQueryDefinition.h" + +//--------------------------------------------------------------------------- + +namespace cool +{ + namespace RelationalQueryDefinitionImpl + { + class SelectItem : public IRelationalQueryDefinition::ISelectItem + { + + public: + + virtual ~SelectItem() + { + if ( m_subquery ) delete m_subquery; + } + + SelectItem( const std::string& expression, + const std::string& alias = "" ) + : m_expression( expression ) + , m_subquery( 0 ) + , m_alias( alias ) + { + } + + SelectItem( const IRelationalQueryDefinition& subquery, + const std::string& alias ) + : m_expression( "" ) + , m_subquery( subquery.clone() ) + , m_alias( alias ) + { + if ( m_alias == "" ) + throw RelationalException( "Subquery with no alias", "SelectItem" ); + } + + bool isSubquery() const + { + return NULL != m_subquery; + } + + const std::string& expression() const + { + if ( m_subquery ) + throw RelationalException( "This is a subquery", "SelectItem" ); + return m_expression; + } + + const IRelationalQueryDefinition& subquery() const + { + if ( ! m_subquery ) + throw RelationalException( "This is not a subquery", "SelectItem" ); + return *m_subquery; + } + + const std::string& alias() const + { + return m_alias; + } + + const ISelectItem* clone() const + { + if ( m_subquery ) return new SelectItem( *m_subquery, m_alias ); + else return new SelectItem( m_expression, m_alias ); + } + + private: + + const std::string m_expression; + const IRelationalQueryDefinition* m_subquery; + const std::string m_alias; + + }; + } +} + +//--------------------------------------------------------------------------- + +namespace cool +{ + namespace RelationalQueryDefinitionImpl + { + class FromItem : public IRelationalQueryDefinition::IFromItem + { + + public: + + virtual ~FromItem() + { + if ( m_subquery ) delete m_subquery; + } + + FromItem( const std::string& expression, + const std::string& alias = "" ) + : m_expression( expression ) + , m_subquery( 0 ) + , m_alias( alias ) + { + } + + FromItem( const IRelationalQueryDefinition& subquery, + const std::string& alias ) + : m_expression( "" ) + , m_subquery( subquery.clone() ) + , m_alias( alias ) + { + if ( m_alias == "" ) + throw RelationalException( "Subquery with no alias", "FromItem" ); + } + + bool isSubquery() const + { + return NULL != m_subquery; + } + + const std::string& expression() const + { + if ( m_subquery ) + throw RelationalException( "This is a subquery", "FromItem" ); + return m_expression; + } + + const IRelationalQueryDefinition& subquery() const + { + if ( ! m_subquery ) + throw RelationalException( "This is not a subquery", "FromItem" ); + return *m_subquery; + } + + const std::string& alias() const + { + return m_alias; + } + + const IFromItem* clone() const + { + if ( m_subquery ) return new FromItem( *m_subquery, m_alias ); + else return new FromItem( m_expression, m_alias ); + } + + private: + + const std::string m_expression; + const IRelationalQueryDefinition* m_subquery; + const std::string m_alias; + + }; + } +} + +//--------------------------------------------------------------------------- + +namespace cool +{ + namespace RelationalQueryDefinitionImpl + { + class GroupItem : public IRelationalQueryDefinition::IGroupItem + { + + public: + + virtual ~GroupItem() + { + } + + GroupItem( const std::string& expression ) + : m_expression( expression ) + { + } + + const std::string& expression() const + { + return m_expression; + } + + const IGroupItem* clone() const + { + return new GroupItem( m_expression ); + } + + private: + + const std::string m_expression; + + }; + } +} + +//--------------------------------------------------------------------------- + +namespace cool +{ + namespace RelationalQueryDefinitionImpl + { + class OrderItem : public IRelationalQueryDefinition::IOrderItem + { + + public: + + virtual ~OrderItem() + { + } + + OrderItem( const std::string& expression ) + : m_expression( expression ) + { + } + + const std::string& expression() const + { + return m_expression; + } + + const IOrderItem* clone() const + { + return new OrderItem( m_expression ); + } + + private: + + const std::string m_expression; + + }; + } +} + +//--------------------------------------------------------------------------- + +// Namespaces +using namespace cool; +using namespace RelationalQueryDefinitionImpl; + +//--------------------------------------------------------------------------- + +RelationalQueryDefinition::RelationalQueryDefinition() {} + +//--------------------------------------------------------------------------- + +RelationalQueryDefinition::~RelationalQueryDefinition() +{ + for ( std::vector<const ISelectItem* >::const_iterator + it = m_selectList.begin(); it != m_selectList.end(); it++ ) + delete *it; + + for ( std::vector<const IFromItem* >::const_iterator + it = m_fromClause.begin(); it != m_fromClause.end(); it++ ) + delete *it; + + for ( std::vector<const IGroupItem* >::const_iterator + it = m_groupClause.begin(); it != m_groupClause.end(); it++ ) + delete *it; + + for ( std::vector<const IOrderItem* >::const_iterator + it = m_orderClause.begin(); it != m_orderClause.end(); it++ ) + delete *it; +} + +//--------------------------------------------------------------------------- + +const IRelationalQueryDefinition* RelationalQueryDefinition::clone() const +{ + RelationalQueryDefinition* query = new RelationalQueryDefinition(); + + query->setHint( m_hint ); + + for ( std::vector<const ISelectItem* >::const_iterator + it = m_selectList.begin(); it != m_selectList.end(); it++ ) + query->addSelectItem( **it ); + + for ( std::vector<const IFromItem* >::const_iterator + it = m_fromClause.begin(); it != m_fromClause.end(); it++ ) + query->addFromItem( **it ); + + query->setWhereClause( m_whereClause ); + + for ( std::vector<const IGroupItem* >::const_iterator + it = m_groupClause.begin(); it != m_groupClause.end(); it++ ) + query->addGroupItem( **it ); + + for ( std::vector<const IOrderItem* >::const_iterator + it = m_orderClause.begin(); it != m_orderClause.end(); it++ ) + query->addOrderItem( **it ); + + query->setBindVariables( m_bindVariables ); + + query->setResultSetSpecification( m_resultSetSpecification ); + + return query; +} + +//--------------------------------------------------------------------------- + +std::ostream& RelationalQueryDefinition::print( std::ostream& s ) const +{ + s << "RelationalQueryDefinition: "; + + s << "SELECT "; + + if ( m_hint != "" ) s << m_hint << " "; + else s << "/*+ [None] */ "; + + if ( m_selectList.size() > 0 ) + { + for ( std::vector<const ISelectItem* >::const_iterator + it = m_selectList.begin(); it != m_selectList.end(); it++ ) + { + if ( it != m_selectList.begin() ) s << ", "; + s << (*it)->expression(); + if ( (*it)->alias() != "" ) s << " AS " << (*it)->alias(); + } + } + else s << "[None]"; + + s << " FROM "; + if ( m_fromClause.size() > 0 ) + { + for ( std::vector<const IFromItem* >::const_iterator + it = m_fromClause.begin(); it != m_fromClause.end(); it++ ) + { + if ( it != m_fromClause.begin() ) s << ", "; + if ( (*it)->isSubquery() ) s << "( " << (*it)->subquery() << " )"; + else s << (*it)->expression(); + if ( (*it)->alias() != "" ) s << " AS " << (*it)->alias(); + } + } + else s << "[None]"; + + s << " WHERE "; + if ( m_whereClause != "" ) s << m_whereClause; + else s << "[None]"; + + s << " GROUP BY "; + if ( m_groupClause.size() > 0 ) + { + for ( std::vector<const IGroupItem* >::const_iterator + it = m_groupClause.begin(); it != m_groupClause.end(); it++ ) + { + if ( it != m_groupClause.begin() ) s << ", "; + s << (*it)->expression(); + } + } + else s << "[None]"; + + s << " ORDER BY "; + if ( m_orderClause.size() > 0 ) + { + for ( std::vector<const IOrderItem* >::const_iterator + it = m_orderClause.begin(); it != m_orderClause.end(); it++ ) + { + if ( it != m_orderClause.begin() ) s << ", "; + s << (*it)->expression(); + } + } + else s << "[None]"; + + s << "; BIND VARIABLES: "; + if ( m_bindVariables.size() > 0 ) + { + s << m_bindVariables; + } + else s << "[None]"; + + s << "; RESULT SET SPECIFICATION: "; + if ( m_resultSetSpecification.size() > 0 ) + { + for ( UInt32 i = 0; i < m_resultSetSpecification.size(); ++i ) + { + if ( i > 0 ) s << ", "; + s << m_resultSetSpecification[i].name(); + } + } + else s << "[None]"; + + return s; +} + +//--------------------------------------------------------------------------- + +void +RelationalQueryDefinition::addSelectItem( const std::string& expression, + const std::string& alias ) +{ + m_selectList.push_back( new SelectItem( expression, alias ) ); +} + +//--------------------------------------------------------------------------- + +void +RelationalQueryDefinition::addSelectItems( const IRecordSpecification& items, + const std::string& prefix ) +{ + for ( unsigned int i=0; i<items.size(); i++ ) + m_selectList.push_back( new SelectItem( prefix + items[i].name() ) ); +} + +//--------------------------------------------------------------------------- + +/* +void +RelationalQueryDefinition::addSelectItem( const IRelationalQueryDefinition& sq, + const std::string& alias ) +{ + m_selectList.push_back( new SelectItem( sq, alias ) ); +} +*/ + +//--------------------------------------------------------------------------- + +void +RelationalQueryDefinition::addFromItem( const std::string& expression, + const std::string& alias ) +{ + m_fromClause.push_back( new FromItem( expression, alias ) ); +} + +//--------------------------------------------------------------------------- + +void +RelationalQueryDefinition::addFromItem( const IRelationalQueryDefinition& sq, + const std::string& alias ) +{ + m_fromClause.push_back( new FromItem( sq, alias ) ); +} + +//--------------------------------------------------------------------------- + +void +RelationalQueryDefinition::addGroupItem( const std::string& expression ) +{ + m_groupClause.push_back( new GroupItem( expression ) ); +} + +//--------------------------------------------------------------------------- + +void +RelationalQueryDefinition::addOrderItem( const std::string& expression ) +{ + m_orderClause.push_back( new OrderItem( expression ) ); +} + +//--------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalQueryDefinition.h b/RelationalCool/src/RelationalQueryDefinition.h new file mode 100644 index 000000000..3aa75e3e1 --- /dev/null +++ b/RelationalCool/src/RelationalQueryDefinition.h @@ -0,0 +1,226 @@ +// $Id: RelationalQueryDefinition.h,v 1.7 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALQUERYDEFINITION_H +#define RELATIONALCOOL_RELATIONALQUERYDEFINITION_H + +// Include files +#include "CoolKernel/Record.h" + +// Local include files +#include "IRelationalQueryDefinition.h" + +namespace cool { + + /** @class RelationalQueryDefinition RelationalQueryDefinition.h + * + * Relational query definition. + * + * @author Andrea Valassi + * @date 2007-06-19 + */ + + class RelationalQueryDefinition : public IRelationalQueryDefinition { + + public: + + /// Constructor. + RelationalQueryDefinition(); + + /// Destructor. + virtual ~RelationalQueryDefinition(); + + /// Clone this query definition. + const IRelationalQueryDefinition* clone() const; + + /// Get the hint in the format "/*+ hints */" + /// ("SELECT /*+ hints */ expr1 alias1, expr2 alias2, ..."). + const std::string& getHint() const + { + return m_hint; + } + + /// Get the SELECT list size + /// ("SELECT expr1 alias1, expr2 alias2, ..."). + unsigned getSelectSize() const + { + return m_selectList.size(); + } + + /// Get a SELECT list item + /// ("SELECT expr1 alias1, expr2 alias2, ..."). + const ISelectItem& getSelectItem( unsigned item ) const + { + return *(m_selectList[item]); + } + + /// Get the FROM clause size + /// ("FROM table1 alias1, table2 alias2, ..."). + unsigned getFromSize() const + { + return m_fromClause.size(); + } + + /// Get a FROM clause item + /// ("FROM table1 alias1, table2 alias2, ..."). + const IFromItem& getFromItem( unsigned item ) const + { + return *(m_fromClause[item]); + } + + /// Get the WHERE clause ("WHERE ..."). + const std::string& getWhereClause() const + { + return m_whereClause; + } + + /// Get the GROUP BY clause size + /// ("GROUP BY expr1, expr2..."). + unsigned getGroupSize() const + { + return m_groupClause.size(); + } + + /// Get a GROUP BY clause item + /// ("GROUP BY expr1, expr2..."). + const IGroupItem& getGroupItem( unsigned item ) const + { + return *(m_groupClause[item]); + } + + /// Get the ORDER BY clause size + /// ("ORDER BY expr1, expr2..."). + unsigned getOrderSize() const + { + return m_orderClause.size(); + } + + /// Get an ORDER BY clause item + /// ("ORDER BY expr1, expr2..."). + const IOrderItem& getOrderItem( unsigned item ) const + { + return *(m_orderClause[item]); + } + + /// Get the bind variables. + /// Bind variables are not necessary here if this is a subquery definition. + const IRecord& getBindVariables() const + { + return m_bindVariables; + } + + /// Get the result set specification. + /// The result set spec is ignored if this is a subquery definition. + const IRecordSpecification& getResultSetSpecification() const + { + return m_resultSetSpecification; + } + + /// Print the relational query definition to an output stream. + std::ostream& print( std::ostream& s ) const; + + /// Set the hint for the query: "SELECT /*+ hints */". + /// The input argument should already be in the form "/*+ hints */". + void setHint( const std::string& hint ) + { + m_hint = hint; + } + + /// Appends an expression to the select list: "SELECT expression alias". + void addSelectItem( const std::string& expression, + const std::string& alias = "" ); + + /// Appends a subquery to the select list: "SELECT (subquery) alias". + /// This may contain bind variables whose values will be defined later. + /// A deep copy of the subquery definition is performed. + //void addSelectItem( const IRelationalQueryDefinition& subquery, + // const std::string& alias = "" ); + + /// Appends many fields to the select list: "SELECT [prefix]x1...". + void addSelectItems( const IRecordSpecification& items, + const std::string& prefix = "" ); + + /// Appends an item to the SELECT list. + /// This may contain bind variables whose values will be defined later. + /// A deep copy of the SELECT list item is performed. + void addSelectItem( const ISelectItem& item ) + { + m_selectList.push_back( item.clone() ); + } + + /// Appends a table to the FROM clause: "FROM table alias". + void addFromItem( const std::string& expression, + const std::string& alias = "" ); + + /// Appends a subquery to the FROM clause: "FROM (subquery) alias". + /// This may contain bind variables whose values will be defined later. + /// A deep copy of the subquery definition is performed. + void addFromItem( const IRelationalQueryDefinition& subquery, + const std::string& alias = "" ); + + /// Appends an item to the FROM clause. + /// This may contain bind variables whose values will be defined later. + /// A deep copy of the FROM clause item is performed. + void addFromItem( const IFromItem& item ) + { + m_fromClause.push_back( item.clone() ); + } + + /// Defines the WHERE clause for the query. + /// This may contain bind variables whose values will be defined later. + void setWhereClause( const std::string& condition ) + { + m_whereClause = condition; + } + + /// Appends an item to the GROUP BY clause. + void addGroupItem( const std::string& expression ); + + /// Appends an item to the GROUP BY clause. + /// A deep copy of the GROUP BY clause item is performed. + void addGroupItem( const IGroupItem& item ) + { + m_groupClause.push_back( item.clone() ); + } + + /// Appends an item to the ORDER BY clause. + void addOrderItem( const std::string& expression ); + + /// Appends an item to the ORDER BY clause. + /// A deep copy of the ORDER BY clause item is performed. + void addOrderItem( const IOrderItem& item ) + { + m_orderClause.push_back( item.clone() ); + } + + /// Defines the bind variables. + void setBindVariables( const IRecord& bindVariables ) + { + m_bindVariables = bindVariables; + } + + /// Defines the result set specification. + void setResultSetSpecification( const IRecordSpecification& spec ) + { + m_resultSetSpecification = spec; + } + + private: + + RelationalQueryDefinition( const RelationalQueryDefinition& ); + RelationalQueryDefinition& operator=( const RelationalQueryDefinition& ); + + private: + + std::string m_hint; + std::vector<const ISelectItem* > m_selectList; + std::vector<const IFromItem* > m_fromClause; + std::string m_whereClause; + std::vector<const IGroupItem*> m_groupClause; + std::vector<const IOrderItem*> m_orderClause; + Record m_bindVariables; + RecordSpecification m_resultSetSpecification; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALQUERYDEFINITION_H diff --git a/RelationalCool/src/RelationalQueryMgr.cpp b/RelationalCool/src/RelationalQueryMgr.cpp new file mode 100644 index 000000000..2904e2cc9 --- /dev/null +++ b/RelationalCool/src/RelationalQueryMgr.cpp @@ -0,0 +1,106 @@ +// $Id: RelationalQueryMgr.cpp,v 1.27 2008-11-04 11:52:11 avalassi Exp $ + +// Local include files +#include "RelationalException.h" +#include "RelationalQueryMgr.h" +#include "RelationalTableRow.h" +#include "timeToString.h" + +// Namespace +using namespace cool; + +//--------------------------------------------------------------------------- + +RelationalQueryMgr::RelationalQueryMgr( ) + : m_log( new coral::MessageStream( "RelationalQueryMgr" ) ) +{ + log() << coral::Debug + << "Instantiate a RelationalQueryMgr" << coral::MessageStream::endmsg; +} + +//--------------------------------------------------------------------------- + +RelationalQueryMgr::~RelationalQueryMgr() +{ + log() << coral::Debug + << "Delete the RelationalQueryMgr" << coral::MessageStream::endmsg; +} + +//--------------------------------------------------------------------------- + +const RelationalTableRow RelationalQueryMgr::fetchRowFromTables +( const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::string& description, + bool forUpdate ) const +{ + UInt32 nExp = 1; // Delegate check as well as fetch + std::vector<RelationalTableRow> rows = fetchRowsFromTables + ( tables, columns, whereClause, whereData, description, nExp, forUpdate ); + if ( rows.size() == 0 ) // PANIC! This should never happen! + { + std::stringstream tableList; + TableNamesWithAliases::const_iterator table; + for ( table = tables.begin(); + table != tables.end(); + table++ ) { + if ( tableList.str() != "" ) tableList << ", "; + tableList << table->first; + } + throw NoRowsFound( "PANIC! No rows selected from " + tableList.str(), + "RelationalQueryMgr" ); + } + return rows[0]; +} + +//--------------------------------------------------------------------------- + +const std::vector<RelationalTableRow> RelationalQueryMgr::fetchRowsFromTables +( const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::string& description, + UInt32 nExp, + bool forUpdate ) const +{ + std::vector<std::string> orderBy; // Empty orderBy clause + return fetchOrderedRowsFromTables + ( tables, columns, + whereClause, whereData, orderBy, description, nExp, forUpdate ); +} + +//--------------------------------------------------------------------------- + +const std::string +RelationalQueryMgr::serverTimeClause( const std::string& technology ) +{ + std::string clause; + if ( technology == "MySQL" ) { + // TEMPORARY! Store MySQL now() __ AS IS __ ASSUMING IT IS GMT! + // MySQL does not handle timezones until 4.1.3 + clause = "DATE_FORMAT(now(),'%Y-%m-%d_%H:%i:%s.000000000 GMT')"; + } + else if ( technology == "Oracle" || technology == "frontier" ) { + // Store Oracle SYSTIMESTAMP converted to GMT + clause = "TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT',"; + clause += "'yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'"; + } + else if ( technology == "SQLite" ) { + // Use GMT time from C++ client with SQLite (there is no server) + // TEMPORARY! Use seal::Time (CURRENT_TIMESTAMP only in SQLite 3.1.0) + // TODO: Use SQLite's CURRENT_TIMESTAMP. + clause = "'"; + clause += timeToString( cool::Time() ); + clause += "'"; + } + else { + throw RelationalException + ( std::string( "Unknown technology " ) + technology, "RalQueryMgr" ); + } + return clause; +} + +//--------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalQueryMgr.h b/RelationalCool/src/RelationalQueryMgr.h new file mode 100644 index 000000000..da2b3f126 --- /dev/null +++ b/RelationalCool/src/RelationalQueryMgr.h @@ -0,0 +1,314 @@ +// $Id: RelationalQueryMgr.h,v 1.64 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALQUERYMGR_H +#define RELATIONALCOOL_RELATIONALQUERYMGR_H + +// Include files +#include <memory> +#include <string> +#include <boost/shared_ptr.hpp> +#include "CoolKernel/types.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoralBase/AttributeList.h" +#include "CoralBase/AttributeSpecification.h" +#include "CoralBase/MessageStream.h" + +namespace cool { + + // Forward declarations + class IRelationalBulkOperation; + class IRelationalCursor; + class IRelationalQueryDefinition; + class RelationalSequenceMgr; + class RelationalTableRow; + + // TEMPORARY... + inline const std::type_info& + typeIdToCoralType( const StorageType::TypeId type_id ) + { + return StorageType::storageType( type_id ).cppType(); + } + + /** @class RelationalQueryMgr RelationalQueryMgr.h + * ----------------------------------------------------------------------- + * RelationalQueryMgr: abstract base class for a manager + * of relational queries (SELECT statements). + * + * Only three methods are pure virtual and implemented in a derived class: + * a check for the existence of a table in the schema, + * a generic query for many ordered rows from many aliased tables, + * and a generic COUNT(*) query from many aliased tables. + * + * Some simpler queries are implemented within this class in terms + * of the two more generic pure abstract methods described above. + * + * Transactions are NOT handled by this class. + * ----------------------------------------------------------------------- + * RelationalUpdateMgr: abstract base class for a manager + * of relational DML operations (INSERT/UPDATE/DELETE statements). + * + * Transactions are NOT handled by this class. + * + * TEMPORARY? These functionalities are presently in RelationalQueryMgr. + * ----------------------------------------------------------------------- + * RelationalSequenceMgr: return a reference to the abstract interface + * for a manager of COOL relational 'sequences'. + * + * Transactions are NOT handled by this class. + * + * TEMPORARY? These functionalities are presently in RelationalQueryMgr. + * ----------------------------------------------------------------------- + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2005-10-11 + */ + + class RelationalQueryMgr + { + + public: + + typedef std::pair< std::string, std::string > TableNameWithAlias; + typedef std::vector< TableNameWithAlias > TableNamesWithAliases; + + /// Build a list of table names and aliases + /// from a single table name and alias. + inline static const TableNamesWithAliases tableList + ( const TableNameWithAlias& table ) + { + TableNamesWithAliases tables; + tables.push_back( table ); + return tables; + } + + /// Build a list of table names and aliases + /// from a single table name (with or without alias). + inline static const TableNamesWithAliases tableList + ( const std::string& tableName, + const std::string& tableAlias = "" ) + { + TableNameWithAlias table( tableName, tableAlias ); + return tableList( table ); + } + + /// Build a list of table names and aliases + /// from a list of table names without alias. + inline static const TableNamesWithAliases tableList + ( const std::vector<std::string>& tableNames ) + { + TableNamesWithAliases tables; + std::vector<std::string>::const_iterator tableName; + for ( tableName = tableNames.begin(); + tableName != tableNames.end(); + tableName++ ) { + TableNameWithAlias table( *tableName, "" ); + tables.push_back( table ); + } + return tables; + } + + public: + + typedef std::vector< std::string > SelectList; + typedef RecordSpecification RSetSpec; + typedef std::pair< SelectList, RSetSpec > SelectListWithRSetSpec; + + /// Build a select list and result set specification + /// from a result set specification and an optional common prefix + /// (i.e. from a coral::AttributeListSpecification and an optional string). + /// The input result set specification is used unchanged. + /// The names of the selected fields are built by prepending the prefix. + inline static const SelectListWithRSetSpec columnList + ( const IRecordSpecification& recSpec, + const std::string& prefix = "" ) + { + SelectList selectList; + RSetSpec rsetSpec; + for ( unsigned int i=0; i<recSpec.size(); i++ ) { + const IFieldSpecification& fldSpec = recSpec[i]; + selectList.push_back( prefix + fldSpec.name() ); + rsetSpec.extend( fldSpec ); + } + SelectListWithRSetSpec columns( selectList, rsetSpec ); + return columns; + } + + public: + + /// Destructor + virtual ~RelationalQueryMgr(); + + /// Clone this query manager. + /// PURE VIRTUAL method implemented in subclasses. + virtual RelationalQueryMgr* clone() const = 0; + + /// Checks if a table exists in the schema. + /// PURE VIRTUAL method implemented in subclasses. + virtual bool existsTable( const std::string& tableName ) const = 0; + + /// Fetch a single row from one or more tables. + /// Throws NoRowsFound if no rows are found. + /// Throws TooManyRowsFound if more than one rows are found. + const RelationalTableRow fetchRowFromTables + ( const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::string& description = "", + bool forUpdate = false ) const; + + /// Fetch a set of rows from one or more tables as a vector. + /// If nExp>0, throws TooManyRowsFound if more than nExp rows are found. + /// If nExp>0, throws an exception if fewer than nExp rows are found. + const std::vector<RelationalTableRow> fetchRowsFromTables + ( const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::string& description = "", + UInt32 nExp = 0, + bool forUpdate = false ) const; + + /// Fetch an ordered set of rows from one or more tables as a vector. + /// If nExp>0, throws TooManyRowsFound if more than nExp rows are found. + /// If nExp>0, throws an exception if fewer than nExp rows are found. + /// PURE VIRTUAL method implemented in subclasses. + virtual const std::vector<RelationalTableRow> fetchOrderedRowsFromTables + ( const TableNamesWithAliases& tables, + const SelectListWithRSetSpec& columns, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::vector<std::string>& orderBy, + const std::string& description = "", + UInt32 nExp = 0, + bool forUpdate = false ) const = 0; + + /// Fetch a "select COUNT(*)" row count from one or more tables. + /// PURE VIRTUAL method implemented in subclasses. + virtual UInt32 countRowsFromTables + ( const TableNamesWithAliases& tables, + const std::string& whereClause, + const coral::AttributeList& whereData, + const std::string& description = "" ) const = 0; + + /// -- NEW -- start + /// Prepare and execute a CORAL query + /// (and start/stop the relevant timing report). + /// The caller becomes the owenr of the returned cursor. + /// PURE VIRTUAL method implemented in subclasses. + virtual IRelationalCursor* prepareAndExecuteQuery + ( const IRelationalQueryDefinition& coolDef, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) const = 0; + /// Fetch an ordered set of rows from one or more tables as a vector. + /// If nExp>0, throws TooManyRowsFound if more than nExp rows are found. + /// If nExp>0, throws an exception if fewer than nExp rows are found. + /// PURE VIRTUAL method implemented in subclasses. + virtual const std::vector<RelationalTableRow> fetchOrderedRows + ( const IRelationalQueryDefinition& coolDef, + const std::string& description = "", + UInt32 nExp = 0, + bool forUpdate = false ) const = 0; + /// Fetch a "select COUNT(*)" row count from one or more tables. + /// PURE VIRTUAL method implemented in subclasses. + virtual UInt32 countRows + ( const IRelationalQueryDefinition& coolDef, + const std::string& description = "" ) const = 0; + /// -- NEW -- end + + /// Returns a new IRelationalBulkOperation object for performing a bulk + /// insert operation specifying the input data buffer and the number of + /// rows that should be cached on the client. + /// PURE VIRTUAL method implemented in subclasses. + virtual boost::shared_ptr<IRelationalBulkOperation> + bulkInsertTableRows( const std::string& tableName, + const coral::AttributeList& dataBuffer, + int rowCacheSize ) = 0; + + /// Insert one row into one table. + /// PURE VIRTUAL method implemented in subclasses. + virtual void insertTableRow + ( const std::string& tableName, + const coral::AttributeList& data ) const = 0; + + /// Returns a new IRelationalBulkOperation object for performing a bulk + /// update operation specifying the input data buffer and the number of + /// rows that should be cached on the client. + /// PURE VIRTUAL method implemented in subclasses. + virtual boost::shared_ptr<IRelationalBulkOperation> + bulkUpdateTableRows( const std::string& tableName, + const std::string& setClause, + const std::string& whereClause, + const coral::AttributeList& dataBuffer, + int rowCacheSize ) = 0; + + /// Update rows in one table. + /// If nExp>0, throws an exception if more than nExp rows are updated. + /// If nExp>0, throws an exception if fewer than nExp rows are updated. + /// PURE VIRTUAL method implemented in subclasses. + virtual UInt32 updateTableRows + ( const std::string& tableName, + const std::string& setClause, + const std::string& whereClause, + const coral::AttributeList& updateData, + UInt32 nExp = 0 ) const = 0; + + /// Delete rows from one table. + /// Throws an exception if #rows deleted is different from the expectation + /// (taken from nExp if > 0; queried internally if nExp = 0). + /// PURE VIRTUAL method implemented in subclasses. + virtual UInt32 deleteTableRows + ( const std::string& tableName, + const std::string& whereClause, + const coral::AttributeList& whereData, + UInt32 nExp = 0 ) const = 0; + + /// Get a RelationalSequenceMgr. + /// PURE VIRTUAL method implemented in subclasses. + virtual RelationalSequenceMgr& sequenceMgr() const = 0; + + /// Build the appropriate backend-specific SQL expression + /// to compute the server-side time in the format used by COOL. + /// PURE VIRTUAL method implemented in subclasses. + virtual const std::string serverTimeClause() const = 0; + + /// Build the appropriate backend-specific SQL expression + /// to compute the server-side time in the format used by COOL. + static const std::string serverTimeClause( const std::string& technology ); + + /// Return the server technology for the current connection. + /// Supported technologies: "Oracle ", "MySQL", "SQLite", "frontier". + /// PURE VIRTUAL method implemented in subclasses. + virtual const std::string databaseTechnology() const = 0; + + /// Return the schema name for the current connection. + /// PURE VIRTUAL method implemented in subclasses. + virtual const std::string schemaName() const = 0; + + protected: + + /// Constructor is protected + RelationalQueryMgr(); + + /// Get a CORAL MessageStream + coral::MessageStream& log() const + { + return *m_log; + } + + private: + + /// Copy constructor is private + RelationalQueryMgr( const RelationalQueryMgr& rhs ); + + /// Assignment operator is private + RelationalQueryMgr& operator=( const RelationalQueryMgr& rhs ); + + private: + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALQUERYMGR_H + diff --git a/RelationalCool/src/RelationalSchemaMgr.cpp b/RelationalCool/src/RelationalSchemaMgr.cpp new file mode 100644 index 000000000..f010cd654 --- /dev/null +++ b/RelationalCool/src/RelationalSchemaMgr.cpp @@ -0,0 +1,63 @@ +// $Id: RelationalSchemaMgr.cpp,v 1.9 2008-11-04 11:52:11 avalassi Exp $ + +// Local include files +#include "RelationalDatabase.h" +#include "RelationalSchemaMgr.h" +#include "uppercaseString.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalSchemaMgr::RelationalSchemaMgr( const RelationalDatabase& aDb ) + : m_db( aDb ) + , m_log( new coral::MessageStream( "RelationalSchemaMgr" ) ) +{ + log() << coral::Debug << "Instantiate a RelationalSchemaMgr" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalSchemaMgr::~RelationalSchemaMgr() +{ + log() << coral::Debug << "Delete the RelationalSchemaMgr" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + + +coral::MessageStream& RelationalSchemaMgr::log() const +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +RelationalQueryMgr& RelationalSchemaMgr::queryMgr() const +{ + return db().queryMgr(); +} + +//----------------------------------------------------------------------------- + +bool +RelationalSchemaMgr::isValidColumnName( const std::string& name ) const +{ + static std::string allowedChar = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890"; + const std::string ucName = uppercaseString( name ); + if ( name.size() < 1 || + name.size() > 30 || + ucName.find_first_not_of( allowedChar ) != ucName.npos || + ucName.find_first_not_of( "_1234567890" ) != 0 ) + return false; + else + return true; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/RelationalSchemaMgr.h b/RelationalCool/src/RelationalSchemaMgr.h new file mode 100644 index 000000000..f9964ff56 --- /dev/null +++ b/RelationalCool/src/RelationalSchemaMgr.h @@ -0,0 +1,208 @@ +// $Id: RelationalSchemaMgr.h,v 1.34 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALSCHEMAMGR_H +#define RELATIONALCOOL_RELATIONALSCHEMAMGR_H + +// Include files +#include <memory> +#include "CoolKernel/FolderVersioning.h" +#include "CoralBase/AttributeList.h" // SAS 19.06.2006 needed only on Mac/gcc4? +#include "CoralBase/MessageStream.h" +#include "RelationalAccess/TableDescription.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + class RelationalDatabase; + class RelationalQueryMgr; + + /** @class RelationalSchemaMgr RelationalSchemaMgr.h + * + * Abstract base class for the manager + * of the COOL relational database schema. + * + * @author Andrea Valassi and Marco Clemencic + * @date 2006-03-15 + */ + + class RelationalSchemaMgr { + + public: + + /// Destructor + virtual ~RelationalSchemaMgr(); + + /// Drop a table (return false if the table does not exist) + /// PURE VIRTUAL method implemented in subclasses. + virtual bool dropTable( const std::string& tableName ) const = 0; + + /// Creates the main table + /// PURE VIRTUAL method implemented in subclasses. + virtual void createMainTable( const std::string& tableName ) const = 0; + + /// Fill the main table + /// PURE VIRTUAL method implemented in subclasses. + virtual void fillMainTable( const std::string& tableName, + const coral::AttributeList& dbAttr ) const = 0; + + // *** START *** 3.0.0 schema extensions (task #4307) + /// Creates the iovTables table + /// PURE VIRTUAL method implemented in subclasses. + virtual void createIovTablesTable + ( const std::string& iovTablesTableName ) const = 0; + + /// Creates the channelTables table + /// PURE VIRTUAL method implemented in subclasses. + virtual void createChannelTablesTable + ( const std::string& channelTablesTableName ) const = 0; + // **** END **** 3.0.0 schema extensions (task #4307) + + /// Creates the node table + /// TEMPORARY - pass the table prefix to create the root fs tag sequence + /// PURE VIRTUAL method implemented in subclasses. + virtual + void createNodeTable( const std::string& nodeTableName, + const std::string& defaultTablePrefix ) const = 0; + + /// Creates the global tag table + /// PURE VIRTUAL method implemented in subclasses. + virtual + void createGlobalTagTable( const std::string& globalTagTableName, + const std::string& nodeTableName ) const = 0; + + // *** START *** 3.0.0 schema extensions (task #4396) + /// Creates the global head tag table + /// PURE VIRTUAL method implemented in subclasses. + virtual void createGlobalHeadTagTable + ( const std::string& globalHeadTagTableName, + const std::string& globalTagTableName ) const = 0; + + /// Creates the global user tag table + /// PURE VIRTUAL method implemented in subclasses. + virtual void createGlobalUserTagTable + ( const std::string& globalUserTagTableName, + const std::string& globalTagTableName ) const = 0; + // **** END **** 3.0.0 schema extensions (task #4396) + + /// Creates the tag2tag HVS table + /// PURE VIRTUAL method implemented in subclasses. + virtual + void createTag2TagTable( const std::string& tag2tagTableName, + const std::string& globalTagTableName, + const std::string& nodeTableName ) const = 0; + + /// Creates the tag2tag HVS table FK references to the tag table + /// *** This is needed by the coolReplicateDB utility *** + /// PURE VIRTUAL method implemented in subclasses. + virtual + void createTag2TagFKs( const std::string& tag2tagTableName, + const std::string& globalTagTableName ) const = 0; + + /// Creates the tag2tag HVS table FK references to the tag table + /// *** This is needed by the coolReplicateDB utility *** + /// PURE VIRTUAL method implemented in subclasses. + virtual + bool dropTag2TagFKs( const std::string& tag2tagTableName, + bool verbose = true ) const = 0; + + /// Creates a shared sequence table + /// PURE VIRTUAL method implemented in subclasses. + virtual + void createSharedSequence( const std::string& sharedSequenceName, + const std::string& nodeTableName ) const = 0; + + /// Creates the tag sequence for a node + /// PURE VIRTUAL method implemented in subclasses. + virtual void createTagSequence( const std::string& seqName ) const = 0; + + /// Creates the tag table for a leaf node + /// PURE VIRTUAL method implemented in subclasses. + virtual void createTagTable( const std::string& tableName ) const = 0; + + /// Creates the channel table for a leaf node + /// PURE VIRTUAL method implemented in subclasses. + virtual void createChannelTable( const std::string& tableName ) const = 0; + + /// Creates the object2tag (iov2tag) table for a leaf node + /// PURE VIRTUAL method implemented in subclasses. + virtual void createObject2TagTable + ( const std::string& object2tagTableName, + const std::string& objectTableName, + const std::string& tagTableName ) const = 0; + + /// Creates the object (iov) table for a leaf node + /// PURE VIRTUAL method implemented in subclasses. + virtual void createObjectTable + ( const std::string& objectTableName, + const std::string& channelTableName, + const IRecordSpecification& payloadSpec, + FolderVersioning::Mode versioningMode ) const = 0; + + /// Creates the FK references from the object table to the channel table + /// *** This is needed by the coolReplicateDB utility *** + /// PURE VIRTUAL method implemented in subclasses. + virtual void createObjectChannelFK + ( const std::string& objectTableName, + const std::string& channelTableName ) const = 0; + + /// Drops the FK reference from the object table to the channel table + /// *** This is needed by the coolReplicateDB utility *** + /// PURE VIRTUAL method implemented in subclasses. + virtual void dropObjectChannelFK + ( const std::string& objectTableName ) const = 0; + + /// Rename a column of the given table + /// PURE VIRTUAL method implemented in subclasses. + virtual void renameColumnInTable + ( const std::string& tableName, + const std::string& oldColumnName, + const std::string& newColumnName ) const = 0; + + /// Add columns to the given table + /// PURE VIRTUAL method implemented in subclasses. + virtual void addColumnsToTable + ( const std::string& tableName, + const IRecord& columnSpecAndValues ) const = 0; + + /// Is this a valid name for a column of a relational table? + virtual bool isValidColumnName( const std::string& name ) const; + + protected: + + /// Constructor from a RelationalDatabase reference + RelationalSchemaMgr( const RelationalDatabase& db ); + + /// Get the RelationalDatabase reference + const RelationalDatabase& db() const { return m_db; } + + /// Get a CORAL MessageStream + coral::MessageStream& log() const; + + /// Get a relational query manager + RelationalQueryMgr& queryMgr() const; + + private: + + /// Standard constructor is private + RelationalSchemaMgr(); + + /// Copy constructor is private + RelationalSchemaMgr( const RelationalSchemaMgr& rhs ); + + /// Assignment operator is private + RelationalSchemaMgr& operator=( const RelationalSchemaMgr& rhs ); + + protected: + + /// Reference to the RelationalDatabase + const RelationalDatabase& m_db; + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALSCHEMAMGR_H + diff --git a/RelationalCool/src/RelationalSequence.cpp b/RelationalCool/src/RelationalSequence.cpp new file mode 100644 index 000000000..45985dabb --- /dev/null +++ b/RelationalCool/src/RelationalSequence.cpp @@ -0,0 +1,128 @@ +// $Id: RelationalSequence.cpp,v 1.10 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoralBase/Attribute.h" +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalDatabase.h" +#include "RelationalException.h" +#include "RelationalQueryMgr.h" +#include "RelationalSequence.h" +#include "RelationalSequenceMgr.h" +#include "RelationalSequenceTable.h" +#include "RelationalTableRow.h" +#include "uppercaseString.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalSequence::RelationalSequence +( const std::string& name, + const RelationalSequenceMgr& sequenceMgr ) + : m_name( name ) + , m_sequenceMgr( sequenceMgr ) +{ + //std::cout << "RelationalSequence constructor" << std::endl; +} + +//----------------------------------------------------------------------------- + +RelationalSequence::~RelationalSequence() +{ + //std::cout << "RelationalSequence destructor" << std::endl; +} + +//----------------------------------------------------------------------------- + +const std::pair<unsigned int, std::string> +RelationalSequence::currValDate( unsigned int nSteps ) +{ + bool setNextValue = false; + if ( nSteps>0 ) setNextValue = true; + + // Select the row with the current sequence value and date FOR UPDATE + RecordSpecification spec; + spec.extend( RelationalSequenceTable::columnNames::currentValue, + RelationalSequenceTable::columnTypeIds::currentValue ); + spec.extend( RelationalSequenceTable::columnNames::lastModDate, + RelationalSequenceTable::columnTypeIds::lastModDate ); + + std::string whereClause = ""; // no selection + coral::AttributeList whereData; + std::string desc = ""; + bool forUpdate = true; + RelationalTableRow row = sequenceMgr().queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( name() ), + RelationalQueryMgr::columnList( spec ), + whereClause, whereData, desc, forUpdate ); + const coral::AttributeList& attr = row.data(); + + // Test whether the sequence is initialised + bool isNull = + attr[RelationalSequenceTable::columnNames::currentValue].isNull(); + + // If setNextValue==false, return the current value + // Throw an exception if the sequence is not yet initialised + if ( !setNextValue ) { + if ( isNull ) { + throw RelationalException + ( "Sequence is not initialized yet", "RelationalSequence" ); + } else { + unsigned int currValue = + attr[RelationalSequenceTable::columnNames::currentValue] + .data<RelationalSequenceTable::columnTypes::currentValue>(); + std::string lastModDate = + attr[RelationalSequenceTable::columnNames::lastModDate] + .data<RelationalSequenceTable::columnTypes::lastModDate>(); + return std::pair<unsigned int, std::string>( currValue, lastModDate ); + } + } + + // If setNextValue==true, increment the current value and return it + // Initialise the sequence if the sequence is not yet initialised + else { + unsigned int nextValue; + if ( isNull ) { + nextValue = s_firstValue; + nextValue += s_increment * (nSteps - 1); + } else { + nextValue = + attr[RelationalSequenceTable::columnNames::currentValue] + .data<RelationalSequenceTable::columnTypes::currentValue>(); + nextValue += s_increment * nSteps; + } + coral::AttributeList updateData; + updateData.extend + ( "newvalue", + typeIdToCoralType(RelationalSequenceTable::columnTypeIds::currentValue) ); + updateData["newvalue"] + .data<RelationalSequenceTable::columnTypes::currentValue>() = nextValue; + std::string setClause = RelationalSequenceTable::columnNames::currentValue; + setClause += "=:newvalue"; + setClause += ", "; + setClause += RelationalSequenceTable::columnNames::lastModDate; + setClause += "="; + setClause += sequenceMgr().queryMgr().serverTimeClause(); + std::string whereClause = ""; // no selection (update all rows) + + // TEMPORARY? No need for checkAttributeListCompliance size checks here + // at update time (the sequence name is unchanged and was checked at + // insertion time, the sequence value has no maximum size to check, + // the last modification date is a short string by construction) + + if ( ! sequenceMgr().queryMgr().updateTableRows + ( name(), setClause, whereClause, updateData ) ) + throw RowNotUpdated + ( "Could not update the sequence table", "RelationalSequence" ); + std::string lastModDate = "UNKNOWN"; + return std::pair<unsigned int, std::string>( nextValue, lastModDate ); + } + +} + +//----------------------------------------------------------------------------- + + diff --git a/RelationalCool/src/RelationalSequence.h b/RelationalCool/src/RelationalSequence.h new file mode 100644 index 000000000..a8349d806 --- /dev/null +++ b/RelationalCool/src/RelationalSequence.h @@ -0,0 +1,112 @@ +// $Id: RelationalSequence.h,v 1.11 2008-11-04 11:25:57 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALSEQUENCE_H +#define RELATIONALCOOL_RELATIONALSEQUENCE_H + +// Include files +#include <string> + +// Local include files +#include "RelationalException.h" + +namespace cool { + + /** @class RelationalSequence RelationalSequence.h + * + * Generic relational implementation of a COOL 'sequence'. + * + * This is actually a table row providing an increasing integer number + * in a sequence with no holes, as well as its last modification date. + * + * Presently each 'sequence' is stored as a separate relational table. + * + * WARNING: this is a private class of the implementation library. + * An instance of this class can only be used as long as the + * RelationalSequenceMgr instance that created it still exists. + * + * @author Andrea Valassi and Marco Clemencic + * @date 2006-03-10 + */ + + class RelationalSequence + { + + friend class RelationalSequenceMgr; + + public: + + /// Destructor + virtual ~RelationalSequence(); + + /// Returns the name of the sequence + const std::string& name() const + { + return m_name; + } + + /// Returns the current value of the sequence + /// Throw an exception if the sequence is not yet initialised + unsigned int currVal() + { + return currValDate(0).first; + } + + /// Increments the sequence and return the new current value + /// Initialise the sequence if the sequence is not yet initialised + /// The nSteps>0 option increments the value by n steps for bulk insertions + unsigned int nextVal( unsigned int nSteps = 1 ) + { + if ( nSteps == 0 ) + throw RelationalException + ( "Invalid argument=0 to nextVal()", "RelationalSequence" ); + return currValDate(nSteps).first; + } + + /// Returns the date corresponding to the current value of the sequence + /// Throw an exception if the sequence is not yet initialised + const std::string currDate() + { + return currValDate(0).second; + } + + protected: + + /// Constructor from a sequence name and a RelationalSequenceMgr + RelationalSequence( const std::string& name, + const RelationalSequenceMgr& sequenceMgr ); + + /// Get the RelationalSequenceMgr reference + const RelationalSequenceMgr& sequenceMgr() const { return m_sequenceMgr; } + + /// Returns the current (nSteps=0) or the next (nSteps>0) value and date + const std::pair<unsigned int, std::string> currValDate( unsigned int nSteps ); + + private: + + /// Standard constructor is private + RelationalSequence(); + + /// Copy constructor is private + RelationalSequence( const RelationalSequence& rhs ); + + /// Assignment operator is private + RelationalSequence& operator=( const RelationalSequence& rhs ); + + private: + + /// The name of the sequence (i.e. the name of the sequence table) + std::string m_name; + + /// Reference to the parent RelationalSequenceMgr + const RelationalSequenceMgr& m_sequenceMgr; + + /// The first value of the sequence + static const unsigned int s_firstValue = 0; + + /// The increment value of the sequence + static const unsigned int s_increment = 1; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALSEQUENCE_H diff --git a/RelationalCool/src/RelationalSequenceMgr.cpp b/RelationalCool/src/RelationalSequenceMgr.cpp new file mode 100644 index 000000000..699edc178 --- /dev/null +++ b/RelationalCool/src/RelationalSequenceMgr.cpp @@ -0,0 +1,40 @@ +// $Id: RelationalSequenceMgr.cpp,v 1.6 2008-03-20 18:30:19 marcocle Exp $ + +// Local include files +#include "RelationalQueryMgr.h" +#include "RelationalSequence.h" +#include "RelationalSequenceMgr.h" + +// Namespace +using namespace cool; + +//--------------------------------------------------------------------------- + +RelationalSequenceMgr::RelationalSequenceMgr +( const RelationalQueryMgr& queryMgr ) + : m_queryMgr( queryMgr ) + , m_log( new coral::MessageStream( "RelationalSequenceMgr" )) +{ + log() << coral::Debug + << "Instantiate a RelationalSequenceMgr" << coral::MessageStream::endmsg; +} + +//--------------------------------------------------------------------------- + +RelationalSequenceMgr::~RelationalSequenceMgr() +{ + log() << coral::Debug + << "Delete the RelationalSequenceMgr" << coral::MessageStream::endmsg; +} + +//--------------------------------------------------------------------------- + +boost::shared_ptr<RelationalSequence> +RelationalSequenceMgr::instantiateSequence( const std::string& name ) +{ + boost::shared_ptr<RelationalSequence> + ptr( new RelationalSequence( name, *this ) ); + return ptr; +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalSequenceMgr.h b/RelationalCool/src/RelationalSequenceMgr.h new file mode 100644 index 000000000..5d1b0951d --- /dev/null +++ b/RelationalCool/src/RelationalSequenceMgr.h @@ -0,0 +1,92 @@ +// $Id: RelationalSequenceMgr.h,v 1.12 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALSEQUENCEMGR_H +#define RELATIONALCOOL_RELATIONALSEQUENCEMGR_H + +// Include files +#include <memory> +#include <string> +#include <boost/shared_ptr.hpp> +#include "CoralBase/MessageStream.h" + +namespace cool { + + // Forward declarations + class RelationalQueryMgr; + class RelationalSequence; + + /** @class RelationalSequenceMgr RelationalSequenceMgr.h + * + * Abstract base class for a manager of COOL relational 'sequences'. + * + * Transactions are NOT handled by this class. + * + * @author Andrea Valassi + * @date 2006-03-10 + */ + + class RelationalSequenceMgr + { + + public: + + /// Destructor + virtual ~RelationalSequenceMgr(); + + /// Create a new sequence (ownership of the C++ instance is shared). + /// PURE VIRTUAL method implemented in subclasses. + virtual boost::shared_ptr<RelationalSequence> + createSequence( const std::string& name ) = 0; + + /// Does this sequence exist? + /// PURE VIRTUAL method implemented in subclasses. + virtual bool existsSequence( const std::string& name ) = 0; + + /// Get an existing sequence (ownership of the C++ instance is shared). + /// PURE VIRTUAL method implemented in subclasses. + virtual boost::shared_ptr<RelationalSequence> + getSequence( const std::string& name ) = 0; + + /// Drop an existing sequence + /// PURE VIRTUAL method implemented in subclasses. + virtual void dropSequence( const std::string& name ) = 0; + + /// Instantiate a sequence (ownership of the C++ instance is shared). + boost::shared_ptr<RelationalSequence> + instantiateSequence( const std::string& name ); + + /// Get the RelationalQueryMgr reference + const RelationalQueryMgr& queryMgr() const { return m_queryMgr; } + + protected: + + /// Constructor from a RelationalQueryMgr reference + RelationalSequenceMgr( const RelationalQueryMgr& queryMgr ); + + /// Get a CORAL MessageStream + coral::MessageStream& log() const { return *m_log; } + + private: + + /// Standard constructor is private + RelationalSequenceMgr(); + + /// Copy constructor is private + RelationalSequenceMgr( const RelationalSequenceMgr& rhs ); + + /// Assignment operator is private + RelationalSequenceMgr& operator=( const RelationalSequenceMgr& rhs ); + + protected: + + /// Reference to the parent RelationalQueryMgr + const RelationalQueryMgr& m_queryMgr; + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALSEQUENCEMGR_H + diff --git a/RelationalCool/src/RelationalSequenceTable.cpp b/RelationalCool/src/RelationalSequenceTable.cpp new file mode 100644 index 000000000..ac9f9d8e5 --- /dev/null +++ b/RelationalCool/src/RelationalSequenceTable.cpp @@ -0,0 +1,36 @@ +// $Id: RelationalSequenceTable.cpp,v 1.7 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalSequenceTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalSequenceTable::tableSpecification +( bool seqNameOnly ) +{ + static RecordSpecification spec_all; + static RecordSpecification spec_name_only; + RecordSpecification& spec = seqNameOnly ? spec_name_only : spec_all; + + if ( spec.size() == 0 ) { + // Include the first column (the sequence name) + spec.extend( RelationalSequenceTable::columnNames::sequenceName, + RelationalSequenceTable::columnTypeIds::sequenceName ); + // Include also all columns after the first column (the sequence name) + if ( ! seqNameOnly ) { + spec.extend( RelationalSequenceTable::columnNames::currentValue, + RelationalSequenceTable::columnTypeIds::currentValue ); + spec.extend( RelationalSequenceTable::columnNames::lastModDate, + RelationalSequenceTable::columnTypeIds::lastModDate ); + } + } + + return spec; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalSequenceTable.h b/RelationalCool/src/RelationalSequenceTable.h new file mode 100644 index 000000000..10d567a62 --- /dev/null +++ b/RelationalCool/src/RelationalSequenceTable.h @@ -0,0 +1,49 @@ +#ifndef RELATIONALCOOL_RELATIONALSEQUENCETABLE_H +#define RELATIONALCOOL_RELATIONALSEQUENCETABLE_H + +// Include files +#include "CoolKernel/StorageType.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalSequenceTable RelationalSequenceTable.h + * + * Relational schema of the tables implementing "sequence" functionalities. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2005-04-15 + */ + + namespace RelationalSequenceTable { + + namespace columnNames { + static const std::string sequenceName = "SEQUENCE_NAME"; + static const std::string currentValue = "CURRENT_VALUE"; + static const std::string lastModDate = "LASTMOD_DATE"; + } + + namespace columnTypeIds { + static const StorageType::TypeId sequenceName = StorageType::String255; + static const StorageType::TypeId currentValue = StorageType::UInt32; + static const StorageType::TypeId lastModDate = StorageType::String255; + } + + namespace columnTypes { + typedef String255 sequenceName; + typedef UInt32 currentValue; + typedef String255 lastModDate; + } + + /// Get the RecordSpecification of the sequence table. + /// If the flag is true, include only the first column (the sequence name). + const IRecordSpecification& + tableSpecification( bool seqNameOnly = false ); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALSEQUENCETABLE_H diff --git a/RelationalCool/src/RelationalSharedSequenceTable.cpp b/RelationalCool/src/RelationalSharedSequenceTable.cpp new file mode 100644 index 000000000..c070feced --- /dev/null +++ b/RelationalCool/src/RelationalSharedSequenceTable.cpp @@ -0,0 +1,43 @@ +// $Id: RelationalSharedSequenceTable.cpp,v 1.2 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalSharedSequenceTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalSharedSequenceTable::tableSpecification +( bool nodeIdOnly ) +{ + static RecordSpecification spec_all; + static RecordSpecification spec_id_only; + RecordSpecification& spec = nodeIdOnly ? spec_id_only : spec_all; + + if ( spec.size() == 0 ) + { + + // Include the first column (the nodeId) + spec.extend + ( RelationalSharedSequenceTable::columnNames::nodeId, + RelationalSharedSequenceTable::columnTypeIds::nodeId ); + + // Include also all columns after the first column (the nodeId) + if ( ! nodeIdOnly ) + { + spec.extend + ( RelationalSharedSequenceTable::columnNames::currentValue, + RelationalSharedSequenceTable::columnTypeIds::currentValue ); + spec.extend + ( RelationalSharedSequenceTable::columnNames::lastModDate, + RelationalSharedSequenceTable::columnTypeIds::lastModDate ); + } + + } + return spec; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalSharedSequenceTable.h b/RelationalCool/src/RelationalSharedSequenceTable.h new file mode 100644 index 000000000..40718c187 --- /dev/null +++ b/RelationalCool/src/RelationalSharedSequenceTable.h @@ -0,0 +1,60 @@ +#ifndef RELATIONALCOOL_RELATIONALSHAREDSEQUENCETABLE_H +#define RELATIONALCOOL_RELATIONALSHAREDSEQUENCETABLE_H + +// Include files +#include "CoolKernel/StorageType.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalSharedSequenceTable RelationalSharedSequenceTable.h + * + * Relational schema of the new "sequence" tables for tag + * (tag and IOV) numbering in individual folder sets (folders). + * + * These new sequence tables are designed to be shared by + * several nodes, hence they have a nodeId column as primary key. + * Two such tables are foreseen, one for tags and one for IOVS. + * Note that IOV numbering in each individual folders uses PKs + * that are globally unique across all channels in the folder. + * + * @author Andrea Valassi + * @date 2007-01-31 + */ + + namespace RelationalSharedSequenceTable + { + + namespace columnNames + { + static const std::string nodeId = "NODE_ID"; + static const std::string currentValue = "CURRENT_VALUE"; + static const std::string lastModDate = "LASTMOD_DATE"; + } + + namespace columnTypeIds + { + static const StorageType::TypeId nodeId = StorageType::UInt32; + static const StorageType::TypeId currentValue = StorageType::UInt32; + static const StorageType::TypeId lastModDate = StorageType::String255; + } + + namespace columnTypes + { + typedef UInt32 nodeId; + typedef UInt32 currentValue; + typedef String255 lastModDate; + } + + /// Get the RecordSpecification of the sequence table. + /// If the flag is true, include only the first column (the nodeId). + const IRecordSpecification& + tableSpecification( bool nodeIdOnly = false ); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALSHAREDSEQUENCETABLE_H diff --git a/RelationalCool/src/RelationalTableRow.cpp b/RelationalCool/src/RelationalTableRow.cpp new file mode 100644 index 000000000..9fa5d0242 --- /dev/null +++ b/RelationalCool/src/RelationalTableRow.cpp @@ -0,0 +1,46 @@ +// $Id: RelationalTableRow.cpp,v 1.5 2006-03-14 16:58:12 avalassi Exp $ + +// Local include files +#include "RelationalTableRow.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalTableRow::~RelationalTableRow() +{ +} + +//----------------------------------------------------------------------------- + +RelationalTableRow::RelationalTableRow() + : RelationalTableRowBase() +{ +} + +//----------------------------------------------------------------------------- + +RelationalTableRow::RelationalTableRow +( const RelationalTableRow& aRow ) + : RelationalTableRowBase( aRow ) +{ +} + +//----------------------------------------------------------------------------- + +RelationalTableRow& +RelationalTableRow::operator=( const RelationalTableRow& aRow ) +{ + m_data = aRow.data(); + return *this; +} + +//--------------------------------------------------------------------------- + +RelationalTableRow::RelationalTableRow( const coral::AttributeList& data ) + : RelationalTableRowBase( data ) +{ +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalTableRow.h b/RelationalCool/src/RelationalTableRow.h new file mode 100644 index 000000000..582a3abb5 --- /dev/null +++ b/RelationalCool/src/RelationalTableRow.h @@ -0,0 +1,53 @@ +// $Id: RelationalTableRow.h,v 1.11 2007-07-05 09:05:12 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALTABLEROW_H +#define RELATIONALCOOL_RELATIONALTABLEROW_H + +// Local include files +#include "RelationalTableRowBase.h" + +namespace cool { + + /** @class RelationalTableRow RelationalTableRow.h + * + * Concrete implementation of a generic relational table row. + * + * This is the generic relational table row created by fetch statements. + * It is the default implementation of a RelationalTableRowBase. + * + * This class can be 'reinterpreted' as rows of specific tables by + * defining a derived class FooTableRow with one constructor from a + * RelationalTableRow. This class mainly exists to avoid constructing a + * FooTableRow from an instance of its base class RelationalTableRowBase. + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2005-10-12 + */ + + class RelationalTableRow : public RelationalTableRowBase { + + public: + + /// Destructor. + virtual ~RelationalTableRow(); + + /// Standard constructor. + /// Creates a table row with empty AttributeList data. + RelationalTableRow(); + + /// Copy constructor. + /// Performs a deep copy of the AttributeList values. + RelationalTableRow( const RelationalTableRow& rhs ); + + /// Assignment operator. + /// Performs a deep copy of the AttributeList values. + RelationalTableRow& operator=( const RelationalTableRow& rhs ); + + /// Constructor from an AttributeList. + /// Performs a deep copy of the AttributeList values. + explicit RelationalTableRow( const coral::AttributeList& data ); + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALTABLEROW_H diff --git a/RelationalCool/src/RelationalTableRowBase.cpp b/RelationalCool/src/RelationalTableRowBase.cpp new file mode 100644 index 000000000..e410043ca --- /dev/null +++ b/RelationalCool/src/RelationalTableRowBase.cpp @@ -0,0 +1,46 @@ +// $Id: RelationalTableRowBase.cpp,v 1.1 2006-03-14 16:58:12 avalassi Exp $ + +// Local include files +#include "RelationalTableRowBase.h" + +// Namespace +using namespace cool; + +//--------------------------------------------------------------------------- + +RelationalTableRowBase::~RelationalTableRowBase() +{ +} + +//--------------------------------------------------------------------------- + +RelationalTableRowBase::RelationalTableRowBase() +{ +} + +//--------------------------------------------------------------------------- + +RelationalTableRowBase::RelationalTableRowBase +( const RelationalTableRowBase& aRow ) + : m_data( aRow.m_data ) +{ +} + +//--------------------------------------------------------------------------- + +RelationalTableRowBase& +RelationalTableRowBase::operator=( const RelationalTableRowBase& aRow ) +{ + m_data = aRow.data(); + return *this; +} + +//--------------------------------------------------------------------------- + +RelationalTableRowBase::RelationalTableRowBase +( const coral::AttributeList& data ) + : m_data( data ) +{ +} + +//--------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalTableRowBase.h b/RelationalCool/src/RelationalTableRowBase.h new file mode 100644 index 000000000..00569a741 --- /dev/null +++ b/RelationalCool/src/RelationalTableRowBase.h @@ -0,0 +1,97 @@ +// $Id: RelationalTableRowBase.h,v 1.1 2006-03-14 16:58:12 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALTABLEROWBASE_H +#define RELATIONALCOOL_RELATIONALTABLEROWBASE_H + +// Include files +#include "CoralBase/AttributeList.h" +#include "CoralBase/AttributeListSpecification.h" + +namespace cool { + + /** @class RelationalTableRowBase RelationalTableRowBase.h + * + * Base class for a relational table row. + * This class cannot be instantiated as all its constructors are protected. + * + * This class mainly exists because of the known problems with the + * coral::AttributeList copy constructor and assignment operator. + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2006-03-11 + */ + + class RelationalTableRowBase { + + public: + + /* + /// Returns the row specification. + const coral::AttributeListSpecification& rowSpecification() const + { + return m_data->attributeListSpecification(); + } + */ + + /// Returns the start const iterator for the fields. + coral::AttributeList::const_iterator begin() const + { + return m_data.begin(); + } + + /// Returns the end const iterator for the fields. + coral::AttributeList::const_iterator end() const + { + return m_data.end(); + } + + /// Proxy for the AttributeList [] access operator (non const version). + coral::Attribute& operator[]( const std::string& name ) + { + return m_data[name]; + } + + /// Proxy for the AttributeList [] access operator (const version). + const coral::Attribute& operator[]( const std::string& name ) const + { + return m_data[name]; + } + + /// Accessor to the row data. + const coral::AttributeList& data() const + { + return m_data; + } + + protected: + + /// Destructor. + virtual ~RelationalTableRowBase(); + + /// Standard constructor. + /// Creates a table row with empty AttributeList data. + RelationalTableRowBase(); + + /// Copy constructor. + /// Performs a deep copy of the AttributeList values. + RelationalTableRowBase( const RelationalTableRowBase& rhs ); + + /// Constructor from an AttributeList. + /// Performs a deep copy of the AttributeList values. + explicit RelationalTableRowBase( const coral::AttributeList& data ); + + /// Assignment operator. + /// Performs a deep copy of the AttributeList values. + /// [AV 14.03.06 - I would have left this private but this is needed by + /// vector<RelationalObjectTable>::push_back()... check why!] + RelationalTableRowBase& operator=( const RelationalTableRowBase& rhs ); + + protected: + + // The relational row data. + coral::AttributeList m_data; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALTABLEROWBASE_H diff --git a/RelationalCool/src/RelationalTag2TagTable.cpp b/RelationalCool/src/RelationalTag2TagTable.cpp new file mode 100644 index 000000000..b4e39dd9a --- /dev/null +++ b/RelationalCool/src/RelationalTag2TagTable.cpp @@ -0,0 +1,30 @@ +// $Id: RelationalTag2TagTable.cpp,v 1.5 2006-09-28 12:49:29 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalTag2TagTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification & +cool::RelationalTag2TagTable::tableSpecification() +{ + static RecordSpecification spec; + if ( spec.size() == 0 ) { + spec.extend( RelationalTag2TagTable::columnNames::parentNodeId, + RelationalTag2TagTable::columnTypeIds::parentNodeId ); + spec.extend( RelationalTag2TagTable::columnNames::parentTagId, + RelationalTag2TagTable::columnTypeIds::parentTagId ); + spec.extend( RelationalTag2TagTable::columnNames::childNodeId, + RelationalTag2TagTable::columnTypeIds::childNodeId ); + spec.extend( RelationalTag2TagTable::columnNames::childTagId, + RelationalTag2TagTable::columnTypeIds::childTagId ); + spec.extend( RelationalTag2TagTable::columnNames::sysInsTime, + RelationalTag2TagTable::columnTypeIds::sysInsTime ); + } + return spec; +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalTag2TagTable.h b/RelationalCool/src/RelationalTag2TagTable.h new file mode 100644 index 000000000..f1edae543 --- /dev/null +++ b/RelationalCool/src/RelationalTag2TagTable.h @@ -0,0 +1,69 @@ +// $Id: RelationalTag2TagTable.h,v 1.9 2007-01-17 17:55:45 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALTAG2TAGTABLE_H +#define RELATIONALCOOL_RELATIONALTAG2TAGTABLE_H + +// Local include files +#include "uppercaseString.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalTag2TagTable RelationalTag2TagTable.h + * + * Relational schema of the table storing + * parent-child relations between HVS global tags. + * + * @author Andrea Valassi and Marco Clemencic + * @date 2006-03-23 + */ + + namespace RelationalTag2TagTable { + + inline const std::string defaultTableName( const std::string& prefix ) { + // TEMPORARY? AV 04.04.2005 + // FIXME: presently the input prefix is uppercase anyway... + return uppercaseString(prefix) + "TAG2TAG"; + } + + inline const std::string sequenceName( const std::string& tableName ) { + // TEMPORARY? AV 04.04.2005 + // FIXME: presently the input table name is uppercase anyway... + return uppercaseString(tableName) + "_SEQ"; + } + + namespace columnNames { + static const std::string parentNodeId = "PARENT_NODEID"; + static const std::string parentTagId = "PARENT_TAGID"; + static const std::string childNodeId = "CHILD_NODEID"; + static const std::string childTagId = "CHILD_TAGID"; + static const std::string sysInsTime = "SYS_INSTIME"; + } + + namespace columnTypeIds { + static const StorageType::TypeId parentNodeId = StorageType::UInt32; + static const StorageType::TypeId parentTagId = StorageType::UInt32; + static const StorageType::TypeId childNodeId = StorageType::UInt32; + static const StorageType::TypeId childTagId = StorageType::UInt32; + // TEMPORARY! Should be Time? + static const StorageType::TypeId sysInsTime = StorageType::String255; + } + + namespace columnTypes { + typedef UInt32 parentNodeId; + typedef UInt32 parentTagId; + typedef UInt32 childNodeId; + typedef UInt32 childTagId; + // TEMPORARY! Should be Time? + typedef String255 sysInsTime; + } + + /// Get the record specification of the tag table + const IRecordSpecification& tableSpecification(); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALTAG2TAGTABLE_H diff --git a/RelationalCool/src/RelationalTagMgr.cpp b/RelationalCool/src/RelationalTagMgr.cpp new file mode 100644 index 000000000..d20c662c8 --- /dev/null +++ b/RelationalCool/src/RelationalTagMgr.cpp @@ -0,0 +1,1440 @@ +// $Id: RelationalTagMgr.cpp,v 1.99 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoralBase/Attribute.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "IRelationalTransactionMgr.h" +#include "RelationalDatabase.h" +#include "RelationalException.h" +#include "RelationalFolder.h" +#include "RelationalQueryMgr.h" +#include "RelationalGlobalTagTable.h" +#include "RelationalHvsTagRecord.h" +#include "RelationalNodeMgr.h" +#include "RelationalNodeTable.h" +#include "RelationalSequence.h" +#include "RelationalSequenceMgr.h" +#include "RelationalTableRow.h" +#include "RelationalTagMgr.h" +#include "RelationalTagSequence.h" +#include "RelationalTag2TagTable.h" +#include "RelationalTransaction.h" +#include "timeToString.h" + +// Namespace +using namespace cool; + +// Local type definitions +typedef boost::shared_ptr<RelationalSequence> RelationalSequencePtr; + +//----------------------------------------------------------------------------- + +RelationalTagMgr::RelationalTagMgr +( const RelationalDatabase& aDb ) + : m_db( aDb ) + , m_log( new coral::MessageStream( "RelationalTagMgr" ) ) +{ + log() << coral::Debug << "Instantiate a RelationalTagMgr" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalTagMgr::~RelationalTagMgr() +{ + log() << coral::Debug << "Delete the RelationalTagMgr" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RelationalQueryMgr& RelationalTagMgr::queryMgr() const +{ + return db().queryMgr(); +} + +//----------------------------------------------------------------------------- + +RelationalNodeMgr& RelationalTagMgr::nodeMgr() const +{ + return db().nodeMgr(); +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalTagMgr::fetchGlobalTagTableRowForNode +( const std::string& tagName ) const +{ + log() << "Fetch global tag table row for tag " << tagName + << coral::MessageStream::endmsg; + + // TEMPORARY implementation - until the isLeaf column is added + bool leafFound = false; + bool innerFound = false; + RelationalTableRow row; + const std::vector<RelationalTableRow> rows = + fetchGlobalTagTableRows( tagName ); + + // Loop over all tag records retrieved + for ( std::vector<RelationalTableRow>::const_iterator + rowIt = rows.begin(); rowIt != rows.end(); ++rowIt ) { + const RelationalTableRow& tagRow = *rowIt; + UInt32 nodeId = + tagRow[RelationalGlobalTagTable::columnNames::nodeId].data<UInt32>(); + const RelationalTableRow nodeRow = + nodeMgr().fetchNodeTableRow( nodeId ); + bool isLeaf = + nodeRow[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + if ( isLeaf ) { + leafFound = true; + row = tagRow; + } + else { + if ( innerFound ) { + throw RelationalException + ( "PANIC! Tag applied to more than one inner node!", + "RelationalTagMgr" ); + } + else { + innerFound = true; + row = tagRow; + } + } + } + + // Tag not found in any (inner or leaf) node + if ( !innerFound && !leafFound ) + throw TagNotFound + ( "Tag '" + tagName + "' not found in any node", "RelationalTagMgr" ); + + // Tag found both in an inner and in a leaf node?! + if ( innerFound && leafFound ) + throw RelationalException + ( "PANIC! Tag applied to both inner and leaf nodes!", + "RelationalTagMgr" ); + + // Tag found (either in an inner or in a leaf node) + // Do not use "else" here: workaround for a warning on MacOSX + // (control reaches end of non-void function) - see task #2062 + return row; + +} + +//----------------------------------------------------------------------------- + +const std::vector<RelationalTableRow> +RelationalTagMgr::fetchGlobalTagTableRows( UInt32 nodeId ) const +{ + log() << "Fetch global tag table rows for node #" << nodeId << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend + ( "nodeId", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::nodeId) ); + whereData["nodeId"].setValue( nodeId ); + std::string whereClause = RelationalGlobalTagTable::columnNames::nodeId; + whereClause += "= :nodeId"; + + // Delegate the query to the RelationalQueryMgr + std::string desc = ""; + std::vector<RelationalTableRow> rows = + queryMgr().fetchRowsFromTables + ( RelationalQueryMgr::tableList( db().globalTagTableName() ), + RelationalQueryMgr::columnList + ( RelationalGlobalTagTable::tableSpecification() ), + whereClause, whereData, desc ); + return rows; +} + +//----------------------------------------------------------------------------- + +const std::vector<RelationalTableRow> +RelationalTagMgr::fetchGlobalTagTableRows( const std::string& tagName ) const +{ + log() << "Fetch global tag table rows for tag " << tagName << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend + ( "tagName", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::tagName) ); + whereData["tagName"].setValue( tagName ); + std::string whereClause = RelationalGlobalTagTable::columnNames::tagName; + whereClause += "= :tagName"; + + // Delegate the query to the RelationalQueryMgr + std::string desc = ""; + std::vector<RelationalTableRow> rows = + queryMgr().fetchRowsFromTables + ( RelationalQueryMgr::tableList( db().globalTagTableName() ), + RelationalQueryMgr::columnList + ( RelationalGlobalTagTable::tableSpecification() ), + whereClause, whereData, desc ); + if ( rows.size() != 0 ) + return rows; + else + throw TagNotFound( "Tag '" + tagName + "' not found in any node", + "RelationalTagMgr" ); +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalTagMgr::fetchGlobalTagTableRow( UInt32 nodeId, + const std::string& tagName ) const +{ + log() << "Fetch global tag table row for nodeId=" << nodeId + << " and tag=" << tagName << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend + ( "nodeId", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::nodeId) ); + whereData.extend + ( "tagName", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::tagName) ); + whereData["nodeId"].setValue( nodeId ); + whereData["tagName"].setValue( tagName ); + std::string whereClause; + whereClause += RelationalGlobalTagTable::columnNames::nodeId; + whereClause += "= :nodeId"; + whereClause += " AND "; + whereClause += RelationalGlobalTagTable::columnNames::tagName; + whereClause += "= :tagName"; + + // Delegate the query to the RelationalQueryMgr + try { + std::string desc = ""; + return queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( db().globalTagTableName() ), + RelationalQueryMgr::columnList + ( RelationalGlobalTagTable::tableSpecification() ), + whereClause, whereData, desc ); + } catch( NoRowsFound& ) { + throw TagNotFound( tagName, nodeId, "RelationalTagMgr" ); + } +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalTagMgr::fetchGlobalTagTableRow( UInt32 nodeId, + UInt32 tagId ) const +{ + log() << "Fetch global tag table row for nodeId=" << nodeId + << " and tagId=" << tagId << coral::MessageStream::endmsg; + + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend + ( "nodeId", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::nodeId) ); + whereData.extend + ( "tagId", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::tagId) ); + whereData["nodeId"].setValue( nodeId ); + whereData["tagId"].setValue( tagId ); + std::string whereClause; + whereClause += RelationalGlobalTagTable::columnNames::nodeId; + whereClause += "= :nodeId"; + whereClause += " AND "; + whereClause += RelationalGlobalTagTable::columnNames::tagId; + whereClause += "= :tagId"; + + // Delegate the query to the RelationalQueryMgr + try { + std::string desc = ""; + return queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( db().globalTagTableName() ), + RelationalQueryMgr::columnList + ( RelationalGlobalTagTable::tableSpecification() ), + whereClause, whereData, desc ); + } catch( NoRowsFound& ) { + throw TagNotFound( tagId, nodeId, "RelationalTagMgr" ); + } +} + +//----------------------------------------------------------------------------- + +bool RelationalTagMgr::existsTag( const std::string& tagName ) const +{ + if ( IHvsNode::isHeadTag( tagName ) ) return true; + try { + // TEMPORARY! This STILL assumes 'tag = tag name' and one node per tag! + tagNameScope( tagName ); + return true; + } catch ( TagNotFound& ) { + return false; + } +} + +//----------------------------------------------------------------------------- + +IHvsNode::Type +RelationalTagMgr::tagNameScope( const std::string& tagName ) const +{ + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalTagMgr" ); + + bool isLeaf; + if ( IHvsNode::isHeadTag( tagName ) ) + isLeaf = true; + RelationalTableRow nodeRow; + RelationalTransaction* pTransaction = 0; + if ( !db().transactionMgr()->isActive() ) + pTransaction = + new RelationalTransaction( db().transactionMgr(), true ); // r/o + try { + std::vector<RelationalTableRow> tagRows = + fetchGlobalTagTableRows( tagName ); // throws TagNotFound if none found + UInt32 nRows = tagRows.size(); + if ( nRows == 0 ) { + throw RelationalException + ( "PANIC! No rows and no throw from fetchGlobalTagTableRows?" ); + } + else if ( nRows > 1 ) { + // AV TEMPORARY - UGLY AND DANGEROUS! + isLeaf = true; + } + else { + RelationalTableRow& tagRow = tagRows[0]; + UInt32 nodeId = + tagRow[RelationalGlobalTagTable::columnNames::nodeId].data<UInt32>(); + nodeRow = nodeMgr().fetchNodeTableRow( nodeId ); + isLeaf = + nodeRow[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + } + } catch (...) { + if ( pTransaction ) delete pTransaction; + throw; + } + if ( pTransaction ) delete pTransaction; + if ( isLeaf ) + return IHvsNode::LEAF_NODE; + else + return IHvsNode::INNER_NODE; +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> +RelationalTagMgr::taggedNodes( const std::string& tagName ) const +{ + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalTagMgr" ); + + std::vector<std::string> nodes; + if ( IHvsNode::isHeadTag( tagName ) ) + throw ReservedHeadTag( tagName, "RelationalTagMgr" ); + RelationalTransaction* pTransaction = 0; + if ( !db().transactionMgr()->isActive() ) + pTransaction = + new RelationalTransaction( db().transactionMgr(), true ); // r/o + try { + std::vector<RelationalTableRow> rows = + fetchGlobalTagTableRows( tagName ); // throws TagNotFound if none found + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + const RelationalTableRow& tagRow = *row; + unsigned int nodeId = + tagRow[RelationalGlobalTagTable::columnNames::nodeId] + .data<unsigned int>(); + RelationalTableRow nodeRow = nodeMgr().fetchNodeTableRow( nodeId ); + std::string fullPath = + nodeRow[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + nodes.push_back( fullPath ); + } + if ( pTransaction ) delete pTransaction; + return nodes; + } catch (...) { + if ( pTransaction ) delete pTransaction; + throw; + } +} + +//----------------------------------------------------------------------------- + +const HvsTagRecord +RelationalTagMgr::findTagRecord( UInt32 nodeId, + const std::string& tagName ) const +{ + //std::cout << "*** RelationalTagMgr::findTagRecord - START" << std::endl; + + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalTagMgr" ); + + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + + RelationalHvsTagRecord record(__findTagRecord(nodeId,tagName)); + + transaction.commit(); + return record; +} + +//----------------------------------------------------------------------------- + +const HvsTagRecord +RelationalTagMgr::__findTagRecord( UInt32 nodeId, + const std::string& tagName ) const +{ + + RelationalTableRow + row( fetchGlobalTagTableRow( nodeId, tagName ) ); + //std::cout << "*** RelationalTagMgr::findTagRecord - 2" << std::endl; + + // AV - Split up the following line in two parts for clarity + //RelationalHvsTagRecord record( row.data() ); + + const coral::AttributeList &rowAL = row.data(); + //std::cout << "*** RelationalTagMgr::findTagRecord - 3" << std::endl; + //std::cout << "*** RelationalTagMgr::findTagRecord - input AL size: " + // << rowAL.size() << std::endl; + //std::stringstream msg; + //rowAL.toOutputStream( msg ); + //std::cout << "*** RelationalTagMgr::findTagRecord - input AL: " + // << msg.str() << std::endl; + + // AV - The following will throw an unknown exception on Windows + //RelationalHvsTagRecord record( rowAL ); + + // AV - The following is a workaround (WHY???) + HvsTagRecord record0 = RelationalHvsTagRecord::fromRow( rowAL ); + //std::cout << "*** RelationalTagMgr::findTagRecord - 4" << std::endl; + RelationalHvsTagRecord record( record0 ); + + //std::cout << "*** RelationalTagMgr::findTagRecord - END" << std::endl; + return record; +} + +//----------------------------------------------------------------------------- + +const HvsTagRecord +RelationalTagMgr::findTagRecord( UInt32 nodeId, + UInt32 tagId ) const +{ + // Cross-check that the database is open + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalTagMgr" ); + + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + + RelationalHvsTagRecord record(__findTagRecord(nodeId,tagId)); + + transaction.commit(); + return record; +} + +//----------------------------------------------------------------------------- + +const HvsTagRecord +RelationalTagMgr::__findTagRecord( UInt32 nodeId, + UInt32 tagId ) const +{ + RelationalTableRow + row( fetchGlobalTagTableRow( nodeId, tagId ) ); + + // AV - Split up the following line in two parts for clarity + //RelationalHvsTagRecord record( row.data() ); + const coral::AttributeList &rowAL = row.data(); + // AV - The following will throw an unknown exception on Windows + //RelationalHvsTagRecord record( rowAL ); + // AV - Apply the same workaround as for findTagRecord( nodeId, tagId ) + HvsTagRecord record0 = RelationalHvsTagRecord::fromRow( rowAL ); + RelationalHvsTagRecord record( record0 ); + + return record; +} + +//----------------------------------------------------------------------------- + +const Time +RelationalTagMgr::tagInsertionTime +( const IHvsNode* node, const std::string& tagName ) const +{ + //std::cout << "*** RelationalTagMgr::tagInsertionTime - START" << std::endl; + + // HEAD tag for folder sets, SV folders, MV folders + if ( IHvsNode::isHeadTag( tagName ) ) { + //std::cout << "*** RelationalTagMgr::tagInsTime - END HEAD" << std::endl; + return node->insertionTime(); + } + + // Retrieve the tag insertion time from the global tag table + return findTagRecord( node->id(), tagName ).insertionTime(); + + /* + // Folder set - retrieve the tag insertion time from the global tag table + if ( !node->isLeaf() ) { + return findTagRecord( node->id(), tagName ).insertionTime(); + } + + // Folder + else { + const RelationalFolder* folder = + dynamic_cast<const RelationalFolder*>( node ); + if ( !folder ) + throw RelationalException + ( "PANIC! Could not dynamic cast IHvsNode* to RelationalFolder*", + "RelationalTagMgr" ); + // SV folder + if ( folder->versioningMode() != FolderVersioning::MULTI_VERSION ) { + throw TagNotFound( tagName, folder->fullPath(), "RelationalTagMgr" ); + } + // MV folder - retrieve the tag insertion time from the global tag table + else { + //std::cout << "*** RelationalTagMgr::tagInsTime - END MV" << std::endl; + return findTagRecord( folder->id(), tagName ).insertionTime(); + } + } + */ + +} + +//----------------------------------------------------------------------------- + +const std::string +RelationalTagMgr::tagDescription +( const IHvsNode* node, const std::string& tagName ) const +{ + // HEAD tag for folder sets, SV folders, MV folders + if ( IHvsNode::isHeadTag( tagName ) ) + return std::string( "HEAD tag" ); + + // Retrieve the tag description from the global tag table + return findTagRecord( node->id(), tagName ).description(); + + /* + // Folder set - retrieve the tag description from the global tag table + if ( !node->isLeaf() ) { + return findTagRecord( node->id(), tagName ).description(); + } + + // Folder + else { + const RelationalFolder* folder = + dynamic_cast<const RelationalFolder*>( node ); + if ( !folder ) + throw RelationalException + ( "PANIC! Could not dynamic cast IHvsNode* to RelationalFolder*", + "RelationalTagMgr" ); + // SV folder + if ( folder->versioningMode() != FolderVersioning::MULTI_VERSION ) { + throw TagNotFound( tagName, node->fullPath(), "RelationalTagMgr" ); + } + // MV folder - retrieve the tag description from the global tag table + else { + return findTagRecord( folder->id(), tagName ).description(); + } + } + */ + +} + +//----------------------------------------------------------------------------- + +HvsTagLock::Status +RelationalTagMgr::tagLockStatus +( const IHvsNode* node, const std::string& tagName ) const +{ + // HEAD tag for folder sets, SV folders, MV folders - never locked! + if ( IHvsNode::isHeadTag( tagName ) ) { + return HvsTagLock::UNLOCKED; + } + + // Retrieve the tag lock status from the global tag table + return findTagRecord( node->id(), tagName ).lockStatus(); + + /* + // Folder set - retrieve the tag lock status from the global tag table + if ( !node->isLeaf() ) { + return findTagRecord( node->id(), tagName ).lockStatus(); + } + + // Folder + else { + const RelationalFolder* folder = + dynamic_cast<const RelationalFolder*>( node ); + if ( !folder ) + throw RelationalException + ( "PANIC! Could not dynamic cast IHvsNode* to RelationalFolder*", + "RelationalTagMgr" ); + // SV folder + if ( folder->versioningMode() != FolderVersioning::MULTI_VERSION ) { + throw TagNotFound( tagName, folder->fullPath(), "RelationalTagMgr" ); + } + // MV folder - retrieve the tag lock status from the global tag table + else { + return findTagRecord( folder->id(), tagName ).lockStatus(); + } + } + */ + +} + +//----------------------------------------------------------------------------- + +void +RelationalTagMgr::setTagLockStatus( const IHvsNode* node, + const std::string& tagName, + HvsTagLock::Status tagLockStatus ) +{ + // HEAD tag for folder sets, SV folders, MV folders - never locked! + if ( IHvsNode::isHeadTag( tagName ) ) { + throw ReservedHeadTag( tagName, "RelationalTagMgr" ); + } + + // Start a transaction + RelationalTransaction transaction( db().transactionMgr() ); // read-write + + // Define the SET and WHERE clauses for the update using bind variables + coral::AttributeList updateData; + updateData.extend + ( "tagLockStatus", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::tagLockStatus) ); + updateData.extend + ( "nodeId", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::nodeId) ); + updateData.extend + ( "tagName", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::tagName) ); + updateData["tagLockStatus"].setValue( (UInt16)tagLockStatus ); + updateData["nodeId"].setValue( node->id() ); + updateData["tagName"].setValue( tagName ); + std::string setClause = + RelationalGlobalTagTable::columnNames::tagLockStatus; + setClause += "= :tagLockStatus"; + std::string whereClause = RelationalGlobalTagTable::columnNames::nodeId; + whereClause += " = :nodeId"; + whereClause += " AND "; + whereClause += RelationalGlobalTagTable::columnNames::tagName; + whereClause += " = :tagName"; + + // Execute the update + if ( 1 != queryMgr().updateTableRows + ( db().globalTagTableName(), setClause, whereClause, updateData ) ) + throw RowNotUpdated + ( "Could not update the tag lock status - does tag exist?", + "RalDatabase" ); + + // Commit the transaction + transaction.commit(); + +} + +//----------------------------------------------------------------------------- + +const HvsTagRecord +RelationalTagMgr::findOrCreateTag( UInt32 nodeId, + const std::string& tagName ) const +{ + if ( ! db().isOpen() ) throw DatabaseNotOpen( "RelationalTagMgr" ); + try { + + // AV - Split up the following line in two parts for clarity + //RelationalHvsTagRecord record + // ( fetchGlobalTagTableRow( nodeId, tagName ).data() ); + const coral::AttributeList rowAL = + fetchGlobalTagTableRow( nodeId, tagName ).data(); + // AV - The following will throw an unknown exception on Windows + //RelationalHvsTagRecord record( rowAL ); + // AV - Apply the same workaround as for findTagRecord( nodeId, tagId ) + HvsTagRecord record0 = RelationalHvsTagRecord::fromRow( rowAL ); + RelationalHvsTagRecord record( record0 ); + + return record; + } + catch ( TagNotFound& ) { + // PERFORMANCE WARNING - createTag() will query existsTag() a 2nd time + std::string description = ""; + return createTag( nodeId, tagName, description ); + } +} + +//----------------------------------------------------------------------------- + +const HvsTagRecord +RelationalTagMgr::createTag( UInt32 nodeId, + const std::string& tagName, + const std::string& description ) const +{ + return createTagAndLocalTag( nodeId, tagName, description, "" ); +} + +//----------------------------------------------------------------------------- + +const HvsTagRecord +RelationalTagMgr::createTagAndLocalTag +( UInt32 nodeId, + const std::string& tagName, + const std::string& description, + const std::string& inputTagTableName ) const +{ + // Check if this tag exists (globally) + // [NB existsTag(tagName) returns true for the reserved tags "" or "HEAD"] + if ( existsTag( tagName ) ) + throw TagExists( tagName, "RelationalTagMgr" ); + + // TEMPORARY! - Start + // TEMPORARY! Functionality needed but this implementation is an ugly hack! + // Check whether the node supports versioning - is it a SV folder? + // Must perform the check before retrieving the tag sequence (none for SV!) + // HACK - Skip check if input local tag name is provided + std::string tagTableName = ""; + if ( inputTagTableName != "" ) { + tagTableName = inputTagTableName; + } + else { + RelationalTableRow row = nodeMgr().fetchNodeTableRow( nodeId ); + bool isLeaf = + row[RelationalNodeTable::columnNames::nodeIsLeaf].data<bool>(); + if ( isLeaf ) { + FolderVersioning::Mode mode = + RelationalFolder::versioningMode( row.data() ); + if ( mode == FolderVersioning::MULTI_VERSION ) + tagTableName = RelationalFolder::tagTableName( row.data() ); + else + throw FolderIsSingleVersion( nodeId, "RelationalTagMgr" ); + } + } + // TEMPORARY! - End + + // Get a new tag ID from the sequence + std::string tagSeqName = RelationalTagSequence::sequenceName + ( db().defaultTablePrefix(), nodeId ); + RelationalSequencePtr sequence + ( db().queryMgr().sequenceMgr().getSequence( tagSeqName ) ); + UInt32 tagId = sequence->nextVal(); + const std::string insertionTime = sequence->currDate(); + + // New tags are UNLOCKED + HvsTagLock::Status tagLockStatus = HvsTagLock::UNLOCKED; + + // Register the tag in the global tag table + insertGlobalTagTableRow + ( nodeId, tagId, tagName, tagLockStatus, description, insertionTime ); + + // TEMPORARY! - Start + // TEMPORARY! - Also fill the local tag table if necessary. + // Fill the local tag table name if one is provided. + // Otherwise retrieve it from the node table for MV folders. + // Insert the new tag also in the local tag table + if ( tagTableName != "" ) + insertTagTableRow + ( tagTableName, tagId, tagName, description, insertionTime ); + // TEMPORARY! - End + + // Return the new tag ID + return HvsTagRecord( tagId, nodeId, tagName, tagLockStatus, description, + stringToTime( insertionTime ) ); +} + +//----------------------------------------------------------------------------- + +void RelationalTagMgr::deleteTag( UInt32 nodeId, + const std::string& tagName ) const +{ + deleteGlobalTagTableRow( nodeId, findTagRecord( nodeId, tagName ).id() ); +} + +//----------------------------------------------------------------------------- + +void RelationalTagMgr::insertGlobalTagTableRow +( UInt32 nodeId, + UInt32 tagId, + const std::string& tagName, + HvsTagLock::Status tagLockStatus, + const std::string& tagDescription, + const std::string& insertionTime ) const +{ + // Transaction handled in the outer scope + // Existence check handled in the outer scope + + // Register the tag in the global tag table + Record data( RelationalGlobalTagTable::tableSpecification() ); + data[RelationalGlobalTagTable::columnNames::nodeId].setValue + ( nodeId ); + data[RelationalGlobalTagTable::columnNames::tagId].setValue + ( tagId ); + data[RelationalGlobalTagTable::columnNames::tagName].setValue + ( tagName ); + data[RelationalGlobalTagTable::columnNames::tagLockStatus].setValue + ( (UInt16)tagLockStatus ); + data[RelationalGlobalTagTable::columnNames::tagDescription].setValue + ( tagDescription ); + data[RelationalGlobalTagTable::columnNames::sysInsTime].setValue + ( insertionTime ); + + // TEMPORARY? Will RAL do this as well? + // Check that all column values are within their allowed range + RelationalGlobalTagTable::tableSpecification().validate(data); + + // Perform the actual db update + queryMgr().insertTableRow + ( db().globalTagTableName(), data.attributeList() ); +} + +//----------------------------------------------------------------------------- + +void RelationalTagMgr::deleteGlobalTagTableRow( UInt32 nodeId, + UInt32 tagId ) const +{ + // Throw TagIsLocked if the tag is locked (either LOCKED or PARTIALLYLOCKED, + // both are equivalent here): this is not strictly necessary because + // this protection is already implemented where necessary (i.e. + // in deleteTag for MV folders and in deleteTagRelation), but is added + // here for extra protection at the cost of little performance overhead. + // PANIC exception because there should be no path to this statement...! + const HvsTagRecord tag = __findTagRecord( nodeId, tagId ); + if ( tag.lockStatus() != HvsTagLock::UNLOCKED ) { + std::stringstream msg; + msg << "PANIC! Cannot delete global tag table row for tag '" << tag.name() + << " (tag #" << tagId << ") in node #" << nodeId + << ": tag is locked"; + throw TagIsLocked( msg.str(), "RelationalTagMgr" ); + } + // Transaction handled in the outer scope + coral::AttributeList whereData; + whereData.extend + ( "nodeId", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::nodeId) ); + whereData.extend + ( "tagId", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::tagId) ); + whereData["nodeId"].setValue( nodeId ); + whereData["tagId"].setValue( tagId ); + std::string whereClause; + whereClause += RelationalGlobalTagTable::columnNames::nodeId; + whereClause += "= :nodeId"; + whereClause += " AND "; + whereClause += RelationalGlobalTagTable::columnNames::tagId; + whereClause += "= :tagId"; + queryMgr().deleteTableRows + ( db().globalTagTableName(), whereClause, whereData, 1 ); +} + +//----------------------------------------------------------------------------- + +UInt32 +RelationalTagMgr::deleteGlobalTagTableRowsForNode( UInt32 nodeId ) const +{ + // Transaction handled in the outer scope + coral::AttributeList whereData; + whereData.extend + ( "nodeId", typeIdToCoralType + (RelationalGlobalTagTable::columnTypeIds::nodeId) ); + whereData["nodeId"].setValue( nodeId ); + std::string whereClause = RelationalGlobalTagTable::columnNames::nodeId; + whereClause += "= :nodeId"; + return queryMgr().deleteTableRows + ( db().globalTagTableName(), whereClause, whereData ); +} + +//----------------------------------------------------------------------------- + +void RelationalTagMgr::insertTagTableRow +( const std::string& tagTableName, + UInt32 tagId, + const std::string& tagName, + const std::string& description, + const std::string& insertionTime ) const +{ + // Transaction handled in the outer scope + + // AV - DO NOT TEST IF TAG EXISTS HERE - TAG DOES EXIST IN GLOBAL TAG TABLE! + + // Register the tag in the local tag table + + const IRecordSpecification& dataSpec = + RelationalTagTable::tableSpecification(); + coral::AttributeList data = Record( dataSpec ).attributeList(); + data[RelationalTagTable::columnNames::tagId].setValue + ( tagId ); + data[RelationalTagTable::columnNames::tagName].setValue + ( tagName ); + data[RelationalTagTable::columnNames::tagDescription].setValue + ( description ); + data[RelationalTagTable::columnNames::sysInsTime].setValue + ( insertionTime ); + + // TEMPORARY? Will RAL do this as well? + // Check that all column values are within their allowed range + dataSpec.validate(data); + + // Perform the actual db update + queryMgr().insertTableRow( tagTableName, data ); + + // Return the systemID for the tag + //return tagId; +} + +//----------------------------------------------------------------------------- + +void RelationalTagMgr::deleteTagTableRow( const std::string& tagTableName, + UInt32 tagId ) const +{ + // Transaction handled in the outer scope + coral::AttributeList whereData; + whereData.extend + ( "tagId", typeIdToCoralType + (RelationalTagTable::columnTypeIds::tagId) ); + whereData["tagId"].setValue( tagId ); + std::string whereClause = RelationalTagTable::columnNames::tagId; + whereClause += "= :tagId"; + queryMgr().deleteTableRows( tagTableName, whereClause, whereData, 1 ); +} + +//----------------------------------------------------------------------------- + +void RelationalTagMgr::insertTag2TagTableRow +( UInt32 parentNodeId, + UInt32 parentTagId, + UInt32 childNodeId, + UInt32 childTagId, + const std::string& insertionTime ) const +{ + // Transaction handled in the outer scope + // Existence check handled in the outer scope + + // Register the tag in the global tag table + const IRecordSpecification& dataSpec = + RelationalTag2TagTable::tableSpecification(); + Record data( dataSpec ); + data[RelationalTag2TagTable::columnNames::parentNodeId].setValue + ( parentNodeId ); + data[RelationalTag2TagTable::columnNames::parentTagId].setValue + ( parentTagId ); + data[RelationalTag2TagTable::columnNames::childNodeId].setValue + ( childNodeId ); + data[RelationalTag2TagTable::columnNames::childTagId].setValue + ( childTagId ); + data[RelationalTag2TagTable::columnNames::sysInsTime].setValue + ( insertionTime ); + + // TEMPORARY? Will RAL do this as well? + // Check that all column values are within their allowed range + dataSpec.validate(data); + + // Perform the actual db update + queryMgr().insertTableRow + ( db().tag2TagTableName(), data.attributeList() ); +} + +//----------------------------------------------------------------------------- + +const RelationalTableRow +RelationalTagMgr::fetchTag2TagTableRow( UInt32 parentNodeId, + UInt32 parentTagId, + UInt32 childNodeId ) const +{ + log() << "Fetch tag2tag row for relation between parent tag #" + << parentTagId << " in node #" << parentNodeId + << " and child tag in node #" << childNodeId << coral::MessageStream::endmsg; + + // Transaction handled in the outer scope + + coral::AttributeList whereData; + whereData.extend + ( "parentNodeId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::parentNodeId) ); + whereData.extend + ( "parentTagId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::parentTagId) ); + whereData.extend + ( "childNodeId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::childNodeId) ); + whereData["parentNodeId"].setValue( parentNodeId ); + whereData["parentTagId"].setValue( parentTagId ); + whereData["childNodeId"].setValue( childNodeId ); + std::string whereClause; + whereClause += RelationalTag2TagTable::columnNames::parentNodeId; + whereClause += "= :parentNodeId"; + whereClause += " AND "; + whereClause += RelationalTag2TagTable::columnNames::parentTagId; + whereClause += "= :parentTagId"; + whereClause += " AND "; + whereClause += RelationalTag2TagTable::columnNames::childNodeId; + whereClause += "= :childNodeId"; + try { + std::string desc = ""; + return queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( db().tag2TagTableName() ), + RelationalQueryMgr::columnList + ( RelationalTag2TagTable::tableSpecification() ), + whereClause, whereData, desc ); + } catch( NoRowsFound& ) { + throw TagRelationNotFound + ( parentNodeId, parentTagId, childNodeId, "RelationalTagMgr" ); + } +} + +//----------------------------------------------------------------------------- + +void RelationalTagMgr::deleteTag2TagTableRow( UInt32 parentNodeId, + UInt32 parentTagId, + UInt32 childNodeId ) const +{ + log() << "Delete tag2tag row for relation between parent tag #" + << parentTagId << " in node #" << parentNodeId + << " and child tag in node #" << childNodeId << coral::MessageStream::endmsg; + + // Transaction handled in the outer scope + + coral::AttributeList whereData; + whereData.extend + ( "parentNodeId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::parentNodeId) ); + whereData.extend + ( "parentTagId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::parentTagId) ); + whereData.extend + ( "childNodeId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::childNodeId) ); + whereData["parentNodeId"].setValue( parentNodeId ); + whereData["parentTagId"].setValue( parentTagId ); + whereData["childNodeId"].setValue( childNodeId ); + std::string whereClause; + whereClause += RelationalTag2TagTable::columnNames::parentNodeId; + whereClause += "= :parentNodeId"; + whereClause += " AND "; + whereClause += RelationalTag2TagTable::columnNames::parentTagId; + whereClause += "= :parentTagId"; + whereClause += " AND "; + whereClause += RelationalTag2TagTable::columnNames::childNodeId; + whereClause += "= :childNodeId"; + queryMgr().deleteTableRows + ( db().tag2TagTableName(), whereClause, whereData, 1 ); +} + +//----------------------------------------------------------------------------- + +UInt32 +RelationalTagMgr::deleteTag2TagTableRowsForNode( UInt32 nodeId ) const +{ + // Transaction handled in the outer scope + coral::AttributeList whereData; + whereData.extend + ( "parentNodeId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::parentNodeId) ); + whereData.extend + ( "childNodeId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::childNodeId) ); + whereData["parentNodeId"].setValue( nodeId ); + whereData["childNodeId"].setValue( nodeId ); + std::string whereClause; + whereClause += RelationalTag2TagTable::columnNames::parentNodeId; + whereClause += "= :parentNodeId"; + whereClause += " OR "; + whereClause += RelationalTag2TagTable::columnNames::childNodeId; + whereClause += "= :childNodeId"; + return queryMgr().deleteTableRows + ( db().tag2TagTableName(), whereClause, whereData ); +} + +//----------------------------------------------------------------------------- + +bool +RelationalTagMgr::existsTagInTag2TagTable( UInt32 nodeId, + UInt32 tagId ) const +{ + // Transaction handled in the outer scope + coral::AttributeList whereData; + whereData.extend + ( "parentNodeId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::parentNodeId) ); + whereData.extend + ( "parentTagId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::parentTagId) ); + whereData.extend + ( "childNodeId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::childNodeId) ); + whereData.extend + ( "childTagId", typeIdToCoralType + (RelationalTag2TagTable::columnTypeIds::childTagId) ); + whereData["parentNodeId"].setValue( nodeId ); + whereData["parentTagId"].setValue( tagId ); + whereData["childNodeId"].setValue( nodeId ); + whereData["childTagId"].setValue( tagId ); + std::string whereClause; + whereClause += "( "; + whereClause += RelationalTag2TagTable::columnNames::parentNodeId; + whereClause += " = :parentNodeId"; + whereClause += " AND "; + whereClause += RelationalTag2TagTable::columnNames::parentTagId; + whereClause += " = :parentTagId"; + whereClause += " ) OR ( "; + whereClause += RelationalTag2TagTable::columnNames::childNodeId; + whereClause += " = :childNodeId"; + whereClause += " AND "; + whereClause += RelationalTag2TagTable::columnNames::childTagId; + whereClause += " = :childTagId"; + whereClause += " )"; + unsigned int rowCount = db().queryMgr().countRowsFromTables + ( RelationalQueryMgr::tableList( db().tag2TagTableName() ), + whereClause, whereData, "" ); + return rowCount > 0; +} + +//----------------------------------------------------------------------------- +/* +bool +RelationalTagMgr::isTagUsed( UInt32 nodeId, + UInt32 tagId ) const +{ + // Is the tag referenced in the TAG2TAG table? + if ( existsTagInTag2TagTable( nodeId, tagId ) ) { + return true; + } + // TEMPORARY? Not nice to have this code here :-( + // Otherwise - must check if this is a folder or folder set + else { + // If this is a folder set, return false + // If this is a folder, check the IOV and IOV2TAG tables + } +} +*/ +//----------------------------------------------------------------------------- + +void +RelationalTagMgr::createTagRelation( UInt32 parentNodeId, + const std::string& parentTagName, + UInt32 childNodeId, + const std::string& childTagName ) const +{ + log() << "Create tag relation between parent tag '" << parentTagName + << "' in node #" << parentNodeId << " and child tag '" << childTagName + << "' in node #" << childNodeId << coral::MessageStream::endmsg; + + // Throw ReservedHeadTag if one of the two tags is a HEAD tag + if ( IHvsNode::isHeadTag( parentTagName ) ) + throw ReservedHeadTag( parentTagName, "RelationalTagMgr" ); + if ( IHvsNode::isHeadTag( childTagName ) ) + throw ReservedHeadTag( childTagName, "RelationalTagMgr" ); + + // Throw NodeRelationNotFound if the nodes are not parent and child + // TEMPORARY! Replace by a method returning a node record... + RelationalTableRow childNode = + db().nodeMgr().fetchNodeTableRow( childNodeId ); + if ( childNode[RelationalNodeTable::columnNames::nodeParentId].data<UInt32>() + != parentNodeId ) + throw NodeRelationNotFound + ( parentNodeId, childNodeId, "RelationalTagMgr", true ); + + // Create the parent tag in the parent node if not defined yet. + const HvsTagRecord parentTag = + findOrCreateTag( parentNodeId, parentTagName ); + UInt32 parentTagId = parentTag.id(); + + // Throw TagIsLocked if the tag is fully LOCKED. + // A new relation can be created both if UNLOCKED or PARTIALLYLOCKED: + // I can add a new child tag relation to a partially locked parent tag. + // If a relation already exists, TagRelationExists is thrown in all cases! + if ( parentTag.lockStatus() != HvsTagLock::UNLOCKED && + parentTag.lockStatus() != HvsTagLock::PARTIALLYLOCKED ) + throw TagIsLocked + ( "Cannot create tag relation to parent tag '" + parentTagName + + "': tag is locked", "RelationalTagMgr" ); + + // Create the child tag in the child node if not defined yet. + UInt32 childTagId = + findOrCreateTag( childNodeId, childTagName ).id(); + + // Throw TagRelationExists if a relation to a child tag already exists + bool tagRelationExists = false; + try { + findTagRelation( parentNodeId, parentTagName, childNodeId ); + tagRelationExists = true; + } + catch( ... ) {} + if ( tagRelationExists ) + throw TagRelationExists + ( parentNodeId, parentTagId, childNodeId, "RelationalTagMgr" ); + + // Get a new insertion time from the tag2tag sequence + const std::string tableName = db().tag2TagTableName(); + const std::string seqName = + RelationalTag2TagTable::sequenceName( tableName ); + RelationalSequencePtr sequence + ( db().queryMgr().sequenceMgr().getSequence( seqName ) ); + sequence->nextVal(); // TEMPORARY! value not used: need a non-sequence clock! + const std::string insertionTime = sequence->currDate(); + + // Insert a new row in the tag2tag table + insertTag2TagTableRow + ( parentNodeId, parentTagId, childNodeId, childTagId, insertionTime ); +} + +//----------------------------------------------------------------------------- + +//void +UInt32 +RelationalTagMgr::deleteTagRelation( UInt32 parentNodeId, + const std::string& parentTagName, + UInt32 childNodeId ) const +{ + log() << "Delete tag relation between parent tag '" << parentTagName + << "' in node #" << parentNodeId + << " and child tag in node #" << childNodeId << coral::MessageStream::endmsg; + + // Throw ReservedHeadTag if the parent tag is a HEAD tag + if ( IHvsNode::isHeadTag( parentTagName ) ) + throw ReservedHeadTag( parentTagName, "RelationalTagMgr" ); + + // Throw TagNotFound if the parent tag does not exist in the parent node + const HvsTagRecord tag = __findTagRecord( parentNodeId, parentTagName ); + UInt32 parentTagId = tag.id(); + + // Throw TagIsLocked if the tag is locked + // (either LOCKED or PARTIALLYLOCKED - both are equivalent here) + if ( tag.lockStatus() != HvsTagLock::UNLOCKED ) + throw TagIsLocked + ( "Cannot delete tag relation to parent tag '" + parentTagName + + "': tag is locked", "RelationalTagMgr" ); + + // Throw TagRelationNotFound if the parent tag has no related child tag + RelationalTableRow relation = + fetchTag2TagTableRow( parentNodeId, parentTagId, childNodeId ); + UInt32 childTagId = + relation[RelationalTag2TagTable::columnNames::childTagId].data<UInt32>(); + + // Delete the relation between a parent tag node and a child tag + deleteTag2TagTableRow( parentNodeId, parentTagId, childNodeId ); + + // Delete the parent tag if not related to another parent/child tag. + // TEMPORARY? Assume the parent can only be a folder set! + // All there is to delete in this case is the global tag table row + if ( ! existsTagInTag2TagTable( parentNodeId, parentTagId ) ) + deleteGlobalTagTableRow( parentNodeId, parentTagId ); + + // TEMPORARY - this is handled in the calling routine... + // Delete the tag in this node if not related to another parent or IOVs. + // Throw TagIsLocked if this would lead to deletion of a locked child tag + // (either LOCKED or PARTIALLYLOCKED - both are equivalent here). + + // TEMPORARY- return the childTagId + return childTagId; +} + +//----------------------------------------------------------------------------- + +void +RelationalTagMgr::deleteTagRelation( const RelationalHvsNode& childNode, + const std::string& parentTagName ) const +{ + UInt32 parentNodeId = childNode.parentId(); + UInt32 childNodeId = childNode.id(); + + // First delete the tag relation + UInt32 childTagId = + deleteTagRelation( parentNodeId, parentTagName, childNodeId ); + + // Then, delete also the child tag if this has no IOV or HVS relations left + // Throw TagIsLocked if this would lead to deletion of a locked child tag + // (either LOCKED or PARTIALLYLOCKED - both are equivalent here) + // [this is ALSO implemented in deleteGlobalTagTableRow for extra protection] + const HvsTagRecord childTag = + __findTagRecord( childNodeId, childTagId ); + + // Check if this is a folder or a folder set + bool isLeaf = childNode.isLeaf(); + // Folder set - nothing else to check or to delete + if ( !isLeaf ) { + if ( ! existsTagInTag2TagTable( childNodeId, childTagId ) ) { + if ( childTag.lockStatus() != HvsTagLock::UNLOCKED ) + throw TagIsLocked + ( "Cannot delete tag relation to parent tag '" + parentTagName + + "': this would lead to the deletion of locked child tag '" + + childTag.name() + "'", "RelationalTagMgr" ); + deleteGlobalTagTableRow( childNodeId, childTagId ); + } + } + // Folder - check if SV or MV + else { + const RelationalFolder* pFolder; + try { + const RelationalFolder& folder = + dynamic_cast<const RelationalFolder&>( childNode ); + pFolder = &folder; + } + catch( ... ) { + throw RelationalException + ( "PANIC! Could not dynamic cast to const RelationalFolder&", + "RelationalTagMgr" ); + } + if ( !pFolder ) + throw RelationalException + ( "PANIC! Null pointer from dynamic cast to const RelationalFolder&", + "RelationalTagMgr" ); + // SV folder - nothing else to check or to delete + if ( pFolder->versioningMode() != FolderVersioning::MULTI_VERSION ) { + if ( ! existsTagInTag2TagTable( childNodeId, childTagId ) ) { + if ( childTag.lockStatus() != HvsTagLock::UNLOCKED ) + throw TagIsLocked + ( "Cannot delete tag relation to parent tag '" + parentTagName + + "': this would lead to the deletion of locked child tag '" + + childTag.name() + "'", "RelationalTagMgr" ); + deleteGlobalTagTableRow( childNodeId, childTagId ); + } + } + // MV folder - check IOV and IOV2TAG table, delete also from TAG table + if ( !existsTagInTag2TagTable( childNodeId, childTagId ) && + !RelationalFolder::existsUserTagInObjectTable + ( db().queryMgr(), childTagId, pFolder->objectTableName() ) && + !RelationalFolder::existsTagInObject2TagTable + ( db().queryMgr(), childTagId, pFolder->object2TagTableName() ) ) + { + if ( childTag.lockStatus() != HvsTagLock::UNLOCKED ) + throw TagIsLocked + ( "Cannot delete tag relation to parent tag '" + parentTagName + + "': this would lead to the deletion of locked child tag '" + + childTag.name() + "'", "RelationalTagMgr" ); + deleteGlobalTagTableRow( childNodeId, childTagId ); + deleteTagTableRow( pFolder->tagTableName(), childTagId ); + } + // TODO + } + +} + +//----------------------------------------------------------------------------- + +UInt32 +RelationalTagMgr::findTagRelation( UInt32 parentNodeId, + const std::string& parentTagName, + UInt32 childNodeId ) const +{ + log() << "Find the child tag in node #" << childNodeId + << " related to parent tag '" << parentTagName + << " in node '" << parentNodeId << coral::MessageStream::endmsg; + + // Throw ReservedHeadTag if the parent tag is a HEAD tag + if ( IHvsNode::isHeadTag( parentTagName ) ) + throw ReservedHeadTag( parentTagName, "RelationalTagMgr" ); + + // Throw TagNotFound if the parent tag does not exist in the parent node + UInt32 parentTagId = + __findTagRecord( parentNodeId, parentTagName ).id(); + + // Throw TagRelationNotFound if the parent tag has no related child tag + RelationalTableRow relation = + fetchTag2TagTableRow( parentNodeId, parentTagId, childNodeId ); + + // Find the child node tag associated to the given parent node tag. + return + relation[RelationalTag2TagTable::columnNames::childTagId].data<UInt32>(); +} + +//----------------------------------------------------------------------------- + +UInt32 +RelationalTagMgr::resolveTag( const std::string& ancestorTagName, + UInt32 descendantNodeId ) const +{ + log() << "Find the descendant tag# in node #" << descendantNodeId + << " related to ancestor tag '" << ancestorTagName << "'" + << coral::MessageStream::endmsg; + + // Throw ReservedHeadTag if the ancestor tag is a HEAD tag + if ( IHvsNode::isHeadTag( ancestorTagName ) ) + throw ReservedHeadTag( ancestorTagName, "RelationalTagMgr" ); + + // Determine the node where the tag is defined. + // Throw TagNotFound if the tag does not exist in any node. + RelationalTableRow ancestorTag = + fetchGlobalTagTableRowForNode( ancestorTagName ); + UInt32 ancestorNodeId = + ancestorTag[RelationalGlobalTagTable::columnNames::nodeId].data<UInt32>(); + UInt32 ancestorTagId = + ancestorTag[RelationalGlobalTagTable::columnNames::tagId].data<UInt32>(); + + // Special case: the node where the tag is defined is the 'descendant' + // node itself + if ( ancestorNodeId == descendantNodeId ) + return ancestorTagId; + + // Throw NodeRelationNotFound if the node where the ancestor tag + // is defined is not an ancestor of the descendant node + const std::vector<UInt32> dNodes = + nodeMgr().resolveNodeHierarchy( ancestorNodeId, descendantNodeId ); + UInt32 parentNodeId = ancestorNodeId; + UInt32 parentTagId = ancestorTagId; + for ( std::vector<UInt32>::const_iterator + dNode = dNodes.begin(); dNode != dNodes.end(); ++dNode ) { + UInt32 childNodeId = *dNode; + // Throw TagRelationNotFound if the parent tag has no related child tag + RelationalTableRow relation = + fetchTag2TagTableRow( parentNodeId, parentTagId, childNodeId ); + UInt32 childTagId = + relation[RelationalTag2TagTable::columnNames::childTagId].data<UInt32>(); + if ( childNodeId == descendantNodeId ) { + return childTagId; + } + else { + parentNodeId = childNodeId; + parentTagId = childTagId; + } + } + throw RelationalException + ( "PANIC! Descendant node not included in resolved hierarchy???", + "RelationalTagMgr" ); +} + +//----------------------------------------------------------------------------- + +void RelationalTagMgr::setTagDescription( const IHvsNode* node, + const std::string& tagName, + const std::string& description ) { + + //if ( IHvsNode::isHeadTag( tagName ) ) + + if (description.size() > 255) { + throw Exception("Description string exceeds 255 character limit.", + "RelationalFolder"); + } + + // We're using the tag lookup in 'findTagRecord' to trigger the + // the following exceptions: + // - trying to set a description for a non-existing tag + // - trying to set a description for tag name not defined for this node + // - trying to set a description for the HEAD tag + findTagRecord(node->id(), tagName); + + // prepare update data + coral::AttributeList updateData; + updateData.extend( + "description", + typeIdToCoralType( RelationalTagTable::columnTypeIds::tagDescription ) + ); + updateData.extend( + "tagName", + typeIdToCoralType( RelationalTagTable::columnTypeIds::tagName ) + ); + updateData["description"].setValue( description ); + updateData["tagName"].setValue( tagName ); + + std::string setClause = + RelationalTagTable::columnNames::tagDescription + " = :description"; + std::string whereClause = + RelationalTagTable::columnNames::tagName + " = :tagName"; + + bool readOnly = false; + RelationalTransaction transaction( db().transactionMgr(), readOnly ); + + // update global tag table + // NB: we are ignoring / have to ignore the local tag table, because only + // leaves (folders, as opposed to foldersets) have one and we can't / don't + // want to differentiate between the two here. The duplication of the tag + // description in the local tag table should be removed. + db().queryMgr().updateTableRows(db().globalTagTableName(), + setClause, + whereClause, + updateData); + + transaction.commit(); +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalTagMgr.h b/RelationalCool/src/RelationalTagMgr.h new file mode 100644 index 000000000..3a99196e2 --- /dev/null +++ b/RelationalCool/src/RelationalTagMgr.h @@ -0,0 +1,318 @@ +// $Id: RelationalTagMgr.h,v 1.68 2008-11-04 12:39:14 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALTAGMGR_H +#define RELATIONALCOOL_RELATIONALTAGMGR_H + +// Include files +#include <memory> +//#include "CoolKernel/IHvsTagMgr.h" +#include "IHvsTagMgr.h" +#include "CoralBase/MessageStream.h" + +namespace cool { + + // Forward declarations + class RelationalDatabase; + class RelationalNodeMgr; + class RelationalQueryMgr; + class RelationalTableRow; + + // TEMPORARY + class RelationalHvsNode; + + /** @class RelationalTagMgr RelationalTagMgr.h + * + * Abstract base class for a manager of a hierarchy + * of conditions database tags stored in a relational database. + * + * @author Andrea Valassi and Marco Clemencic + * @date 2006-03-02 + */ + + class RelationalTagMgr : public IHvsTagMgr { + + public: + + /// Destructor + virtual ~RelationalTagMgr(); + + /// Constructor from a relational database + RelationalTagMgr( const RelationalDatabase& db ); + + /// Return the type of node (inner/leaf) where this tag name can be used. + /// Tag names, except for "HEAD", are case sensitive. + /// Throws TagNameNotFound if the tag name does not exist. + IHvsNode::Type tagNameScope( const std::string& tagName ) const; + + /// Does a tag with this name exist (in any node)? + /// Tag names, except for "HEAD", are case sensitive. + /// Returns true for the reserved tags "" and "HEAD". + bool existsTag( const std::string& tagName ) const; + + /// Return the names of the nodes where the tag is defined. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + const std::vector<std::string> + taggedNodes( const std::string& tagName ) const; + + /// Find a tag record by nodeId and tag name. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + /// Starts a transaction. + const HvsTagRecord findTagRecord( UInt32 nodeId, + const std::string& tagName ) const; + + /// Find a tag record by nodeId and tag name. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + /// Does not start a transaction (prefix __) + const HvsTagRecord __findTagRecord( UInt32 nodeId, + const std::string& tagName ) const; + + /// Find a tag record by nodeId and tagId. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + /// Starts a transaction. + const HvsTagRecord findTagRecord( UInt32 nodeId, + UInt32 tagId ) const; + + /// Find a tag record by nodeId and tagId. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + /// Throws TagNotFound if the tag does not exist. + /// Does not start a transaction (prefix __) + const HvsTagRecord __findTagRecord( UInt32 nodeId, + UInt32 tagId ) const; + + /// Create a relation between tags for a pair of parent/child nodes. + /// Create the parent tag in the parent node if not defined yet. + /// Create the child tag in the child node if not defined yet. + /// Throws ReservedHeadTag if one of the two tags is a HEAD tag. + /// Throws NodeIsSingleVersion if either node does not support versioning. + /// Throws NodeRelationNotFound if the nodes are not parent and child. + /// Throws TagExists if either tag is already used in another node. + /// Throws TagRelationExists if a relation to a child tag already exists. + void createTagRelation( UInt32 parentNodeId, + const std::string& parentTagName, + UInt32 childNodeId, + const std::string& childTagName ) const; + + /// Delete the relation between a parent tag node and a child tag. + /// Delete the parent tag if not related to another parent/child tag. + /// - NOT Delete the child tag if not related to another tag or IOVs. + /// Throws ReservedHeadTag if the parent tag is a HEAD tag. + /// Throws TagNotFound if the parent tag does not exist in the parent node. + /// Throws TagRelationNotFound if the parent tag has no related child tag. + /// - NEW returns the id of the deleted childTagId + //void + UInt32 deleteTagRelation( UInt32 parentNodeId, + const std::string& parentTagName, + UInt32 childNodeId ) const; + + /// Delete the relation between a parent tag node and a child tag. + /// Delete the parent tag if not related to another parent/child tag. + /// Delete the child tag if not related to another tag or IOVs. + /// Throws ReservedHeadTag if the parent tag is a HEAD tag. + /// Throws TagNotFound if the parent tag does not exist in the parent node. + /// Throws TagRelationNotFound if the parent tag has no related child tag. + void deleteTagRelation( const RelationalHvsNode& childNode, + const std::string& parentTagName ) const; + + /// Find the child node tag associated to the given parent node tag. + /// Throws ReservedHeadTag if the parent tag is a HEAD tag. + /// Throws TagNotFound if the parent tag does not exist in the parent node. + /// Throws TagRelationNotFound if the parent tag has no related child tag. + UInt32 findTagRelation( UInt32 parentNodeId, + const std::string& parentTagName, + UInt32 childNodeId ) const; + + /// Main HVS method: determine the descendant node tag that is related to + /// the given ancestor tag (assumed to be defined in an ancestor node). + /// The corresponding ancestor node is also internally determined. + /// The ancestor tag is returned if defined directly in the descendant. + /// Throws ReservedHeadTag if the ancestor tag is a HEAD tag. + /// Throws TagNotFound if the tag does not exist in any inner node. + /// Throws NodeRelationNotFound if the inner node where the ancestor tag + /// is defined is not an ancestor of the descendant node. + /// Throws TagRelationNotFound if no hierarchical tag relation exists. + UInt32 resolveTag( const std::string& ancestorTagName, + UInt32 descendantNodeId ) const; + + /// Fetch the global tag table row for the given tagName. + /// Throws TagNotFound if the tag does not exist in any node. + const RelationalTableRow + fetchGlobalTagTableRowForNode( const std::string& tagName ) const; + + /// Fetch all global tag table rows for the given nodeId. + const std::vector<RelationalTableRow> + fetchGlobalTagTableRows( UInt32 nodeId ) const; + + /// Fetch all global tag table rows for the given tagName. + /// Throws TagNotFound if the tag does not exist in any node. + const std::vector<RelationalTableRow> + fetchGlobalTagTableRows( const std::string& tagName ) const; + + /// Fetch the global tag table row for the given nodeId and tagName + const RelationalTableRow + fetchGlobalTagTableRow( UInt32 nodeId, + const std::string& tagName ) const; + + /// Fetch the global tag table row for the given nodeId and tagId + const RelationalTableRow + fetchGlobalTagTableRow( UInt32 nodeId, + UInt32 tagId ) const; + + /// Insertion time of a tag defined for the given node + /// (i.e. the time when the tag was first assigned to the node). + const Time tagInsertionTime( const IHvsNode* node, + const std::string& tagName ) const; + + /// Description of a tag defined for the given node. + const std::string tagDescription( const IHvsNode* node, + const std::string& tagName ) const; + + /// Lock status of a tag defined for the given node. + void setTagLockStatus( const IHvsNode* node, + const std::string& tagName, + HvsTagLock::Status tagLockStatus ); + + /// Lock status of a tag defined for the given node. + HvsTagLock::Status tagLockStatus( const IHvsNode* node, + const std::string& tagName ) const; + + /// This method does not handle transactions. + /// Find a tag in an HVS node, else create it if it does not exist yet. + const HvsTagRecord findOrCreateTag( UInt32 nodeId, + const std::string& tagName ) const; + + /// TEMPORARY! Also fill the local tag table until it is removed. + /// This method does not handle transactions. + /// Create a tag in an HVS node. + /// Throws TagExists if the tag already exists (in this or another node). + const HvsTagRecord createTag( UInt32 nodeId, + const std::string& tagName, + const std::string& description = "" ) const; + + /// TEMPORARY! Remove this method when the local tag table is removed. + /// Internal method. + const HvsTagRecord createTagAndLocalTag + ( UInt32 nodeId, + const std::string& tagName, + const std::string& description, + const std::string& localTagTableName ) const; + + /// This method does not handle transactions. + /// Delete a tag in an HVS node. + void deleteTag( UInt32 nodeId, + const std::string& tagName ) const; + + /// Create a new entry in the global tag table. + void insertGlobalTagTableRow( UInt32 nodeId, + UInt32 tagId, + const std::string& tagName, + HvsTagLock::Status tagLockStatus, + const std::string& tagDescription, + const std::string& insertionTime ) const; + + /// Delete the row indicated by nodeId and tagId from the global tag table. + void deleteGlobalTagTableRow( UInt32 nodeId, + UInt32 tagId ) const; + + /// Delete all rows for nodeId from the global tag table. + /// Returns the number of deleted rows. + UInt32 deleteGlobalTagTableRowsForNode( const UInt32 nodeId ) const; + + /// TEMPORARY! The local tag table must be removed! + /// Creates a new entry in the given local tag table + /// Returns the tag id of the new entry + void insertTagTableRow( const std::string& tagTableName, + UInt32 tagId, + const std::string& tagName, + const std::string& description, + const std::string& insertionTime ) const; + + /// TEMPORARY! The local tag table must be removed! + /// Delete the row indicated by tagId from the given local tag table. + void deleteTagTableRow( const std::string& tagTableName, + UInt32 tagId ) const; + + /// Does this user tag exist in the tag2tag table? + bool existsTagInTag2TagTable( UInt32 nodeId, + UInt32 tagId ) const; + + /* + /// Does this tag defined in this node have any relation (i.e. does + /// it reference a parent tag or is it referenced by any children)? + /// Returns false if this tag does not exist in this node. + bool isTagUsed( UInt32 nodeId, + UInt32 tagId ) const; + */ + + /// Delete all rows for the given node from the tag2tag table. + UInt32 deleteTag2TagTableRowsForNode( const UInt32 nodeId ) const; + + /// Set the description of a tag. + /// Throws TagNotFound the tag does not exist. + /// Throws an Exception if the description is longer than 255 characters. + void setTagDescription( const IHvsNode* node, + const std::string& tagName, + const std::string& description ); + + + protected: + + /// Get the RelationalDatabase reference + const RelationalDatabase& db() const { return m_db; } + + /// Get a CORAL MessageStream + coral::MessageStream& log() const { return *m_log; } + + /// Get a relational query manager + RelationalQueryMgr& queryMgr() const; + + /// Get a relational node manager + RelationalNodeMgr& nodeMgr() const; + + private: + + /// Standard constructor is private + RelationalTagMgr(); + + /// Copy constructor is private + RelationalTagMgr( const RelationalTagMgr& rhs ); + + /// Assignment operator is private + RelationalTagMgr& operator=( const RelationalTagMgr& rhs ); + + /// Create a new row in the tag2tag table. + void insertTag2TagTableRow( UInt32 parentNodeId, + UInt32 parentTagId, + UInt32 childNodeId, + UInt32 childTagId, + const std::string& insertionTime ) const; + + /// Fetch the given row from the tag2tag table. + /// Throw RowNotFound if no row was found. + const RelationalTableRow + fetchTag2TagTableRow( UInt32 parentNodeId, + UInt32 parentTagId, + UInt32 childNodeId ) const; + + /// Delete the given row row in the tag2tag table. + /// Throw RowNotDeleted if no row was deleted. + void deleteTag2TagTableRow( UInt32 parentNodeId, + UInt32 parentTagId, + UInt32 childNodeId ) const; + + protected: + + /// Reference to the RelationalDatabase + const RelationalDatabase& m_db; + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALTAGMGR_H + diff --git a/RelationalCool/src/RelationalTagSequence.h b/RelationalCool/src/RelationalTagSequence.h new file mode 100644 index 000000000..d4b9ad6e2 --- /dev/null +++ b/RelationalCool/src/RelationalTagSequence.h @@ -0,0 +1,30 @@ +// $Id: RelationalTagSequence.h,v 1.2 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALTAGSEQUENCE_H +#define RELATIONALCOOL_RELATIONALTAGSEQUENCE_H + +// Local include files +#include "RelationalTagTable.h" + +namespace cool { + + /** @namespace cool::RelationalTagSequence RelationalTagSequence.h + * + * Properties of the COOL "sequence" for local tag ID's in each node. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2006-03-28 + */ + + namespace RelationalTagSequence { + + inline const std::string sequenceName( const std::string& prefix, + unsigned nodeId ) + { + return RelationalTagTable::defaultTableName( prefix, nodeId ) + "_SEQ"; + } + + } + +} + +#endif // RELATIONALCOOL_RELATIONALTAGSEQUENCE_H diff --git a/RelationalCool/src/RelationalTagSharedSequenceTable.h b/RelationalCool/src/RelationalTagSharedSequenceTable.h new file mode 100644 index 000000000..fb127a11c --- /dev/null +++ b/RelationalCool/src/RelationalTagSharedSequenceTable.h @@ -0,0 +1,30 @@ +// $Id: RelationalTagSharedSequenceTable.h,v 1.1 2007-02-01 00:28:33 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALTAGSHAREDSEQUENCETABLE_H +#define RELATIONALCOOL_RELATIONALTAGSHAREDSEQUENCETABLE_H + +// Local include files +#include "uppercaseString.h" + +namespace cool { + + /** @namespace cool::RelationalTagSharedSequenceTable RelationalTagSharedSequenceTable.h + * + * Relational schema of the shared 'sequence table' for tag PKs. + * + * @author Andrea Valassi + * @date 2007-01-31 + */ + + namespace RelationalTagSharedSequenceTable + { + + inline const std::string defaultTableName( const std::string& prefix ) + { + // Note: presently the input prefix is uppercase anyway... + return uppercaseString(prefix) + "TAGS_SEQ"; + } + + } + +} +#endif // RELATIONALCOOL_RELATIONALTAGSHAREDSEQUENCETABLE_H diff --git a/RelationalCool/src/RelationalTagTable.cpp b/RelationalCool/src/RelationalTagTable.cpp new file mode 100644 index 000000000..24288c9a9 --- /dev/null +++ b/RelationalCool/src/RelationalTagTable.cpp @@ -0,0 +1,32 @@ +// $Id: RelationalTagTable.cpp,v 1.6 2006-09-26 22:44:09 avalassi Exp $ + +// Include files +#include "CoolKernel/RecordSpecification.h" + +// Local include files +#include "RelationalTagTable.h" + +//----------------------------------------------------------------------------- + +const cool::IRecordSpecification& +cool::RelationalTagTable::tableSpecification() +{ + + static RecordSpecification spec; + + if ( spec.size() == 0 ){ + spec.extend( RelationalTagTable::columnNames::tagId, + RelationalTagTable::columnTypeIds::tagId ); + spec.extend( RelationalTagTable::columnNames::tagName, + RelationalTagTable::columnTypeIds::tagName ); + spec.extend( RelationalTagTable::columnNames::tagDescription, + RelationalTagTable::columnTypeIds::tagDescription ); + spec.extend( RelationalTagTable::columnNames::sysInsTime, + RelationalTagTable::columnTypeIds::sysInsTime ); + } + + return spec; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/src/RelationalTagTable.h b/RelationalCool/src/RelationalTagTable.h new file mode 100644 index 000000000..3a01f85b7 --- /dev/null +++ b/RelationalCool/src/RelationalTagTable.h @@ -0,0 +1,64 @@ +// $Id: RelationalTagTable.h,v 1.15 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALTAGTABLE_H +#define RELATIONALCOOL_RELATIONALTAGTABLE_H + +// Local include files +#include "uppercaseString.h" + +namespace cool { + + // Forward declarations + class IRecordSpecification; + + /** @namespace cool::RelationalTagTable RelationalTagTable.h + * + * Relational schema of the table storing COOL local tags. + * + * @author Andrea Valassi, Sven A. Schmidt and Marco Clemencic + * @date 2005-02-05 + */ + + namespace RelationalTagTable { + + inline const std::string defaultTableName + ( const std::string& prefix, unsigned nodeId ) { + char tableName[] = "Fxxxx_TAGS"; + sprintf( tableName, "F%4.4i_TAGS", nodeId ); + return uppercaseString( prefix ) + std::string( tableName ); + } + + inline const std::string sequenceName( const std::string& tableName ) { + return uppercaseString(tableName) + "_SEQ"; + } + + namespace columnNames { + static const std::string tagId = "TAG_ID"; + static const std::string tagName = "TAG_NAME"; + static const std::string tagDescription = "TAG_DESCRIPTION"; + static const std::string sysInsTime = "SYS_INSTIME"; + } + + namespace columnTypeIds { + static const StorageType::TypeId tagId = StorageType::UInt32; + static const StorageType::TypeId tagName = StorageType::String255; + static const StorageType::TypeId tagDescription = StorageType::String255; + // TEMPORARY! Should be Time? + static const StorageType::TypeId sysInsTime = StorageType::String255; + } + + namespace columnTypes { + typedef UInt32 tagId; + typedef String255 tagName; + typedef String255 tagDescription; + // TEMPORARY! Should be Time? + typedef String255 sysInsTime; + } + + /// Get the RecordSpecification of the tag table + const IRecordSpecification& tableSpecification(); + + } + +} + +#endif // RELATIONALCOOL_RELATIONALTAGTABLE_H diff --git a/RelationalCool/src/RelationalTransaction.cpp b/RelationalCool/src/RelationalTransaction.cpp new file mode 100644 index 000000000..eceb8e97d --- /dev/null +++ b/RelationalCool/src/RelationalTransaction.cpp @@ -0,0 +1,56 @@ +// $Id: RelationalTransaction.cpp,v 1.5 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include <string> + +// Local include files +#include "IRelationalTransactionMgr.h" +#include "RelationalTransaction.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RelationalTransaction::RelationalTransaction +( const boost::shared_ptr<IRelationalTransactionMgr>& transactionMgr, + bool readOnly ) + : m_transactionMgr( transactionMgr ) +{ + std::string msg; + if( readOnly ) msg = "read-only transaction"; + else msg = "read-write transaction"; + //m_transactionMgr->log() << "Start a new " << msg << seal::flush; + m_transactionMgr->start( readOnly ); +} + +//----------------------------------------------------------------------------- + +RelationalTransaction::~RelationalTransaction() +{ + rollback(); +} + +//----------------------------------------------------------------------------- + +void RelationalTransaction::commit() +{ + //m_transactionMgr->log() << "Commit any open transaction" << seal::flush; + if ( m_transactionMgr->isActive() ) { + m_transactionMgr->commit(); + } +} + +//----------------------------------------------------------------------------- + +void RelationalTransaction::rollback() +{ + //m_transactionMgr->log() << "Rollback any open transaction" << seal::flush; + if ( m_transactionMgr->isActive() ) { + m_transactionMgr->rollback(); + } +} + +//----------------------------------------------------------------------------- + + diff --git a/RelationalCool/src/RelationalTransaction.h b/RelationalCool/src/RelationalTransaction.h new file mode 100644 index 000000000..f8972376b --- /dev/null +++ b/RelationalCool/src/RelationalTransaction.h @@ -0,0 +1,66 @@ +// $Id: RelationalTransaction.h,v 1.9 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALTRANSACTION_H +#define RELATIONALCOOL_RELATIONALTRANSACTION_H + +// Include files +#include <boost/shared_ptr.hpp> + +namespace cool +{ + + // Forward declarations + class IRelationalTransactionMgr; + + /** @class RelationalTransaction RelationalTransaction.h + * + * Generic implementation of a relational database transaction. + * + * A transaction is started when this class is instantiated. + * + * An explicit commit() call is necessary for committing the transaction. + * When the instance goes out of scope, the transaction is rolled back. + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2006-03-10 + */ + + class RelationalTransaction + { + + public: + + /// Destructor + virtual ~RelationalTransaction(); + + /// Constructor from a IRelationalTransactionMgr + RelationalTransaction + ( const boost::shared_ptr<IRelationalTransactionMgr>& transactionMgr, + bool readOnly = false ); + + /// Commit the transaction + void commit(); + + /// Rollback the transaction + void rollback(); + + private: + + /// Standard constructor is private + RelationalTransaction(); + + /// Copy constructor is private + RelationalTransaction( const RelationalTransaction& rhs ); + + /// Assignment operator is private + RelationalTransaction& operator=( const RelationalTransaction& rhs ); + + private: + + /// Handle to the IRelationalTransactionMgr (shared ownership) + boost::shared_ptr<IRelationalTransactionMgr> m_transactionMgr; + + }; + +} // namespace + +#endif diff --git a/RelationalCool/src/SealBase_TimeInfo.cpp b/RelationalCool/src/SealBase_TimeInfo.cpp new file mode 100644 index 000000000..4f4604057 --- /dev/null +++ b/RelationalCool/src/SealBase_TimeInfo.cpp @@ -0,0 +1,413 @@ +//<<<<<< INCLUDES >>>>>> + +#include "SealBase_TimeInfo.h" + +// ========================================================================== +// #include "SealBase/sysapi/TimeInfo.h" +# include <cerrno> +# ifdef _WIN32 +# include <windows.h> +# include <time.h> +# else +# include <unistd.h> +# include <fcntl.h> +# include <sys/time.h> +# include <time.h> +# include <sys/times.h> +# include <sys/sysctl.h> +# include <sys/resource.h> +# endif +# include <limits.h> +# include <stdio.h> +# include <string.h> +# include <stdlib.h> + +// A gross hack for linux which lies that CLK_TCK is 1000000 when the +// values are really 100. +# ifdef __linux +# undef CLK_TCK +# define CLK_TCK 100 +# endif + +// ========================================================================== +#include "SealBase_sysapi_Windows.h" + +// see also http://high-res-timers.sourceforge.net/; linux kernel +// (arch/*/kernel/time.c; search get_cycles()); netbsd kernel; +// http://pdplab.trc.rwcp.or.jp/pdperf/timer-collection/; papi +// (http://icl.cs.utk.edu/projects/papi); gnu nana. + +namespace seal { + +bool TimeInfo::s_initialised = false; +unsigned TimeInfo::s_features = 0; +double TimeInfo::s_ghz = 1.; +TimeInfo::NanoSecs TimeInfo::s_clockBase = 0; +double TimeInfo::s_hiResFactor = 1.0; + +/** Initialise high-resolution time measurement system. + + Determines the processor speed and/or clock resolution. You + should call this method before calling the cycle counter methods + (direct cycle counters or the nanosecond counterparts), or the + process time methods. It is safe to call this more than once; all + but the first call are ignored. + + This method (and subsequenty the high-resolution timers) will give + incorrect results on multi-processor systems that have processors + running at different frequencies. + + Records also the current #time() value such that #elapsedTime() + can be used to measure monotonic time if the system has no process + time accounting. If a precise process start time is available, + records that as the time base instead of the current #time(). + + On systems where other means to determine cpu speed fail, uses a + calibration spin loop that takes approximately half a second. */ +void +TimeInfo::init (void) +{ + if (s_initialised) + return; + + // Get process real time base for #elapsedTime() and process + // idle time calculations. Note: we want this to be the first + // thing we check, since the other things below may take time + // (like the calibration loop). + // + // Assume first that no start time available from the system: + // subtract current #processCpuTime() from current #time() + // (assumed to use the same epoch!). This will work reasonably + // well if you call #init() early in the program: hopefully the + // process will not have idled for too long during the start-up + // (though it may have if there are many shared libraries and it + // takes a long time to load them, for example due to loading them + // from a networked file system). Note that #processTimes() may + // use s_clockBase but that's fine since s_clockBase is + // currently zero anyway. + s_clockBase = time () - processCpuTime (); + +#ifdef __linux + bool haveBase = false; + FILE *status = 0; + if (! haveBase && (status = fopen ("/proc/self/stat", "r"))) + { + // Linux. 22nd field is process starttime %d; the first is + // pid, then process name in parens; the rest of the fields + // are simple values separated by spaces. Skip the process + // name by hand since it may contain spaces (it might also + // contain parens, so we may still get things wrong). + // Hopefully future versions do not change the format... + static const int START_TIME_FIELD = 22; + int field = 1; + int ch = 0; + int start; + + // skip first field + while (ch != EOF && ch != ' ') + ch = fgetc (status); + ++field; + + // skip process name + if ((ch = fgetc (status)) != '(') + ch = EOF; + + while (ch != EOF && ch != ')') + ch = fgetc (status); + + if ((ch = fgetc (status)) != ' ') + ch = EOF; + ++field; + + // skip the other fields in between + for ( ; ch != EOF && field < START_TIME_FIELD; ++field) + while ((ch = fgetc (status)) != EOF && ch != ' ') + ; + + // get the start time + if (ch != EOF && fscanf (status, "%d", &start) == 1) + { + haveBase = true; + s_clockBase = start * (1e9 / CLK_TCK); + } + + // done, ignore the rest + fclose (status); + } +#endif // __linux + + // Compute various feature bits + s_features |= FEATURE_TIME_EPOCH; + s_features |= FEATURE_REAL_COUNT_EPOCH; + s_features |= FEATURE_PROCESS_TIMES; + +#ifdef __linux + // Try to determine CPU speed (linux): look for a "cpu MHz : + // <float>" line. + if (FILE *cpu = fopen("/proc/cpuinfo", "r")) + { + char buf [512]; + while (fgets (buf, sizeof (buf), cpu)) + if (!strncmp (buf, "cpu MHz", 7)) + if (char *colon = strchr (buf, ':')) + { + s_features |= FEATURE_EXACT_MHZ; + s_ghz = atof (colon + 1) / 1000.; + s_hiResFactor = 1e9 / s_ghz; + break; + } + + fclose (cpu); + } +#elif defined _WIN32 // (windows) + if (! (s_features & FEATURE_EXACT_MHZ)) + { + size_t sz; + SYSTEM_INFO si; + PROCESSOR_POWER_INFORMATION *info; + LARGE_INTEGER freq; + + // Determine cpu clock speed. Assume all cpus run at roughly + // the same clock speed and that we only care about the full + // clock rate -- not whatever the os might have lowered it to. + GetSystemInfo (&si); + sz = si.dwNumberOfProcessors * sizeof (PROCESSOR_POWER_INFORMATION); + info = new PROCESSOR_POWER_INFORMATION [si.dwNumberOfProcessors]; + if (CallNtPowerInformation (ProcessorInformation, 0, 0, info, sz) == STATUS_SUCCESS) + { + s_features |= FEATURE_EXACT_MHZ; + s_ghz = info [0].MaxMhz / 1e3; + } + delete [] info; + + // Get cycles/tick multiplier + QueryPerformanceFrequency (&freq); + s_hiResFactor = freq.QuadPart / (s_ghz * 1e9); + } +#endif + // There is no way to get a cpu speed estimate: we can't get real + // cpu cycle counts to run a calibration loop, nor can we get the + // info from the operation system. Just say we are running at one + // gigahertz as this will translate the system timing information + // best to cycles. It won't be true, but hey, you can extend the + // code above to deal better with your system and at least we are + // not losing any timing data. (The setting to a gigahertz + // already took place in the s_ghz initialiser.) + + s_initialised = true; +} + +/** Return the processor speed in megahertz as determined by #init(). */ +double +TimeInfo::mhz (void) +{ return s_ghz * 1000.; } + +/** Return the processor speed in gigahertz as determined by #init(). */ +double +TimeInfo::ghz (void) +{ return s_ghz; } + +/** Return the system capabilities as determined by #init(). */ +unsigned +TimeInfo::features (void) +{ return s_features; } + +/** Return high-resolution, monotonic system time in nanoseconds from + some system- or process-dependent epoch. Not dependent on + #init(). */ +TimeInfo::NanoSecs +TimeInfo::time (void) +{ +#ifndef _WIN32 + struct tms now; return times (&now) * (1e9 / CLK_TCK); +#else + // Do not use process-relative time: we probably can't measure real + // time anyway (only user + system), and even if we can, we'll end + // up using each other to calcuate the idle time. FIXME: WIN32? + return clock () * (1e9 / CLOCKS_PER_SEC); +#endif +} + +/** Return high-resolution monotonic virtual time in nanoseconds: like + #realNsecs() except counts time only for this process. + + Like with the real-time counterparts, do not mix #virtualNsecs() + and #virtualCycles() assuming you can directly map one to the + other. You can still of course convert cycles to nanosecond + estimates using #ghz(). + + The return value is monotonically growing time in nanoseconds from + some system dependent epoch (possibly the process start-up). + Unlike #realNsecs(), monotonicity is guaranteed since time is + only counted for this process. Not all systems can provide this + information and always return zero. */ +//TimeInfo::NanoSecs +//TimeInfo::virtualNsecs (void) +//{ +//#if HAVE_GETHRTIME // (solaris) +// return gethrvtime (); +//#elif HAVE_CPU_VIRTUAL_CYCLE_COUNTER +// return virtualCycles () / s_ghz; +//#elif HAVE_CLOCK_GETTIME && HAVE_CLOCK_PROCESS_CPUTIME_ID +// // FIXME: CLOCK_THREAD_CPUTIME_ID? +// struct timespec now; clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &now); +// return (now.tv_sec * 1e9) + now.tv_nsec; +//#elif HAVE_CLOCK_GETTIME && HAVE_CLOCK_PROFILE // (hp-ux) +// struct timespec now; clock_gettime (CLOCK_PROFILE, &now); +// return (now.tv_sec * 1e9) + now.tv_nsec; +//#elif HAVE_CLOCK_GETTIME && HAVE_CLOCK_PROF // (darwin) +// struct timespec now; clock_gettime (CLOCK_PROF, &now); +// return (now.tv_sec * 1e9) + now.tv_nsec; +//#else +// return processCpuTime (); +//#endif +//} + +/** Return high-resolution monotonic virtual time in CPU cycle ticks: + like #realCycles() except counts ticks only for this process. + + Like with the real-time counterparts, do not mix #virtualNsecs() + and #virtualCycles() assuming you can directly map one to the + other. You can still of course convert cycles to nanosecond + estimates using #ghz(). + + The return value is monotonically growing time in CPU cycles from + some system dependent epoch (possibly the process startup). + Unlike #realCycles(), monotonicity is guaranteed since time is + only counted for this process. Not all systems can provide this + information and always return zero. */ +//TimeInfo::NanoTicks +//TimeInfo::virtualCycles (void) +//{ +//#if defined CPU_VIRTUAL_CYCLES_ASM // (gcc on alpha) +// unsigned low, high; NanoTicks time; __asm__ volatile (CPU_VIRTUAL_CYCLES_ASM); +// return CPU_VIRTUAL_CYCLES_VALUE; +//#else +// // #elif HAVE_PMAPI_H +// // Use the pmapi (aix) calls to get events (see real_cycles). +// +// // #elif HAVE_SYS_PSTAT_H +// // // pst_cpticks seems always empty so use the clock_gettime above +// // pst_status stat; pstat_getproc (&stat, sizeof (stat), 0, getpid()); +// // return stat.pst_cpticks; +// return (NanoTicks) (virtualNsecs () * s_ghz); +//#endif +//} + +////////////////////////////////////////////////////////////////////// +/** Get all process time statistics in one go. + + Sets @a user, @a system and @a real to the amount of CPU time + consumed by the process in user mode, on its behalf in the kernel, + and in real time, respectively. The real time is monotonic real + time, not system wall clock time. All times are in nanoseconds. + + Not all systems can provide this information. On such systems @a + real will equal to #elapsedTime() and user and system times will + be reported to be zero (resulting all time to be reported to be + idle). */ +void +TimeInfo::processTimes (NanoSecs &user, NanoSecs &system, NanoSecs &real) +{ +#ifndef _WIN32 + // HP-UX has clock_gettime with CLOCK_VIRTUAL (user time) and + // CLOCK_PROFILE (user + system time) with nsec accuracy, but to + // use them we would have to call clock_gettime twice and then + // times to get real time so don't bother and get them all through + // times -- AFAIK HP-UX only counts clock ticks anyway. + // + // Note that on linux and hp-ux s_clockBase is precise. Other + // systems resort to estimated real time based on call to init. + struct tms now; real = times (&now) * (1e9 / CLK_TCK); + user = now.tms_utime * (1e9/CLK_TCK); + system = now.tms_stime * (1e9/CLK_TCK); + real -= s_clockBase; +#else + // Real time will be based on an estimate from call to init; the + // start time reported by GetProcessTimes is based on system wall + // clock and can't be trusted to be monotonic. + FILETIME ftdummy, ftkernel, ftuser; + GetProcessTimes (GetCurrentProcess (), &ftdummy, &ftdummy, + &ftkernel, &ftuser); + NanoSecs now = time (); + system = static_cast<NanoSecs>( + (((NanoTicks) ftkernel.dwHighDateTime << 32) + + ftkernel.dwLowDateTime) * 100); + user = static_cast<NanoSecs>( + (((NanoTicks) ftuser.dwHighDateTime << 32) + + ftuser.dwLowDateTime) * 100); + real = now - s_clockBase; +#endif +} + +/** Get user time consumed by the process in nanoseconds. + + Not all systems can provide this information. On such systems + #processRealTime() will equal to #elapsedTime() and user and + system times will be reported to be zero (resulting all time to be + reported to be idle). */ +TimeInfo::NanoSecs +TimeInfo::processUserTime (void) +{ + NanoSecs user, system, real; + processTimes (user, system, real); + return user; +} + +/** Get system time consumed by the process in nanoseconds. + + Not all systems can provide this information. On such systems + #processRealTime() will equal to #elapsedTime() and user and + system times will be reported to be zero (resulting all time to be + reported to be idle). */ +TimeInfo::NanoSecs +TimeInfo::processSystemTime (void) +{ + NanoSecs user, system, real; + processTimes (user, system, real); + return system; +} + +/** Get process cpu time (user + system) in nanoseconds. + + Not all systems can provide this information. On such systems + #processRealTime() will equal to #elapsedTime() and user and + system times will be reported to be zero (resulting all time to be + reported to be idle). */ +TimeInfo::NanoSecs +TimeInfo::processCpuTime (void) +{ + NanoSecs user, system, real; + processTimes (user, system, real); + return user + system; +} + +/** Get process idle time in nanoseconds. + + Not all systems can provide this information. On such systems + #processRealTime() will equal to #elapsedTime() and user and + system times will be reported to be zero (resulting all time to be + reported to be idle). */ +TimeInfo::NanoSecs +TimeInfo::processIdleTime (void) +{ + NanoSecs user, system, real; + processTimes (user, system, real); + return real - (user + system); +} + +/** Get process real time in nanoseconds. + + The process real time is the time from the process start up to now + according to the monotonic system clock. On some systems this + information is not available and equals to #elapsedTime() (that + is, an estimate based on the first call to #init()). */ +TimeInfo::NanoSecs +TimeInfo::processRealTime (void) +{ + NanoSecs user, system, real; + processTimes (user, system, real); + return real; +} + +} // namespace seal diff --git a/RelationalCool/src/SealBase_TimeInfo.h b/RelationalCool/src/SealBase_TimeInfo.h new file mode 100644 index 000000000..1b6d52ade --- /dev/null +++ b/RelationalCool/src/SealBase_TimeInfo.h @@ -0,0 +1,135 @@ +#ifndef SEAL_BASE_TIME_INFO_H +# define SEAL_BASE_TIME_INFO_H + +//<<<<<< INCLUDES >>>>>> + +#include "CoolKernel/types.h" + +namespace seal { +//<<<<<< PUBLIC DEFINES >>>>>> +//<<<<<< PUBLIC CONSTANTS >>>>>> +//<<<<<< PUBLIC TYPES >>>>>> +//<<<<<< PUBLIC VARIABLES >>>>>> +//<<<<<< PUBLIC FUNCTIONS >>>>>> +//<<<<<< CLASS DECLARATIONS >>>>>> + +/** Utilities for monotonically growing high-resolution timers. + + This class provides access to, among other things, virtual and + real nanosecond-resolution timing info. The implementation does + its best to use the cheapest, most trustworthy time calculation + method: system-provided high-resolution clocks or reading CPU + cycle counters directly. If those are not available, falls back + to whatever is likely to produce the best data on the system, + usually a system call that promises best resolution. + + On systems that do provide accurate monotonic process-specific or + system-wide high-resolution clocks (e.g. POSIX CLOCK_MONOTONIC and + CLOCK_PROCESS_CPUTIME_ID clocks), they are used in preference to CPU + cycle counters. If no such clock is available, the monotonicity + cannot always be guaranteed: + - On a SMP system the process may hop from one processor to + another, reading cycle counters on different CPUs. + - Most multi-processor systems allow CPUs to be taken offline and + put back online at any time. The cycle counters may be reset + or slowed down while the processor is offline. + - Advanced power saving features can slow down CPU clock rates or + put processes or the whole system to sleep or suspend mode. In + such a case the returned cycle counts may still be accurate but + cannot be converted to nanoseconds meaningfully. At any rate + it is usually impossible to find out when this has happened. + In fact the clock speed reported by the system may not even be + right if something (e.g. the user) has put the system in a + power-conserving mode that has slowed down the CPU clock rate + -- the CPU clock rate may be wrong for the whole duration of + the program. + + In most of these cases it is anybody's guess what the timers read + after such an event. Most likely the readings are not linear. + + The clock ticks are represented as a 64-bit signed integral type + (see #NanoTicks). Nanosecond times are represented as a double + (see #NanoSecs). This accomodates some 290 years worth of cycle + counter ticks on a 1GHz CPU. Cycle counters are usually zeroed on + boot, so this should be plenty enough for another few years to + come. Please note however that not all systems provide cycle + counters with this many significant bits. */ +class TimeInfo +{ +public: + // FIXME: feature bits for...? + // - whether real cycles are exact or derived + // - whether real nsecs are exact or derived + // - whether real nsecs were derived from cycles and mhz + // - whether real cycles were derived from nsecs and mhz + // - (the above four for virtual) + // - whether virtual nsecs were derived from process times + // - real/virtual resolution + // - sleep resolution + + /** #feature() bit indicating that #mhz() is the exact value + provided by the system (for the cycle counts vs. nsecs). If + not set, the speed was estimated with a calibration loop. */ + static const int FEATURE_EXACT_MHZ = 1; + + /** #feature() bit indicating that #time() may not be + process-specific but can have system-wide source. */ + static const int FEATURE_TIME_EPOCH = 2; + + /** #feature() bit indicating that #realCycles() and + #realNsecs() can have have system-wide source. */ + static const int FEATURE_REAL_COUNT_EPOCH = 4; + + /** #feature() bit indicating that #processUserTime(), + #processSystemTime() and #processCpuTime() are + meaningful. */ + static const int FEATURE_PROCESS_TIMES = 16; + + /** Type for nanosecond times. */ + typedef double NanoSecs; + + /** Type for cpu cycle counters. */ + typedef cool::Int64 NanoTicks; + + static void init (void); + + static double mhz (void); + static double ghz (void); + static unsigned features (); + + // FIXME: Wall clock/real time support? This really is #Time. + // Would be neat however if we can find out accurate process + // start-up time. Do we need more than just processTimes()? + // + // POSIX systems with clock_gettime() may provide CLOCK_REALTIME + // (= wall), CLOCK_MONOTONIC (= real), CLOCK_PROCESS_CPUTIME_ID (= + // virtual) and CLOCK_THREAD_CPUTIME_ID (= virtual thread-specific) + // -- check. + + // FIXME: Provide estimate of clock read overhead? + + // high-res monotonic process time consumption + static void processTimes (NanoSecs &user, NanoSecs &system, + NanoSecs &real); + static NanoSecs processUserTime (void); + static NanoSecs processSystemTime (void); + static NanoSecs processCpuTime (void); + static NanoSecs processIdleTime (void); + static NanoSecs processRealTime (void); + + // high-res system timer; not (necessarily) anchored to process + // time but guaranteed to be monotonic; usually measures system + // time since boot or something like that. + static NanoSecs time (void); +private: + static bool s_initialised; + static unsigned s_features; + static double s_ghz; + static double s_hiResFactor; + static NanoSecs s_clockBase; +}; + +//<<<<<< INLINE PUBLIC FUNCTIONS >>>>>> + +} // namespace seal +#endif // SEAL_BASE_TIME_INFO_H diff --git a/RelationalCool/src/SealBase_sysapi_TimeInfo.h b/RelationalCool/src/SealBase_sysapi_TimeInfo.h new file mode 100644 index 000000000..2e6577dd1 --- /dev/null +++ b/RelationalCool/src/SealBase_sysapi_TimeInfo.h @@ -0,0 +1,97 @@ +#ifndef SEAL_BASE_SYSAPI_TIME_INFO_H +# define SEAL_BASE_SYSAPI_TIME_INFO_H + +//<<<<<< INCLUDES >>>>>> + +# include "SealBase/config.h" +# include <cerrno> + +// FIXME: use the autoconf logic to include time.h and sys/time.h +# ifdef _WIN32 +# include <windows.h> +# include <time.h> +# else +# include <unistd.h> +# include <fcntl.h> +# if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +# else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +# endif +# if HAVE_SYS_TIMES_H +# include <sys/times.h> +# endif +# if HAVE_SYS_SYSCTL_H +# include <sys/sysctl.h> +# endif +# if HAVE_SYS_PROCESSOR_H +# include <sys/processor.h> +# endif +# if HAVE_SYS_RESOURCE_H +# include <sys/resource.h> +# endif +# if HAVE_PMAPI_H +# include <pmapi.h> +# endif +# if HAVE_INVENT_H +# include <invent.h> +# endif +# if HAVE_MACH_MACH_TIME_H +# include <mach/mach_time.h> +# endif +// #if HAVE_MACHINE_INLINE_H +// # include <machine/inline.h> +// #endif +# if HAVE_SYS_PSTAT_H +# define _PSTAT64 +# include <sys/param.h> +# include <sys/pstat.h> +# endif +# if HAVE_PROCFS_H +# include <procfs.h> +# endif +# endif +# include <limits.h> +# include <stdio.h> +# include <string.h> +# include <stdlib.h> + +//<<<<<< PUBLIC DEFINES >>>>>> + +// A gross hack for linux which lies that CLK_TCK is 1000000 when the +// values are really 100. +# ifdef __linux +# undef CLK_TCK +# define CLK_TCK 100 +# endif + +// Define some helper states to simplify the logic + +#if HAVE_READ_REAL_TIME || defined CPU_REAL_CYCLES_ASM || HAVE_MACH_MACH_TIME_H || defined _WIN32 +# define HAVE_CPU_REAL_CYCLE_COUNTER 1 +#endif + +#if (HAVE_GETHRTIME \ + || (HAVE_CLOCK_GETTIME && HAVE_CLOCK_SGI_CYCLE) \ + || HAVE_CPU_REAL_CYCLE_COUNTER) +# define HAVE_CPU_REAL_TIME_COUNTER 1 +#endif + +#if defined CPU_VIRTUAL_CYCLES_ASM +# define HAVE_CPU_VIRTUAL_CYCLE_COUNTER 1 +#endif + +//<<<<<< PUBLIC CONSTANTS >>>>>> +//<<<<<< PUBLIC TYPES >>>>>> +//<<<<<< PUBLIC VARIABLES >>>>>> +//<<<<<< PUBLIC FUNCTIONS >>>>>> +//<<<<<< CLASS DECLARATIONS >>>>>> +//<<<<<< INLINE PUBLIC FUNCTIONS >>>>>> +//<<<<<< INLINE MEMBER FUNCTIONS >>>>>> + +#endif // SEAL_BASE_SYSAPI_TIME_INFO_H diff --git a/RelationalCool/src/SealBase_sysapi_Windows.h b/RelationalCool/src/SealBase_sysapi_Windows.h new file mode 100644 index 000000000..8628ae24c --- /dev/null +++ b/RelationalCool/src/SealBase_sysapi_Windows.h @@ -0,0 +1,92 @@ +#ifndef SEAL_BASE_SYSAPI_WINDOWS_H +# define SEAL_BASE_SYSAPI_WINDOWS_H + +//<<<<<< INCLUDES >>>>>> + +# ifdef _WIN32 +#if 0 +# include "SealBase/AutoLoad.h" +#endif +# include <windows.h> +extern "C" { +# include <powrprof.h> +} +//# include <ntdef.h> + +//<<<<<< PUBLIC DEFINES >>>>>> + +# define STATUS_SUCCESS ((NTSTATUS) 0x0L) + +//# define NtQueryInformationProcess (*MyNtQueryInformationProcess) +//# define CallNtPowerInformation (*MyCallNtPowerInformation) +//# ifndef GetComputerNameEx +//# ifdef UNICODE +//# define GetComputerNameExW (*MyGetComputerNameExW) +//# else +//# define GetComputerNameExA (*MyGetComputerNameExA) +//# endif +//# endif + + +//<<<<<< PUBLIC CONSTANTS >>>>>> +//<<<<<< PUBLIC TYPES >>>>>> + +// FIXME: This stuff lives in ntddk.h/ntddl.h, but apparently doesn't +// necessarily coexist with windows.h very well. So add the definitions +// we need here. + +enum PROCESSINFOCLASS { + ProcessBasicInformation = 0, + ProcessQuotaLimits = 1, + ProcessVmCounters = 3, + ProcessTimes = 4 +}; + +typedef LONG NTSTATUS; +typedef ULONG KAFFINITY; +typedef LONG KPRIORITY; + +struct PROCESS_BASIC_INFORMATION { + NTSTATUS ExitStatus; // MSDN: PVOID Reserved1; + void *PebBaseAddress; // MSDN: PPEB PebBaseAddress; + KAFFINITY AffinityMask; // MSDN: PVOID Reserved2 [2]; + KPRIORITY PriorityMask; // -- "" -- + ULONG UniqueProcessId; + ULONG InheritedFromUniqueProcessId; // MSDN: PVOID Reserved3 +}; + +typedef struct _PROCESSOR_POWER_INFORMATION { + ULONG Number; + ULONG MaxMhz; + ULONG CurrentMhz; + ULONG MhzLimit; + ULONG MaxIdleState; + ULONG CurrentIdleState; +} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION; + +//<<<<<< PUBLIC VARIABLES >>>>>> +//<<<<<< PUBLIC FUNCTIONS >>>>>> + +// Work around functions we don't have appropriate headers for, or +// don't want to force everyone to know which libraries to link against. +#if 0 +extern seal::AutoLoadLib WinStubNTDLL; +extern seal::AutoLoadLib WinStubKernel32; +extern seal::AutoLoadLib WinStubPowrprof; +extern seal::AutoLoad<NTSTATUS (HANDLE hProcess, PROCESSINFOCLASS pic, + PVOID pi, ULONG len, PULONG plen)> + MyNtQueryInformationProcess; +extern seal::AutoLoad<NTSTATUS (POWER_INFORMATION_LEVEL level, PVOID pin, + ULONG nin, PVOID pout, ULONG nout)> + MyCallNtPowerInformation; +extern seal::AutoLoad<BOOL (COMPUTER_NAME_FORMAT fmt, LPWSTR name, LPDWORD size)> + MyGetComputerNameExW; +extern seal::AutoLoad<BOOL (COMPUTER_NAME_FORMAT fmt, LPSTR name, LPDWORD size)> + MyGetComputerNameExA; +#endif +//<<<<<< CLASS DECLARATIONS >>>>>> +//<<<<<< INLINE PUBLIC FUNCTIONS >>>>>> +//<<<<<< INLINE MEMBER FUNCTIONS >>>>>> + +# endif // _WIN32 +#endif // SEAL_BASE_SYSAPI_WINDOWS_H diff --git a/RelationalCool/src/SealUtil_BaseSealChrono.h b/RelationalCool/src/SealUtil_BaseSealChrono.h new file mode 100644 index 000000000..059c553a9 --- /dev/null +++ b/RelationalCool/src/SealUtil_BaseSealChrono.h @@ -0,0 +1,46 @@ +// Project : LCG +// Package : SealUtil +// Author : Lorenzo.MONETA@cern.ch +// Created by: moneta at Tue Sep 2 16:03:40 2003 + +#ifndef SEALUTIL_BASESEALCHRONO_H +#define SEALUTIL_BASESEALCHRONO_H 1 + + +#include <string> +#include <vector> + +namespace seal +{ + +/** + * Basic class for Seal Chronos used by timers and TimingReport + */ +class BaseSealChrono +{ + +public: + + virtual ~BaseSealChrono() {} + + + virtual void start() = 0; + + virtual void stop() = 0; + + virtual std::vector<std::string> names() const = 0; + + virtual std::vector<double> values() const = 0; + + virtual unsigned int nTypes() const = 0; + + + enum UnitType { NANOSECONDS = 0, SECONDS = 1, CLOCKTICKS = 2 }; + //values is nanoseconds + + virtual unsigned int timeUnit() { return BaseSealChrono::NANOSECONDS; } + +}; + +} // end namespace SealUtil +#endif diff --git a/RelationalCool/src/SealUtil_SealTimer.cpp b/RelationalCool/src/SealUtil_SealTimer.cpp new file mode 100644 index 000000000..461142e5f --- /dev/null +++ b/RelationalCool/src/SealUtil_SealTimer.cpp @@ -0,0 +1,101 @@ +// Project : LCG +// Package : SealUtil +// Author : Lorenzo.MONETA@cern.ch +// Created by: moneta at Fri Aug 29 16:05:03 2003 + + +#include "TimingReport.h" +#include "SealUtil_BaseSealChrono.h" +#include "SealUtil_SealTimer.h" + +namespace seal +{ + + // construct only from string. Use default SealChrono + // + +/* + SealTimer::SealTimer(const std::string & itemName, bool printResult, std::ostream & out) : + m_printResult(printResult), + m_out(out), + m_ownItem(true), + m_default_chrono(0) +{ + // construct a time report item + m_default_chrono = new SealChrono(); + m_item = new TimingItem(*m_default_chrono,itemName); + // need to add to TimingReport + start(); +} +*/ + // construct from string and chrono + // (item in this case is local and will be destroyed at the end of the loop ) + // + + + SealTimer::SealTimer(BaseSealChrono & chrono, const std::string & itemName, bool printResult, std::ostream & out) : + m_printResult(printResult), + m_out(out), + m_ownItem(true), + m_default_chrono(0) +{ + // construct a time report item + m_item = new TimingItem(chrono,itemName); + // need to add to TimingReport + start(); +} + + // construct from a time report item + + SealTimer::SealTimer(TimingItem & item, bool printResult, std::ostream & out) : + m_printResult(printResult), + m_out(out), + m_item(&item), + m_ownItem(false), + m_default_chrono(0) +{ + start(); +} + +SealTimer::~SealTimer() +{ + // A) Throwing an exception from a destructor is a Bad Thing. + // B) The progress_timer destructor does output which may throw. + // C) A timer is usually not critical to the application. + // Therefore, wrap the I/O in a try block, catch and ignore all exceptions. + try + { + stop(); + if (m_printResult) cool::TimingReport::printLast(*m_item,m_out); + } + catch (...) {} // eat all exceptions + + if (m_ownItem) { + if (m_item) delete m_item; + if (m_default_chrono) delete m_default_chrono; + } +} + + + +void SealTimer::start() { + + m_item->chrono().start(); + +} + +void SealTimer::stop() { + + m_item->chrono().stop(); + + m_item->accumulate(); + +} + +double SealTimer::elapsed(unsigned int i) { + stop(); + return m_item->lastValue(i); +} + + +} // end namespace seal diff --git a/RelationalCool/src/SealUtil_SealTimer.h b/RelationalCool/src/SealUtil_SealTimer.h new file mode 100644 index 000000000..4ea9f2bb5 --- /dev/null +++ b/RelationalCool/src/SealUtil_SealTimer.h @@ -0,0 +1,99 @@ +// Project : LCG +// Package : SealUtil +// Author : Lorenzo.MONETA@cern.ch +// Created by: moneta at Fri Aug 29 16:05:03 2003 + +#ifndef SEALUTIL_SEALTIMER_H +#define SEALUTIL_SEALTIMER_H 1 + + +#include <string> +#include <iostream> + + +namespace seal +{ + + class TimingItem; + class BaseSealChrono; + +/** + * Seal timer class measuring real time, CPU time (separated as user and system) + * and idle time + * Timer starts when constructed and finish at destructions + * + * NOTE: This class does not support copying. + */ + + class SealTimer +{ + +public: + // construct using default chrono (SealBaseChrono) + //SealTimer(const std::string & s = "", bool printResult = true, std::ostream & out = std::cout); + // constructors passing a chrono and a string - no connection to report + SealTimer(BaseSealChrono & c, const std::string & s = "", bool printResult = true, std::ostream & out = std::cout); + // construct from item + SealTimer(TimingItem & item, bool printResult = false, std::ostream & out = std::cout); + virtual ~SealTimer(); + + private: + /// copying unimplemented in this class. + SealTimer(const SealTimer&) : m_out (std::cout) { } + /// copying unimplemented in this class. + SealTimer & operator = (const SealTimer & rhs) { + if (this == &rhs) return *this; // time saving self-test + return *this; + } + + public : + + /* + * start measuring time. Normally not need to call, it is called automatically + * in constructors + */ + + void start(); + + /* + * stop timer and calculate difference from start. + * called automatically in destructor + */ + + void stop(); + + /* + * print timing result. Called also automatically from destructors + */ + + void print(); + + /* + * return elapsed time since start. + * Index i correspond to type of time identified + * according to the chrono used + */ + + double elapsed(unsigned int i = 0); + + protected: + + + private : + + // initial times in nano-seconds + + + bool m_printResult; + std::ostream & m_out; + + TimingItem * m_item; + bool m_ownItem; + BaseSealChrono * m_default_chrono; + +}; + + + +} // end namespace SealUtil +#endif diff --git a/RelationalCool/src/SealUtil_TimingItem.cpp b/RelationalCool/src/SealUtil_TimingItem.cpp new file mode 100644 index 000000000..a4a7719b9 --- /dev/null +++ b/RelationalCool/src/SealUtil_TimingItem.cpp @@ -0,0 +1,101 @@ +// Project : LCG +// Package : SealUtil +// Author : Lorenzo.MONETA@cern.ch +// Created by: moneta at Tue Sep 2 14:06:56 2003 + + +#include "SealUtil_TimingItem.h" + +#include <math.h> +#include <assert.h> + + +namespace seal +{ + + +TimingItem::TimingItem(Chrono & c, const std::string & name) : + m_name(name), + m_counter(0), + m_chrono(c) +{ + m_convScale = 1; + if (c.timeUnit() == BaseSealChrono::CLOCKTICKS ) { + m_unit = "ticks"; + } + else { + m_unit = "s"; + if (c.timeUnit() == BaseSealChrono::NANOSECONDS ) { + m_convScale = 1.0/static_cast<double>(nsec_per_sec); + } + } + m_sumV.resize(numberOfTypes()); + m_sumV2.resize(numberOfTypes()); + +} + + +TimingItem::TimingItem(const TimingItem& other) : m_chrono(other.m_chrono) +{ +} + +TimingItem & TimingItem::operator = (const TimingItem &rhs) +{ + if (this == &rhs) return *this; // time saving self-test + + return *this; +} + + + +// TimingItem class + +// collect statistics +void TimingItem::accumulate() { + m_counter++; + std::vector<double> v = m_chrono.values(); + assert(v.size() == m_sumV.size() ); + assert(m_sumV.size() == m_sumV2.size() ); + + for (unsigned int i = 0; i < numberOfTypes(); ++i) { + // assume implicit conversion from time results to doubles + m_sumV[i] += v[i]; + m_sumV2[i] += v[i]*v[i]; + } +} + +std::string TimingItem::timeType(unsigned int i ) const { + if ( i < numberOfTypes() ) + return m_chrono.names()[i]; + + return std::string(""); +} + +double TimingItem::mean(unsigned int i) const{ + if (m_counter > 0 && i < numberOfTypes() ) + return (m_sumV[i]/m_counter)*m_convScale; + + return 0; +} + +double TimingItem::rms(unsigned int i) const{ + if (m_counter > 0 && i < numberOfTypes() ) { + double rms2 = ( m_sumV2[i] - m_sumV[i]*m_sumV[i]/m_counter )/m_counter; + if (rms2 < 0) return 0; + return sqrt( rms2 )*m_convScale; + } + return 0; +} + +double TimingItem::lastValue(unsigned int i) const { + + if ( i < numberOfTypes() ) + return m_chrono.values()[i]*m_convScale; + + return 0; +} + + + + +} // end namespace SealUtil diff --git a/RelationalCool/src/SealUtil_TimingItem.h b/RelationalCool/src/SealUtil_TimingItem.h new file mode 100644 index 000000000..b5437e516 --- /dev/null +++ b/RelationalCool/src/SealUtil_TimingItem.h @@ -0,0 +1,92 @@ +// Project : LCG +// Package : SealUtil +// Author : Lorenzo.MONETA@cern.ch +// Created by: moneta at Tue Sep 2 14:06:56 2003 + +#ifndef SEALUTIL_TIMINGITEM_H +#define SEALUTIL_TIMINGITEM_H 1 + +#include "SealUtil_BaseSealChrono.h" + + +namespace seal +{ + +/** + * class used to collect the timing result and statistics for a specific item + * Used by the TimingReport + * This class does not support copying. + */ + + +//template <class Chrono=SealChrono> class TimingItem; + + +class TimingItem +{ + + + + static const long nsec_per_sec = 1000000000; // nanosec in one second + + typedef BaseSealChrono Chrono; + +public: + + TimingItem(Chrono & c, const std::string & name); + + ~TimingItem() {/* no op */ } + +private: + /// copying unimplemented in this class. + TimingItem(const TimingItem &); + /// copying unimplemented in this class. + TimingItem & operator = (const TimingItem &); + +public: + + + + void accumulate(); + + + std::string name() { return m_name; } + + std::string unit() { return m_unit; } + + Chrono & chrono() { return m_chrono; } + + unsigned int numberOfMeasurements() const { return m_counter; } + + unsigned int numberOfTypes() const { return m_chrono.nTypes(); } + + std::string timeType(unsigned int i = 0) const; + + // unit here are doubles indicating the number of second + + double mean(unsigned int i = 0) const; + + double rms(unsigned int i = 0) const; + + double lastValue(unsigned int i=0) const; + + + private : + + std::string m_name; + std::string m_unit; + unsigned int m_counter; + std::vector<double> m_sumV; + std::vector<double> m_sumV2; + // by default results are in seconds + // conversion from nanosec to seconds + double m_convScale; + + Chrono & m_chrono; + + + +}; + +} // end namespace SealUtil +#endif diff --git a/RelationalCool/src/SimpleObject.h b/RelationalCool/src/SimpleObject.h new file mode 100644 index 000000000..bba845349 --- /dev/null +++ b/RelationalCool/src/SimpleObject.h @@ -0,0 +1,128 @@ +// $Id: SimpleObject.h,v 1.9 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_SIMPLEOBJECT_H +#define RELATIONALCOOL_SIMPLEOBJECT_H + +// Include files +#include <boost/shared_ptr.hpp> +#include <vector> +#include "CoolKernel/ValidityKey.h" + +namespace cool { + + // Forward declarations + class SimpleObject; + typedef std::vector<SimpleObject> SOVector; + typedef std::vector<SimpleObject>::const_iterator SOIterator; + std::ostream &operator<<( std::ostream& s, const SimpleObject& o ); + + /** SimpleObject.h + * + * A basic object 'shell' used for lightweight object comparison/handling. + * It encapsulated the key attributes of an object without payload. + * + * @author Sven A. Schmidt and Andrea Valassi + * @date 2005-02-11 + */ + + class SimpleObject + { + public: + + unsigned int objectId; + ChannelId channelId; + ValidityKey since; + ValidityKey until; + + SimpleObject( unsigned int anObjectId, + const ChannelId& aChannelId, + const ValidityKey& aSince, + const ValidityKey& anUntil ) + { + objectId = anObjectId; + channelId = aChannelId; + since = aSince; + until = anUntil; + } + + /// Only consider the object id in comparison + bool operator==( const SimpleObject& rhs ) const + { + return objectId == rhs.objectId; + } + + SOVector intersect( const SOVector& objects ) const + { + SOVector res; + for ( SOIterator obj = objects.begin(); obj != objects.end(); ++obj ) { + if ( overlaps( *obj ) ) res.push_back( *obj ); + } + return res; + } + + bool overlaps( const SimpleObject& obj ) const + { + if ( channelId != obj.channelId ) { + return false; + } else { + return ( since <= obj.since && obj.since < until ) + || ( obj.since <= since && since < obj.until ); + } + } + + SOVector filter( const SimpleObject& obj ) const + { + SOVector res; + if ( ! overlaps( obj ) ) { + res.push_back( obj ); + return res; + } + if ( obj.since < since ) + res.push_back + ( SimpleObject( obj.objectId, obj.channelId, obj.since, since ) ); + if ( obj.until > until ) + res.push_back + ( SimpleObject( obj.objectId, obj.channelId, until, obj.until ) ); + return res; + } + + SOVector visibleThrough( const SOVector& objects ) const + { + SOVector res( 1, *this ); + SOVector tmp1, tmp2; + for ( SOIterator obj = objects.begin(); obj != objects.end(); ++obj ) { + tmp1.clear(); + for ( SOIterator source = res.begin(); + source != res.end(); + ++source ) { + tmp2 = obj->filter( *source ); + tmp1.insert( tmp1.end(), tmp2.begin(), tmp2.end() ); + } + res.clear(); + res.insert( res.end(), tmp1.begin(), tmp1.end() ); + } + return res; + } + + }; + + /// Streamer for SimpleObject objects + inline std::ostream &operator<<( std::ostream& s, const SimpleObject& o ) + { + s << o.objectId << ", " << o.channelId + << " [" << o.since << "," << o.until << "]"; + return s; + } + + /// Less than comparison functor to compare SimpleObject since + struct lt_since + : public std::binary_function<SimpleObject, SimpleObject, bool> + { + bool operator()( const SimpleObject& lhs, + const SimpleObject& rhs ) const { + return ( lhs.since < rhs.since ); } + }; + +} // namespace + +#endif + diff --git a/RelationalCool/src/TimingReport.cpp b/RelationalCool/src/TimingReport.cpp new file mode 100644 index 000000000..cbc29798b --- /dev/null +++ b/RelationalCool/src/TimingReport.cpp @@ -0,0 +1,126 @@ +// $Id: TimingReport.cpp,v 1.9 2008-04-11 10:02:46 marcocle Exp $ + +#include "TimingReport.h" + +#include <math.h> + +#include <iostream> + +namespace cool +{ + + TimingReport::~TimingReport() + { + // delete items + /* + for (std::vector<TimingItem *>::iterator + itr = m_items.begin(); itr != m_items.end(); ++itr) + delete *itr; + */ + + m_items.clear(); + + // delete chronos - fix bug #9253 (memory leak!) + for ( std::vector< CoolChrono* >::iterator + itr = m_chronos.begin(); itr != m_chronos.end(); ++itr ) + delete *itr; + + } + + + // print reports + void TimingReport::printLast( seal::TimingItem& item, std::ostream& out ) + { + out << "Timing in " << item.name() << " : "; + for (unsigned int i = 0; i < item.numberOfTypes(); ++i) + out << item.timeType(i) << " = " << item.lastValue(i) + << " (" << item.unit() << "), "; + out << std::endl; + } + + // print results for all timings + /* + void TimingReport::dumpFull(std::ostream & out) + { + out << ">>>>>> Timing Results <<<<<<<<<< " << std::endl; + for (MapItems::iterator itr = m_items.begin(); + itr != m_items.end(); ++itr) { + STItem item = itr->second; + out << "----- " << item->name() << " : " + << " ( n = " << item->numberOfMeasurements() << " )" + << std::endl; + for (unsigned int i = 0; i < item->numberOfTypes(); ++i) { + out << item->timeType(i) << " : mean = " << item->mean(i) + << " (" << item->unit() << "), " + << " RMS = " << item->rms(i) << " (" << item->unit() << ")" + << std::endl; + } + out << std::endl; + } + } + */ + + void TimingReport::dumpFull(std::ostream & out) + { + out << ">>>>>> Timing Results <<<<<<<<<< " << std::endl; + for (MapItems::iterator itr = m_items.begin(); + itr != m_items.end(); ++itr) + { + STItem item = itr->second; + char formattedOut1[] = + "System Time: 123456.000 +/- 123456.000 s (n=1234567890)"; + sprintf( formattedOut1, "%-40.40s (n=%10.1d)", + item->name().c_str(), item->numberOfMeasurements() ); + out << "----- " << formattedOut1 << std::endl; + for (unsigned int i = 0; i < item->numberOfTypes(); ++i) { + if ( item->timeType(i) != "Cpu Time" ) { + /* + out << item->timeType(i) << " : mean = " + << item->mean(i) << " (" << item->unit() << "), " + << " RMS = " << item->rms(i) + << " (" << item->unit() << ")" << std::endl; + */ + /* + out << item->timeType(i) << " : total = " + << item->mean(i)*item->numberOfMeasurements() + << " (" << item->unit() << ") " + << " +/- " << item->rms(i)*sqrt(item->numberOfMeasurements()) + << " (" << item->unit() << ")" << std::endl; + */ + char formattedOut2[] = "System Time: 123456.000 +/- 123456.000"; + sprintf( formattedOut2, + "%-11.11s: %10.3f +/- %10.3f", + (item->timeType(i)).c_str(), + item->mean(i)*item->numberOfMeasurements(), + item->mean(i)*sqrt((double)item->numberOfMeasurements()) ); + if ( item->timeType(i) != "VmSize incr" && + item->timeType(i) != "VmRSS incr" ) { + out << "Total " << formattedOut2 << " " << item->unit() + << std::endl; + } else { + // WARNING! Memory monitoring slows down performance by factors! + if ( getenv ( "COOL_COOLCHRONO_PROCMEMORY" ) ) { + out << "Total " << formattedOut2 << " MB" << std::endl; + } + } + } + } + //out << std::endl; + } + } + + void TimingReport::dump(std::ostream & out) + { + for (MapItems::iterator itr = m_items.begin(); + itr != m_items.end(); ++itr) { + STItem item = itr->second; + out << item->name() << ", n = " << item->numberOfMeasurements() << " "; + for (unsigned int i = 0; i < item->numberOfTypes(); ++i) { + out << item->timeType(i) << " = " << item->mean(i) << " +/- " + << item->rms(i) << " (" << item->unit() << ") "; + } + out << std::endl; + } + } + +} diff --git a/RelationalCool/src/TimingReport.h b/RelationalCool/src/TimingReport.h new file mode 100644 index 000000000..a1a9a624e --- /dev/null +++ b/RelationalCool/src/TimingReport.h @@ -0,0 +1,110 @@ +// $Id: TimingReport.h,v 1.6 2008-04-11 10:02:46 marcocle Exp $ +#ifndef RELATIONALCOOL_TIMINGREPORT_H +#define RELATIONALCOOL_TIMINGREPORT_H 1 + +// AV Copied from SealUtils +#include <boost/shared_ptr.hpp> +#include <iostream> +#include <string> +#include <map> +#include "CoolChrono.h" +#include "SealUtil_TimingItem.h" + +//using namespace seal; + +namespace cool +{ + + /** + * class managing the various timers + * an internal class TimingItem contains the result of the timers + * + * + * This class does not support copying. + */ + + class TimingReport + { + + public: + + TimingReport() {} + + virtual ~TimingReport(); + + private: + + /// copying unimplemented in this class. + TimingReport( const TimingReport& ) {} + + /// copying unimplemented in this class. + TimingReport& operator=( const TimingReport& rhs ) + { + if (this == &rhs) return *this; // time saving self-test + return *this; + } + + public: + + /* + // generic implemetation + template<class Chrono> seal::TimingItem& item( const std::string& name ) + { + MapItems::iterator itr = m_items.find(name); + // item not found create a new one + if (itr == m_items.end() ) { + // create a new Chrono + Chrono * c = new Chrono(); + STItem theItem(new seal::TimingItem(*c,name) ); + m_items.insert(std::make_pair(name,theItem) ); + return *theItem; + } + else { + STItem theItem = itr->second; + return *theItem; + } + } + */ + + // default implementation based on CoolChrono + seal::TimingItem& item( const std::string& name ) + { + MapItems::iterator itr = m_items.find(name); + // item not found create a new one + if (itr == m_items.end() ) { + // create a new CoolChrono + CoolChrono* c = new CoolChrono(); + m_chronos.push_back( c ); + STItem theItem( new seal::TimingItem( *c, name ) ); + m_items.insert(std::make_pair(name,theItem) ); + return *theItem; + } + else { + STItem theItem = itr->second; + return *theItem; + } + } + + // dump compact info + void dump( std::ostream& os = std::cout ); + + // dump in a more extended format + void dumpFull( std::ostream& os = std::cout ); + + // print reports + static + void printLast( seal::TimingItem& item, std::ostream& os = std::cout ); + + private: + + std::vector<CoolChrono*> m_chronos; + + typedef boost::shared_ptr<seal::TimingItem > STItem; + typedef std::map<std::string, STItem> MapItems; + MapItems m_items; + + }; + +} + +#endif diff --git a/RelationalCool/src/TimingReportMgr.cpp b/RelationalCool/src/TimingReportMgr.cpp new file mode 100644 index 000000000..087ae9b24 --- /dev/null +++ b/RelationalCool/src/TimingReportMgr.cpp @@ -0,0 +1,118 @@ +// $Id: TimingReportMgr.cpp,v 1.2 2008-11-04 11:52:11 avalassi Exp $ + +// Include files +#include "CoolKernel/Exception.h" + +// Local include files +#include "TimingReportMgr.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +bool TimingReportMgr::isActive() +{ + if ( pTimingReport() ) return true; + else return false; +} + +//----------------------------------------------------------------------------- + +void TimingReportMgr::initialize() +{ + if ( pTimingReport() ) + { + throw Exception + ( "TimingReportMgr already initialized", "TimingReportMgr" ); + } + else + { + pTimingReport() = new TimingReport(); + } +} + +//----------------------------------------------------------------------------- + +void TimingReportMgr::finalize() +{ + if ( pTimingReport() ) + { + pTimingReport()->dumpFull(); + delete pTimingReport(); + pTimingReport() = 0; + } + else + { + throw Exception + ( "TimingReportMgr not initialized", "TimingReportMgr" ); + } +} + +//----------------------------------------------------------------------------- + +TimingReport& TimingReportMgr::timingReport() +{ + if ( pTimingReport() ) + { + return *pTimingReport(); + } + else + { + throw Exception + ( "TimingReportMgr not initialized", "TimingReportMgr" ); + } +} + +//----------------------------------------------------------------------------- + +TimingReport*& TimingReportMgr::pTimingReport() +{ + static TimingReport* s_report = 0; + return s_report; +} + +//----------------------------------------------------------------------------- + +void TimingReportMgr::startTimer( const std::string& name ) +{ + if ( timerMap().find( name ) != timerMap().end() ) + { + throw Exception + ( "Timer already started for item " + name, "TimingReportMgr" ); + } + else + { + timerMap()[name] = new seal::SealTimer( timingReport().item( name ) ); + } +} + +//----------------------------------------------------------------------------- + +void TimingReportMgr::stopTimer( const std::string& name ) +{ + if ( timerMap().find( name ) == timerMap().end() ) + { + throw Exception + ( "Timer not started for item " + name, "TimingReportMgr" ); + } + else + { + if ( timerMap()[name] ) { + delete timerMap()[name]; + timerMap()[name] = 0; + } + timerMap().erase( timerMap().find( name ) ); + } +} + +//----------------------------------------------------------------------------- + +TimingReportMgr::TimerMap& TimingReportMgr::timerMap() +{ + static TimerMap s_map; + return s_map; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/TimingReportMgr.h b/RelationalCool/src/TimingReportMgr.h new file mode 100644 index 000000000..30f0c3252 --- /dev/null +++ b/RelationalCool/src/TimingReportMgr.h @@ -0,0 +1,48 @@ +// $Id: TimingReportMgr.h,v 1.3 2008-11-04 11:52:11 avalassi Exp $ +#ifndef RELATIONALCOOL_TIMINGREPORTMGR_H +#define RELATIONALCOOL_TIMINGREPORTMGR_H 1 + +// Include files +#include <map> +#include "SealUtil_SealTimer.h" + +// Local include files +#include "TimingReport.h" + +namespace cool +{ + + class TimingReportMgr { + + public: + + static bool isActive(); + + static void initialize(); + static void finalize(); + + static void startTimer( const std::string& name ); + static void stopTimer( const std::string& name ); + + private: + + TimingReportMgr( ); + TimingReportMgr( const TimingReportMgr& rhs ); + TimingReportMgr& operator= ( const TimingReportMgr& rhs ); + virtual ~TimingReportMgr( ); + + private: + + //static TimingReport* s_report; // Link fails + static TimingReport*& pTimingReport(); + + static TimingReport& timingReport(); + + typedef std::map< std::string, seal::SealTimer* > TimerMap; + static TimerMap& timerMap(); + + }; + +} + +#endif // RELATIONALCOOL_TIMINGREPORTMGR_H diff --git a/RelationalCool/src/VersionInfo.h b/RelationalCool/src/VersionInfo.h new file mode 100644 index 000000000..539b2e68b --- /dev/null +++ b/RelationalCool/src/VersionInfo.h @@ -0,0 +1,28 @@ +// $Id: VersionInfo.h,v 1.38 2009-01-06 12:36:25 avalassi Exp $ +#ifndef RELATIONALCOOL_VERSION_INFO_H +#define RELATIONALCOOL_VERSION_INFO_H + +// Include files +#include "VersionNumber.h" + +namespace cool { + + /** VersionInfo.h + * + * Code version number and schema version number for the current release. + * + * @author Sven A. Schmidt, Andrea Valassi and Marco Clemencic + * @date 2005-04-25 + */ + + namespace VersionInfo + { + const VersionNumber release = "2.7.0"; + const VersionNumber schemaVersion = "2.0.0"; + const std::string schemaEvolutionPrefix = "SE_2_2_0_"; + } + +} // namespace + +#endif + diff --git a/RelationalCool/src/VersionNumber.h b/RelationalCool/src/VersionNumber.h new file mode 100644 index 000000000..0e00c9a59 --- /dev/null +++ b/RelationalCool/src/VersionNumber.h @@ -0,0 +1,116 @@ +// $Id: VersionNumber.h,v 1.6 2008-11-04 11:52:11 avalassi Exp $ +#ifndef VERSIONNUMBER_H +#define VERSIONNUMBER_H 1 + +// Include files +#include <string> +#include <sstream> +#include <stdexcept> + +// forward declarations +class VersionNumber; +std::ostream& operator<< ( std::ostream& str, const VersionNumber& vers ); + +/** @class VersionNumber VersionNumber.h + * + * Class used to handle version numbers of format "x.y.z". + * There is no strict format check. + * + * @author Marco Clemencic + * @date 2006-11-09 + */ +class VersionNumber { + +public: + + /// Standard constructor + inline VersionNumber( const std::string &vers ){ initialize(vers); } + + /// Standard constructor (from char array) + inline VersionNumber( const char *vers ){ initialize(vers); } + + // accessors + + inline int majorVersion() const { return m_major; } + inline int minorVersion() const { return m_minor; } + inline int patchVersion() const { return m_patch; } + + // comparison operators + + inline bool operator== (const VersionNumber& rhs) const + { + return + ( majorVersion() == rhs.majorVersion() ) + && ( minorVersion() == rhs.minorVersion() ) + && ( patchVersion() == rhs.patchVersion() ); + } + + inline bool operator!= (const VersionNumber& rhs) const + { + return ! (*this == rhs ); + } + + inline bool operator< (const VersionNumber& rhs) const + { + return + ( majorVersion() < rhs.majorVersion() ) + || ( ( majorVersion() == rhs.majorVersion() ) + && ( minorVersion() < rhs.minorVersion() ) ) + || ( ( majorVersion() == rhs.majorVersion() ) + && ( minorVersion() == rhs.minorVersion() ) + && ( patchVersion() < rhs.patchVersion() ) ); + } + + inline bool operator<= (const VersionNumber& rhs) const + { + return *this == rhs || *this < rhs; + } + + inline bool operator> (const VersionNumber& rhs) const + { + return !( *this <= rhs ); + } + + inline bool operator>= (const VersionNumber& rhs) const + { + return *this == rhs || *this > rhs; + } + + /// Conversion to string + inline operator std::string () const + { + std::ostringstream s; + s << *this; + return s.str(); + } + +private: + + void initialize(const std::string &vers) + { + m_major = m_minor = m_patch = -1; + + std::istringstream s(vers); + char sep; + s >> m_major >> sep >> m_minor >> sep >> m_patch; + if ( m_major < 0 || m_minor < 0 || m_patch < 0 ){ + throw std::runtime_error("Bad version string format: '"+vers+"'"); + } + } + +private: + + int m_major; + int m_minor; + int m_patch; + +}; + +inline std::ostream& operator<< ( std::ostream& str, const VersionNumber& vers) +{ + return str << vers.majorVersion() + << '.' << vers.minorVersion() + << '.' << vers.patchVersion(); +} + +#endif // VERSIONNUMBER_H diff --git a/RelationalCool/src/attributeListToString.h b/RelationalCool/src/attributeListToString.h new file mode 100644 index 000000000..c57aac010 --- /dev/null +++ b/RelationalCool/src/attributeListToString.h @@ -0,0 +1,23 @@ +// $Id: attributeListToString.h,v 1.3 2005-12-09 12:10:51 marcocle Exp $ +#ifndef RELATIONALCOOL_ATTRIBUTELISTTOSTRING_H +#define RELATIONALCOOL_ATTRIBUTELISTTOSTRING_H + +// Include files +#include <sstream> +#include <string> +#include "CoralBase/AttributeList.h" + +namespace cool { + + /// Print an AttributeList to a string using AttributeList::print(). + inline const + std::string attributeListToString( const coral::AttributeList& data ) + { + std::ostringstream dataStream; + data.toOutputStream( dataStream ); + return dataStream.str(); + } + +} + +#endif // RELATIONALCOOL_ATTRIBUTELISTTOSTRING_H diff --git a/RelationalCool/src/new/IHvsNodeMgr.h b/RelationalCool/src/new/IHvsNodeMgr.h new file mode 100644 index 000000000..17cb1ae5b --- /dev/null +++ b/RelationalCool/src/new/IHvsNodeMgr.h @@ -0,0 +1,69 @@ +// $Id: IHvsNodeMgr.h,v 1.2 2007-07-05 09:05:12 avalassi Exp $ +#ifndef COOLKERNEL_IHVSNODEMGR_H +#define COOLKERNEL_IHVSNODEMGR_H + +// Include files +#include <string> +#include "CoolKernel/IHvsNodeRecordMgr.h" + +namespace cool { + + // Forward declarations + class IHvsNode; + + /** @class IHvsNodeMgr IHvsNodeMgr.h + * + * Abstract interface for the manager of one HVS node tree. + * + * The HVS node manager handles a single tree of HVS nodes. + * The tree is a connected (single root), directed (relations are + * between parent and child), acyclic graph where each vertex has + * indegree 0 or 1 (all nodes have 1 parent, but the root has none). + * + * HVS nodes can be uniquely identified by their "full path" names + * (following the same syntax used for UNIX files and directories). + * + * Each node is also assigned a unique integer id by the system. + * + * When users create a node, they must specify whether it can have + * children or not. Nodes that cannot have children are called leaf + * nodes. Nodes that can have children (even if they currently have + * none) are called inner nodes or internal nodes. + * + * @author Andrea Valassi + * @date 2006-03-02 + */ + + class IHvsNodeMgr : public IHvsNodeRecordMgr { + + public: + + /// Destructor + virtual ~IHvsNodeMgr() {}; + + /// Find a node by (full path) name. + /// Throws NodeNotFound if the node does not exist. + virtual const IHvsNode& findNode( const std::string& fullPath ) const = 0; + + /// Find a node by id. + /// Throws NodeNotFound if the node does not exist. + virtual const IHvsNode& findNode( const uInt32 id ) const = 0; + + /// Drop an existing node (leaf node or inner node). + /// Return true if the node and all its structures are dropped as expected. + /// Return false (without throwing any exception) if the node and + /// all its structures do not exist any more on exit from this method, + /// but the node or some of its structures did not exist to start with. + /// Throw an exception if the node or one of its structures + /// cannot be dropped (i.e. continues to exist on exit from this method): + /// Throw an exception if the node is a non-empty inner node. + /// Also deletes any tags associated to the node + /// (throw an exception if such tags cannot be deleted). + virtual const bool dropNode( const std::string& fullPath ) = 0; + + }; + +} + +#endif // COOLKERNEL_IHVSNODEMGR_H + diff --git a/RelationalCool/src/new/IHvsNodeRecordMgr.h b/RelationalCool/src/new/IHvsNodeRecordMgr.h new file mode 100644 index 000000000..bf44c2e58 --- /dev/null +++ b/RelationalCool/src/new/IHvsNodeRecordMgr.h @@ -0,0 +1,61 @@ +// $Id: IHvsNodeRecordMgr.h,v 1.1 2006-04-03 11:33:23 avalassi Exp $ +#ifndef COOLKERNEL_IHVSNODERECORDMGR_H +#define COOLKERNEL_IHVSNODERECORDMGR_H + +// Include files +#include <string> + +namespace cool { + + // Forward declarations + class IHvsNodeRecord; + + /** @class IHvsNodeRecordMgr IHvsNodeRecordMgr.h + * + * Abstract interface for the manager of one HVS node tree. + * + * The HVS node manager handles a single tree of HVS nodes. + * The tree is a connected (single root), directed (relations are + * between parent and child), acyclic graph where each vertex has + * indegree 0 or 1 (all nodes have 1 parent, but the root has none). + * + * HVS nodes can be uniquely identified by their "full path" names + * (following the same syntax used for UNIX files and directories). + * + * Each node is also assigned a unique integer id by the system. + * + * When users create a node, they must specify whether it can have + * children or not. Nodes that cannot have children are called leaf + * nodes. Nodes that can have children (even if they currently have + * none) are called inner nodes or internal nodes. + * + * @author Andrea Valassi + * @date 2006-03-02 + */ + + class IHvsNodeRecordMgr { + + public: + + /// Destructor + virtual ~IHvsNodeRecordMgr() {}; + + /// Find a node record by (full path) name. + /// Throws NodeNotFound if the node does not exist. + virtual const IHvsNodeRecord& + findNodeRecord( const std::string& fullPath ) const = 0; + + /// Find a node record by id. + /// Throws NodeNotFound if the node does not exist. + virtual const IHvsNodeRecord& + findNodeRecord( const uInt32 id ) const = 0; + + /// Does a node with this (full path) name exist? + virtual const bool existsNode( const std::string& nodeName ) const = 0; + + }; + +} + +#endif // COOLKERNEL_IHVSNODERECORDMGR_H + diff --git a/RelationalCool/src/new/IHvsTag.h b/RelationalCool/src/new/IHvsTag.h new file mode 100644 index 000000000..ebee8a3c1 --- /dev/null +++ b/RelationalCool/src/new/IHvsTag.h @@ -0,0 +1,43 @@ +// $Id: IHvsTag.h,v 1.2 2007-07-05 09:05:12 avalassi Exp $ +#ifndef COOLKERNEL_IHVSTAG_H +#define COOLKERNEL_IHVSTAG_H + +// Include files +#include "CoolKernel/IHvsTagRecord.h" + +namespace cool { + + /** @class IHvsTag IHvsTag.h + * + * Abstract interface for one tag stored in an HVS tag tree + * (read-only interface to access the properties of existing tags). + * + * HVS tags can be uniquely identified by their names. + * The terms "tag" and "tag name" are thus equivalent. + * + * Each tag is also assigned a unique integer id by the system. + * + * When users create a tag, they must specify whether it will be used + * for inner nodes or leaf nodes. A given tag can be used only for one + * inner node or for many leaf nodes: the same tag cannot be used for + * more than one inner node, or for one inner node and one leaf node. + * + * @author Andrea Valassi + * @date 2006-03-03 + */ + + class IHvsTag : public IHvsTagRecord { + + public: + + /// Destructor. + virtual ~IHvsTag() {} + + /// Change the tag description stored in the database. + virtual void setDescription( const std::string& description ) = 0; + + }; + +} + +#endif // COOLKERNEL_IHVSTAG_H diff --git a/RelationalCool/src/new/RelationalHvsTagMgr.cpp b/RelationalCool/src/new/RelationalHvsTagMgr.cpp new file mode 100644 index 000000000..78eb467ae --- /dev/null +++ b/RelationalCool/src/new/RelationalHvsTagMgr.cpp @@ -0,0 +1,84 @@ +// $Id: RelationalHvsTagMgr.cpp,v 1.1 2006-04-03 11:33:23 avalassi Exp $ + +// Include files +#include "CoolKernel/Exception.h" +#include "CoolKernel/IHvsNodeMgr.h" +#include "CoolKernel/IHvsNodeRecord.h" +#include "CoolKernel/IHvsTagRecord.h" + +// Local include files +#include "RelationalHvsTagMgr.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +const IHvsTagRecord& +RelationalHvsTagMgr::findTagRecord( const std::string& /*tagName*/ ) const +{ + throw Exception( "Not yet implemented", "RelationalHvsTagMgr" ); +} + +//----------------------------------------------------------------------------- + +/* +const IHvsTag& +RelationalHvsTagMgr::findTag( const std::string& tagName ) const +{ +} +*/ + +//----------------------------------------------------------------------------- + +const bool +RelationalHvsTagMgr::existsTag( const std::string& tagName ) const +{ + if ( IHvsNode::isHeadTag( tagName ) ) return true; + try { + findTagRecord( tagName ); + return true; + } catch ( TagNotFound& /* dummy */ ) { + return false; + } +} + +//----------------------------------------------------------------------------- +/* +const IHvsNode::Type +RelationalHvsTagMgr::tagScope( const std::string& tagName ) const +{ + const IHvsTagRecord& tag = findTagRecord( tagName ); + return tag.scope(); +} +*/ +//----------------------------------------------------------------------------- + +const std::string +RelationalHvsTagMgr::taggedNode( const std::string& tagName ) const +{ + const IHvsTagRecord& tag = findTagRecord( tagName ); + return hvsNodeMgr().findNodeRecord( tag.nodeId() ).fullPath(); +} + +//----------------------------------------------------------------------------- + +const std::vector<std::string> +RelationalHvsTagMgr::taggedNodes( const std::string& tagName ) const +{ + // TEMPORARY IMPLEMENTATION! + std::vector<std::string> nodes; + nodes.push_back( taggedNode( tagName ) ); + return nodes; +} + +//----------------------------------------------------------------------------- + +const IHvsNodeMgr& +RelationalHvsTagMgr::hvsNodeMgr() const +{ + return *m_hvsNodeMgr; +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/src/new/RelationalHvsTagMgr.h b/RelationalCool/src/new/RelationalHvsTagMgr.h new file mode 100644 index 000000000..148f69529 --- /dev/null +++ b/RelationalCool/src/new/RelationalHvsTagMgr.h @@ -0,0 +1,107 @@ +// $Id: RelationalHvsTagMgr.h,v 1.1 2006-04-03 11:33:23 avalassi Exp $ +#ifndef RELATIONALCOOL_RELATIONALHVSTAGMGR_H +#define RELATIONALCOOL_RELATIONALHVSTAGMGR_H + +// Include files +#include "CoolKernel/IHvsTagMgr.h" + +namespace cool { + + /** @class RelationalHvsTagMgr RelationalHvsTagMgr.h + * + * Abstract interface for the manager of one HVS tag tree. + * + * HVS tags can be uniquely identified by their names. + * The terms "tag" and "tag name" are thus equivalent. + * + * Each tag is also assigned a unique integer id by the system. + * + * When users create a tag, they must specify whether it will be used + * for inner nodes or leaf nodes. A given tag can be used only for one + * inner node or for many leaf nodes: the same tag cannot be used for + * more than one inner node, or for one inner node and one leaf node. + * + * @author Andrea Valassi + * @date 2006-03-02 + */ + + class RelationalHvsTagMgr { + + public: + + /// Destructor + virtual ~RelationalHvsTagMgr() {}; + + /// Get a tag record by name. + /// Throws TagNotFound if the tag does not exist. + virtual const IHvsTagRecord& + findTagRecord( const std::string& tagName ) const; + + /* + /// Get a tag by name. + /// Throws TagNotFound if the tag does not exist. + virtual const IHvsTag& findTag( const std::string& tagName ); + */ + + /// Does a tag with this name exist? + /// Tag names, except for "HEAD", are case sensitive. + /// Returns true for the reserved tags "" and "HEAD". + virtual const bool existsTag( const std::string& tagName ) const; + + /* + /// Return the type of node (inner/leaf) where the tag can be defined. + /// Tag names, except for "HEAD", are case sensitive. + /// Throws TagNotFound if the tag does not exist. + virtual const IHvsNode::Type tagScope( const std::string& tagName ) const; + */ + + /// Return the names of the node where the tag is defined. + /// Tag names, except for "HEAD", are case sensitive. + /// Throws TagNotFound if the tag does not exist. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + virtual const std::string taggedNode( const std::string& tagName ) const; + + /// Return the names of the nodes where the tag is defined. + /// Tag names, except for "HEAD", are case sensitive. + /// Throws TagNotFound if the tag does not exist. + /// Throws ReservedHeadTag for the HEAD tag (defined in all folders). + virtual const + std::vector<std::string> taggedNodes( const std::string& tagName ) const; + + /* + /// Main HVS method: determine the tag associated to a node, given + /// a tag associated to an ancestor of that descendant node. + /// The corresponding ancestor node is also internally determined. + /// Throw an exception if the tag is not associated to any ancestor node. + /// The input 'ancestor' tag is returned if it is directly associated to + /// the node itself, rather than to an ancestor of that node. + virtual const + std::string resolveTag( const std::string& descendantNode, + const std::string& ancestorTag ); + + /// Main HVS method: determine the tag associated to a node, given + /// an ancestor of that descendant node and a tag associated to it. + /// Throw an exception if the tag is not associated to the ancestor node. + /// Throw an exception if the two nodes are not ancestor and descendant. + virtual const + std::string resolveTag( const std::string& descendantNode, + const std::string& ancestorTag, + const std::string& ancestorNode ); + */ + + private: + + /// Handle to the IHvsNodeMgr + const IHvsNodeMgr& hvsNodeMgr() const; + + private: + + /// Handle to the IHvsNodeMgr + IHvsNodeMgr* m_hvsNodeMgr; + + }; + +} + +#endif // RELATIONALCOOL_RELATIONALHVSTAGMGR_H + diff --git a/RelationalCool/src/sigsegv.cpp b/RelationalCool/src/sigsegv.cpp new file mode 100644 index 000000000..71728ea43 --- /dev/null +++ b/RelationalCool/src/sigsegv.cpp @@ -0,0 +1,296 @@ +// $Id: sigsegv.cpp,v 1.8 2008-05-16 11:29:19 avalassi Exp $ +#ifndef __APPLE__ +#ifndef WIN32 + +//----------------------------------------------------------------------------- +// From the SEAL config.h +//----------------------------------------------------------------------------- + +// AV simple workaround for SEAL config - START +// Compare SEAL config.h for LX32, LX64, MAC, WIN +#ifndef WIN32 +# define HAVE_POSIX_SIGNALS 1 // ok LX32/LX64/MAC, no WIN +#endif +// AV simple workaround for SEAL config - END + +//----------------------------------------------------------------------------- +// From http://tlug.up.ac.za/wiki/index.php/ +// Obtaining_a_stack_trace_in_C_upon_SIGSEGV +//----------------------------------------------------------------------------- + +/** + * This source file is used to print out a stack-trace when your program + * segfaults. It is relatively reliable and spot-on accurate. + * + * This code is in the public domain. Use it as you see fit, some credit + * would be appreciated, but is not a prerequisite for usage. Feedback + * on it's use would encourage further development and maintenance. + * + * Author: Jaco Kroon <jaco@kroon.co.za> + * + * Copyright (C) 2005 - 2006 Jaco Kroon + */ +#ifndef WIN32 // AV +//#define _GNU_SOURCE // AV +//#define NO_CPP_DEMANGLE // AV +#include <memory.h> +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#include <ucontext.h> +#include <dlfcn.h> +#include <execinfo.h> +#ifndef NO_CPP_DEMANGLE +#include <cxxabi.h> +#endif + +#if defined(REG_RIP) +# define SIGSEGV_STACK_IA64 +# define REGFORMAT "%016lx" +#elif defined(REG_EIP) +# define SIGSEGV_STACK_X86 +# define REGFORMAT "%08x" +#else +# define SIGSEGV_STACK_GENERIC +# define REGFORMAT "%x" +#endif + +namespace cool +{ + + // Declare SEAL functions + const char* seal_describe (int sig, int code); + + static void signal_segv(int signum, siginfo_t* info, void*ptr) + { + static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"}; + + ucontext_t *ucontext = (ucontext_t*)ptr; + +#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) + int f = 0; + Dl_info dlinfo; + void **bp = 0; + void *ip = 0; +#else + void *bt[20]; + char **strings; + size_t sz; +#endif + + fprintf(stderr, "Segmentation Fault!\n"); + fprintf(stderr, "info.si_signo = %d\n", signum); + fprintf(stderr, "info.si_errno = %d\n", info->si_errno); + //fprintf(stderr, "info.si_code = %d (%s)\n", info->si_code, si_codes[info->si_code]); + fprintf(stderr, "info.si_code = %d (%s: %s)\n", info->si_code, si_codes[info->si_code], seal_describe(signum,info->si_code)); + fprintf(stderr, "info.si_addr = %p\n", info->si_addr); + // AV skip registry dump - START + //size_t i1; + //for(i1 = 0; i1 < NGREG; i1++) + // fprintf(stderr, "reg[%02d] = 0x" REGFORMAT "\n", i1, ucontext->uc_mcontext.gregs[i1]); + // AV skip registry dump - END + +#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) +# if defined(SIGSEGV_STACK_IA64) + ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP]; + bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP]; +# elif defined(SIGSEGV_STACK_X86) + ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP]; + bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP]; +# endif + + fprintf(stderr, "Stack trace:\n"); + while(bp && ip) { + if(!dladdr(ip, &dlinfo)) + break; + + const char *symname = dlinfo.dli_sname; +#ifndef NO_CPP_DEMANGLE + int status; + //char *tmp = __cxa_demangle(symname, NULL, 0, &status); + char *tmp = abi::__cxa_demangle(symname, NULL, 0, &status); // AV + + if(status == 0 && tmp) + symname = tmp; +#endif + + fprintf(stderr, "% 2d: %p <%s+%lu> (%s)\n", + ++f, + ip, + symname, + (unsigned long)(dlinfo.dli_saddr)-(unsigned long)ip, + dlinfo.dli_fname); + +#ifndef NO_CPP_DEMANGLE + if(tmp) + free(tmp); +#endif + + if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main")) + break; + + ip = bp[1]; + bp = (void**)bp[0]; + } +#else + fprintf(stderr, "Stack trace (non-dedicated):\n"); + sz = backtrace(bt, 20); + strings = backtrace_symbols(bt, sz); + + size_t i; + for(i = 0; i < sz; ++i) + fprintf(stderr, "%s\n", strings[i]); +#endif + fprintf(stderr, "End of stack trace\n"); + exit (-1); + } + + int setup_sigsegv() + { + struct sigaction action; + memset(&action, 0, sizeof(action)); + action.sa_sigaction = signal_segv; + action.sa_flags = SA_SIGINFO; + if(sigaction(SIGSEGV, &action, NULL) < 0) { + perror("sigaction"); + return 0; + } + + return 1; + } + +#define SIGSEGV_NO_AUTO_INIT 1 // AV +#ifndef SIGSEGV_NO_AUTO_INIT + static void __attribute((constructor)) init(void) { + setup_sigsegv(); + } +#endif +#endif // AV + +//----------------------------------------------------------------------------- +// From the SEAL Signal class +//----------------------------------------------------------------------------- + +/** Return the description for signal info code @a code for signal + number @a sig. The code should come from @c siginfo_t::si_code. */ + const char* seal_describe (int sig, int code) + { + static struct { int sig; int code; const char *desc; } s_infos [] = { +#if HAVE_POSIX_SIGNALS + { -1, SI_USER, "user sent: kill, sigsend or raise" }, +# ifdef SI_KERNEL + { -1, SI_KERNEL, "kernel" }, +# endif + { -1, SI_QUEUE, "sigqueue" }, + { -1, SI_TIMER, "timer expired" }, + { -1, SI_MESGQ, "mesq state changed" }, + { -1, SI_ASYNCIO, "AIO completed" }, +# ifdef SI_SIGIO // not solaris + { -1, SI_SIGIO, "queued SIGIO" }, +# endif + +# ifdef ILL_NOOP // darwin + { SIGILL, ILL_NOOP, "noop" }, +# endif + { SIGILL, ILL_ILLOPC, "illegal opcode" }, +# ifdef ILL_ILLOPN // not darwin + { SIGILL, ILL_ILLOPN, "illegal operand" }, +# endif +# ifdef ILL_ILLADR // not darwin + { SIGILL, ILL_ILLADR, "illegal addressing mode" }, +# endif + { SIGILL, ILL_ILLTRP, "illegal trap" }, + { SIGILL, ILL_PRVOPC, "priveleged opcode" }, +# ifdef ILL_PRVREG // not darwin + { SIGILL, ILL_PRVREG, "privileged register" }, +# endif +# ifdef ILL_COPROC // not darwin + { SIGILL, ILL_COPROC, "coprocessor error" }, +# endif +# ifdef ILL_BADSTK // not darwin + { SIGILL, ILL_BADSTK, "internal stack error" }, +# endif + +# ifdef FPE_NOOP // darwin + { SIGFPE, FPE_NOOP, "noop" }, +# endif +# ifdef FPE_INTDIV // not darwin + { SIGFPE, FPE_INTDIV, "integer divide by zero" }, +# endif +# ifdef FPE_INTOVF // not darwin + { SIGFPE, FPE_INTOVF, "integer overflow" }, +# endif + { SIGFPE, FPE_FLTDIV, "flaoting point divide by zero" }, + { SIGFPE, FPE_FLTOVF, "floating point overflow" }, + { SIGFPE, FPE_FLTUND, "floating point underflow" }, + { SIGFPE, FPE_FLTRES, "floating point inexact result" }, + { SIGFPE, FPE_FLTINV, "floating point in valid operation" }, +# ifdef FPE_FLTSUB // not darwin + { SIGFPE, FPE_FLTSUB, "subscript out of range" }, +# endif + +# ifdef SEGV_NOOP // darwin + { SIGSEGV, SEGV_NOOP, "noop" }, +# endif + { SIGSEGV, SEGV_MAPERR, "address not mapped to object" }, + { SIGSEGV, SEGV_ACCERR, "invalid permissions for mapped object" }, + +# ifdef BUS_NOOP // darwin + { SIGBUS, BUS_NOOP, "noop" }, +# endif + { SIGBUS, BUS_ADRALN, "invalid address alignment" }, +# ifdef BUS_ADRERR // not darwin + { SIGBUS, BUS_ADRERR, "non-existent physical address" }, +# endif +# ifdef BUS_OBJERR // not darwin + { SIGBUS, BUS_OBJERR, "object specific hardware error" }, +# endif + +# ifdef TRAP_BRKPT // not darwin + { SIGTRAP, TRAP_BRKPT, "process break point" }, +# endif +# ifdef TRAP_TRACE // not darwin + { SIGTRAP, TRAP_TRACE, "process trace trap" }, +# endif + +# ifdef CLD_NOOP // darwin + { SIGCHLD, CLD_NOOP, "noop" }, +# endif + { SIGCHLD, CLD_EXITED, "child has exited" }, + { SIGCHLD, CLD_KILLED, "child was killed" }, + { SIGCHLD, CLD_DUMPED, "child terminated abnormally" }, + { SIGCHLD, CLD_TRAPPED, "traced child has trapped" }, + { SIGCHLD, CLD_STOPPED, "child has stopped" }, + { SIGCHLD, CLD_CONTINUED,"stopped child has continued" }, + +# ifdef SIGPOLL // not darwin + { SIGPOLL, POLL_IN, "data input available" }, + { SIGPOLL, POLL_OUT, "output buffers available" }, + { SIGPOLL, POLL_MSG, "input message available" }, + { SIGPOLL, POLL_ERR, "i/o error" }, + { SIGPOLL, POLL_PRI, "high priority input available" }, + { SIGPOLL, POLL_HUP, "device disconnected" }, +# endif +#endif // HAVE_POSIX_SIGNALS + + { -1, -1, 0 } + }; + + for (unsigned i = 0; s_infos [i].desc; ++i) + if ((s_infos [i].sig == -1 || s_infos [i].sig == sig) + && s_infos [i].code == code) + return s_infos [i].desc; + + return "*unknown reason*"; + } + +} + +//----------------------------------------------------------------------------- +#endif // WIN32 +#else // __APPLE__ +namespace cool +{ + int setup_sigsegv(){ return 0; } +} +#endif // __APPLE__ diff --git a/RelationalCool/src/sigsegv.h b/RelationalCool/src/sigsegv.h new file mode 100644 index 000000000..203ec3f8d --- /dev/null +++ b/RelationalCool/src/sigsegv.h @@ -0,0 +1,12 @@ +// $Id: sigsegv.h,v 1.2 2008-04-10 10:12:17 avalassi Exp $ +// From http://tlug.up.ac.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV +#ifndef SIGSEGV_H +#define SIGSEGV_H 1 +#ifdef __cplusplus +//extern "C" // AV +#endif +namespace cool +{ + int setup_sigsegv(); +} +#endif diff --git a/RelationalCool/src/sleep.h b/RelationalCool/src/sleep.h new file mode 100644 index 000000000..b4d6bec90 --- /dev/null +++ b/RelationalCool/src/sleep.h @@ -0,0 +1,19 @@ +#include "boost/thread/xtime.hpp" +#include <boost/thread.hpp> + +namespace cool +{ + void sleep(int sec) + { + boost::xtime t; + if ( boost::xtime_get(&t,boost::TIME_UTC) == boost::TIME_UTC ) + { + t.sec += sec; + boost::thread::sleep(t); + } + else + { + // TODO: (Marco) do something if cannot get the time... + } + } +} diff --git a/RelationalCool/src/timeToString.h b/RelationalCool/src/timeToString.h new file mode 100644 index 000000000..e566f0476 --- /dev/null +++ b/RelationalCool/src/timeToString.h @@ -0,0 +1,92 @@ +// $Id: timeToString.h,v 1.10 2007-03-29 15:57:01 avalassi Exp $ +#ifndef RELATIONALCOOL_TIMETOSTRING_H +#define RELATIONALCOOL_TIMETOSTRING_H + +// Include files +#include <iostream> +#include <sstream> +#include <string> +#include "CoolKernel/Exception.h" +#include "CoolKernel/Time.h" + +namespace cool { + + /// Convert a string date "yyyy-mm-dd_hh:mm:ss.nnnnnnnnn into a Time. + /// The format is the one we used to store dates for both Oracle and MySQL. + /// The input string is expected to represent a GMT time and ends with "GMT" + inline const Time stringToTime( const std::string& timeString ) + { + int year, month, day, hour, min, sec; + long nsec; + if ( timeString.size() == + std::string( "yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT" ).size() + && sscanf( timeString.c_str(), "%4d-%2d-%2d_%2d:%2d:%2d.%9ld GMT", + &year, &month, &day, &hour, &min, &sec, &nsec) == 7 + && timeString.substr(4,1) == "-" + && timeString.substr(7,1) == "-" // Month in [1-12] + && timeString.substr(10,1) == "_" + && timeString.substr(13,1) == ":" + && timeString.substr(16,1) == ":" + && timeString.substr(19,1) == "." + && timeString.substr(29,4) == " GMT" ) { + Time time( year, month, day, hour, min, sec, nsec ); + /* + std::cout<< "__stringToTime ( '" << timeString << "' )" << std::endl; + std::cout<<"Year: "<<year<<" -> "<<time.year()<<std::endl; + std::cout<<"Month: "<<month<<" -> "<<time.month()<<std::endl; + std::cout<<"Day: "<<day<<" -> "<<time.day()<<std::endl; + std::cout<<"Hour: "<<hour<<" -> "<<time.hour()<<std::endl; + std::cout<<"Min: "<<min<<" -> "<<time.minute()<<std::endl; + std::cout<<"Sec: "<<sec<<" -> "<<time.second()<<std::endl; + std::cout<<"nSec: "<<nsec<<" -> "<<time.nanosecond()<<std::endl; + std::cout<< "__stringToTime = '" << time << "'" << std::endl; + */ + return time; + } else { + std::stringstream msg; + msg << "Error decoding string '" << timeString << "' into Time"; + throw cool::Exception( msg.str(), "cool::stringToTime" ); + } + } + + /// Convert any ITime into a string in the format expected by stringToTime. + /// Useful to print an ITime (there is no default operator<<). + /// The output string represents a GMT time and ends with "GMT" + inline const std::string timeToString( const ITime& time ) + { + int year = time.year(); + int month = time.month(); // Months are in [1-12] + int day = time.day(); + int hour = time.hour(); + int min = time.minute(); + int sec = time.second(); + long nsec = time.nanosecond(); + char timeChar[] = "yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT"; + int nChar = std::string(timeChar).size(); + if ( sprintf( timeChar, "%4.4d-%2.2d-%2.2d_%2.2d:%2.2d:%2.2d.%9.9ld GMT", + year, month, day, hour, min, sec, nsec) == nChar ) { + std::string timeString = std::string( timeChar ); + /* + std::cout<< "__timeToString ( '" << time << "' )" << std::endl; + std::cout<<"Year: "<<year<<std::endl; + std::cout<<"Month(1-12): "<<month<<std::endl; + std::cout<<"Day: "<<day<<std::endl; + std::cout<<"Hour: "<<hour<<std::endl; + std::cout<<"Min: "<<min<<std::endl; + std::cout<<"Sec: "<<sec<<std::endl; + std::cout<<"nSec: "<<nsec<<std::endl; + std::cout<< "__timeToString = '" << timeString << "'" << std::endl; + */ + return timeString; + } else { + std::stringstream msg; + msg << "PANIC! Error encoding ITime into string: " + << year << "-" << month << "-" << day << "_" + << hour << ":" << min << ":" << sec << "." << nsec; + throw cool::Exception( msg.str(), "cool::timeToString" ); + } + + } + +} +#endif // RELATIONALCOOL_TIMETOSTRING_H diff --git a/RelationalCool/src/uppercaseString.h b/RelationalCool/src/uppercaseString.h new file mode 100644 index 000000000..d806d5152 --- /dev/null +++ b/RelationalCool/src/uppercaseString.h @@ -0,0 +1,21 @@ +// $Id: uppercaseString.h,v 1.4 2005-12-09 12:10:51 marcocle Exp $ +#ifndef UPPERCASESTRING_H +#define UPPERCASESTRING_H 1 + +// Include files +#include <algorithm> +#include <cctype> +#include <string> + +namespace cool { + + inline const std::string uppercaseString( const std::string& aString ) { + std::string aStringUp = aString; + std::transform + ( aStringUp.begin(), aStringUp.end(), aStringUp.begin(), toupper ); + return aStringUp; + } + +} + +#endif // UPPERCASESTRING_H diff --git a/RelationalCool/tests/AttributeList/test_AttributeList.cpp b/RelationalCool/tests/AttributeList/test_AttributeList.cpp new file mode 100644 index 000000000..3271ac549 --- /dev/null +++ b/RelationalCool/tests/AttributeList/test_AttributeList.cpp @@ -0,0 +1,124 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT +// $Id: test_AttributeList.cpp,v 1.8 2008-08-06 09:33:04 avalassi Exp $ + +#include <iostream> +#include <string> +#include "AttributeList/AttributeList.h" +#include "../../src/ProcMemory.h" +#include "../../src/sleep.h" + +using namespace std; + +//----------------------------------------------------------------------------- + +void test_memory_leak() { + pool::AttributeListSpecification spec; + spec.push_back("I","int"); + ProcMemory mem; + + long nObjs = 1*1000*1000; + for ( long i = 0; i < nObjs; ++i ) { + if ( i % 100000 == 0 ) { + std::cout << "object " << i << "\t"; + mem.printVm(); + std::cout << std::endl; + cool::sleep(1); + } + pool::AttributeList list( spec ); + } +} + +//----------------------------------------------------------------------------- + +int test_specs() { + + cout << "Entering test_specs" << endl; + + pool::AttributeList* alpFrefCc; // copy-construct AL built from reference + pool::AttributeList* alpFrefAs; // assignment of AL built from reference + pool::AttributeList* alpFshpCc; // copy-construct AL built from sh pointer + pool::AttributeList* alpFshpAs; // assignment of AL built from sh pointer + + { + // The two AttributeList specifications + pool::AttributeListSpecification alRefSpec; + alRefSpec.push_back( "REFERENCE", "string" ); + boost::shared_ptr<pool::AttributeListSpecification> alShpSpec + ( new pool::AttributeListSpecification() ); + alShpSpec->push_back( "SHARED", "string" ); + alShpSpec->push_back( "POINTER", "string" ); + cout << "Shared pointer - built specification" << endl; + cout << "Shared pointer use count = " << alShpSpec.use_count() << endl; + // Build AL from reference or shared pointer specification + pool::AttributeList alFref( alRefSpec ); + pool::AttributeList alFshp( alShpSpec ); + cout << "Shared pointer - built AL from specification" << endl; + cout << "Shared pointer use count = " << alShpSpec.use_count() << endl; + alFref["REFERENCE"].setValueAsString("---"); + alFshp["SHARED"].setValueAsString("---"); + alFshp["POINTER"].setValueAsString("---"); + // Copy-construct and assign the four pointers + alpFrefCc = new pool::AttributeList( alFref ); // PROBLEMS! + alpFrefAs = new pool::AttributeList(); *alpFrefAs = alFref; // PROBLEMS! + alpFshpCc = new pool::AttributeList( alFshp ); // PROBLEMS! + cout << "Shared pointer - built AL from copy constructor" << endl; + cout << "Shared pointer use count = " << alShpSpec.use_count() << endl; + alpFshpAs = new pool::AttributeList(); *alpFshpAs = alFshp; // OK? + cout << "Shared pointer - assigned AL" << endl; + cout << "Shared pointer use count = " << alShpSpec.use_count() << endl; + // Print the four lists + cout << "Size alpFrefCc = " + << alpFrefCc->attributeListSpecification().size() << endl; + alpFrefCc->print( cout ); cout << endl; + cout << "Size alpFrefAs = " + << alpFrefAs->attributeListSpecification().size() << endl; + alpFrefAs->print( cout ); cout << endl; + cout << "Size alpFshpCc = " + << alpFshpCc->attributeListSpecification().size() << endl; + alpFshpCc->print( cout ); cout << endl; + cout << "Size alpFshpAs = " + << alpFshpAs->attributeListSpecification().size() << endl; + alpFshpAs->print( cout ); cout << endl; + } + + // Print the four lists again + cout << "Size alpFrefCc = " + << alpFrefCc->attributeListSpecification().size() << endl; + //alpFrefCc->print( cout ); cout << endl; + cout << "Size alpFrefAs = " + << alpFrefAs->attributeListSpecification().size() << endl; + //alpFrefAs->print( cout ); cout << endl; + cout << "Size alpFshpCc = " + << alpFshpCc->attributeListSpecification().size() << endl; + //alpFshpCc->print( cout ); cout << endl; + cout << "Size alpFshpAs = " + << alpFshpAs->attributeListSpecification().size() << endl; + //alpFshpAs->print( cout ); cout << endl; + + // Delete the AL holding the specification shared pointer + delete alpFshpAs; + cout << "Size alpFshpCc = " + << alpFshpCc->attributeListSpecification().size() << endl; + //alpFshpCc->print( cout ); cout << endl; + + // Delete all other ALs + delete alpFrefCc; + delete alpFrefAs; + delete alpFshpCc; + + cout << "Exiting test_specs" << endl; + return 0; + +} + +//----------------------------------------------------------------------------- + +int main() { + test_specs(); + + test_memory_leak(); +} + +#endif // NOPORT diff --git a/RelationalCool/tests/AttributeListDump/test_AttributeListDump.cpp b/RelationalCool/tests/AttributeListDump/test_AttributeListDump.cpp new file mode 100644 index 000000000..c3df9b1ef --- /dev/null +++ b/RelationalCool/tests/AttributeListDump/test_AttributeListDump.cpp @@ -0,0 +1,22 @@ +#include <iostream> +#include "CoolKernel/types.h" +#include "CoralBase/AttributeList.h" + +#include "../Common/releaser.h" + +// These two alone provide "<< AttributeList" functionalities...!? +// NOT ANY LONGER after making the constructors explicit! +#include "src/RelationalObjectTableRow.h" +using namespace cool; + +int main() { + boost::shared_ptr<coral::AttributeListSpecification> + spec( new coral::AttributeListSpecification(), cool::releaser() ); + spec->extend( "i", "int" ); + coral::AttributeList dummy( *spec ); + // The following does not work anymore! + //std::cout << "Dummy AttributeList: " << dummy << std::endl; + // The following works... but will clearly never be written! :-) + std::cout << "Dummy AttributeList: " + << RelationalObjectTableRow( dummy ) << std::endl; +} diff --git a/RelationalCool/tests/BoolIO/authentication.xml b/RelationalCool/tests/BoolIO/authentication.xml new file mode 100755 index 000000000..da8dc0f83 --- /dev/null +++ b/RelationalCool/tests/BoolIO/authentication.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" ?> +<connectionlist> + +<connection name="oracle://devdb10/lcg_cool"> + <parameter name="user" value="USER" /> + <parameter name="password" value="PASSWORD" /> +</connection> + +<connection name="mysql://pcitdb59/COOLDB"> + <parameter name="user" value="USER" /> + <parameter name="password" value="PASSWORD" /> +</connection> + +</connectionlist> diff --git a/RelationalCool/tests/BoolIO/boolIO.cpp b/RelationalCool/tests/BoolIO/boolIO.cpp new file mode 100644 index 000000000..a58d7607f --- /dev/null +++ b/RelationalCool/tests/BoolIO/boolIO.cpp @@ -0,0 +1,225 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +#include <iostream> +#include <stdexcept> +#include <memory> +#include "RelationalAccess/RelationalException.h" +#include "RelationalAccess/IRelationalService.h" +#include "RelationalAccess/IRelationalDomain.h" +#include "RelationalAccess/IRelationalSession.h" +#include "RelationalAccess/IRelationalTransaction.h" +#include "RelationalAccess/IRelationalSchema.h" +#include "RelationalAccess/IRelationalTable.h" +#include "RelationalAccess/RelationalEditableTableDescription.h" +#include "RelationalAccess/IRelationalTableDataEditor.h" +#include "RelationalAccess/IRelationalBulkRowInserter.h" +#include "RelationalAccess/IRelationalCursor.h" +#include "RelationalAccess/IRelationalQuery.h" +#include "CoralBase/AttributeList.h" +#include "POOLCore/POOLContext.h" +#include "SealKernel/Context.h" + +int main( int, char** ) +{ + try { + pool::POOLContext::loadComponent + ( "SEAL/Services/MessageService" ); + pool::POOLContext::loadComponent + ( "POOL/Services/XMLAuthenticationService" ); + pool::POOLContext::loadComponent + ( "POOL/Services/RelationalService" ); + pool::POOLContext::setMessageVerbosityLevel + ( seal::Msg::Warning ); + seal::MessageStream log + ( pool::POOLContext::context(), "BoolIO_Test" ); + seal::IHandle<pool::IRelationalService> + serviceHandle = + pool::POOLContext::context()->query<pool::IRelationalService> + ( "POOL/Services/RelationalService" ); + if ( ! serviceHandle ) { + throw std::runtime_error( "Could not retrieve the relational service" ); + } + + std::string connectionString = "oracle://devdb10/lcg_cool"; + //std::string connectionString = "mysql://pcitdb59/COOLDB"; + pool::IRelationalDomain& domain = + serviceHandle->domainForConnection( connectionString ); + + // Creating a session + std::auto_ptr< pool::IRelationalSession > + session( domain.newSession( connectionString ) ); + + // Establish a connection with the server + std::cout << "Connecting to " << connectionString << std::endl; + if ( ! session->connect() ) { + throw std::runtime_error( "Could not connect to the database server." ); + } + + // Table name + std::string tableName = "TEST_BOOL_IO"; + + // INSERT DATA + { + // Start a transaction + std::cout << "Starting a new transaction" << std::endl; + if ( ! session->transaction().start() ) { + throw std::runtime_error( "Could not start a new transaction." ); + } + + // Droping old table + if ( session->userSchema().existsTable( tableName ) ) { + std::cout << "Deleting table '" << tableName << "'" << std::endl; + if ( ! session->userSchema().dropTable( tableName ) ) { + throw std::runtime_error( "Could not drop a table." ); + } + } + + // Creating the description for the table + std::auto_ptr< pool::IRelationalEditableTableDescription > description + ( new pool::RelationalAccess::RelationalEditableTableDescription + ( log, domain.flavorName() ) ); + description->insertColumn + ( "id", pool::AttributeStaticTypeInfo<int>::type_name() ); + description->insertColumn + ( "flag", pool::AttributeStaticTypeInfo<bool>::type_name() ); + description->insertColumn + ( "comment", pool::AttributeStaticTypeInfo<std::string>::type_name() ); + + // Create the table. + std::cout << "Creating table '" << tableName << "'" << std::endl; + pool::IRelationalTable& table = + session->userSchema().createTable( tableName, *description ); + + // Costructing a row buffer. + pool::AttributeListSpecification spec; + spec.push_back + ( "id", pool::AttributeStaticTypeInfo<int>::type_name() ); + spec.push_back + ( "flag", pool::AttributeStaticTypeInfo<bool>::type_name() ); + spec.push_back + ( "comment", pool::AttributeStaticTypeInfo<std::string>::type_name() ); + pool::AttributeList data( spec ); + // NB This is OK on Oracle but fails on MySQL! + //pool::AttributeList data( table.description().columnNamesAndTypes() ); + + // Adding new rows + std::cout << "Inserting new rows into the table." << std::endl; + pool::IRelationalBulkRowInserter& rowInserter = + table.dataEditor().bulkRowInserter(); + if ( ! rowInserter.setup( data, 500 ) ) { + throw std::runtime_error( "Could not bind a new row for inserting." ); + } + std::cout << "Prepared the bulk row inserter." << std::endl; + + data["id"].setValue<int>( 1 ); + data["flag"].setValue<bool>( false ); + data["comment"].setValue<std::string>( "false - bulk" ); + std::cout << "Insert: "; data.print( std::cout ); std::cout << std::endl; + if ( ! rowInserter.insertNewRow() ) + throw std::runtime_error + ( "Could not bulk insert a new row into the table." ); + + data["id"].setValue<int>( 2 ); + data["flag"].setValue<bool>( true ); + data["comment"].setValue<std::string>( "true - bulk" ); + std::cout << "Insert: "; data.print( std::cout ); std::cout << std::endl; + if ( ! rowInserter.insertNewRow() ) + throw std::runtime_error + ( "Could not bulk insert a new row into the table." ); + if ( ! rowInserter.flushCache() ) + throw std::runtime_error + ( "Could not flush the remaining rows into the table." ); + + data["id"].setValue<int>( 3 ); + data["flag"].setValue<bool>( false ); + data["comment"].setValue<std::string>( "false - no bulk" ); + std::cout << "Insert: "; data.print( std::cout ); std::cout << std::endl; + if ( ! table.dataEditor().insertNewRow( data ) ) + throw std::runtime_error + ( "Could not single insert a new row into the table." ); + + data["id"].setValue<int>( 4 ); + data["flag"].setValue<bool>( true ); + data["comment"].setValue<std::string>( "true - no bulk" ); + std::cout << "Insert: "; data.print( std::cout ); std::cout << std::endl; + if ( ! table.dataEditor().insertNewRow( data ) ) + throw std::runtime_error + ( "Could not single insert a new row into the table." ); + + // Committing the transaction + std::cout << "Committing..." << std::endl; + if ( ! session->transaction().commit() ) { + throw std::runtime_error( "Could not commit the transaction." ); + } + } + + // READ BACK THE DATA + { + + // Start a transaction + std::cout << "Starting a new transaction" << std::endl; + if ( ! session->transaction().start() ) { + throw std::runtime_error( "Could not start a new transaction." ); + } + + // Prepare the query the table + pool::IRelationalTable& table = + session->userSchema().tableHandle( tableName ); + std::auto_ptr< pool::IRelationalQuery > query( table.createQuery() ); + query->addToOutputList( "id" ); + query->addToOutputList( "flag" ); + query->addToOutputList( "comment" ); + + // This is only needed for MySQL (else bool is read back as char) + pool::AttributeListSpecification spec; + spec.push_back + ( "id", pool::AttributeStaticTypeInfo<int>::type_name() ); + spec.push_back + ( "flag", pool::AttributeStaticTypeInfo<bool>::type_name() ); + spec.push_back + ( "comment", pool::AttributeStaticTypeInfo<std::string>::type_name() ); + query->defineOutput( spec ); + + // Query the table + pool::IRelationalCursor& cursor = query->process(); + if ( cursor.start() ) { + while ( cursor.next() ) { + const pool::AttributeList& row = cursor.currentRow(); + std::cout<<"Read back: "; row.print(std::cout); std::cout<<std::endl; + } + } + + // Committing the transaction + std::cout << "Committing..." << std::endl; + if ( ! session->transaction().commit() ) { + throw std::runtime_error( "Could not commit the transaction." ); + } + + } + + // Disconnecting + std::cout << "Disconnecting..." << std::endl; + session->disconnect(); + + std::cout << "Exiting..." << std::endl; + } + catch ( pool::RelationalException& re ) { + std::cerr << "Relational exception from module " + << re.flavorName() << std::endl + << " " << re.what() << std::endl; + return 1; + } + catch ( std::exception& e ) { + std::cerr << "Standard C++ exception : " << e.what() << std::endl; + return 1; + } + catch ( ... ) { + std::cerr << "Exception caught (...)" << std::endl; + return 1; + } + return 0; +} + +#endif // NOPORT diff --git a/RelationalCool/tests/BoolIO/boolIO.txt.MySQL b/RelationalCool/tests/BoolIO/boolIO.txt.MySQL new file mode 100644 index 000000000..b701e05fe --- /dev/null +++ b/RelationalCool/tests/BoolIO/boolIO.txt.MySQL @@ -0,0 +1,25 @@ +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +Connecting to mysql://pcitdb59/COOLDB +Starting a new transaction +Deleting table 'TEST_BOOL_IO' +Creating table 'TEST_BOOL_IO' +Inserting new rows into the table. +Prepared the bulk row inserter. +Insert: attribute list: size = 3 [ 1 as id:int, 0 as flag:bool, false - bulk as comment:string ] +Insert: attribute list: size = 3 [ 2 as id:int, 1 as flag:bool, true - bulk as comment:string ] +Insert: attribute list: size = 3 [ 3 as id:int, 0 as flag:bool, false - no bulk as comment:string ] +Insert: attribute list: size = 3 [ 4 as id:int, 1 as flag:bool, true - no bulk as comment:string ] +Committing... +Starting a new transaction +Read back: attribute list: size = 3 [ 1 as id:int, 1 as flag:bool, false - bulk as comment:string ] +Read back: attribute list: size = 3 [ 2 as id:int, 1 as flag:bool, true - bulk as comment:string ] +Read back: attribute list: size = 3 [ 3 as id:int, 0 as flag:bool, false - no bulk as comment:string ] +Read back: attribute list: size = 3 [ 4 as id:int, 1 as flag:bool, true - no bulk as comment:string ] +Committing... +Disconnecting... +Exiting... diff --git a/RelationalCool/tests/BoolIO/boolIO.txt.Oracle b/RelationalCool/tests/BoolIO/boolIO.txt.Oracle new file mode 100644 index 000000000..84eaed991 --- /dev/null +++ b/RelationalCool/tests/BoolIO/boolIO.txt.Oracle @@ -0,0 +1,25 @@ +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +Connecting to oracle://devdb/conddb_test +Starting a new transaction +Deleting table 'TEST_BOOL_IO' +Creating table 'TEST_BOOL_IO' +Inserting new rows into the table. +Prepared the bulk row inserter. +Insert: attribute list: size = 3 [ 1 as id:int, 0 as flag:bool, false - bulk as comment:string ] +Insert: attribute list: size = 3 [ 2 as id:int, 1 as flag:bool, true - bulk as comment:string ] +Insert: attribute list: size = 3 [ 3 as id:int, 0 as flag:bool, false - no bulk as comment:string ] +Insert: attribute list: size = 3 [ 4 as id:int, 1 as flag:bool, true - no bulk as comment:string ] +Committing... +Starting a new transaction +Read back: attribute list: size = 3 [ 1 as id:int, 1 as flag:bool, false - bulk as comment:string ] +Read back: attribute list: size = 3 [ 2 as id:int, 1 as flag:bool, true - bulk as comment:string ] +Read back: attribute list: size = 3 [ 3 as id:int, 0 as flag:bool, false - no bulk as comment:string ] +Read back: attribute list: size = 3 [ 4 as id:int, 1 as flag:bool, true - no bulk as comment:string ] +Committing... +Disconnecting... +Exiting... diff --git a/RelationalCool/tests/BuildFile b/RelationalCool/tests/BuildFile new file mode 100644 index 000000000..b1d4e7701 --- /dev/null +++ b/RelationalCool/tests/BuildFile @@ -0,0 +1,31 @@ +<use name=CoolApplication> +<external ref=cppunit> + +# Dependency on CORAL RelationalAccess +# [Package granularity dropped: inherit dependency on all CORAL via CoolKernel] +###<external ref=CORAL use=RelationalAccess></external> + +# Skip unnecessary SCRAM build to save time +<skip dir=AttributeList> +<skip dir=AttributeListDump> +<skip dir=BoolIO> +<skip dir=CMS_ECAL> +<skip dir=CMS_extRef> +<skip dir=ClobIO> +<skip dir=CreateDatabase> +<skip dir=Int64IO> +<skip dir=MemoryConsumption> +<skip dir=MyODBCBulkTest> +<skip dir=MyTest> +<skip dir=Performance> +<skip dir=PerformanceAV> +<skip dir=Privileges> +<skip dir=ProcMemory> +<skip dir=RalDatabase_versioning> +<skip dir=Regression> +#<skip dir=SchemaDump> +<skip dir=SchemaEvolution> +<skip dir=Skeleton> +<skip dir=StressTest> +<skip dir=TransactionHandling> + diff --git a/RelationalCool/tests/CMS_ECAL/README.CMS_ECAL b/RelationalCool/tests/CMS_ECAL/README.CMS_ECAL new file mode 100644 index 000000000..5424125d7 --- /dev/null +++ b/RelationalCool/tests/CMS_ECAL/README.CMS_ECAL @@ -0,0 +1,3 @@ +Timing for inserting 9.6M rows (12000 channels * 800 keys): +2080.040u 7.970s 46:52.27 74.2% 0+0k 0+0io 2527pf+0w + diff --git a/RelationalCool/tests/CMS_ECAL/testCmsEcal.cpp b/RelationalCool/tests/CMS_ECAL/testCmsEcal.cpp new file mode 100644 index 000000000..36ee4df97 --- /dev/null +++ b/RelationalCool/tests/CMS_ECAL/testCmsEcal.cpp @@ -0,0 +1,254 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +// $Id: testCmsEcal.cpp,v 1.14 2008-08-27 09:34:27 avalassi Exp $ + +// Include files +#include <iostream> +#include <sstream> +#include <string> +#include "AttributeList/AttributeList.h" +#include "CoolKernel/DatabaseId.h" +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IFolderSet.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "src/CoralApplication.h" +#include "src/sleep.h" +#include "src/timeToString.h" +#include "src/uppercaseString.h" + +// Namespace +using namespace cool; + +// Message output +#define LOG std::cout << "__main " + +//----------------------------------------------------------------------------- + +int main ( int /* argc */, char* /* argv[] */ ) +{ + + LOG << "Entering main" << std::endl; + int status = -1; + + // Connection string + std::string connectString; + if ( getenv( "COOLCMSECALDB" ) ) { + connectString = getenv( "COOLCMSECALDB" ); + } else { + std::cout << "Please provide a connect string in " + << "the environment variable COOLCMSECALDB, e.g." + << std::endl; + std::cout << "setenv COOLCMSECALDB " + << "\"oracle://cooldb2;schema=AVALASSICMS;" + << "user=avalassicms;password=PASSWORD;dbname=CMS_ECAL\"" + << std::endl; + std::cout << "setenv COOLCMSECALDB " + << "\"mysql://lxb0771;schema=AVALASSICMS;" + << "user=avalassicms;password=PASSWORD;dbname=CMS_ECAL\"" + << std::endl; + std::cout << "Aborting test" << std::endl; + exit(-1); + } + + try { + + LOG << "Get a handle to the COOL database service" << std::endl; + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + + //------------------------ + // DEFINE THE DATABASE ID + //------------------------ + + cool::DatabaseId dbId = connectString; + + //-------------------------------- + // DROP THE DATABASE IF IT EXISTS + //-------------------------------- + + // Drop the COOL conditions database if it already exists + LOG << "Drop if it exists the conditions database: " << dbId << std::endl; + dbSvc.dropDatabase( dbId ); + + //----------------------- + // CREATE A NEW DATABASE + //----------------------- + + // Create a new COOL conditions database + LOG << "Create a new conditions database: " << dbId << std::endl; + cool::IDatabasePtr db1 = dbSvc.createDatabase( dbId ); + LOG << "Conditions database created: " << std::endl; + LOG << "-> Database ID: " << db1->databaseId() << std::endl; + std::ostringstream dbAttr; + db1->databaseAttributes().print( dbAttr ); + LOG << "-> Database attributes: " << dbAttr.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::sleep(1); + + // Create pedestal folder + pool::AttributeListSpecification folderPedSpec; + folderPedSpec.push_back("value00","long"); + std::string folderPedName( "/cms/ecal/pedestals" ); + cool::IFolderPtr folderPed = db1->createFolder + ( folderPedName, folderPedSpec, "", + FolderVersioning::SINGLE_VERSION, true ); + LOG << "Folder created: " << std::endl; + LOG << "-> Folder name: " << folderPed->fullPath() << std::endl; + std::ostringstream folderPedAttr; + folderPed->payloadSpecification().print( folderPedAttr ); + LOG << "-> Folder payload specification: " + << folderPedAttr.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::sleep(1); + + // Print the list of folders + std::vector<std::string> folderList; + std::vector<std::string>::iterator folderIt; + folderList = db1->getFolderSet( "/cms/ecal" )->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + + // Bulk insert data into pedestal folder + // In online folders, until=+infinity means valid until next iov + //unsigned nChannels = 60000; + unsigned nChannels = 12000; + unsigned nKeys = 800; + //unsigned nKeys = 100; + unsigned chId; + ValidityKey key; + ValidityKey plusInfinity = ValidityKeyMax; + pool::AttributeList folderPedData( folderPedSpec ); + folderPed->setupStorageBuffer(); + for ( chId = 1; chId <= nChannels; chId ++ ) { + for ( key = 1; key <= nKeys; key ++ ) { + folderPedData["value00"].setValue<long>( (long)key*100000+chId ); + folderPed->storeObject( key*10, plusInfinity, folderPedData, chId ); + } + // Hack: bulk insertion into different channels is not supported yet! + folderPed->flushStorageBuffer(); + } + // NO: bulk insertion into different channels is not supported yet! + //folderPed->flushStorageBuffer(); + + // Dump the object stored for time t=55 in channel 13 + IObjectPtr objPed_ch13_55 = folderPed->findObject( 55, 13 ); + LOG << "Retrieved object valid at t=55 in channel 13 of folder " + << folderPed->fullPath() << std::endl; + LOG << "Object: channelId=" << objPed_ch13_55->channelId() << std::endl; + LOG << "Object: since=" << objPed_ch13_55->since() + << ", until=" << objPed_ch13_55->until() << std::endl; + LOG << "Object: payload values (true types)" + << ": payload[\"value00\"]=" + << objPed_ch13_55->payloadValue<long>("value00") + << std::endl; + LOG << "Object: payload values (as strings)" + << ": payload[\"value00\"]=" + << objPed_ch13_55->payloadValue("value00") + << std::endl; + if( ! objPed_ch13_55->isStored() ) { + LOG << "Object: isStored=false" << std::endl; + } else { + LOG << "Object: isStored=true" << std::endl; + LOG << "Object: insertionTime=" + << timeToString( objPed_ch13_55->insertionTime() ) << std::endl;; + } + + // Reset the database pointer: this will close the connection + LOG << "Release the conditions database connection" << std::endl; + cool::IDatabasePtr dbNull; + db1 = dbNull; + + //--------------------------- + // OPEN AN EXISTING DATABASE + //--------------------------- + + // Open an existing COOL conditions database + LOG << "Open an existing conditions database: " << dbId << std::endl; + cool::IDatabasePtr db2 = dbSvc.openDatabase( dbId, false ); + LOG << "Conditions database opened: " << std::endl; + LOG << "-> Database ID: " << db2->databaseId() << std::endl; + std::ostringstream db2Attr; + db2->databaseAttributes().print( db2Attr ); + LOG << "-> Database attributes: " << db2Attr.str() << std::endl; + + // Print the list of folders + folderList = db2->getFolderSet( "/cms/ecal" )->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + + // *** WARNING!! *** + // You MUST get a new handle to the folder here: the old one is invalid and + // causes a segmentation fault. A protection must be added in the code! + folderPed = db2->getFolder( folderPedName ); + + // Bulk-retrieve the objects stored in channel 13 in [45,95] + std::string tag = ""; + ChannelId channelId = 13; + ValidityKey since = 45; + ValidityKey until = 95; + IObjectIteratorPtr objIt = + folderPed->browseObjects( since, until, channelId, tag ); + LOG << "Retrieved object iterator in [45,95] for channel 13 of folder " + << folderPed->fullPath() << std::endl; + if ( objIt->isEmpty() ) { + LOG << "Iterator contains no objects" << std::endl; + } else { + objIt->goToStart(); + while( objIt->hasNext() ) { + IObjectPtr object = objIt->next(); + LOG << "Object: channelId=" << object->channelId() + << ", since=" << object->since() + << ", until=" << object->until() << std::endl; + LOG << "Object: payload values (true types)" + << ": payload[\"value00\"]=" + << object->payloadValue<long>("value00") + << std::endl; + if( ! object->isStored() ) { + LOG << "Object: isStored=false" << std::endl; + } else { + LOG << "Object: isStored=true, insertionTime=" + << timeToString( object->insertionTime() ) << std::endl;; + } + } + } + + // Successful completion + LOG << "Program terminating succesfully" << std::endl; + status = 0; + + } + catch(std::exception& e) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + status = 1; + } + catch(...) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + status = 1; + } + + // Program termination + LOG << "Exiting main" << std::endl; + return status; + +} + +//----------------------------------------------------------------------------- + +#endif // NOPORT diff --git a/RelationalCool/tests/CMS_extRef/extraSQL.sql b/RelationalCool/tests/CMS_extRef/extraSQL.sql new file mode 100644 index 000000000..e107bb977 --- /dev/null +++ b/RelationalCool/tests/CMS_extRef/extraSQL.sql @@ -0,0 +1,41 @@ + +/* +-- To restart from scratch... +alter table CMSCALIB_F0003_IOVS drop constraint CMSCALIB_F0003_IOVS_CHS_FK; +alter table CMSCALIB_F0003_IOVS drop constraint CMSCALIB_F0003_IOVS_CALSET_FK; +drop table CMSCALIB_F0003_CHANNELS; +drop table CMSCALIB_EXT_CALIBSET; +*/ + +create table CMSCALIB_F0003_CHANNELS +( channel_id number(38), channel_description varchar2(1024) ); + +alter table CMSCALIB_F0003_CHANNELS +add constraint CMSCALIB_F0003_CHANNELS_PK primary key ( channel_id ); + +insert into CMSCALIB_F0003_CHANNELS +select distinct channel_id, +'Calibration channel '||channel_id from CMSCALIB_F0003_IOVS; + +alter table CMSCALIB_F0003_IOVS +add constraint CMSCALIB_F0003_IOVS_CHS_FK +foreign key ( channel_id ) +references CMSCALIB_F0003_CHANNELS ( channel_id ); + +create table CMSCALIB_EXT_CALIBSET +( calset_id number(38), calibset_description varchar2(1024) ); + +alter table CMSCALIB_EXT_CALIBSET +add constraint CMSCALIB_CALIBSET_PK primary key ( calset_id ); + +insert into CMSCALIB_EXT_CALIBSET +select distinct calset_id, +'Calibration set '||calset_id from CMSCALIB_F0003_IOVS; + +alter table CMSCALIB_F0003_IOVS +add constraint CMSCALIB_F0003_IOVS_CALSET_FK +foreign key ( calset_id ) +references CMSCALIB_EXT_CALIBSET ( calset_id ); + + + diff --git a/RelationalCool/tests/CMS_extRef/testCmsExtRef.cpp b/RelationalCool/tests/CMS_extRef/testCmsExtRef.cpp new file mode 100644 index 000000000..f8c640e83 --- /dev/null +++ b/RelationalCool/tests/CMS_extRef/testCmsExtRef.cpp @@ -0,0 +1,267 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +// $Id: testCmsExtRef.cpp,v 1.13 2008-08-27 09:34:27 avalassi Exp $ + +// Include files +#include <iostream> +#include <sstream> +#include "AttributeList/AttributeList.h" +#include "CoolKernel/DatabaseId.h" +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IFolderSet.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "src/CoralApplication.h" +#include "src/sleep.h" +#include "src/timeToString.h" +#include "src/uppercaseString.h" + +// Namespace +using namespace cool; + +// Message output +#define LOG std::cout << "__main " + +//----------------------------------------------------------------------------- + +int main ( int /* argc */, char* /* argv[] */ ) +{ + + LOG << "Entering main" << std::endl; + int status = -1; + + // Connection string + std::string connectString; + if ( getenv( "COOLCMSEXTDB" ) ) { + connectString = getenv( "COOLCMSEXTDB" ); + } else { + std::cout << "Please provide a connect string in " + << "the environment variable COOLCMSEXTDB, e.g." + << std::endl; + std::cout << "setenv COOLCMSEXTDB " + << "\"oracle://cooldb2;schema=AVALASSI;" + << "user=avalassi;password=PASSWORD;dbname=CMSCALIB\"" + << std::endl; + std::cout << "setenv COOLCMSEXTDB " + << "\"mysql://lxb0771;schema=AVALASSI;" + << "user=avalassi;password=PASSWORD;dbname=CMSCALIB\"" + << std::endl; + std::cout << "Aborting test" << std::endl; + exit(-1); + } + + try { + + LOG << "Get a handle to the COOL database service" << std::endl; + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + + //------------------------ + // DEFINE THE DATABASE ID + //------------------------ + + cool::DatabaseId dbId = connectString; + + //-------------------------------- + // DROP THE DATABASE IF IT EXISTS + //-------------------------------- + + // Drop the COOL conditions database if it already exists + LOG << "Drop if it exists the conditions database: " << dbId << std::endl; + dbSvc.dropDatabase( dbId ); + + //----------------------- + // CREATE A NEW DATABASE + //----------------------- + + // Create a new COOL conditions database + LOG << "Create a new conditions database: " << dbId << std::endl; + cool::IDatabasePtr db1 = dbSvc.createDatabase( dbId ); + LOG << "Conditions database created: " << std::endl; + LOG << "-> Database ID: " << db1->databaseId() << std::endl; + std::ostringstream dbAttr; + db1->databaseAttributes().print( dbAttr ); + LOG << "-> Database attributes: " << dbAttr.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::sleep(1); + + // Create calibration folder + pool::AttributeListSpecification folderCalSpec; + folderCalSpec.push_back("CALSET_ID","long"); + std::string folderCalName( "/cms/hcal/calibration" ); + cool::IFolderPtr folderCal = db1->createFolder + ( folderCalName, folderCalSpec, "", + FolderVersioning::MULTI_VERSION, true ); + LOG << "Folder created: " << std::endl; + LOG << "-> Folder name: " << folderCal->fullPath() << std::endl; + std::ostringstream folderCalAttr; + folderCal->payloadSpecification().print( folderCalAttr ); + LOG << "-> Folder payload specification: " + << folderCalAttr.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::sleep(1); + + // Print the list of folders + std::vector<std::string> folderList; + std::vector<std::string>::iterator folderIt; + folderList = db1->getFolderSet( "/cms/hcal" )->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + + /* + // Define an external reference constraint on the folder payload columns + std::string constraintName = "CALIBSET"; + std::vector<std::string> attributes; + attributes.push_back( "CALSET_ID" ); + std::string referencedEntity = + "local://schema=AVALASSI;table=CMS_EXT_CALIBRATION_SETS"; + std::vector<std::string> referencedAttributes; + referencedAttributes.push_back( "SET_ID" ); + folderCal->declareExternalReference + ( constraintName, attributes, referencedEntity, referencedAttributes ); + */ + + // Bulk insert data into caibration folder + // In online folders, until=+infinity means valid until next iov + unsigned nChannels = 10; + unsigned nKeys = 20; + unsigned chId; + unsigned key; + ValidityKey plusInfinity = ValidityKeyMax; + pool::AttributeList folderCalData( folderCalSpec ); + folderCal->setupStorageBuffer(); + for ( chId = 1; chId <= nChannels; chId ++ ) { + for ( key = 1; key <= nKeys; key ++ ) { + folderCalData["CALSET_ID"].setValue<long> + ( (long)10*(key-key/3*3)+chId ); + folderCal->storeObject( key*10, plusInfinity, folderCalData, chId ); + } + // Hack: bulk insertion into different channels is not supported yet! + folderCal->flushStorageBuffer(); + } + // NO: bulk insertion into different channels is not supported yet! + //folderCal->flushStorageBuffer(); + + // Dump the object stored for time t=55 in channel 7 + IObjectPtr objPed_ch7_55 = folderCal->findObject( 55, 7 ); + LOG << "Retrieved object valid at t=55 in channel 7 of folder " + << folderCal->fullPath() << std::endl; + LOG << "Object: channelId=" << objPed_ch7_55->channelId() << std::endl; + LOG << "Object: since=" << objPed_ch7_55->since() + << ", until=" << objPed_ch7_55->until() << std::endl; + LOG << "Object: payload values (true types)" + << ": payload[\"CALSET_ID\"]=" + << objPed_ch7_55->payloadValue<long>("CALSET_ID") + << std::endl; + LOG << "Object: payload values (as strings)" + << ": payload[\"CALSET_ID\"]=" + << objPed_ch7_55->payloadValue("CALSET_ID") + << std::endl; + if( ! objPed_ch7_55->isStored() ) { + LOG << "Object: isStored=false" << std::endl; + } else { + LOG << "Object: isStored=true" << std::endl; + LOG << "Object: insertionTime=" + << timeToString( objPed_ch7_55->insertionTime() ) << std::endl;; + } + + // Reset the database pointer: this will close the connection + LOG << "Release the conditions database connection" << std::endl; + cool::IDatabasePtr dbNull; + db1 = dbNull; + + /* + //--------------------------- + // OPEN AN EXISTING DATABASE + //--------------------------- + + // Open an existing COOL conditions database + LOG << "Open an existing conditions database: " << dbId << std::endl; + cool::IDatabasePtr db2 = dbSvc.openDatabase( dbId ); + LOG << "Conditions database opened: " << std::endl; + LOG << "-> Database ID: " << db2->databaseId() << std::endl; + std::ostringstream db2Attr; + db2->databaseAttributes().print( db2Attr ); + LOG << "-> Database attributes: " << db2Attr.str() << std::endl; + + // Print the list of folders + folderList = db2->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + + // *** WARNING!! *** + // You MUST get a new handle to the folder here: the old one is invalid and + // causes a segmentation fault. A protection must be added in the code! + folderCal = db2->getFolder( folderCalName ); + + // Bulk-retrieve the objects stored in channel 7 in [45,95] + std::string tag = ""; + ChannelId channelId = 7; + ValidityKey since = 45; + ValidityKey until = 95; + IObjectIteratorPtr objIt = + folderCal->browseObjects( since, until, channelId, tag ); + LOG << "Retrieved object iterator in [45,95] for channel 7 of folder " + << folderCal->fullPath() << std::endl; + if ( objIt->isEmpty() ) { + LOG << "Iterator contains no objects" << std::endl; + } else { + objIt->goToStart(); + while( objIt->hasNext() ) { + IObjectPtr object = objIt->next(); + LOG << "Object: channelId=" << object->channelId() + << ", since=" << object->since() + << ", until=" << object->until() << std::endl; + LOG << "Object: payload values (true types)" + << ": payload[\"CALSET_ID\"]=" + << object->payloadValue<long>("CALSET_ID") + << std::endl; + if( ! object->isStored() ) { + LOG << "Object: isStored=false" << std::endl; + } else { + LOG << "Object: isStored=true, insertionTime=" + << timeToString( object->insertionTime() ) << std::endl;; + } + } + } + */ + + // Successful completion + LOG << "Program terminating succesfully" << std::endl; + status = 0; + + } + catch(std::exception& e) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + status = 1; + } + catch(...) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + status = 1; + } + + // Program termination + LOG << "Exiting main" << std::endl; + return status; + +} + +//----------------------------------------------------------------------------- + +#endif // NOPORT diff --git a/RelationalCool/tests/ChannelSelection/test_ChannelSelection.cpp b/RelationalCool/tests/ChannelSelection/test_ChannelSelection.cpp new file mode 100644 index 000000000..d4b879cea --- /dev/null +++ b/RelationalCool/tests/ChannelSelection/test_ChannelSelection.cpp @@ -0,0 +1,356 @@ +// $Id: test_ChannelSelection.cpp,v 1.6 2009-01-06 13:54:38 avalassi Exp $ +/** + +@file test_ChannelSelection.cpp + +@author Sven A. Schmidt and Marco Clemencic + +@date 2006-04-25 + +*/ + +#include "CoolUnitTest.h" + +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/Exception.h" + +namespace cool +{ + + class ChannelSelectionTest : public CoolUnitTest + { + + CPPUNIT_TEST_SUITE( ChannelSelectionTest ); + + CPPUNIT_TEST( test_default_constructor ); + CPPUNIT_TEST( test_from_int ); + CPPUNIT_TEST( test_order ); + CPPUNIT_TEST( test_InvalidChannelRange ); + CPPUNIT_TEST( test_range ); + CPPUNIT_TEST( test_range_order ); + CPPUNIT_TEST( test_all ); + CPPUNIT_TEST( test_ChannelRange ); + CPPUNIT_TEST( test_ChannelRange_inRange ); + CPPUNIT_TEST( test_inSelection ); + CPPUNIT_TEST( test_addRange ); + CPPUNIT_TEST( test_addRange_outOfOrder ); + CPPUNIT_TEST( test_addRange_overlap ); + CPPUNIT_TEST( test_isContiguous ); + CPPUNIT_TEST( test_addChannel ); + CPPUNIT_TEST( test_addChannel_outOfOrder ); + CPPUNIT_TEST( test_addChannel_overlap ); + CPPUNIT_TEST( test_channelName_constructor ); + CPPUNIT_TEST( test_non_numeric_exceptions ); + CPPUNIT_TEST( test_numeric_exceptions ); + CPPUNIT_TEST( test_inSelection_string ); + + CPPUNIT_TEST_SUITE_END(); + + public: + + void test_default_constructor() { + ChannelSelection s; + CPPUNIT_ASSERT_EQUAL( (ChannelId)0, s.firstChannel() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)4294967295ul, s.lastChannel() ); + CPPUNIT_ASSERT_EQUAL( ChannelSelection::channelBeforeSince, s.order() ); + CPPUNIT_ASSERT( s.allChannels() ); + CPPUNIT_ASSERT( s.isNumeric() ); + } + + + void test_from_int() { + ChannelSelection s( 5 ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)5, s.firstChannel() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)5, s.lastChannel() ); + CPPUNIT_ASSERT_EQUAL( ChannelSelection::channelBeforeSince, s.order() ); + CPPUNIT_ASSERT( ! s.allChannels() ); + CPPUNIT_ASSERT( s.isNumeric() ); + } + + + void test_order() { + ChannelSelection s( ChannelSelection::sinceBeforeChannel ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)0, s.firstChannel() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)4294967295ul, s.lastChannel() ); + CPPUNIT_ASSERT_EQUAL( ChannelSelection::sinceBeforeChannel, s.order() ); + CPPUNIT_ASSERT( s.allChannels() ); + CPPUNIT_ASSERT( s.isNumeric() ); + } + + + /// Tests exceptional behavior of the ChannelSelection constructor + void test_InvalidChannelRange() { + CPPUNIT_ASSERT_THROW( ChannelSelection s( 3, 2 ), + InvalidChannelRange ); + } + + void test_range() { + ChannelSelection s( 5, 10 ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)5, s.firstChannel() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)10, s.lastChannel() ); + CPPUNIT_ASSERT_EQUAL( ChannelSelection::channelBeforeSince, s.order() ); + CPPUNIT_ASSERT( ! s.allChannels() ); + CPPUNIT_ASSERT( s.isNumeric() ); + } + + + void test_range_order() { + ChannelSelection s( 5, 10, ChannelSelection::sinceBeforeChannel ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)5, s.firstChannel() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)10, s.lastChannel() ); + CPPUNIT_ASSERT_EQUAL( ChannelSelection::sinceBeforeChannel, s.order() ); + CPPUNIT_ASSERT( ! s.allChannels() ); + CPPUNIT_ASSERT( s.isNumeric() ); + } + + + void test_all() { + ChannelSelection s = ChannelSelection::all(); + CPPUNIT_ASSERT_EQUAL( (ChannelId)0, s.firstChannel() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)4294967295ul, s.lastChannel() ); + CPPUNIT_ASSERT_EQUAL( ChannelSelection::channelBeforeSince, s.order() ); + CPPUNIT_ASSERT( s.allChannels() ); + CPPUNIT_ASSERT( s.isNumeric() ); + } + + + void test_ChannelRange() { + ChannelSelection::ChannelRange r( 2, 4 ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)2, r.firstChannel() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)4, r.lastChannel() ); + } + + + void test_ChannelRange_inRange() { + ChannelSelection::ChannelRange r( 2, 4 ); + CPPUNIT_ASSERT( ! r.inRange( 1 ) ); + CPPUNIT_ASSERT( r.inRange( 2 ) ); + CPPUNIT_ASSERT( r.inRange( 3 ) ); + CPPUNIT_ASSERT( r.inRange( 4 ) ); + CPPUNIT_ASSERT( ! r.inRange( 5 ) ); + } + + + void test_inSelection() { + ChannelSelection s( 2, 4 ); + CPPUNIT_ASSERT( ! s.inSelection( 1 ) ); + CPPUNIT_ASSERT( s.inSelection( 2 ) ); + CPPUNIT_ASSERT( s.inSelection( 3 ) ); + CPPUNIT_ASSERT( s.inSelection( 4 ) ); + CPPUNIT_ASSERT( ! s.inSelection( 5 ) ); + } + + + void test_addRange() { + ChannelSelection s( 2, 4 ); + s.addRange( 6, 8 ); + CPPUNIT_ASSERT( ! s.inSelection( 1 ) ); + CPPUNIT_ASSERT( s.inSelection( 2 ) ); + CPPUNIT_ASSERT( s.inSelection( 3 ) ); + CPPUNIT_ASSERT( s.inSelection( 4 ) ); + CPPUNIT_ASSERT( ! s.inSelection( 5 ) ); + CPPUNIT_ASSERT( s.inSelection( 6 ) ); + CPPUNIT_ASSERT( s.inSelection( 7 ) ); + CPPUNIT_ASSERT( s.inSelection( 8 ) ); + CPPUNIT_ASSERT( ! s.inSelection( 9 ) ); + CPPUNIT_ASSERT( ! s.isContiguous() ); + } + + + void test_addRange_outOfOrder() { + ChannelSelection s( 6, 8 ); + s.addRange( 2, 4 ); + CPPUNIT_ASSERT( ! s.inSelection( 1 ) ); + CPPUNIT_ASSERT( s.inSelection( 2 ) ); + CPPUNIT_ASSERT( s.inSelection( 3 ) ); + CPPUNIT_ASSERT( s.inSelection( 4 ) ); + CPPUNIT_ASSERT( ! s.inSelection( 5 ) ); + CPPUNIT_ASSERT( s.inSelection( 6 ) ); + CPPUNIT_ASSERT( s.inSelection( 7 ) ); + CPPUNIT_ASSERT( s.inSelection( 8 ) ); + CPPUNIT_ASSERT( ! s.inSelection( 9 ) ); + CPPUNIT_ASSERT( ! s.isContiguous() ); + } + + + /// Tests isContiguous for multiple ranges + void test_isContiguous() { + { + ChannelSelection s( 5, 7 ); + CPPUNIT_ASSERT( s.isContiguous() ); + s.addChannel( 8 ); + CPPUNIT_ASSERT( s.isContiguous() ); + s.addRange( 3, 4 ); + CPPUNIT_ASSERT( s.isContiguous() ); + s.addRange( 9, 10 ); + CPPUNIT_ASSERT( s.isContiguous() ); + s.addRange( 0, 1 ); + CPPUNIT_ASSERT( ! s.isContiguous() ); + } + { + ChannelSelection s( 4, 5 ); + CPPUNIT_ASSERT( s.isContiguous() ); + s.addRange( 7,8 ); + CPPUNIT_ASSERT( ! s.isContiguous() ); + } + } + + + void test_addRange_overlap() { + try { + ChannelSelection s( 6, 8 ); + s.addRange( 2, 7 ); + CPPUNIT_FAIL( "Exception excepted" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string( "Cannot add range [2,7], " + "because it overlaps with " + "selection" ), + std::string( e.what() ) ); + } + try { + ChannelSelection s( 6, 8 ); + s.addRange( 7, 9 ); + CPPUNIT_FAIL( "Exception excepted" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string( "Cannot add range [7,9], " + "because it overlaps with " + "selection" ), + std::string( e.what() ) ); + } + } + + + void test_addChannel() { + ChannelSelection s( 2, 4 ); + s.addChannel( 6 ); + CPPUNIT_ASSERT( ! s.inSelection( 1 ) ); + CPPUNIT_ASSERT( s.inSelection( 2 ) ); + CPPUNIT_ASSERT( s.inSelection( 3 ) ); + CPPUNIT_ASSERT( s.inSelection( 4 ) ); + CPPUNIT_ASSERT( ! s.inSelection( 5 ) ); + CPPUNIT_ASSERT( s.inSelection( 6 ) ); + CPPUNIT_ASSERT( ! s.inSelection( 7 ) ); + CPPUNIT_ASSERT( ! s.isContiguous() ); + } + + + void test_addChannel_outOfOrder() { + ChannelSelection s( 4, 6 ); + s.addChannel( 2 ); + CPPUNIT_ASSERT( ! s.inSelection( 1 ) ); + CPPUNIT_ASSERT( s.inSelection( 2 ) ); + CPPUNIT_ASSERT( ! s.inSelection( 3 ) ); + CPPUNIT_ASSERT( s.inSelection( 4 ) ); + CPPUNIT_ASSERT( s.inSelection( 5 ) ); + CPPUNIT_ASSERT( s.inSelection( 6 ) ); + CPPUNIT_ASSERT( ! s.inSelection( 7 ) ); + CPPUNIT_ASSERT( ! s.isContiguous() ); + } + + + void test_addChannel_overlap() { + try { + ChannelSelection s( 6, 8 ); + s.addChannel( 7 ); + CPPUNIT_FAIL( "Exception excepted" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string( "Cannot add range [7,7], " + "because it overlaps with " + "selection" ), + std::string( e.what() ) ); + } + } + + + void test_channelName_constructor() { + ChannelSelection s( "channel A" ); + CPPUNIT_ASSERT( ! s.isNumeric() ); + CPPUNIT_ASSERT_EQUAL( ChannelSelection::channelBeforeSince, s.order() ); + CPPUNIT_ASSERT( ! s.allChannels() ); + CPPUNIT_ASSERT_EQUAL( std::string("channel A"), s.channelName() ); + } + + + void test_non_numeric_exceptions() { + ChannelSelection s( "channel A" ); + + try { + s.addChannel( 0 ); + CPPUNIT_FAIL( "Expected exception" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string("Numeric method called for " + "non-numeric ChannelSelection"), + std::string(e.what()) ); + } + try { + s.addRange( 0, 1 ); + CPPUNIT_FAIL( "Expected exception" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string("Numeric method called for " + "non-numeric ChannelSelection"), + std::string(e.what()) ); + } + try { + s.firstChannel(); + CPPUNIT_FAIL( "Expected exception" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string("Numeric method called for " + "non-numeric ChannelSelection"), + std::string(e.what()) ); + } + try { + s.lastChannel(); + CPPUNIT_FAIL( "Expected exception" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string("Numeric method called for " + "non-numeric ChannelSelection"), + std::string(e.what()) ); + } + try { + s.inSelection( 0 ); + CPPUNIT_FAIL( "Expected exception" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string("Numeric method called for " + "non-numeric ChannelSelection"), + std::string(e.what()) ); + } + try { + s.isContiguous(); + CPPUNIT_FAIL( "Expected exception" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string("Numeric method called for " + "non-numeric ChannelSelection"), + std::string(e.what()) ); + } + } + + + void test_numeric_exceptions() { + ChannelSelection s( 0 ); + + try { + s.inSelection( "channel 1" ); + CPPUNIT_FAIL( "Expected exception" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL( std::string("Non-numeric method called for " + "numeric ChannelSelection"), + std::string(e.what()) ); + } + } + + + void test_inSelection_string() { + ChannelSelection s( "channel 1" ); + CPPUNIT_ASSERT( ! s.inSelection( "channel 0" ) ); + CPPUNIT_ASSERT( s.inSelection( "channel 1" ) ); + } + + + }; + +CPPUNIT_TEST_SUITE_REGISTRATION( ChannelSelectionTest ); + +} // namespace + +COOLTEST_MAIN( ChannelSelectionTest ) + diff --git a/RelationalCool/tests/Channels/test_Channels.cpp b/RelationalCool/tests/Channels/test_Channels.cpp new file mode 100644 index 000000000..63c920f11 --- /dev/null +++ b/RelationalCool/tests/Channels/test_Channels.cpp @@ -0,0 +1,685 @@ +/** + +@file test_Channels.cpp + +*/ + +#include "CoolDBUnitTest.h" + +#include "RelationalAccess/IRelationalService.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeListException.h" + +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IField.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordException.h" +#include "CoolKernel/RecordSpecification.h" + +#include "src/RalDatabase.h" +#include "src/RelationalChannelTable.h" +#include "src/RelationalException.h" +#include "src/RelationalFolder.h" +#include "src/RelationalTableRow.h" +#include "src/RelationalTransaction.h" +#include "src/timeToString.h" + +// ---- this things are needed to force a drop of the connection +#include "src/RalDatabaseSvc.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" + +using coral::AttributeList; +using coral::AttributeListSpecification; + +#include <string> +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +#include <vector> +using std::vector; + +namespace cool +{ + + //! \brief Channels test class. + class ChannelsTest : public CoolDBUnitTest + { + + CPPUNIT_TEST_SUITE( ChannelsTest ); + + CPPUNIT_TEST( test_listChannels ); + CPPUNIT_TEST( test_listChannels_order ); + CPPUNIT_TEST( test_listChannelsWithNames ); + + CPPUNIT_TEST( test_createChannel ); + CPPUNIT_TEST( test_dropChannel ); + CPPUNIT_TEST( test_dropChannel_exceptionSV ); + CPPUNIT_TEST( test_dropChannel_exceptionMV ); + CPPUNIT_TEST( test_existsChannel ); + CPPUNIT_TEST( test_channelId ); + CPPUNIT_TEST( test_channelName_exception ); + CPPUNIT_TEST( test_channelDescription_exception ); + CPPUNIT_TEST( test_channelId_exception ); + CPPUNIT_TEST( test_setChannelName ); + CPPUNIT_TEST( test_setChannelDescription ); + + CPPUNIT_TEST( test_channelNameUnique ); + + CPPUNIT_TEST( test_setChannelName_sameName ); + + CPPUNIT_TEST( test_existsChannelSV_withoutCreateChannel ); + CPPUNIT_TEST( test_existsChannelMV_withoutCreateChannel ); + CPPUNIT_TEST( test_setChannelNameSV_withoutCreateChannel ); + CPPUNIT_TEST( test_setChannelNameMV_withoutCreateChannel ); + CPPUNIT_TEST( test_setChannelDescSV_withoutCreateChannel ); + CPPUNIT_TEST( test_setChannelDescMV_withoutCreateChannel ); + CPPUNIT_TEST( test_channelNameSV_withoutCreateChannel ); + CPPUNIT_TEST( test_channelNameMV_withoutCreateChannel ); + CPPUNIT_TEST( test_channelDescSV_withoutCreateChannel ); + CPPUNIT_TEST( test_channelDescMV_withoutCreateChannel ); + + CPPUNIT_TEST( test_existsChannelSV_withCreateChannel_withoutIOVs ); + CPPUNIT_TEST( test_existsChannelMV_withCreateChannel_withoutIOVs ); + + CPPUNIT_TEST( test_listChannelsSV_withoutCreateChannel ); + CPPUNIT_TEST( test_listChannelsMV_withoutCreateChannel ); + CPPUNIT_TEST( test_listChannelsSV_withCreateChannel_withoutIOVs ); + CPPUNIT_TEST( test_listChannelsMV_withCreateChannel_withoutIOVs ); + CPPUNIT_TEST( test_listChannelsSV_withAndWithoutCreateChannel ); + CPPUNIT_TEST( test_listChannelsMV_withAndWithoutCreateChannel ); + + CPPUNIT_TEST_SUITE_END(); + + public: + + RecordSpecification payloadSpec; + + /// Tests setChannelDescription() + void test_setChannelDescription() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->createChannel( 1, "ch 1", "desc 1" ); + CPPUNIT_ASSERT_EQUAL( std::string("desc 1"), + folder->channelDescription( 1 ) ); + folder->setChannelDescription( 1, "new desc" ); + CPPUNIT_ASSERT_EQUAL( std::string("new desc"), + folder->channelDescription( 1 ) ); + try { + folder->setChannelDescription( 2, "new desc" ); + CPPUNIT_FAIL( "ChannelNotFound exception expected" ); + } catch ( ChannelNotFound& ) {} + } + + + /// Tests setChannelName() + void test_setChannelName() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->createChannel( 1, "ch 1", "desc 1" ); + CPPUNIT_ASSERT_EQUAL( std::string("ch 1"), + folder->channelName( 1 ) ); + folder->setChannelName( 1, "new name 1" ); + CPPUNIT_ASSERT_EQUAL( std::string("new name 1"), + folder->channelName( 1 ) ); + try { + folder->setChannelName( 2, "new name 2" ); + CPPUNIT_FAIL( "ChannelNotFound exception expected" ); + } catch ( ChannelNotFound& ) {} + folder->createChannel( 2, "ch 2", "desc 2" ); + CPPUNIT_ASSERT_EQUAL( std::string("ch 2"), + folder->channelName( 2 ) ); + try { + folder->setChannelName( 2, "new name 1" ); + CPPUNIT_FAIL( "ChannelExists exception expected" ); + } catch ( ChannelExists& ) {} + } + + + /// Tests setChannelName() with the same name (bug #23754) + void test_setChannelName_sameName() { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->createChannel( 1, "ch 1", "desc 1" ); + CPPUNIT_ASSERT_EQUAL( std::string("ch 1"), + folder->channelName( 1 ) ); + folder->setChannelName( 1, "ch 1" ); + CPPUNIT_ASSERT_EQUAL( std::string("ch 1"), + folder->channelName( 1 ) ); + } + + + /// Tests existsChannel() for SV folders if createChannel was not called + void test_existsChannelSV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + CPPUNIT_ASSERT_EQUAL + ( true, folder->existsChannel( chId ) ); + } + + + /// Tests existsChannel() for MV folders if createChannel was not called + /// (bug #24449 - also related to bug #23755) + void test_existsChannelMV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + CPPUNIT_ASSERT_EQUAL + ( true, folder->existsChannel( chId ) ); + } + + + /// Tests existsChannel() for SV folders if createChannel was called + /// but there are no IOVs + void test_existsChannelSV_withCreateChannel_withoutIOVs() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + //folder->storeObject( 0, 10, payload, chId ); + folder->createChannel( chId, "MyChannel", " A channel" ); + CPPUNIT_ASSERT_EQUAL + ( true, folder->existsChannel( chId ) ); + } + + + /// Tests existsChannel() for MV folders if createChannel was called + /// but there are no IOVs (bug #30431 - also related to bug #23755) + void test_existsChannelMV_withCreateChannel_withoutIOVs() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + //folder->storeObject( 0, 10, payload, chId ); + folder->createChannel( chId, "MyChannel", "A channel" ); + CPPUNIT_ASSERT_EQUAL + ( true, folder->existsChannel( chId ) ); + } + + + /// Tests listChannels() for SV folders if createChannel was not called + void test_listChannelsSV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + //folder->createChannel( chId, "MyChannel", " A channel" ); + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 1u, (unsigned int)channels.size() ); + } + + + /// Tests listChannels() for MV folders if createChannel was not called + void test_listChannelsMV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + //folder->createChannel( chId, "MyChannel", "A channel" ); + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 1u, (unsigned int)channels.size() ); + } + + + /// Tests listChannels() for SV folders if createChannel was called + /// but there are no IOVs + void test_listChannelsSV_withCreateChannel_withoutIOVs() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + //folder->storeObject( 0, 10, payload, chId ); + folder->createChannel( chId, "MyChannel", " A channel" ); + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 1u, (unsigned int)channels.size() ); + } + + + /// Tests listChannels() for MV folders if createChannel was called + /// but there are no IOVs (bug #30443) + void test_listChannelsMV_withCreateChannel_withoutIOVs() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + //folder->storeObject( 0, 10, payload, chId ); + folder->createChannel( chId, "MyChannel", "A channel" ); + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 1u, (unsigned int)channels.size() ); + } + + + /// Tests listChannels() for SV folders in a complex case + void test_listChannelsSV_withAndWithoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload( payloadSpec ); + ChannelId chId1 = 1; + folder->storeObject( 0, 10, payload, chId1 ); + ChannelId chId2 = 2; + folder->createChannel( chId2, "MyChannel", " A channel" ); + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 2u, (unsigned int)channels.size() ); + } + + + /// Tests listChannels() for MV folders in a complex case + /// This is also affected by bug #30443 in COOL221 + void test_listChannelsMV_withAndWithoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + Record payload( payloadSpec ); + ChannelId chId1 = 1; + folder->storeObject( 0, 10, payload, chId1 ); + ChannelId chId2 = 2; + folder->createChannel( chId2, "MyChannel", "A channel" ); + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 2u, (unsigned int)channels.size() ); + } + + + /// Tests setChannelName() for SV folders if createChannel was not called + void test_setChannelNameSV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + folder->setChannelName( chId, "ch 1" ); + CPPUNIT_ASSERT_EQUAL( std::string("ch 1"), folder->channelName( chId ) ); + } + + + /// Tests setChannelName() for MV folders if createChannel was not called + /// (bug #24445 - also related to bug #23755) + void test_setChannelNameMV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + folder->setChannelName( chId, "ch 1" ); + CPPUNIT_ASSERT_EQUAL( std::string("ch 1"), folder->channelName( chId ) ); + } + + + /// Tests setChannelDescription() for SV if createChannel was not called + void test_setChannelDescSV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + folder->setChannelDescription( chId, "ch 1 desc" ); + CPPUNIT_ASSERT_EQUAL + ( std::string("ch 1 desc"), folder->channelDescription( chId ) ); + } + + + /// Tests setChannelDescription() for MV if createChannel was not called + /// (bug #244461 - also related to bug #23755) + void test_setChannelDescMV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + folder->setChannelDescription( chId, "ch 1 desc" ); + CPPUNIT_ASSERT_EQUAL + ( std::string("ch 1 desc"), folder->channelDescription( chId ) ); + } + + + /// Tests channelName() for MV folders if createChannel was not called + void test_channelNameSV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), folder->channelName( chId ) ); + } + + + /// Tests channelName() for MV folders if createChannel was not called + /// (bug #24463 - also related to bug #23755) + void test_channelNameMV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), folder->channelName( chId ) ); + } + + + /// Tests channelDesc() for SV folders if createChannel was not called + void test_channelDescSV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), folder->channelDescription( chId ) ); + } + + + /// Tests channelDesc() for MV folders if createChannel was not called + /// (bug #24463 - also related to bug #23755) + void test_channelDescMV_withoutCreateChannel() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + Record payload( payloadSpec ); + ChannelId chId = 1; + folder->storeObject( 0, 10, payload, chId ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), folder->channelDescription( chId ) ); + } + + + /// Tests channelId() exceptional behavior + void test_channelId_exception() { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + CPPUNIT_ASSERT_THROW( folder->channelId( "unknown channel" ), + ChannelNotFound ); + } + + + /// Tests channelDescription() exceptional behavior + void test_channelDescription_exception() { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + CPPUNIT_ASSERT_THROW( folder->channelDescription( 1 ), + ChannelNotFound ); + } + + + /// Tests channelName() exceptional behavior + void test_channelName_exception() { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + CPPUNIT_ASSERT_THROW( folder->channelName( 1 ), + ChannelNotFound ); + } + + + /// Tests channelId( channelName ) + void test_channelId() { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->createChannel( 1, "ch 1", "desc 1" ); + folder->createChannel( 2, "ch 2", "desc 2" ); + folder->createChannel( 3, "ch 3", "desc 3" ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)2, + folder->channelId( "ch 2" ) ); + } + + + /// Tests existsChannel() + void test_existsChannel() { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->createChannel( 1, "ch 1", "desc 1" ); + CPPUNIT_ASSERT( folder->existsChannel( 1 ) ); + CPPUNIT_ASSERT( ! folder->existsChannel( 2 ) ); + CPPUNIT_ASSERT( folder->existsChannel( "ch 1" ) ); + CPPUNIT_ASSERT( ! folder->existsChannel( "ch 2" ) ); + } + + + /// Tests UK on channel name and channel id in createChannel() + void test_channelNameUnique() { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + std::string name0 = ""; + std::string name1 = "my channel 1"; + std::string name2 = "my channel 2"; + std::string name3 = "my channel 3"; + std::string desc = "my description"; + + folder->createChannel( 0, name0, desc ); + CPPUNIT_ASSERT_EQUAL( name0, folder->channelName( 0 ) ); + CPPUNIT_ASSERT_EQUAL( desc, folder->channelDescription( 0 ) ); + + folder->createChannel( 1, name1, desc ); + CPPUNIT_ASSERT_EQUAL( name1, folder->channelName( 1 ) ); + CPPUNIT_ASSERT_EQUAL( desc, folder->channelDescription( 1 ) ); + + folder->createChannel( 2, name2, desc ); + CPPUNIT_ASSERT_EQUAL( name2, folder->channelName( 2 ) ); + CPPUNIT_ASSERT_EQUAL( desc, folder->channelDescription( 2 ) ); + + std::cout << std::endl; + + try { + folder->createChannel( 0, name3, desc ); + CPPUNIT_FAIL( "Creating channel with duplicate id=0 should fail" ); + } + catch ( ChannelExists& ) { + } + + try { + folder->createChannel( 3, name0, desc ); + CPPUNIT_ASSERT_EQUAL( name0, folder->channelName( 3 ) ); + CPPUNIT_ASSERT_EQUAL( desc, folder->channelDescription( 3 ) ); + } + catch ( std::exception& e ) { + std::cout << "ERROR! Exception caught: '" + << e.what() << "'" << std::endl; + throw; + } + + try { + folder->createChannel( 4, name1, desc ); + CPPUNIT_FAIL + ( "Creating channel with duplicate name=" + name1 + " should fail" ); + } + catch ( ChannelExists& ) { + } + + try { + folder->setChannelName( 1, name2 ); + CPPUNIT_FAIL + ( "Setting channel duplicate name=" + name1 + " should fail" ); + } + catch ( ChannelExists& ) { + } + + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, folder->channelId( name1 ) ); + + } + + + /// Tests createChannel(), channelName(), and channelDescription() + void test_createChannel() { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->createChannel( 1, "ch 1", "desc 1" ); + CPPUNIT_ASSERT_EQUAL( std::string("ch 1"), + folder->channelName( 1 ) ); + CPPUNIT_ASSERT_EQUAL( std::string("desc 1"), + folder->channelDescription( 1 ) ); + } + + + /// Tests dropChannel() + void test_dropChannel() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->createChannel( 1, "ch 1", "desc 1" ); + CPPUNIT_ASSERT_EQUAL( true, folder->existsChannel( 1 ) ); + folder->dropChannel( 1 ); + CPPUNIT_ASSERT_EQUAL( false, folder->existsChannel( 1 ) ); + } + + + /// Tests dropChannel() with an exception (SV IOVs) + void test_dropChannel_exceptionSV() + { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + coral::AttributeList payload = Record( payloadSpec ).attributeList(); + folder->storeObject( 0, 1, payload, 1 ); + CPPUNIT_ASSERT_EQUAL( true, folder->existsChannel( 1 ) ); + try + { + folder->dropChannel( 1 ); + CPPUNIT_FAIL( "exception expected" ); + } + catch ( RelationalException& ) {} + CPPUNIT_ASSERT_EQUAL( true, folder->existsChannel( 1 ) ); + } + + + /// Tests dropChannel() with an exception (MV IOVs) + void test_dropChannel_exceptionMV() + { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + coral::AttributeList payload = Record( payloadSpec ).attributeList(); + folder->storeObject( 0, 1, payload, 1 ); + CPPUNIT_ASSERT_EQUAL( true, folder->existsChannel( 1 ) ); + try + { + folder->dropChannel( 1 ); + CPPUNIT_FAIL( "exception expected" ); + } + catch ( RelationalException& ) {} + CPPUNIT_ASSERT_EQUAL( true, folder->existsChannel( 1 ) ); + } + + + /// Tests listChannels (SingleVersion only, MultiVersion test in + /// test_RalDatabase) + void test_listChannels() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + ChannelId channel = 1; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 3; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 5; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 3u, (unsigned int)channels.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", (ChannelId)1, channels[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", (ChannelId)3, channels[1] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", (ChannelId)5, channels[2] ); + + // check exceptional behavior + folder = m_db->createFolder( "/empty_folder", payloadSpec ); + + // a folder without data has no channels + channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel list size", 0u, (unsigned int)channels.size() ); + } + + + /// Test the odering of the list of channels when the highest bit is set. + /// Used to fail for SQLite with bug #15128 and later bug #24103. + void test_listChannels_order() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + ChannelId channel = 1; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 2147483648u; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + //MSG::Level outLvl = application().outputLevel(); + //application().setOutputLevel( MSG::VERBOSE ); + std::vector<ChannelId> channels = folder->listChannels(); + //application().setOutputLevel( outLvl ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel list size", 2u, (unsigned int)channels.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", (ChannelId)1, channels[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2147483648", (ChannelId)2147483648u, channels[1] ); + } + + + /// Tests listChannelsWithNames + void test_listChannelsWithNames() + { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + ChannelId channel = 1; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 3; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 5; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + folder->setChannelName( 3, "channel 3" ); + folder->setChannelName( 5, "channel 5" ); + std::map<ChannelId,std::string> channelsWithNames = + folder->listChannelsWithNames(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 3u, (unsigned int)channelsWithNames.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel 1", std::string(""), channelsWithNames[1] ); + CPPUNIT_ASSERT_MESSAGE + ( "channel 2", channelsWithNames.find(2) == channelsWithNames.end() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel 3", std::string("channel 3"), channelsWithNames[3] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel 5", std::string("channel 5"), channelsWithNames[5] ); + + // check exceptional behavior + folder = m_db->createFolder( "/empty_folder", payloadSpec ); + + // a folder without data has no channels + channelsWithNames = folder->listChannelsWithNames(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel list size", 0u, (unsigned int)channelsWithNames.size() ); + } + + + /// Creates a dummy payload AttributeList for a given index + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + ChannelsTest() + : CoolDBUnitTest(), payloadSpec() + { + payloadSpec.extend("I",StorageType::Int32); + payloadSpec.extend("S",StorageType::String255); + payloadSpec.extend("X",StorageType::Float); + } + + void setUp() { + dropDB(); + createDB(); + openDB(); + } + + void tearDown() { + closeDB(); // Fix for bug #27650 on OSX + } + + }; + + CPPUNIT_TEST_SUITE_REGISTRATION( ChannelsTest ); + +} // namespace + +COOLTEST_MAIN(ChannelsTest) diff --git a/RelationalCool/tests/ClobIO/authentication.xml b/RelationalCool/tests/ClobIO/authentication.xml new file mode 100755 index 000000000..da8dc0f83 --- /dev/null +++ b/RelationalCool/tests/ClobIO/authentication.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" ?> +<connectionlist> + +<connection name="oracle://devdb10/lcg_cool"> + <parameter name="user" value="USER" /> + <parameter name="password" value="PASSWORD" /> +</connection> + +<connection name="mysql://pcitdb59/COOLDB"> + <parameter name="user" value="USER" /> + <parameter name="password" value="PASSWORD" /> +</connection> + +</connectionlist> diff --git a/RelationalCool/tests/ClobIO/clobInputOutput.cpp b/RelationalCool/tests/ClobIO/clobInputOutput.cpp new file mode 100755 index 000000000..7dac711e4 --- /dev/null +++ b/RelationalCool/tests/ClobIO/clobInputOutput.cpp @@ -0,0 +1,211 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +#include <iostream> +#include <stdexcept> +#include <memory> +#include "RelationalAccess/RelationalException.h" +#include "RelationalAccess/IRelationalService.h" +#include "RelationalAccess/IRelationalDomain.h" +#include "RelationalAccess/IRelationalSession.h" +#include "RelationalAccess/IRelationalTransaction.h" +#include "RelationalAccess/IRelationalSchema.h" +#include "RelationalAccess/IRelationalTable.h" +#include "RelationalAccess/IRelationalQuery.h" +#include "RelationalAccess/IRelationalCursor.h" +#include "RelationalAccess/RelationalEditableTableDescription.h" +#include "RelationalAccess/IRelationalTableDataEditor.h" +#include "RelationalAccess/IRelationalTypeConverter.h" +#include "AttributeList/AttributeList.h" +#include "POOLCore/POOLContext.h" +#include "SealKernel/Context.h" +#include "../src/sleep.h" + +void writeClob( const std::string& connectionString ) +{ + seal::MessageStream log( pool::POOLContext::context(), "CLOBInputOutput_Test" ); + seal::IHandle<pool::IRelationalService> serviceHandle = pool::POOLContext::context()->query<pool::IRelationalService>( "POOL/Services/RelationalService" ); + if ( ! serviceHandle ) { + throw std::runtime_error( "Could not retrieve the relational service" ); + } + pool::IRelationalDomain& domain = serviceHandle->domainForConnection( connectionString ); + + // Creating a session + std::auto_ptr< pool::IRelationalSession > session( domain.newSession( connectionString ) ); + + // Establish a connection with the server + std::cout << "Connecting..." << std::endl; + if ( ! session->connect() ) { + throw std::runtime_error( "Could not connect to the database server." ); + } + + // Start a transaction + std::cout << "Starting a new transaction" << std::endl; + if ( ! session->transaction().start() ) { + throw std::runtime_error( "Could not start a new transaction." ); + } + + + if ( session->userSchema().existsTable( "DataTable" ) ) { + std::cout << "Deleting table \"DataTable\"" << std::endl; + if ( ! session->userSchema().dropTable( "DataTable" ) ) { + throw std::runtime_error( "Could not drop a table." ); + } + } + + // Creating the description for the table + std::auto_ptr< pool::IRelationalEditableTableDescription > description( new pool::RelationalAccess::RelationalEditableTableDescription( log, + domain.flavorName() ) ); + description->insertColumn( "id", pool::AttributeStaticTypeInfo<int>::type_name() ); + description->insertColumn( "data", pool::AttributeStaticTypeInfo<std::string>::type_name() ); + + // Setting the std::string -> CLOB + session->typeConverter().setSqlTypeForCppType( "CLOB", pool::AttributeStaticTypeInfo<std::string>::type_name() ); + + // Create the first table. + std::cout << "Creating table \"DataTable\"" << std::endl; + pool::IRelationalTable& table = session->userSchema().createTable( "DataTable", *description ); + + // Costructing a row buffer. + pool::AttributeList data( table.description().columnNamesAndTypes() ); + + // Retrieving the editor object. + pool::IRelationalTableDataEditor& dataEditor = table.dataEditor(); + + // Adding new rows + std::cout << "Adding a row into the table" << std::endl; + data["id"].setValue<int>( 1 ); + std::string input = "Begin"; + for ( int i = 0; i < 10*1024*1024; ++i ) input += "."; + input += "End"; + data["data"].setValue<std::string>( input ); + + if ( ! dataEditor.insertNewRow( data ) ) { + throw std::runtime_error( "Could not insert a new row into the table." ); + } + + std::cout << "Adding a second row into the table" << std::endl; + data["id"].setValue<int>( 2 ); + input = "Begin"; + for ( int i = 0; i < 20*1024*1024; ++i ) input += "-"; + input += "End"; + data["data"].setValue<std::string>( input ); + + if ( ! dataEditor.insertNewRow( data ) ) { + throw std::runtime_error( "Could not insert a new row into the table." ); + } + + // Committing the transaction + std::cout << "Committing..." << std::endl; + if ( ! session->transaction().commit() ) { + throw std::runtime_error( "Could not commit the transaction." ); + } + + // Disconnecting + std::cout << "Disconnecting..." << std::endl; + session->disconnect(); +} + + + +void readClob( const std::string& connectionString ) +{ + seal::MessageStream log( pool::POOLContext::context(), "CLOBInputOutput_Test" ); + seal::IHandle<pool::IRelationalService> serviceHandle = pool::POOLContext::context()->query<pool::IRelationalService>( "POOL/Services/RelationalService" ); + if ( ! serviceHandle ) { + throw std::runtime_error( "Could not retrieve the relational service" ); + } + pool::IRelationalDomain& domain = serviceHandle->domainForConnection( connectionString ); + + // Creating a session + std::auto_ptr< pool::IRelationalSession > session( domain.newSession( connectionString ) ); + + // Establish a connection with the server + std::cout << "Connecting..." << std::endl; + if ( ! session->connect() ) { + throw std::runtime_error( "Could not connect to the database server." ); + } + + // Start a transaction + std::cout << "Starting a new transaction" << std::endl; + if ( ! session->transaction().start( true ) ) { + throw std::runtime_error( "Could not start a new transaction." ); + } + + pool::IRelationalTable& table = session->userSchema().tableHandle( "DataTable" ); + + std::auto_ptr< pool::IRelationalQuery > query( table.createQuery() ); + query->addToOutputList( "id" ); + query->addToOutputList( "data" ); + pool::IRelationalCursor& cursor = query->process(); + if ( cursor.start() ) { + int i = 0; + while ( cursor.next() ) { + const pool::AttributeList& row = cursor.currentRow(); + pool::AttributeList::const_iterator iAttribute = row.begin(); + std::string result = (++iAttribute)->getValueAsString(); + std::string input = "Begin"; + if ( i == 0 ) { + for ( int i = 0; i < 10*1024*1024; ++i ) input += "."; + } + else { + for ( int i = 0; i < 20*1024*1024; ++i ) input += "-"; + } + input += "End"; + + std::cout << "Expected : " << input.size() << " retrieved : " << result.size() << std::endl; + if ( input != result ) { + throw std::runtime_error( "Input and output differ" ); + } + ++i; + } + } + + // Committing the transaction + std::cout << "Committing..." << std::endl; + if ( ! session->transaction().commit() ) { + throw std::runtime_error( "Could not commit the transaction." ); + } + + // Disconnecting + std::cout << "Disconnecting..." << std::endl; + session->disconnect(); +} + + +int main( int, char** ) +{ + try { + pool::POOLContext::loadComponent( "SEAL/Services/MessageService" ); + pool::POOLContext::loadComponent( "POOL/Services/XMLAuthenticationService" ); + pool::POOLContext::loadComponent( "POOL/Services/RelationalService" ); + //pool::POOLContext::setMessageVerbosityLevel( seal::Msg::Info ); + pool::POOLContext::setMessageVerbosityLevel( seal::Msg::Verbose ); + + std::string connectionString = "oracle://devdb10/lcg_cool"; + writeClob( connectionString ); + + cool::sleep(1); + + readClob( connectionString ); + + std::cout << "Exiting..." << std::endl; + } + catch ( pool::RelationalException& re ) { + std::cerr << "Relational exception from module " << re.flavorName() << std::endl + << " " << re.what() << std::endl; + return 1; + } + catch ( std::exception& e ) { + std::cerr << "Standard C++ exception : " << e.what() << std::endl; + return 1; + } + catch ( ... ) { + std::cerr << "Exception caught (...)" << std::endl; + return 1; + } + return 0; +} + +#endif // NOPORT diff --git a/RelationalCool/tests/Common/CoolDBUnitTest.h b/RelationalCool/tests/Common/CoolDBUnitTest.h new file mode 100644 index 000000000..328c0c8c5 --- /dev/null +++ b/RelationalCool/tests/Common/CoolDBUnitTest.h @@ -0,0 +1,157 @@ +// $Id: CoolDBUnitTest.h,v 1.18 2008-08-06 09:37:43 avalassi Exp $ +#ifndef COMMON_COOLDBUNITTEST_H +#define COMMON_COOLDBUNITTEST_H 1 + +// Include files +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" + +// Local include files +#include "CoolUnitTest.h" +#include "src/CoralApplication.h" +#include "src/CoralConnectionServiceProxy.h" +#include "src/RalDatabaseSvc.h" +#include "src/RelationalDatabaseId.h" +#include "src/RelationalException.h" +#include "src/sleep.h" + +namespace cool +{ + + const char* COOLTESTDB = "COOLTESTDB"; + + /** @class CoolDBUnitTest CoolDBUnitTest.h + * + * @author Marco Clemencic and Andrea Valassi + * @date 2006-03-13 + */ + class CoolDBUnitTest: public CoolUnitTest { + + public: + + /// Standard constructor + CoolDBUnitTest( bool getSvc = true ) + : m_connectionString( "" ) + , m_coolDBName( "" ) + , m_app( new CoralApplication() ) + , m_db() + { + if ( getenv( COOLTESTDB ) ) { + m_connectionString = getenv( COOLTESTDB ); + } else { + std::cout + << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << std::endl; + std::cout + << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" + << std::endl; + std::cout << "Aborting test" << std::endl; + exit(-1); + } + + // Decode the COOL database name + RelationalDatabaseId id( m_connectionString ); + m_coolDBName = id.dbName(); + + // This is to avoid mixture between SEAL unavoidable + // messages and test progress output (now on std::cout) + if ( getSvc ) dbs(); + + } + + /// Destructor + virtual ~CoolDBUnitTest() + { + delete m_app; + } + + protected: + + /// Sleep n seconds (ORA-01466 workaround). + inline void sleep( int n ) + { + cool::sleep(n); + } + + /// Retrieve the database service in the application. + inline IApplication& application() + { + return *m_app; + } + + /// Return a reference to the coral::ConnectionService. + coral::IConnectionService& connectionSvc() + { + return application().connectionSvc(); + } + + /// Return THE shared pointer to the coral::ConnectionService pointer. + CoralConnectionServiceProxyPtr ppConnectionSvc() + { + RalDatabaseSvc* ralDbs = dynamic_cast<RalDatabaseSvc*>( &dbs() ); + if ( !ralDbs ) + throw RelationalException( "PANIC! Not a RalDatabaseSvc in CoolDBUnitTest?", "" ); + return ralDbs->ppConnectionSvc(); + } + + /// Retrieve the database service in the application. + inline IDatabaseSvc& dbs() + { + return application().databaseService(); + } + + /// Create an empty database and disconnect. + void createDB() + { + dropDB(); + dbs().createDatabase( m_connectionString ); + forceDisconnect(); + } + + + /// Open the database (set the pointer "m_db"). + void openDB( bool readOnly = false ) + { + m_db = dbs().openDatabase( m_connectionString, readOnly ); + } + + /// Close the database (reset the pointer "m_db"). + void closeDB() + { + if ( m_db ) m_db.reset(); + } + + /// Drop the DB. + void dropDB() + { + closeDB(); + dbs().dropDatabase( m_connectionString ); + forceDisconnect(); + } + + /// Purge coral ConnectionPool. + void forceDisconnect() + { + closeDB(); + static bool first = true; + if ( first ) { + application().connectionSvc().configuration().setConnectionTimeOut(-1); + first = false; + } + application().connectionSvc().purgeConnectionPool(); + } + + protected: + + std::string m_connectionString; + std::string m_coolDBName; + CoralApplication* m_app; + IDatabasePtr m_db; + + }; + +} + +#endif // COMMON_COOLDBUNITTEST_H diff --git a/RelationalCool/tests/Common/CoolUnitTest.h b/RelationalCool/tests/Common/CoolUnitTest.h new file mode 100644 index 000000000..38a0144a4 --- /dev/null +++ b/RelationalCool/tests/Common/CoolUnitTest.h @@ -0,0 +1,367 @@ +// $Id: CoolUnitTest.h,v 1.10 2009-01-13 18:09:23 avalassi Exp $ +#ifndef COMMON_COOLUNITTEST_H +#define COMMON_COOLUNITTEST_H 1 + +// Include files +#include <stdexcept> +#include <iostream> +#ifdef _WIN32 +#include <eh.h> +#include <windows.h> +#endif + +// Local include files +#include "CppUnit_headers.h" + +// Redefine CPPUNIT_TEST +#undef CPPUNIT_TEST +#define CPPUNIT_TEST( testMethod ) \ +CPPUNIT_TEST_SUITE_ADD_TEST( \ + ( new cool::TestCaller<TestFixtureType>( \ + context.getTestNameFor( #testMethod ), \ + &TestFixtureType::testMethod, \ + context.makeFixture() ) ) ) + +namespace cool +{ + + //-------------------------------------------------------------------------- + +#ifdef _WIN32 + + /* + * Windows Structured Exception Handling (SEH) using _set_se_translator. + * See http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx + * + * @author Andrea Valassi + * @date 2009-01-12 + */ + + class SE_Exception : public std::exception + { + public: + SE_Exception( int n = -1 ) : m_nSE( n ) + { + std::stringstream msg; + msg << "WINDOWS STRUCTURED EXCEPTION"; + if ( m_nSE >=0 ) msg << " (#" << m_nSE << ")"; + else msg << " (UNKNOWN)"; + m_message = msg.str(); + } + virtual ~SE_Exception() {} + int getSeNumber() { return m_nSE; } + const char* what() const{ return m_message.c_str(); } + private: + int m_nSE; + std::string m_message; + }; + + void SE_translator( unsigned int, EXCEPTION_POINTERS* ) + { + std::cout << "__cool::SE_translator WINDOWS SE CAUGHT" << std::endl; + throw SE_Exception(); + } + +#endif + + //-------------------------------------------------------------------------- + + /** @class TestCaller + * + * Simple TestCaller wrapping the execution of each test in a test suite. + * + * @author Andrea Valassi + * @date 2009-01-12 + */ + + template< class Fixture > class TestCaller + : virtual public CppUnit::TestCaller<Fixture> + { + + typedef void( Fixture::* TestMethod )(); + + public: + + virtual ~TestCaller(){} + + TestCaller( std::string name, TestMethod test ) + : CppUnit::TestCaller<Fixture>( name, test ){} + + TestCaller( std::string name, TestMethod test, Fixture& fixture ) + : CppUnit::TestCaller<Fixture>( name, test, fixture ){} + + TestCaller( std::string name, TestMethod test, Fixture* fixture ) + : CppUnit::TestCaller<Fixture>( name, test, fixture ){} + +#ifdef _WIN32 + // See http://msdn.microsoft.com/en-us/library/s58ftw19.aspx + int filter( unsigned int code, struct _EXCEPTION_POINTERS* ep ) + { + if ( code == EXCEPTION_ACCESS_VIOLATION ) + { + std::cout << "__cool::TestCaller::filter" + << " ERROR! WIN32 Access Violation" << std::endl; + return EXCEPTION_EXECUTE_HANDLER; + } + else + { + std::cout << "__cool::TestCaller::filter" + << " ERROR! WIN32 Unknown exception" << std::endl; + return EXCEPTION_EXECUTE_HANDLER; + //return EXCEPTION_CONTINUE_SEARCH; + }; + } +#endif + + void runTest() + { + //std::cout << std::endl; + //std::cout << "+++ cool::TestCaller::runTest '" + // << this->getName() << "'..." << std::endl; +#ifdef _WIN32 + // This fails to build even when replacing /EHsc by /EHa + // (C2712: Cannot use __try in functions that require object unwinding) + // See http://msdn.microsoft.com/en-us/library/1deeycx5(VS.80).aspx and + // http://http://msdn.microsoft.com/en-us/library/1deeycx5(VS.80).aspx + /* + __try { + CppUnit::TestCaller<Fixture>::runTest(); + } + __except( filter( GetExceptionCode(), GetExceptionInformation() ) ) { + std::cout << "__cool::TestCaller::runTest" + << " ERROR! WIN32 Structured exception caught" << std::endl; + } + */ + try + { + CppUnit::TestCaller<Fixture>::runTest(); + } + catch (...) + { + //std::cout << "+++ cool::TestCaller::runTest '" << this->getName() + // << "'... EXCEPTION CAUGHT!" << std::endl; + throw; + } +#else + CppUnit::TestCaller<Fixture>::runTest(); +#endif + //std::cout << "--- cool::TestCaller::runTest '" + // << this->getName() << "'... DONE" << std::endl; + } + + private: + + TestCaller<Fixture>(); + + }; + + //-------------------------------------------------------------------------- + + /** @class TextTestRunner + * + * Simple TextTestRunner wrapping the execution of a test suite. + * + * @author Andrea Valassi + * @date 2009-01-12 + */ + + class TextTestRunner : virtual public CppUnit::TextTestRunner + { + + public: + + virtual ~TextTestRunner(){} + + TextTestRunner() : CppUnit::TextTestRunner() {} + + void run( CppUnit::TestResult& controller, const std::string& testPath="" ) + { + // Avoid compilation warning (virtual function was hidden...) on osx + CppUnit::TextTestRunner::run( controller, testPath ); + } + + bool run( std::string testName = "", + bool doWait = false, + bool doPrintResult = true, + bool doPrintProgress = true ) + { + //std::cout << "+++ cool::TextTestRunner::run '" + // << testName << "'..." << std::endl; + bool status = CppUnit::TextTestRunner::run( testName, + doWait, + doPrintResult, + doPrintProgress ); + //std::cout << "--- cool::TextTestRunner::run '" + // << testName << "'... DONE" << std::endl; + return status; + } + + }; + + //-------------------------------------------------------------------------- + + /** @class ProgressListener + * + * Simple TestListener printing one line per test in the standard output. + * + * Based on CppUnit::BriefTestProgressListener (copy and paste) + * using std::cout instead of std::cerr. + * + * @author Marco Clemencic + * @date 2006-11-13 + */ + + class ProgressListener : public CppUnit::TestListener + { + + public: + + /// Default constructor. + ProgressListener(): m_lastTestFailed(false) {} + + /// Destructor. + virtual ~ProgressListener() {} + + void startTest( CppUnit::Test *test ) + { + std::cout << test->getName(); + std::cout.flush(); + m_lastTestFailed = false; + } + + void addFailure( const CppUnit::TestFailure &failure ) + { + std::cout << " : " << (failure.isError() ? "error" : "assertion"); + m_lastTestFailed = true; + } + + void endTest( CppUnit::Test * /*test*/ ) + { + if ( !m_lastTestFailed ) + std::cout << " : OK"; + std::cout << std::endl; + } + + private: + + bool m_lastTestFailed; + + }; + + + //--------------------------------------------------------------------------- + + /** @class CoolUnitTest CoolUnitTest.h Common/CoolUnitTest.h + * + * Base class for COOL tests that does not use a database + * (use CoolDBUnitTest for tests involving databases). + * + * @author Marco Clemencic + * @date 2006-05-09 + */ + class CoolUnitTest: public CppUnit::TestFixture { + + public: + + /// Standard constructor + CoolUnitTest(){} + + /// Destructor + virtual ~CoolUnitTest(){} + + /// Program main + static int Main( int argc, char* argv[] ); + + }; + + int CoolUnitTest::Main( int argc, char* argv[] ) + { + //std::cout << "+++ cool::CoolUnitTest::Main..." << std::endl; +#ifdef _WIN32 + _set_se_translator( cool::SE_translator ); +#endif + // Retrieve test path from command line first argument. + // Default to "" which resolve to the top level suite. + std::string testPath = + (argc > 1) ? std::string(argv[1]) : std::string(""); + + // Add a listener that colllects test result + //CppUnit::TestResultCollector result; + //controller.addListener( &result ); + + /// Get the top level suite from the registry + CppUnit::Test *suite = + CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + + /// Adds the test to the list of test to run + // CppUnit::TestRunner runner; + // CppUnit::TextTestRunner runner; + cool::TextTestRunner runner; + runner.addTest( suite ); + + // Change the default outputter to a compiler error format outputter + // uncomment the following line if you need a compiler outputter. + runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(), + std::cout ) ); + + // Change the default outputter to a xml error format outputter + // uncomment the following line if you need a xml outputter. + //runner.setOutputter( new CppUnit::XmlOutputter( &runner.result(), + // std::cout ) ); + + runner.eventManager().addListener( new cool::ProgressListener() ); + + //CppUnit::TestResultCollector *collector = + // new CppUnit::TestResultCollector(); + //runner.eventManager().addListener(collector); + + bool wasSuccessful = false; + + try + { + wasSuccessful = runner.run( testPath, false, true, false ); + } + + // Test path not resolved + catch ( std::invalid_argument &e ) + { + std::cout << std::endl << "ERROR: " << e.what() << std::endl; + return 0; + } + + // Should never happen? + catch ( std::exception& e ) + { + std::cout << std::endl + << "UNEXPECTED STD EXCEPTION CAUGHT in CoolUnitTest: " + << e.what() << std::endl; + return 0; + } + + // Should never happen? + catch ( ... ) + { + std::cout << std::endl + << "UNKNOWN EXCEPTION CAUGHT in CoolUnitTest" << std::endl; + return 0; + } + + // Return error code 1 if the one of tests failed. + // Print a message on standard error if something failed (for QMTest) + if ( ! wasSuccessful ) std::cerr << "Error: CppUnit Failures" << std::endl; + int retcode = wasSuccessful ? 0 : 1; + // Uncomment the next line if you want to integrate CppUnit with Oval + std::cout << "[OVAL] Cppunit-result =" << retcode << std::endl; + //std::cout << "--- cool::CoolUnitTest::Main... DONE" << std::endl; + return retcode; + + } + + //--------------------------------------------------------------------------- + +} + +#define COOLTEST_MAIN(CLASS) int main( int argc, char* argv[] ) \ + { return cool::CLASS::Main( argc, argv ); } + +#endif // COMMON_COOLUNITTEST_H diff --git a/RelationalCool/tests/Common/CppUnit_headers.h b/RelationalCool/tests/Common/CppUnit_headers.h new file mode 100644 index 000000000..d093ca404 --- /dev/null +++ b/RelationalCool/tests/Common/CppUnit_headers.h @@ -0,0 +1,45 @@ +// $Id: CppUnit_headers.h,v 1.4 2008-02-28 14:19:46 avalassi Exp $ +#ifndef COMMON_CPPUNIT_HEADERS_H +#define COMMON_CPPUNIT_HEADERS_H 1 + +// Disable warnings triggered by the CppUnit headers +// See http://wiki.services.openoffice.org/wiki/Writing_warning-free_code +// See also http://www.artima.com/cppsource/codestandards.html +// See also http://gcc.gnu.org/onlinedocs/gcc-4.1.1/cpp/System-Headers.html +// See also http://gcc.gnu.org/ml/gcc-help/2007-01/msg00172.html +#if defined __GNUC__ +#pragma GCC system_header +#endif + +// Include files + +// from SPI version of the testdriver +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/TextTestRunner.h> +#include <cppunit/CompilerOutputter.h> +#include <cppunit/TextOutputter.h> +#include <cppunit/XmlOutputter.h> + +// to produce one line per test +#include <cppunit/TestResult.h> +//#include <cppunit/BriefTestProgressListener.h> +//#include <cppunit/TestResultCollector.h> + +// needed by the implementation of cool::ProgressListener +#include <cppunit/Test.h> +#include <cppunit/TestFailure.h> +#include <cppunit/TestListener.h> + +// provides macros for the tests +#include <cppunit/extensions/HelperMacros.h> + +// try (unsuccessfully) to avoid some warnings in test_RelationalFolder.cpp +// - these lines force instantiation here, but the warning does happen here too +// - even moving these lines to another included file did not remove warnings +//#include <cppunit/extensions/ExceptionTestCaseDecorator.h> +//namespace cool { class Exception; } +//template class CppUnit::ExceptionTestCaseDecorator<cool::Exception>; +//namespace cool { class TagNotFound; } +//template class CppUnit::ExceptionTestCaseDecorator<cool::TagNotFound>; + +#endif // COMMON_CPPUNIT_HEADERS_H diff --git a/RelationalCool/tests/Common/CppUnit_testdriver.icpp b/RelationalCool/tests/Common/CppUnit_testdriver.icpp new file mode 100644 index 000000000..04643a516 --- /dev/null +++ b/RelationalCool/tests/Common/CppUnit_testdriver.icpp @@ -0,0 +1,4 @@ + +#include "CoolUnitTest.h" + +COOLTEST_MAIN(CoolUnitTest) diff --git a/RelationalCool/tests/Common/cppunit/TestListener.h b/RelationalCool/tests/Common/cppunit/TestListener.h new file mode 100644 index 000000000..7dc14d9b5 --- /dev/null +++ b/RelationalCool/tests/Common/cppunit/TestListener.h @@ -0,0 +1,23 @@ +#ifndef CPPUNIT_TESTLISTENER_H +#define CPPUNIT_TESTLISTENER_H +namespace CppUnit +{ + class Test; + class TestFailure; + class TestResult; + class TestListener + { + public: + virtual ~TestListener() {} + virtual void startTest( Test* ){} + virtual void addFailure( const TestFailure& ){} + virtual void endTest( Test* ){} + virtual void startSuite( Test* ){} + virtual void endSuite( Test* ){} + virtual void startTestRun( Test*, TestResult* ){} + virtual void endTestRun( Test*, TestResult* ){} + }; +} +#endif // CPPUNIT_TESTLISTENER_H + + diff --git a/RelationalCool/tests/Common/releaser.h b/RelationalCool/tests/Common/releaser.h new file mode 100644 index 000000000..2f33d85db --- /dev/null +++ b/RelationalCool/tests/Common/releaser.h @@ -0,0 +1,18 @@ +// $Id: releaser.h,v 1.1 2006-11-15 16:18:25 avalassi Exp $ +#ifndef RELATIONALCOOL_RELEASER_H +#define RELATIONALCOOL_RELEASER_H 1 + +// Include files +#include "CoralBase/AttributeListSpecification.h" + +namespace cool +{ + + class releaser { + public: + void operator()( coral::AttributeListSpecification* p ) { p->release(); } + }; + +} + +#endif // RELEASER_H diff --git a/RelationalCool/tests/CoolCppUnitTestDriver.cpp b/RelationalCool/tests/CoolCppUnitTestDriver.cpp new file mode 100644 index 000000000..1ddc07405 --- /dev/null +++ b/RelationalCool/tests/CoolCppUnitTestDriver.cpp @@ -0,0 +1,72 @@ +// From /afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/slc3_ia32_gcc323/include +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/ui/text/TestRunner.h> +#include <cppunit/CompilerOutputter.h> +#include <cppunit/TextOutputter.h> +#include <cppunit/XmlOutputter.h> +#include <iostream> + +#include <cppunit/TestResult.h> +#include <cppunit/TextTestProgressListener.h> +namespace cool { + // See http://kmymoney2.sourceforge.net/phb/test-container-example.html + // See http://cppunit.sourceforge.net/doc/lastest/cppunit_cookbook.html + // See http://cppunit.sourceforge.net/cppunit-wiki/FrequentlyAskedQuestions + class CoolProgressListener : public CppUnit::TextTestProgressListener + { + void startTest(CppUnit::Test *test) { + std::string name = test->getName().c_str(); + if(m_name != name) { + std::cout << "Running: " << name << std::endl; + m_name = name; + } + } + private: + std::string m_name; + }; +} + +/** Main class for all the CppUnit test classes +* +* This will be the driver class of all your CppUnit test classes. +* - All registered CppUnit test classes will be run. +* - You can also modify the output (text, compiler, XML). +* - This class will also integrate CppUnit test with Oval +*/ + + +int main( int /*argc*/, char /* **argv */) + { + /// Get the top level suite from the registry + CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + + /// Adds the test to the list of test to run + CppUnit::TextUi::TestRunner runner; + runner.addTest( suite ); + + // Change the default outputter to a compiler error format outputter + // uncomment the following line if you need a compiler outputter. + runner.setOutputter(new CppUnit::CompilerOutputter( &runner.result(), + std::cout ) ); + + // Change the default outputter to a xml error format outputter + // uncomment the following line if you need a xml outputter. + //runner.setOutputter( new CppUnit::XmlOutputter( &runner.result(), + // std::cerr ) ); + + // Print out the name of each test before its execution + cool::CoolProgressListener progress; + runner.eventManager().addListener(&progress); + + /// Run the tests. + // bool wasSuccessful = runner.run(); + // If you want to avoid the CppUnit typical output change the line above + // by the following one: + bool wasSuccessful = runner.run("",false,true,false); + + // Return error code 1 if the one of test failed. + // Uncomment the next line if you want to integrate CppUnit with Oval + if(!wasSuccessful !=0) std::cerr <<"Error: CppUnit Failures"<<std::endl; + std::cout <<"[OVAL] Cppunit-result ="<<!wasSuccessful<<std::endl; + return 0; + } diff --git a/RelationalCool/tests/CreateDatabase/createDatabase.cpp b/RelationalCool/tests/CreateDatabase/createDatabase.cpp new file mode 100644 index 000000000..d9b3049b7 --- /dev/null +++ b/RelationalCool/tests/CreateDatabase/createDatabase.cpp @@ -0,0 +1,446 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +// $Id: createDatabase.cpp,v 1.69 2008-08-27 09:34:28 avalassi Exp $ + +// Include files +#include <iostream> +#include <sstream> +#include <string> +#include "AttributeList/AttributeList.h" +#include "CoolKernel/DatabaseId.h" +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IFolderSet.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "src/CoralApplication.h" +#include "src/sleep.h" +#include "src/timeToString.h" +#include "src/uppercaseString.h" + +// Namespace +using namespace cool; + +// Message output +#define LOG std::cout << "__main " + +//----------------------------------------------------------------------------- + +int main ( int argc, char* argv[] ) +{ + + LOG << "Entering main" << std::endl; + int status = -1; + + // User name + std::string userName; + if ( getenv( "USER" ) ) + userName = uppercaseString( getenv( "USER" ) ); + else if ( getenv( "USERNAME" ) ) + userName = uppercaseString( getenv( "USERNAME" ) ); + else { + LOG << "ERROR! Environment variables USER and USERNAME both undefined" + << std::endl; + return status; + } + std::string dbName = userName + "2"; + if ( dbName == "AVALASSI2" ) dbName = "COOLTSTA"; + if ( dbName == "SAS2" ) dbName = "COOLTSTS"; + + // Default connection strings + std::string dbIdOracle = + std::string( "oracle://devdb10;schema=lcg_cool;dbname=" ) + dbName; + std::string dbIdMySQL = + std::string( "mysql://pcitdb59;schema=COOLDB;dbname=" ) + dbName; + + // Command line input: connection string + std::string dbIdString; + if ( argc == 1 || argc > 2 ) { + LOG << "Usage: " << argv[0] << " dbId|'oracle'|'mysql'" << std:: endl; + LOG << "Example: " << argv[0] << " oracle"<< std::endl; + LOG << "Example: " << argv[0] << " mysql"<< std::endl; + LOG << "Example: " << argv[0] << " \"" << dbIdOracle << "\""<< std::endl; + LOG << "Example: " << argv[0] << " \"" << dbIdMySQL << "\""<< std::endl; + return 1; + } else { + dbIdString = argv[1]; + if ( dbIdString == "oracle" ) dbIdString = dbIdOracle; + if ( dbIdString == "mysql" ) dbIdString = dbIdMySQL; + } + + try { + + LOG << "Get a handle to the COOL database service" << std::endl; + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + + //------------------------ + // DEFINE THE DATABASE ID + //------------------------ + + cool::DatabaseId dbId = dbIdString; + + //-------------------------------- + // DROP THE DATABASE IF IT EXISTS + //-------------------------------- + + // Drop the COOL conditions database if it already exists + LOG << "Drop if it exists the conditions database: " << dbId << std::endl; + dbSvc.dropDatabase( dbId ); + + //----------------------- + // CREATE A NEW DATABASE + //----------------------- + + // Create a new COOL conditions database + LOG << "Create a new conditions database: " << dbId << std::endl; + cool::IDatabasePtr db = dbSvc.createDatabase( dbId ); + LOG << "Conditions database created: " << std::endl; + LOG << "-> Database ID: " << db->databaseId() << std::endl; + std::ostringstream dbAttr; + db->databaseAttributes().print( dbAttr ); + LOG << "-> Database attributes: " << dbAttr.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::sleep(1); + + // Create two new COOL conditions folders with the same payload spec + pool::AttributeListSpecification payloadSpec1; + payloadSpec1.push_back("I","int"); + payloadSpec1.push_back("S","string"); + payloadSpec1.push_back("X","float"); + payloadSpec1.push_back("UI64","unsigned long long"); + //payloadSpec1.push_back("SI64","long long"); + + // Create folder 1a + std::string folderName1a( "/my/folder1a" ); + cool::IFolderPtr folder1a = db->createFolder + ( folderName1a, payloadSpec1, "", + FolderVersioning::SINGLE_VERSION, true ); + LOG << "Folder created: " << std::endl; + LOG << "-> Folder name: " << folder1a->fullPath() << std::endl; + std::ostringstream folderAttr1a; + folder1a->payloadSpecification().print( folderAttr1a ); + LOG << "-> Folder payload specification: " + << folderAttr1a.str() << std::endl; + + // Create folder 1b + std::string folderName1b( "/my/folder1b" ); + cool::IFolderPtr folder1b = db->createFolder + ( folderName1b, payloadSpec1, "", + FolderVersioning::SINGLE_VERSION, true ); + LOG << "Folder created: " << std::endl; + LOG << "-> Folder name: " << folder1b->fullPath() << std::endl; + std::ostringstream folderAttr1b; + folder1b->payloadSpecification().print( folderAttr1b ); + LOG << "-> Folder payload specification: " + << folderAttr1b.str() << std::endl; + + // Create folder 1c + std::string folderName1c( "/my/folder1c" ); + cool::IFolderPtr folder1c = db->createFolder + ( folderName1c, payloadSpec1, "", + FolderVersioning::SINGLE_VERSION, true ); + LOG << "Folder created: " << std::endl; + LOG << "-> Folder name: " << folder1c->fullPath() << std::endl; + std::ostringstream folderAttr1c; + folder1c->payloadSpecification().print( folderAttr1c ); + LOG << "-> Folder payload specification: " + << folderAttr1c.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::sleep(1); + + // Print the list of folders + std::vector<std::string> folderList; + std::vector<std::string>::iterator folderIt; + folderList = db->getFolderSet( "/my" )->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + + // In online folders, until=+infinity means valid until next iov + ValidityKey plusInfinity = ValidityKeyMax; + + // Insert some data into folder 1a + pool::AttributeList payload1( payloadSpec1 ); + payload1["I"].setValue<int>( 1 ); + payload1["S"].setValue<std::string>( "Object 1" ); + payload1["X"].setValue<float>( 0.001 ); + payload1["UI64"].setValue<unsigned long long>( 64 ); + //payload1["SI64"].setValue<long long>( -64 ); + folder1a->storeObject( 0, 10, payload1, 1 ); + folder1a->storeObject( 10, 20, payload1, 1 ); + folder1a->storeObject( 0, plusInfinity, payload1, 2 ); + folder1a->storeObject( 10, plusInfinity, payload1, 2 ); + folder1a->storeObject( 20, plusInfinity, payload1, 2 ); + folder1a->storeObject( 30, plusInfinity, payload1, 2 ); + + // Try to insert data with online IOV overlap: this will throw an exception + try { + folder1a->storeObject( 5, 15, payload1, 1 ); + } catch ( std::exception& e ) { + LOG << "Exception caught as expected: " << e.what() << std::endl; + } + + // Store a valid IOV - test that the previous invalid IOV was discarded + folder1a->storeObject( 40, plusInfinity, payload1, 2 ); + + // Print the list of channels + std::vector<ChannelId> channelList = folder1a->listChannels(); + LOG << "-> List of channels in folder " + << folder1a->fullPath() << std::endl; + std::vector<ChannelId>::const_iterator channelIt; + for( channelIt = channelList.begin(); + channelIt != channelList.end(); + channelIt++ ) { + std::cout << *channelIt << std::endl; + } + + // Dump the object stored for time t=5 in channel 1 + IObjectPtr obj1a_ch1_5 = folder1a->findObject( 5, 1 ); + LOG << "Retrieved object valid at t=5 in channel 1 of folder " + << folder1a->fullPath() << std::endl; + LOG << "Object: channelId=" << obj1a_ch1_5->channelId() << std::endl; + LOG << "Object: since=" << obj1a_ch1_5->since() + << ", until=" << obj1a_ch1_5->until() << std::endl; + LOG << "Object: payload values (true types)" + << ": payload[\"I\"]=" << obj1a_ch1_5->payloadValue<int>("I") + << ", payload[\"S\"]=" << obj1a_ch1_5->payloadValue<std::string>("S") + << ", payload[\"X\"]=" << obj1a_ch1_5->payloadValue<float>("X") + << ", payload[\"UI64\"]=" + << obj1a_ch1_5->payloadValue<unsigned long long>("UI64") + //<< ", payload[\"SI64\"]=" + //<< obj1a_ch1_5->payloadValue<long long>("SI64") + << std::endl; + LOG << "Object: payload values (as strings)" + << ": payload[\"I\"]=" << obj1a_ch1_5->payloadValue("I") + << ", payload[\"S\"]=" << obj1a_ch1_5->payloadValue("S") + << ", payload[\"X\"]=" << obj1a_ch1_5->payloadValue("X") + << ", payload[\"UI64\"]=" << obj1a_ch1_5->payloadValue("UI64") + //<< ", payload[\"SI64\"]=" << obj1a_ch1_5->payloadValue("SI64") + << std::endl; + if( ! obj1a_ch1_5->isStored() ) { + LOG << "Object: isStored=false" << std::endl; + } else { + LOG << "Object: isStored=true" << std::endl; + LOG << "Object: insertionTime=" + << timeToString( obj1a_ch1_5->insertionTime() ) << std::endl;; + } + + // Try to insert data with since>until: this will throw an exception + try { + folder1a->storeObject( 30, 20, payload1 ); + } catch ( std::exception& e ) { + LOG << "Exception caught as expected: " << e.what() << std::endl; + } + + // Try to insert data with until>MAX: this will throw an exception + try { + ValidityKey since = ValidityKeyMax; + // Split the following line on two lines (Windows compiler warning) + //ValidityKey until = ValidityKeyMax+1; + ValidityKey until = ValidityKeyMax; + until = until+1; + // NB: Now (ValidityKey=long_long, ValidityKeyMax=LONG_LONG_MAX) + // ==> LONG_LONG_MAX+1 is an invalid int64 LONG_LONG_MIN < since + // NB: Previously (ValidityKey=long_long, ValidityKeyMax=LONG_MAX) + // ==> LONG_MAX+1 is an invalid int64 > LONG_MAX=ValidityKeyMax + folder1a->storeObject( since, until, payload1 ); + } catch ( std::exception& e ) { + LOG << "Exception caught as expected: " << e.what() << std::endl; + } + + // Insert some data into folder 1b + folder1b->storeObject( 0, 10, payload1 ); + + // Drop folder 1b + db->dropNode( folderName1b ); + + // Print the list of folders again + folderList = db->getFolderSet( "/my" )->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + + // Try to insert data into deleted folder 1b: this will throw an exception + // Try to insert data with since>until: this will throw an exception + try { + folder1b->storeObject( 10, 20, payload1 ); + } catch ( std::exception& e ) { + LOG << "Exception caught as expected: " << e.what() << std::endl; + } + + // Bulk-insert some data into folder 1c + ValidityKey bulkSince; + folder1c->setupStorageBuffer(); + for ( bulkSince=0; bulkSince<100; bulkSince++ ) { + folder1c->storeObject( bulkSince*10, plusInfinity, payload1, 1 ); + } + folder1c->flushStorageBuffer(); + + // Reset the database pointer: this will close the connection + LOG << "Release the conditions database connection" << std::endl; + cool::IDatabasePtr dbNull; + db = dbNull; + + //--------------------------- + // OPEN AN EXISTING DATABASE + //--------------------------- + + // Open an existing COOL conditions database + LOG << "Open an existing conditions database: " << dbId << std::endl; + cool::IDatabasePtr db2 = dbSvc.openDatabase( dbId, false ); + LOG << "Conditions database opened: " << std::endl; + LOG << "-> Database ID: " << db2->databaseId() << std::endl; + std::ostringstream db2Attr; + db2->databaseAttributes().print( db2Attr ); + LOG << "-> Database attributes: " << db2Attr.str() << std::endl; + + // Print the list of folders + folderList = db2->getFolderSet( "/my" )->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + + // *** WARNING!! *** + // You MUST get a new handle to folder 1c here: the old one is invalid and + // causes a segmentation fault. A protection must be added in the code! + folder1c = db2->getFolder( folderName1c ); + + // Bulk-retrieve the objects stored in channel 1 of folder 1c in [245,295] + std::string tag = ""; + ChannelId channelId = 1; + ValidityKey since = 245; + ValidityKey until = 295; + IObjectIteratorPtr objIt = + folder1c->browseObjects( since, until, channelId, tag ); + LOG << "Retrieved object iterator in [245,295] for channel 1 of folder " + << folder1c->fullPath() << std::endl; + if ( objIt->isEmpty() ) { + LOG << "Iterator contains no objects" << std::endl; + } else { + objIt->goToStart(); + while( objIt->hasNext() ) { + IObjectPtr object = objIt->next(); + LOG << "Object: channelId=" << object->channelId() + << ", since=" << object->since() + << ", until=" << object->until() << std::endl; + LOG << "Object: payload values (true types)" + << ": payload[\"I\"]=" << object->payloadValue<int>("I") + << ", payload[\"S\"]=" << object->payloadValue<std::string>("S") + << ", payload[\"X\"]=" << object->payloadValue<float>("X") + << ", payload[\"UI64\"]=" + << object->payloadValue<unsigned long long>("UI64") + //<< ", payload[\"SI64\"]=" + //<< object->payloadValue<long long>("SI64") + << std::endl; + if( ! object->isStored() ) { + LOG << "Object: isStored=false" << std::endl; + } else { + LOG << "Object: isStored=true, insertionTime=" + << timeToString( object->insertionTime() ) << std::endl;; + } + } + } + + // Create folder 1d + std::string folderName1d( "/my/folder1d" ); + cool::IFolderPtr folder1d = db2->createFolder + ( folderName1d, payloadSpec1, "", + FolderVersioning::MULTI_VERSION, true ); + LOG << "Folder created: " << std::endl; + LOG << "-> Folder name: " << folder1d->fullPath() << std::endl; + std::ostringstream folderAttr1d; + folder1c->payloadSpecification().print( folderAttr1d ); + LOG << "-> Folder payload specification: " + << folderAttr1d.str() << std::endl; + + // Print the list of folders again + folderList = db2->getFolderSet( "/my" )->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + + // Insert some data into folder 1d + folder1d->storeObject( 1, 8, payload1, 1 ); + folder1d->storeObject( 2, 5, payload1, 1 ); + folder1d->storeObject( 3, 6, payload1, 1 ); + folder1d->storeObject( 4, 7, payload1, 1 ); + + // Bulk-retrieve the objects stored in channel 1 of folder 1d + tag = ""; + channelId = 1; + since = ValidityKeyMin; + until = ValidityKeyMax; + objIt = + folder1d->browseObjects( since, until, channelId, tag ); + LOG << "Retrieved object iterator in [-inf,+inf] for channel 1 of folder " + << folder1d->fullPath() << std::endl; + if ( objIt->isEmpty() ) { + LOG << "Iterator contains no objects" << std::endl; + } else { + objIt->goToStart(); + while( objIt->hasNext() ) { + IObjectPtr object = objIt->next(); + LOG << "Object: channelId=" << object->channelId() + << ", since=" << object->since() + << ", until=" << object->until() << std::endl; + LOG << "Object: payload values (true types)" + << ": payload[\"I\"]=" << object->payloadValue<int>("I") + << ", payload[\"S\"]=" << object->payloadValue<std::string>("S") + << ", payload[\"X\"]=" << object->payloadValue<float>("X") + << ", payload[\"UI64\"]=" + << object->payloadValue<unsigned long long>("UI64") + //<< ", payload[\"SI64\"]=" + //<< object->payloadValue<long long>("SI64") + << std::endl; + if( ! object->isStored() ) { + LOG << "Object: isStored=false" << std::endl; + } else { + LOG << "Object: isStored=true, insertionTime=" + << timeToString( object->insertionTime() ) << std::endl;; + } + } + } + + // Successful completion + LOG << "Program terminating succesfully" << std::endl; + status = 0; + + } + catch(std::exception& e) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + status = 1; + } + catch(...) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + status = 1; + } + + // Program termination + LOG << "Exiting main" << std::endl; + return status; + +} + +//----------------------------------------------------------------------------- + +#endif // NOPORT diff --git a/RelationalCool/tests/HvsPathHandler/test_HvsPathHandler.cpp b/RelationalCool/tests/HvsPathHandler/test_HvsPathHandler.cpp new file mode 100644 index 000000000..da003170b --- /dev/null +++ b/RelationalCool/tests/HvsPathHandler/test_HvsPathHandler.cpp @@ -0,0 +1,230 @@ +// $Id: test_HvsPathHandler.cpp,v 1.7 2007-04-02 11:53:33 marcocle Exp $ + +// Include files +#include "../Common/CppUnit_headers.h" // Disable CppUnit header warnings + +// Local include files +#include "src/HvsPathHandler.h" +#include "src/HvsPathHandlerException.h" + +namespace cool { + // This line is to avoid error "qualified name does not name a class" + // on gcc 4.1 + class HvsPathHandlerTest; +} + +//----------------------------------------------------------------------------- + +class cool::HvsPathHandlerTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( HvsPathHandlerTest ); + CPPUNIT_TEST( test_removeTrailingSeparators ); + CPPUNIT_TEST( test_removeDoubleSeparators ); + CPPUNIT_TEST( test_splitFullPath ); + CPPUNIT_TEST( test_decodeFullPath ); + CPPUNIT_TEST( test_encodeFullPath ); + CPPUNIT_TEST_SUITE_END(); + +public: + + void setUp() { + } + + void tearDown() { + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + typedef std::string S; + typedef std::pair<S,S> P; + typedef std::vector<S> V; + const V newV( const int nS, const S& s1, const S& s2="", const S& s3="", + const S& s4="", const S& s5="", const S& s6="" ) { + V v; + if ( nS<1 || nS >6 ) + throw HvsPathHandlerException( "Wrong arguments to newV" ); + if ( nS>=1 ) v.push_back( s1 ); + if ( nS>=2 ) v.push_back( s2 ); + if ( nS>=3 ) v.push_back( s3 ); + if ( nS>=4 ) v.push_back( s4 ); + if ( nS>=5 ) v.push_back( s5 ); + if ( nS>=6 ) v.push_back( s6 ); + return v; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_removeTrailingSeparators() { + HvsPathHandler h; + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b/c'", + "/a/b/c" == h.removeTrailingSeparators("/a/b/c") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b/c/'", + "/a/b/c" == h.removeTrailingSeparators("/a/b/c/") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b/c//'", + "/a/b/c" == h.removeTrailingSeparators("/a/b/c//") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/'", + "/" == h.removeTrailingSeparators("/") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '//'", + "/" == h.removeTrailingSeparators("//") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test ''", + "" == h.removeTrailingSeparators("") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test 'a//b/c//'", + "a//b/c" == h.removeTrailingSeparators("a//b/c//") ); + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_removeDoubleSeparators() { + HvsPathHandler h; + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b/c'", + "/a/b/c" == h.removeDoubleSeparators("/a/b/c") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b/c/'", + "/a/b/c/" == h.removeDoubleSeparators("/a/b/c/") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b/c//'", + "/a/b/c/" == h.removeDoubleSeparators("/a/b/c//") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b//c'", + "/a/b/c" == h.removeDoubleSeparators("/a/b//c") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '///a/b///c//'", + "/a/b/c/" == h.removeDoubleSeparators("///a///b/c//") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/'", + "/" == h.removeDoubleSeparators("/") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '//'", + "/" == h.removeDoubleSeparators("//") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test ''", + "" == h.removeDoubleSeparators("") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test 'a//b/c'", + "a/b/c" == h.removeDoubleSeparators("a//b/c") ); + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_splitFullPath() { + + HvsPathHandler h; + + // Test retrieving pairs + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b/c'", + P( "/a/b", "c" ) == h.splitFullPath("/a/b/c") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a'", + P( "/", "a" ) == h.splitFullPath("/a") ); + + // Test catching exceptions + bool caught; + std::vector<std::string> excPaths; + excPaths.push_back(""); + excPaths.push_back("/"); + excPaths.push_back("/a/b/"); + excPaths.push_back("/a//b"); + excPaths.push_back("//"); + std::vector<std::string>::const_iterator iPath; + for ( iPath = excPaths.begin(); iPath != excPaths.end(); iPath++ ) { + std::string excPath = *iPath; + try { caught = false; h.splitFullPath(excPath); } + catch ( HvsPathHandlerException& /* dummy */ ) { caught = true; } + CPPUNIT_ASSERT_MESSAGE( std::string("Test ")+excPath, caught == true ); + } + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_decodeFullPath() { + + HvsPathHandler h; + + // Test retrieving vectors + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b/c'", + newV( 4, "", "a", "b", "c" ) == h.decodeFullPath("/a/b/c") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a'", + newV( 2, "", "a" ) == h.decodeFullPath("/a") ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/", + newV( 1, "" ) == h.decodeFullPath("/") ); + + // Test catching exceptions + bool caught; + std::vector<std::string> excPaths; + excPaths.push_back(""); + excPaths.push_back("a"); + excPaths.push_back("/a/b/"); + excPaths.push_back("/a//b"); + excPaths.push_back("//"); + std::vector<std::string>::const_iterator iPath; + for ( iPath = excPaths.begin(); iPath != excPaths.end(); iPath++ ) { + std::string excPath = *iPath; + try { caught = false; h.decodeFullPath(excPath); } + catch ( HvsPathHandlerException& /* dummy */ ) { caught = true; } + CPPUNIT_ASSERT_MESSAGE( std::string("Test ")+excPath, caught == true ); + } + + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_encodeFullPath() { + + HvsPathHandler h; + + // Test building full paths + CPPUNIT_ASSERT_MESSAGE + ( "Test '/a/b/c'", + "/a/b/c" == h.encodeFullPath( newV(4,"","a","b","c") ) ); + CPPUNIT_ASSERT_MESSAGE + ( "Test '/'", + "/" == h.encodeFullPath( newV(1,"") ) ); + + // Test catching exceptions + bool caught; + std::vector<V> excLists; + excLists.push_back(newV(1,"a")); + excLists.push_back(newV(1,"/")); + excLists.push_back(newV(2,"/","a")); + excLists.push_back(newV(2,"","/")); + excLists.push_back(newV(2,"","/a")); + excLists.push_back(newV(2,"","a/")); + std::vector<V>::const_iterator iList; + for ( iList = excLists.begin(); iList != excLists.end(); iList++ ) { + V excList = *iList; + try { caught = false; h.encodeFullPath(excList); } + catch ( HvsPathHandlerException& /* dummy */ ) { caught = true; } + std::ostringstream msg; + msg << "Test " << excList.size(); + for ( V::const_iterator iS = (*iList).begin(); iS != (*iList).end(); + iS++ ) { msg << ", '" << *iS << "'"; } + CPPUNIT_ASSERT_MESSAGE( msg.str(), caught == true ); + } + + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( cool::HvsPathHandlerTest ); + +//----------------------------------------------------------------------------- + +// Include CppUnit test driver +#include<CppUnit_testdriver.icpp> + + + diff --git a/RelationalCool/tests/HvsTags/test_HvsTags.cpp b/RelationalCool/tests/HvsTags/test_HvsTags.cpp new file mode 100644 index 000000000..31205a9c6 --- /dev/null +++ b/RelationalCool/tests/HvsTags/test_HvsTags.cpp @@ -0,0 +1,2738 @@ +// $Id: test_HvsTags.cpp,v 1.67 2008-11-03 12:20:15 avalassi Exp $ + +// Include files +#include <iostream> +#include "../Common/CppUnit_headers.h" // Disable CppUnit header warnings +#include "src/CoralApplication.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IFolderSet.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoolKernel/Time.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/MessageStream.h" + +// Namespace +namespace cool { + const char* COOLTESTDB = "COOLTESTDB"; + class HvsTagTest; +} + +//----------------------------------------------------------------------------- + +class cool::HvsTagTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( HvsTagTest ); + + CPPUNIT_TEST( test_hvsTags ); + CPPUNIT_TEST( test_iovHeadAndUserTags ); + CPPUNIT_TEST( test_iovAndHvsTags ); + CPPUNIT_TEST( test_userAndHvsTags ); + CPPUNIT_TEST( test_hvsAndIovTags ); + CPPUNIT_TEST( test_hvsAndUserTags ); + CPPUNIT_TEST( test_createParentsTrue ); + CPPUNIT_TEST( test_createParentsFalse ); + CPPUNIT_TEST( test_svFolder ); + CPPUNIT_TEST( test_listTags ); + CPPUNIT_TEST( test_resolveLocalTag ); + CPPUNIT_TEST( test_resolveTagFails ); + CPPUNIT_TEST( test_tagRelationExists ); + + CPPUNIT_TEST( test_lockTag_fails ); + CPPUNIT_TEST( test_tagLocked_dropNode ); + CPPUNIT_TEST( test_tagLocked_storeObjectWithUserTag ); + CPPUNIT_TEST( test_tagLocked_tagCurrentHead ); + CPPUNIT_TEST( test_tagLocked_tagHeadAsOfDate ); + CPPUNIT_TEST( test_tagLocked_deleteTag ); + CPPUNIT_TEST( test_tagLocked_createTagRelation ); + CPPUNIT_TEST( test_tagLocked_deleteTagRelation ); + + CPPUNIT_TEST( test_partiallyLockTag_fails ); + CPPUNIT_TEST( test_tagPartiallyLocked_dropNode ); + CPPUNIT_TEST( test_tagPartiallyLocked_storeObjectWithUserTag ); + CPPUNIT_TEST( test_tagPartiallyLocked_tagCurrentHead ); + CPPUNIT_TEST( test_tagPartiallyLocked_tagHeadAsOfDate ); + CPPUNIT_TEST( test_tagPartiallyLocked_deleteTag ); + CPPUNIT_TEST( test_tagPartiallyLocked_createTagRelation ); + CPPUNIT_TEST( test_tagPartiallyLocked_deleteTagRelation ); + CPPUNIT_TEST( test_tagPartiallyLocked_storeObjectWithUserTagNoOverlap ); + + CPPUNIT_TEST( test_emptyTag ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + std::string connectString; + IDatabasePtr db; + + RecordSpecification payloadSpec; + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_hvsTags() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + IFolderSetPtr sA = db->createFolderSet( "/A" ); + IFolderPtr fAX = createAndFillMVFolder( "/A/fX" ); + IFolderPtr fAY = createAndFillMVFolder( "/A/fY" ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string tA_1 = "/A version #1"; + std::string tAX_1 = "/A/fX version #1"; + std::string tAY_1 = "/A/fY version #1"; + fAX->createTagRelation( tA_1, tAX_1 ); + fAY->createTagRelation( tA_1, tAY_1 ); + + // Query parent-child tag relations + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fX tag for " + tA_1, tAX_1, fAX->findTagRelation( tA_1 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fY tag for " + tA_1, tAY_1, fAY->findTagRelation( tA_1 ) ); + + // Tag hierarchy for "/A version #2" + // -> fldset '/A version #2' + // -> folder '/A/fX version #2' + // -> folder '/A/fY version #2' + std::string tA_2 = "/A version #2"; + std::string tAX_2 = "/A/fX version #2"; + std::string tAY_2 = "/A/fY version #2"; + fAX->createTagRelation( tA_2, tAX_2 ); + fAY->createTagRelation( tA_2, tAY_2 ); + + // Query parent-child tag relations + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fX tag for " + tA_2, tAX_2, fAX->findTagRelation( tA_2 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fY tag for " + tA_2, tAY_2, fAY->findTagRelation( tA_2 ) ); + + // Tag hierarchy for "/ version PROD" + // -> fldset '/ version PROD' + // -> fldset '/A version PROD' + // -> folder '/A/fX version #2' + // -> folder '/A/fY version #1' + std::string tA_PR = "/A version PROD"; + std::string t_PR = "/ version PROD"; + + // Test existance of tags in any node + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_PR + " exist?", false, db->existsTag( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + t_PR + " exist?", false, db->existsTag( t_PR ) ); + + // Create tag relations for /A PROD version + fAX->createTagRelation( tA_PR, tAX_2 ); + fAY->createTagRelation( tA_PR, tAY_1 ); + + // Test existance of tags in any node + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_PR + " exist?", true, db->existsTag( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + t_PR + " exist?", false, db->existsTag( t_PR ) ); + + // Create tag relations for / PROD version + sA->createTagRelation( t_PR, tA_PR ); + + // Test existance of tags in any node + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_PR + " exist?", true, db->existsTag( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + t_PR + " exist?", true, db->existsTag( t_PR ) ); + + // Query parent-child tag relations + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fX tag for " + tA_PR, + tAX_2, fAX->findTagRelation( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fY tag for " + tA_PR, + tAY_1, fAY->findTagRelation( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A tag for " + t_PR, tA_PR, sA->findTagRelation( t_PR ) ); + + // Resolve parent-child tag relations (w/o assuming parent-child nodes) + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fX tag for " + tA_PR, tAX_2, fAX->resolveTag( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fY tag for " + tA_PR, tAY_1, fAY->resolveTag( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A tag for " + t_PR, tA_PR, sA->resolveTag( t_PR ) ); + + // Resolve ancestor-descendant tag relations + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fX tag for " + t_PR, tAX_2, fAX->resolveTag( t_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A/fY tag for " + t_PR, tAY_1, fAY->resolveTag( t_PR ) ); + + // Test existance of tags in any node + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_PR + " exist?", true, db->existsTag( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + t_PR + " exist?", true, db->existsTag( t_PR ) ); + + // Delete tag relation for / PROD version + sA->deleteTagRelation( t_PR ); + + // Test existance of tag relation + try { + sA->findTagRelation( t_PR ); + CPPUNIT_FAIL( "Find /A tag for " + t_PR + " should fail" ); + } + catch ( TagNotFound& ) {} + catch ( TagRelationNotFound& ) { + CPPUNIT_FAIL( "Find /A tag for " + t_PR + " TagNotFound expected" ); + } + + // Test existance of tags in any node + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_PR + " exist?", true, db->existsTag( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + t_PR + " exist?", false, db->existsTag( t_PR ) ); + + // Create tag relations for / PROD version - again + sA->createTagRelation( t_PR, tA_PR ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Find /A tag for " + t_PR, tA_PR, sA->findTagRelation( t_PR ) ); + + // Delete tag relation for / PROD version - again + sA->deleteTagRelation( t_PR ); + try { + sA->findTagRelation( t_PR ); + CPPUNIT_FAIL( "Find /A tag for " + t_PR + " should fail" ); + } + catch ( TagNotFound& ) {} + catch ( TagRelationNotFound& ) { + CPPUNIT_FAIL( "Find /A tag for " + t_PR + " TagNotFound expected" ); + } + + // Test existance of tags in any node + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_PR + " exist?", true, db->existsTag( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + t_PR + " exist?", false, db->existsTag( t_PR ) ); + + // Delete /A/fX tag relation for /A PROD version + fAX->deleteTagRelation( tA_PR ); + try { + fAX->findTagRelation( tA_PR ); + CPPUNIT_FAIL( "Find /A/fX tag for " + tA_PR + " should fail" ); + } + catch ( TagRelationNotFound& ) {} + + // Test existance of tags in any node + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tAX_2 + " exist?", true, db->existsTag( tAX_2 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_PR + " exist?", true, db->existsTag( tA_PR ) ); + + // Delete /A/fY tag relation for /A PROD version + fAY->deleteTagRelation( tA_PR ); + try { + fAY->findTagRelation( tA_PR ); + CPPUNIT_FAIL( "Find /A/fY tag for " + tA_PR + " should fail" ); + } + catch ( TagNotFound& ) {} + catch ( TagRelationNotFound& ) { + CPPUNIT_FAIL( "Find /A/fY tag for " + t_PR + " TagNotFound expected" ); + } + + // Test existance of tags in any node + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tAY_1 + " exist?", true, db->existsTag( tAY_1 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_PR + " exist?", false, db->existsTag( tA_PR ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_1 + " exist?", true, db->existsTag( tA_1 ) ); + + // Delete /A/fY tag relation for /A version #1 + fAY->deleteTagRelation( tA_1 ); + try { + fAY->findTagRelation( tA_1 ); + CPPUNIT_FAIL( "Find /A/fY tag for " + tA_1 + " should fail" ); + } + catch ( TagRelationNotFound& ) {} + + // Test existance of tags in any node + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tAY_1 + " exist?", false, db->existsTag( tAY_1 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Does tag " + tA_1 + " exist?", true, db->existsTag( tA_1 ) ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_iovHeadAndUserTags() + { + bool debug = false; + try { + + // Folder /fA + if ( debug ) std::cout << "Test A" << std::endl; + IFolderPtr fa = createAndFillMVFolder( "/fA" ); + std::string ah1 = "AH1"; + std::string ad1 = "AD1"; + std::string au1 = "AU1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 Exist "+ah1, false, db->existsTag(ah1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 Exist "+ad1, false, db->existsTag(ad1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 Exist "+au1, false, db->existsTag(au1) ); + if ( debug ) std::cout << "Test A count AH1" << std::endl; + CPPUNIT_ASSERT_THROW + ( fa->countObjects(0,100,0,ah1), TagNotFound ); + if ( debug ) std::cout << "Test A count AD1" << std::endl; + CPPUNIT_ASSERT_THROW + ( fa->countObjects(0,100,0,ad1), TagNotFound ); + if ( debug ) std::cout << "Test A count AU1" << std::endl; + CPPUNIT_ASSERT_THROW + ( fa->countObjects(0,100,0,au1), TagNotFound ); + + // - create AH1 as IOV head tag + // > using AH1 as IOV date tag fails + // > using AH1 as IOV user tag fails + if ( debug ) std::cout << "Test AH1" << std::endl; + fa->tagCurrentHead( ah1 ); + Time date = fa->findObject( 20, 0 )->insertionTime(); + Record payload = dummyPayload( 10 ); + try { + fa->tagHeadAsOfDate( date, ah1 ); + CPPUNIT_FAIL( "Using AH1 as date tag should fail" ); + } catch ( TagExists& ) {} + try { + fa->storeObject( 5, 15, payload, 0, ah1 ); + CPPUNIT_FAIL( "Using AH1 as user tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Exist "+ah1, true, db->existsTag(ah1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Exist "+ad1, false, db->existsTag(ad1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Exist "+au1, false, db->existsTag(au1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 # "+ah1, 3u, fa->countObjects(0,100,0,ah1) ); + CPPUNIT_ASSERT_THROW + ( fa->countObjects(0,100,0,ad1), TagNotFound ); + CPPUNIT_ASSERT_THROW + ( fa->countObjects(0,100,0,au1), TagNotFound ); + + // - create AD1 as IOV date tag + // > using AD1 as IOV head tag fails + // > using AD1 as IOV user tag fails + if ( debug ) std::cout << "Test AD1" << std::endl; + fa->tagHeadAsOfDate( date, ad1 ); + try { + fa->tagCurrentHead( ad1 ); + CPPUNIT_FAIL( "Using AD1 as head tag should fail" ); + } catch ( TagExists& ) {} + try { + fa->storeObject( 5, 15, payload, 0, ad1 ); + CPPUNIT_FAIL( "Using AD1 as user tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Exist "+ah1, true, db->existsTag(ah1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Exist "+ad1, true, db->existsTag(ad1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Exist "+au1, false, db->existsTag(au1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 # "+ah1, 3u, fa->countObjects(0,100,0,ah1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 # "+ad1, 3u, fa->countObjects(0,100,0,ad1) ); + CPPUNIT_ASSERT_THROW + ( fa->countObjects(0,100,0,au1), TagNotFound ); + + // - create AU1 as IOV user tag + // > using AU1 as IOV head tag fails + // > using AU1 as IOV date tag fails + if ( debug ) std::cout << "Test AU1" << std::endl; + fa->storeObject( 5, 15, payload, 0, au1 ); + try { + fa->tagCurrentHead( au1 ); + CPPUNIT_FAIL( "Using AU1 as head tag should fail" ); + } catch ( TagExists& ) {} + try { + fa->tagHeadAsOfDate( date, au1 ); + CPPUNIT_FAIL( "Using AU1 as date tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Exist "+ah1, true, db->existsTag(ah1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Exist "+ad1, true, db->existsTag(ad1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Exist "+au1, true, db->existsTag(au1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 # "+ah1, 3u, fa->countObjects(0,100,0,ah1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 # "+ad1, 3u, fa->countObjects(0,100,0,ad1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 # "+au1, 1u, fa->countObjects(0,100,0,au1) ); + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_iovAndHvsTags() + { + + try { + Record payload = dummyPayload( 10 ); + // Folder /fA + // - create A1 as IOV head tag + // > using A1 as IOV user tag fails + // - create A1 as HVS tag (create relation) + // - delete A1 as IOV tag + // - delete A1 as HVS tag (delete relation) + IFolderPtr fa = createAndFillMVFolder( "/fA" ); + std::string prod = "PROD"; + std::string a1 = "A1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_THROW( fa->countObjects(0,100,0,a1), TagNotFound ); + fa->tagCurrentHead( a1 ); + try { + fa->storeObject( 5, 15, payload, 0, a1 ); + CPPUNIT_FAIL( "Using A1 as user tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 3u, fa->countObjects(0,100,0,a1) ); + fa->createTagRelation( prod, a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+a1, a1, fa->findTagRelation(prod) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 3u, fa->countObjects(0,100,0,a1) ); + // This may be a bit confusing: the tag still exists after being deleted! + // A better name for this method may be 'untag' (remove IOV2TAG links). + fa->deleteTag( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+a1, a1, fa->findTagRelation(prod) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 0u, fa->countObjects(0,100,0,a1) ); + fa->deleteTagRelation( prod ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_userAndHvsTags() + { + + try { + Record payload = dummyPayload( 10 ); + // Folder /fA + // - create A1 as IOV user tag + // > using A1 as IOV head tag fails + // - create A1 as HVS tag (create relation) + // - delete A1 as IOV tag + // - delete A1 as HVS tag (delete relation) + IFolderPtr fa = createAndFillMVFolder( "/fA" ); + std::string prod = "PROD"; + std::string a1 = "A1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_THROW( fa->countObjects(0,100,0,a1), TagNotFound ); + fa->storeObject( 5, 15, payload, 0, a1 ); + try { + fa->tagCurrentHead( a1 ); + CPPUNIT_FAIL( "Using A1 as head tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 1u, fa->countObjects(0,100,0,a1) ); + fa->createTagRelation( prod, a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+a1, a1, fa->findTagRelation(prod) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 1u, fa->countObjects(0,100,0,a1) ); + fa->deleteTag( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+a1, a1, fa->findTagRelation(prod) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 0u, fa->countObjects(0,100,0,a1) ); + fa->deleteTagRelation( prod ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_hvsAndIovTags() + { + + try { + Record payload = dummyPayload( 10 ); + // Folder /fA + // - create A1 as HVS tag (create relation) + // - create A1 as IOV head tag + // > using A1 as IOV user tag fails + // - delete A1 as HVS tag (delete relation) + // - delete A1 as IOV tag + IFolderPtr fa = createAndFillMVFolder( "/fA" ); + std::string prod = "PROD"; + std::string a1 = "A1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + fa->createTagRelation( prod, a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+a1, a1, fa->findTagRelation(prod) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 0u, fa->countObjects(0,100,0,a1) ); + fa->tagCurrentHead( a1 ); + try { + fa->storeObject( 5, 15, payload, 0, a1 ); + CPPUNIT_FAIL( "Using A1 as user tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 3u, fa->countObjects(0,100,0,a1) ); + fa->deleteTagRelation( prod ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 3u, fa->countObjects(0,100,0,a1) ); + try { + fa->findTagRelation(prod); + CPPUNIT_FAIL( "Solving the PROD-A1 relation should fail" ); + } catch ( TagNotFound& ) {} + fa->deleteTag( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_THROW( fa->countObjects(0,100,0,a1), TagNotFound ); + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_hvsAndUserTags() + { + + try { + Record payload = dummyPayload( 10 ); + // Folder /fA + // - create A1 as HVS tag (create relation) + // - create A1 as IOV user tag + // > using A1 as IOV head tag fails + // - delete A1 as HVS tag (delete relation) + // - delete A1 as IOV tag + IFolderPtr fa = createAndFillMVFolder( "/fA" ); + std::string prod = "PROD"; + std::string a1 = "A1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + fa->createTagRelation( prod, a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 0u, fa->countObjects(0,100,0,a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+a1, a1, fa->findTagRelation(prod) ); + fa->storeObject( 5, 15, payload, 0, a1 ); + try { + fa->tagCurrentHead( a1 ); + CPPUNIT_FAIL( "Using A1 as head tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 1u, fa->countObjects(0,100,0,a1) ); + fa->deleteTagRelation( prod ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 1u, fa->countObjects(0,100,0,a1) ); + try { + fa->findTagRelation(prod); + CPPUNIT_FAIL( "Solving the PROD-A1 relation should fail" ); + } catch ( TagNotFound& ) {} + fa->deleteTag( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_THROW( fa->countObjects(0,100,0,a1), TagNotFound ); + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + /// Tests that the tag sequence table is created for folder sets that are + /// not automatically generated (control sample for bug #16257) + void test_createParentsFalse() + { + try { + bool createParents = false; + db->createFolderSet( "/top" ); + IFolderPtr fa = db->createFolder + ( "/top/A1", payloadSpec, "desc", + FolderVersioning::MULTI_VERSION, createParents ); + Record payload = dummyPayload( 10 ); + fa->storeObject( 5, 15, payload, 0, "user tag" ); + fa->createTagRelation( "PROD", "user tag" ); + CPPUNIT_ASSERT_EQUAL( std::string("user tag"), + fa->resolveTag( "PROD" ) ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + /// Tests that the tag sequence table is created also for folder sets + /// that are automatically generated for createParents=true (bug #16257) + void test_createParentsTrue() + { + try { + bool createParents = true; + IFolderPtr fa = db->createFolder + ( "/top/A1", payloadSpec, "desc", + FolderVersioning::MULTI_VERSION, createParents ); + Record payload = dummyPayload( 10 ); + fa->storeObject( 5, 15, payload, 0, "user tag" ); + fa->createTagRelation( "PROD", "user tag" ); + CPPUNIT_ASSERT_EQUAL( std::string("user tag"), + fa->resolveTag( "PROD" ) ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_svFolder() + { + + try { + // Node hierarchy + // -> fldset / + // -> folder /mv + // -> folder /sv + IFolderPtr fmv = createAndFillMVFolder( "/mv" ); + IFolderPtr fsv = createAndFillSVFolder( "/sv" ); + std::string prod = "PROD"; + std::string s1 = "S1"; + std::string m1 = "M1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+s1, false, db->existsTag(s1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+m1, false, db->existsTag(m1) ); + fmv->createTagRelation( prod, m1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+s1, false, db->existsTag(s1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+m1, true, db->existsTag(m1) ); + try { + fsv->createTagRelation( prod, s1 ); + CPPUNIT_FAIL( "Creating HVS relation for SV folder should fail" ); + } + catch ( FolderIsSingleVersion& ) {} + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_listTags() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/mv + // -> folder /A/sv + IFolderSetPtr sA = db->createFolderSet( "/A" ); + IFolderPtr fAM = createAndFillMVFolder( "/A/mv" ); + IFolderPtr fAS = createAndFillSVFolder( "/A/sv" ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/mv version #1' + std::string tA_1 = "/A version #1"; + std::string tAM_1 = "/A/mv version #1"; + fAM->createTagRelation( tA_1, tAM_1 ); + + // Tag hierarchy for "/A version #2" + // -> fldset '/A version #2' + // -> folder '/A/mv version #2' + std::string tA_2 = "/A version #2"; + std::string tAM_2 = "/A/mv version #2"; + fAM->createTagRelation( tA_2, tAM_2 ); + + // Tag hierarchy for "/ version PROD" + // -> fldset '/ version PROD' + // -> fldset '/A version PROD' + // -> folder '/A/mv version #1' + std::string t_PR = "/ version PROD"; + std::string tA_PR = "/A version PROD"; + sA->createTagRelation( t_PR, tA_PR ); + fAM->createTagRelation( tA_PR, tAM_1 ); + + // List tags for MV folder "/A/mv" + std::vector<std::string> tagsAM = fAM->listTags(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "/A/mv tag count", 2u, (unsigned int)tagsAM.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/A/mv tag 1", tAM_1, tagsAM[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/A/mv tag 2", tAM_2, tagsAM[1] ); + + // List tags for SV folder "/A/sv" + std::vector<std::string> tagsAS = fAS->listTags(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "/A/sv tag count", 0u, (unsigned int)tagsAS.size() ); + + // List tags for folder set "/A" + std::vector<std::string> tagsA = sA->listTags(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "/A tag count", 3u, (unsigned int)tagsA.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/A tag 1", tA_1, tagsA[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/A tag 2", tA_2, tagsA[1] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/A tag 3", tA_PR, tagsA[2] ); + + // List tags for folder set "/" + IFolderSetPtr sROOT = db->getFolderSet( "/" ); + std::vector<std::string> tagsROOT = sROOT->listTags(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "/ tag count", 1u, (unsigned int)tagsROOT.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/ tag 1", t_PR, tagsROOT[0] ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + // Test for bug #16566 + void test_resolveLocalTag() + { + + try { + + IFolderPtr f = createAndFillMVFolder( "/folder" ); + std::string folderTag = "local_tag_1"; + std::string folderSetTag = "prod_v1"; + f->tagCurrentHead( folderTag ); + // COOL_1_3_1 exception: "Tag 'local_tag_1' not found in any inner node" + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Resolve (1) " + folderTag, + folderTag, f->resolveTag( folderTag ) ); + f->createTagRelation( folderSetTag, folderTag ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Resolve (2) " + folderTag, + folderTag, f->resolveTag( folderTag ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Resolve " + folderSetTag, + folderTag, f->resolveTag( folderSetTag ) ); + std::vector<std::string> fTags = f->listTags(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "/folder tag count", 1u, (unsigned int)fTags.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/folder tag 1", folderTag, fTags[0] ); + IFolderSetPtr rf = db->getFolderSet("/"); + std::vector<std::string> rfTags = rf->listTags(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "/ tag count", 1u, (unsigned int)rfTags.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/ tag 1", folderSetTag, rfTags[0] ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_resolveTagFails() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + IFolderSetPtr sA = db->createFolderSet( "/A" ); + IFolderPtr fAX = createAndFillMVFolder( "/A/fX" ); + + // Tag hierarchy for "/ version PROD" + // -> fldset '/ version PROD' + // -> fldset '/A version #1' + std::string tA_1 = "/A version #1"; + std::string t_PR = "/ version PROD"; + + // Create tag relations for / PROD version + sA->createTagRelation( t_PR, tA_1 ); + + // Test that resolveTag should fail at this stage + try { + fAX->resolveTag( t_PR ); + CPPUNIT_FAIL( "Resolve /A/fX tag for " + t_PR + " should fail" ); + } + catch ( TagRelationNotFound& ) {} + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + // Test for bug #18201 + void test_tagRelationExists() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + IFolderSetPtr sA = db->createFolderSet( "/A" ); + + // Tag hierarchy for "/ version PROD" + // -> fldset '/ version PROD' + // -> fldset '/A version #1' + // OR fldset '/A version #2' + std::string tA_1 = "/A version #1"; + std::string tA_2 = "/A version #2"; + std::string t_PR = "/ version PROD"; + + // Create tag relations for / PROD version + sA->createTagRelation( t_PR, tA_1 ); + + // Test that resolveTag should fail at this stage + try { + sA->createTagRelation( t_PR, tA_2 ); + CPPUNIT_FAIL( "Creating tag relation between " + t_PR + " and " + tA_2 + + " should fail" ); + } + catch ( TagRelationExists& ) {} + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_lockTag_fails() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + + // Attempt to lock tags before they are created fails + // (fails with private RowNotUpdated exception) + CPPUNIT_ASSERT_THROW + ( sA->setTagLockStatus( a1, HvsTagLock::LOCKED ), Exception ); + CPPUNIT_ASSERT_THROW + ( fAX->setTagLockStatus( x1, HvsTagLock::LOCKED ), Exception ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_THROW( sA->tagLockStatus( a1 ), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->tagLockStatus( x1 ), TagNotFound ); + + // Attempt to lock tags after they are created succeds + fAX->createTagRelation( a1, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Locked "+a1, + (int)HvsTagLock::UNLOCKED, (int)sA->tagLockStatus(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Locked "+x1, + (int)HvsTagLock::UNLOCKED, (int)fAX->tagLockStatus(x1) ); + sA->setTagLockStatus( a1, HvsTagLock::LOCKED ); + fAX->setTagLockStatus( x1, HvsTagLock::LOCKED ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Locked "+a1, + (int)HvsTagLock::LOCKED, (int)sA->tagLockStatus(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Locked "+x1, + (int)HvsTagLock::LOCKED, (int)fAX->tagLockStatus(x1) ); + + // Cleanup - unlock all tags + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + fAX->setTagLockStatus( x1, HvsTagLock::UNLOCKED ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Locked "+a1, + (int)HvsTagLock::UNLOCKED, (int)sA->tagLockStatus(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Locked "+x1, + (int)HvsTagLock::UNLOCKED, (int)fAX->tagLockStatus(x1) ); + + // Attempt to lock HEAD tag always fails - HEAD is always unlocked + std::string h1 = "HEAD"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5 Exist "+h1, true, db->existsTag(h1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5 Locked "+h1, + (int)HvsTagLock::UNLOCKED, (int)fAX->tagLockStatus(h1) ); + CPPUNIT_ASSERT_THROW + ( fAX->setTagLockStatus( h1, HvsTagLock::LOCKED ), ReservedHeadTag ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6 Exist "+h1, true, db->existsTag(h1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6 Locked "+h1, + (int)HvsTagLock::UNLOCKED, (int)fAX->tagLockStatus(h1) ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagLocked_dropNode() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + std::string nameAY = "/A/fY"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + IFolderPtr fAY = createAndFillMVFolder( nameAY ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string tA_1 = "/A version #1"; + std::string tAX_1 = "/A/fX version #1"; + std::string tAY_1 = "/A/fY version #1"; + fAX->createTagRelation( tA_1, tAX_1 ); + fAY->createTagRelation( tA_1, tAY_1 ); + + // Lock a tag in /A/fY + fAY->setTagLockStatus( tAY_1, HvsTagLock::LOCKED ); + + // Attempt to drop nodes + db->dropNode( nameAX ); + CPPUNIT_ASSERT_THROW( db->dropNode( nameAY ), TagIsLocked ); + CPPUNIT_ASSERT_THROW( db->dropNode( nameA ), Exception ); // not empty + + // Unlock all tags in /A/fY + fAY->setTagLockStatus( tAY_1, HvsTagLock::UNLOCKED ); + + // Lock a tag in /A + sA->setTagLockStatus( tA_1, HvsTagLock::LOCKED ); + + // Attempt to drop nodes again + db->dropNode( nameAY ); + CPPUNIT_ASSERT_THROW( db->dropNode( nameA ), TagIsLocked ); + + // Unlock all tags in /A + sA->setTagLockStatus( tA_1, HvsTagLock::UNLOCKED ); + + // Attempt to drop nodes again + db->dropNode( nameA ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagLocked_storeObjectWithUserTag() + { + + try { + + // Folder /fA + // - create A1 as child HVS tag (create relation) + // - create A1 as IOV user tag + // > attempt to use A1 as IOV head tag fails + IFolderPtr fA = createAndFillMVFolder( "/fA" ); + std::string prod = "PROD"; + std::string a1 = "A1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + fA->createTagRelation( prod, a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 0u, fA->countObjects(0,100,0,a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+a1, a1, fA->findTagRelation(prod) ); + Record payload = dummyPayload( 10 ); + fA->storeObject( 5, 15, payload, 0, a1 ); + try { + fA->tagCurrentHead( a1 ); + CPPUNIT_FAIL( "Using A1 as head tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 1u, fA->countObjects(0,100,0,a1) ); + + // - lock A1 user tag + // - delete A1 as child HVS tag (delete relation) + // - attempt to add another object to A1 user tag fails + // - attempt to delete A1 as IOV tag fails + fA->setTagLockStatus( a1, HvsTagLock::LOCKED ); + fA->deleteTagRelation( prod ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 1u, fA->countObjects(0,100,0,a1) ); + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 15, 25, payload, 0, a1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW + ( fA->deleteTag( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 #", 1u, fA->countObjects(0,100,0,a1) ); + + // - unlock A1 user tag + // - attempt to add another object to A1 user tag succeeds + // - attempt to delete A1 as IOV tag succeeds + fA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + fA->storeObject( 15, 25, payload, 0, a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 #", 2u, fA->countObjects(0,100,0,a1) ); + fA->deleteTag( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_THROW( fA->countObjects(0,100,0,a1), TagNotFound ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagLocked_tagCurrentHead() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + + // - create X1 as IOV head tag + // > using X1 as IOV user tag fails + // - create X1 as HVS tag (create relation) + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + fAX->tagCurrentHead( x1 ); + Record payload = dummyPayload( 10 ); + try { + fAX->storeObject( 5, 15, payload, 0, x1 ); + CPPUNIT_FAIL( "Using X1 as user tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 3u, fAX->countObjects(0,100,0,x1) ); + fAX->createTagRelation( a1, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 3u, fAX->countObjects(0,100,0,x1) ); + + // - lock folder set A1 tag + // - lock folder X1 head tag + // - attempt to add another object to HEAD succeeds + // - attempt to delete X1 as IOV tag fails + // - attempt to retag the current HEAD fails + sA->setTagLockStatus( a1, HvsTagLock::LOCKED ); + fAX->setTagLockStatus( x1, HvsTagLock::LOCKED ); + fAX->storeObject( 5, 15, payload, 0 ); + CPPUNIT_ASSERT_THROW( fAX->deleteTag( x1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW( fAX->tagCurrentHead( x1 ), TagExists ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 3u, fAX->countObjects(0,100,0,x1) ); + + // - unlock folder X1 head tag + // - attempt to delete X1 as IOV tag succeeds + // > tag X1 still exists as HVS tag + // - attempt to retag the current HEAD succeeds + fAX->setTagLockStatus( x1, HvsTagLock::UNLOCKED ); + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 #", 0u, fAX->countObjects(0,100,0,x1) ); + fAX->tagCurrentHead( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 #", 4u, fAX->countObjects(0,100,0,x1) ); + + // - attempt to delete A1 as folder set tag fails + // - unlock folder set tag A1 + // - attempt to delete A1 as folder set tag succeeds + // - attempt to delete X1 as IOV tag succeeds + CPPUNIT_ASSERT_THROW( fAX->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+x1, true, db->existsTag(x1) ); + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + fAX->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+x1, true, db->existsTag(x1) ); + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 Exist "+x1, false, db->existsTag(x1) ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagLocked_tagHeadAsOfDate() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + + // - create X1 as IOV date tag + // > using X1 as IOV user tag fails + // - create X1 as HVS tag (create relation) + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + Time date = fAX->findObject( 20, 0 )->insertionTime(); + fAX->tagHeadAsOfDate( date, x1 ); + Record payload = dummyPayload( 10 ); + try { + fAX->storeObject( 5, 15, payload, 0, x1 ); + CPPUNIT_FAIL( "Using X1 as user tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 3u, fAX->countObjects(0,100,0,x1) ); + fAX->createTagRelation( a1, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 3u, fAX->countObjects(0,100,0,x1) ); + + // - lock folder set A1 tag + // - lock folder X1 head tag + // - attempt to add another object to HEAD succeeds + // - attempt to delete X1 as IOV tag fails + // - attempt to retag at new date fails + sA->setTagLockStatus( a1, HvsTagLock::LOCKED ); + fAX->setTagLockStatus( x1, HvsTagLock::LOCKED ); + fAX->storeObject( 5, 15, payload, 0 ); + date = fAX->findObject( 5, 0 )->insertionTime(); + CPPUNIT_ASSERT_THROW( fAX->deleteTag( x1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW + ( fAX->tagHeadAsOfDate( date, x1 ), TagExists ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 3u, fAX->countObjects(0,100,0,x1) ); + + // - unlock folder X1 head tag + // - attempt to delete X1 as IOV tag succeeds + // > tag X1 still exists as HVS tag + // - attempt to retag at new date succeeds + fAX->setTagLockStatus( x1, HvsTagLock::UNLOCKED ); + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 #", 0u, fAX->countObjects(0,100,0,x1) ); + fAX->tagHeadAsOfDate( date, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 #", 4u, fAX->countObjects(0,100,0,x1) ); + + // - attempt to delete A1 as folder set tag fails + // - unlock folder set tag A1 + // - attempt to delete A1 as folder set tag succeeds + // - attempt to delete X1 as IOV tag succeeds + CPPUNIT_ASSERT_THROW( fAX->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+x1, true, db->existsTag(x1) ); + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + fAX->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+x1, true, db->existsTag(x1) ); + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 Exist "+x1, false, db->existsTag(x1) ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagLocked_deleteTag() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + std::string nameAY = "/A/fY"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + IFolderPtr fAY = createAndFillMVFolder( nameAY ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + std::string y1 = "/A/fY version #1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + // Create tag relations + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 0u, fAX->countObjects(0,100,0,x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Lock a tag in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::LOCKED ); + + // Attempt to delete folder tags + // Note that actually these folder tags have no IOVs associated... even + // if deleteTag( x1 ) succceds, it actually does nothing because the + // relation to a1 still exists (hence do not attempt to recreate it!) + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_THROW( fAY->deleteTag( y1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 0u, fAX->countObjects(0,100,0,x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + + // Lock a tag in /A + sA->setTagLockStatus( a1, HvsTagLock::LOCKED ); + + // Attempt to delete folder tags again + fAX->deleteTag( x1 ); + fAY->deleteTag( y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 0u, fAX->countObjects(0,100,0,x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + + // Delete all tag relations + fAX->deleteTagRelation( a1 ); + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + // Tag current HEAD in /A/fY + fAY->tagCurrentHead( y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 #", 3u, fAY->countObjects(0,100,0,y1) ); + + // Lock a tag in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::LOCKED ); + + // Attempt to delete folder tags + // Note that actually these folder tags have no IOVs associated... even + // if deleteTag( x1 ) succceds, it actually does nothing because the + // relation to a1 still exists (hence do not attempt to recreate it!) + CPPUNIT_ASSERT_THROW( fAY->deleteTag( y1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 #", 3u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + + // Attempt to delete folder tags again + fAY->deleteTag( y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagLocked_createTagRelation() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + std::string nameAY = "/A/fY"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + IFolderPtr fAY = createAndFillMVFolder( nameAY ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + std::string y1 = "/A/fY version #1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Create tag relations + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+y1, y1, fAY->findTagRelation(a1) ); + + // Delete tag relations + fAX->deleteTagRelation( a1 ); + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Lock a tag in /A/fY + // You must create the tag first (eg by tagCurrentHead) + fAY->tagCurrentHead( y1 ); + fAY->setTagLockStatus( y1, HvsTagLock::LOCKED ); + + // Create tag relations + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+y1, y1, fAY->findTagRelation(a1) ); + + // Delete tag relations + fAX->deleteTagRelation( a1 ); + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Attempt to delete the /A/fY tag will fail + CPPUNIT_ASSERT_THROW( fAY->deleteTag(y1), TagIsLocked ); + + // Unlock all tags in /A/fY (and delete them) + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + fAY->deleteTag(y1); + + // Attempt to lock a tag in /A + // This will fail because the tag does not exist, i.e. has no associated + // child node tags (and note that it throws Exception, not TagNotFound) + CPPUNIT_ASSERT_THROW + ( sA->setTagLockStatus( a1, HvsTagLock::LOCKED ), Exception ); + + // Create /A/fX tag relation - this will create the /A tag + fAX->createTagRelation( a1, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagRelationNotFound ); + + // Lock a tag in /A + sA->setTagLockStatus( a1, HvsTagLock::LOCKED ); + + // Attempt to create tag relations + CPPUNIT_ASSERT_THROW( fAY->createTagRelation( a1, y1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagRelationNotFound ); + + // Unlock all tags in /A + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagLocked_deleteTagRelation() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + std::string nameAY = "/A/fY"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + IFolderPtr fAY = createAndFillMVFolder( nameAY ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + std::string y1 = "/A/fY version #1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Create tag relations + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+y1, y1, fAY->findTagRelation(a1) ); + + // Lock a tag in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::LOCKED ); + + // Attempt to delete tag relations + // Deleting the /A/fY tag relation fails because the child tag would + // be deleted and is locked (it would not fail if the child tag were + // locked but deleteTagRelation would not lead to deleting the tag) + fAX->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_THROW( fAY->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagRelationNotFound ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + + // Use tags in /A/fY for the current HEAD and lock them again + fAY->tagCurrentHead( y1 ); + fAY->setTagLockStatus( y1, HvsTagLock::LOCKED ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagRelationNotFound ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 3u, fAY->countObjects(0,100,0,y1) ); + + // Attempt to delete tag relations again + // Deleting the /A/fY tag relation does NOT fail even if the child tag is + // locked, because deleteTagRelation would not lead to deleting the tag + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 #", 3u, fAY->countObjects(0,100,0,y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Unlock all tags in /A/fY (and delete them) + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + fAY->deleteTag( y1 ); + + // Create tag relations again + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+y1, y1, fAY->findTagRelation(a1) ); + + // Lock a tag in /A + sA->setTagLockStatus( a1, HvsTagLock::LOCKED ); + + // Attempt to delete tag relations - will fail as parent tag is locked + CPPUNIT_ASSERT_THROW( fAX->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW( fAY->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 #", 0u, fAX->countObjects(0,100,0,x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + + // Delete tag relations again + fAX->deleteTagRelation( a1 ); + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_partiallyLockTag_fails() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + + // Attempt to lock tags before they are created fails + // (fails with private RowNotUpdated exception) + CPPUNIT_ASSERT_THROW + ( sA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ), Exception ); + CPPUNIT_ASSERT_THROW + ( fAX->setTagLockStatus( x1, HvsTagLock::PARTIALLYLOCKED ), Exception ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_THROW( sA->tagLockStatus( a1 ), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->tagLockStatus( x1 ), TagNotFound ); + + // Attempt to lock tags after they are created succeds + fAX->createTagRelation( a1, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Locked "+a1, + (int)HvsTagLock::UNLOCKED, (int)sA->tagLockStatus(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Locked "+x1, + (int)HvsTagLock::UNLOCKED, (int)fAX->tagLockStatus(x1) ); + sA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ); + fAX->setTagLockStatus( x1, HvsTagLock::PARTIALLYLOCKED ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Locked "+a1, + (int)HvsTagLock::PARTIALLYLOCKED, (int)sA->tagLockStatus(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Locked "+x1, + (int)HvsTagLock::PARTIALLYLOCKED, (int)fAX->tagLockStatus(x1) ); + + // Cleanup - unlock all tags + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + fAX->setTagLockStatus( x1, HvsTagLock::UNLOCKED ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Locked "+a1, + (int)HvsTagLock::UNLOCKED, (int)sA->tagLockStatus(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Locked "+x1, + (int)HvsTagLock::UNLOCKED, (int)fAX->tagLockStatus(x1) ); + + // Attempt to lock HEAD tag always fails - HEAD is always unlocked + std::string h1 = "HEAD"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5 Exist "+h1, true, db->existsTag(h1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5 Locked "+h1, + (int)HvsTagLock::UNLOCKED, (int)fAX->tagLockStatus(h1) ); + CPPUNIT_ASSERT_THROW + ( fAX->setTagLockStatus( h1, HvsTagLock::PARTIALLYLOCKED ), ReservedHeadTag ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6 Exist "+h1, true, db->existsTag(h1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6 Locked "+h1, + (int)HvsTagLock::UNLOCKED, (int)fAX->tagLockStatus(h1) ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagPartiallyLocked_dropNode() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + std::string nameAY = "/A/fY"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + IFolderPtr fAY = createAndFillMVFolder( nameAY ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string tA_1 = "/A version #1"; + std::string tAX_1 = "/A/fX version #1"; + std::string tAY_1 = "/A/fY version #1"; + fAX->createTagRelation( tA_1, tAX_1 ); + fAY->createTagRelation( tA_1, tAY_1 ); + + // Lock a tag in /A/fY + fAY->setTagLockStatus( tAY_1, HvsTagLock::PARTIALLYLOCKED ); + + // Attempt to drop nodes + db->dropNode( nameAX ); + CPPUNIT_ASSERT_THROW( db->dropNode( nameAY ), TagIsLocked ); + CPPUNIT_ASSERT_THROW( db->dropNode( nameA ), Exception ); // not empty + + // Unlock all tags in /A/fY + fAY->setTagLockStatus( tAY_1, HvsTagLock::UNLOCKED ); + + // Lock a tag in /A + sA->setTagLockStatus( tA_1, HvsTagLock::PARTIALLYLOCKED ); + + // Attempt to drop nodes again + db->dropNode( nameAY ); + CPPUNIT_ASSERT_THROW( db->dropNode( nameA ), TagIsLocked ); + + // Unlock all tags in /A + sA->setTagLockStatus( tA_1, HvsTagLock::UNLOCKED ); + + // Attempt to drop nodes again + db->dropNode( nameA ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagPartiallyLocked_storeObjectWithUserTag() + { + + try { + + // Folder /fA + // - create A1 as child HVS tag (create relation) + // - create A1 as IOV user tag + // > attempt to use A1 as IOV head tag fails + IFolderPtr fA = createAndFillMVFolder( "/fA" ); + std::string prod = "PROD"; + std::string a1 = "A1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + fA->createTagRelation( prod, a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 0u, fA->countObjects(0,100,0,a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+a1, a1, fA->findTagRelation(prod) ); + Record payload = dummyPayload( 10 ); + fA->storeObject( 5, 15, payload, 0, a1 ); + try { + fA->tagCurrentHead( a1 ); + CPPUNIT_FAIL( "Using A1 as head tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 1u, fA->countObjects(0,100,0,a1) ); + + // - lock A1 user tag + // - delete A1 as child HVS tag (delete relation) + // - attempt to add another object to A1 user tag fails + // - attempt to delete A1 as IOV tag fails + fA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ); + fA->deleteTagRelation( prod ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 1u, fA->countObjects(0,100,0,a1) ); + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 14, 25, payload, 0, a1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW + ( fA->deleteTag( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 #", 1u, fA->countObjects(0,100,0,a1) ); + + // - unlock A1 user tag + // - attempt to add another object to A1 user tag succeeds + // - attempt to delete A1 as IOV tag succeeds + fA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + fA->storeObject( 15, 25, payload, 0, a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 #", 2u, fA->countObjects(0,100,0,a1) ); + fA->deleteTag( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_THROW( fA->countObjects(0,100,0,a1), TagNotFound ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + void test_tagPartiallyLocked_storeObjectWithUserTagNoOverlap() + { + + // Folder /fA + // - create A1 as child HVS tag (create relation) + // - create A1 as IOV user tag + std::string prod = "PROD"; + std::string a1 = "A1"; + IFolderPtr fA = db->createFolder + ( "/fA1martin", payloadSpec, "desc", FolderVersioning::MULTI_VERSION ); + + try + { + + Record payload = dummyPayload( 510 ); + // only store into user tag + fA->storeObject( 5, 10, payload, 0, a1, true ); + //coral::MsgLevel coralLevel = coral::MessageStream::msgVerbosity(); + //coral::MessageStream::setMsgVerbosity( coral::Verbose ); + fA->storeObject( 7, 20, dummyPayload(720), 0, a1, true ); + //coral::MessageStream::setMsgVerbosity( coralLevel ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Count objects ", 2u, + fA->countObjects(0,200,0, a1) ); + fA->storeObject(20, 30, dummyPayload(2030), 0, a1, true ); + // leave a hole from 30 to 40 + fA->storeObject(40, 50, dummyPayload(4050), 0, a1, true ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Count objects ", 4u, + fA->countObjects(0,200,0, a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, true, db->existsTag(a1) ); + + // - partially lock A1 user tag + // - attempt to add another object with overlapping IOVs + // to A1 user tag fails + // - attempt to add another object with no overlapping IOVs + // to A1 user tag succeeds + fA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + + // IOV covering all existing IOVs fails + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 0, 80, payload, 0, a1 ), TagIsLocked ); + + // since is one before the hole -> failure + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 29, 35, payload, 0, a1 ), TagIsLocked ); + // until one after the hole -> failure + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 30, 41, payload, 0, a1 ), TagIsLocked ); + // inside one IOV -> failure + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 15, 18, payload, 0, a1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 7, 15, payload, 0, a1 ), TagIsLocked ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 Count objects ", 4u, fA->countObjects(0,200,0, a1) ); + + // no overlap succeeds + // into the hole + fA->storeObject(30, 40, payload, 0, a1, true); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 Count objects ", 5u, fA->countObjects(0,200,0, a1) ); + // at the end + fA->storeObject(50, 60, dummyPayload(5060), 0, a1, true ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 Count objects ", 6u, fA->countObjects(0,200,0, a1) ); + // at the beginning + fA->storeObject( 0, 5, payload, 0, a1, true ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5 Count objects ", 7u, fA->countObjects(0,200,0, a1) ); + + // storing into head succeeds + fA->storeObject( 0, 40, dummyPayload(2), 0); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6 Count objects ", 1u, fA->countObjects(0,200,0) ); + + // store into user tag and head with overlaping head + fA->storeObject(65, 75, payload, 0); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ("7 Count objects ", 2u, fA->countObjects(0, 200, 0)); + fA->storeObject(60, 70, dummyPayload(3141), 0, a1, false); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ("8 Count objects ", 8u, fA->countObjects(0, 200, 0, a1)); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ("9 Count objects ", 3u, fA->countObjects(0, 200, 0)); + + // the same IOVs again fail now + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 30, 40, payload, 0, a1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 50, 60, payload, 0, a1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW + ( fA->storeObject( 0, 5, payload, 0, a1 ), TagIsLocked ); + + CPPUNIT_ASSERT_THROW( fA->deleteTag( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, true, db->existsTag(a1) ); + + // test bulk storage + fA->setupStorageBuffer( true ); + + // overlap of objects to store + fA->storeObject(90, 120, payload, 0, a1 ); + fA->storeObject(110, 130, payload, 0, a1 ); + fA->storeObject( 80, 90, payload, 0, a1 ); + + CPPUNIT_ASSERT_THROW( fA->flushStorageBuffer(), TagIsLocked); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "9 Count objects ", 8u, fA->countObjects(0,200,0, a1) ); + + // no overlap of objects to store + fA->storeObject(90, 120, payload, 0, a1 ); + fA->storeObject(120, 130, payload, 0, a1 ); + fA->storeObject( 80, 90, payload, 0, a1 ); + + fA->flushStorageBuffer(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "10 Count objects ", 11u, fA->countObjects(0,200,0, a1) ); + + fA->setupStorageBuffer( false ); + + // unlock tag + fA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + + // storing is again possible + fA->storeObject( 0, 80, payload, 0, a1 ); + fA->storeObject( 10, 11, payload, 0, a1 ); + fA->storeObject( 15, 18, payload, 0, a1 ); + fA->storeObject( 15, 25, payload, 0, a1 ); + + fA->deleteTag( a1 ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + fA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagPartiallyLocked_tagCurrentHead() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + + // - create X1 as IOV head tag + // > using X1 as IOV user tag fails + // - create X1 as HVS tag (create relation) + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + fAX->tagCurrentHead( x1 ); + Record payload = dummyPayload( 10 ); + try { + fAX->storeObject( 5, 15, payload, 0, x1 ); + CPPUNIT_FAIL( "Using X1 as user tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 3u, fAX->countObjects(0,100,0,x1) ); + fAX->createTagRelation( a1, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 3u, fAX->countObjects(0,100,0,x1) ); + + // - lock folder set A1 tag + // - lock folder X1 head tag + // - attempt to add another object to HEAD succeeds + // - attempt to delete X1 as IOV tag fails + // - attempt to retag the current HEAD fails + sA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ); + fAX->setTagLockStatus( x1, HvsTagLock::PARTIALLYLOCKED ); + fAX->storeObject( 5, 15, payload, 0 ); + CPPUNIT_ASSERT_THROW( fAX->deleteTag( x1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW( fAX->tagCurrentHead( x1 ), TagExists ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 3u, fAX->countObjects(0,100,0,x1) ); + + // - unlock folder X1 head tag + // - attempt to delete X1 as IOV tag succeeds + // > tag X1 still exists as HVS tag + // - attempt to retag the current HEAD succeeds + fAX->setTagLockStatus( x1, HvsTagLock::UNLOCKED ); + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 #", 0u, fAX->countObjects(0,100,0,x1) ); + fAX->tagCurrentHead( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 #", 4u, fAX->countObjects(0,100,0,x1) ); + + // - attempt to delete A1 as folder set tag fails + // - unlock folder set tag A1 + // - attempt to delete A1 as folder set tag succeeds + // - attempt to delete X1 as IOV tag succeeds + CPPUNIT_ASSERT_THROW( fAX->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+x1, true, db->existsTag(x1) ); + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + fAX->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+x1, true, db->existsTag(x1) ); + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 Exist "+x1, false, db->existsTag(x1) ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagPartiallyLocked_tagHeadAsOfDate() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + + // - create X1 as IOV date tag + // > using X1 as IOV user tag fails + // - create X1 as HVS tag (create relation) + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + Time date = fAX->findObject( 20, 0 )->insertionTime(); + fAX->tagHeadAsOfDate( date, x1 ); + Record payload = dummyPayload( 10 ); + try { + fAX->storeObject( 5, 15, payload, 0, x1 ); + CPPUNIT_FAIL( "Using X1 as user tag should fail" ); + } catch ( TagExists& ) {} + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 3u, fAX->countObjects(0,100,0,x1) ); + fAX->createTagRelation( a1, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 3u, fAX->countObjects(0,100,0,x1) ); + + // - lock folder set A1 tag + // - lock folder X1 head tag + // - attempt to add another object to HEAD succeeds + // - attempt to delete X1 as IOV tag fails + // - attempt to retag at new date fails + sA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ); + fAX->setTagLockStatus( x1, HvsTagLock::PARTIALLYLOCKED ); + fAX->storeObject( 5, 15, payload, 0 ); + date = fAX->findObject( 5, 0 )->insertionTime(); + CPPUNIT_ASSERT_THROW( fAX->deleteTag( x1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW + ( fAX->tagHeadAsOfDate( date, x1 ), TagExists ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 3u, fAX->countObjects(0,100,0,x1) ); + + // - unlock folder X1 head tag + // - attempt to delete X1 as IOV tag succeeds + // > tag X1 still exists as HVS tag + // - attempt to retag at new date succeeds + fAX->setTagLockStatus( x1, HvsTagLock::UNLOCKED ); + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 #", 0u, fAX->countObjects(0,100,0,x1) ); + fAX->tagHeadAsOfDate( date, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 #", 4u, fAX->countObjects(0,100,0,x1) ); + + // - attempt to delete A1 as folder set tag fails + // - unlock folder set tag A1 + // - attempt to delete A1 as folder set tag succeeds + // - attempt to delete X1 as IOV tag succeeds + CPPUNIT_ASSERT_THROW( fAX->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+x1, true, db->existsTag(x1) ); + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + fAX->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+x1, true, db->existsTag(x1) ); + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 Exist "+x1, false, db->existsTag(x1) ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagPartiallyLocked_deleteTag() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + std::string nameAY = "/A/fY"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + IFolderPtr fAY = createAndFillMVFolder( nameAY ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + std::string y1 = "/A/fY version #1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + // Create tag relations + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 0u, fAX->countObjects(0,100,0,x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Lock a tag in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::PARTIALLYLOCKED ); + + // Attempt to delete folder tags + // Note that actually these folder tags have no IOVs associated... even + // if deleteTag( x1 ) succceds, it actually does nothing because the + // relation to a1 still exists (hence do not attempt to recreate it!) + fAX->deleteTag( x1 ); + CPPUNIT_ASSERT_THROW( fAY->deleteTag( y1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 0u, fAX->countObjects(0,100,0,x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + + // Lock a tag in /A + sA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ); + + // Attempt to delete folder tags again + fAX->deleteTag( x1 ); + fAY->deleteTag( y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 0u, fAX->countObjects(0,100,0,x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + + // Delete all tag relations + fAX->deleteTagRelation( a1 ); + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + // Tag current HEAD in /A/fY + fAY->tagCurrentHead( y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 #", 3u, fAY->countObjects(0,100,0,y1) ); + + // Lock a tag in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::PARTIALLYLOCKED ); + + // Attempt to delete folder tags + // Note that actually these folder tags have no IOVs associated... even + // if deleteTag( x1 ) succceds, it actually does nothing because the + // relation to a1 still exists (hence do not attempt to recreate it!) + CPPUNIT_ASSERT_THROW( fAY->deleteTag( y1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 #", 3u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + + // Attempt to delete folder tags again + fAY->deleteTag( y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagPartiallyLocked_createTagRelation() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + std::string nameAY = "/A/fY"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + IFolderPtr fAY = createAndFillMVFolder( nameAY ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + std::string y1 = "/A/fY version #1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Create tag relations + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+y1, y1, fAY->findTagRelation(a1) ); + + // Delete tag relations + fAX->deleteTagRelation( a1 ); + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Lock a tag in /A/fY + // You must create the tag first (eg by tagCurrentHead) + fAY->tagCurrentHead( y1 ); + fAY->setTagLockStatus( y1, HvsTagLock::PARTIALLYLOCKED ); + + // Create tag relations + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+y1, y1, fAY->findTagRelation(a1) ); + + // Delete tag relations + fAX->deleteTagRelation( a1 ); + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Attempt to delete the /A/fY tag will fail + CPPUNIT_ASSERT_THROW( fAY->deleteTag(y1), TagIsLocked ); + + // Unlock all tags in /A/fY (and delete them) + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + fAY->deleteTag(y1); + + // Attempt to lock a tag in /A + // This will fail because the tag does not exist, i.e. has no associated + // child node tags (and note that it throws Exception, not TagNotFound) + CPPUNIT_ASSERT_THROW + ( sA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ), Exception ); + + // Create /A/fX tag relation - this will create the /A tag + fAX->createTagRelation( a1, x1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagRelationNotFound ); + + // Lock a tag in /A + sA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ); + + // Create tag relations + // Here LOCKED and PARTIALLYLOCKED behave differently! + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 - "+y1, y1, fAY->findTagRelation(a1) ); + + // Unlock all tags in /A + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_tagPartiallyLocked_deleteTagRelation() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + std::string nameAY = "/A/fY"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = createAndFillMVFolder( nameAX ); + IFolderPtr fAY = createAndFillMVFolder( nameAY ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + std::string y1 = "/A/fY version #1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Create tag relations + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 - "+y1, y1, fAY->findTagRelation(a1) ); + + // Lock a tag in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::PARTIALLYLOCKED ); + + // Attempt to delete tag relations + // Deleting the /A/fY tag relation fails because the child tag would + // be deleted and is locked (it would not fail if the child tag were + // locked but deleteTagRelation would not lead to deleting the tag) + fAX->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_THROW( fAY->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagRelationNotFound ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A/fY + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + + // Use tags in /A/fY for the current HEAD and lock them again + fAY->tagCurrentHead( y1 ); + fAY->setTagLockStatus( y1, HvsTagLock::PARTIALLYLOCKED ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagRelationNotFound ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 #", 3u, fAY->countObjects(0,100,0,y1) ); + + // Attempt to delete tag relations again + // Deleting the /A/fY tag relation does NOT fail even if the child tag is + // locked, because deleteTagRelation would not lead to deleting the tag + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 #", 3u, fAY->countObjects(0,100,0,y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + + // Unlock all tags in /A/fY (and delete them) + fAY->setTagLockStatus( y1, HvsTagLock::UNLOCKED ); + fAY->deleteTag( y1 ); + + // Create tag relations again + fAX->createTagRelation( a1, x1 ); + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 - "+y1, y1, fAY->findTagRelation(a1) ); + + // Lock a tag in /A + sA->setTagLockStatus( a1, HvsTagLock::PARTIALLYLOCKED ); + + // Attempt to delete tag relations - will fail as parent tag is locked + CPPUNIT_ASSERT_THROW( fAX->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_THROW( fAY->deleteTagRelation( a1 ), TagIsLocked ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+x1, true, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 - "+x1, x1, fAX->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 #", 0u, fAX->countObjects(0,100,0,x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 #", 0u, fAY->countObjects(0,100,0,y1) ); + + // Unlock all tags in /A + sA->setTagLockStatus( a1, HvsTagLock::UNLOCKED ); + + // Delete tag relations again + fAX->deleteTagRelation( a1 ); + fAY->deleteTagRelation( a1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + // Tests for the issues discussed in bug #22951 + void test_emptyTag() + { + + try { + + // Node hierarchy + // -> fldset / + // -> fldset /A + // -> folder /A/fX + // -> folder /A/fY + std::string nameA = "/A"; + std::string nameAX = "/A/fX"; + std::string nameAY = "/A/fY"; + IFolderSetPtr sA = db->createFolderSet( nameA ); + IFolderPtr fAX = db->createFolder + ( nameAX, payloadSpec, "desc", FolderVersioning::MULTI_VERSION ); + IFolderPtr fAY = createAndFillMVFolder( nameAY ); + + // Tag hierarchy for "/A version #1" + // -> fldset '/A version #1' + // -> folder '/A/fX version #1' + // -> folder '/A/fY version #1' + std::string a1 = "/A version #1"; + std::string x1 = "/A/fX version #1"; + std::string y1 = "/A/fY version #1"; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + // Attempt to tag current HEAD of /A/fX (with 0 objects) fails + CPPUNIT_ASSERT_THROW( fAX->tagCurrentHead(x1), Exception ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+a1, false, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist "+y1, false, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->findTagRelation(a1), TagNotFound ); + CPPUNIT_ASSERT_THROW( fAY->countObjects(0,100,0,y1), TagNotFound ); + + // Create a tag relation between /A and /A/fY + fAY->createTagRelation( a1, y1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+a1, true, db->existsTag(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+x1, false, db->existsTag(x1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist "+y1, true, db->existsTag(y1) ); + CPPUNIT_ASSERT_THROW( fAX->findTagRelation(a1), TagRelationNotFound ); + CPPUNIT_ASSERT_THROW( fAX->countObjects(0,100,0,x1), TagNotFound ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 - "+y1, y1, fAY->findTagRelation(a1) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 #", 0u, fAY->countObjects(0,100,0,y1) ); + + } + + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + IFolderPtr createAndFillMVFolder( const std::string& folderName ) + { + IFolderPtr folder = db->createFolder + ( folderName, payloadSpec, "desc", FolderVersioning::MULTI_VERSION ); + for ( int i = 0; i < 3; ++i ) { + ValidityKey since = i*10; + ValidityKey until = ValidityKeyMax; + Record payload = dummyPayload( i ); + folder->storeObject( since, until, payload, 0 ); + } + return folder; + } + + IFolderPtr createAndFillSVFolder( const std::string& folderName ) + { + IFolderPtr folder = db->createFolder + ( folderName, payloadSpec, "desc", FolderVersioning::SINGLE_VERSION ); + for ( int i = 0; i < 3; ++i ) { + ValidityKey since = i*10; + ValidityKey until = ValidityKeyMax; + Record payload = dummyPayload( i ); + folder->storeObject( since, until, payload, 0 ); + } + return folder; + } + + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + HvsTagTest() + : payloadSpec() + { + payloadSpec.extend("I",StorageType::Int32); + payloadSpec.extend("S",StorageType::String255); + payloadSpec.extend("X",StorageType::Float); + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + std::cout + << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << std::endl; + std::cout + << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << std::endl; + std::cout << "Aborting test" << std::endl; + exit(-1); + } + } + + ~HvsTagTest() {} + + void setUp() + { + try + { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + } + catch ( std::exception& e ) + { + std::cout << e.what() << std::endl; + throw; + } + } + + void tearDown() + { + db.reset(); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( cool::HvsTagTest ); + +//----------------------------------------------------------------------------- + +// Include CppUnit test driver +#include <CppUnit_testdriver.icpp> + diff --git a/RelationalCool/tests/Int64IO/Int64InputOutput.cpp b/RelationalCool/tests/Int64IO/Int64InputOutput.cpp new file mode 100755 index 000000000..a143612f4 --- /dev/null +++ b/RelationalCool/tests/Int64IO/Int64InputOutput.cpp @@ -0,0 +1,275 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +#include <iostream> +#include <stdexcept> +#include <memory> +#include "RelationalAccess/RelationalException.h" +#include "RelationalAccess/IRelationalService.h" +#include "RelationalAccess/IRelationalDomain.h" +#include "RelationalAccess/IRelationalSession.h" +#include "RelationalAccess/IRelationalTransaction.h" +#include "RelationalAccess/IRelationalSchema.h" +#include "RelationalAccess/IRelationalTable.h" +#include "RelationalAccess/IRelationalQuery.h" +#include "RelationalAccess/IRelationalCursor.h" +#include "RelationalAccess/RelationalEditableTableDescription.h" +#include "RelationalAccess/IRelationalTableDataEditor.h" +#include "RelationalAccess/IRelationalTypeConverter.h" +#include "AttributeList/AttributeList.h" +#include "POOLCore/POOLContext.h" +#include "SealKernel/Context.h" +#include "SealBase/IntBits.h" +// Max and Min in SealBase/IntTraits.h are broken on Win32 +//#include "SealBase/IntTraits.h" +#include "CoolKernel/types.h" +#include "src/sleep.h" + +static const int nbits = 63; + +int main( int, char** ) +{ + try { + pool::POOLContext::loadComponent( "SEAL/Services/MessageService" ); + pool::POOLContext::loadComponent( "POOL/Services/XMLAuthenticationService" ); + pool::POOLContext::loadComponent( "POOL/Services/RelationalService" ); + pool::POOLContext::setMessageVerbosityLevel( seal::Msg::Debug ); + seal::MessageStream log( pool::POOLContext::context(), "TableDataEditor_Test" ); + seal::IHandle<pool::IRelationalService> serviceHandle = pool::POOLContext::context()->query<pool::IRelationalService>( "POOL/Services/RelationalService" ); + if ( ! serviceHandle ) { + throw std::runtime_error( "Could not retrieve the relational service" ); + } + + std::string connectionString = "oracle://devdb10/lcg_cool"; + pool::IRelationalDomain& domain = serviceHandle->domainForConnection( connectionString ); + + // Creating a session + std::auto_ptr< pool::IRelationalSession > session( domain.newSession( connectionString ) ); + + // Establish a connection with the server + std::cout << "Connecting..." << std::endl; + if ( ! session->connect() ) { + throw std::runtime_error( "Could not connect to the database server." ); + } + + // Start a transaction + std::cout << "Starting a new transaction" << std::endl; + if ( ! session->transaction().start() ) { + throw std::runtime_error( "Could not start a new transaction." ); + } + + // Dropping the old table + session->userSchema().dropIfExistsTable( "DATATABLE64" ); + + // Creating the description for the table + std::auto_ptr< pool::IRelationalEditableTableDescription > description( new pool::RelationalAccess::RelationalEditableTableDescription( log, + domain.flavorName() ) ); + std::cout << "Defining a column of type " << pool::AttributeStaticTypeInfo<int>::type_name() << std::endl; + description->insertColumn( "ID", pool::AttributeStaticTypeInfo<int>::type_name() ); + std::cout << "Defining a column of type " << pool::AttributeStaticTypeInfo<seal::IntBits<64>::ULeast>::type_name() << std::endl; + description->insertColumn( "U64", pool::AttributeStaticTypeInfo<seal::IntBits<64>::ULeast>::type_name() ); + description->insertColumn( "S64", pool::AttributeStaticTypeInfo<seal::IntBits<64>::SLeast>::type_name() ); + + /* + // CHANGE THE RAL DEFAULT TO TRY TO AVOID THE SEGMENTATION FAULT + // But it is not enough... + if ( ! session->typeConverter().setSqlTypeForCppType + ( "NUMBER(20)", "unsigned long long" ) ) + throw std::runtime_error( "Could not change the u long long SQL type" ); + if ( ! session->typeConverter().setSqlTypeForCppType + ( "NUMBER(20)", "long long" ) ) + throw std::runtime_error( "Could not change the long long SQL type" ); + */ + + // Create the first table. + std::cout << "Creating table \"DATATABLE64\"" << std::endl; + pool::IRelationalTable& table = session->userSchema().createTable( "DATATABLE64", *description ); + + std::cout << "About to insert new rows" << std::endl; + + // Costructing a row buffer. + pool::AttributeListSpecification specForData; + specForData.push_back< int >( "ID" ); + specForData.push_back< seal::IntBits<64>::ULeast >( "U64" ); + specForData.push_back< seal::IntBits<64>::SLeast >( "S64" ); + + pool::AttributeList data( specForData ); + + // Retrieving the editor object. + pool::IRelationalTableDataEditor& dataEditor = table.dataEditor(); + + // Adding new rows + std::cout << "Adding five rows into the table" << std::endl; + data["ID"].setValue<int>( 1 ); + data["U64"].setValue<seal::IntBits<64>::ULeast>( 10 ); + data["S64"].setValue<seal::IntBits<64>::SLeast> + ( cool::sInt64Min + 1 ); // OK! + //( seal::sInt64Min ); // OCI-22053 + std::cout << "Adding row: "; + data.print( std::cout ); + std::cout << std::endl; + + if ( ! dataEditor.insertNewRow( data ) ) { + throw std::runtime_error( "Could not insert a new row into the table." ); + } + + data["ID"].setValue<int>( 2 ); + seal::IntBits<64>::ULeast udata = 1; + udata <<= nbits; + data["U64"].setValue<seal::IntBits<64>::ULeast>( udata ); + data["S64"].setValue<seal::IntBits<64>::SLeast> + ( cool::sInt64Max ); + + std::cout << "Adding row: "; + data.print( std::cout ); + std::cout << std::endl; + + if ( ! dataEditor.insertNewRow( data ) ) { + throw std::runtime_error( "Could not insert a new row into the table." ); + } + + // Committing the transaction + std::cout << "Committing..." << std::endl; + if ( ! session->transaction().commit() ) { + throw std::runtime_error( "Could not commit the transaction." ); + } + + // Disconnecting + std::cout << "Disconnecting..." << std::endl; + session->disconnect(); + + cool::sleep(1); + + // Performing a query... + // Establish a connection with the server + std::cout << "Re-connecting..." << std::endl; + if ( ! session->connect() ) { + throw std::runtime_error( "Could not connect to the database server." ); + } + + // Start a transaction + std::cout << "Starting a read-only transaction" << std::endl; + if ( ! session->transaction().start( true ) ) { + throw std::runtime_error( "Could not start a new transaction." ); + } + + std::auto_ptr<pool::IRelationalQuery> query( session->userSchema().tableHandle( "DATATABLE64" ).createQuery() ); + query->addToOutputList( "ID" ); + query->addToOutputList( "U64" ); + query->addToOutputList( "S64" ); + query->addToOrderList( "ID" ); + query->defineOutput( specForData ); + pool::IRelationalCursor& cursor = query->process(); + if ( ! cursor.start() ) throw std::runtime_error( "Could not start the iteration over the result set" ); + int numberOfRows = 0; + while ( cursor.next() ) { + std::cout << "Read back : "; + cursor.currentRow().print( std::cout ); + std::cout << std::endl; + + pool::AttributeList::const_iterator iData = cursor.currentRow().begin(); + + int id = 0; + iData->getValue<int>( id ); + if ( id != numberOfRows + 1 ) throw std::runtime_error( "Unexpected data for id" ); + + ++iData; + seal::IntBits<64>::ULeast udata = 0; + iData->getValue<seal::IntBits<64>::ULeast>( udata ); + + seal::IntBits<64>::ULeast refdata = 1; + if ( id == 1 ) refdata = 10; + else refdata <<= nbits; + if ( udata != refdata ) throw std::runtime_error( "Unexpected data for u64" ); + + numberOfRows++; + } + if ( numberOfRows != 2 ) throw std::runtime_error( "Number of rows received different than those expected" ); + + + // Committing the transaction + std::cout << "Committing..." << std::endl; + if ( ! session->transaction().commit() ) { + throw std::runtime_error( "Could not commit the transaction." ); + } + + // AV - START - March 2005 - test the numeric values + // Update the data + std::cout << "Starting a read-write transaction" << std::endl; + if ( ! session->transaction().start( false ) ) { + throw std::runtime_error( "Could not start a new transaction." ); + } + pool::AttributeListSpecification dummySpec; + pool::AttributeList dummyList( dummySpec ); + std::cout << "Update both rows: set U64 = U64 - 1" << std::endl; + long updatedRows = session->userSchema().tableHandle( "DATATABLE64" ) + .dataEditor().updateRows( "U64=U64-1", "", dummyList ); + std::cout << "Updated " << updatedRows << " rows" << std::endl; + std::cout << "Committing..." << std::endl; + if ( ! session->transaction().commit() ) { + throw std::runtime_error( "Could not commit the transaction." ); + } + + // Read back updated data + std::cout << "Starting a read-only transaction" << std::endl; + if ( ! session->transaction().start( true ) ) { + throw std::runtime_error( "Could not start a new transaction." ); + } + std::auto_ptr<pool::IRelationalQuery> query1( session->userSchema().tableHandle( "DATATABLE64" ).createQuery() ); + query1->addToOutputList( "ID" ); + query1->addToOutputList( "U64" ); + query1->addToOutputList( "S64" ); + query1->addToOrderList( "ID" ); + query1->defineOutput( specForData ); + pool::IRelationalCursor& cursor1 = query1->process(); + if ( ! cursor1.start() ) throw std::runtime_error( "Could not start the iteration over the result set" ); + int numberOfRows1 = 0; + while ( cursor1.next() ) { + std::cout << "Read back : "; + cursor1.currentRow().print( std::cout ); + std::cout << std::endl; + pool::AttributeList::const_iterator iData = cursor1.currentRow().begin(); + int id = 0; + iData->getValue<int>( id ); + if ( id != numberOfRows1 + 1 ) throw std::runtime_error( "Unexpected data for id" ); + ++iData; + seal::IntBits<64>::ULeast udata = 0; + iData->getValue<seal::IntBits<64>::ULeast>( udata ); + seal::IntBits<64>::ULeast refdata = 1; + if ( id == 1 ) refdata = 9; + else { refdata <<= nbits; refdata--; } + if ( udata != refdata ) throw std::runtime_error( "Unexpected data for u64" ); + numberOfRows1++; + } + if ( numberOfRows1 != 2 ) throw std::runtime_error( "Number of rows received different than those expected" ); + std::cout << "Committing..." << std::endl; + if ( ! session->transaction().commit() ) { + throw std::runtime_error( "Could not commit the transaction." ); + } + // AV - END - March 2005 + + // Disconnecting + std::cout << "Disconnecting..." << std::endl; + session->disconnect(); + + + std::cout << "Exiting..." << std::endl; + } + catch ( pool::RelationalException& re ) { + std::cerr << "Relational exception from module " << re.flavorName() << std::endl + << " " << re.what() << std::endl; + return 1; + } + catch ( std::exception& e ) { + std::cerr << "Standard C++ exception : " << e.what() << std::endl; + return 1; + } + catch ( ... ) { + std::cerr << "Exception caught (...)" << std::endl; + return 1; + } + return 0; +} + +#endif // NOPORT diff --git a/RelationalCool/tests/Int64IO/Int64InputOutput.txt b/RelationalCool/tests/Int64IO/Int64InputOutput.txt new file mode 100644 index 000000000..49069d0b2 --- /dev/null +++ b/RelationalCool/tests/Int64IO/Int64InputOutput.txt @@ -0,0 +1,43 @@ +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +Connecting... +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +Starting a new transaction +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'CONDDB_TEST'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "CONDDB_TEST"."DATATABLE64"" +Defining a column of type int +Defining a column of type unsigned long long +Creating table "DATATABLE64" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "CONDDB_TEST"."DATATABLE64" ( "ID" NUMBER(10), "U64" NUMBER, "S64" NUMBER )" +About to insert new rows +Adding five rows into the table +Adding row: attribute list: size = 3 [ 1 as ID:int, 10 as U64:unsigned long long, -9223372036854775807 as S64:long long ] +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "CONDDB_TEST"."DATATABLE64" ("ID","U64","S64") VALUES (:"ID",:"U64",:"S64")" +Adding row: attribute list: size = 3 [ 2 as ID:int, 9223372036854775808 as U64:unsigned long long, 9223372036854775807 as S64:long long ] +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "CONDDB_TEST"."DATATABLE64" ("ID","U64","S64") VALUES (:"ID",:"U64",:"S64")" +Committing... +Disconnecting... +Re-connecting... +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +Starting a read-only transaction +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'CONDDB_TEST'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "ID", "U64", "S64" FROM "CONDDB_TEST"."DATATABLE64" ORDER BY "ID"" +Read back : attribute list: size = 3 [ 1 as ID:int, 10 as U64:unsigned long long, -9223372036854775807 as S64:long long ] +Read back : attribute list: size = 3 [ 2 as ID:int, 9223372036854775808 as U64:unsigned long long, 9223372036854775807 as S64:long long ] +Committing... +Starting a read-write transaction +Update both rows: set U64 = U64 - 1 +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "CONDDB_TEST"."DATATABLE64" SET "U64"="U64"-1" +Updated 2 rows +Committing... +Starting a read-only transaction +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "ID", "U64", "S64" FROM "CONDDB_TEST"."DATATABLE64" ORDER BY "ID"" +Read back : attribute list: size = 3 [ 1 as ID:int, 9 as U64:unsigned long long, -9223372036854775807 as S64:long long ] +Read back : attribute list: size = 3 [ 2 as ID:int, 9223372036854775807 as U64:unsigned long long, 9223372036854775807 as S64:long long ] +Committing... +Disconnecting... +Exiting... diff --git a/RelationalCool/tests/MemoryConsumption/execTest.sh b/RelationalCool/tests/MemoryConsumption/execTest.sh new file mode 100755 index 000000000..898343c22 --- /dev/null +++ b/RelationalCool/tests/MemoryConsumption/execTest.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +test=unitTest_RelationalCool_MemoryConsumption +# call $test without arguments to get the tests +tests=`$test` +outdir=/tmp/$USER +outfile=$outdir/COOLTEST.db +mkdir -p $outdir +export COOLTESTDB="sqlite://none;schema=$outfile;dbname=COOLTEST" + +echo `date` +echo Connection: $COOLTESTDB +\rm -f $outfile + +export POOL_OUTMSG_LEVEL="E" + +\rm -f $test.out.$SCRAM_ARCH + +for t in $tests; do + # Run the tests inside the unit test suite in isolation and append + # the results to the output file. + # We run the tests in isolation, because otherwise not all memory + # leaks are visible. + $test $t | tee -a $test.out.$SCRAM_ARCH 2>&1 +done diff --git a/RelationalCool/tests/MemoryConsumption/test_MemoryConsumption.cpp b/RelationalCool/tests/MemoryConsumption/test_MemoryConsumption.cpp new file mode 100755 index 000000000..001b95991 --- /dev/null +++ b/RelationalCool/tests/MemoryConsumption/test_MemoryConsumption.cpp @@ -0,0 +1,729 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +/** + +@file test_MemoryConsumption.cpp + +@author Sven A. Schmidt + +@date 2005-09-15 + +*/ + + +#include<cppunit/extensions/HelperMacros.h> +#include <cppunit/TestSuite.h> + +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/Exception.h" +#include "CoolKernel/ChannelSelection.h" + +#include "SealUtil/SealTimer.h" +#include "SealUtil/TimingItem.h" + +// we need some of the private header for the low level tests +#include "src/CoralApplication.h" +#include "src/RalDatabase.h" +#include "src/RelationalTransaction.h" +#include "src/RelationalFolder.h" +#include "src/ProcMemory.h" +#include "src/RelationalObjectTable.h" +#include "src/TimingReport.h" +#include "src/RalObjectTable.h" + +#include "RelationalAccess/IRelationalTable.h" +#include "RelationalAccess/IRelationalQuery.h" +#include "RelationalAccess/IRelationalCursor.h" +#include "RelationalAccess/IRelationalSchema.h" + +#include "AttributeList/AttributeValueAccessor.h" +using pool::AttributeList; +using pool::AttributeListSpecification; +typedef boost::shared_ptr<AttributeListSpecification> SpecPtr; + +#include <string> +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +#include <vector> +using std::vector; + +namespace cool { + +const char* COOLTESTDB = "COOLTESTDB"; + +/// MemoryConsumption test class +/// +/// NB: To get reliable results, run these tests in isolation! +/// A memory leak will most likely not be visible if the leak +/// does not increase the total memory requirement of the process +/// beyond what the process has already requested (especially if +/// there's already been a leak in a previous test and the process +/// can't even free that memory). +/// +class MemoryConsumptionTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( MemoryConsumptionTest ); + + CPPUNIT_TEST( test_seal_TimingItem ); + + CPPUNIT_TEST( test_AttributeListSpecification ); + CPPUNIT_TEST( test_AttributeList ); + + CPPUNIT_TEST( test_storeObject_bulk ); + CPPUNIT_TEST( test_browseObjects ); + + CPPUNIT_TEST( test_fetchRowsSV ); + CPPUNIT_TEST( test_fetchRowsSV_detail ); + + CPPUNIT_TEST( test_RelationalObjectTableRow ); + CPPUNIT_TEST( test_RelationalObjectTableRow_vector ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + AttributeListSpecification mixedPayloadSpec; + string connectString; + IDatabasePtr db; + + //------------------------------------------------------------------------ + + void test_seal_TimingItem() { + ProcMemory mem; + std::cout << "\nStart test_seal_TimingItem "; + mem.printVm(); + + int nObjs = 10 * 1000; + + for ( int i = 0; i < nObjs; ++i ) { + cool::TimingReport timeReport; + seal::TimingItem& timeItem = timeReport.item("timeReport item"); + + if ( i % 1000 == 0 ) { + cout << "object # " << i << "\t"; + mem.printVm(); + } + + // silence the comiler... + timeItem.accumulate(); + } + + std::cout << "End "; + mem.printVm(); + } + + //------------------------------------------------------------------------ + + /// Tests memory consumption of a vector of RelationalObjectTableRow objects + void test_RelationalObjectTableRow_vector() { + + ProcMemory mem; + std::cout << "\nStart test_RelationalObjectTableRow_vector "; + mem.printVm(); + + RalDatabase* ralDb = dynamic_cast<RalDatabase*>(db.get()); + + boost::shared_ptr<pool::AttributeListSpecification> + spec = ralDb->attrListSpecToAttrListSpecPtr( mixedPayloadSpec ); + pool::AttributeList payload = mixedPayload( 0 ); + + + int nObjs = 10 * 1000; + + for ( int i = 0; i < nObjs; ++i ) { + vector<RelationalObjectTableRow> rows; + for ( int j = 0; j < 10; ++j ) { + RelationalObjectTableRow row( payload, spec ); + rows.push_back( row ); + } + + if ( i % 1000 == 0 ) { + cout << "object # " << i << "\t"; + mem.printVm(); + } + } + + std::cout << "End "; + mem.printVm(); + } + + //------------------------------------------------------------------------ + + /// Tests memory consumption of RelationalObjectTableRow objects + void test_RelationalObjectTableRow() { + + ProcMemory mem; + std::cout << "\nStart test_RelationalObjectTableRow "; + mem.printVm(); + + RalDatabase* ralDb = dynamic_cast<RalDatabase*>(db.get()); + + boost::shared_ptr<pool::AttributeListSpecification> + spec = ralDb->attrListSpecToAttrListSpecPtr( mixedPayloadSpec ); + pool::AttributeList payload = mixedPayload( 0 ); + + + int nObjs = 100 * 1000; + + for ( int i = 0; i < nObjs; ++i ) { + RelationalObjectTableRow row( payload, spec ); + + if ( i % 10000 == 0 ) { + cout << "object # " << i << "\t"; + mem.printVm(); + } + } + + std::cout << "End "; + mem.printVm(); + } + + //------------------------------------------------------------------------ + + //---------------------------------------------------------------------- + // The following is a (trimmed to essentials) copy of + // RalObjectTable::fetchRowsSV + //---------------------------------------------------------------------- + + vector<RelationalObjectTableRow> + fetch( const std::string& objectTableName, + const pool::AttributeListSpecification& payloadSpec, + const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels ) { + + RalDatabase* ralDb = dynamic_cast<RalDatabase*>(db.get()); + + // Prepare the result vector + std::vector<RelationalObjectTableRow> rset; + { + + // Create a query on the IOV table + pool::IRelationalTable& objectTable = + ralDb->session().userSchema().tableHandle( objectTableName ); + std::auto_ptr<pool::IRelationalQuery> query( objectTable.createQuery() ); + + // Add all table columns to the output list and define the output format + boost::shared_ptr<pool::AttributeListSpecification> objectTableSpec = + RelationalObjectTable::tableSpecification( payloadSpec ); + pool::AttributeListSpecification::const_iterator iColumn; + for ( iColumn = objectTableSpec->begin(); + iColumn != objectTableSpec->end(); + iColumn++ ) { + query->addToOutputList( iColumn->name() ); + } + query->defineOutput( *objectTableSpec ); + + // Define the WHERE clause for the selection using bind variables + pool::AttributeListSpecification whereSpec; + // Only specify a channel selection if *not* all channels are selected + if ( ! channels.allChannels() ) { + if ( channels.firstChannel() == channels.lastChannel() ) { + whereSpec.push_back( "channel", + RelationalObjectTable::columnTypes::channelId() ); + } else { + whereSpec.push_back( "firstChannel", + RelationalObjectTable::columnTypes::channelId() ); + whereSpec.push_back( "lastChannel", + RelationalObjectTable::columnTypes::channelId() ); + } + } + whereSpec.push_back( "since1", + RelationalObjectTable::columnTypes::iovSince() ); + whereSpec.push_back( "since2", + RelationalObjectTable::columnTypes::iovSince() ); + whereSpec.push_back( "since3", + RelationalObjectTable::columnTypes::iovSince() ); + whereSpec.push_back( "until", + RelationalObjectTable::columnTypes::iovUntil() ); + pool::AttributeList whereData( whereSpec ); + // Only specify a channel selection if *not* all channels are selected + if ( ! channels.allChannels() ) { + if ( channels.firstChannel() == channels.lastChannel() ) { + whereData["channel"].setValue( channels.firstChannel() ); + } else { + whereData["firstChannel"].setValue( channels.firstChannel() ); + whereData["lastChannel"].setValue( channels.lastChannel() ); + } + } + whereData["since1"].setValue( since ); + whereData["since2"].setValue( since ); + whereData["since3"].setValue( since ); + whereData["until"].setValue( until ); + + std::string whereClause; + // Only provide a channel selection clause if *not* all channels + // are selected in 'channels' + if ( ! channels.allChannels() ) { + // Tailor the where clause to the actual range + if ( channels.firstChannel() == channels.lastChannel() ) { + whereClause += RelationalObjectTable::columnNames::channelId(); + whereClause += "= :channel"; + } else { + whereClause = ":firstChannel <= "; + whereClause += RelationalObjectTable::columnNames::channelId(); + whereClause += " and "; + whereClause += RelationalObjectTable::columnNames::channelId(); + whereClause += " <= :lastChannel"; + } + whereClause += " AND "; + } + + std::string s = RelationalObjectTable::columnNames::iovSince(); + std::string u = RelationalObjectTable::columnNames::iovUntil(); + + // Also see SimpleObject::overlaps for this clause + // but note that the upper end is *included* (<= :until) + whereClause += "("; + whereClause += " ( ( " + s + " <= :since1 )"; + whereClause += " AND ( :since2 < " + u + " ) )"; + whereClause += " OR "; + whereClause += " ( ( :since3 <= " + s + " )"; + whereClause += " AND ( " + s + " <= :until ) )"; + whereClause += ")"; + + query->setCondition( whereClause, whereData ); + + if ( channels.firstChannel() == channels.lastChannel() ) { + // Only one channel, skip 'channelId' in order clause + query->addToOrderList + ( RelationalObjectTable::columnNames::iovSince() + " ASC" ); + } else { + if ( channels.order() == ChannelSelection::channelBeforeSince ) { + query->addToOrderList + ( RelationalObjectTable::columnNames::channelId() + " ASC" ); + query->addToOrderList + ( RelationalObjectTable::columnNames::iovSince() + " ASC" ); + } else { + query->addToOrderList + ( RelationalObjectTable::columnNames::iovSince() + " ASC" ); + query->addToOrderList + ( RelationalObjectTable::columnNames::channelId() + " ASC" ); + } + } + + // Set the row cache size + long newRowCacheSize = 100; + query->setRowCacheSize( newRowCacheSize ); + + // Retrieve a cursor over the result set + pool::IRelationalCursor& cursor = query->process(); + if ( ! cursor.start() ) + throw RelationalException + ( "Could not start cursor loop", "RalDatabase" ); + + while ( cursor.next() ) { + RelationalObjectTableRow row( cursor.currentRow(), objectTableSpec ); + rset.push_back( row ); + } + } + + return rset; + } + + + + /// Tests memory consumption of fetchRowsSV + void test_fetchRowsSV_detail() { + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + + int index = 0; + for ( int i = 0; i < 3; ++i ) { + folder->storeObject( 0, 10, mixedPayload( index++ ), (ChannelId)i ); + folder->storeObject( 10, 20, mixedPayload( index++ ), (ChannelId)i ); + folder->storeObject( 20, ValidityKeyMax, + mixedPayload( index++ ), (ChannelId)i ); + } + + RalDatabase* ralDb = dynamic_cast<RalDatabase*>(db.get()); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + ProcMemory mem; + std::cout << "\nStart test_fetchObjectTableRowsSV_detail "; + mem.printVm(); + + int nObjs = 3 * 1000; + + for ( int i = 0; i < nObjs; ++i ) { + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + std::vector<RelationalObjectTableRow> rows + = fetch( relfolder->objectTableName(), + relfolder->payloadSpecification(), + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all() ); + + if ( i % 1000 == 0 ) { + cout << "object # " << i << "\t"; + mem.printVm(); + } + } + + std::cout << "End "; + mem.printVm(); + + } + + //------------------------------------------------------------------------ + + /// Tests memory consumption of fetchRowsSV + void test_fetchRowsSV() { + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + + int index = 0; + for ( int i = 0; i < 3; ++i ) { + folder->storeObject( 0, 10, mixedPayload( index++ ), (ChannelId)i ); + folder->storeObject( 10, 20, mixedPayload( index++ ), (ChannelId)i ); + folder->storeObject( 20, ValidityKeyMax, + mixedPayload( index++ ), (ChannelId)i ); + } + + RalDatabase* ralDb = dynamic_cast<RalDatabase*>(db.get()); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + RalObjectTable objectTable( ralDb->ralDbPtr(), *relfolder ); + + ProcMemory mem; + std::cout << "\nStart test_fetchObjectTableRowsSV "; + mem.printVm(); + + int nObjs = 3 * 1000; + + for ( int i = 0; i < nObjs; ++i ) { + RelationalTransaction transaction( ralDb->transactionMgr() ); + + std::vector<RelationalObjectTableRow> rows = + objectTable.fetchRowsSV( relfolder->payloadSpecification(), + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all() ); + if ( i % 1000 == 0 ) { + cout << "object # " << i << "\t"; + mem.printVm(); + } + } + + std::cout << "End "; + mem.printVm(); + + } + + //------------------------------------------------------------------------ + + /// Tests memory consumption of browseObjects + void test_browseObjects() { + IFolderPtr folder = db->createFolder( "/myfolder", + mixedPayloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + + int index = 0; + for ( int i = 0; i < 3; ++i ) { + folder->storeObject( 0, 10, mixedPayload( index++ ), (ChannelId)i ); + folder->storeObject( 10, 20, mixedPayload( index++ ), (ChannelId)i ); + folder->storeObject( 20, ValidityKeyMax, + mixedPayload( index++ ), (ChannelId)i ); + } + + ProcMemory mem; + std::cout << "\nStart test_browseObjects "; + mem.printVm(); + + int nObjs = 10 * 1000; + + for ( int i = 0; i < nObjs; ++i ) + { + ValidityKey since = 5; + ValidityKey until = 15; + IObjectIteratorPtr + objs = folder->browseObjects( since, until, + ChannelSelection::all() ); + if ( i % 1000 == 0 ) { + cout << "object # " << i << "\t"; + mem.printVm(); + } + } + + std::cout << "End "; + mem.printVm(); + + } + + //------------------------------------------------------------------------ + + /// Tests memory consumption of bulk storeObjects + void test_storeObject_bulk() { + + ProcMemory mem; + std::cout << "\nStart test_storeObject_bulk "; + mem.printVm(); + + long nObjs = 50 * 1000; + + { + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, mixedPayload( i ) ); + if ( i % 10000 == 0 ) { + cout << "object # " << i << "\t"; + mem.printVm(); + folder->flushStorageBuffer(); + } + } + + std::cout << "Before flushing "; + mem.printVm(); + + folder->flushStorageBuffer(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** wrote " << nObjs << " objects (150 bytes mixed) **" << endl; + } + + std::cout << "End "; + mem.printVm(); + + } + + //------------------------------------------------------------------------ + + void test_AttributeList() { + pool::AttributeListSpecification spec; + spec.push_back("I","int"); + + ProcMemory mem; + std::cout << "\nStart test_AttributeList "; + mem.printVm(); + + long nObjs = 1*1000*1000; + for ( long i = 0; i < nObjs; ++i ) { + if ( i % 100000 == 0 ) { + std::cout << "object " << i << "\t"; + mem.printVm(); + } + pool::AttributeList list( spec ); + } + } + + //------------------------------------------------------------------------ + + void test_AttributeListSpecification() { + ProcMemory mem; + std::cout << "\nStart test_AttributeListSpecification "; + mem.printVm(); + + long nObjs = 1*1000*1000; + for ( long i = 0; i < nObjs; ++i ) { + if ( i % 100000 == 0 ) { + std::cout << "object " << i << "\t"; + mem.printVm(); + } + pool::AttributeListSpecification spec; + spec.push_back("I","int"); + } + } + + //------------------------------------------------------------------------ + + /// Creates a dummy payload AttributeList for a given index + AttributeList mixedPayload( int index ) { + AttributeList payload( mixedPayloadSpec ); + payload["I"].setValue<int>( index ); + stringstream s; + s << "Object " << index; + payload["S"].setValue<string>( s.str() ); + payload["X0"].setValue<float>( (float)(index/1000.) ); + payload["X1"].setValue<float>( (float)(index/1000.) ); + payload["X2"].setValue<float>( (float)(index/1000.) ); + payload["X3"].setValue<float>( (float)(index/1000.) ); + payload["X4"].setValue<float>( (float)(index/1000.) ); + payload["X5"].setValue<float>( (float)(index/1000.) ); + payload["X6"].setValue<float>( (float)(index/1000.) ); + payload["X7"].setValue<float>( (float)(index/1000.) ); + payload["X8"].setValue<float>( (float)(index/1000.) ); + payload["X9"].setValue<float>( (float)(index/1000.) ); + payload["P"].setValue<string>( "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + ); + return payload; + } + + + /// Creates a uniform payload specification for nFields fields + SpecPtr uniformSpec( int nFields, const string & type ) { + SpecPtr spec( new AttributeListSpecification() ); + for ( int i = 0; i < nFields; ++i ) { + stringstream s; + s << "X" << i; + spec->push_back( s.str(), type ); + } + return spec; + } + + + /// Creates a dummy 4kB string AttributeList + AttributeList string4kbPayload( SpecPtr & spec ) { + stringstream payloadString; + int bytes = 4000; + for ( int i = 0; i < bytes; ++i ) payloadString << "a"; + + int nFields = spec->size(); + AttributeList payload( spec ); + for ( int i = 0; i < nFields; ++i ) { + stringstream s; + s << "X" << i; + payload[ s.str() ].setValue<string>( payloadString.str() ); + } + return payload; + } + + + /// Creates a dummy float AttributeList for a given index + AttributeList floatPayload( int index, SpecPtr & spec ) { + int nFields = spec->size(); + AttributeList payload( spec ); + for ( int i = 0; i < nFields; ++i ) { + stringstream s; + s << "X" << i; + payload[ s.str() ].setValue<float>( (float)(index/1000.) ); + } + return payload; + } + + + void setUp() { + if ( mixedPayloadSpec.size() == 0 ) { + mixedPayloadSpec.push_back("I","int"); + mixedPayloadSpec.push_back("S","string"); + mixedPayloadSpec.push_back("X0","float"); + mixedPayloadSpec.push_back("X1","float"); + mixedPayloadSpec.push_back("X2","float"); + mixedPayloadSpec.push_back("X3","float"); + mixedPayloadSpec.push_back("X4","float"); + mixedPayloadSpec.push_back("X5","float"); + mixedPayloadSpec.push_back("X6","float"); + mixedPayloadSpec.push_back("X7","float"); + mixedPayloadSpec.push_back("X8","float"); + mixedPayloadSpec.push_back("X9","float"); + mixedPayloadSpec.push_back("P","string"); + } + + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + cout << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << endl; + cout << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << endl; + cout << "Aborting test" << endl; + exit(-1); + } + + static CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + } + + void tearDown() { + db.reset(); + } + + // Make the private suite() available to main() + // MemoryConsumptionTest::suite() is generated by CPPUNIT_TEST_SUITE_END + static CppUnit::TestSuite* theSuite() { return suite(); } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( MemoryConsumptionTest ); + +} // namespace + + +#include <cppunit/ui/text/TestRunner.h> +#include <cppunit/CompilerOutputter.h> + + +int main( int argc, char **argv ) { + + string command; + + if ( argc == 1 ) { + command = "showTests"; + } else if ( argc == 2 ) { + command = argv[1]; + } else { + cout << "Usage:\n" << argv[0] << " [test]" << endl; + cout << "Runs the given test. If called without arguments returns a list " + "of available tests." << endl; + exit(-1); + } + + + CppUnit::TestSuite* suite = cool::MemoryConsumptionTest::theSuite(); + + if ( command == "showTests" ) { + std::vector<CppUnit::Test*> tests = suite->getTests(); + bool first = true; + for ( std::vector<CppUnit::Test*>::const_iterator + test = tests.begin(); test != tests.end(); ++test ) { + if ( first ) { + cout << (*test)->getName(); + first = false; + } else { + cout << " " << (*test)->getName(); + } + } + cout << endl; + return 0; + + } else { + + string testname = command; + + /// Adds the test to the list of test to run + CppUnit::TextUi::TestRunner runner; + std::vector<CppUnit::Test*> tests = suite->getTests(); + for ( std::vector<CppUnit::Test*>::const_iterator + test = tests.begin(); test != tests.end(); ++test ) { + runner.addTest( *test ); + } + + // Change the default outputter to a compiler error format outputter + // uncomment the following line if you need a compiler outputter. + runner.setOutputter(new CppUnit::CompilerOutputter( &runner.result(), + std::cout ) ); + + bool wasSuccessful = runner.run(testname,false,true,false); + + // Return error code 1 if the one of test failed. + // Uncomment the next line if you want to integrate CppUnit with Oval + if(!wasSuccessful !=0) std::cerr <<"Error: CppUnit Failures"<<std::endl; + std::cout <<"[OVAL] Cppunit-result ="<<!wasSuccessful<<std::endl; + return 0; + } +} + +#endif // NOPORT diff --git a/RelationalCool/tests/MemoryConsumption/unitTest_RelationalCool_MemoryConsumption.out.osx103_gcc33 b/RelationalCool/tests/MemoryConsumption/unitTest_RelationalCool_MemoryConsumption.out.osx103_gcc33 new file mode 100644 index 000000000..5194eee23 --- /dev/null +++ b/RelationalCool/tests/MemoryConsumption/unitTest_RelationalCool_MemoryConsumption.out.osx103_gcc33 @@ -0,0 +1,127 @@ + +Start test_seal_TimingItem VSZ=130872 RSS=11692 +object # 0 VSZ=130872 RSS=11740 +object # 1000 VSZ=130948 RSS=12268 +object # 2000 VSZ=131228 RSS=12800 +object # 3000 VSZ=131628 RSS=13340 +object # 4000 VSZ=132052 RSS=13884 +object # 5000 VSZ=132532 RSS=14420 +object # 6000 VSZ=133008 RSS=14960 +object # 7000 VSZ=133420 RSS=15488 +object # 8000 VSZ=133984 RSS=16024 +object # 9000 VSZ=134476 RSS=16544 +End VSZ=134796 RSS=17072 + +OK (1) +[OVAL] Cppunit-result =0 + +Start test_AttributeListSpecification VSZ=130872 RSS=14004 +object 0 VSZ=130872 RSS=14004 +object 100000 VSZ=132292 RSS=15608 +object 200000 VSZ=134036 RSS=17200 +object 300000 VSZ=135508 RSS=18772 +object 400000 VSZ=137212 RSS=20344 +object 500000 VSZ=139000 RSS=21916 +object 600000 VSZ=140652 RSS=23492 +object 700000 VSZ=141932 RSS=25056 +object 800000 VSZ=143376 RSS=26620 +object 900000 VSZ=145008 RSS=28188 + +OK (1) +[OVAL] Cppunit-result =0 + +Start test_AttributeList VSZ=130872 RSS=11664 +object 0 VSZ=130872 RSS=11664 +object 100000 VSZ=130872 RSS=11664 +object 200000 VSZ=130872 RSS=11664 +object 300000 VSZ=130872 RSS=11664 +object 400000 VSZ=130872 RSS=11664 +object 500000 VSZ=130872 RSS=11664 +object 600000 VSZ=130872 RSS=11664 +object 700000 VSZ=130872 RSS=11664 +object 800000 VSZ=130872 RSS=11664 +object 900000 VSZ=130872 RSS=11664 + +OK (1) +[OVAL] Cppunit-result =0 + +Start test_storeObject_bulk VSZ=130872 RSS=11668 +object # 0 VSZ=130872 RSS=11880 +object # 10000 VSZ=145924 RSS=27208 +object # 20000 VSZ=185980 RSS=62092 +object # 30000 VSZ=193264 RSS=69200 +object # 40000 VSZ=199992 RSS=75952 +Before flushing VSZ=207608 RSS=82196 + +---------------------------------------------------- +** wrote 50000 objects (150 bytes mixed) ** +End VSZ=211988 RSS=82524 + +OK (1) +[OVAL] Cppunit-result =0 + +Start test_browseObjects VSZ=130872 RSS=14880 +object # 0 VSZ=130872 RSS=14904 +object # 1000 VSZ=132100 RSS=16080 +object # 2000 VSZ=133872 RSS=17788 +object # 3000 VSZ=135504 RSS=19472 +object # 4000 VSZ=137372 RSS=21144 +object # 5000 VSZ=139112 RSS=22804 +object # 6000 VSZ=140884 RSS=24468 +object # 7000 VSZ=142524 RSS=26128 +object # 8000 VSZ=144092 RSS=27772 +object # 9000 VSZ=145864 RSS=29424 +End VSZ=147472 RSS=31068 + +OK (1) +[OVAL] Cppunit-result =0 + +Start test_fetchObjectTableRowsSV VSZ=130872 RSS=11992 +object # 0 VSZ=130872 RSS=12032 +object # 1000 VSZ=132672 RSS=14356 +object # 2000 VSZ=134988 RSS=16648 +End VSZ=137392 RSS=18896 + +OK (1) +[OVAL] Cppunit-result =0 + +Start test_fetchObjectTableRowsSV_detail VSZ=130872 RSS=12000 +object # 0 VSZ=130872 RSS=12032 +object # 1000 VSZ=132632 RSS=14352 +object # 2000 VSZ=134764 RSS=16628 +End VSZ=137156 RSS=18896 + +OK (1) +[OVAL] Cppunit-result =0 + +Start test_RelationalObjectTableRow VSZ=130872 RSS=11672 +object # 0 VSZ=130872 RSS=11700 +object # 10000 VSZ=130872 RSS=11700 +object # 20000 VSZ=130872 RSS=11700 +object # 30000 VSZ=130872 RSS=11700 +object # 40000 VSZ=130872 RSS=11700 +object # 50000 VSZ=130872 RSS=11700 +object # 60000 VSZ=130872 RSS=11700 +object # 70000 VSZ=130872 RSS=11700 +object # 80000 VSZ=130872 RSS=11700 +object # 90000 VSZ=130872 RSS=11700 +End VSZ=130872 RSS=11700 + +OK (1) +[OVAL] Cppunit-result =0 + +Start test_RelationalObjectTableRow_vector VSZ=130872 RSS=11668 +object # 0 VSZ=130872 RSS=11716 +object # 1000 VSZ=130872 RSS=11716 +object # 2000 VSZ=130872 RSS=11716 +object # 3000 VSZ=130872 RSS=11716 +object # 4000 VSZ=130872 RSS=11716 +object # 5000 VSZ=130872 RSS=11716 +object # 6000 VSZ=130872 RSS=11716 +object # 7000 VSZ=130872 RSS=11716 +object # 8000 VSZ=130872 RSS=11716 +object # 9000 VSZ=130872 RSS=11716 +End VSZ=130872 RSS=11716 + +OK (1) +[OVAL] Cppunit-result =0 diff --git a/RelationalCool/tests/MemoryConsumption/unitTest_RelationalCool_MemoryConsumption.out.slc3_ia32_gcc323 b/RelationalCool/tests/MemoryConsumption/unitTest_RelationalCool_MemoryConsumption.out.slc3_ia32_gcc323 new file mode 100644 index 000000000..04211c9a3 --- /dev/null +++ b/RelationalCool/tests/MemoryConsumption/unitTest_RelationalCool_MemoryConsumption.out.slc3_ia32_gcc323 @@ -0,0 +1,151 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 5 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/home/sas/Projects/Atlas/myLCG/cool_extras/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" + +Start test_seal_TimingItem VSZ=10180 RSS=5956 +object # 0 VSZ=10180 RSS=5972 +object # 1000 VSZ=10580 RSS=6268 +object # 2000 VSZ=10852 RSS=6608 +object # 3000 VSZ=11168 RSS=6940 +object # 4000 VSZ=11500 RSS=7280 +object # 5000 VSZ=11832 RSS=7612 +object # 6000 VSZ=12312 RSS=7952 +object # 7000 VSZ=12616 RSS=8288 +object # 8000 VSZ=12920 RSS=8620 +object # 9000 VSZ=13348 RSS=8960 +End VSZ=13508 RSS=9300 + +OK (1) +[OVAL] Cppunit-result =0 +Property Catalogue: level[Info] Adding property: OutputLevel = 5 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/home/sas/Projects/Atlas/myLCG/cool_extras/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" + +Start test_AttributeList VSZ=10180 RSS=5996 +object 0 VSZ=10180 RSS=5996 +object 100000 VSZ=10180 RSS=5996 +object 200000 VSZ=10180 RSS=5996 +object 300000 VSZ=10180 RSS=5996 +object 400000 VSZ=10180 RSS=5996 +object 500000 VSZ=10180 RSS=5996 +object 600000 VSZ=10180 RSS=5996 +object 700000 VSZ=10180 RSS=5996 +object 800000 VSZ=10180 RSS=5996 +object 900000 VSZ=10180 RSS=5996 + +OK (1) +[OVAL] Cppunit-result =0 +Property Catalogue: level[Info] Adding property: OutputLevel = 5 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/home/sas/Projects/Atlas/myLCG/cool_extras/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" + +Start test_storeObject_bulk VSZ=10176 RSS=5992 +object # 0 VSZ=10176 RSS=6152 +object # 10000 VSZ=22964 RSS=18940 +object # 20000 VSZ=41108 RSS=37148 +object # 30000 VSZ=41752 RSS=37792 +object # 40000 VSZ=41936 RSS=37976 +object # 50000 VSZ=42080 RSS=38120 +object # 60000 VSZ=42104 RSS=38144 +object # 70000 VSZ=42104 RSS=38144 +object # 80000 VSZ=42104 RSS=38144 +object # 90000 VSZ=42112 RSS=38152 +object # 100000 VSZ=41524 RSS=37564 +object # 110000 VSZ=41832 RSS=37872 +object # 120000 VSZ=42000 RSS=38040 +object # 130000 VSZ=42108 RSS=38148 +object # 140000 VSZ=42108 RSS=38148 +object # 150000 VSZ=42112 RSS=38152 +object # 160000 VSZ=41920 RSS=37960 +object # 170000 VSZ=42068 RSS=38108 +object # 180000 VSZ=42116 RSS=38156 +object # 190000 VSZ=41108 RSS=37148 +Before flushing VSZ=41764 RSS=37804 + +---------------------------------------------------- +** wrote 200000 objects (150 bytes mixed) ** +End VSZ=41812 RSS=37904 + +OK (1) +[OVAL] Cppunit-result =0 +Property Catalogue: level[Info] Adding property: OutputLevel = 5 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/home/sas/Projects/Atlas/myLCG/cool_extras/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" + +Start test_browseObjects VSZ=10224 RSS=6304 +object # 0 VSZ=10224 RSS=6324 +object # 1000 VSZ=10224 RSS=6324 +object # 2000 VSZ=10224 RSS=6324 +object # 3000 VSZ=10224 RSS=6324 +object # 4000 VSZ=10224 RSS=6324 +object # 5000 VSZ=10224 RSS=6324 +object # 6000 VSZ=10224 RSS=6324 +object # 7000 VSZ=10224 RSS=6324 +object # 8000 VSZ=10224 RSS=6324 +object # 9000 VSZ=10224 RSS=6324 +End VSZ=10224 RSS=6324 + +OK (1) +[OVAL] Cppunit-result =0 +Property Catalogue: level[Info] Adding property: OutputLevel = 5 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/home/sas/Projects/Atlas/myLCG/cool_extras/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" + +Start test_fetchObjectTableRowsSV VSZ=10300 RSS=6260 +object # 0 VSZ=10300 RSS=6276 +object # 1000 VSZ=10300 RSS=6276 +object # 2000 VSZ=10300 RSS=6276 +End VSZ=10300 RSS=6276 + +OK (1) +[OVAL] Cppunit-result =0 +Property Catalogue: level[Info] Adding property: OutputLevel = 5 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/home/sas/Projects/Atlas/myLCG/cool_extras/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" + +Start test_fetchObjectTableRowsSV_detail VSZ=10284 RSS=6256 +object # 0 VSZ=10284 RSS=6268 +object # 1000 VSZ=10284 RSS=6268 +object # 2000 VSZ=10284 RSS=6268 +End VSZ=10284 RSS=6268 + +OK (1) +[OVAL] Cppunit-result =0 +Property Catalogue: level[Info] Adding property: OutputLevel = 5 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/home/sas/Projects/Atlas/myLCG/cool_extras/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" + +Start test_RelationalObjectTableRow VSZ=10176 RSS=6008 +object # 0 VSZ=10176 RSS=6024 +object # 10000 VSZ=10176 RSS=6024 +object # 20000 VSZ=10176 RSS=6024 +object # 30000 VSZ=10176 RSS=6024 +object # 40000 VSZ=10176 RSS=6024 +object # 50000 VSZ=10176 RSS=6024 +object # 60000 VSZ=10176 RSS=6024 +object # 70000 VSZ=10176 RSS=6024 +object # 80000 VSZ=10176 RSS=6024 +object # 90000 VSZ=10176 RSS=6024 +End VSZ=10176 RSS=6024 + +OK (1) +[OVAL] Cppunit-result =0 +Property Catalogue: level[Info] Adding property: OutputLevel = 5 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/home/sas/Projects/Atlas/myLCG/cool_extras/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" + +Start test_RelationalObjectTableRow_vector VSZ=10176 RSS=5996 +object # 0 VSZ=10176 RSS=6012 +object # 1000 VSZ=10176 RSS=6012 +object # 2000 VSZ=10176 RSS=6012 +object # 3000 VSZ=10176 RSS=6012 +object # 4000 VSZ=10176 RSS=6012 +object # 5000 VSZ=10176 RSS=6012 +object # 6000 VSZ=10176 RSS=6012 +object # 7000 VSZ=10176 RSS=6012 +object # 8000 VSZ=10176 RSS=6012 +object # 9000 VSZ=10176 RSS=6012 +End VSZ=10176 RSS=6012 + +OK (1) +[OVAL] Cppunit-result =0 diff --git a/RelationalCool/tests/MyODBCBulkTest/README b/RelationalCool/tests/MyODBCBulkTest/README new file mode 100644 index 000000000..44b51ceb1 --- /dev/null +++ b/RelationalCool/tests/MyODBCBulkTest/README @@ -0,0 +1,128 @@ +Summary table (strings only) +----------------------------- + +#chars #cols #rows Result (#chars+2)*(#cols) + +8186 1 1 OK 8188 +8187 1 1 ERROR #1 8189 + +4091 2 1 OK 8186 +4092 2 1 ERROR #1 8188 + +1020 8 1 OK 8176 +1021 8 1 ERROR #1 8184 + +10 674 1 OK 8088 +10 675 1 ERROR #2 8100 + +8 809 1 OK 8090 +8 810 1 ERROR #2 8100 + +100 79 1 OK 8058 +100 80 1 ERROR #3 8160 + +98 80 1 OK 8000 +98 81 1 ERROR #4 8100 + +7 899 1 OK 8091 +7 900 1 ERROR #2 8100 + +6 1000 1 OK 8000 +6 1001 1 ERROR #5 -- too many columns -- + +Looks like: +=> OK if ( #chars + 2 ) * ( #cols ) <= 8000 +=> May (or may not) fail otherwise + +NB: +- checked that the names of the columns are irrelevant (eg "sXXX" vs "ssXXX") +- checked that the name of the table is irrelevant (eg "DataTable" vs "Table") + +Error messages +--------------- + +* ERROR #1 + +POOL/RelationalPlugins/mysql/odbc: level[Info] Bulk rowset SQL: SELECT "s0"... + +POOL/RelationalPlugins/mysql/odbc: level[Error] /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_1_2/src/ODBCAccess/src/ODBCBulkRowInserter.cpp:316:pcitdb59.cern.ch:HY000:Affected rows 0:-1:1064:[MySQL][ODBC 3.51 Driver][mysqld-4.0.25-standard-log]You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 + +Segmentation fault + +* ERROR #2 + +POOL/RelationalPlugins/mysql/odbc: level[Info] Bulk rowset SQL: SELECT "s0"... + +POOL/RelationalPlugins/mysql/odbc: level[Error] /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_1_2/src/ODBCAccess/src/ODBCBulkRowInserter.cpp:316:pcitdb59.cern.ch:HY000:Affected rows 0:-1:1030:[MySQL][ODBC 3.51 Driver][mysqld-4.0.25-standard-log]Got error 139 from table handler + +Standard C++ exception : Could not flush the remaining rows into the table. + +* ERROR #3 + +POOL/RelationalPlugins/mysql/odbc: level[Info] Bulk rowset SQL: SELECT "s0"... + +Out of memory (Needed 2924090368 bytes) + +POOL/RelationalPlugins/mysql/odbc: level[Error] /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_1_2/src/ODBCAccess/src/ODBCBulkRowInserter.cpp:316:pcitdb59.cern.ch:HY000:Affected rows 0:-1:1136:[MySQL][ODBC 3.51 Driver][mysqld-4.0.25-standard-log]Column count doesn't match value count at row 1 + +Standard C++ exception : Could not flush the remaining rows into the table. + +* ERROR #4 + +POOL/RelationalPlugins/mysql/odbc: level[Info] Bulk rowset SQL: SELECT "s0"... + +POOL/RelationalPlugins/mysql/odbc: level[Error] /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_1_2/src/ODBCAccess/src/ODBCBulkRowInserter.cpp:316:pcitdb59.cern.ch:HY000:Affected rows 0:-1:1136:[MySQL][ODBC 3.51 Driver][mysqld-4.0.25-standard-log]Column count doesn't match value count at row 1 + +Standard C++ exception : Could not flush the remaining rows into the table. + +* ERROR #5 + +POOL/RelationalPlugins/mysql/odbc: level[Debug] Prepared statement: CREATE TABLE + +POOL/RelationalPlugins/mysql/odbc: level[Error] /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_1_2/src/ODBCAccess/src/ODBCStatement.cpp:335:pcitdb59.cern.ch:HY000:Affected rows 0:-1:1005:[MySQL][ODBC 3.51 Driver][mysqld-4.0.25-standard-log]Can't create table './COOLDB/DataTable.frm' (errno: 139) + +Relational exception from module MySQL/ODBC + Could not create a table named "DataTable" + +Summary table (strings and integers) +------------------------------------- + +#chars #cols #rows Result intValue #intCols + +8186 1 1 OK 0 0 +8187 1 1 ERROR #1 0 0 + +8183 1 1 OK 1 1 +8184 1 1 ERROR #1 1 1 + +8183 1 1 OK 9999 1 +8183 1 1 ERROR #1 10000 1 +8182 1 1 OK 10000 1 +8182 1 1 OK 99999 1 +8182 1 1 ERROR #1 100000 1 +8181 1 1 OK 100000 1 + +8178 1 1 OK 999999999 1 +8178 1 1 ERROR #1 1000000000 1 +8177 1 1 OK 1000000000 1 + +So, clearly integer columns ALSO take up space, and they take up a space +that ALSO depends on the integer value (although it is not a simple +count of the decimal representation string length). + +eg "1" takes up 2 (overhead) + 1 byte +eg "1000" takes up 2 (overhead) + 1 byte +eg "10000" takes up 2 (overhead) + 2 bytes +eg "100000000" takes up 2 (overhead) + 6 bytes + +MyODBC code +------------ + +According to Marco: the problem is in cursor.c, lines 1048-1049: + + dynstr_append_mem(ext_query, net->buff, length-1); + dynstr_append_mem(ext_query, "),", 2); + +This shows that bind variables are not used (and could be analysed +to understand what exactly is done - but we will not bother!). + diff --git a/RelationalCool/tests/MyODBCBulkTest/test_MyODBCBulkOp.cpp b/RelationalCool/tests/MyODBCBulkTest/test_MyODBCBulkOp.cpp new file mode 100755 index 000000000..320a3ec09 --- /dev/null +++ b/RelationalCool/tests/MyODBCBulkTest/test_MyODBCBulkOp.cpp @@ -0,0 +1,213 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +#include <iostream> +#include <stdexcept> +#include <memory> +#include "RelationalAccess/RelationalException.h" +#include "RelationalAccess/IRelationalService.h" +#include "RelationalAccess/IRelationalDomain.h" +#include "RelationalAccess/IRelationalSession.h" +#include "RelationalAccess/IRelationalTransaction.h" +#include "RelationalAccess/IRelationalSchema.h" +#include "RelationalAccess/IRelationalTable.h" +#include "RelationalAccess/RelationalEditableTableDescription.h" +#include "RelationalAccess/IRelationalTableDataEditor.h" +#include "RelationalAccess/IRelationalBulkRowInserter.h" +#include "RelationalAccess/IRelationalQuery.h" +#include "RelationalAccess/IRelationalCursor.h" +#include "AttributeList/AttributeList.h" +#include "POOLCore/POOLContext.h" +#include "SealKernel/Context.h" +#include "RelationalAccess/IRelationalTypeConverter.h" +#include <sstream> + +#include <cstdlib> + +int main( int argc, char *argv[] ) +{ + + if ( argc != 4 && argc != 6 ) { + std::cout << "Usage " << argv[0] + << " n_chars n_charCols n_rows [intValue n_intCols]" + << std::endl; + return 1; + } + + try { + std::string charCol_name = "s"; // No difference if changed to "ss" + std::string intCol_name = "i"; + std::string tab_name = "DataTable"; // No difference if changed to "Table" + size_t n_chars; + int n_charCols; + int n_rows; + int intValue = 0; + int n_intCols = 0; + + { + std::istringstream a1(argv[1]); a1 >> n_chars; + std::istringstream a2(argv[2]); a2 >> n_charCols; + std::istringstream a3(argv[3]); a3 >> n_rows; + if ( argc == 6 ) + { std::istringstream a4(argv[4]); a4 >> intValue; + std::istringstream a5(argv[5]); a5 >> n_intCols; } + } + + pool::POOLContext::loadComponent( "SEAL/Services/Message Service" ); + pool::POOLContext::loadComponent( "POOL/Services/XMLAuthenticationService" ); + pool::POOLContext::loadComponent( "POOL/Services/RelationalService" ); + pool::POOLContext::setMessageVerbosityLevel( seal::Msg::Debug ); + seal::MessageStream log( pool::POOLContext::context(), "TableDataEditor_Test" ); + seal::IHandle<pool::IRelationalService> serviceHandle = + pool::POOLContext::context()->query<pool::IRelationalService>( "POOL/Services/RelationalService" ); + if ( ! serviceHandle ) { + throw std::runtime_error( "Could not retrieve the relational service" ); + } + + std::string connectionString = "mysql://pcitdb59.cern.ch/COOLDB"; + pool::IRelationalDomain& domain = serviceHandle->domainForConnection( connectionString ); + + // Creating a session + std::auto_ptr< pool::IRelationalSession > session( domain.newSession( connectionString ) ); + + // Establish a connection with the server + std::cout << "Connecting..." << std::endl; + if ( ! session->connect() ) { + throw std::runtime_error( "Could not connect to the database server." ); + } + + // Start a transaction + std::cout << "Starting a new transaction" << std::endl; + if ( ! session->transaction().start() ) { + throw std::runtime_error( "Could not start a new transaction." ); + } + + // Droping old tables + if ( session->userSchema().existsTable( tab_name ) ) { + std::cout << "Deleting table \"" << tab_name << "\"" << std::endl; + if ( ! session->userSchema().dropTable( tab_name ) ) { + throw std::runtime_error( "Could not drop a table." ); + } + } + + session->typeConverter().setSqlTypeForCppType("TEXT",pool::AttributeStaticTypeInfo<std::string>::type_name()); + + // Creating the description for the table + std::auto_ptr< pool::IRelationalEditableTableDescription > + description1( new pool::RelationalAccess::RelationalEditableTableDescription( log, + domain.flavorName() )); + for ( int j = 0 ; j < n_charCols ; ++j ){ + std::ostringstream cn; + cn << charCol_name << j; + description1->insertColumn( cn.str(), pool::AttributeStaticTypeInfo<std::string>::type_name() ); + } + for ( int j = 0 ; j < n_intCols ; ++j ){ + std::ostringstream cn; + cn << intCol_name << j; + description1->insertColumn( cn.str(), pool::AttributeStaticTypeInfo<int>::type_name() ); + } + + // Create the first table. + std::cout << "Creating table \"" << tab_name << "\"" << std::endl; + pool::IRelationalTable& table1 = session->userSchema().createTable( tab_name, *description1 ); + + // Costructing a row buffer. + pool::AttributeList data1( table1.description().columnNamesAndTypes() ); + + // Adding new rows + std::cout << "Inserting new rows into the table." << std::endl; + pool::IRelationalBulkRowInserter& rowInserter1 = table1.dataEditor().bulkRowInserter(); + if ( ! rowInserter1.setup( data1, 50 ) ) + { + throw std::runtime_error( "Could not bind a new row for inserting." ); + } + + for ( int i = 0; i < n_rows; ++i ) + { + for ( int j = 0 ; j < n_charCols ; ++j ){ + std::ostringstream cn; + cn << charCol_name << j; + data1[cn.str()].setValue<std::string>( std::string(n_chars,'x') ); + } + for ( int j = 0 ; j < n_intCols ; ++j ){ + std::ostringstream cn; + cn << intCol_name << j; + data1[cn.str()].setValue<int>( intValue ); + } + + if ( ! rowInserter1.insertNewRow() ) + { + throw std::runtime_error( "Could not insert a new row into the table." ); + } + } + + if ( ! rowInserter1.flushCache() ) { + throw std::runtime_error( "Could not flush the remaining rows into the table." ); + } + + // Committing the transaction + std::cout << "Committing..." << std::endl; + if ( ! session->transaction().commit() ) { + throw std::runtime_error( "Could not commit the transaction." ); + } + + // Read back some first 255 rows from the table + std::cout << "Querying : SELECT * FROM " << tab_name << " LIMIT 255" << std::endl; + std::auto_ptr< pool::IRelationalQuery > query1( table1.createQuery() ); + query1->setRowCacheSize( 5 ); + query1->limitReturnedRows( 255 ); + pool::AttributeList emptyBindVariableList; + pool::IRelationalCursor& cursor1 = query1->process(); + + if ( cursor1.start() ) + { + while( cursor1.next() ) + { + const pool::AttributeList& row = cursor1.currentRow(); + for ( pool::AttributeList::const_iterator iColumn = row.begin(); + iColumn != row.end(); ++iColumn ) + { + if( iColumn->spec().type_name() == "unsigned char" ) + { + unsigned char ucval = 0; + iColumn->getValue( ucval ); + std::cout << iColumn->spec().name() << " : " << (unsigned short)ucval << "\t"; + } + else + std::cout << iColumn->spec().name() << " : " << iColumn->getValueAsString().size() << "\t"; + + } + std::cout << std::endl; + } + } + + std::cout << cursor1.numberOfRows() << " row(s) selected." << std::endl; + + // Disconnecting + std::cout << "Disconnecting..." << std::endl; + session->disconnect(); + + std::cout << "Exiting..." << std::endl; + } + catch ( pool::RelationalException& re ) { + std::cerr << "Relational exception from module " << re.flavorName() << std::endl + << " " << re.what() << std::endl; + return 1; + } + catch ( seal::Exception& se ) { + std::cerr << "Seal Exception : " << se.what() << std::endl; + return 1; + } + catch ( std::exception& e ) { + std::cerr << "Standard C++ exception : " << e.what() << std::endl; + return 1; + } + catch ( ... ) { + std::cerr << "Exception caught (...)" << std::endl; + return 1; + } + return 0; +} + +#endif // NOPORT diff --git a/RelationalCool/tests/MyTest/DO_NOT_DELETE_ME b/RelationalCool/tests/MyTest/DO_NOT_DELETE_ME new file mode 100644 index 000000000..e69de29bb diff --git a/RelationalCool/tests/ObjectId/test_ObjectId.cpp b/RelationalCool/tests/ObjectId/test_ObjectId.cpp new file mode 100644 index 000000000..da4dbd5b7 --- /dev/null +++ b/RelationalCool/tests/ObjectId/test_ObjectId.cpp @@ -0,0 +1,306 @@ +// $Id: test_ObjectId.cpp,v 1.11 2006-11-22 12:45:53 marcocle Exp $ + +// Include files +#include "CoolUnitTest.h" + +// Local include files +#include "src/ObjectId.h" + +//----------------------------------------------------------------------------- + +class cool::ObjectIdTest : public cool::CoolUnitTest { + + CPPUNIT_TEST_SUITE( ObjectIdTest ); + CPPUNIT_TEST( test_ObjectId1 ); + CPPUNIT_TEST( test_ObjectId2 ); + CPPUNIT_TEST( test_ObjectId3 ); + CPPUNIT_TEST( test_ObjectId4 ); + CPPUNIT_TEST( test_ObjectId5 ); + CPPUNIT_TEST( test_ObjectId6 ); + CPPUNIT_TEST( test_ObjectId7 ); + CPPUNIT_TEST( test_ObjectId8 ); + CPPUNIT_TEST( test_ObjectId9 ); + CPPUNIT_TEST( test_maxId ); + CPPUNIT_TEST( test_maxId_overflow ); + CPPUNIT_TEST_SUITE_END(); + +public: + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_ObjectId1() { + ObjectId id = 1; + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == true ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "userObject", ObjectIdHandler::userObject(id) == 1 ); + CPPUNIT_ASSERT_MESSAGE + ( "lSysObject", ObjectIdHandler::lSysObject(id) == 2 ); + CPPUNIT_ASSERT_MESSAGE + ( "rSysObject", ObjectIdHandler::rSysObject(id) == 3 ); + CPPUNIT_ASSERT_MESSAGE + ( "nextUserObject", ObjectIdHandler::nextUserObject(id) == 7 ); + try { + ObjectIdHandler::prevUserObject(id); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( Exception& e ) { + std::ostringstream msg; + msg << "ObjectId '" << id << "' has no previous user object"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", msg.str(), std::string( e.what() ) ); + } + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_ObjectId2() { + ObjectId id = 2; + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == true ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "userObject", ObjectIdHandler::userObject(id) == 1 ); + CPPUNIT_ASSERT_MESSAGE + ( "lSysObject", ObjectIdHandler::lSysObject(id) == 2 ); + CPPUNIT_ASSERT_MESSAGE + ( "rSysObject", ObjectIdHandler::rSysObject(id) == 3 ); + CPPUNIT_ASSERT_MESSAGE + ( "nextUserObject", ObjectIdHandler::nextUserObject(id) == 7 ); + try { + ObjectIdHandler::prevUserObject(id); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( Exception& e ) { + std::ostringstream msg; + msg << "ObjectId '" << id << "' has no previous user object"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", std::string( e.what() ), msg.str() ); + } + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_ObjectId3() { + ObjectId id = 3; + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == true ); + CPPUNIT_ASSERT_MESSAGE + ( "userObject", ObjectIdHandler::userObject(id) == 1 ); + CPPUNIT_ASSERT_MESSAGE + ( "lSysObject", ObjectIdHandler::lSysObject(id) == 2 ); + CPPUNIT_ASSERT_MESSAGE + ( "rSysObject", ObjectIdHandler::rSysObject(id) == 3 ); + CPPUNIT_ASSERT_MESSAGE + ( "nextUserObject", ObjectIdHandler::nextUserObject(id) == 7 ); + try { + ObjectIdHandler::prevUserObject(id); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( Exception& e ) { + std::ostringstream msg; + msg << "ObjectId '" << id << "' has no previous user object"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", std::string( e.what() ), msg.str() ); + } + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_ObjectId4() { + ObjectId id = 4; // this is unused and reserved for user tag related ids + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "userObject", ObjectIdHandler::userObject(id) == 1 ); + CPPUNIT_ASSERT_MESSAGE + ( "lSysObject", ObjectIdHandler::lSysObject(id) == 2 ); + CPPUNIT_ASSERT_MESSAGE + ( "rSysObject", ObjectIdHandler::rSysObject(id) == 3 ); + CPPUNIT_ASSERT_MESSAGE + ( "nextUserObject", ObjectIdHandler::nextUserObject(id) == 7 ); + try { + ObjectIdHandler::prevUserObject(id); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( Exception& e ) { + std::ostringstream msg; + msg << "ObjectId '" << id << "' has no previous user object"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", std::string( e.what() ), msg.str() ); + } + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_ObjectId5() { + ObjectId id = 5; // this is unused and reserved for user tag related ids + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "userObject", ObjectIdHandler::userObject(id) == 1 ); + CPPUNIT_ASSERT_MESSAGE + ( "lSysObject", ObjectIdHandler::lSysObject(id) == 2 ); + CPPUNIT_ASSERT_MESSAGE + ( "rSysObject", ObjectIdHandler::rSysObject(id) == 3 ); + CPPUNIT_ASSERT_MESSAGE + ( "nextUserObject", ObjectIdHandler::nextUserObject(id) == 7 ); + try { + ObjectIdHandler::prevUserObject(id); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( Exception& e ) { + std::ostringstream msg; + msg << "ObjectId '" << id << "' has no previous user object"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", std::string( e.what() ), msg.str() ); + } + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_ObjectId6() { + ObjectId id = 6; // this is unused and reserved for user tag related ids + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "userObject", ObjectIdHandler::userObject(id) == 1 ); + CPPUNIT_ASSERT_MESSAGE + ( "lSysObject", ObjectIdHandler::lSysObject(id) == 2 ); + CPPUNIT_ASSERT_MESSAGE + ( "rSysObject", ObjectIdHandler::rSysObject(id) == 3 ); + CPPUNIT_ASSERT_MESSAGE + ( "nextUserObject", ObjectIdHandler::nextUserObject(id) == 7 ); + try { + ObjectIdHandler::prevUserObject(id); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( Exception& e ) { + std::ostringstream msg; + msg << "ObjectId '" << id << "' has no previous user object"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", std::string( e.what() ), msg.str() ); + } + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_ObjectId7() { + ObjectId id = 7; + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == true ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "userObject", ObjectIdHandler::userObject(id) == 7 ); + CPPUNIT_ASSERT_MESSAGE + ( "lSysObject", ObjectIdHandler::lSysObject(id) == 8 ); + CPPUNIT_ASSERT_MESSAGE + ( "rSysObject", ObjectIdHandler::rSysObject(id) == 9 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "nextUserObject", 13u, ObjectIdHandler::nextUserObject(id) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "prevUserObject", 1u, ObjectIdHandler::prevUserObject(id) ); + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_ObjectId8() { + ObjectId id = 8; + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == true ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "userObject", ObjectIdHandler::userObject(id) == 7 ); + CPPUNIT_ASSERT_MESSAGE + ( "lSysObject", ObjectIdHandler::lSysObject(id) == 8 ); + CPPUNIT_ASSERT_MESSAGE + ( "rSysObject", ObjectIdHandler::rSysObject(id) == 9 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "nextUserObject", 13u, ObjectIdHandler::nextUserObject(id) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "prevUserObject", 1u, ObjectIdHandler::prevUserObject(id) ); + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + void test_ObjectId9() { + ObjectId id = 9; + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == true ); + CPPUNIT_ASSERT_MESSAGE + ( "userObject", ObjectIdHandler::userObject(id) == 7 ); + CPPUNIT_ASSERT_MESSAGE + ( "lSysObject", ObjectIdHandler::lSysObject(id) == 8 ); + CPPUNIT_ASSERT_MESSAGE + ( "rSysObject", ObjectIdHandler::rSysObject(id) == 9 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "nextUserObject", 13u, ObjectIdHandler::nextUserObject(id) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "prevUserObject", 1u, ObjectIdHandler::prevUserObject(id) ); + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + + void test_maxId() { + ObjectId id = UINT_MAX; // == 4294967295 + CPPUNIT_ASSERT_MESSAGE + ( "isUserObject", ObjectIdHandler::isUserObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isLSysObject", ObjectIdHandler::isLSysObject(id) == false ); + CPPUNIT_ASSERT_MESSAGE + ( "isRSysObject", ObjectIdHandler::isRSysObject(id) == true ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "userObject", 4294967293u, ObjectIdHandler::userObject(id) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "lSysObject", 4294967294u, ObjectIdHandler::lSysObject(id) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "rSysObject", 4294967295u, ObjectIdHandler::rSysObject(id) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "prevUserObject", 4294967287u, ObjectIdHandler::prevUserObject(id) ); + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + + void test_maxId_overflow() { + ObjectId id = UINT_MAX; + CPPUNIT_ASSERT_THROW(ObjectIdHandler::nextUserObject(id) , ObjectIdException); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( cool::ObjectIdTest ); + +//----------------------------------------------------------------------------- + +COOLTEST_MAIN(ObjectIdTest) + + diff --git a/RelationalCool/tests/PayloadSpecification/test_PayloadSpecification.cpp b/RelationalCool/tests/PayloadSpecification/test_PayloadSpecification.cpp new file mode 100644 index 000000000..e56388843 --- /dev/null +++ b/RelationalCool/tests/PayloadSpecification/test_PayloadSpecification.cpp @@ -0,0 +1,474 @@ +// $Id: test_PayloadSpecification.cpp,v 1.13 2006-12-14 12:04:46 avalassi Exp $ +#include "CoolUnitTest.h" + +// Include files +#include "CoralBase/Attribute.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordException.h" +#include "CoolKernel/RecordSpecification.h" +#include "../../src/RelationalDatabase.h" +#include "../../src/RelationalException.h" +#include "../../src/RelationalQueryMgr.h" + +namespace cool { + + class PayloadSpecificationTest : public CoolUnitTest { + + CPPUNIT_TEST_SUITE( PayloadSpecificationTest ); + + CPPUNIT_TEST( test_extend ); + CPPUNIT_TEST( test_cannot_extend ); + + CPPUNIT_TEST( test_copy_constructor ); + + CPPUNIT_TEST( test_sum ); + + CPPUNIT_TEST( test_size ); + CPPUNIT_TEST( test_empty ); + + CPPUNIT_TEST( test_extend_AL ); + CPPUNIT_TEST( test_create_AL ); + + CPPUNIT_TEST( test_check_AL ); + CPPUNIT_TEST( test_check_AL_bad_size ); + CPPUNIT_TEST( test_check_AL_bad_string_size ); + CPPUNIT_TEST( test_check_AL_good_string_size ); + CPPUNIT_TEST( test_check_AL_bad_UInt63 ); + CPPUNIT_TEST( test_check_AL_good_UInt63 ); + CPPUNIT_TEST( test_check_AL_unexpected_type ); + + // Tests coming from RelationalDatabase tests + CPPUNIT_TEST( test_encode_decode ); + CPPUNIT_TEST( test_decodeEmptySpec ); + CPPUNIT_TEST( test_decodeNoColon ); + CPPUNIT_TEST( test_decodeTrailingComma ); + + CPPUNIT_TEST_SUITE_END(); + + public: + + void setUp() { + /// prepare for the test + } + + void tearDown(){ + /// clean up after the test + } + + // ------------------------------------------------------ + // The tests + // ------------------------------------------------------ + + // ------------------------------------------------------ + void test_extend() { + // ------------------------------------------------------ + // -- allowed macros + // CPPUNIT_ASSERT(condition) + // CPPUNIT_ASSERT_MESSAGE(message,condition) + // CPPUNIT_ASSERT_EQUAL(expected,actual) + // CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,actual) + // CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,actual,delta) + // CPPUNIT_ASSERT_THROW( expression, ExceptionType ) + // CPPUNIT_ASSERT_NO_THROW( expression ) + + // Test the signatures of the RecordSpecification::extend method + RecordSpecification pls; + + // void extend( const std::string&, const StorageType::TypeId ); + pls.extend( "I", cool::StorageType::Int32 ); + + // void extend( const std::string&, const StorageType& ); + pls.extend + ( "X", cool::StorageType::storageType( cool::StorageType::Float ) ); + + // void extend( const IFieldSpecification& ); + RecordSpecification tmp_pls1; + tmp_pls1.extend( "S255", cool::StorageType::String255 ); + pls.extend( tmp_pls1["S255"] ); + + // void extend( const IRecordSpecification& ); + RecordSpecification tmp_pls2; + tmp_pls2.extend( "A", cool::StorageType::UInt32 ); + tmp_pls2.extend( "B", cool::StorageType::String4k ); + pls.extend( tmp_pls2 ); + + // Check that the final specification is as expected + CPPUNIT_ASSERT_MESSAGE + ("RecordSpec::extend(const std::string&, StorageType::TypeId) failed", + pls["I"].storageType() == cool::StorageType::Int32); + CPPUNIT_ASSERT_MESSAGE + ("RecordSpec::extend(const std::string&, const StorageType&) failed", + pls["X"].storageType() == cool::StorageType::Float); + CPPUNIT_ASSERT_MESSAGE + ("RecordSpec::extend(const IFieldSpecification&) failed", + pls["S255"].storageType() == cool::StorageType::String255); + + CPPUNIT_ASSERT_MESSAGE + ("RecordSpec::extend(const IRecordSpecification&)failed", + (pls["A"].storageType() == cool::StorageType::UInt32) && + (pls["B"].storageType() == cool::StorageType::String4k)); + + } + + // ------------------------------------------------------ + void test_cannot_extend() { + // ------------------------------------------------------ + RecordSpecification pls; + + pls.extend( "A", cool::StorageType::UInt32 ); + pls.extend( "B", cool::StorageType::String4k ); + + CPPUNIT_ASSERT_THROW + ( pls.extend( "A", cool::StorageType::String255 ), + RecordSpecificationCannotExtend ); + + } + + // ------------------------------------------------------ + void test_copy_constructor() { + // ------------------------------------------------------ + RecordSpecification pls; + + pls.extend( "A", cool::StorageType::UInt32 ); + pls.extend( "B", cool::StorageType::String4k ); + + RecordSpecification pls2(pls); + + CPPUNIT_ASSERT_MESSAGE + ("RecordSpec::extend(const IRecordSpecification&) failed", + (pls2["A"].storageType() == cool::StorageType::UInt32) && + (pls2["B"].storageType() == cool::StorageType::String4k)); + + } + + // ------------------------------------------------------ + void test_sum() { + // ------------------------------------------------------ + RecordSpecification pls1; + + pls1.extend( "A", cool::StorageType::UInt32 ); + pls1.extend( "B", cool::StorageType::String4k ); + + RecordSpecification pls2; + + pls2.extend( "C", cool::StorageType::Float ); + pls2.extend( "D", cool::StorageType::Double ); + + RecordSpecification pls = pls1; + pls.extend( pls2 ); + + CPPUNIT_ASSERT_MESSAGE + ("RecordSpec::extend(const IRecordSpecification&) failed", + (pls["A"].storageType() == cool::StorageType::UInt32) && + (pls["B"].storageType() == cool::StorageType::String4k) && + (pls["C"].storageType() == cool::StorageType::Float) && + (pls["D"].storageType() == cool::StorageType::Double)); + + } + + // ------------------------------------------------------ + void test_size() { + // ------------------------------------------------------ + RecordSpecification pls; + + CPPUNIT_ASSERT_EQUAL((UInt32)0,pls.size()); + + pls.extend( "A", cool::StorageType::UInt32 ); + + CPPUNIT_ASSERT_EQUAL((UInt32)1,pls.size()); + + pls.extend( "B", cool::StorageType::String4k ); + + CPPUNIT_ASSERT_EQUAL((UInt32)2,pls.size()); + } + + // ------------------------------------------------------ + void test_empty() { + // ------------------------------------------------------ + RecordSpecification pls; + + CPPUNIT_ASSERT(pls.size()==0); + + pls.extend( "TEST", cool::StorageType::Double ); + + CPPUNIT_ASSERT(pls.size()!=0); + } + + // ------------------------------------------------------ + void test_extend_AL() { + // ------------------------------------------------------ + RecordSpecification pls; + + pls.extend( "A", cool::StorageType::UInt32 ); + pls.extend( "B", cool::StorageType::String4k ); + + coral::AttributeList al = Record( pls ).attributeList(); + + CPPUNIT_ASSERT_MESSAGE + ("Test_extend_AL failed", + (al["A"].specification().type() == + typeIdToCoralType(cool::StorageType::UInt32)) && + (al["B"].specification().type() == + typeIdToCoralType(cool::StorageType::String4k))); + } + + // ------------------------------------------------------ + void test_create_AL() { + // ------------------------------------------------------ + RecordSpecification pls; + + pls.extend( "A", cool::StorageType::UInt32 ); + pls.extend( "B", cool::StorageType::String4k ); + + coral::AttributeList al = Record( pls ).attributeList(); + + CPPUNIT_ASSERT_MESSAGE + ("Test_create_AL failed", + (al["A"].specification().type() == + typeIdToCoralType(cool::StorageType::UInt32)) && + (al["B"].specification().type() == + typeIdToCoralType(cool::StorageType::String4k))); + } + + // ------------------------------------------------------ + void test_check_AL() { + // ------------------------------------------------------ + std::vector<StorageType::TypeId> all_types; + + all_types.push_back(StorageType::Bool); + //all_types.push_back(StorageType::Char); + all_types.push_back(StorageType::UChar); + all_types.push_back(StorageType::Int16); + all_types.push_back(StorageType::UInt16); + all_types.push_back(StorageType::Int32); + all_types.push_back(StorageType::UInt32); + all_types.push_back(StorageType::UInt63); + all_types.push_back(StorageType::Int64); + //all_types.push_back(StorageType::UInt64); + all_types.push_back(StorageType::Float); + all_types.push_back(StorageType::Double); + all_types.push_back(StorageType::String255); + all_types.push_back(StorageType::String4k); + all_types.push_back(StorageType::String64k); + all_types.push_back(StorageType::String16M); + + RecordSpecification pls; + std::vector<StorageType::TypeId>::iterator i; + for(i = all_types.begin(); i != all_types.end(); ++i ){ + pls.extend( StorageType::storageType(*i).name(),*i); + } + + coral::AttributeList al = Record( pls ).attributeList(); + + CPPUNIT_ASSERT_NO_THROW(pls.validate(al)); + } + + // ------------------------------------------------------ + void test_check_AL_bad_size() { + // ------------------------------------------------------ + + std::vector<StorageType::TypeId> all_types; + all_types.push_back(StorageType::Int32); + all_types.push_back(StorageType::UInt32); + all_types.push_back(StorageType::UInt63); + all_types.push_back(StorageType::Float); + + RecordSpecification pls; + std::vector<StorageType::TypeId>::iterator i; + for(i = all_types.begin(); i != all_types.end(); ++i ) + pls.extend(StorageType::storageType(*i).name(),*i); + + coral::AttributeList al = Record( pls ).attributeList(); + al.extend("AnotherOne","double"); + + CPPUNIT_ASSERT_THROW(pls.validate(al), + RecordSpecificationWrongSize); + + } + + // ------------------------------------------------------ + void test_check_AL_bad_string_size() { + // ------------------------------------------------------ + + std::vector<StorageType::TypeId> all_types; + all_types.push_back(StorageType::String255); + all_types.push_back(StorageType::String4k); + all_types.push_back(StorageType::String64k); + all_types.push_back(StorageType::String16M); + + std::vector<StorageType::TypeId>::iterator i; + for(i = all_types.begin(); i != all_types.end(); ++i ){ + + RecordSpecification pls; + + pls.extend("S",*i); + + coral::AttributeList al = Record( pls ).attributeList(); + + al["S"].data<std::string>().append + (StorageType::storageType(*i).maxSize()+1,'x'); + + CPPUNIT_ASSERT_THROW(pls.validate(al), + StorageTypeInvalidValue); + + } + } + + // ------------------------------------------------------ + void test_check_AL_good_string_size() { + // ------------------------------------------------------ + + std::vector<StorageType::TypeId> all_types; + all_types.push_back(StorageType::String255); + all_types.push_back(StorageType::String4k); + all_types.push_back(StorageType::String64k); + all_types.push_back(StorageType::String16M); + + std::vector<StorageType::TypeId>::iterator i; + for(i = all_types.begin(); i != all_types.end(); ++i ){ + + RecordSpecification pls; + + pls.extend("S",*i); + + coral::AttributeList al = Record( pls ).attributeList(); + + al["S"].data<std::string>() + .append(StorageType::storageType(*i).maxSize(),'x'); + + CPPUNIT_ASSERT_NO_THROW(pls.validate(al)); + + } + + } + + // ------------------------------------------------------ + void test_check_AL_bad_UInt63() { + // ------------------------------------------------------ + RecordSpecification pls; + pls.extend("I", StorageType::UInt63); + + coral::AttributeList al = Record( pls ).attributeList(); + + al["I"].data<UInt63>() = 9223372036854775808ULL; + + CPPUNIT_ASSERT_THROW(pls.validate(al), + StorageTypeInvalidValue); + + } + + // ------------------------------------------------------ + void test_check_AL_good_UInt63() { + // ------------------------------------------------------ + RecordSpecification pls; + pls.extend("I", StorageType::UInt63); + + coral::AttributeList al = Record( pls ).attributeList(); + + al["I"].data<UInt63>() = 9223372036854775807ULL; + + CPPUNIT_ASSERT_NO_THROW(pls.validate(al)); + + } + + // ------------------------------------------------------ + void test_check_AL_unexpected_type() { + // ------------------------------------------------------ + RecordSpecification pls; + pls.extend( "A", cool::StorageType::UInt32 ); + pls.extend( "B", cool::StorageType::String4k ); + + coral::AttributeList al; + al.extend<cool::UInt32>("A"); + al.extend<float>("B"); + + CPPUNIT_ASSERT_THROW(pls.validate(al), + StorageTypeWrongCppType); + + } + + + // ------------------------------------------------------ + void test_encode_decode() { + // ------------------------------------------------------ + typedef std::pair<std::string,StorageType::TypeId> pair_type; + std::vector<pair_type> all_types; + + all_types.push_back(pair_type("Bool",StorageType::Bool)); + //all_types.push_back(pair_type("Char",StorageType::Char)); + all_types.push_back(pair_type("UChar",StorageType::UChar)); + all_types.push_back(pair_type("Int16",StorageType::Int16)); + all_types.push_back(pair_type("UInt16",StorageType::UInt16)); + all_types.push_back(pair_type("Int32",StorageType::Int32)); + all_types.push_back(pair_type("UInt32",StorageType::UInt32)); + all_types.push_back(pair_type("UInt63",StorageType::UInt63)); + all_types.push_back(pair_type("Int64",StorageType::Int64)); + //all_types.push_back(pair_type("UInt64",StorageType::UInt64)); + all_types.push_back(pair_type("Float",StorageType::Float)); + all_types.push_back(pair_type("Double",StorageType::Double)); + all_types.push_back(pair_type("String255",StorageType::String255)); + all_types.push_back(pair_type("String4k",StorageType::String4k)); + all_types.push_back(pair_type("String64k",StorageType::String64k)); + all_types.push_back(pair_type("String16M",StorageType::String16M)); + + RecordSpecification pls; + std::ostringstream expected; + + std::vector<pair_type>::iterator i; + for(i = all_types.begin(); i != all_types.end(); ++i ){ + pls.extend(i->first,i->second); + if (i != all_types.begin()) expected << ","; + expected << i->first << ":" + << StorageType::storageType(i->second).name(); + } + + CPPUNIT_ASSERT_EQUAL + ( expected.str(), RelationalDatabase::encodeRecordSpecification(pls) ); + + std::string pls2 = + RelationalDatabase::encodeRecordSpecification(pls); + + CPPUNIT_ASSERT_MESSAGE + ("encoded and decoded payloads do not match", + pls == RelationalDatabase::decodeRecordSpecification(pls2)); + + } + + // ------------------------------------------------------ + void test_decodeEmptySpec() { + // ------------------------------------------------------ + + std::string encodedSpec = ""; + RecordSpecification spec = + RelationalDatabase::decodeRecordSpecification(encodedSpec); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string( "RecordSpecification size" ), + (UInt32)0,spec.size() ); + } + + // Tests exception in decoding spec with no ":" colon + // (missing type - "name" instead of "name:type") + // ------------------------------------------------------ + void test_decodeNoColon() { + // ------------------------------------------------------ + CPPUNIT_ASSERT_THROW + ( RelationalDatabase::decodeRecordSpecification("I/Int32"), + RelationalException ); + } + + + // ------------------------------------------------------ + void test_decodeTrailingComma() { + // ------------------------------------------------------ + CPPUNIT_ASSERT_THROW + ( RelationalDatabase::decodeRecordSpecification("I:Int32,"), + RelationalException ); + } + + }; + +CPPUNIT_TEST_SUITE_REGISTRATION( PayloadSpecificationTest ); + +} + +COOLTEST_MAIN( PayloadSpecificationTest ) diff --git a/RelationalCool/tests/Performance/Benchmark.h b/RelationalCool/tests/Performance/Benchmark.h new file mode 100644 index 000000000..6f69b71cd --- /dev/null +++ b/RelationalCool/tests/Performance/Benchmark.h @@ -0,0 +1,52 @@ +/** + @file Benchmark.h + + @author Sven A. Schmidt + + @date 2004-08-19 +*/ + + +#ifndef BENCHMARK_H +#define BENCHMARK_H + +//#include <sys/time.h> +#include "boost/timer.hpp" + +#include <iostream> + +/// Utility class to benchmark code +/// +/// The current implementation has a resolution of seconds and measures +/// elapsed real time. +class Benchmark { + boost::timer m_timer; +public: + + /// Starts the timer + void start() { + m_timer.restart(); + } + + /// Stops the timer and returns the number of seconds since the timer + /// was started + double stop() { + return elapsed(); + } + + /// Returns the number of seconds since the timer was started + double elapsed() { + return m_timer.elapsed(); + } + +}; + +/* +inline ostream &operator<<( ostream &s, Benchmark &b ) { + s << "elapsed: " << b.elapsed() << " seconds"; + return s; +} +*/ + +#endif + diff --git a/RelationalCool/tests/Performance/performance_test.txt b/RelationalCool/tests/Performance/performance_test.txt new file mode 100644 index 000000000..2727fd3dc --- /dev/null +++ b/RelationalCool/tests/Performance/performance_test.txt @@ -0,0 +1,67 @@ +These are 'ballpark' figures. The benchmark measures real time, therefore the +tests are subject to additional load on the machine. They skew by +several seconds even under the same conditions on the same machine. Only use +these to monitor performance evolution, not for performance comparison. + +------------------------------------------------------------------------ + +2005-01-04, Powerbook sas (G4 1.5 GHz, 1GB RAM, Oracle 10 prerelease, -g) + +** writing 10k objects (150 bytes mixed) ** +sec total: 15 +obj/s: 666.667 +** reading 25k objects (150 bytes mixed) ** +read back 10000 objects +sec total: 26 +obj/s: 384.615 + +** writing 25k objects (20 floats) ** +wrote 25000 objects +sec total: 45 +obj/s: 555.556 +** reading 25k objects (20 floats) ** +read back 25000 objects +sec total: 85 +obj/s: 294.118 + +------------------------------------------------------------------------ + +2005-01-04, Powermac sas (G5 2GHz, 1GB RAM, Oracle 10 prerelease, -g) + +** writing 10k objects (150 bytes mixed) ** +sec total: 14 +obj/s: 714.286 +** reading 25k objects (150 bytes mixed) ** +read back 10000 objects +sec total: 20 +obj/s: 500 + +** writing 25k objects (20 floats) ** +wrote 25000 objects +sec total: 33 +obj/s: 757.576 +** reading 25k objects (20 floats) ** +read back 25000 objects +sec total: 63 +obj/s: 396.825 + +------------------------------------------------------------------------ + +2005-01-08, Powermac sas (G5 2GHz, 1GB RAM, Oracle 10 Production, -g) + +** writing 10k objects (150 bytes mixed) ** +sec total: 10 +obj/s: 1000 +** reading 25k objects (150 bytes mixed) ** +read back 10000 objects +sec total: 19 +obj/s: 526.316 + +** writing 25k objects (20 floats) ** +wrote 25000 objects +sec total: 32 +obj/s: 781.25 +** reading 25k objects (20 floats) ** +read back 25000 objects +sec total: 61 +obj/s: 409.836 diff --git a/RelationalCool/tests/Performance/test_Performance.cpp b/RelationalCool/tests/Performance/test_Performance.cpp new file mode 100644 index 000000000..281b7262e --- /dev/null +++ b/RelationalCool/tests/Performance/test_Performance.cpp @@ -0,0 +1,998 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT +/** + +@file test_Performance.cpp + +@author Sven A. Schmidt + +@date 2005-01-03 + +*/ + + +#include<cppunit/extensions/HelperMacros.h> + +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/Exception.h" + +#include "Benchmark.h" + +#include "src/CoralApplication.h" +#include "src/ProcMemory.h" + +#include "AttributeList/AttributeValueAccessor.h" +using coral::AttributeList; +using coral::AttributeListSpecification; +typedef boost::shared_ptr<AttributeListSpecification> SpecPtr; + +// include for 'sleep' (ORA-01466 workaround) +#include "src/sleep.h" + +#include <string> +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +#include <vector> +using std::vector; + +namespace cool { + +const char* COOLTESTDB = "COOLTESTDB"; + +// set this to true to have a quick run through all tests +// tests should initialize their iteration count like this: +// long iterations = quick ? 1 : 10000; +const bool quick = true; + +// uncomment this to enable memory profiling +//#define MEMTEST + + +/// Performace test class +class PerformanceTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( PerformanceTest ); + + CPPUNIT_TEST( test_bulk_rw_mixed ); + CPPUNIT_TEST( test_bulk_rw_mixed_MV ); + CPPUNIT_TEST( test_bulk_rw_mixed_MV_withHEAD ); + + CPPUNIT_TEST( test_bulk_w_mixed_multichannel ); + CPPUNIT_TEST( test_bulk_w_mixed_multichannel_update ); + CPPUNIT_TEST( test_bulk_w_mixed_multichannel_old ); + + CPPUNIT_TEST( test_bulk_rw_float_1 ); + CPPUNIT_TEST( test_bulk_rw_float_20 ); + CPPUNIT_TEST( test_bulk_rw_float_100 ); + CPPUNIT_TEST( test_bulk_rw_float_200 ); + + CPPUNIT_TEST( test_bulk_rw_string4kb_1 ); + CPPUNIT_TEST( test_bulk_rw_string4kb_100 ); + CPPUNIT_TEST( test_bulk_rw_string4kb_200 ); + + CPPUNIT_TEST( test_boost_shared_ptr ); + CPPUNIT_TEST( test_boost_shared_ptr_2 ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + AttributeListSpecification mixedPayloadSpec; + string connectString; + IDatabasePtr db; + + /// Tests boost::shared_ptr performance + void test_boost_shared_ptr_2() { + int nObjs = quick ? 1 : 1000 * 1000; + + cout << "\ntest_boost_shared_ptr_2" << endl; + + cout << "\nsingle object, referenced " << nObjs << " times" << endl; + + { + SpecPtr spec( new coral::AttributeListSpecification() ); + + Benchmark b, b_delete; + b.start(); + { + vector<SpecPtr> specs; + for ( int i = 0; i < nObjs; ++i ) { + specs.push_back( spec ); + } + b_delete.start(); + } + cout << "boost vector: " << b.stop() << endl; + cout << " delete: " << b_delete.stop() << endl; + } + + { + coral::AttributeListSpecification* spec + = new coral::AttributeListSpecification(); + + Benchmark b, b_delete; + b.start(); + { + vector<coral::AttributeListSpecification*> specs; + for ( int i = 0; i < nObjs; ++i ) { + specs.push_back( spec ); + } + b_delete.start(); + } + cout << "bare pointers: " << b.stop() << endl; + cout << " delete: " << b_delete.stop() << endl; + + delete spec; + } + + cout << "\n" << nObjs << " individual objects" << endl; + + { + Benchmark b, b_delete; + b.start(); + { + vector<SpecPtr> specs; + for ( int i = 0; i < nObjs; ++i ) { + SpecPtr spec( new coral::AttributeListSpecification() ); + specs.push_back( spec ); + } + b_delete.start(); + } + cout << "boost vector: " << b.stop() << endl; + cout << " delete: " << b_delete.stop() << endl; + } + + { + Benchmark b, b_delete; + b.start(); + { + vector<coral::AttributeListSpecification*> specs; + for ( int i = 0; i < nObjs; ++i ) { + coral::AttributeListSpecification* spec + = new coral::AttributeListSpecification(); + + specs.push_back( spec ); + } + b_delete.start(); + for ( vector<coral::AttributeListSpecification*>::iterator + spec = specs.begin(); + spec != specs.end(); + ++spec ) { + delete *spec; + } + } + cout << "bare pointers: " << b.stop() << endl; + cout << " delete: " << b_delete.stop() << endl; + } + + + } + + + //---------------------------------------------------------------------------- + + boost::shared_ptr<coral::AttributeList> + copyAttributeList( const coral::AttributeList& list ) + { + + // Instantiate a new AttributeListSpecification by performing + // a deep copy of the individual Attribute specifications + const coral::AttributeListSpecification& + spec = list.attributeListSpecification(); + boost::shared_ptr<coral::AttributeListSpecification> + newSpec( new coral::AttributeListSpecification() ); + coral::AttributeListSpecification::const_iterator itSpec; + for ( itSpec = spec.begin(); itSpec != spec.end(); ++itSpec ) { + newSpec->push_back( itSpec->name(), itSpec->type_name() ); + } + + // Instantiate a new AttributeList owning the new specification + // Copy the individual Attribute values into the new List + return copyAttributeList( list, newSpec ); + + } + + //---------------------------------------------------------------------------- + + boost::shared_ptr<coral::AttributeList> copyAttributeList + ( const coral::AttributeList& oldList, + boost::shared_ptr<coral::AttributeListSpecification>& specPtr ) + { + // Instantiate a new AttributeList owning the specification + boost::shared_ptr<coral::AttributeList> + newList( new coral::AttributeList( specPtr ) ); + + coral::AttributeList::const_iterator oldAttr; + coral::AttributeList::iterator newAttr = newList->begin(); + for ( oldAttr = oldList.begin(); + oldAttr != oldList.end(); + oldAttr++, newAttr++ ) { + coral::AttributeValueAccessor( *newAttr ).setValueFromData + ( coral::AttributeValueAccessor( *oldAttr ).getMemoryAddress() ); + } + + return newList; + + } + + //---------------------------------------------------------------------------- + + + void test_boost_shared_ptr() { + cout << "\ntest_boost_shared_ptr_2" << endl; + + int * i; + cout << "size of *int: " + << sizeof(i) << endl; + + cout << "size of boost::shared_ptr<coral::AttributeList>: " + << sizeof(boost::shared_ptr<coral::AttributeList>) << endl; + + cout << "size of boost::shared_ptr<coral::AttributeListSpecification>: " + << sizeof(boost::shared_ptr<coral::AttributeListSpecification>) << endl; + + cout << "size of coral::AttributeList: " + << sizeof(coral::AttributeList) << endl; + + cout << "size of coral::AttributeListSpecification: " + << sizeof(coral::AttributeListSpecification) << endl; + + + int nRows = quick ? 1 : 10 * 1000; + + Benchmark b1, b1_delete; + b1.start(); + { + // copy mixedPayloadSpec to a shared_ptr + boost::shared_ptr<coral::AttributeListSpecification> + spec( new coral::AttributeListSpecification() ); + for ( coral::AttributeListSpecification::const_iterator + i = mixedPayloadSpec.begin(); + i != mixedPayloadSpec.end(); + ++i ) { + spec->push_back( i->name(), i->type_name() ); + } + + std::vector< boost::shared_ptr<coral::AttributeList> > objs; + for ( int i = 0; i < nRows; ++i ) { + coral::AttributeList payload( mixedPayload( i ) ); + objs.push_back( copyAttributeList( payload, spec ) ); + } + + b1_delete.start(); + } + cout << "new version: " << b1.stop() << endl; + cout << " delete: " << b1_delete.stop() << endl; + + Benchmark b2, b2_delete; + b2.start(); + { + std::vector< boost::shared_ptr<coral::AttributeList> > objs; + for ( int i = 0; i < nRows; ++i ) { + coral::AttributeList payload( mixedPayload( i ) ); + objs.push_back( copyAttributeList( payload ) ); + } + + b2_delete.start(); + } + cout << "old version: " << b2.stop() << endl; + cout << " delete: " << b2_delete.stop() << endl; + + } + + + void test_bulk_rw_string4kb_1() { + int nFields = 1; + long nObjs = quick ? 1 : 25000; + rw_string4kb( nFields, nObjs ); + } + + void test_bulk_rw_string4kb_100() { + int nFields = 100; + long nObjs = quick ? 1 : 200; // reduced row count, each obj is 400kB + // 25k objects would allocate 10GB of memory + // could run several batches instead + rw_string4kb( nFields, nObjs ); + } + + void test_bulk_rw_string4kb_200() { + int nFields = 200; + long nObjs = quick ? 1 : 100; // reduced row count, each obj is 400kB + // 25k objects would allocate 20GB of memory + // could run several batches instead + rw_string4kb( nFields, nObjs ); + } + + + void rw_string4kb( int nFields, long nObjs ) { + + SpecPtr spec = uniformSpec( nFields, "string" ); + AttributeList payload = string4kbPayload( spec ); + + IFolderPtr folder = db->createFolder( "/myfolder", *spec ); + + mysleep(); + + { + Benchmark b; + b.start(); + + folder->setupStorageBuffer(); + + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, payload ); + } + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs << " objects (" + << nFields << " 4kb strings) **" << endl; + cout << "wrote " << nObjs << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + + + { + Benchmark b; + b.start(); + + IObjectIteratorPtr objs = + folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0, "" ); + + long nReadObjects = objs->size(); + + double secElapsed = b.stop(); + + cout << "** reading " << nObjs << " objects (" + << nFields << " 4kb strings) **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + + } + + + + + void test_bulk_rw_float_1() { + int nFields = 1; + long nObjs = quick ? 1 : 25000; + rw_floats( nFields, nObjs ); + } + + void test_bulk_rw_float_100() { + int nFields = 100; + long nObjs = quick ? 1 : 25000; + rw_floats( nFields, nObjs ); + } + + void test_bulk_rw_float_200() { + int nFields = 200; + long nObjs = quick ? 1 : 25000; + rw_floats( nFields, nObjs ); + } + + void test_bulk_rw_float_20() { + int nFields = 20; + long nObjs = quick ? 1 : 25000; + rw_floats( nFields, nObjs ); + } + + + void rw_floats( int nFields, long nObjs ) { + + SpecPtr spec = uniformSpec( nFields, "float" ); + IFolderPtr folder = db->createFolder( "/myfolder", *spec ); + + { + Benchmark b; + b.start(); + + folder->setupStorageBuffer(); + + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, floatPayload( i, spec ) ); + } + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs << " objects (" + << nFields << " floats) **" << endl; + cout << "wrote " << nObjs << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + + + { + Benchmark b; + b.start(); + + IObjectIteratorPtr objs = + folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0, "" ); + + long nReadObjects = objs->size(); + + double secElapsed = b.stop(); + + cout << "** reading " << nObjs << " objects (" + << nFields << " floats) **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + + } + + + /// Tests writing mixed payloads in MULTI_VERSION mode + /// This case adds a persistent object to the HEAD before executing the + /// bulk storage + void test_bulk_rw_mixed_MV_withHEAD() { + + Benchmark fullRun; + fullRun.start(); + { + +#ifdef MEMTEST + ProcMemory* mem = new ProcMemory(); + std::cout << "START of TEST" << std::endl; mem->printVm(); +#endif + + long nObjs = quick ? 1 : 10 * 100; + + { + IFolderPtr folder = db->createFolder( "/myfolder", + mixedPayloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + mysleep(); + + Benchmark b; + b.start(); + + // add one persistent HEAD object first + folder->storeObject( 0, ValidityKeyMax, mixedPayload( 0 ) ); + + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, i+1, mixedPayload( i ) ); + } + +#ifdef MEMTEST + std::cout << "Before flushing" << std::endl; mem->printVm(); +#endif + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs + << " objects (150 bytes mixed, MULTI_VERSION mode w/HEAD) **" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + +#ifdef MEMTEST + std::cout << "After flushing" << std::endl; mem->printVm(); +#endif + + Benchmark bFull; + bFull.start(); + + if (0) { // reading not implemented yet + IFolderPtr folder = db->getFolder( "/myfolder" ); + + Benchmark b; + b.start(); + + IObjectIteratorPtr objs = + folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0, "" ); + +#ifdef MEMTEST + std::cout << "After reading" << std::endl; mem->printVm(); +#endif + + long nReadObjects = objs->size(); + + double secElapsed = b.stop(); + + cout << "** reading " << nObjs + << " objects (150 bytes mixed, MULTI_VERSION mode w/HEAD) **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + + cout << "sec total (INCLUDING DELETE): " << bFull.stop() << endl; + +#ifdef MEMTEST + std::cout << "END OF TEST" << std::endl; mem->printVm(); +#endif + + } + cout << "sec total (full test): " << fullRun.stop() << endl; + + } + + + + /// Tests writing mixed payloads in MULTI_VERSION mode + void test_bulk_rw_mixed_MV() { + + Benchmark fullRun; + fullRun.start(); + { + +#ifdef MEMTEST + ProcMemory* mem = new ProcMemory(); + std::cout << "START of TEST" << std::endl; mem->printVm(); +#endif + + long nObjs = quick ? 1 : 10 * 100; + + { + IFolderPtr folder = db->createFolder( "/myfolder", + mixedPayloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + mysleep(); + + Benchmark b; + b.start(); + + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, i+1, mixedPayload( i ) ); + } + +#ifdef MEMTEST + std::cout << "Before flushing" << std::endl; mem->printVm(); +#endif + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs + << " objects (150 bytes mixed, MULTI_VERSION mode) **" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + +#ifdef MEMTEST + std::cout << "After flushing" << std::endl; mem->printVm(); +#endif + + Benchmark bFull; + bFull.start(); + + if (0) { // reading not implemented yet + IFolderPtr folder = db->getFolder( "/myfolder" ); + + Benchmark b; + b.start(); + + IObjectIteratorPtr objs = + folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0, "" ); + +#ifdef MEMTEST + std::cout << "After reading" << std::endl; mem->printVm(); +#endif + + long nReadObjects = objs->size(); + + double secElapsed = b.stop(); + + cout << "** reading " << nObjs + << " objects (150 bytes mixed, MULTI_VERSION mode) **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + + cout << "sec total (INCLUDING DELETE): " << bFull.stop() << endl; + +#ifdef MEMTEST + std::cout << "END OF TEST" << std::endl; mem->printVm(); +#endif + + } + cout << "sec total (full test): " << fullRun.stop() << endl; + + } + + + /// Tests the performance of the multichannel bulk storage + /// with existing data in the channels: This will require IOV updates + /// in those channels. Compare performance to test_bulk_w_mixed_multichannel. + void test_bulk_w_mixed_multichannel_update() { + + long nObjs = quick ? 1 : 10 * 1000; + + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + mysleep(); + + // Preload data into channels + { + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( 0, ValidityKeyMax, mixedPayload( i ), i ); + } + folder->flushStorageBuffer(); + } + + { + +#ifdef MEMTEST + ProcMemory* mem = new ProcMemory(); + std::cout << "START of TEST" << std::endl; mem->printVm(); +#endif + + { + Benchmark b; + b.start(); + + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( 5, ValidityKeyMax, mixedPayload( i ), i ); + } + +#ifdef MEMTEST + std::cout << "Before flushing" << std::endl; mem->printVm(); +#endif + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs << " objects (150 bytes mixed) **" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + +#ifdef MEMTEST + std::cout << "After flushing" << std::endl; mem->printVm(); +#endif + + } + } + + + /// Tests the performance of the multichannel bulk storage (compare to + /// write performance of test_bulk_rw_mixed) + void test_bulk_w_mixed_multichannel() { + + { + +#ifdef MEMTEST + ProcMemory* mem = new ProcMemory(); + std::cout << "START of TEST" << std::endl; mem->printVm(); +#endif + + long nObjs = quick ? 1 : 10 * 1000; + + { + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + mysleep(); + + Benchmark b; + b.start(); + + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, mixedPayload( i ), i ); + } + +#ifdef MEMTEST + std::cout << "Before flushing" << std::endl; mem->printVm(); +#endif + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs << " objects (150 bytes mixed) **" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + +#ifdef MEMTEST + std::cout << "After flushing" << std::endl; mem->printVm(); +#endif + + } + } + + + + /// Tests the performance of the multichannel bulk storage in the workaround + /// mode of the 'old' implementation (i.e. prior to the multi channel + /// extension) + void test_bulk_w_mixed_multichannel_old() { + + long nObjs = quick ? 1 : 10 * 1000; + + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + { + for ( long i = 0; i < nObjs; ++i ) { + folder->setupStorageBuffer(); + folder->storeObject( (ValidityKey)0, ValidityKeyMax, + mixedPayload( i ), i ); + folder->flushStorageBuffer(); + } + } + +#ifdef MEMTEST + ProcMemory* mem = new ProcMemory(); + std::cout << "START of TEST" << std::endl; mem->printVm(); +#endif + + { + Benchmark b; + b.start(); + + for ( long i = 0; i < nObjs; ++i ) { + folder->setupStorageBuffer(); + folder->storeObject( (ValidityKey)5, ValidityKeyMax, + mixedPayload( i ), i ); + folder->flushStorageBuffer(); + } + +#ifdef MEMTEST + std::cout << "Before flushing" << std::endl; mem->printVm(); +#endif + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs << " objects (150 bytes mixed) **" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + +#ifdef MEMTEST + std::cout << "After flushing" << std::endl; mem->printVm(); +#endif + + } + + + + void test_bulk_rw_mixed() { + + Benchmark fullRun; + fullRun.start(); + { + +#ifdef MEMTEST + ProcMemory* mem = new ProcMemory(); + std::cout << "START of TEST" << std::endl; mem->printVm(); +#endif + + long nObjs = quick ? 1 : 10 * 1000; + + { + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + mysleep(); + + Benchmark b; + b.start(); + + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, mixedPayload( i ) ); + } + +#ifdef MEMTEST + std::cout << "Before flushing" << std::endl; mem->printVm(); +#endif + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs << " objects (150 bytes mixed) **" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + +#ifdef MEMTEST + std::cout << "After flushing" << std::endl; mem->printVm(); +#endif + + Benchmark bFull; + bFull.start(); + + { + IFolderPtr folder = db->getFolder( "/myfolder" ); + + Benchmark b; + b.start(); + + IObjectIteratorPtr objs = + folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0, "" ); + +#ifdef MEMTEST + std::cout << "After reading" << std::endl; mem->printVm(); +#endif + + long nReadObjects = objs->size(); + + double secElapsed = b.stop(); + + cout << "** reading " << nObjs << " objects (150 bytes mixed) **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + + cout << "sec total (INCLUDING DELETE): " << bFull.stop() << endl; + +#ifdef MEMTEST + std::cout << "END OF TEST" << std::endl; mem->printVm(); +#endif + + } + cout << "sec total (full test): " << fullRun.stop() << endl; + + } + + + + + /// Creates a dummy payload AttributeList for a given index + AttributeList mixedPayload( int index ) { + AttributeList payload( mixedPayloadSpec ); + payload["I"].setValue<int>( index ); + stringstream s; + s << "Object " << index; + payload["S"].setValue<string>( s.str() ); + payload["X0"].setValue<float>( (float)(index/1000.) ); + payload["X1"].setValue<float>( (float)(index/1000.) ); + payload["X2"].setValue<float>( (float)(index/1000.) ); + payload["X3"].setValue<float>( (float)(index/1000.) ); + payload["X4"].setValue<float>( (float)(index/1000.) ); + payload["X5"].setValue<float>( (float)(index/1000.) ); + payload["X6"].setValue<float>( (float)(index/1000.) ); + payload["X7"].setValue<float>( (float)(index/1000.) ); + payload["X8"].setValue<float>( (float)(index/1000.) ); + payload["X9"].setValue<float>( (float)(index/1000.) ); + payload["P"].setValue<string>( "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + ); + return payload; + } + + + /// Creates a uniform payload specification for nFields fields + SpecPtr uniformSpec( int nFields, const string & type ) { + SpecPtr spec( new AttributeListSpecification() ); + for ( int i = 0; i < nFields; ++i ) { + stringstream s; + s << "X" << i; + spec->push_back( s.str(), type ); + } + return spec; + } + + + /// Creates a dummy 4kB string AttributeList + AttributeList string4kbPayload( SpecPtr & spec ) { + stringstream payloadString; + int bytes = 4000; + for ( int i = 0; i < bytes; ++i ) payloadString << "a"; + + int nFields = spec->size(); + AttributeList payload( spec ); + for ( int i = 0; i < nFields; ++i ) { + stringstream s; + s << "X" << i; + payload[ s.str() ].setValue<string>( payloadString.str() ); + } + return payload; + } + + + /// Creates a dummy float AttributeList for a given index + AttributeList floatPayload( int index, SpecPtr & spec ) { + int nFields = spec->size(); + AttributeList payload( spec ); + for ( int i = 0; i < nFields; ++i ) { + stringstream s; + s << "X" << i; + payload[ s.str() ].setValue<float>( (float)(index/1000.) ); + } + return payload; + } + + + void mysleep() { + const int sleep_timeout = 0; + if ( sleep_timeout > 0 ) { + cout << "temporary 'sleep()' to work aound ORA-01466 problem" << endl; + cool::sleep(sleep_timeout); + } + } + + + void setUp() { + if ( mixedPayloadSpec.size() == 0 ) { + mixedPayloadSpec.push_back("I","int"); + mixedPayloadSpec.push_back("S","string"); + mixedPayloadSpec.push_back("X0","float"); + mixedPayloadSpec.push_back("X1","float"); + mixedPayloadSpec.push_back("X2","float"); + mixedPayloadSpec.push_back("X3","float"); + mixedPayloadSpec.push_back("X4","float"); + mixedPayloadSpec.push_back("X5","float"); + mixedPayloadSpec.push_back("X6","float"); + mixedPayloadSpec.push_back("X7","float"); + mixedPayloadSpec.push_back("X8","float"); + mixedPayloadSpec.push_back("X9","float"); + mixedPayloadSpec.push_back("P","string"); + } + + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + cout << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << endl; + cout << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << endl; + cout << "Aborting test" << endl; + exit(-1); + } + + static CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + + mysleep(); + } + + void tearDown() { + db.reset(); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( PerformanceTest ); + +} // namespace + +// sas: This file is from the OPAL package I believe. It allows for +// shorter test classes and prepares the test class for OPAL +#include<CppUnit_testdriver.icpp> + + +#endif // NOPORT diff --git a/RelationalCool/tests/PerformanceAV/README.Performance b/RelationalCool/tests/PerformanceAV/README.Performance new file mode 100644 index 000000000..20bca538e --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/README.Performance @@ -0,0 +1,242 @@ +-------------------------- +ServerCache (31-Jan-2005) +-------------------------- + +Only reading, 100k mixed rows (Oracle table not yet analyzed). +This is the same exact table used the next day for 10k tests. +The version of the software is slightly older but the results are firm. + +Two interesting points tested: +- is there any effect from server-side in-memory caching? +- what is the maximum perfromance that can be reached using Benthic/mysql? + +Typical numbers for both Oracle and MySQL: +~100 seconds to retrieve 100k rows +(~40 seconds from fetching, ~60 seconds from client side handling). + +Results for server-side caching +(this is achieved by shutting down and restarting the Oracle +or MySQL database before running the test: if there is any +in-memory cache, this is emptied at server restart) +- No effect observed! Out of the ~100 seconds, the reading from disk + of the ~30MB data for 100k rows takes a fraction of a second. +- In Oracle, the trace file confirms that data need to be read + from disk the first time the test is executed. + +Results for the comparison COOL to Benthic for Oracle +- Benthic takes approximately ~5 seconds on my Windows 500MB memory PC. + The trace file shows that the server returns the query in 1.5 seconds! +- Something very weird goes on inside the SQL processing within COOL/RAL: + not only it takes ~40 seconds to return the query, but especially + the number of rows processed by the server is 195k instead of 100k!!! + This was first observed thanks to help from Bjorn. +- THIS SHOWS THAT THE RAL PROCESSING COULD GO DOWN FROM 40 to ~5 SECONDS. + +Results for the comparison COOL to mysql tool for MySQL +- The mysql tool takes approximately ~7.5 seconds (2.5 seconds user time + plus 5 seconds idle/network time), which is similar to Benthic/Oracle +- Again the numbers observed for COOL are ~40 seconds for the RAL fetching, + plus ~60 seconds overhead from COOL. + +-------------------------- +TestNewCopy (01-Feb-2005) +-------------------------- + +Only reading, 10k mixed rows, on a table not yet analyzed. +Test done for Oracle using cooldb2. + +Typical numbers for Oracle: +~10 seconds to retrieve 10k rows +(~4 seconds from fetching, ~6 seconds from client side handling). + +Compare the "old" copyAttributeList algorithm to Sven's "new" +copyAttributeList algorithm that takes an AttributeListSpecification +shared pointer as extra argument. + +Very strange results: +- On my private RH73 node (500MB memory) and on lxplus7 (1GB memory), + the net result is slower because deleting objects wrapped with + boost shared pointers takes very long (the effect is devastating + for 100k rows - not studied here -, it takes very very long). + That is to say, the ~10 seconds increases to ~14 seconds. +- On lxplus (SLC with 2GB memory), the net results is faster. Deleting + takes a negligible time, the copying itself is faster. This is in line + with what originally observed by Sven. +- The memory usage is negligible for both cases. + +CONCLUSION: For the moment, keep the old algorithm. +The use of boost pointers and the performance implications +need to be better understood. + +-------------------------- +TestRalOnly (01-Feb-2005) +-------------------------- + +Only reading, 10k mixed rows, on a table not yet analyzed. +Test done for Oracle using cooldb2. + +Typical numbers for Oracle: +~10 seconds to retrieve 10k rows +(~4 seconds from fetching, ~6 seconds from client side handling). + +Switch off all internal COOL data handling, measure the +intrinsic RAL performance. + +Results: +- The COOL overhead is large, more than 60%. Work is needed + to reduce this significantly. +- The RAL numbers are only 40% of the total, but may still be + significant in absolute terms (when compared to Benthic, for + instance - for which numbers are not given here). + +In other words: the ~4 seconds inside the "fetch" portion are +essentially dictated by RAL and not affected by COOL, while the +remaining ~6 seconds in all other parts are indeed a COOL-only overhead. + +----------------------------------- +TestRalOnly (01-Feb-2005) ANALYZED +----------------------------------- + +The test was repeated after analyzing the table. + +Good point: the correct execution plan is used +(see the trace files filtered through tkprof). +QUESTION: why is it necessary to analyze the table? + +No improvement in time performance was observed, however. +This is interesting because it means that also the +results of previous tests (eg vs Benthic) can be trusted +even if the wrong execution plan was used. + +---------------------------- +TestShareData (01-Feb-2005) +---------------------------- + +Only reading, 10k mixed rows, on a table previously analyzed. +Test done for Oracle using cooldb2. + +The previous tests wre using COOL_0_0_3-pre1-alpha. +In COOL_0_0_3-pre1-beta I just changed the interface to use iterators again. +This test uses COOL_0_0_3-pre1-gamma. + +The tested feature is now the default: copy attributes using +shareData() instead of the setValueAsString() method. +This dramatically improves the COOL performance. +The COOL overhead is reduced by a factor 3! +Thanks to Ioannis who originally mentioned copyData()! + +Typical numbers for Oracle: +From ~10 down to ~6 seconds for retrieving 10k rows +(~4 seconds from fetching remains unchanged and is now the bottleneck, +from ~6 seconds down to ~2 seconds for client side handling). + +THE INTRINSIC PERFORMANCE FROM RAL IS NOW THE BOTTLENECK (~70% TOTAL). + +Note also that the use of shareData() reduces memory usage by a factor 2. + +------------------------------------ +TestScrollableCursors (02-Feb-2005) +------------------------------------ + +Only reading, 10k mixed rows, on a table previously analyzed. +Test done for Oracle using cooldb2. + +No changes to the COOL code. +These tests are included in version tagged as COOL_0_0_3-pre1-delta. + +After discussing with Ioannis about the weird tkprof output from RAL, +he suggested to disable scrollable cursors in RAL. +Code changes with respect to POOL_2_0_0-iota: + diff -r1.5 OracleCursor.cpp + 19c19,20 + < if ( ! ( m_statement.execute( true ) ) ) { + --- + > bool scrollableCursors = getenv( "RAL_SCROLLABLECURSORS" ); + > if ( ! ( m_statement.execute( scrollableCursors ) ) ) { + 47c48,49 + < if ( ! ( m_statement.execute( true ) ) ) { + --- + > bool scrollableCursors = getenv( "RAL_SCROLLABLECURSORS" ); + > if ( ! ( m_statement.execute( scrollableCursors ) ) ) { + +The tested feature is now the default in this private version of POOL: +queries return cursors that are not backwards-scrollable +(they can only be looped on in the forward direction). + +This dramatically improves the RAL performance by a factor 5! +More importantly, the CPU consumption on the server goes down +by a factor 20 (!!) and the tkprof output looks much better, only 10k +rows are analyzed if 10k rows are returned, just like in Benthic. + +This means that there are now good prospects to further improve +COOL/RAL performance by improving the client side data manipulation. + +Typical numbers for Oracle: +From ~6 seconds down to ~3.8 seconds for retrieving 10k rows +(~4 seconds from fetching goes down to ~0.8 seconds in RAL, +~3 seconds for COOL client side handling remains unchanged). + +THE COOL OVERHEAD IS NOW AGAIN THE BOTTLENECK (~80% TOTAL). + +Note also that the .trc files on the server +(from which the tkprof .prf files are produced) +have roughly half the size than with scrollable cursors. + +Thanks a lot to Ioannis for the quick and efficient help!! + +---------------------------- +TestShareData (02-Feb-2005) +---------------------------- + +Ooops. The use of shareData() is much faster but it does not work! +Thanks to Marco Clemencic for pointing this out. +Essentially all objects in the iterator end up having the same data. + +This is now shown in the output of the test. +I rerun all tests using COOL_0_0_3-pre1-epsilon and commit this test again. + +By the way, from COOL_0_0_3-pre1-epsilon onwards POOL has been +updated from POOL_2_0_0-iota to POOL_2_0_0-kappa. + +----------------------------------------- +TestAttributeValueAccessor (02-Feb-2005) +----------------------------------------- + +Only reading, 10k mixed rows, on a table previously analyzed. +Test done for Oracle using cooldb2. + +This test is commiteed as COOL_0_0_3-pre1-zeta. + +The tested feature is now the default: copy attributes using +the AttributeValueAccessor instead of the setValueAsString() method. + +The performance is equivalent to that observed +using the (wrong) shareData() method. +This dramatically improves the COOL performance +with respect to the setValueAsString solution, by a factor 3. + +And especially this works (the attribute data are correct!). + +Thanks to Ioannis who suggested the complete AttributeValueAccessor recipe! + +Typical numbers for Oracle are now +~3.8 seconds for retrieving 10k rows +(~0.8 seconds from fetching in RAL, +~3 seconds for client side handling). + +THE COOL OVERHEAD IS NOW AGAIN THE BOTTLENECK (~80% TOTAL). + +Note also that, in contrast to what happened with shareData(), +the usage of the AttributeValueAccessor does not reduce memory usage. + +---------------------------- +Minor changes (02-Feb-2005) +---------------------------- + +Cleaned up the copyAttributeList implementation using two iterators +as suggested by Ioannis. No major performance improvement. + +Committed code and tests as the final COOL_0_0_3-pre1. + + + diff --git a/RelationalCool/tests/PerformanceAV/README.sqlTrace b/RelationalCool/tests/PerformanceAV/README.sqlTrace new file mode 100644 index 000000000..67e8acd01 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/README.sqlTrace @@ -0,0 +1,5 @@ +# Copy trc files from /ORA/dbs00/oracle/admin/cooldb2/udump/ +# Use level 12 SQL_TRACE + +tkprof file.trc file.prf sort=exeela,fchela + diff --git a/RelationalCool/tests/PerformanceAV/ServerCache/100k-my-cool-first.out b/RelationalCool/tests/PerformanceAV/ServerCache/100k-my-cool-first.out new file mode 100644 index 000000000..608e6b98e --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/ServerCache/100k-my-cool-first.out @@ -0,0 +1,91 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'mysql://lxb0771;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'mysql://lxb0771;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/odbc/ODBCDriverSelector Info ODBC Drivers found: +POOL/odbc/ODBCDriverSelector Info [MyODBC] +POOL/odbc/ODBCDriverSelector Info Description = MySQL ODBC 3.51 driver for Linux; +POOL/odbc/ODBCDriverSelector Info Driver = libmyodbc3.so; +POOL/odbc/ODBCDriverSelector Info FileUsage = 1; +POOL/odbc/ODBCDriverSelector Info [MySQL] +POOL/odbc/ODBCDriverSelector Info Description = MySQL ODBC 3.51 driver for Linux; +POOL/odbc/ODBCDriverSelector Info Driver = libmyodbc3.so; +POOL/odbc/ODBCDriverSelector Info FileUsage = 1; +POOL/RelationalPlugins/mysql/odbc Info Connection URI : mysql://lxb0771/AVALASSI +POOL/RelationalPlugins/mysql/odbc Info Connection string: DRIVER={MySQL};SERVER=lxb0771;DATABASE=AVALASSI;USER=avalassi;PASSWORD=andrea;OPTION=0; +POOL/RelationalPlugins/mysql/odbc Info Connected via MySQL driver +POOL/RelationalPlugins/mysql/odbc Info Connected using full connection string: DRIVER={MySQL ODBC 3.51 Driver};DB=AVALASSI;SERVER=lxb0771;UID=avalassi;PASSWORD=andrea;PORT=3306;SOCKET=;OPTION=0;STMT=; +2Preparing statement: SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES" +2Preparing statement: SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=? +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +2Preparing statement: SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=? AND "IOV_SINCE">=? AND "IOV_UNTIL"<=? ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.060 +/- 0.060 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.060 +/- 0.060 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 6.610 +/- 6.610 s +Total User Time : 0.210 +/- 0.210 s +Total System Time: 0.470 +/- 0.470 s +Total Idle Time : 5.930 +/- 5.930 s +----- 3.FetchRows-------------- : ( n=100001 ) +Total Real Time : 33.520 +/- 0.106 s +Total User Time : 18.140 +/- 0.057 s +Total System Time: 15.790 +/- 0.050 s +Total Idle Time : -0.390 +/- -0.001 s +----- 4.CopyAttributeList------ : ( n=100000 ) +Total Real Time : 61.080 +/- 0.193 s +Total User Time : 60.430 +/- 0.191 s +Total System Time: 0.570 +/- 0.002 s +Total Idle Time : 0.160 +/- 0.001 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 102.670 +/- 102.670 s +Total User Time : 79.750 +/- 79.750 s +Total System Time: 16.910 +/- 16.910 s +Total Idle Time : 6.010 +/- 6.010 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 102.670 +/- 102.670 s +Total User Time : 79.750 +/- 79.750 s +Total System Time: 16.910 +/- 16.910 s +Total Idle Time : 6.010 +/- 6.010 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 9.860 +/- 9.860 s +Total User Time : 9.410 +/- 9.410 s +Total System Time: 0.170 +/- 0.170 s +Total Idle Time : 0.280 +/- 0.280 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 1.610 +/- 1.610 s +Total User Time : 1.570 +/- 1.570 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.040 +/- 0.040 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 114.140 +/- 114.140 s +Total User Time : 90.730 +/- 90.730 s +Total System Time: 17.080 +/- 17.080 s +Total Idle Time : 6.330 +/- 6.330 s +** reading 100000 objects (150 bytes mixed) ** +read back 100000 objects +sec total: 114.161 +obj/s: 875.956 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 115.409 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'mysql://lxb0771;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/mysql/odbc Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'mysql://lxb0771;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/ServerCache/100k-my-cool-next.out b/RelationalCool/tests/PerformanceAV/ServerCache/100k-my-cool-next.out new file mode 100644 index 000000000..14b72b978 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/ServerCache/100k-my-cool-next.out @@ -0,0 +1,91 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'mysql://lxb0771;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'mysql://lxb0771;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/odbc/ODBCDriverSelector Info ODBC Drivers found: +POOL/odbc/ODBCDriverSelector Info [MyODBC] +POOL/odbc/ODBCDriverSelector Info Description = MySQL ODBC 3.51 driver for Linux; +POOL/odbc/ODBCDriverSelector Info Driver = libmyodbc3.so; +POOL/odbc/ODBCDriverSelector Info FileUsage = 1; +POOL/odbc/ODBCDriverSelector Info [MySQL] +POOL/odbc/ODBCDriverSelector Info Description = MySQL ODBC 3.51 driver for Linux; +POOL/odbc/ODBCDriverSelector Info Driver = libmyodbc3.so; +POOL/odbc/ODBCDriverSelector Info FileUsage = 1; +POOL/RelationalPlugins/mysql/odbc Info Connection URI : mysql://lxb0771/AVALASSI +POOL/RelationalPlugins/mysql/odbc Info Connection string: DRIVER={MySQL};SERVER=lxb0771;DATABASE=AVALASSI;USER=avalassi;PASSWORD=andrea;OPTION=0; +POOL/RelationalPlugins/mysql/odbc Info Connected via MySQL driver +POOL/RelationalPlugins/mysql/odbc Info Connected using full connection string: DRIVER={MySQL ODBC 3.51 Driver};DB=AVALASSI;SERVER=lxb0771;UID=avalassi;PASSWORD=andrea;PORT=3306;SOCKET=;OPTION=0;STMT=; +2Preparing statement: SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES" +2Preparing statement: SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=? +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +2Preparing statement: SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=? AND "IOV_SINCE">=? AND "IOV_UNTIL"<=? ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.130 +/- 0.130 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.120 +/- 0.120 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 6.080 +/- 6.080 s +Total User Time : 0.200 +/- 0.200 s +Total System Time: 0.490 +/- 0.490 s +Total Idle Time : 5.390 +/- 5.390 s +----- 3.FetchRows-------------- : ( n=100001 ) +Total Real Time : 33.180 +/- 0.105 s +Total User Time : 16.830 +/- 0.053 s +Total System Time: 15.650 +/- 0.049 s +Total Idle Time : 1.020 +/- 0.003 s +----- 4.CopyAttributeList------ : ( n=100000 ) +Total Real Time : 59.960 +/- 0.190 s +Total User Time : 60.460 +/- 0.191 s +Total System Time: 0.440 +/- 0.001 s +Total Idle Time : -0.970 +/- -0.003 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 100.680 +/- 100.680 s +Total User Time : 78.420 +/- 78.420 s +Total System Time: 16.660 +/- 16.660 s +Total Idle Time : 5.600 +/- 5.600 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 100.690 +/- 100.690 s +Total User Time : 78.420 +/- 78.420 s +Total System Time: 16.660 +/- 16.660 s +Total Idle Time : 5.610 +/- 5.610 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 10.110 +/- 10.110 s +Total User Time : 9.470 +/- 9.470 s +Total System Time: 0.200 +/- 0.200 s +Total Idle Time : 0.440 +/- 0.440 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 1.570 +/- 1.570 s +Total User Time : 1.550 +/- 1.550 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.020 +/- 0.020 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 112.370 +/- 112.370 s +Total User Time : 89.440 +/- 89.440 s +Total System Time: 16.860 +/- 16.860 s +Total Idle Time : 6.070 +/- 6.070 s +** reading 100000 objects (150 bytes mixed) ** +read back 100000 objects +sec total: 112.375 +obj/s: 889.881 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 113.62 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'mysql://lxb0771;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/mysql/odbc Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'mysql://lxb0771;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-benthic-first.prf b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-benthic-first.prf new file mode 100644 index 000000000..abe7a7fb8 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-benthic-first.prf @@ -0,0 +1,680 @@ + +TKPROF: Release 10.1.0.2.0 - Production on Mon Jan 31 11:46:22 2005 + +Copyright (c) 1982, 2004, Oracle. All rights reserved. + +Trace file: benthic1.trc +Sort options: exeela fchela +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT * FROM COOLTEST_F0001_IOVS +WHERE "CHANNEL_ID"=0 AND "IOV_SINCE">=0 AND "IOV_UNTIL"<=100001 +ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.04 0.01 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1000 1.43 1.43 4089 6055 0 99999 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1002 1.47 1.45 4089 6055 0 99999 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 99999 TABLE ACCESS BY INDEX ROWID COOLTEST_F0001_IOVS + 99999 INDEX RANGE SCAN COOLTEST_F0001_IOVS_CSU_3INDX (object id 8142) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1001 0.00 0.00 + SQL*Net message from client 1001 0.01 3.85 + db file sequential read 4089 0.00 0.18 + SQL*Net more data to client 6000 0.00 0.15 +******************************************************************************** + +select /*+ rule */ bucket_cnt, row_cnt, cache_cnt, null_cnt, timestamp#, + sample_size, minimum, maximum, distcnt, lowval, hival, density, col#, + spare1, spare2, avgcln +from + hist_head$ where obj#=:1 and intcol#=:2 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 18 0.00 0.00 0 0 0 0 +Fetch 18 0.00 0.00 2 36 0 18 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 37 0.00 0.00 2 36 0 18 + +Misses in library cache during parse: 1 +Optimizer mode: RULE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 2 0.00 0.00 +******************************************************************************** + +select i.obj#,i.ts#,i.file#,i.block#,i.intcols,i.type#,i.flags, i.property, + i.pctfree$,i.initrans,i.maxtrans,i.blevel,i.leafcnt,i.distkey, i.lblkkey, + i.dblkkey,i.clufac,i.cols,i.analyzetime,i.samplesize,i.dataobj#, + nvl(i.degree,1),nvl(i.instances,1),i.rowcnt,mod(i.pctthres$,256), + i.indmethod#,i.trunccnt,nvl(c.unicols,0),nvl(c.deferrable#+c.valid#,0), + nvl(i.spare1,i.intcols),i.spare4,spare2,spare6, decode(i.pctthres$,null, + null, mod(trunc(i.pctthres$/256),256)) +from + ind$ i, (select enabled, min(cols) unicols, min(to_number(bitand(defer,1))) + deferrable#, min(to_number(bitand(defer,4))) valid# from cdef$ where obj#= + :1 and enabled > 1 group by enabled) c where i.obj#=c.enabled(+) and i.bo#= + :1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 4 0.00 0.00 1 6 0 3 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 6 0.00 0.00 1 6 0 3 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select o.owner#,o.name,o.namespace,o.remoteowner,o.linkname,o.subname, + o.dataobj#,o.flags +from + obj$ o where o.obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 3 0.00 0.00 0 0 0 0 +Execute 7 0.00 0.00 0 0 0 0 +Fetch 7 0.00 0.00 0 21 0 7 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 17 0.00 0.00 0 21 0 7 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select tc.type#,tc.intcol#,tc.position#,c.type#, c.length,c.scale, + c.precision#,c.charsetid,c.charsetform +from + triggercol$ tc,col$ c ,trigger$ tr where tc.obj#=:1 and c.obj#=:2 and + tc.intcol#=c.intcol# and tr.obj# = tc.obj# and (bitand(tr.property,32) != + 32 or bitand(tc.type#,20) = 20) union select type#,intcol#,position#,69,0,0, + 0,0,0 from triggercol$ where obj#=:3 and intcol#=1001 union select tc.type#, + tc.intcol#,tc.position#,121,0,0,0,0,0 from triggercol$ tc,trigger$ tr where + tr.obj# = tc.obj# and bitand(tr.property,32) = 32 and tc.obj# = :4 and + bitand(tc.type#,20) != 20 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.01 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 4 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.01 0.00 0 4 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 0 SORT UNIQUE + 0 UNION-ALL + 0 NESTED LOOPS + 0 NESTED LOOPS + 0 TABLE ACCESS CLUSTER COL$ + 0 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 0 INDEX RANGE SCAN I_TRIGGERCOL2 (object id 133) + 0 TABLE ACCESS BY INDEX ROWID TRIGGER$ + 0 INDEX UNIQUE SCAN I_TRIGGER2 (object id 131) + 0 INDEX RANGE SCAN I_TRIGGERCOL2 (object id 133) + 0 NESTED LOOPS + 0 INDEX RANGE SCAN I_TRIGGERCOL2 (object id 133) + 0 TABLE ACCESS BY INDEX ROWID TRIGGER$ + 0 INDEX UNIQUE SCAN I_TRIGGER2 (object id 131) + +******************************************************************************** + +select type#,blocks,extents,minexts,maxexts,extsize,extpct,user#,iniexts, + NVL(lists,65535),NVL(groups,65535),cachehint,hwmincr, NVL(spare1,0) +from + seg$ where ts#=:1 and file#=:2 and block#=:3 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 4 0.00 0.00 0 0 0 0 +Fetch 4 0.00 0.00 0 12 0 4 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 12 0.00 0.00 0 12 0 4 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS CLUSTER SEG$ + 1 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + +******************************************************************************** + +select owner#,name,namespace,remoteowner,linkname,p_timestamp,p_obj#, + d_owner#, nvl(property,0),subname +from + dependency$,obj$ where d_obj#=:1 and p_obj#=obj#(+) order by order# + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.01 0.00 0 0 0 0 +Fetch 4 0.00 0.00 1 11 0 3 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 6 0.01 0.00 1 11 0 3 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 3 SORT ORDER BY + 3 NESTED LOOPS OUTER + 3 TABLE ACCESS BY INDEX ROWID DEPENDENCY$ + 3 INDEX RANGE SCAN I_DEPENDENCY1 (object id 127) + 3 TABLE ACCESS BY INDEX ROWID OBJ$ + 3 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select name,intcol#,segcol#,type#,length,nvl(precision#,0),decode(type#,2, + nvl(scale,-127/*MAXSB1MINAL*/),178,scale,179,scale,180,scale,181,scale,182, + scale,183,scale,231,scale,0),null$,fixedstorage,nvl(deflength,0),default$, + rowid,col#,property, nvl(charsetid,0),nvl(charsetform,0),spare1,spare2, + nvl(spare3,0) +from + col$ where obj#=:1 order by intcol# + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 19 0.00 0.00 0 3 0 18 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 21 0.00 0.00 0 3 0 18 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select pos#,intcol#,col#,spare1,bo#,spare2 +from + icol$ where obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 3 0.00 0.00 0 0 0 0 +Fetch 9 0.00 0.00 1 18 0 6 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 13 0.00 0.00 1 18 0 6 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select obj#,type#,ctime,mtime,stime,status,dataobj#,flags,oid$, spare1, + spare2 +from + obj$ where owner#=:1 and name=:2 and namespace=:3 and remoteowner is null + and linkname is null and subname is null + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 2 0.00 0.00 0 0 0 0 +Execute 2 0.01 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 6 0 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 6 0.01 0.00 0 6 0 2 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID OBJ#(18) + 1 INDEX RANGE SCAN OBJ#(37) (object id 37) + +******************************************************************************** + +select col#, grantee#, privilege#,max(mod(nvl(option$,0),2)) +from + objauth$ where obj#=:1 and col# is not null group by privilege#, col#, + grantee# order by col#, grantee# + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 1 2 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 1 2 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select ts#,file#,block#,nvl(bobj#,0),nvl(tab#,0),intcols,nvl(clucols,0), + audit$,flags,pctfree$,pctused$,initrans,maxtrans,rowcnt,blkcnt,empcnt, + avgspc,chncnt,avgrln,analyzetime, samplesize,cols,property,nvl(degree,1), + nvl(instances,1),avgspc_flb,flbcnt,kernelcols,nvl(trigflag, 0),nvl(spare1,0) + ,nvl(spare2,0),spare4,spare6 +from + tab$ where obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 1 3 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 1 3 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS CLUSTER OBJ#(4) + 1 INDEX UNIQUE SCAN OBJ#(3) (object id 3) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select grantee#,privilege#,nvl(col#,0),max(mod(nvl(option$,0),2)) +from + objauth$ where obj#=:1 group by grantee#,privilege#,nvl(col#,0) order by + grantee# + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 2 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 2 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select intcol#,nvl(pos#,0),col# +from + ccol$ where con#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 1 4 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 1 4 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select con#,type#,condlength,intcols,robj#,rcon#,match#,refact,nvl(enabled,0), + rowid,cols,nvl(defer,0),mtime,nvl(spare1,0) +from + cdef$ where obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 4 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 4 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select order#,columns,types +from + access$ where d_obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.00 0.00 0 6 0 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.00 0.00 0 6 0 2 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS BY INDEX ROWID ACCESS$ + 2 INDEX RANGE SCAN I_ACCESS1 (object id 129) + +******************************************************************************** + +select con#,obj#,rcon#,enabled,nvl(defer,0) +from + cdef$ where robj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 1 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 1 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select baseobject,type#,update$,insert$,delete$,refnewname,refoldname, + whenclause,definition,enabled,property,sys_evts,nttrigcol,nttrigatt, + refprtname,rowid +from + trigger$ where obj# =:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 2 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 2 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID TRIGGER$ + 1 INDEX UNIQUE SCAN I_TRIGGER2 (object id 131) + +******************************************************************************** + +select action# +from + trigger$ where obj# = :1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 3 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 3 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID TRIGGER$ + 1 INDEX UNIQUE SCAN I_TRIGGER2 (object id 131) + +******************************************************************************** + +select audit$,options +from + procedure$ where obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 3 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 3 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID PROCEDURE$ + 1 INDEX UNIQUE SCAN I_PROCEDURE1 (object id 115) + +******************************************************************************** + +select actionsize +from + trigger$ where obj# = :1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 2 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 2 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID TRIGGER$ + 1 INDEX UNIQUE SCAN I_TRIGGER2 (object id 131) + +******************************************************************************** + +commit + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 2 0.00 0.00 0 0 0 0 +Execute 2 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 6.92 6.94 +******************************************************************************** + +alter session set events '10046 trace name context level 12, forever' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Misses in library cache during execute: 1 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +set transaction read only + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 2 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.01 0.01 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.04 0.01 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 1000 1.43 1.43 4089 6055 0 99999 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1009 1.47 1.45 4089 6055 0 99999 + +Misses in library cache during parse: 3 +Misses in library cache during execute: 1 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1005 0.00 0.00 + SQL*Net message from client 1005 6.92 10.81 + db file sequential read 4089 0.00 0.18 + SQL*Net more data to client 6000 0.00 0.15 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 26 0.01 0.01 0 0 0 0 +Execute 49 0.02 0.01 0 0 0 0 +Fetch 83 0.00 0.00 8 149 0 70 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 158 0.03 0.03 8 149 0 70 + +Misses in library cache during parse: 20 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 8 0.00 0.00 + + 5 user SQL statements in session. + 26 internal SQL statements in session. + 31 SQL statements in session. +******************************************************************************** +Trace file: benthic1.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchela + 1 session in tracefile. + 5 user SQL statements in trace file. + 26 internal SQL statements in trace file. + 31 SQL statements in trace file. + 24 unique SQL statements in trace file. + 13762 lines in trace file. + 12 elapsed seconds in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-benthic-next.prf b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-benthic-next.prf new file mode 100644 index 000000000..b93cce94f --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-benthic-next.prf @@ -0,0 +1,164 @@ + +TKPROF: Release 10.1.0.2.0 - Production on Mon Jan 31 11:46:17 2005 + +Copyright (c) 1982, 2004, Oracle. All rights reserved. + +Trace file: benthic2.trc +Sort options: exeela fchela +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT * FROM COOLTEST_F0001_IOVS +WHERE "CHANNEL_ID"=0 AND "IOV_SINCE">=0 AND "IOV_UNTIL"<=100001 +ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1000 1.22 1.13 0 6055 0 99999 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1002 1.22 1.13 0 6055 0 99999 + +Misses in library cache during parse: 0 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 99999 TABLE ACCESS BY INDEX ROWID COOLTEST_F0001_IOVS + 99999 INDEX RANGE SCAN COOLTEST_F0001_IOVS_CSU_3INDX (object id 8142) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1001 0.00 0.00 + SQL*Net message from client 1001 0.02 4.29 + SQL*Net more data to client 6000 0.00 0.12 +******************************************************************************** + +commit + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 2 0.00 0.00 0 0 0 0 +Execute 2 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 4.06 4.07 +******************************************************************************** + +alter session set events '10046 trace name context level 12, forever' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +set transaction read only + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 2 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.01 0.01 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 1000 1.22 1.13 0 6055 0 99999 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1009 1.22 1.13 0 6055 0 99999 + +Misses in library cache during parse: 0 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1005 0.00 0.00 + SQL*Net message from client 1005 4.06 8.39 + SQL*Net more data to client 6000 0.00 0.12 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: benthic2.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchela + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 4 unique SQL statements in trace file. + 9066 lines in trace file. + 5 elapsed seconds in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-first.out b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-first.out new file mode 100644 index 000000000..baa58c2de --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-first.out @@ -0,0 +1,82 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 4.980 +/- 4.980 s +Total User Time : 0.230 +/- 0.230 s +Total System Time: 0.210 +/- 0.210 s +Total Idle Time : 4.540 +/- 4.540 s +----- 3.FetchRows-------------- : ( n=100001 ) +Total Real Time : 41.630 +/- 0.132 s +Total User Time : 6.290 +/- 0.020 s +Total System Time: 0.440 +/- 0.001 s +Total Idle Time : 35.010 +/- 0.111 s +----- 4.CopyAttributeList------ : ( n=100000 ) +Total Real Time : 58.130 +/- 0.184 s +Total User Time : 57.540 +/- 0.182 s +Total System Time: 0.830 +/- 0.003 s +Total Idle Time : -0.260 +/- -0.001 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 105.760 +/- 105.760 s +Total User Time : 64.740 +/- 64.740 s +Total System Time: 1.610 +/- 1.610 s +Total Idle Time : 39.410 +/- 39.410 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 105.760 +/- 105.760 s +Total User Time : 64.740 +/- 64.740 s +Total System Time: 1.610 +/- 1.610 s +Total Idle Time : 39.410 +/- 39.410 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 9.780 +/- 9.780 s +Total User Time : 9.470 +/- 9.470 s +Total System Time: 0.210 +/- 0.210 s +Total Idle Time : 0.100 +/- 0.100 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 1.560 +/- 1.560 s +Total User Time : 1.550 +/- 1.550 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 117.100 +/- 117.100 s +Total User Time : 75.760 +/- 75.760 s +Total System Time: 1.820 +/- 1.820 s +Total Idle Time : 39.520 +/- 39.520 s +** reading 100000 objects (150 bytes mixed) ** +read back 100000 objects +sec total: 117.115 +obj/s: 853.865 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 118.388 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-first.prf b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-first.prf new file mode 100644 index 000000000..390a7b353 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-first.prf @@ -0,0 +1,898 @@ + +TKPROF: Release 10.1.0.2.0 - Production on Mon Jan 31 11:39:28 2005 + +Copyright (c) 1982, 2004, Oracle. All rights reserved. + +Trace file: pluto1.trc +Sort options: exeela fchela +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 30 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 20 39.80 40.15 7409 298624 1445689 194981 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 22 39.80 40.15 7409 298654 1445689 194981 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 100000 SORT ORDER BY + 100000 TABLE ACCESS FULL COOLTEST_F0001_IOVS + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 20 0.00 0.00 + db file sequential read 1 0.00 0.00 + db file scattered read 252 0.00 0.24 + direct path write 4 0.00 0.00 + direct path read 69 0.00 0.00 + SQL*Net more data to client 13468 0.00 0.51 + SQL*Net message from client 20 6.10 63.10 +******************************************************************************** + +select i.obj#,i.ts#,i.file#,i.block#,i.intcols,i.type#,i.flags, i.property, + i.pctfree$,i.initrans,i.maxtrans,i.blevel,i.leafcnt,i.distkey, i.lblkkey, + i.dblkkey,i.clufac,i.cols,i.analyzetime,i.samplesize,i.dataobj#, + nvl(i.degree,1),nvl(i.instances,1),i.rowcnt,mod(i.pctthres$,256), + i.indmethod#,i.trunccnt,nvl(c.unicols,0),nvl(c.deferrable#+c.valid#,0), + nvl(i.spare1,i.intcols),i.spare4,spare2,spare6, decode(i.pctthres$,null, + null, mod(trunc(i.pctthres$/256),256)) +from + ind$ i, (select enabled, min(cols) unicols, min(to_number(bitand(defer,1))) + deferrable#, min(to_number(bitand(defer,4))) valid# from cdef$ where obj#= + :1 and enabled > 1 group by enabled) c where i.obj#=c.enabled(+) and i.bo#= + :1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.01 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 13 0.00 0.00 1 30 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 22 0.01 0.00 1 30 0 8 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 2) + +Rows Row Source Operation +------- --------------------------------------------------- + 2 MERGE JOIN OUTER + 2 SORT JOIN + 2 TABLE ACCESS CLUSTER OBJ#(19) + 2 INDEX UNIQUE SCAN OBJ#(3) (object id 3) + 0 SORT JOIN + 0 VIEW + 0 SORT GROUP BY + 0 TABLE ACCESS CLUSTER OBJ#(31) + 2 INDEX UNIQUE SCAN OBJ#(30) (object id 30) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select name,intcol#,segcol#,type#,length,nvl(precision#,0),decode(type#,2, + nvl(scale,-127/*MAXSB1MINAL*/),178,scale,179,scale,180,scale,181,scale,182, + scale,183,scale,231,scale,0),null$,fixedstorage,nvl(deflength,0),default$, + rowid,col#,property, nvl(charsetid,0),nvl(charsetform,0),spare1,spare2, + nvl(spare3,0) +from + col$ where obj#=:1 order by intcol# + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 6 0.00 0.00 0 0 0 0 +Fetch 94 0.00 0.00 1 19 0 88 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 104 0.00 0.00 1 19 0 88 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 59 SORT ORDER BY + 59 TABLE ACCESS CLUSTER OBJ#(21) + 3 INDEX UNIQUE SCAN OBJ#(3) (object id 3) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select /*+ rule */ bucket_cnt, row_cnt, cache_cnt, null_cnt, timestamp#, + sample_size, minimum, maximum, distcnt, lowval, hival, density, col#, + spare1, spare2, avgcln +from + hist_head$ where obj#=:1 and intcol#=:2 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 18 0.00 0.00 0 0 0 0 +Fetch 18 0.00 0.00 2 36 0 18 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 37 0.00 0.00 2 36 0 18 + +Misses in library cache during parse: 1 +Optimizer mode: RULE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 2 0.00 0.00 +******************************************************************************** + +select obj#,type#,ctime,mtime,stime,status,dataobj#,flags,oid$, spare1, + spare2 +from + obj$ where owner#=:1 and name=:2 and namespace=:3 and remoteowner is null + and linkname is null and subname is null + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 10 0.00 0.00 0 0 0 0 +Fetch 10 0.00 0.00 3 27 0 7 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 24 0.00 0.00 3 27 0 7 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 3 0.00 0.00 +******************************************************************************** + +select type#,blocks,extents,minexts,maxexts,extsize,extpct,user#,iniexts, + NVL(lists,65535),NVL(groups,65535),cachehint,hwmincr, NVL(spare1,0) +from + seg$ where ts#=:1 and file#=:2 and block#=:3 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 11 0.00 0.00 0 0 0 0 +Execute 11 0.00 0.00 0 0 0 0 +Fetch 11 0.00 0.00 0 33 0 11 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 33 0.00 0.00 0 33 0 11 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 2) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS CLUSTER SEG$ + 1 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + +******************************************************************************** + +select o.owner#,o.name,o.namespace,o.remoteowner,o.linkname,o.subname, + o.dataobj#,o.flags +from + obj$ o where o.obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 7 0.00 0.00 0 0 0 0 +Execute 15 0.00 0.00 0 0 0 0 +Fetch 15 0.00 0.00 0 45 0 15 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 37 0.00 0.00 0 45 0 15 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select pos#,intcol#,col#,spare1,bo#,spare2 +from + icol$ where obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 8 0.00 0.00 0 0 0 0 +Fetch 19 0.00 0.00 1 38 0 11 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 31 0.00 0.00 1 38 0 11 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 2) + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS BY INDEX ROWID OBJ#(20) + 2 INDEX RANGE SCAN OBJ#(40) (object id 40) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select col#, grantee#, privilege#,max(mod(nvl(option$,0),2)) +from + objauth$ where obj#=:1 and col# is not null group by privilege#, col#, + grantee# order by col#, grantee# + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 4 0.01 0.00 0 0 0 0 +Fetch 4 0.01 0.00 2 8 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 12 0.02 0.00 2 8 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 2 0.00 0.00 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 1 15 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.01 0.00 5 10 19 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.01 0.00 6 25 19 2 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 3 0.00 0.00 + db file scattered read 1 0.00 0.00 + SQL*Net message from client 3 0.00 0.00 +******************************************************************************** + +select grantee#,privilege#,nvl(col#,0),max(mod(nvl(option$,0),2)) +from + objauth$ where obj#=:1 group by grantee#,privilege#,nvl(col#,0) order by + grantee# + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 4 0.00 0.00 0 0 0 0 +Fetch 5 0.00 0.00 1 9 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 13 0.00 0.00 1 9 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.03 0.02 0 9 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 4 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.03 0.02 4 131 0 8 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + db file sequential read 4 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +select ts#,file#,block#,nvl(bobj#,0),nvl(tab#,0),intcols,nvl(clucols,0), + audit$,flags,pctfree$,pctused$,initrans,maxtrans,rowcnt,blkcnt,empcnt, + avgspc,chncnt,avgrln,analyzetime, samplesize,cols,property,nvl(degree,1), + nvl(instances,1),avgspc_flb,flbcnt,kernelcols,nvl(trigflag, 0),nvl(spare1,0) + ,nvl(spare2,0),spare4,spare6 +from + tab$ where obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.01 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 5 0.00 0.00 0 15 0 5 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 14 0.01 0.00 0 15 0 5 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 2) + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS CLUSTER OBJ#(4) + 2 INDEX UNIQUE SCAN OBJ#(3) (object id 3) + +******************************************************************************** + +select owner#,name,namespace,remoteowner,linkname,p_timestamp,p_obj#, + d_owner#, nvl(property,0),subname +from + dependency$,obj$ where d_obj#=:1 and p_obj#=obj#(+) order by order# + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 10 0.00 0.00 3 21 0 9 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 12 0.00 0.00 3 21 0 9 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 9 SORT ORDER BY + 9 NESTED LOOPS OUTER + 9 TABLE ACCESS BY INDEX ROWID DEPENDENCY$ + 9 INDEX RANGE SCAN I_DEPENDENCY1 (object id 127) + 7 TABLE ACCESS BY INDEX ROWID OBJ$ + 7 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 3 0.00 0.00 +******************************************************************************** + +select intcol#,nvl(pos#,0),col# +from + ccol$ where con#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 3 0.00 0.00 0 0 0 0 +Execute 4 0.00 0.00 0 0 0 0 +Fetch 8 0.00 0.00 1 16 0 4 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 15 0.00 0.00 1 16 0 4 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 1 0.00 0.00 +******************************************************************************** + +select con#,type#,condlength,intcols,robj#,rcon#,match#,refact,nvl(enabled,0), + rowid,cols,nvl(defer,0),mtime,nvl(spare1,0) +from + cdef$ where obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 3 0.00 0.00 0 0 0 0 +Execute 3 0.00 0.00 0 0 0 0 +Fetch 7 0.00 0.00 0 13 0 4 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 13 0.00 0.00 0 13 0 4 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select col#,intcol#,charsetid,charsetform +from + col$ where obj#=:1 order by intcol# asc + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 48 0.00 0.00 0 4 0 47 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 50 0.00 0.00 0 4 0 47 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select con#,obj#,rcon#,enabled,nvl(defer,0) +from + cdef$ where robj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 3 0.00 0.00 0 0 0 0 +Execute 3 0.00 0.00 0 0 0 0 +Fetch 4 0.00 0.00 0 5 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 10 0.00 0.00 0 5 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select order#,columns,types +from + access$ where d_obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 9 0.00 0.00 2 18 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 11 0.00 0.00 2 18 0 8 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 8 TABLE ACCESS BY INDEX ROWID ACCESS$ + 8 INDEX RANGE SCAN I_ACCESS1 (object id 129) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 2 0.00 0.00 +******************************************************************************** + +select col#,intcol#,toid,version#,packed,intcols,intcol#s,flags, synobj#, + nvl(typidcol#, 0) +from + coltype$ where obj#=:1 order by intcol# desc + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 4 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 4 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select cols,audit$,textlength,intcols,property,flags,rowid +from + view$ where obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 1 1 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 3 3 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 4 4 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID OBJ#(62) + 1 INDEX UNIQUE SCAN OBJ#(104) (object id 104) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 4 0.00 0.00 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 28 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 2 2 7 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 2 30 7 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + db file sequential read 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +select node,owner,name +from + syn$ where obj#=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.01 0.00 1 1 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 3 3 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.01 0.00 4 4 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID OBJ#(61) + 1 INDEX UNIQUE SCAN OBJ#(106) (object id 106) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 4 0.00 0.00 +******************************************************************************** + +select l.col#, l.intcol#, l.lobj#, l.ind#, l.ts#, l.file#, l.block#, l.chunk, + l.pctversion$, l.flags, l.property, l.retention, l.freepools +from + lob$ l where l.obj# = :1 order by l.intcol# asc + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 4 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 4 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 0 SORT ORDER BY + 0 TABLE ACCESS CLUSTER LOB$ + 1 INDEX UNIQUE SCAN I_OBJ# (object id 3) + +******************************************************************************** + +select intcol#, toid, version#, intcols, intcol#s, flags, synobj# +from + subcoltype$ where obj#=:1 order by intcol# asc + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 4 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 4 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select intcol#,type,flags,lobcol,objcol,extracol,schemaoid, elemnum +from + opqtype$ where obj# = :1 order by intcol# asc + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 4 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 4 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select col#,intcol#,ntab# +from + ntab$ where obj#=:1 order by intcol# asc + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 4 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 4 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select col#,intcol#,reftyp,stabid,expctoid +from + refcon$ where obj#=:1 order by intcol# asc + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.01 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 4 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.01 0.00 0 4 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) +******************************************************************************** + +select text +from + view$ where rowid=:1 + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.01 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 2 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.01 0.00 0 2 0 1 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY USER ROWID VIEW$ + +******************************************************************************** + +select p.value$, lengthb(p.value$) +from + sys.props$ p where p.name = 'BACK_END_DB' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 3 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 3 0 0 + +Misses in library cache during parse: 1 +Optimizer mode: CHOOSE +Parsing user id: SYS (recursive depth: 1) + +Rows Row Source Operation +------- --------------------------------------------------- + 0 TABLE ACCESS FULL PROPS$ + +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Misses in library cache during execute: 1 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.03 0.03 1 82 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 26 39.81 40.15 7420 298758 1445715 194992 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 35 39.84 40.19 7421 298840 1445715 194992 + +Misses in library cache during parse: 4 +Misses in library cache during execute: 1 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 39 0.00 0.00 + SQL*Net message from client 39 12.18 76.30 + db file sequential read 11 0.00 0.00 + db file scattered read 253 0.00 0.24 + SQL*Net more data to client 13469 0.00 0.51 + direct path write 4 0.00 0.00 + direct path read 69 0.00 0.00 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 69 0.04 0.03 2 2 0 0 +Execute 109 0.02 0.02 0 0 0 0 +Fetch 290 0.01 0.01 23 372 0 240 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 468 0.07 0.07 25 374 0 240 + +Misses in library cache during parse: 26 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + db file sequential read 23 0.00 0.00 + + 5 user SQL statements in session. + 69 internal SQL statements in session. + 74 SQL statements in session. +******************************************************************************** +Trace file: pluto1.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchela + 1 session in tracefile. + 5 user SQL statements in trace file. + 69 internal SQL statements in trace file. + 74 SQL statements in trace file. + 31 unique SQL statements in trace file. + 15449 lines in trace file. + 104 elapsed seconds in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-next.out b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-next.out new file mode 100644 index 000000000..b244b188c --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-next.out @@ -0,0 +1,82 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 4.590 +/- 4.590 s +Total User Time : 0.230 +/- 0.230 s +Total System Time: 0.130 +/- 0.130 s +Total Idle Time : 4.230 +/- 4.230 s +----- 3.FetchRows-------------- : ( n=100001 ) +Total Real Time : 42.540 +/- 0.135 s +Total User Time : 6.110 +/- 0.019 s +Total System Time: 0.370 +/- 0.001 s +Total Idle Time : 36.090 +/- 0.114 s +----- 4.CopyAttributeList------ : ( n=100000 ) +Total Real Time : 57.530 +/- 0.182 s +Total User Time : 56.910 +/- 0.180 s +Total System Time: 0.880 +/- 0.003 s +Total Idle Time : -0.210 +/- -0.001 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 105.810 +/- 105.810 s +Total User Time : 64.230 +/- 64.230 s +Total System Time: 1.450 +/- 1.450 s +Total Idle Time : 40.130 +/- 40.130 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 105.820 +/- 105.820 s +Total User Time : 64.230 +/- 64.230 s +Total System Time: 1.450 +/- 1.450 s +Total Idle Time : 40.140 +/- 40.140 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 9.690 +/- 9.690 s +Total User Time : 9.540 +/- 9.540 s +Total System Time: 0.080 +/- 0.080 s +Total Idle Time : 0.070 +/- 0.070 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 1.570 +/- 1.570 s +Total User Time : 1.570 +/- 1.570 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 117.080 +/- 117.080 s +Total User Time : 75.340 +/- 75.340 s +Total System Time: 1.530 +/- 1.530 s +Total Idle Time : 40.210 +/- 40.210 s +** reading 100000 objects (150 bytes mixed) ** +read back 100000 objects +sec total: 117.093 +obj/s: 854.021 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 118.316 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-next.prf b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-next.prf new file mode 100644 index 000000000..1ecedb1d6 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/ServerCache/100k-ora-cool-next.prf @@ -0,0 +1,246 @@ + +TKPROF: Release 10.1.0.2.0 - Production on Mon Jan 31 11:39:22 2005 + +Copyright (c) 1982, 2004, Oracle. All rights reserved. + +Trace file: pluto2.trc +Sort options: exeela fchela +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 20 40.48 40.71 4632 298624 1445635 194981 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 22 40.48 40.71 4632 298624 1445635 194981 + +Misses in library cache during parse: 0 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 100000 SORT ORDER BY + 100000 TABLE ACCESS FULL COOLTEST_F0001_IOVS + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 20 0.00 0.00 + db file scattered read 68 0.00 0.06 + direct path write 4 0.00 0.00 + direct path read 48 0.00 0.00 + SQL*Net more data to client 13468 0.00 0.51 + SQL*Net message from client 20 6.03 62.61 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.00 0.00 0 10 19 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.00 0.00 0 10 19 2 + +Misses in library cache during parse: 0 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 3 0.00 0.00 + SQL*Net message from client 3 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 122 0 8 + +Misses in library cache during parse: 0 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.01 0.00 0 2 7 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.01 0.00 0 2 7 1 + +Misses in library cache during parse: 0 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer mode: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 26 40.49 40.72 4632 298758 1445661 194992 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 35 40.49 40.72 4632 298758 1445661 194992 + +Misses in library cache during parse: 0 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 39 0.00 0.00 + SQL*Net message from client 39 12.07 75.70 + SQL*Net more data to client 13469 0.00 0.51 + db file scattered read 68 0.00 0.06 + direct path write 4 0.00 0.00 + direct path read 48 0.00 0.00 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: pluto2.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchela + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 5 unique SQL statements in trace file. + 13792 lines in trace file. + 104 elapsed seconds in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/TODO.Performance b/RelationalCool/tests/PerformanceAV/TODO.Performance new file mode 100644 index 000000000..62f51a85e --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TODO.Performance @@ -0,0 +1,38 @@ +* Make sure that the best execution plan is used in COOL in the trace file. + The first example with Bjorn used the indexes, but later examples did not. + Although this does not seem to explain the performance penalty, + it is annoying. Can it be because in Bjorn's example I was both + writing and reading? + > DONE: after 'analyze table compute statistics' the index is used + +* Instrument the writing code to test how much time is lost in the + bad select for the last inserted IOV. Improve on that (quite easy...). + +* Clearly document and study the effect of RAL itself. + Instrument the RAL code to check where the overhead is + and why the trace file looks so weird. + +* Document all previous points: + - scaling of results between 1k to 200k rows + - different payload types + - writing + - reading cache size and memory size + - MyISAM vs InnoDB + +* Test Radovan's native MySQL implementation instead of ODBC + [PS: It may be more important to disable scrollable cursors in ODBC!] + +* Change the vector iterator implementation into one using an 'AttributeTable'. + The steps should be: + - copy the results from RAL into an AttributeTable + that returns to the user an AttributeList reference (or shared ptr) + - create a class implementing IObject that is just a wrapper + for an AttributeList reference (or shared ptr) + - create a class implementin IObjectIterator that is just a + wrapper for an AttributeTable instance + - the AttributeTable belongs to the iterator and is destroyed + when the iterator goes out of scope + - there is only one AttributeListSpecification in the system + +* Test whether string manipulation in RAL introduces a client overhead. + Numbers may be better if an integer-only patylaod is used. \ No newline at end of file diff --git a/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/doNotUseAccessor-memory.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/doNotUseAccessor-memory.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..518538bb1 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/doNotUseAccessor-memory.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,109 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +Total VmSize incr: 0.400 +/- 0.400 MB +Total VmRSS incr : 0.408 +/- 0.408 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 7.460 +/- 0.075 s +Total User Time : 5.190 +/- 0.052 s +Total System Time: 1.650 +/- 0.016 s +Total Idle Time : 0.660 +/- 0.007 s +Total VmSize incr: 0.172 +/- 0.002 MB +Total VmRSS incr : 1.552 +/- 0.016 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 11.620 +/- 0.116 s +Total User Time : 9.570 +/- 0.096 s +Total System Time: 1.700 +/- 0.017 s +Total Idle Time : 0.350 +/- 0.004 s +Total VmSize incr: 24.512 +/- 0.245 MB +Total VmRSS incr : 23.780 +/- 0.238 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 31.030 +/- 31.030 s +Total User Time : 23.360 +/- 23.360 s +Total System Time: 7.310 +/- 7.310 s +Total Idle Time : 0.360 +/- 0.360 s +Total VmSize incr: 25.788 +/- 25.788 MB +Total VmRSS incr : 25.740 +/- 25.740 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 31.030 +/- 31.030 s +Total User Time : 23.360 +/- 23.360 s +Total System Time: 7.310 +/- 7.310 s +Total Idle Time : 0.360 +/- 0.360 s +Total VmSize incr: 25.788 +/- 25.788 MB +Total VmRSS incr : 25.748 +/- 25.748 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.970 +/- 0.970 s +Total User Time : 0.970 +/- 0.970 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 3.036 +/- 3.036 MB +Total VmRSS incr : 2.984 +/- 2.984 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.028 +/- 0.028 MB +Total VmRSS incr : 0.076 +/- 0.076 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 32.160 +/- 32.160 s +Total User Time : 24.490 +/- 24.490 s +Total System Time: 7.320 +/- 7.320 s +Total Idle Time : 0.350 +/- 0.350 s +Total VmSize incr: 28.720 +/- 28.720 MB +Total VmRSS incr : 28.728 +/- 28.728 MB +==> First object: since=0 +==> Last object: since=9999 +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 32.1738 +obj/s: 310.812 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 32.309 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/doNotUseAccessor-time.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/doNotUseAccessor-time.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..2c944faa0 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/doNotUseAccessor-time.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,87 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 0.870 +/- 0.009 s +Total User Time : 0.590 +/- 0.006 s +Total System Time: 0.020 +/- 0.000 s +Total Idle Time : 0.220 +/- 0.002 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 5.270 +/- 0.053 s +Total User Time : 5.220 +/- 0.052 s +Total System Time: 0.090 +/- 0.001 s +Total Idle Time : -0.010 +/- -0.000 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 6.330 +/- 6.330 s +Total User Time : 5.900 +/- 5.900 s +Total System Time: 0.140 +/- 0.140 s +Total Idle Time : 0.290 +/- 0.290 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 6.330 +/- 6.330 s +Total User Time : 5.900 +/- 5.900 s +Total System Time: 0.140 +/- 0.140 s +Total Idle Time : 0.290 +/- 0.290 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.970 +/- 0.970 s +Total User Time : 0.970 +/- 0.970 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 7.460 +/- 7.460 s +Total User Time : 7.040 +/- 7.040 s +Total System Time: 0.140 +/- 0.140 s +Total Idle Time : 0.280 +/- 0.280 s +==> First object: since=0 +==> Last object: since=9999 +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 7.47047 +obj/s: 1338.6 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 7.60483 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/execTestAttributeValueAccessor.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/execTestAttributeValueAccessor.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..5a40b31ce --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/execTestAttributeValueAccessor.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,4 @@ +3.410u 0.190s 0:05.00 72.0% 0+0k 0+0io 2278pf+0w +7.340u 0.190s 0:08.90 84.6% 0+0k 0+0io 2282pf+0w +20.380u 7.300s 0:29.12 95.0% 0+0k 0+0io 2277pf+0w +24.810u 7.350s 0:33.61 95.6% 0+0k 0+0io 2282pf+0w diff --git a/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/useAccessor-memory.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/useAccessor-memory.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..bc588f13a --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/useAccessor-memory.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,109 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : -0.010 +/- -0.010 s +Total VmSize incr: 0.396 +/- 0.396 MB +Total VmRSS incr : 0.404 +/- 0.404 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 6.910 +/- 0.069 s +Total User Time : 4.730 +/- 0.047 s +Total System Time: 1.860 +/- 0.019 s +Total Idle Time : 0.300 +/- 0.003 s +Total VmSize incr: 0.172 +/- 0.002 MB +Total VmRSS incr : 1.584 +/- 0.016 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 7.210 +/- 0.072 s +Total User Time : 5.800 +/- 0.058 s +Total System Time: 1.720 +/- 0.017 s +Total Idle Time : -0.300 +/- -0.003 s +Total VmSize incr: 24.060 +/- 0.241 MB +Total VmRSS incr : 23.712 +/- 0.237 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 26.510 +/- 26.510 s +Total User Time : 18.930 +/- 18.930 s +Total System Time: 7.230 +/- 7.230 s +Total Idle Time : 0.350 +/- 0.350 s +Total VmSize incr: 25.776 +/- 25.776 MB +Total VmRSS incr : 25.700 +/- 25.700 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 26.510 +/- 26.510 s +Total User Time : 18.930 +/- 18.930 s +Total System Time: 7.230 +/- 7.230 s +Total Idle Time : 0.350 +/- 0.350 s +Total VmSize incr: 25.776 +/- 25.776 MB +Total VmRSS incr : 25.720 +/- 25.720 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.980 +/- 0.980 s +Total User Time : 0.960 +/- 0.960 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 3.008 +/- 3.008 MB +Total VmRSS incr : 2.956 +/- 2.956 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.028 +/- 0.028 MB +Total VmRSS incr : 0.076 +/- 0.076 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 27.660 +/- 27.660 s +Total User Time : 20.060 +/- 20.060 s +Total System Time: 7.250 +/- 7.250 s +Total Idle Time : 0.350 +/- 0.350 s +Total VmSize incr: 28.692 +/- 28.692 MB +Total VmRSS incr : 28.672 +/- 28.672 MB +==> First object: since=0 +==> Last object: since=9999 +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 27.6715 +obj/s: 361.383 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 27.8057 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/useAccessor-time.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/useAccessor-time.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..ab8cfb557 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestAttributeValueAccessor/useAccessor-time.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,87 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 0.770 +/- 0.008 s +Total User Time : 0.510 +/- 0.005 s +Total System Time: 0.060 +/- 0.001 s +Total Idle Time : 0.220 +/- 0.002 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 1.520 +/- 0.015 s +Total User Time : 1.370 +/- 0.014 s +Total System Time: 0.040 +/- 0.000 s +Total Idle Time : 0.110 +/- 0.001 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 2.390 +/- 2.390 s +Total User Time : 1.960 +/- 1.960 s +Total System Time: 0.130 +/- 0.130 s +Total Idle Time : 0.300 +/- 0.300 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 2.390 +/- 2.390 s +Total User Time : 1.960 +/- 1.960 s +Total System Time: 0.130 +/- 0.130 s +Total Idle Time : 0.300 +/- 0.300 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.960 +/- 0.960 s +Total User Time : 0.940 +/- 0.940 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 3.520 +/- 3.520 s +Total User Time : 3.060 +/- 3.060 s +Total System Time: 0.140 +/- 0.140 s +Total Idle Time : 0.320 +/- 0.320 s +==> First object: since=0 +==> Last object: since=9999 +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 3.52561 +obj/s: 2836.38 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 3.66015 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.rh73.1006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.rh73.1006MB.out new file mode 100644 index 000000000..46aa75c73 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.rh73.1006MB.out @@ -0,0 +1,5 @@ +8.170u 0.330s 0:13.50 62.9% 0+0k 0+0io 2271pf+0w +20.720u 0.240s 0:25.24 83.0% 0+0k 0+0io 2271pf+0w +25.180u 7.720s 0:37.63 87.4% 0+0k 0+0io 2271pf+0w +36.560u 7.410s 0:49.07 89.6% 0+0k 0+0io 2271pf+0w + diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.rh73.501MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.rh73.501MB.out new file mode 100644 index 000000000..dc2964e82 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.rh73.501MB.out @@ -0,0 +1,5 @@ +7.730u 0.160s 0:12.29 64.1% 0+0k 0+0io 2272pf+0w +20.540u 0.130s 0:25.04 82.5% 0+0k 0+0io 2272pf+0w +25.040u 7.760s 0:37.04 88.5% 0+0k 0+0io 2272pf+0w +36.630u 7.090s 0:47.92 91.2% 0+0k 0+0io 2272pf+0w + diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.slc3.2006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.slc3.2006MB.out new file mode 100644 index 000000000..1befd9ed5 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/execTestNewCopy.slc3.2006MB.out @@ -0,0 +1,5 @@ +7.520u 0.260s 0:19.21 40.4% 0+0k 0+0io 2480pf+0w +5.760u 0.170s 0:12.18 48.6% 0+0k 0+0io 2479pf+0w +18.680u 5.110s 0:39.16 60.7% 0+0k 0+0io 2480pf+0w +17.260u 4.920s 0:29.91 74.1% 0+0k 0+0io 2479pf+0w + diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.rh73.1006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.rh73.1006MB.out new file mode 100644 index 000000000..f6900bbee --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.rh73.1006MB.out @@ -0,0 +1,102 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.012 +/- 0.012 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.412 +/- 0.412 MB +Total VmRSS incr : 0.412 +/- 0.412 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 10.350 +/- 0.103 s +Total User Time : 5.130 +/- 0.051 s +Total System Time: 1.730 +/- 0.017 s +Total Idle Time : 3.480 +/- 0.035 s +Total VmSize incr: 0.796 +/- 0.008 MB +Total VmRSS incr : 1.560 +/- 0.016 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 10.650 +/- 0.106 s +Total User Time : 9.040 +/- 0.090 s +Total System Time: 1.760 +/- 0.018 s +Total Idle Time : -0.120 +/- -0.001 s +Total VmSize incr: 16.028 +/- 0.160 MB +Total VmRSS incr : 16.080 +/- 0.161 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 33.550 +/- 33.550 s +Total User Time : 22.660 +/- 22.660 s +Total System Time: 7.270 +/- 7.270 s +Total Idle Time : 3.620 +/- 3.620 s +Total VmSize incr: 18.132 +/- 18.132 MB +Total VmRSS incr : 18.064 +/- 18.064 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 33.550 +/- 33.550 s +Total User Time : 22.660 +/- 22.660 s +Total System Time: 7.280 +/- 7.280 s +Total Idle Time : 3.610 +/- 3.610 s +Total VmSize incr: 18.132 +/- 18.132 MB +Total VmRSS incr : 18.072 +/- 18.072 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 1.000 +/- 1.000 s +Total User Time : 0.960 +/- 0.960 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.030 +/- 0.030 s +Total VmSize incr: 3.016 +/- 3.016 MB +Total VmRSS incr : 2.956 +/- 2.956 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 4.440 +/- 4.440 s +Total User Time : 4.360 +/- 4.360 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 0.060 +/- 0.060 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 39.000 +/- 39.000 s +Total User Time : 27.990 +/- 27.990 s +Total System Time: 7.310 +/- 7.310 s +Total Idle Time : 3.700 +/- 3.700 s +Total VmSize incr: 21.016 +/- 21.016 MB +Total VmRSS incr : 20.948 +/- 20.948 MB +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 39.0098 +obj/s: 256.346 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 47.4793 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.rh73.501MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.rh73.501MB.out new file mode 100644 index 000000000..197da322d --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.rh73.501MB.out @@ -0,0 +1,102 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.012 +/- 0.012 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.412 +/- 0.412 MB +Total VmRSS incr : 0.412 +/- 0.412 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 9.800 +/- 0.098 s +Total User Time : 5.100 +/- 0.051 s +Total System Time: 1.550 +/- 0.015 s +Total Idle Time : 3.150 +/- 0.031 s +Total VmSize incr: 0.796 +/- 0.008 MB +Total VmRSS incr : 1.560 +/- 0.016 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 10.510 +/- 0.105 s +Total User Time : 9.150 +/- 0.091 s +Total System Time: 1.560 +/- 0.016 s +Total Idle Time : -0.200 +/- -0.002 s +Total VmSize incr: 16.028 +/- 0.160 MB +Total VmRSS incr : 16.080 +/- 0.161 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 32.750 +/- 32.750 s +Total User Time : 22.680 +/- 22.680 s +Total System Time: 7.000 +/- 7.000 s +Total Idle Time : 3.070 +/- 3.070 s +Total VmSize incr: 18.132 +/- 18.132 MB +Total VmRSS incr : 18.064 +/- 18.064 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 32.760 +/- 32.760 s +Total User Time : 22.680 +/- 22.680 s +Total System Time: 7.000 +/- 7.000 s +Total Idle Time : 3.080 +/- 3.080 s +Total VmSize incr: 18.132 +/- 18.132 MB +Total VmRSS incr : 18.072 +/- 18.072 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.970 +/- 0.970 s +Total User Time : 0.960 +/- 0.960 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 3.016 +/- 3.016 MB +Total VmRSS incr : 2.956 +/- 2.956 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 4.190 +/- 4.190 s +Total User Time : 4.210 +/- 4.210 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.020 +/- -0.020 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 37.920 +/- 37.920 s +Total User Time : 27.860 +/- 27.860 s +Total System Time: 7.000 +/- 7.000 s +Total Idle Time : 3.060 +/- 3.060 s +Total VmSize incr: 21.016 +/- 21.016 MB +Total VmRSS incr : 20.948 +/- 20.948 MB +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 37.9256 +obj/s: 263.674 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 46.4649 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.slc3.2006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.slc3.2006MB.out new file mode 100644 index 000000000..653429ae2 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-memory.slc3.2006MB.out @@ -0,0 +1,102 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 1.024 +/- 1.024 MB +Total VmRSS incr : 0.420 +/- 0.420 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 9.330 +/- 0.093 s +Total User Time : 3.240 +/- 0.032 s +Total System Time: 1.080 +/- 0.011 s +Total Idle Time : 5.050 +/- 0.050 s +Total VmSize incr: 1.024 +/- 0.010 MB +Total VmRSS incr : 1.524 +/- 0.015 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 8.100 +/- 0.081 s +Total User Time : 6.620 +/- 0.066 s +Total System Time: 1.290 +/- 0.013 s +Total Idle Time : 0.170 +/- 0.002 s +Total VmSize incr: 15.360 +/- 0.154 MB +Total VmRSS incr : 16.416 +/- 0.164 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 26.860 +/- 26.860 s +Total User Time : 15.390 +/- 15.390 s +Total System Time: 4.860 +/- 4.860 s +Total Idle Time : 6.610 +/- 6.610 s +Total VmSize incr: 18.432 +/- 18.432 MB +Total VmRSS incr : 18.368 +/- 18.368 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 26.870 +/- 26.870 s +Total User Time : 15.390 +/- 15.390 s +Total System Time: 4.860 +/- 4.860 s +Total Idle Time : 6.620 +/- 6.620 s +Total VmSize incr: 18.432 +/- 18.432 MB +Total VmRSS incr : 18.376 +/- 18.376 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 1.460 +/- 1.460 s +Total User Time : 1.420 +/- 1.420 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 0.020 +/- 0.020 s +Total VmSize incr: 3.072 +/- 3.072 MB +Total VmRSS incr : 3.196 +/- 3.196 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.090 +/- 0.090 s +Total User Time : 0.100 +/- 0.100 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 28.430 +/- 28.430 s +Total User Time : 16.920 +/- 16.920 s +Total System Time: 4.880 +/- 4.880 s +Total Idle Time : 6.630 +/- 6.630 s +Total VmSize incr: 21.504 +/- 21.504 MB +Total VmRSS incr : 21.572 +/- 21.572 MB +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 28.4342 +obj/s: 351.689 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 28.5795 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.rh73.1006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.rh73.1006MB.out new file mode 100644 index 000000000..f88c2aa3a --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.rh73.1006MB.out @@ -0,0 +1,82 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 3.900 +/- 0.039 s +Total User Time : 0.750 +/- 0.007 s +Total System Time: 0.060 +/- 0.001 s +Total Idle Time : 3.120 +/- 0.031 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 4.640 +/- 0.046 s +Total User Time : 4.610 +/- 0.046 s +Total System Time: 0.080 +/- 0.001 s +Total Idle Time : -0.020 +/- -0.000 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 8.730 +/- 8.730 s +Total User Time : 5.450 +/- 5.450 s +Total System Time: 0.160 +/- 0.160 s +Total Idle Time : 3.120 +/- 3.120 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 8.730 +/- 8.730 s +Total User Time : 5.450 +/- 5.450 s +Total System Time: 0.170 +/- 0.170 s +Total Idle Time : 3.110 +/- 3.110 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.980 +/- 0.980 s +Total User Time : 0.950 +/- 0.950 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.020 +/- 0.020 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 4.640 +/- 4.640 s +Total User Time : 4.620 +/- 4.620 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.020 +/- 0.020 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 14.350 +/- 14.350 s +Total User Time : 11.020 +/- 11.020 s +Total System Time: 0.180 +/- 0.180 s +Total Idle Time : 3.150 +/- 3.150 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 14.3532 +obj/s: 696.709 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 23.9338 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.rh73.501MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.rh73.501MB.out new file mode 100644 index 000000000..4ba875cf7 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.rh73.501MB.out @@ -0,0 +1,82 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.020 +/- 0.020 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.020 +/- 0.020 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 3.760 +/- 0.038 s +Total User Time : 0.700 +/- 0.007 s +Total System Time: 0.030 +/- 0.000 s +Total Idle Time : 3.050 +/- 0.030 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 4.800 +/- 0.048 s +Total User Time : 4.550 +/- 0.046 s +Total System Time: 0.060 +/- 0.001 s +Total Idle Time : 0.180 +/- 0.002 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 8.690 +/- 8.690 s +Total User Time : 5.360 +/- 5.360 s +Total System Time: 0.090 +/- 0.090 s +Total Idle Time : 3.240 +/- 3.240 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 8.700 +/- 8.700 s +Total User Time : 5.360 +/- 5.360 s +Total System Time: 0.090 +/- 0.090 s +Total Idle Time : 3.250 +/- 3.250 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.970 +/- 0.970 s +Total User Time : 0.930 +/- 0.930 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 0.020 +/- 0.020 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 4.460 +/- 4.460 s +Total User Time : 4.460 +/- 4.460 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 14.130 +/- 14.130 s +Total User Time : 10.750 +/- 10.750 s +Total System Time: 0.110 +/- 0.110 s +Total Idle Time : 3.270 +/- 3.270 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 14.1329 +obj/s: 707.567 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 23.7273 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.slc3.2006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.slc3.2006MB.out new file mode 100644 index 000000000..58be89f95 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/newCopy-time.slc3.2006MB.out @@ -0,0 +1,82 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 4.120 +/- 0.041 s +Total User Time : 0.530 +/- 0.005 s +Total System Time: 0.050 +/- 0.000 s +Total Idle Time : 3.540 +/- 0.035 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 4.760 +/- 0.048 s +Total User Time : 3.320 +/- 0.033 s +Total System Time: 0.060 +/- 0.001 s +Total Idle Time : 1.390 +/- 0.014 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 9.150 +/- 9.150 s +Total User Time : 3.960 +/- 3.960 s +Total System Time: 0.130 +/- 0.130 s +Total Idle Time : 5.060 +/- 5.060 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 9.150 +/- 9.150 s +Total User Time : 3.960 +/- 3.960 s +Total System Time: 0.130 +/- 0.130 s +Total Idle Time : 5.060 +/- 5.060 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 1.460 +/- 1.460 s +Total User Time : 1.410 +/- 1.410 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.050 +/- 0.050 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.080 +/- 0.080 s +Total User Time : 0.080 +/- 0.080 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 10.690 +/- 10.690 s +Total User Time : 5.450 +/- 5.450 s +Total System Time: 0.130 +/- 0.130 s +Total Idle Time : 5.110 +/- 5.110 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 10.6924 +obj/s: 935.247 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 10.861 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.rh73.1006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.rh73.1006MB.out new file mode 100644 index 000000000..5d8d9f898 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.rh73.1006MB.out @@ -0,0 +1,102 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.012 +/- 0.012 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.020 +/- 0.020 s +Total User Time : 0.020 +/- 0.020 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.412 +/- 0.412 MB +Total VmRSS incr : 0.412 +/- 0.412 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 10.140 +/- 0.101 s +Total User Time : 5.030 +/- 0.050 s +Total System Time: 1.950 +/- 0.019 s +Total Idle Time : 3.190 +/- 0.032 s +Total VmSize incr: 0.024 +/- 0.000 MB +Total VmRSS incr : 1.460 +/- 0.015 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 12.330 +/- 0.123 s +Total User Time : 10.130 +/- 0.101 s +Total System Time: 1.910 +/- 0.019 s +Total Idle Time : 0.320 +/- 0.003 s +Total VmSize incr: 25.344 +/- 0.253 MB +Total VmRSS incr : 23.880 +/- 0.239 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 35.010 +/- 35.010 s +Total User Time : 23.730 +/- 23.730 s +Total System Time: 7.660 +/- 7.660 s +Total Idle Time : 3.620 +/- 3.620 s +Total VmSize incr: 25.824 +/- 25.824 MB +Total VmRSS incr : 25.764 +/- 25.764 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 35.010 +/- 35.010 s +Total User Time : 23.730 +/- 23.730 s +Total System Time: 7.660 +/- 7.660 s +Total Idle Time : 3.620 +/- 3.620 s +Total VmSize incr: 25.824 +/- 25.824 MB +Total VmRSS incr : 25.772 +/- 25.772 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 1.000 +/- 1.000 s +Total User Time : 0.980 +/- 0.980 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 3.012 +/- 3.012 MB +Total VmRSS incr : 2.952 +/- 2.952 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 36.170 +/- 36.170 s +Total User Time : 24.870 +/- 24.870 s +Total System Time: 7.680 +/- 7.680 s +Total Idle Time : 3.620 +/- 3.620 s +Total VmSize incr: 28.704 +/- 28.704 MB +Total VmRSS incr : 28.644 +/- 28.644 MB +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 36.1765 +obj/s: 276.422 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 36.309 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.rh73.501MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.rh73.501MB.out new file mode 100644 index 000000000..2e199cc2f --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.rh73.501MB.out @@ -0,0 +1,102 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.012 +/- 0.012 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.412 +/- 0.412 MB +Total VmRSS incr : 0.412 +/- 0.412 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 10.030 +/- 0.100 s +Total User Time : 5.040 +/- 0.050 s +Total System Time: 1.920 +/- 0.019 s +Total Idle Time : 3.070 +/- 0.031 s +Total VmSize incr: 0.024 +/- 0.000 MB +Total VmRSS incr : 1.460 +/- 0.015 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 11.700 +/- 0.117 s +Total User Time : 9.790 +/- 0.098 s +Total System Time: 1.900 +/- 0.019 s +Total Idle Time : 0.010 +/- 0.000 s +Total VmSize incr: 25.344 +/- 0.253 MB +Total VmRSS incr : 23.880 +/- 0.239 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 34.280 +/- 34.280 s +Total User Time : 23.580 +/- 23.580 s +Total System Time: 7.680 +/- 7.680 s +Total Idle Time : 3.020 +/- 3.020 s +Total VmSize incr: 25.824 +/- 25.824 MB +Total VmRSS incr : 25.764 +/- 25.764 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 34.280 +/- 34.280 s +Total User Time : 23.580 +/- 23.580 s +Total System Time: 7.680 +/- 7.680 s +Total Idle Time : 3.020 +/- 3.020 s +Total VmSize incr: 25.824 +/- 25.824 MB +Total VmRSS incr : 25.772 +/- 25.772 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.990 +/- 0.990 s +Total User Time : 0.980 +/- 0.980 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 3.012 +/- 3.012 MB +Total VmRSS incr : 2.952 +/- 2.952 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 35.430 +/- 35.430 s +Total User Time : 24.720 +/- 24.720 s +Total System Time: 7.680 +/- 7.680 s +Total Idle Time : 3.030 +/- 3.030 s +Total VmSize incr: 28.704 +/- 28.704 MB +Total VmRSS incr : 28.644 +/- 28.644 MB +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 35.4379 +obj/s: 282.184 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 35.576 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.slc3.2006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.slc3.2006MB.out new file mode 100644 index 000000000..37c6ab28f --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-memory.slc3.2006MB.out @@ -0,0 +1,102 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.396 +/- 0.396 MB +Total VmRSS incr : 0.416 +/- 0.416 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 13.060 +/- 0.131 s +Total User Time : 3.450 +/- 0.034 s +Total System Time: 1.230 +/- 0.012 s +Total Idle Time : 8.360 +/- 0.084 s +Total VmSize incr: 0.236 +/- 0.002 MB +Total VmRSS incr : 1.508 +/- 0.015 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 11.050 +/- 0.111 s +Total User Time : 7.860 +/- 0.079 s +Total System Time: 1.160 +/- 0.012 s +Total Idle Time : 2.060 +/- 0.021 s +Total VmSize incr: 27.544 +/- 0.275 MB +Total VmRSS incr : 24.276 +/- 0.243 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 35.960 +/- 35.960 s +Total User Time : 16.850 +/- 16.850 s +Total System Time: 5.000 +/- 5.000 s +Total Idle Time : 14.110 +/- 14.110 s +Total VmSize incr: 26.596 +/- 26.596 MB +Total VmRSS incr : 26.208 +/- 26.208 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 35.960 +/- 35.960 s +Total User Time : 16.850 +/- 16.850 s +Total System Time: 5.000 +/- 5.000 s +Total Idle Time : 14.110 +/- 14.110 s +Total VmSize incr: 26.596 +/- 26.596 MB +Total VmRSS incr : 26.216 +/- 26.216 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 1.470 +/- 1.470 s +Total User Time : 1.370 +/- 1.370 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 0.080 +/- 0.080 s +Total VmSize incr: 3.300 +/- 3.300 MB +Total VmRSS incr : 3.192 +/- 3.192 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.140 +/- 0.140 s +Total User Time : 0.140 +/- 0.140 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 37.610 +/- 37.610 s +Total User Time : 18.390 +/- 18.390 s +Total System Time: 5.020 +/- 5.020 s +Total Idle Time : 14.200 +/- 14.200 s +Total VmSize incr: 29.764 +/- 29.764 MB +Total VmRSS incr : 29.328 +/- 29.328 MB +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 37.6132 +obj/s: 265.864 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 37.7453 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.rh73.1006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.rh73.1006MB.out new file mode 100644 index 000000000..a4d408c08 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.rh73.1006MB.out @@ -0,0 +1,82 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 3.930 +/- 0.039 s +Total User Time : 0.790 +/- 0.008 s +Total System Time: 0.110 +/- 0.001 s +Total Idle Time : 3.020 +/- 0.030 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 5.800 +/- 0.058 s +Total User Time : 5.840 +/- 0.058 s +Total System Time: 0.100 +/- 0.001 s +Total Idle Time : -0.150 +/- -0.002 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 9.910 +/- 9.910 s +Total User Time : 6.730 +/- 6.730 s +Total System Time: 0.210 +/- 0.210 s +Total Idle Time : 2.970 +/- 2.970 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 9.910 +/- 9.910 s +Total User Time : 6.740 +/- 6.740 s +Total System Time: 0.210 +/- 0.210 s +Total Idle Time : 2.960 +/- 2.960 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.990 +/- 0.990 s +Total User Time : 0.980 +/- 0.980 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.170 +/- 0.170 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 11.070 +/- 11.070 s +Total User Time : 7.880 +/- 7.880 s +Total System Time: 0.210 +/- 0.210 s +Total Idle Time : 2.980 +/- 2.980 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 11.0703 +obj/s: 903.317 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 11.2085 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.rh73.501MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.rh73.501MB.out new file mode 100644 index 000000000..4a073d9dc --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.rh73.501MB.out @@ -0,0 +1,82 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 3.880 +/- 0.039 s +Total User Time : 0.610 +/- 0.006 s +Total System Time: 0.010 +/- 0.000 s +Total Idle Time : 3.310 +/- 0.033 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 5.550 +/- 0.056 s +Total User Time : 5.570 +/- 0.056 s +Total System Time: 0.100 +/- 0.001 s +Total Idle Time : -0.070 +/- -0.001 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 9.620 +/- 9.620 s +Total User Time : 6.280 +/- 6.280 s +Total System Time: 0.120 +/- 0.120 s +Total Idle Time : 3.220 +/- 3.220 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 9.630 +/- 9.630 s +Total User Time : 6.280 +/- 6.280 s +Total System Time: 0.120 +/- 0.120 s +Total Idle Time : 3.230 +/- 3.230 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.980 +/- 0.980 s +Total User Time : 0.970 +/- 0.970 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 10.770 +/- 10.770 s +Total User Time : 7.410 +/- 7.410 s +Total System Time: 0.120 +/- 0.120 s +Total Idle Time : 3.240 +/- 3.240 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 10.7714 +obj/s: 928.382 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 10.9092 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.slc3.2006MB.out b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.slc3.2006MB.out new file mode 100644 index 000000000..6f3b75576 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestNewCopy/oldCopy-time.slc3.2006MB.out @@ -0,0 +1,82 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 7.560 +/- 0.076 s +Total User Time : 0.490 +/- 0.005 s +Total System Time: 0.040 +/- 0.000 s +Total Idle Time : 7.060 +/- 0.071 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 7.070 +/- 0.071 s +Total User Time : 4.870 +/- 0.049 s +Total System Time: 0.120 +/- 0.001 s +Total Idle Time : 2.080 +/- 0.021 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 15.210 +/- 15.210 s +Total User Time : 5.520 +/- 5.520 s +Total System Time: 0.180 +/- 0.180 s +Total Idle Time : 9.510 +/- 9.510 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 15.210 +/- 15.210 s +Total User Time : 5.520 +/- 5.520 s +Total System Time: 0.180 +/- 0.180 s +Total Idle Time : 9.510 +/- 9.510 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 2.020 +/- 2.020 s +Total User Time : 1.500 +/- 1.500 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 0.500 +/- 0.500 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.140 +/- 0.140 s +Total User Time : 0.140 +/- 0.140 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 17.370 +/- 17.370 s +Total User Time : 7.160 +/- 7.160 s +Total System Time: 0.200 +/- 0.200 s +Total Idle Time : 10.010 +/- 10.010 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 17.3679 +obj/s: 575.775 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 17.5473 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/execTestRalOnly.rh73.501MB.oracle.out b/RelationalCool/tests/PerformanceAV/TestRalOnly/execTestRalOnly.rh73.501MB.oracle.out new file mode 100644 index 000000000..ab54f9e04 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/execTestRalOnly.rh73.501MB.oracle.out @@ -0,0 +1,4 @@ +7.810u 0.230s 0:13.16 61.0% 0+0k 0+0io 2277pf+0w +0.670u 0.060s 0:05.44 13.4% 0+0k 0+0io 2271pf+0w +25.140u 7.490s 0:37.00 88.1% 0+0k 0+0io 2277pf+0w +0.620u 0.050s 0:05.50 12.1% 0+0k 0+0io 2271pf+0w diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/execTestRalOnly.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestRalOnly/execTestRalOnly.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..8e9207e94 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/execTestRalOnly.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,3 @@ +7.690u 0.330s 0:12.86 62.3% 0+0k 0+0io 2277pf+0w +0.630u 0.120s 0:05.27 14.2% 0+0k 0+0io 2271pf+0w + diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-memory.rh73.501MB.oracle.out b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-memory.rh73.501MB.oracle.out new file mode 100644 index 000000000..85f63b64e --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-memory.rh73.501MB.oracle.out @@ -0,0 +1,103 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.012 +/- 0.012 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.250 +/- 0.250 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.250 +/- 0.250 s +Total VmSize incr: 0.412 +/- 0.412 MB +Total VmRSS incr : 0.404 +/- 0.404 MB +----- 3.FetchRows-------------- : ( n=1 ) +Total Real Time : 3.730 +/- 3.730 s +Total User Time : 0.430 +/- 0.430 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 3.280 +/- 3.280 s +Total VmSize incr: 0.012 +/- 0.012 MB +Total VmRSS incr : 0.028 +/- 0.028 MB +----- 4.CopyAttributeList------ : ( n=0 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 3.990 +/- 3.990 s +Total User Time : 0.430 +/- 0.430 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 3.540 +/- 3.540 s +Total VmSize incr: 0.424 +/- 0.424 MB +Total VmRSS incr : 0.444 +/- 0.444 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 4.000 +/- 4.000 s +Total User Time : 0.440 +/- 0.440 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 3.540 +/- 3.540 s +Total VmSize incr: 0.436 +/- 0.436 MB +Total VmRSS incr : 0.468 +/- 0.468 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 4.010 +/- 4.010 s +Total User Time : 0.440 +/- 0.440 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 3.550 +/- 3.550 s +Total VmSize incr: 0.436 +/- 0.436 MB +Total VmRSS incr : 0.468 +/- 0.468 MB +** reading 100000 objects (150 bytes mixed) ** +read back 0 objects +sec total: 4.01592 +obj/s: 0 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 4.03061 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.out b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.out new file mode 100644 index 000000000..b74733f8a --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.out @@ -0,0 +1,83 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.240 +/- 0.240 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.240 +/- 0.240 s +----- 3.FetchRows-------------- : ( n=1 ) +Total Real Time : 3.850 +/- 3.850 s +Total User Time : 0.490 +/- 0.490 s +Total System Time: 0.030 +/- 0.030 s +Total Idle Time : 3.330 +/- 3.330 s +----- 4.CopyAttributeList------ : ( n=0 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 4.100 +/- 4.100 s +Total User Time : 0.490 +/- 0.490 s +Total System Time: 0.030 +/- 0.030 s +Total Idle Time : 3.580 +/- 3.580 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 4.110 +/- 4.110 s +Total User Time : 0.490 +/- 0.490 s +Total System Time: 0.030 +/- 0.030 s +Total Idle Time : 3.590 +/- 3.590 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 4.120 +/- 4.120 s +Total User Time : 0.490 +/- 0.490 s +Total System Time: 0.030 +/- 0.030 s +Total Idle Time : 3.600 +/- 3.600 s +** reading 100000 objects (150 bytes mixed) ** +read back 0 objects +sec total: 4.1212 +obj/s: 0 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 4.13695 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..b76b5bbc8 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,83 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.FetchRows-------------- : ( n=1 ) +Total Real Time : 3.790 +/- 3.790 s +Total User Time : 0.470 +/- 0.470 s +Total System Time: 0.060 +/- 0.060 s +Total Idle Time : 3.260 +/- 3.260 s +----- 4.CopyAttributeList------ : ( n=0 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 3.810 +/- 3.810 s +Total User Time : 0.470 +/- 0.470 s +Total System Time: 0.060 +/- 0.060 s +Total Idle Time : 3.280 +/- 3.280 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 3.810 +/- 3.810 s +Total User Time : 0.470 +/- 0.470 s +Total System Time: 0.060 +/- 0.060 s +Total Idle Time : 3.280 +/- 3.280 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.020 +/- 0.020 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.020 +/- 0.020 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 3.830 +/- 3.830 s +Total User Time : 0.470 +/- 0.470 s +Total System Time: 0.060 +/- 0.060 s +Total Idle Time : 3.300 +/- 3.300 s +** reading 100000 objects (150 bytes mixed) ** +read back 0 objects +sec total: 3.8278 +obj/s: 0 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 3.84342 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.prf b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.prf new file mode 100644 index 000000000..7fcafc1cb --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.prf @@ -0,0 +1,239 @@ + +TKPROF: Release 9.2.0.6.0 - Production on Tue Feb 1 14:51:57 2005 + +Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. + +Trace file: cooldb2_ora_5020.trc +Sort options: exeela fchcnt +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 197 3.48 3.39 0 34442 140451 19604 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 199 3.48 3.39 0 34442 140451 19604 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 10000 SORT ORDER BY + 10000 TABLE ACCESS FULL COOLTEST_F0001_IOVS + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 197 0.00 0.00 + SQL*Net more data to client 1177 0.00 0.05 + SQL*Net message from client 197 0.00 0.56 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 2 7 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 2 7 1 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 122 0 8 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.00 0.00 0 10 19 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.00 0.00 0 10 19 2 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 3 0.00 0.00 + SQL*Net message from client 3 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 203 3.48 3.40 0 34576 140477 19615 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 212 3.48 3.40 0 34576 140477 19615 + +Misses in library cache during parse: 0 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 216 0.00 0.00 + SQL*Net message from client 216 0.98 1.58 + SQL*Net more data to client 1178 0.00 0.05 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: cooldb2_ora_5020.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchcnt + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 5 unique SQL statements in trace file. + 1911 lines in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.prf.ANALYZED b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.prf.ANALYZED new file mode 100644 index 000000000..e1763e135 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/ralOnly-time.rh73.501MB.oracle.prf.ANALYZED @@ -0,0 +1,239 @@ + +TKPROF: Release 9.2.0.6.0 - Production on Tue Feb 1 15:12:08 2005 + +Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. + +Trace file: cooldb2_ora_5101.trc +Sort options: exeela fchcnt +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 197 3.15 3.10 0 31647 140451 19604 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 199 3.15 3.10 0 31647 140451 19604 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 10000 TABLE ACCESS BY INDEX ROWID COOLTEST_F0001_IOVS + 10000 INDEX RANGE SCAN COOLTEST_F0001_IOVS_CSU_3INDX (object id 8142) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 197 0.00 0.00 + SQL*Net more data to client 1177 0.00 0.04 + SQL*Net message from client 197 0.00 0.57 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 2 7 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 2 7 1 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 122 0 8 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.00 0.00 0 10 19 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.00 0.00 0 10 19 2 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 3 0.00 0.00 + SQL*Net message from client 3 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 203 3.15 3.11 0 31781 140477 19615 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 212 3.15 3.11 0 31781 140477 19615 + +Misses in library cache during parse: 0 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 216 0.00 0.00 + SQL*Net message from client 216 0.98 1.59 + SQL*Net more data to client 1178 0.00 0.04 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: cooldb2_ora_5101.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchcnt + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 5 unique SQL statements in trace file. + 1911 lines in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-memory.rh73.501MB.oracle.out b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-memory.rh73.501MB.oracle.out new file mode 100644 index 000000000..fcebcd2cf --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-memory.rh73.501MB.oracle.out @@ -0,0 +1,103 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.012 +/- 0.012 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.250 +/- 0.250 s +Total User Time : 0.020 +/- 0.020 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.230 +/- 0.230 s +Total VmSize incr: 0.412 +/- 0.412 MB +Total VmRSS incr : 0.404 +/- 0.404 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 10.360 +/- 0.104 s +Total User Time : 4.880 +/- 0.049 s +Total System Time: 1.910 +/- 0.019 s +Total Idle Time : 3.590 +/- 0.036 s +Total VmSize incr: 0.448 +/- 0.004 MB +Total VmRSS incr : 1.528 +/- 0.015 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 11.370 +/- 0.114 s +Total User Time : 10.000 +/- 0.100 s +Total System Time: 1.770 +/- 0.018 s +Total Idle Time : -0.400 +/- -0.004 s +Total VmSize incr: 25.092 +/- 0.251 MB +Total VmRSS incr : 23.796 +/- 0.238 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 34.380 +/- 34.380 s +Total User Time : 23.690 +/- 23.690 s +Total System Time: 7.390 +/- 7.390 s +Total Idle Time : 3.300 +/- 3.300 s +Total VmSize incr: 26.016 +/- 26.016 MB +Total VmRSS incr : 25.740 +/- 25.740 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 34.380 +/- 34.380 s +Total User Time : 23.700 +/- 23.700 s +Total System Time: 7.390 +/- 7.390 s +Total Idle Time : 3.290 +/- 3.290 s +Total VmSize incr: 26.028 +/- 26.028 MB +Total VmRSS incr : 25.752 +/- 25.752 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.990 +/- 0.990 s +Total User Time : 0.960 +/- 0.960 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.020 +/- 0.020 s +Total VmSize incr: 3.016 +/- 3.016 MB +Total VmRSS incr : 2.956 +/- 2.956 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 35.530 +/- 35.530 s +Total User Time : 24.820 +/- 24.820 s +Total System Time: 7.400 +/- 7.400 s +Total Idle Time : 3.310 +/- 3.310 s +Total VmSize incr: 28.912 +/- 28.912 MB +Total VmRSS incr : 28.628 +/- 28.628 MB +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 35.5368 +obj/s: 281.398 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 35.6753 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.out b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.out new file mode 100644 index 000000000..50c33f562 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.out @@ -0,0 +1,83 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.250 +/- 0.250 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.250 +/- 0.250 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 4.180 +/- 0.042 s +Total User Time : 0.630 +/- 0.006 s +Total System Time: 0.040 +/- 0.000 s +Total Idle Time : 3.530 +/- 0.035 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 5.550 +/- 0.056 s +Total User Time : 5.640 +/- 0.056 s +Total System Time: 0.060 +/- 0.001 s +Total Idle Time : -0.130 +/- -0.001 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 10.120 +/- 10.120 s +Total User Time : 6.400 +/- 6.400 s +Total System Time: 0.110 +/- 0.110 s +Total Idle Time : 3.610 +/- 3.610 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 10.120 +/- 10.120 s +Total User Time : 6.400 +/- 6.400 s +Total System Time: 0.110 +/- 0.110 s +Total Idle Time : 3.610 +/- 3.610 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 1.010 +/- 1.010 s +Total User Time : 0.960 +/- 0.960 s +Total System Time: 0.030 +/- 0.030 s +Total Idle Time : 0.020 +/- 0.020 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.150 +/- 0.150 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 11.290 +/- 11.290 s +Total User Time : 7.510 +/- 7.510 s +Total System Time: 0.140 +/- 0.140 s +Total Idle Time : 3.640 +/- 3.640 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 11.2898 +obj/s: 885.756 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 11.4288 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..0d0e57422 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,83 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.220 +/- 0.220 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.210 +/- 0.210 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 4.090 +/- 0.041 s +Total User Time : 0.730 +/- 0.007 s +Total System Time: 0.100 +/- 0.001 s +Total Idle Time : 3.250 +/- 0.032 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 5.550 +/- 0.056 s +Total User Time : 5.410 +/- 0.054 s +Total System Time: 0.110 +/- 0.001 s +Total Idle Time : 0.070 +/- 0.001 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 10.020 +/- 10.020 s +Total User Time : 6.240 +/- 6.240 s +Total System Time: 0.250 +/- 0.250 s +Total Idle Time : 3.530 +/- 3.530 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 10.030 +/- 10.030 s +Total User Time : 6.240 +/- 6.240 s +Total System Time: 0.250 +/- 0.250 s +Total Idle Time : 3.540 +/- 3.540 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.970 +/- 0.970 s +Total User Time : 0.970 +/- 0.970 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 11.160 +/- 11.160 s +Total User Time : 7.370 +/- 7.370 s +Total System Time: 0.250 +/- 0.250 s +Total Idle Time : 3.540 +/- 3.540 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 11.1632 +obj/s: 895.803 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 11.3014 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.prf b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.prf new file mode 100644 index 000000000..8b3af0e32 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.prf @@ -0,0 +1,241 @@ + +TKPROF: Release 9.2.0.6.0 - Production on Tue Feb 1 14:51:49 2005 + +Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. + +Trace file: cooldb2_ora_5014.trc +Sort options: exeela fchcnt +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 197 3.61 3.42 32 34442 140447 19604 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 199 3.61 3.42 32 34442 140447 19604 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 10000 SORT ORDER BY + 10000 TABLE ACCESS FULL COOLTEST_F0001_IOVS + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 197 0.00 0.00 + db file scattered read 16 0.00 0.00 + SQL*Net more data to client 1177 0.00 0.04 + SQL*Net message from client 197 0.06 6.41 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 2 7 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 2 7 1 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.01 0.00 0 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.01 0.00 0 122 0 8 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.01 0.00 0 10 19 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.01 0.00 0 10 19 2 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 3 0.00 0.00 + SQL*Net message from client 3 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 203 3.63 3.43 32 34576 140473 19615 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 212 3.63 3.43 32 34576 140473 19615 + +Misses in library cache during parse: 0 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 216 0.00 0.00 + SQL*Net message from client 216 1.24 8.67 + SQL*Net more data to client 1178 0.00 0.04 + db file scattered read 16 0.00 0.00 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: cooldb2_ora_5014.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchcnt + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 5 unique SQL statements in trace file. + 1927 lines in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.prf.ANALYZED b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.prf.ANALYZED new file mode 100644 index 000000000..06691fa26 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestRalOnly/withCool-time.rh73.501MB.oracle.prf.ANALYZED @@ -0,0 +1,239 @@ + +TKPROF: Release 9.2.0.6.0 - Production on Tue Feb 1 15:11:57 2005 + +Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. + +Trace file: cooldb2_ora_5099.trc +Sort options: exeela fchcnt +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 197 3.33 3.13 0 31647 140451 19604 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 199 3.33 3.13 0 31647 140451 19604 + +Misses in library cache during parse: 1 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 10000 TABLE ACCESS BY INDEX ROWID COOLTEST_F0001_IOVS + 10000 INDEX RANGE SCAN COOLTEST_F0001_IOVS_CSU_3INDX (object id 8142) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 197 0.00 0.00 + SQL*Net more data to client 1177 0.00 0.04 + SQL*Net message from client 197 0.26 6.60 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 2 7 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 2 7 1 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.01 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.01 0.00 0 122 0 8 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.01 0.00 0 10 19 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.01 0.00 0 10 19 2 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 3 0.00 0.00 + SQL*Net message from client 3 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.01 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 203 3.34 3.13 0 31781 140477 19615 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 212 3.35 3.14 0 31781 140477 19615 + +Misses in library cache during parse: 1 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 216 0.00 0.00 + SQL*Net message from client 216 1.21 8.84 + SQL*Net more data to client 1178 0.00 0.04 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: cooldb2_ora_5099.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchcnt + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 5 unique SQL statements in trace file. + 1911 lines in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/TestScrollableCursor/execTestScrollableCursor.rh73.1006MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/execTestScrollableCursor.rh73.1006MB.oracle.out.ANALYZED new file mode 100644 index 000000000..e992a6cb7 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/execTestScrollableCursor.rh73.1006MB.oracle.out.ANALYZED @@ -0,0 +1,5 @@ +3.600u 0.220s 0:08.22 46.4% 0+0k 0+0io 2274pf+0w +3.590u 0.210s 0:04.99 76.1% 0+0k 0+0io 2273pf+0w +21.360u 7.090s 0:33.04 86.1% 0+0k 0+0io 2274pf+0w +20.990u 7.250s 0:29.71 95.0% 0+0k 0+0io 2273pf+0w + diff --git a/RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-memory.rh73.1006MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-memory.rh73.1006MB.oracle.out.ANALYZED new file mode 100644 index 000000000..e0ed13c11 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-memory.rh73.1006MB.oracle.out.ANALYZED @@ -0,0 +1,110 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.012 +/- 0.012 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.412 +/- 0.412 MB +Total VmRSS incr : 0.404 +/- 0.404 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 6.700 +/- 0.067 s +Total User Time : 4.900 +/- 0.049 s +Total System Time: 1.780 +/- 0.018 s +Total Idle Time : 0.020 +/- 0.000 s +Total VmSize incr: 0.012 +/- 0.000 MB +Total VmRSS incr : 0.024 +/- 0.000 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 7.970 +/- 0.080 s +Total User Time : 6.210 +/- 0.062 s +Total System Time: 1.550 +/- 0.015 s +Total Idle Time : 0.250 +/- 0.003 s +Total VmSize incr: 12.216 +/- 0.122 MB +Total VmRSS incr : 12.172 +/- 0.122 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 27.240 +/- 27.240 s +Total User Time : 19.690 +/- 19.690 s +Total System Time: 7.180 +/- 7.180 s +Total Idle Time : 0.370 +/- 0.370 s +Total VmSize incr: 12.680 +/- 12.680 MB +Total VmRSS incr : 12.612 +/- 12.612 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 27.240 +/- 27.240 s +Total User Time : 19.690 +/- 19.690 s +Total System Time: 7.180 +/- 7.180 s +Total Idle Time : 0.370 +/- 0.370 s +Total VmSize incr: 12.692 +/- 12.692 MB +Total VmRSS incr : 12.636 +/- 12.636 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.980 +/- 0.980 s +Total User Time : 0.980 +/- 0.980 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 3.032 +/- 3.032 MB +Total VmRSS incr : 2.980 +/- 2.980 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.110 +/- 0.110 s +Total User Time : 0.100 +/- 0.100 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.076 +/- -0.076 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 28.340 +/- 28.340 s +Total User Time : 20.770 +/- 20.770 s +Total System Time: 7.190 +/- 7.190 s +Total Idle Time : 0.380 +/- 0.380 s +Total VmSize incr: 15.460 +/- 15.460 MB +Total VmRSS incr : 15.460 +/- 15.460 MB +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 28.3538 +obj/s: 352.687 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 28.3953 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-time.rh73.1006MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-time.rh73.1006MB.oracle.out.ANALYZED new file mode 100644 index 000000000..7b155b4e3 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-time.rh73.1006MB.oracle.out.ANALYZED @@ -0,0 +1,88 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 0.680 +/- 0.007 s +Total User Time : 0.400 +/- 0.004 s +Total System Time: 0.040 +/- 0.000 s +Total Idle Time : 0.260 +/- 0.003 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 1.800 +/- 0.018 s +Total User Time : 1.810 +/- 0.018 s +Total System Time: 0.080 +/- 0.001 s +Total Idle Time : -0.070 +/- -0.001 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 2.550 +/- 2.550 s +Total User Time : 2.290 +/- 2.290 s +Total System Time: 0.140 +/- 0.140 s +Total Idle Time : 0.120 +/- 0.120 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 2.560 +/- 2.560 s +Total User Time : 2.290 +/- 2.290 s +Total System Time: 0.140 +/- 0.140 s +Total Idle Time : 0.130 +/- 0.130 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.980 +/- 0.980 s +Total User Time : 0.980 +/- 0.980 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.100 +/- 0.100 s +Total User Time : 0.110 +/- 0.110 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 3.650 +/- 3.650 s +Total User Time : 3.380 +/- 3.380 s +Total System Time: 0.140 +/- 0.140 s +Total Idle Time : 0.130 +/- 0.130 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 3.66011 +obj/s: 2732.16 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 3.69912 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-time.rh73.1006MB.oracle.prf.ANALYZED b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-time.rh73.1006MB.oracle.prf.ANALYZED new file mode 100644 index 000000000..0d82221fd --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/notScrollable-time.rh73.1006MB.oracle.prf.ANALYZED @@ -0,0 +1,239 @@ + +TKPROF: Release 9.2.0.6.0 - Production on Wed Feb 2 10:33:23 2005 + +Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. + +Trace file: notScrollable.trc +Sort options: exeela fchcnt +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 100 0.15 0.17 0 852 0 10000 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 102 0.15 0.17 0 852 0 10000 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 10000 TABLE ACCESS BY INDEX ROWID COOLTEST_F0001_IOVS + 10000 INDEX RANGE SCAN COOLTEST_F0001_IOVS_CSU_3INDX (object id 8142) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 100 0.00 0.00 + SQL*Net more data to client 595 0.00 0.01 + SQL*Net message from client 100 0.02 2.30 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 2 0 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 2 0 1 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 122 0 8 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 8 0 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 8 0 2 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 105 0.15 0.17 0 984 0 10011 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 114 0.15 0.18 0 984 0 10011 + +Misses in library cache during parse: 0 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 118 0.00 0.00 + SQL*Net message from client 118 1.10 4.41 + SQL*Net more data to client 596 0.00 0.01 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: notScrollable.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchcnt + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 5 unique SQL statements in trace file. + 1035 lines in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-memory.rh73.1006MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-memory.rh73.1006MB.oracle.out.ANALYZED new file mode 100644 index 000000000..85df71f55 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-memory.rh73.1006MB.oracle.out.ANALYZED @@ -0,0 +1,110 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.012 +/- 0.012 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.020 +/- 0.020 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.020 +/- 0.020 s +Total VmSize incr: 0.412 +/- 0.412 MB +Total VmRSS incr : 0.404 +/- 0.404 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 10.280 +/- 0.103 s +Total User Time : 4.970 +/- 0.050 s +Total System Time: 1.750 +/- 0.017 s +Total Idle Time : 3.580 +/- 0.036 s +Total VmSize incr: 0.024 +/- 0.000 MB +Total VmRSS incr : 0.024 +/- 0.000 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 7.930 +/- 0.079 s +Total User Time : 6.310 +/- 0.063 s +Total System Time: 1.710 +/- 0.017 s +Total Idle Time : -0.110 +/- -0.001 s +Total VmSize incr: 12.196 +/- 0.122 MB +Total VmRSS incr : 12.172 +/- 0.122 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 30.560 +/- 30.560 s +Total User Time : 20.020 +/- 20.020 s +Total System Time: 7.020 +/- 7.020 s +Total Idle Time : 3.520 +/- 3.520 s +Total VmSize incr: 12.672 +/- 12.672 MB +Total VmRSS incr : 12.612 +/- 12.612 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 30.570 +/- 30.570 s +Total User Time : 20.030 +/- 20.030 s +Total System Time: 7.020 +/- 7.020 s +Total Idle Time : 3.520 +/- 3.520 s +Total VmSize incr: 12.684 +/- 12.684 MB +Total VmRSS incr : 12.636 +/- 12.636 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.990 +/- 0.990 s +Total User Time : 0.990 +/- 0.990 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 3.040 +/- 3.040 MB +Total VmRSS incr : 2.980 +/- 2.980 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.110 +/- 0.110 s +Total User Time : 0.100 +/- 0.100 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.076 +/- -0.076 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 31.680 +/- 31.680 s +Total User Time : 21.120 +/- 21.120 s +Total System Time: 7.020 +/- 7.020 s +Total Idle Time : 3.540 +/- 3.540 s +Total VmSize incr: 15.460 +/- 15.460 MB +Total VmRSS incr : 15.460 +/- 15.460 MB +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 31.6942 +obj/s: 315.516 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 31.7334 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-time.rh73.1006MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-time.rh73.1006MB.oracle.out.ANALYZED new file mode 100644 index 000000000..3a4968c38 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-time.rh73.1006MB.oracle.out.ANALYZED @@ -0,0 +1,88 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 3.760 +/- 0.038 s +Total User Time : 0.590 +/- 0.006 s +Total System Time: 0.110 +/- 0.001 s +Total Idle Time : 3.020 +/- 0.030 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 1.860 +/- 0.019 s +Total User Time : 1.600 +/- 0.016 s +Total System Time: 0.050 +/- 0.001 s +Total Idle Time : 0.220 +/- 0.002 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 5.740 +/- 5.740 s +Total User Time : 2.270 +/- 2.270 s +Total System Time: 0.170 +/- 0.170 s +Total Idle Time : 3.300 +/- 3.300 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 5.740 +/- 5.740 s +Total User Time : 2.280 +/- 2.280 s +Total System Time: 0.170 +/- 0.170 s +Total Idle Time : 3.290 +/- 3.290 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 1.000 +/- 1.000 s +Total User Time : 0.990 +/- 0.990 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.110 +/- 0.110 s +Total User Time : 0.100 +/- 0.100 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 6.850 +/- 6.850 s +Total User Time : 3.380 +/- 3.380 s +Total System Time: 0.170 +/- 0.170 s +Total Idle Time : 3.300 +/- 3.300 s +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 6.86195 +obj/s: 1457.31 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 6.90321 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-time.rh73.1006MB.oracle.prf.ANALYZED b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-time.rh73.1006MB.oracle.prf.ANALYZED new file mode 100644 index 000000000..550117029 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestScrollableCursor/scrollable-time.rh73.1006MB.oracle.prf.ANALYZED @@ -0,0 +1,239 @@ + +TKPROF: Release 9.2.0.6.0 - Production on Wed Feb 2 10:33:29 2005 + +Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. + +Trace file: scrollable.trc +Sort options: exeela fchcnt +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 197 2.99 3.10 0 31647 140447 19604 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 199 2.99 3.10 0 31647 140447 19604 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 10000 TABLE ACCESS BY INDEX ROWID COOLTEST_F0001_IOVS + 10000 INDEX RANGE SCAN COOLTEST_F0001_IOVS_CSU_3INDX (object id 8142) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 197 0.00 0.00 + SQL*Net more data to client 1177 0.00 0.04 + SQL*Net message from client 197 0.02 2.46 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 2 7 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 2 7 1 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 122 0 8 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.00 0.00 0 10 19 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.00 0.00 0 10 19 2 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 3 0.00 0.00 + SQL*Net message from client 3 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 203 2.99 3.10 0 31781 140473 19615 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 212 2.99 3.10 0 31781 140473 19615 + +Misses in library cache during parse: 0 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 216 0.00 0.00 + SQL*Net message from client 216 1.10 4.57 + SQL*Net more data to client 1178 0.00 0.04 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: scrollable.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchcnt + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 5 unique SQL statements in trace file. + 1911 lines in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-memory.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-memory.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..01ca28da3 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-memory.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,112 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.004 +/- 0.004 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.404 +/- 0.404 MB +Total VmRSS incr : 0.408 +/- 0.408 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 7.250 +/- 0.072 s +Total User Time : 5.120 +/- 0.051 s +Total System Time: 1.760 +/- 0.018 s +Total Idle Time : 0.360 +/- 0.004 s +Total VmSize incr: 0.172 +/- 0.002 MB +Total VmRSS incr : 1.540 +/- 0.015 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 11.680 +/- 0.117 s +Total User Time : 9.880 +/- 0.099 s +Total System Time: 1.830 +/- 0.018 s +Total Idle Time : -0.010 +/- -0.000 s +Total VmSize incr: 24.504 +/- 0.245 MB +Total VmRSS incr : 23.788 +/- 0.238 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 31.650 +/- 31.650 s +Total User Time : 23.890 +/- 23.890 s +Total System Time: 7.430 +/- 7.430 s +Total Idle Time : 0.330 +/- 0.330 s +Total VmSize incr: 25.772 +/- 25.772 MB +Total VmRSS incr : 25.740 +/- 25.740 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 31.650 +/- 31.650 s +Total User Time : 23.900 +/- 23.900 s +Total System Time: 7.430 +/- 7.430 s +Total Idle Time : 0.320 +/- 0.320 s +Total VmSize incr: 25.784 +/- 25.784 MB +Total VmRSS incr : 25.756 +/- 25.756 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.950 +/- 0.950 s +Total User Time : 0.950 +/- 0.950 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 3.008 +/- 3.008 MB +Total VmRSS incr : 2.952 +/- 2.952 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.028 +/- 0.028 MB +Total VmRSS incr : 0.076 +/- 0.076 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 32.780 +/- 32.780 s +Total User Time : 25.020 +/- 25.020 s +Total System Time: 7.430 +/- 7.430 s +Total Idle Time : 0.330 +/- 0.330 s +Total VmSize incr: 28.688 +/- 28.688 MB +Total VmRSS incr : 28.704 +/- 28.704 MB +==> First object: since=0 +==> Last object: since=9999 +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 32.7868 +obj/s: 305.001 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 32.9312 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-time.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-time.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..bbe0dde5a --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-time.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,90 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 0.980 +/- 0.010 s +Total User Time : 0.620 +/- 0.006 s +Total System Time: 0.050 +/- 0.000 s +Total Idle Time : 0.300 +/- 0.003 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 5.560 +/- 0.056 s +Total User Time : 5.490 +/- 0.055 s +Total System Time: 0.130 +/- 0.001 s +Total Idle Time : -0.070 +/- -0.001 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 6.650 +/- 6.650 s +Total User Time : 6.230 +/- 6.230 s +Total System Time: 0.190 +/- 0.190 s +Total Idle Time : 0.230 +/- 0.230 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 6.650 +/- 6.650 s +Total User Time : 6.230 +/- 6.230 s +Total System Time: 0.190 +/- 0.190 s +Total Idle Time : 0.230 +/- 0.230 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.950 +/- 0.950 s +Total User Time : 0.930 +/- 0.930 s +Total System Time: 0.020 +/- 0.020 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.160 +/- 0.160 s +Total User Time : 0.160 +/- 0.160 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 7.770 +/- 7.770 s +Total User Time : 7.330 +/- 7.330 s +Total System Time: 0.210 +/- 0.210 s +Total Idle Time : 0.230 +/- 0.230 s +==> First object: since=0 +==> Last object: since=9999 +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 7.77131 +obj/s: 1286.78 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 7.90669 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-time.rh73.501MB.oracle.prf.ANALYZED b/RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-time.rh73.501MB.oracle.prf.ANALYZED new file mode 100644 index 000000000..4c009ece1 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestShareData/doNotShareData-time.rh73.501MB.oracle.prf.ANALYZED @@ -0,0 +1,239 @@ + +TKPROF: Release 9.2.0.6.0 - Production on Tue Feb 1 19:54:46 2005 + +Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. + +Trace file: doNotShareData.trc +Sort options: exeela fchcnt +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 197 3.06 3.02 0 31647 140451 19604 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 199 3.06 3.02 0 31647 140451 19604 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 10000 TABLE ACCESS BY INDEX ROWID COOLTEST_F0001_IOVS + 10000 INDEX RANGE SCAN COOLTEST_F0001_IOVS_CSU_3INDX (object id 8142) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 197 0.00 0.00 + SQL*Net more data to client 1177 0.00 0.04 + SQL*Net message from client 197 0.06 6.57 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 2 7 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 2 7 1 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.00 0.00 0 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.00 0.00 0 122 0 8 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.00 0.00 0 10 19 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.00 0.00 0 10 19 2 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 3 0.00 0.00 + SQL*Net message from client 3 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 203 3.06 3.03 0 31781 140477 19615 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 212 3.06 3.03 0 31781 140477 19615 + +Misses in library cache during parse: 0 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 216 0.00 0.00 + SQL*Net message from client 216 1.26 8.85 + SQL*Net more data to client 1178 0.00 0.04 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: doNotShareData.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchcnt + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 5 unique SQL statements in trace file. + 1911 lines in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/TestShareData/execTestShareData.out.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestShareData/execTestShareData.out.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..df0b7f12c --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestShareData/execTestShareData.out.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,5 @@ +3.580u 0.140s 0:05.05 73.6% 0+0k 0+0io 2281pf+0w +7.660u 0.250s 0:09.21 85.8% 0+0k 0+0io 2286pf+0w +20.480u 7.570s 0:29.45 95.2% 0+0k 0+0io 2281pf+0w +25.350u 7.480s 0:34.42 95.3% 0+0k 0+0io 2286pf+0w + diff --git a/RelationalCool/tests/PerformanceAV/TestShareData/shareData-memory.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestShareData/shareData-memory.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..f4038f479 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestShareData/shareData-memory.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,112 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.004 +/- 0.004 MB +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.404 +/- 0.404 MB +Total VmRSS incr : 0.408 +/- 0.408 MB +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 7.140 +/- 0.071 s +Total User Time : 4.920 +/- 0.049 s +Total System Time: 1.830 +/- 0.018 s +Total Idle Time : 0.370 +/- 0.004 s +Total VmSize incr: 0.012 +/- 0.000 MB +Total VmRSS incr : 0.020 +/- 0.000 MB +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 7.730 +/- 0.077 s +Total User Time : 5.820 +/- 0.058 s +Total System Time: 1.900 +/- 0.019 s +Total Idle Time : 0.020 +/- 0.000 s +Total VmSize incr: 12.212 +/- 0.122 MB +Total VmRSS incr : 12.160 +/- 0.122 MB +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 0.000 +/- 0.000 MB +Total VmRSS incr : 0.000 +/- 0.000 MB +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 27.010 +/- 27.010 s +Total User Time : 19.220 +/- 19.220 s +Total System Time: 7.480 +/- 7.480 s +Total Idle Time : 0.310 +/- 0.310 s +Total VmSize incr: 12.824 +/- 12.824 MB +Total VmRSS incr : 12.596 +/- 12.596 MB +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 27.010 +/- 27.010 s +Total User Time : 19.230 +/- 19.230 s +Total System Time: 7.480 +/- 7.480 s +Total Idle Time : 0.300 +/- 0.300 s +Total VmSize incr: 12.836 +/- 12.836 MB +Total VmRSS incr : 12.628 +/- 12.628 MB +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.950 +/- 0.950 s +Total User Time : 0.940 +/- 0.940 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: 3.016 +/- 3.016 MB +Total VmRSS incr : 2.956 +/- 2.956 MB +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.100 +/- 0.100 s +Total User Time : 0.100 +/- 0.100 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.080 +/- -0.080 MB +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +Total VmSize incr: -0.132 +/- -0.132 MB +Total VmRSS incr : -0.076 +/- -0.076 MB +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 28.080 +/- 28.080 s +Total User Time : 20.280 +/- 20.280 s +Total System Time: 7.500 +/- 7.500 s +Total Idle Time : 0.300 +/- 0.300 s +Total VmSize incr: 15.588 +/- 15.588 MB +Total VmRSS incr : 15.428 +/- 15.428 MB +==> First object: since=9999 +==> Last object: since=9999 +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 28.0914 +obj/s: 355.981 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 28.1286 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestShareData/shareData-time.rh73.501MB.oracle.out.ANALYZED b/RelationalCool/tests/PerformanceAV/TestShareData/shareData-time.rh73.501MB.oracle.out.ANALYZED new file mode 100644 index 000000000..43c2ea5cd --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestShareData/shareData-time.rh73.501MB.oracle.out.ANALYZED @@ -0,0 +1,90 @@ +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 9.2.0.6.0 +POOL/RelationalPlugins/oracle Warning Environment variable RAL_SQLTRACE is set: enable SQL_TRACE +POOL/RelationalPlugins/oracle Debug Prepared statement : "alter session set events '10046 trace name context forever, level 12'" +POOL/RelationalPlugins/oracle Warning SQL_TRACE enabled +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'AVALASSI'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM "AVALASSI"."COOLTEST_DB_ATTRIBUTES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME" FROM "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/myfolder' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" FROM "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC,"IOV_SINCE" ASC" +>>>>>> Timing Results <<<<<<<<<< +----- 1.PrepareQuery----------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +----- 2.ProcessQuery----------- : ( n=1 ) +Total Real Time : 0.010 +/- 0.010 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.FetchRows-------------- : ( n=10001 ) +Total Real Time : 0.840 +/- 0.008 s +Total User Time : 0.460 +/- 0.005 s +Total System Time: 0.020 +/- 0.000 s +Total Idle Time : 0.390 +/- 0.004 s +----- 4.CopyAttributeList------ : ( n=10000 ) +Total Real Time : 1.640 +/- 0.016 s +Total User Time : 1.780 +/- 0.018 s +Total System Time: 0.040 +/- 0.000 s +Total Idle Time : -0.180 +/- -0.002 s +----- 5.CloseQuery------------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.000 +/- 0.000 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.000 +/- 0.000 s +----- TOTAL FetchObjRowsByVal-- : ( n=1 ) +Total Real Time : 2.620 +/- 2.620 s +Total User Time : 2.290 +/- 2.290 s +Total System Time: 0.070 +/- 0.070 s +Total Idle Time : 0.260 +/- 0.260 s +>>>>>> Timing Results <<<<<<<<<< +----- 1.FetchObjRowsByVal----- : ( n=1 ) +Total Real Time : 2.620 +/- 2.620 s +Total User Time : 2.290 +/- 2.290 s +Total System Time: 0.080 +/- 0.080 s +Total Idle Time : 0.250 +/- 0.250 s +----- 2.DecodeRow------------- : ( n=1 ) +Total Real Time : 0.960 +/- 0.960 s +Total User Time : 0.950 +/- 0.950 s +Total System Time: 0.010 +/- 0.010 s +Total Idle Time : 0.000 +/- 0.000 s +----- 3.DeleteOld------------- : ( n=1 ) +Total Real Time : 0.110 +/- 0.110 s +Total User Time : 0.100 +/- 0.100 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : 0.010 +/- 0.010 s +----- 4.FillIterator---------- : ( n=1 ) +Total Real Time : 0.000 +/- 0.000 s +Total User Time : 0.010 +/- 0.010 s +Total System Time: 0.000 +/- 0.000 s +Total Idle Time : -0.010 +/- -0.010 s +----- TOTAL BrowseObjInTag---- : ( n=1 ) +Total Real Time : 3.690 +/- 3.690 s +Total User Time : 3.350 +/- 3.350 s +Total System Time: 0.090 +/- 0.090 s +Total Idle Time : 0.250 +/- 0.250 s +==> First object: since=9999 +==> Last object: since=9999 +** reading 100000 objects (150 bytes mixed) ** +read back 10000 objects +sec total: 3.69822 +obj/s: 2704.01 +RelationalFolder Debug Delete the RelationalFolder for '/myfolder' +sec total (INCLUDING DELETE): 3.73535 + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://cooldb2;schema=AVALASSI;user=avalassi;password=andrea;dbname=COOLTEST' diff --git a/RelationalCool/tests/PerformanceAV/TestShareData/shareData-time.rh73.501MB.oracle.prf.ANALYZED b/RelationalCool/tests/PerformanceAV/TestShareData/shareData-time.rh73.501MB.oracle.prf.ANALYZED new file mode 100644 index 000000000..db4dad511 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/TestShareData/shareData-time.rh73.501MB.oracle.prf.ANALYZED @@ -0,0 +1,239 @@ + +TKPROF: Release 9.2.0.6.0 - Production on Tue Feb 1 19:54:36 2005 + +Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. + +Trace file: shareData.trc +Sort options: exeela fchcnt +******************************************************************************** +count = number of times OCI procedure was executed +cpu = cpu time in seconds executing +elapsed = elapsed time in seconds executing +disk = number of physical reads of buffers from disk +query = number of buffers gotten for consistent read +current = number of buffers gotten in current mode (usually for update) +rows = number of rows processed by the fetch or execute call +******************************************************************************** + +SELECT "OBJECT_ID", "CHANNEL_ID", "IOV_SINCE", "IOV_UNTIL", "SYS_INSTIME", + "I", "S", "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "P" +FROM + "AVALASSI"."COOLTEST_F0001_IOVS" WHERE "CHANNEL_ID"=:"channel" AND + "IOV_SINCE">=:"since" AND "IOV_UNTIL"<=:"till" ORDER BY "CHANNEL_ID" ASC, + "IOV_SINCE" ASC + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 197 3.16 3.02 0 31647 140447 19604 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 199 3.16 3.02 0 31647 140447 19604 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 10000 TABLE ACCESS BY INDEX ROWID COOLTEST_F0001_IOVS + 10000 INDEX RANGE SCAN COOLTEST_F0001_IOVS_CSU_3INDX (object id 8142) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 197 0.00 0.00 + SQL*Net more data to client 1177 0.00 0.05 + SQL*Net message from client 197 0.02 2.49 +******************************************************************************** + +SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", + "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", + "FOLDER_IOVTABLENAME" +FROM + "AVALASSI"."COOLTEST_FOLDERS" WHERE "NODE_FULLPATH"=:"fullName" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 2 0.00 0.00 0 2 7 1 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 4 0.00 0.00 0 2 7 1 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 1 TABLE ACCESS BY INDEX ROWID COOLTEST_FOLDERS + 1 INDEX RANGE SCAN COOLTEST_FOLDERS_FULN_1INDX (object id 8136) + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 2 0.00 0.00 + SQL*Net message from client 2 0.00 0.00 +******************************************************************************** + +SELECT TABLE_NAME +FROM + ALL_TABLES WHERE OWNER = 'AVALASSI' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 1 0.01 0.00 0 122 0 8 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 3 0.01 0.00 0 122 0 8 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 8 FILTER + 8 NESTED LOOPS + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS OUTER + 8 NESTED LOOPS + 16 NESTED LOOPS + 1 TABLE ACCESS BY INDEX ROWID USER$ + 1 INDEX UNIQUE SCAN I_USER1 (object id 44) + 16 TABLE ACCESS BY INDEX ROWID OBJ$ + 16 INDEX RANGE SCAN I_OBJ2 (object id 37) + 8 TABLE ACCESS CLUSTER TAB$ + 8 INDEX UNIQUE SCAN I_OBJ# (object id 3) + 8 TABLE ACCESS BY INDEX ROWID OBJ$ + 8 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 0 INDEX UNIQUE SCAN I_OBJ1 (object id 36) + 8 TABLE ACCESS CLUSTER USER$ + 8 INDEX UNIQUE SCAN I_USER# (object id 11) + 8 TABLE ACCESS CLUSTER SEG$ + 8 INDEX UNIQUE SCAN I_FILE#_BLOCK# (object id 9) + 8 TABLE ACCESS CLUSTER TS$ + 8 INDEX UNIQUE SCAN I_TS# (object id 7) + 0 NESTED LOOPS + 0 FIXED TABLE FULL X$KZSRO + 0 INDEX RANGE SCAN I_OBJAUTH2 (object id 109) + 0 FIXED TABLE FULL X$KZSPR + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +alter session set events '10046 trace name context forever, level 12' + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 1 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 1 0.00 0.00 + SQL*Net message from client 1 0.00 0.00 +******************************************************************************** + +SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" +FROM + "AVALASSI"."COOLTEST_DB_ATTRIBUTES" + + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 1 0.00 0.00 0 0 0 0 +Execute 1 0.00 0.00 0 0 0 0 +Fetch 3 0.00 0.00 0 10 19 2 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 5 0.00 0.00 0 10 19 2 + +Misses in library cache during parse: 0 +Optimizer goal: CHOOSE +Parsing user id: 25 + +Rows Row Source Operation +------- --------------------------------------------------- + 2 TABLE ACCESS FULL COOLTEST_DB_ATTRIBUTES + + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 3 0.00 0.00 + SQL*Net message from client 3 0.00 0.00 + + + +******************************************************************************** + +OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 4 0.00 0.00 0 0 0 0 +Execute 5 0.00 0.00 0 0 0 0 +Fetch 203 3.17 3.03 0 31781 140473 19615 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 212 3.17 3.03 0 31781 140473 19615 + +Misses in library cache during parse: 0 + +Elapsed times include waiting on following events: + Event waited on Times Max. Wait Total Waited + ---------------------------------------- Waited ---------- ------------ + SQL*Net message to client 216 0.00 0.00 + SQL*Net message from client 216 1.10 4.61 + SQL*Net more data to client 1178 0.00 0.05 + + +OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS + +call count cpu elapsed disk query current rows +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +Parse 0 0.00 0.00 0 0 0 0 +Execute 0 0.00 0.00 0 0 0 0 +Fetch 0 0.00 0.00 0 0 0 0 +------- ------ -------- ---------- ---------- ---------- ---------- ---------- +total 0 0.00 0.00 0 0 0 0 + +Misses in library cache during parse: 0 + + 5 user SQL statements in session. + 0 internal SQL statements in session. + 5 SQL statements in session. +******************************************************************************** +Trace file: shareData.trc +Trace file compatibility: 9.02.00 +Sort options: exeela fchcnt + 1 session in tracefile. + 5 user SQL statements in trace file. + 0 internal SQL statements in trace file. + 5 SQL statements in trace file. + 5 unique SQL statements in trace file. + 1911 lines in trace file. + + diff --git a/RelationalCool/tests/PerformanceAV/execTestAttributeValueAccessor.csh b/RelationalCool/tests/PerformanceAV/execTestAttributeValueAccessor.csh new file mode 100755 index 000000000..a351d939d --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/execTestAttributeValueAccessor.csh @@ -0,0 +1,53 @@ +#! /bin/csh -f + +set theOS = `more /etc/redhat-release` +if ( "$theOS" == "Red Hat Linux release 7.3 (Valhalla)" ) then + set theOS = rh73 +else if ( "$theOS" == "Scientific Linux CERN release 3.0.3 (SL)" ) then + set theOS = slc3 +else + echo "Unknown OS"; exit 1 +endif + +set theMem = `more /proc/meminfo|grep MemTotal|awk '{print int($2/1024) "MB"}'` + +set theDB = `echo $COOLTESTDB | awk '{print substr($1,0,index($1,"://")-1)}'` + +###set out = $theOS.$theMem.$theDB.out +set out = $theOS.$theMem.$theDB.out.ANALYZED + +unsetenv POOL_ORA_SQL_TRACE +###setenv POOL_ORA_SQL_TRACE ON + +\rm TestAttributeValueAccessor/*$out +setenv COOL_RALDATABASE_USETIMER ON +unsetenv COOL_RALDATABASE_TESTNEWCOPY +unsetenv COOL_RALDATABASE_RALONLY + +unsetenv COOL_RALDATABASE_DONOTUSEAVACCESSOR +unsetenv COOL_COOLCHRONO_PROCMEMORY +time unitTest_RelationalCool_PerformanceAV \ + >& TestAttributeValueAccessor/useAccessor-time.$out + +setenv COOL_RALDATABASE_DONOTUSEAVACCESSOR ON +unsetenv COOL_COOLCHRONO_PROCMEMORY +time unitTest_RelationalCool_PerformanceAV \ + >& TestAttributeValueAccessor/doNotUseAccessor-time.$out + +tkdiff TestAttributeValueAccessor/useAccessor-time.$out \ + TestAttributeValueAccessor/doNotUseAccessor-time.$out & + +###exit 1 + +unsetenv COOL_RALDATABASE_DONOTUSEAVACCESSOR +setenv COOL_COOLCHRONO_PROCMEMORY ON +time unitTest_RelationalCool_PerformanceAV \ + >& TestAttributeValueAccessor/useAccessor-memory.$out + +setenv COOL_RALDATABASE_DONOTUSEAVACCESSOR ON +setenv COOL_COOLCHRONO_PROCMEMORY ON +time unitTest_RelationalCool_PerformanceAV \ + >& TestAttributeValueAccessor/doNotUseAccessor-memory.$out + +tkdiff TestAttributeValueAccessor/useAccessor-memory.$out \ + TestAttributeValueAccessor/doNotUseAccessor-memory.$out & diff --git a/RelationalCool/tests/PerformanceAV/execTestNewCopy.csh b/RelationalCool/tests/PerformanceAV/execTestNewCopy.csh new file mode 100755 index 000000000..e19887aca --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/execTestNewCopy.csh @@ -0,0 +1,38 @@ +#! /bin/csh -f + +set theOS = `more /etc/redhat-release` +if ( "$theOS" == "Red Hat Linux release 7.3 (Valhalla)" ) then + set theOS = rh73 +else if ( "$theOS" == "Scientific Linux CERN release 3.0.3 (SL)" ) then + set theOS = slc3 +else + echo "Unknown OS"; exit 1 +endif + +set theMem = `more /proc/meminfo|grep MemTotal|awk '{print int($2/1024) "MB"}'` + +set out = $theOS.$theMem.out + +\rm TestNewCopy/*$out +unsetenv COOL_RALDATABASE_TESTRALONLY + +unsetenv COOL_RALDATABASE_TESTNEWCOPY +unsetenv COOL_COOLCHRONO_PROCMEMORY +time unitTest_RelationalCool_PerformanceAV >& TestNewCopy/oldCopy-time.$out + +setenv COOL_RALDATABASE_TESTNEWCOPY ON +unsetenv COOL_COOLCHRONO_PROCMEMORY +time unitTest_RelationalCool_PerformanceAV >& TestNewCopy/newCopy-time.$out + +tkdiff TestNewCopy/oldCopy-time.$out TestNewCopy/newCopy-time.$out & + +unsetenv COOL_RALDATABASE_TESTNEWCOPY +setenv COOL_COOLCHRONO_PROCMEMORY ON +time unitTest_RelationalCool_PerformanceAV >& TestNewCopy/oldCopy-memory.$out + +setenv COOL_RALDATABASE_TESTNEWCOPY ON +setenv COOL_COOLCHRONO_PROCMEMORY ON +time unitTest_RelationalCool_PerformanceAV >& TestNewCopy/newCopy-memory.$out + +tkdiff TestNewCopy/oldCopy-memory.$out TestNewCopy/newCopy-memory.$out & + diff --git a/RelationalCool/tests/PerformanceAV/execTestRalOnly.csh b/RelationalCool/tests/PerformanceAV/execTestRalOnly.csh new file mode 100755 index 000000000..a5836206e --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/execTestRalOnly.csh @@ -0,0 +1,46 @@ +#! /bin/csh -f + +set theOS = `more /etc/redhat-release` +if ( "$theOS" == "Red Hat Linux release 7.3 (Valhalla)" ) then + set theOS = rh73 +else if ( "$theOS" == "Scientific Linux CERN release 3.0.3 (SL)" ) then + set theOS = slc3 +else + echo "Unknown OS"; exit 1 +endif + +set theMem = `more /proc/meminfo|grep MemTotal|awk '{print int($2/1024) "MB"}'` + +set theDB = `echo $COOLTESTDB | awk '{print substr($1,0,index($1,"://")-1)}'` + +set out = $theOS.$theMem.$theDB.out +###set out = $theOS.$theMem.$theDB.out.ANALYZED + +unsetenv POOL_ORA_SQL_TRACE +###setenv POOL_ORA_SQL_TRACE ON + +\rm TestRalOnly/*$out +unsetenv COOL_RALDATABASE_TESTNEWCOPY + +unsetenv COOL_COOLCHRONO_PROCMEMORY +unsetenv COOL_RALDATABASE_RALONLY +time unitTest_RelationalCool_PerformanceAV >& TestRalOnly/withCool-time.$out + +unsetenv COOL_COOLCHRONO_PROCMEMORY +setenv COOL_RALDATABASE_RALONLY ON +time unitTest_RelationalCool_PerformanceAV >& TestRalOnly/ralOnly-time.$out + +tkdiff TestRalOnly/withCool-time.$out TestRalOnly/ralOnly-time.$out & + +###exit 1 + +setenv COOL_COOLCHRONO_PROCMEMORY ON +unsetenv COOL_RALDATABASE_RALONLY +time unitTest_RelationalCool_PerformanceAV >& TestRalOnly/withCool-memory.$out + +setenv COOL_COOLCHRONO_PROCMEMORY ON +setenv COOL_RALDATABASE_RALONLY ON +time unitTest_RelationalCool_PerformanceAV >& TestRalOnly/ralOnly-memory.$out + +tkdiff TestRalOnly/withCool-memory.$out TestRalOnly/ralOnly-memory.$out & + diff --git a/RelationalCool/tests/PerformanceAV/execTestScrollableCursor.csh b/RelationalCool/tests/PerformanceAV/execTestScrollableCursor.csh new file mode 100755 index 000000000..4c92f3f7d --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/execTestScrollableCursor.csh @@ -0,0 +1,59 @@ +#! /bin/csh -f + +set theOS = `more /etc/redhat-release` +if ( "$theOS" == "Red Hat Linux release 7.3 (Valhalla)" ) then + set theOS = rh73 +else if ( "$theOS" == "Scientific Linux CERN release 3.0.3 (SL)" ) then + set theOS = slc3 +else + echo "Unknown OS"; exit 1 +endif + +set theMem = `more /proc/meminfo|grep MemTotal|awk '{print int($2/1024) "MB"}'` + +set theDB = `echo $COOLTESTDB | awk '{print substr($1,0,index($1,"://")-1)}'` + +#setenv COOL_TESTAV_RECREATEDB ON +#unitTest_RelationalCool_PerformanceAV +unsetenv COOL_TESTAV_RECREATEDB + +setenv COOL_RALDATABASE_USETIMER ON + +###set out = $theOS.$theMem.$theDB.out +set out = $theOS.$theMem.$theDB.out.ANALYZED + +unsetenv POOL_ORA_SQL_TRACE +###setenv POOL_ORA_SQL_TRACE ON + +\rm TestScrollableCursor/*$out +unsetenv COOL_RALDATABASE_TESTNEWCOPY +unsetenv COOL_RALDATABASE_RALONLY + +setenv POOL_ORA_SCROLLABLE_CURSOR ON +unsetenv COOL_COOLCHRONO_PROCMEMORY +time unitTest_RelationalCool_PerformanceAV \ + >& TestScrollableCursor/scrollable-time.$out + +unsetenv POOL_ORA_SCROLLABLE_CURSOR +unsetenv COOL_COOLCHRONO_PROCMEMORY +time unitTest_RelationalCool_PerformanceAV \ + >& TestScrollableCursor/notScrollable-time.$out + +tkdiff TestScrollableCursor/scrollable-time.$out \ + TestScrollableCursor/notScrollable-time.$out & + +###exit 1 + +setenv POOL_ORA_SCROLLABLE_CURSOR ON +setenv COOL_COOLCHRONO_PROCMEMORY ON +time unitTest_RelationalCool_PerformanceAV \ + >& TestScrollableCursor/scrollable-memory.$out + +unsetenv POOL_ORA_SCROLLABLE_CURSOR +setenv COOL_COOLCHRONO_PROCMEMORY ON +time unitTest_RelationalCool_PerformanceAV \ + >& TestScrollableCursor/notScrollable-memory.$out + +tkdiff TestScrollableCursor/scrollable-memory.$out \ + TestScrollableCursor/notScrollable-memory.$out & + diff --git a/RelationalCool/tests/PerformanceAV/execTestShareData.csh b/RelationalCool/tests/PerformanceAV/execTestShareData.csh new file mode 100755 index 000000000..ad61d946f --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/execTestShareData.csh @@ -0,0 +1,55 @@ +#! /bin/csh -f + +echo "This test is not supported anymore as of COOL_0_0_3-pre1-zeta!"; exit 1 + +set theOS = `more /etc/redhat-release` +if ( "$theOS" == "Red Hat Linux release 7.3 (Valhalla)" ) then + set theOS = rh73 +else if ( "$theOS" == "Scientific Linux CERN release 3.0.3 (SL)" ) then + set theOS = slc3 +else + echo "Unknown OS"; exit 1 +endif + +set theMem = `more /proc/meminfo|grep MemTotal|awk '{print int($2/1024) "MB"}'` + +set theDB = `echo $COOLTESTDB | awk '{print substr($1,0,index($1,"://")-1)}'` + +###set out = $theOS.$theMem.$theDB.out +set out = $theOS.$theMem.$theDB.out.ANALYZED + +###unsetenv POOL_ORA_SQL_TRACE +setenv POOL_ORA_SQL_TRACE ON + +\rm TestShareData/*$out +setenv COOL_RALDATABASE_USETIMER ON +unsetenv COOL_RALDATABASE_TESTNEWCOPY +unsetenv COOL_RALDATABASE_RALONLY + +unsetenv COOL_RALDATABASE_DONOTSHAREDATA +unsetenv COOL_COOLCHRONO_PROCMEMORY +time unitTest_RelationalCool_PerformanceAV \ + >& TestShareData/shareData-time.$out + +setenv COOL_RALDATABASE_DONOTSHAREDATA ON +unsetenv COOL_COOLCHRONO_PROCMEMORY +time unitTest_RelationalCool_PerformanceAV \ + >& TestShareData/doNotShareData-time.$out + +tkdiff TestShareData/shareData-time.$out \ + TestShareData/doNotShareData-time.$out & + +###exit 1 + +unsetenv COOL_RALDATABASE_DONOTSHAREDATA +setenv COOL_COOLCHRONO_PROCMEMORY ON +time unitTest_RelationalCool_PerformanceAV \ + >& TestShareData/shareData-memory.$out + +setenv COOL_RALDATABASE_DONOTSHAREDATA ON +setenv COOL_COOLCHRONO_PROCMEMORY ON +time unitTest_RelationalCool_PerformanceAV \ + >& TestShareData/doNotShareData-memory.$out + +tkdiff TestShareData/shareData-memory.$out \ + TestShareData/doNotShareData-memory.$out & diff --git a/RelationalCool/tests/PerformanceAV/mySetupMySQL.csh b/RelationalCool/tests/PerformanceAV/mySetupMySQL.csh new file mode 100644 index 000000000..221675cef --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/mySetupMySQL.csh @@ -0,0 +1,2 @@ +setenv COOLTESTDB "mysql://lxb0771;schema=AVALASSI;user=avalassi;password=PASSWORD;dbname=COOLTSTA" + diff --git a/RelationalCool/tests/PerformanceAV/mySetupOracle.csh b/RelationalCool/tests/PerformanceAV/mySetupOracle.csh new file mode 100644 index 000000000..1e80b4f24 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/mySetupOracle.csh @@ -0,0 +1,2 @@ +setenv COOLTESTDB "oracle://cooldb2;schema=AVALASSI;user=avalassi;password=PASSWORD;dbname=COOLTSTA" +setenv TNS_ADMIN ~/myLCG/COOL_HEAD/src/RelationalCool/tests diff --git a/RelationalCool/tests/PerformanceAV/scaling_mixed.txt b/RelationalCool/tests/PerformanceAV/scaling_mixed.txt new file mode 100644 index 000000000..3754e74f7 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/scaling_mixed.txt @@ -0,0 +1,82 @@ +MIXED test +----------- + +#objects Write Read Data + +COOL-MySQL +10k 11 sec 11 sec 3.6 MB +20k 29 sec 23 sec 6.8 MB +50k 114 sec 60 sec 15.2 MB +100k 380 sec 121 sec 31.0 MB + +COOL-Oracle +10k 15 sec 33 sec 4.0 MB +20k 30 sec 74 sec 7.3 MB +50k 82 sec 295 sec 16.7 MB +100k ERROR + +Lisbon-MySQL +10k 27 sec 0 sec! 1.4 MB +20k 55 sec 1 sec! 2.8 MB +50k 109 sec 2 sec! 7.2 MB +100k 259 sec 4 sec! 14.4 MB + +Comments: + +- Both COOL-MySQL and COOL-Oracle occupy more than twice bytes as + Lisbon-MySQL: this may indicate a difference in data type storage + that may contribute a factor 2 to the comparison (COOL appears + slower by a factor 2 because it occupies twice as much space?) + +- COOL-MySQL scales well in reading: good. + +- COOL-MySQL does NOT scale in writing: BAD! + This needs to be understood/fixed. + +- Lisbon-MySQL read may not have hit yet the threshold for cache usage: the + tests should be repeated with higher load until the threshold is found. + +- COOL-Oracle is a factor 3 slower than COOL-MySQL at low data. + +- COOL-Oracle does NOT scale in reading: VERY BAD! + This needs to be understood/fixed. + +- COOL-Oracle is almost a factor 2 faster than Lisbon-MySQL in writing. + +- COOL-Oracle crashes in writing 100k: VERY BAD! + Error ORA-24381: error(s) in array DML (executing the bulk insert statement) + This needs to be understood/fixed. + +Summary: +* COOL-MySQL + - BAD writing does not scale! + - OK reading scales, but slow +* Lisbon-MySQL + - OK writing scales, but slow + - VERY GOOD reading, very fast + (factor 30 better than COOL-MySQL: or maybe 15, if same data volume used?) +* COOL-Oracle [NOT USING A DEDICATED SERVER] + - BAD writing crashes at 100k! + - BAD reading does not scale! + +Comment on the cache: +* I repeated some tests on the MySQL server after disabling the query cache: + #query_cache_type=1 + #query_cache_size=16M + query_cache_limit=0 + query_cache_type=0 + query_cache_size=0M +I find that Lisbon-MySQL gets slower in writing, but not in reading! +This is unlikely to be a statistical fluctuation (I got 180, 152, 150 with +no cache, versus 109, 127, 132 with cache, before and after the no cache test) + Lisbon-MySQL + 50k 150 sec 2 sec! 7.2 MB + (was 109) (was 2) +Instead COOL-MySQL stays exactly the same + COOL-MySQL + 50k 114 sec 59 sec 15.2 MB + (was 114) (was 2) +* Direct SQL query from TOra: it gets stuck, too much data. +* All in all, it seems that Lisbon-MySQL is intrinsecally faster because +a MyISAM table is used. I do not see any threshold effect from caching +(not yet?). I am not sure I can see any effect from the C++ driver. \ No newline at end of file diff --git a/RelationalCool/tests/PerformanceAV/scaling_mixed_2.txt b/RelationalCool/tests/PerformanceAV/scaling_mixed_2.txt new file mode 100644 index 000000000..a3a7bd6e1 --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/scaling_mixed_2.txt @@ -0,0 +1,98 @@ +MIXED test +----------- + +#objects Write Read Data + +COOL-MySQL [write using 10k object bursts: in parentheses, single burst] +10k 11 sec (11) 11 sec 3.6 MB +20k 29 sec (29) 23 sec 6.8 MB +50k 70 sec (114) 60 sec 15.2 MB +100k 156 sec (380) 121 sec 31.0 MB +200k 418 sec (---) 603 sec (??) 61.4 MB +[Clear non-linearity in writing 200k: first 10k burst in 10 sec, last in 25] +[Reading 200k may be the first sign of end-of-caching] +[Client memory seems too limited to handle such large in-memory data] + +COOL-Oracle [write using 50k object bursts: in parentheses, single burst] +10k 9 sec (9) 24 sec 4.0 MB +20k 18 sec (18) 48 sec 7.3 MB +50k 55 sec (51) 122 sec 16.7 MB +100k 108 sec (ERROR) 248 sec 32.5 MB +200k 234 sec (ERROR) 697 sec 63.9 MB + +Lisbon-MySQL +10k 27 sec 0 sec! 1.4 MB +20k 55 sec 1 sec! 2.8 MB +50k 109 sec 2 sec! 7.2 MB +100k 259 sec 4 sec! 14.4 MB +200k 553 sec 8 sec! 28.8 MB + +Comments: + +- Both COOL-MySQL and COOL-Oracle occupy more than twice bytes as + Lisbon-MySQL: this may indicate a difference in data type storage + that may contribute a factor 2 to the comparison (COOL appears + slower by a factor 2 because it occupies twice as much space?) + +- COOL-MySQL scales well in reading: good. + BUT it suddenly become non-linear at 200k objects: BAD! + This needs to be understood/fixed: this might be the end-of-caching. + +- COOL-MySQL writing needs splitting the job in 10k bursts. + Using 10k bursts is already much better when storing 50k objects. + +- COOL-Oracle writing needs splitting the job in 50k bursts. + There is no performance enhancement (if anything, a slight degradation), + but otherwise it crashes with ORA-24381. + +- COOL-MySQL almost scales in writing: so so. + The more data in the database, the slower it goes? + This needs to be understood/fixed. + +- Lisbon-MySQL read may not have hit yet the threshold for cache usage: the + tests should be repeated with higher load until the threshold is found. + Or is there something else? MyISAM? Driver? Not loading all CondDBTable??? + +- COOL-Oracle is faster in writing than both COOL-MySQL (factor 1.5 to 2) + and Lisbon-MySQL (factor 2.5): VERY GOOD! + +- The tests may need to be changed: the effect of the limited memory of the + client seems to become apparent. After writing the buffer, it takes a + long time to destroy the in-memory vector and start reading? + +- COOL-Oracle does not scale too well in reading: so so. + This needs to be understood/fixed. Related to client memory? + +Summary: +* COOL-MySQL + - SOSO writing, does not scale very well + - OK reading, scales but slow +* Lisbon-MySQL + - OK writing, scales but slow + - VERY GOOD reading, very fast + (factor 30 better than COOL-MySQL: or maybe 15, if same data volume used?) +* COOL-Oracle + - GOOD writing, faster than the other two! + - SOSO reading, does not scale very well + +Comment on the cache: +* I repeated some tests on the MySQL server after disabling the query cache: + #query_cache_type=1 + #query_cache_size=16M + query_cache_limit=0 + query_cache_type=0 + query_cache_size=0M +I find that Lisbon-MySQL gets slower in writing, but not in reading! +This is unlikely to be a statistical fluctuation (I got 180, 152, 150 with +no cache, versus 109, 127, 132 with cache, before and after the no cache test) + Lisbon-MySQL + 50k 150 sec 2 sec! 7.2 MB + (was 109) (was 2) +Instead COOL-MySQL stays exactly the same + COOL-MySQL [no 10k bursts] + 50k 114 sec 59 sec 15.2 MB + (was 114) (was 59) +* Direct SQL query from TOra: it gets stuck, too much data. +* All in all, it seems that Lisbon-MySQL is intrinsecally faster because +a MyISAM table is used. I do not see any threshold effect from caching +(not yet?). I am not sure I can see any effect from the C++ driver. \ No newline at end of file diff --git a/RelationalCool/tests/PerformanceAV/test_PerformanceAV.cpp b/RelationalCool/tests/PerformanceAV/test_PerformanceAV.cpp new file mode 100644 index 000000000..d3f69257a --- /dev/null +++ b/RelationalCool/tests/PerformanceAV/test_PerformanceAV.cpp @@ -0,0 +1,477 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT +/** + +@file test_PerformanceAV.cpp + +@author Sven A. Schmidt + +@date 2005-01-03 + +*/ + + +#include<cppunit/extensions/HelperMacros.h> + +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/Exception.h" + +#include "../Performance/Benchmark.h" + +#include "src/CoralApplication.h" +#include "src/ProcMemory.h" + +using coral::AttributeList; +using coral::AttributeListSpecification; +typedef boost::shared_ptr<AttributeListSpecification> SpecPtr; + +// include for 'sleep' (ORA-01466 workaround) +//#include <unistd.h> +#include "src/sleep.h" + +#include <string> +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +#include <vector> +using std::vector; + +namespace cool { + +const char* COOLTESTDB = "COOLTESTDB"; + +// set this to true to have a quick run through all tests +// tests should initialize their iteration count like this: +// long iterations = quick ? 1 : 10000; +const bool quick = true; +//const bool quick = false; + + +/// Performace test class +class PerformanceTestAV : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( PerformanceTestAV ); + + CPPUNIT_TEST( test_bulk_rw_mixed ); + + //CPPUNIT_TEST( test_bulk_rw_float_1 ); + //CPPUNIT_TEST( test_bulk_rw_float_20 ); + //CPPUNIT_TEST( test_bulk_rw_float_100 ); + //CPPUNIT_TEST( test_bulk_rw_float_200 ); + + //CPPUNIT_TEST( test_bulk_rw_string4kb_1 ); + //CPPUNIT_TEST( test_bulk_rw_string4kb_100 ); + //CPPUNIT_TEST( test_bulk_rw_string4kb_200 ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + AttributeListSpecification mixedPayloadSpec; + string connectString; + IDatabasePtr db; + + + /* + void test_bulk_rw_string4kb_1() { + int nFields = 1; + long nObjs = quick ? 1 : 25000; + rw_string4kb( nFields, nObjs ); + } + + void test_bulk_rw_string4kb_100() { + int nFields = 100; + long nObjs = quick ? 1 : 200; // reduced row count, each obj is 400kB + // 25k objects would allocate 10GB of memory + // could run several batches instead + rw_string4kb( nFields, nObjs ); + } + + void test_bulk_rw_string4kb_200() { + int nFields = 200; + long nObjs = quick ? 1 : 100; // reduced row count, each obj is 400kB + // 25k objects would allocate 20GB of memory + // could run several batches instead + rw_string4kb( nFields, nObjs ); + } + + + void rw_string4kb( int nFields, long nObjs ) { + + SpecPtr spec = uniformSpec( nFields, "string" ); + AttributeList payload = string4kbPayload( spec ); + + IFolderPtr folder = db->createFolder( "/myfolder", *spec ); + + mysleep(); + + { + Benchmark b; + b.start(); + + folder->setupStorageBuffer(); + + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, payload ); + } + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs << " objects (" + << nFields << " 4kb strings) **" << endl; + cout << "wrote " << nObjs << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + + + { + Benchmark b; + b.start(); + + IObjectIteratorPtr objs = + folder->browseObjectsInTag( "", 0, 0, ValidityKeyMax ); + + long nReadObjects = 0; + while( objs->hasNext() ) { + objs->next(); + nReadObjects++; + } + + double secElapsed = b.stop(); + + cout << "** reading " << nObjs << " objects (" + << nFields << " 4kb strings) **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + + } + + + + + void test_bulk_rw_float_1() { + int nFields = 1; + long nObjs = quick ? 1 : 25000; + rw_floats( nFields, nObjs ); + } + + void test_bulk_rw_float_100() { + int nFields = 100; + long nObjs = quick ? 1 : 25000; + rw_floats( nFields, nObjs ); + } + + void test_bulk_rw_float_200() { + int nFields = 200; + long nObjs = quick ? 1 : 25000; + rw_floats( nFields, nObjs ); + } + + + void test_bulk_rw_float_20() { + int nFields = 20; + long nObjs = quick ? 1 : 25000; + rw_floats( nFields, nObjs ); + } + + + void rw_floats( int nFields, long nObjs ) { + + SpecPtr spec = uniformSpec( nFields, "float" ); + IFolderPtr folder = db->createFolder( "/myfolder", *spec ); + + mysleep(); + + { + Benchmark b; + b.start(); + + folder->setupStorageBuffer(); + + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, floatPayload( i, spec ) ); + } + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs << " objects (" + << nFields << " floats) **" << endl; + cout << "wrote " << nObjs << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + } + + + { + Benchmark b; + b.start(); + + IObjectIteratorPtr objs = + folder->browseObjectsInTag( "", 0, 0, ValidityKeyMax ); + + long nReadObjects = 0; + while( objs->hasNext() ) { + objs->next(); + nReadObjects++; + } + + double secElapsed = b.stop(); + + cout << "** reading " << nObjs << " objects (" + << nFields << " floats) **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + + } + + */ + + void test_bulk_rw_mixed() { + + //ProcMemory* mem = new ProcMemory(); + //std::cout << "START of TEST" << std::endl; mem->printVm(); + + //long nObjs = quick ? 1 : 10000; + //long nObjs = 1; + //long nObjs = 10; + //long nObjs = 1000; + //long nObjs = 10000; + //long nObjs = 20000; + //long nObjs = 50000; + long nObjs = 100000; + //long nObjs = 200000; + + if ( getenv ( "COOL_TESTAV_RECREATEDB" ) ) { + + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + + Benchmark b; + b.start(); + + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, mixedPayload( i ) ); + } + + //std::cout << "Before flushing" << std::endl; mem->printVm(); + + folder->flushStorageBuffer(); + + double secElapsed = b.stop(); + + cout << "\n----------------------------------------------------" << endl; + cout << "** writing " << nObjs << " objects (150 bytes mixed) **" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nObjs/secElapsed << endl << endl; + + // ORA-01466 + cool::sleep(1); + + } + + //std::cout << "After flushing" << std::endl; mem->printVm(); + + Benchmark bFull; + bFull.start(); + + { + + IFolderPtr folder = db->getFolder( "/myfolder" ); + + Benchmark b; + b.start(); + + // Read ALL objects in tag + //IObjectIteratorPtr objs = + // folder->browseObjects( 0, ValidityKeyMax, 0, "" ); + // folder->browseObjectsInTag( "", 0, 0, ValidityKeyMax ); // OLD! + + // Read only 10k objects in tag + IObjectIteratorPtr objs = + folder->browseObjects( 0, 10000, 0, "" ); + //folder->browseObjectsInTag( "", 0, 0, 10000 ); // OLD! + + //std::cout << "After reading" << std::endl; mem->printVm(); + + long nReadObjects = 0; + while( objs->hasNext() ) { + objs->next(); + nReadObjects++; + if( nReadObjects == 1 ) + cout << "==> First object: since=" << objs->current()->since() << endl; + } + cout << "==> Last object: since=" << objs->current()->since() << endl; + + double secElapsed = b.stop(); + + cout << "** reading " << nObjs << " objects (150 bytes mixed) **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + + cout << "sec total (INCLUDING DELETE): " << bFull.stop() << endl; + + //std::cout << "END OF TEST" << std::endl; mem->printVm(); + + } + + + + + /// Creates a dummy payload AttributeList for a given index + AttributeList mixedPayload( int index ) { + AttributeList payload( mixedPayloadSpec ); + payload["I"].setValue<int>( index ); + stringstream s; + s << "Object " << index; + payload["S"].setValue<string>( s.str() ); + payload["X0"].setValue<float>( (float)(index/1000.) ); + payload["X1"].setValue<float>( (float)(index/1000.) ); + payload["X2"].setValue<float>( (float)(index/1000.) ); + payload["X3"].setValue<float>( (float)(index/1000.) ); + payload["X4"].setValue<float>( (float)(index/1000.) ); + payload["X5"].setValue<float>( (float)(index/1000.) ); + payload["X6"].setValue<float>( (float)(index/1000.) ); + payload["X7"].setValue<float>( (float)(index/1000.) ); + payload["X8"].setValue<float>( (float)(index/1000.) ); + payload["X9"].setValue<float>( (float)(index/1000.) ); + payload["P"].setValue<string>( "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + "0123456789" + ); + return payload; + } + + + /// Creates a uniform payload specification for nFields fields + SpecPtr uniformSpec( int nFields, const string & type ) { + SpecPtr spec( new AttributeListSpecification() ); + for ( int i = 0; i < nFields; ++i ) { + stringstream s; + s << "X" << i; + spec->push_back( s.str(), type ); + } + return spec; + } + + + /// Creates a dummy 4kB string AttributeList + AttributeList string4kbPayload( SpecPtr & spec ) { + stringstream payloadString; + int bytes = 4000; + for ( int i = 0; i < bytes; ++i ) payloadString << "a"; + + int nFields = spec->size(); + AttributeList payload( spec ); + for ( int i = 0; i < nFields; ++i ) { + stringstream s; + s << "X" << i; + payload[ s.str() ].setValue<string>( payloadString.str() ); + } + return payload; + } + + + /// Creates a dummy float AttributeList for a given index + AttributeList floatPayload( int index, SpecPtr & spec ) { + int nFields = spec->size(); + AttributeList payload( spec ); + for ( int i = 0; i < nFields; ++i ) { + stringstream s; + s << "X" << i; + payload[ s.str() ].setValue<float>( (float)(index/1000.) ); + } + return payload; + } + + + void mysleep() { + const int sleep_timeout = 1; + if ( sleep_timeout > 0 ) { + //cout << "temporary 'sleep()' to work aound ORA-01466 problem" << endl; + cool::sleep(sleep_timeout); + } + } + + + void setUp() { + if ( mixedPayloadSpec.size() == 0 ) { + mixedPayloadSpec.push_back("I","int"); + mixedPayloadSpec.push_back("S","string"); + mixedPayloadSpec.push_back("X0","float"); + mixedPayloadSpec.push_back("X1","float"); + mixedPayloadSpec.push_back("X2","float"); + mixedPayloadSpec.push_back("X3","float"); + mixedPayloadSpec.push_back("X4","float"); + mixedPayloadSpec.push_back("X5","float"); + mixedPayloadSpec.push_back("X6","float"); + mixedPayloadSpec.push_back("X7","float"); + mixedPayloadSpec.push_back("X8","float"); + mixedPayloadSpec.push_back("X9","float"); + mixedPayloadSpec.push_back("P","string"); + } + + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + cout << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << endl; + cout << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << endl; + cout << "Aborting test" << endl; + exit(-1); + } + + static CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + if ( getenv ( "COOL_TESTAV_RECREATEDB" ) ) { + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + } else + db = dbSvc.openDatabase( connectString, false ); + + mysleep(); + } + + void tearDown() { + db.reset(); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( PerformanceTestAV ); + +} // namespace + +// sas: This file is from the OPAL package I believe. It allows for +// shorter test classes and prepares the test class for OPAL +#include<CppUnit_testdriver.icpp> + + +#endif // NOPORT diff --git a/RelationalCool/tests/Privileges/out.oracle.slc3_ia32_gcc323 b/RelationalCool/tests/Privileges/out.oracle.slc3_ia32_gcc323 new file mode 100644 index 000000000..433eb6b88 --- /dev/null +++ b/RelationalCool/tests/Privileges/out.oracle.slc3_ia32_gcc323 @@ -0,0 +1,186 @@ +============================================ +Executing test as user 'lcg_cooltest' +Connection string: 'oracle://coolprod;schema=lcg_cooltest;dbname=COOLTEST;user=lcg_cooltest' +Property Catalogue: level[Info] Adding property: OutputLevel = 5 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/afs/cern.ch/user/a/avalassi/private/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" +==> Start TEST: create database +++++> End TEST: create database +==> Start TEST: open database +++++> End TEST: open database +==> Start TEST: create new MV folder +++++> End TEST: create new MV folder +==> Start TEST: create new folder set +++++> End TEST: create new folder set +==> Start TEST: read SV IOVs +++++> End TEST: read SV IOVs +==> Start TEST: read MV IOVs head +++++> End TEST: read MV IOVs head +==> Start TEST: read MV IOVs mytag +++++> End TEST: read MV IOVs mytag +==> Start TEST: tag MV IOVs +++++> End TEST: tag MV IOVs +==> Start TEST: retag MV IOVs +++++> End TEST: retag MV IOVs +==> Start TEST: insert SV IOVs +++++> End TEST: insert SV IOVs +==> Start TEST: insert MV IOVs +++++> End TEST: insert MV IOVs +==> Start TEST: drop SV folder +++++> End TEST: drop SV folder +==> Start TEST: drop MV folder +++++> End TEST: drop MV folder +==> Start TEST: drop folderset +++++> End TEST: drop folderset +==> Start TEST: drop database +++++> End TEST: drop database +++++++++++++++++++++++++++++++++++++++++++++ +============================================ +Executing test as user 'lcg_cooltest_reader' +Connection string: 'oracle://coolprod;schema=lcg_cooltest;dbname=COOLTEST;user=lcg_cooltest_reader' +==> Start TEST: create database +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "CREATE TABLE "LCG_COOLTEST"."COOLTEST_DB_ATTRIBUTES" ( "DB_ATTRIBUTE_NAME" VARCHAR2(255) )") +++++> End TEST: create database +==> Start TEST: open database +++++> End TEST: open database +==> Start TEST: create new MV folder +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: create new MV folder +==> Start TEST: create new folder set +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: create new folder set +==> Start TEST: read SV IOVs +++++> End TEST: read SV IOVs +==> Start TEST: read MV IOVs head +++++> End TEST: read MV IOVs head +==> Start TEST: read MV IOVs mytag +++++> End TEST: read MV IOVs mytag +==> Start TEST: tag MV IOVs +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_F0003_TAGS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: tag MV IOVs +==> Start TEST: retag MV IOVs +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DELETE FROM "LCG_COOLTEST"."COOLTEST_F0003_IOV2TAG" WHERE "TAG_ID"= :"tagId"") +++++> End TEST: retag MV IOVs +==> Start TEST: insert SV IOVs +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_F0002_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: insert SV IOVs +==> Start TEST: insert MV IOVs +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_F0003_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: insert MV IOVs +==> Start TEST: drop SV folder +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DROP TABLE "LCG_COOLTEST"."COOLTEST_F0002_IOVS"") +++++> End TEST: drop SV folder +==> Start TEST: drop MV folder +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DROP TABLE "LCG_COOLTEST"."COOLTEST_F0003_IOV2TAG"") +++++> End TEST: drop MV folder +==> Start TEST: drop folderset +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DELETE FROM "LCG_COOLTEST"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"") +++++> End TEST: drop folderset +==> Start TEST: drop database +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DELETE FROM "LCG_COOLTEST"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"") +++++> End TEST: drop database +++++++++++++++++++++++++++++++++++++++++++++ +============================================ +Executing test as user 'lcg_cooltest_writer' +Connection string: 'oracle://coolprod;schema=lcg_cooltest;dbname=COOLTEST;user=lcg_cooltest_writer' +==> Start TEST: create database +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "CREATE TABLE "LCG_COOLTEST"."COOLTEST_DB_ATTRIBUTES" ( "DB_ATTRIBUTE_NAME" VARCHAR2(255) )") +++++> End TEST: create database +==> Start TEST: open database +++++> End TEST: open database +==> Start TEST: create new MV folder +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: create new MV folder +==> Start TEST: create new folder set +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: create new folder set +==> Start TEST: read SV IOVs +++++> End TEST: read SV IOVs +==> Start TEST: read MV IOVs head +++++> End TEST: read MV IOVs head +==> Start TEST: read MV IOVs mytag +++++> End TEST: read MV IOVs mytag +==> Start TEST: tag MV IOVs +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_F0003_TAGS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: tag MV IOVs +==> Start TEST: retag MV IOVs +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DELETE FROM "LCG_COOLTEST"."COOLTEST_F0003_IOV2TAG" WHERE "TAG_ID"= :"tagId"") +++++> End TEST: retag MV IOVs +==> Start TEST: insert SV IOVs +++++> End TEST: insert SV IOVs +==> Start TEST: insert MV IOVs +++++> End TEST: insert MV IOVs +==> Start TEST: drop SV folder +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DROP TABLE "LCG_COOLTEST"."COOLTEST_F0002_IOVS"") +++++> End TEST: drop SV folder +==> Start TEST: drop MV folder +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DROP TABLE "LCG_COOLTEST"."COOLTEST_F0003_IOV2TAG"") +++++> End TEST: drop MV folder +==> Start TEST: drop folderset +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DELETE FROM "LCG_COOLTEST"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"") +++++> End TEST: drop folderset +==> Start TEST: drop database +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DELETE FROM "LCG_COOLTEST"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"") +++++> End TEST: drop database +++++++++++++++++++++++++++++++++++++++++++++ +============================================ +Executing test as user 'lcg_cooltest_tagger' +Connection string: 'oracle://coolprod;schema=lcg_cooltest;dbname=COOLTEST;user=lcg_cooltest_tagger' +==> Start TEST: create database +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "CREATE TABLE "LCG_COOLTEST"."COOLTEST_DB_ATTRIBUTES" ( "DB_ATTRIBUTE_NAME" VARCHAR2(255) )") +++++> End TEST: create database +==> Start TEST: open database +++++> End TEST: open database +==> Start TEST: create new MV folder +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: create new MV folder +==> Start TEST: create new folder set +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: create new folder set +==> Start TEST: read SV IOVs +++++> End TEST: read SV IOVs +==> Start TEST: read MV IOVs head +++++> End TEST: read MV IOVs head +==> Start TEST: read MV IOVs mytag +++++> End TEST: read MV IOVs mytag +==> Start TEST: tag MV IOVs +++++> End TEST: tag MV IOVs +==> Start TEST: retag MV IOVs +++++> End TEST: retag MV IOVs +==> Start TEST: insert SV IOVs +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_F0002_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: insert SV IOVs +==> Start TEST: insert MV IOVs +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "UPDATE "LCG_COOLTEST"."COOLTEST_F0003_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'") +++++> End TEST: insert MV IOVs +==> Start TEST: drop SV folder +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DROP TABLE "LCG_COOLTEST"."COOLTEST_F0002_IOVS"") +++++> End TEST: drop SV folder +==> Start TEST: drop MV folder +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DROP TABLE "LCG_COOLTEST"."COOLTEST_F0003_IOV2TAG"") +++++> End TEST: drop MV folder +==> Start TEST: drop folderset +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DELETE FROM "LCG_COOLTEST"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"") +++++> End TEST: drop folderset +==> Start TEST: drop database +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "DELETE FROM "LCG_COOLTEST"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"") +++++> End TEST: drop database +++++++++++++++++++++++++++++++++++++++++++++ +============================================ +Executing test as user 'lcg_cooltest_nopriv' +Connection string: 'oracle://coolprod;schema=lcg_cooltest;dbname=COOLTEST;user=lcg_cooltest_nopriv' +==> Start TEST: create database +POOL/RelationalPlugins/oracle Error ORA-01031: insufficient privileges (executing the statement "CREATE TABLE "LCG_COOLTEST"."COOLTEST_DB_ATTRIBUTES" ( "DB_ATTRIBUTE_NAME" VARCHAR2(255) )") +++++> End TEST: create database +==> Start TEST: open database +++++> End TEST: open database +**** SKIP TEST: create new MV folder +**** SKIP TEST: create new folderset +**** SKIP TEST: drop SV folder +**** SKIP TEST: drop MV folder +**** SKIP TEST: drop folderset +**** SKIP TEST: drop database +++++++++++++++++++++++++++++++++++++++++++++ + +OK (5) +[OVAL] Cppunit-result =0 diff --git a/RelationalCool/tests/Privileges/test_Privileges.cpp b/RelationalCool/tests/Privileges/test_Privileges.cpp new file mode 100644 index 000000000..115f310a1 --- /dev/null +++ b/RelationalCool/tests/Privileges/test_Privileges.cpp @@ -0,0 +1,954 @@ +int main() { return 0; } +#ifdef NOPORT +// $Id: test_Privileges.cpp,v 1.15 2008-08-27 09:34:29 avalassi Exp $ + +// Include files +#include <cppunit/extensions/HelperMacros.h> +#include <sstream> +#include "AttributeList/AttributeList.h" +#include "CoolKernel/Exception.h" +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObjectIterator.h" +#include "RelationalAccess/RelationalException.h" + +// Local include files +#include "src/CoralApplication.h" +#include "src/RalPrivilegeManager.h" +#include "src/RelationalDatabaseId.h" + +// Forward declaration +namespace cool { + class PrivilegesTest; +} + +// Environment variable name +namespace cool { + const char* COOLTESTDB = "COOLTESTDB"; +} + +//----------------------------------------------------------------------------- + +class cool::PrivilegesTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( PrivilegesTest ); + + CPPUNIT_TEST( testAll_Owner ); + CPPUNIT_TEST( testAll_Reader ); + CPPUNIT_TEST( testAll_Writer ); + CPPUNIT_TEST( testAll_Tagger ); + CPPUNIT_TEST( testAll_NoPriv ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + enum Role { NONE=-1, OWNER=0, READER=1, WRITER=2, TAGGER=3, NOPRIV=4 }; + + Role m_role; + std::string m_connectOwner; + std::string m_userOwner; + std::string m_connect; + std::string m_user; + IDatabasePtr m_db; + pool::AttributeListSpecification m_payloadSpec; + std::string m_fNameSV; + std::string m_fNameMV; + std::string m_fsName; + ChannelId m_chId; + unsigned long m_expSV; + std::string m_tagMV; + unsigned long m_expMVtag; + unsigned long m_expMVhead; + + //--------------------------------------------------------------------------- + + IDatabaseSvc& databaseService() + { + static CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + return dbSvc; + } + + //--------------------------------------------------------------------------- + + const std::string userForRole( const Role& role ) + { + // Default suffixes are used for the user names for the various roles + std::string user; + if ( role == OWNER ) { + user = m_userOwner; + } else if ( role == READER ) { + user = m_userOwner + "_reader"; + } else if ( role == WRITER ) { + user = m_userOwner + "_writer"; + } else if ( role == TAGGER ) { + user = m_userOwner + "_tagger"; + } else if ( role == NOPRIV ) { + user = m_userOwner + "_nopriv"; + } else { + std::cout << "PANIC! Unknown role " << role << std::endl; + exit( -1 ); + } + return user; + } + + //--------------------------------------------------------------------------- + + void getConnectString() + { + + // Get the connection string for the owner user + if ( getenv( COOLTESTDB ) ) { + m_connectOwner = getenv( COOLTESTDB ); + } else { + std::cout << "ERROR! You must provide a connection string " + << "in the environment variable " << COOLTESTDB << ", e.g." + << std::endl; + std::cout << "setenv " << COOLTESTDB + << " 'oracle://coolprod;schema=lcg_cooltest;dbname=COOLTEST" + << ";user=lcg_cooltest'" << std::endl; + exit(-1); + } + RelationalDatabaseId idOwner( m_connectOwner ); + if ( idOwner.user() == "" ) { + std::cout << "ERROR! You must specify the (owner) user" << std::endl; + exit(-1); + } + if ( idOwner.password() != "" ) { + std::cout << "ERROR! You must NOT specify the password" << std::endl; + exit(-1); + } + m_userOwner = idOwner.user(); + + // Get the appropriate user name and connection string for the current role + m_user = userForRole( m_role ); + std::cout << "============================================" << std::endl; + std::cout << "Executing test as user '" << m_user << "'" << std::endl; + RelationalDatabaseId id( idOwner.technology(), + idOwner.server(), + idOwner.schema(), + idOwner.dbName(), + m_user ); + m_connect = id.url(); + std::cout << "Connection string: '" << m_connect << "'" << std::endl; + + } + + //--------------------------------------------------------------------------- + + void dropDatabaseAsOwner() + { + IDatabaseSvc& dbSvc = databaseService(); + dbSvc.dropDatabase( m_connectOwner ); + } + + //--------------------------------------------------------------------------- + + void createDatabaseAsOwner() + { + + // Drop the database and recreate it + dropDatabaseAsOwner(); + IDatabaseSvc& dbSvc = databaseService(); + IDatabasePtr db = dbSvc.createDatabase( m_connectOwner ); + //cool::Sleep(1); // TEMPORARY? Patch for ORA-01466 + + // Create two new folders (one SV, one MV) with the same payload spec + IFolderPtr fSV = db->createFolder + ( m_fNameSV, m_payloadSpec, "", FolderVersioning::SINGLE_VERSION, true ); + IFolderPtr fMV = db->createFolder + ( m_fNameMV, m_payloadSpec, "", FolderVersioning::MULTI_VERSION, true ); + + // Create an empty folder set + db->createFolderSet( m_fsName, "", true ); + + // Store some IOVs in the two folders + fSV->storeObject( 0, ValidityKeyMax, dummyPayload( 1 ), m_chId ); + fSV->storeObject( 10, ValidityKeyMax, dummyPayload( 2 ), m_chId ); + fSV->storeObject( 20, ValidityKeyMax, dummyPayload( 3 ), m_chId ); + m_expSV = 3; // #IOVs in HEAD [0,10] [10,20] [20,+inf] + fMV->storeObject( 0, 100, dummyPayload( 1 ), m_chId ); + fMV->storeObject( 10, 20, dummyPayload( 2 ), m_chId ); + fMV->storeObject( 20, 30, dummyPayload( 3 ), m_chId ); + m_tagMV = "MYTAG"; + fMV->tagCurrentHead( m_tagMV, "Description of " + m_tagMV ); + m_expMVtag = 4; // #IOVs in MYTAG [0,10] [10,20] [20,30] [30,100] + fMV->storeObject( 30, 40, dummyPayload( 4 ), m_chId ); + m_expMVhead = 5; // #IOVs in HEAD [0,10] [10,20] [20,30] [30,40] [40,100] + + // Grant the appropriate rights to the appropriate users + // Nothing to do for the owner (already owner) and the no-privilege role + RalDatabase* ralDb = dynamic_cast<RalDatabase*>( db.get() ); + RalPrivilegeManager prMgr( ralDb ); + std::string user; + // --- Reader + user = userForRole( READER ); + prMgr.grantReaderPrivileges( user ); + //prMgr.revokeWriterPrivileges( user ); + //prMgr.revokeTaggerPrivileges( user ); + // --- Writer + user = userForRole( WRITER ); + prMgr.grantReaderPrivileges( user ); + prMgr.grantWriterPrivileges( user ); + //prMgr.revokeTaggerPrivileges( user ); + // --- Tagger + user = userForRole( TAGGER ); + bool retag = true; // grant retag privileges + prMgr.grantReaderPrivileges( user ); + //prMgr.revokeWriterPrivileges( user ); + prMgr.grantTaggerPrivileges( user, retag ); + + } + + //--------------------------------------------------------------------------- + + void test_CreateDatabase() + { + std::string status; + const std::string statusOk = "OK - Database created"; + const std::string statusTableNotCreated = "Not OK - Table not created"; + const std::string statusCoolExc = "Not OK - Unknown COOL exception"; + const std::string statusSealExc = "Not OK - Unknown SEAL exception"; + const std::string statusStdExc = "Not OK - Unknown std::exception"; + const std::string statusUnknown = "Not OK - Unknown exception"; + try { + IDatabaseSvc& dbSvc = databaseService(); + dbSvc.createDatabase( m_connect ); + status = statusOk; + } catch ( pool::RelationalTableNotCreated& /* dummy */ ) { + status = statusTableNotCreated; + } catch ( cool::Exception& e ) { + std::cout << "cool::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusCoolExc; + } catch ( seal::Exception& e ) { + std::cout << "seal::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusSealExc; + } catch( std::exception& se ) { + std::cout << "std::exception caught: '" << se.what() << "'" << std::endl; + status = statusStdExc; + } catch ( ... ) { + std::cout << "Unknown exception caught" << std::endl; + status = statusUnknown; + } + + // Different results are expected for different roles + std::string msg = std::string( "Create database as user " ) + m_user; + if ( m_role == OWNER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == READER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusTableNotCreated, status ); + } + else if ( m_role == WRITER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusTableNotCreated, status ); + } + else if ( m_role == TAGGER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusTableNotCreated, status ); + } + else if ( m_role == NOPRIV ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusTableNotCreated, status ); + } + else { + std::cout << "PANIC! Unknown role type" << std::endl; + exit( -1 ); + } + } + + //--------------------------------------------------------------------------- + + const bool test_OpenDatabase() + { + std::string status; + const std::string statusOk = "OK - Database opened"; + const std::string statusNotFound = "Not OK - Database not found"; + const std::string statusCoolExc = "Not OK - Unknown COOL exception"; + const std::string statusSealExc = "Not OK - Unknown SEAL exception"; + const std::string statusStdExc = "Not OK - Unknown std::exception"; + const std::string statusUnknown = "Not OK - Unknown exception"; + try { + IDatabaseSvc& dbSvc = databaseService(); + m_db = dbSvc.openDatabase( m_connect, false ); + status = statusOk; + } catch ( DatabaseDoesNotExist& /* dummy */ ) { + status = statusNotFound; + } catch ( cool::Exception& e ) { + std::cout << "cool::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusCoolExc; + } catch ( seal::Exception& e ) { + std::cout << "seal::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusSealExc; + } catch( std::exception& se ) { + std::cout << "std::exception caught: '" << se.what() << "'" << std::endl; + status = statusStdExc; + } catch ( ... ) { + std::cout << "Unknown exception caught" << std::endl; + status = statusUnknown; + } + + // Different results are expected for different roles + std::string msg = std::string( "Open database as user " ) + m_user; + if ( m_role == OWNER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == READER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == WRITER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == TAGGER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == NOPRIV ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusNotFound, status ); + } + else { + std::cout << "PANIC! Unknown role type" << std::endl; + exit( -1 ); + } + + // Status code is needed to know if further tests can be performed + if ( status == statusOk ) return true; + else return false; + + } + + //--------------------------------------------------------------------------- + + void test_CreateNode( const std::string& fullPath, const bool isFolder ) + { + std::string status; + const std::string statusOk = "OK - Node created"; + const std::string statusTableNotCreated = "Not OK - Table not created"; + const std::string statusRowNotUpdated = "Not OK - Row not updated"; + const std::string statusCoolExc = "Not OK - Unknown COOL exception"; + const std::string statusSealExc = "Not OK - Unknown SEAL exception"; + const std::string statusStdExc = "Not OK - Unknown std::exception"; + const std::string statusUnknown = "Not OK - Unknown exception"; + try { + if ( isFolder ) + m_db->createFolder + ( fullPath, + m_payloadSpec, "", FolderVersioning::MULTI_VERSION, true ); + else + m_db->createFolderSet + ( fullPath, "", true ); + status = statusOk; + } catch ( pool::RelationalTableNotCreated& /* dummy */ ) { + status = statusTableNotCreated; + } catch ( RowNotUpdated& /* dummy */ ) { + status = statusRowNotUpdated; + } catch ( cool::Exception& e ) { + std::cout << "cool::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusCoolExc; + } catch ( seal::Exception& e ) { + std::cout << "seal::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusSealExc; + } catch( std::exception& se ) { + std::cout << "std::exception caught: '" << se.what() << "'" << std::endl; + status = statusStdExc; + } catch ( ... ) { + std::cout << "Unknown exception caught" << std::endl; + status = statusUnknown; + } + + // Different results are expected for different roles + std::string msg = + std::string( "Create node " ) + fullPath + " as user " + m_user; + if ( m_role == OWNER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == READER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotUpdated, status ); + } + else if ( m_role == WRITER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotUpdated, status ); + } + else if ( m_role == TAGGER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotUpdated, status ); + } + /* + else if ( m_role == NOPRIV ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ???, status ); + } + */ + else { + std::cout << "PANIC! Unknown role type" << std::endl; + exit( -1 ); + } + } + + //--------------------------------------------------------------------------- + + void test_ReadIOVs( const std::string& fullPath, + const std::string& tagName, + const unsigned long nExpected ) + { + std::string status; + const std::string statusOk = "OK - IOVs retrieved"; + const std::string statusCoolExc = "Not OK - Unknown COOL exception"; + const std::string statusSealExc = "Not OK - Unknown SEAL exception"; + const std::string statusStdExc = "Not OK - Unknown std::exception"; + const std::string statusUnknown = "Not OK - Unknown exception"; + unsigned long nActual = 0; + try { + IFolderPtr folder = m_db->getFolder( fullPath ); + IObjectIteratorPtr objs = + folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, m_chId, tagName ); + nActual = objs->size(); + status = statusOk; + } catch ( cool::Exception& e ) { + std::cout << "cool::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusCoolExc; + } catch ( seal::Exception& e ) { + std::cout << "seal::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusSealExc; + } catch( std::exception& se ) { + std::cout << "std::exception caught: '" << se.what() << "'" << std::endl; + status = statusStdExc; + } catch ( ... ) { + std::cout << "Unknown exception caught" << std::endl; + status = statusUnknown; + } + + // Different results are expected for different roles + std::string msg = + std::string( "Read IOVs of folder " ) + fullPath + " in tag " + tagName + + " as user " + m_user; + if ( m_role == OWNER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == READER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == WRITER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == TAGGER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + /* + else if ( m_role == NOPRIV ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ???, status ); + } + */ + else { + std::cout << "PANIC! Unknown role type" << std::endl; + exit( -1 ); + } + + // Also test that the expected number of IOVS was actually retrieved + if ( status == statusOk ) + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( msg + ": IOV count", nExpected, nActual ); + } + + //--------------------------------------------------------------------------- + + void test_TagIOVs( const std::string& fullPath, + const std::string& tagName, + const bool retag, + const unsigned long nExpected ) + { + std::string status; + const std::string statusOk = "OK - IOVs tagged"; + const std::string statusFolderSV = "Not OK - Single version folder"; + const std::string statusRowNotInserted = "Not OK - Row not inserted"; + const std::string statusRowNotUpdated = "Not OK - Row not updated"; + const std::string statusRowNotDeleted = "Not OK - Row not deleted"; + const std::string statusCoolExc = "Not OK - Unknown COOL exception"; + const std::string statusSealExc = "Not OK - Unknown SEAL exception"; + const std::string statusStdExc = "Not OK - Unknown std::exception"; + const std::string statusUnknown = "Not OK - Unknown exception"; + unsigned long nActual = 0; + try { + IFolderPtr folder = m_db->getFolder( fullPath ); + bool existsTag = m_db->existsTag( tagName ); + if ( retag ) { + if ( ! existsTag ) + throw Exception + ( "PANIC! Tag for retagging does not exist", "test_TagIOVs" ); + folder->deleteTag( tagName ); + } else { + if ( existsTag ) + throw Exception + ( "PANIC! Tag for new tagging already exists", "test_TagIOVs" ); + } + folder->tag( tagName, "Description of " + tagName ); + IObjectIteratorPtr objs = + folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, m_chId, tagName ); + nActual = objs->size(); + status = statusOk; + } catch ( FolderIsSingleVersion& /* dummy */ ) { + status = statusFolderSV; + } catch ( RowNotInserted& /* dummy */ ) { + status = statusRowNotInserted; + } catch ( RowNotUpdated& /* dummy */ ) { + status = statusRowNotUpdated; + } catch ( RowNotDeleted& /* dummy */ ) { + status = statusRowNotDeleted; + } catch ( cool::Exception& e ) { + std::cout << "cool::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusCoolExc; + } catch ( seal::Exception& e ) { + std::cout << "seal::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusSealExc; + } catch( std::exception& se ) { + std::cout << "std::exception caught: '" << se.what() << "'" << std::endl; + status = statusStdExc; + } catch ( ... ) { + std::cout << "Unknown exception caught" << std::endl; + status = statusUnknown; + } + + // Different results are expected for different roles + std::string msg; + if ( retag ) + msg = std::string( "Retag IOVs in folder " ) + fullPath + + " with tag " + tagName + " as user " + m_user; + else + msg = std::string( "Tag IOVs in folder " ) + fullPath + + " with tag " + tagName + " as user " + m_user; + if ( m_role == OWNER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == READER ) { + if ( !retag ) + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotUpdated, status ); + else + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotDeleted, status ); + } + else if ( m_role == WRITER ) { + if ( !retag ) + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotUpdated, status ); + else + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotDeleted, status ); + } + else if ( m_role == TAGGER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + /* + else if ( m_role == NOPRIV ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ???, status ); + } + */ + else { + std::cout << "PANIC! Unknown role type" << std::endl; + exit( -1 ); + } + + // Also test that the expected number of IOVs was retrieved + if ( status == statusOk ) + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( msg + ": IOV count", nExpected, nActual ); + } + + //--------------------------------------------------------------------------- + + void test_InsertIOVs( const std::string& fullPath, + const bool singleVersion ) + { + std::string status; + const std::string statusOk = "OK - IOVs inserted"; + const std::string statusRowNotInserted = "Not OK - Row not inserted"; + const std::string statusRowNotUpdated = "Not OK - Row not updated"; + const std::string statusCoolExc = "Not OK - Unknown COOL exception"; + const std::string statusSealExc = "Not OK - Unknown SEAL exception"; + const std::string statusStdExc = "Not OK - Unknown std::exception"; + const std::string statusUnknown = "Not OK - Unknown exception"; + unsigned long nExpected; + unsigned long nActual = 0; + try { + IFolderPtr folder = m_db->getFolder( fullPath ); + if ( singleVersion ) { + folder->storeObject( 50, ValidityKeyMax, dummyPayload( 11 ), m_chId ); + folder->storeObject( 100, ValidityKeyMax, dummyPayload( 12 ), m_chId ); + // New HEAD: [0,10] [10,20] [20,50] [50,100] [100,+inf] + nExpected = 5; + } + else { + folder->storeObject( 50, 100, dummyPayload( 11 ), m_chId ); + folder->storeObject( 60, 80, dummyPayload( 12 ), m_chId ); + // New HEAD: [0,10][10,20][20,30][30,40][40,50][50,60][60,80][80,100] + nExpected = 8; + } + IObjectIteratorPtr objs = + folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, m_chId, "" ); + nActual = objs->size(); + status = statusOk; + } catch ( RowNotInserted& /* dummy */ ) { + status = statusRowNotInserted; + } catch ( RowNotUpdated& /* dummy */ ) { + status = statusRowNotUpdated; + } catch ( cool::Exception& e ) { + std::cout << "cool::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusCoolExc; + } catch ( seal::Exception& e ) { + std::cout << "seal::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusSealExc; + } catch( std::exception& se ) { + std::cout << "std::exception caught: '" << se.what() << "'" << std::endl; + status = statusStdExc; + } catch ( ... ) { + std::cout << "Unknown exception caught" << std::endl; + status = statusUnknown; + } + + // Different results are expected for different roles + std::string msg = + std::string( "Insert IOVs into folder " ) + fullPath + + " as user " + m_user; + if ( m_role == OWNER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == READER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotUpdated, status ); + } + else if ( m_role == WRITER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == TAGGER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotUpdated, status ); + } + /* + else if ( m_role == NOPRIV ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ???, status ); + } + */ + else { + std::cout << "PANIC! Unknown role type" << std::endl; + exit( -1 ); + } + + // Also test that the expected number of IOVs was retrieved + if ( status == statusOk ) + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( msg + ": IOV count", nExpected, nActual ); + } + + //--------------------------------------------------------------------------- + + void test_DropNode( const std::string& fullPath, const bool isFolder ) + { + std::string status; + const std::string statusOk = "OK - Node dropped"; + const std::string statusNotFound = "Not OK - Node not found"; + const std::string statusTableNotDropped = "Not OK - Table not dropped"; + const std::string statusRowNotDeleted = "Not OK - Row not deleted"; + const std::string statusCoolExc = "Not OK - Unknown COOL exception"; + const std::string statusSealExc = "Not OK - Unknown SEAL exception"; + const std::string statusStdExc = "Not OK - Unknown std::exception"; + const std::string statusUnknown = "Not OK - Unknown exception"; + try { + m_db->dropNode( fullPath ); + status = statusOk; + } catch ( FolderNotFound& /* dummy */ ) { + status = statusNotFound; + } catch ( FolderSetNotFound& /* dummy */ ) { + status = statusNotFound; + } catch ( TableNotDropped& /* dummy */ ) { + status = statusTableNotDropped; + } catch ( RowNotDeleted& /* dummy */ ) { + status = statusRowNotDeleted; + } catch ( cool::Exception& e ) { + std::cout << "cool::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusCoolExc; + } catch ( seal::Exception& e ) { + std::cout << "seal::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusSealExc; + } catch( std::exception& se ) { + std::cout << "std::exception caught: '" << se.what() << "'" << std::endl; + status = statusStdExc; + } catch ( ... ) { + std::cout << "Unknown exception caught" << std::endl; + status = statusUnknown; + } + + // Different results are expected for different roles + std::string msg = + std::string( "Drop node " ) + fullPath + " as user " + m_user; + if ( m_role == OWNER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == READER ) { + if ( isFolder ) + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusTableNotDropped, status ); + else + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotDeleted, status ); + } + else if ( m_role == WRITER ) { + if ( isFolder ) + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusTableNotDropped, status ); + else + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotDeleted, status ); + } + else if ( m_role == TAGGER ) { + if ( isFolder ) + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusTableNotDropped, status ); + else + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotDeleted, status ); + } + /* + else if ( m_role == NOPRIV ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ???, status ); + } + */ + else { + std::cout << "PANIC! Unknown role type" << std::endl; + exit( -1 ); + } + } + + //--------------------------------------------------------------------------- + + void test_DropDatabase() + { + std::string status; + const std::string statusOk = "OK - Database dropped"; + const std::string statusNotFound = "Not OK - Database not found"; + const std::string statusTableNotDropped = "Not OK - Table not dropped"; + const std::string statusRowNotDeleted = "Not OK - Row not deleted"; + const std::string statusCoolExc = "Not OK - Unknown COOL exception"; + const std::string statusSealExc = "Not OK - Unknown SEAL exception"; + const std::string statusStdExc = "Not OK - Unknown std::exception"; + const std::string statusUnknown = "Not OK - Unknown exception"; + try { + IDatabaseSvc& dbSvc = databaseService(); + dbSvc.dropDatabase( m_connect ); + status = statusOk; + } catch ( DatabaseDoesNotExist& /* dummy */ ) { + status = statusNotFound; + } catch ( TableNotDropped& /* dummy */ ) { + status = statusTableNotDropped; + } catch ( RowNotDeleted& /* dummy */ ) { + status = statusRowNotDeleted; + } catch ( cool::Exception& e ) { + std::cout << "cool::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusCoolExc; + } catch ( seal::Exception& e ) { + std::cout << "seal::Exception caught: '" << e.message() <<"'"<<std::endl; + status = statusSealExc; + } catch( std::exception& se ) { + std::cout << "std::exception caught: '" << se.what() << "'" << std::endl; + status = statusStdExc; + } catch ( ... ) { + std::cout << "Unknown exception caught" << std::endl; + status = statusUnknown; + } + + // Different results are expected for different roles + std::string msg = std::string( "Drop database as user " ) + m_user; + if ( m_role == OWNER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusOk, status ); + } + else if ( m_role == READER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotDeleted, status ); + } + else if ( m_role == WRITER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotDeleted, status ); + } + else if ( m_role == TAGGER ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, statusRowNotDeleted, status ); + } + /* + else if ( m_role == NOPRIV ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ???, status ); + } + */ + else { + std::cout << "PANIC! Unknown role type" << std::endl; + exit( -1 ); + } + } + + //--------------------------------------------------------------------------- + + void testAll_Role( const Role role ) + { + m_role = role; + try { + + getConnectString(); + + dropDatabaseAsOwner(); + std::cout << "==> Start TEST: create database" << std::endl; + test_CreateDatabase(); + std::cout << "++++> End TEST: create database" << std::endl; + + createDatabaseAsOwner(); + std::cout << "==> Start TEST: open database" << std::endl; + bool openOK = test_OpenDatabase(); + std::cout << "++++> End TEST: open database" << std::endl; + + // Execute these tests only if the database can be opened + if ( openOK ) { + + std::cout << "==> Start TEST: create new MV folder" << std::endl; + test_CreateNode( m_fNameMV + "_new", true ); + std::cout << "++++> End TEST: create new MV folder" << std::endl; + + std::cout << "==> Start TEST: create new folder set" << std::endl; + test_CreateNode( m_fsName + "_new", false ); + std::cout << "++++> End TEST: create new folder set" << std::endl; + + std::cout << "==> Start TEST: read SV IOVs" << std::endl; + test_ReadIOVs( m_fNameSV, "", m_expSV ); + std::cout << "++++> End TEST: read SV IOVs" << std::endl; + + std::cout << "==> Start TEST: read MV IOVs head" << std::endl; + test_ReadIOVs( m_fNameMV, "", m_expMVhead ); + std::cout << "++++> End TEST: read MV IOVs head" << std::endl; + + std::cout << "==> Start TEST: read MV IOVs mytag" << std::endl; + test_ReadIOVs( m_fNameMV, m_tagMV, m_expMVtag ); + std::cout << "++++> End TEST: read MV IOVs mytag" << std::endl; + + std::cout << "==> Start TEST: tag MV IOVs" << std::endl; + test_TagIOVs( m_fNameMV, m_tagMV + "_new", false, m_expMVhead ); + std::cout << "++++> End TEST: tag MV IOVs" << std::endl; + + std::cout << "==> Start TEST: retag MV IOVs" << std::endl; + test_TagIOVs( m_fNameMV, m_tagMV, true, m_expMVhead ); + std::cout << "++++> End TEST: retag MV IOVs" << std::endl; + + std::cout << "==> Start TEST: insert SV IOVs" << std::endl; + test_InsertIOVs( m_fNameSV, true ); + std::cout << "++++> End TEST: insert SV IOVs" << std::endl; + + std::cout << "==> Start TEST: insert MV IOVs" << std::endl; + test_InsertIOVs( m_fNameMV, false ); + std::cout << "++++> End TEST: insert MV IOVs" << std::endl; + + std::cout << "==> Start TEST: drop SV folder" << std::endl; + test_DropNode( m_fNameSV, true ); + std::cout << "++++> End TEST: drop SV folder" << std::endl; + + std::cout << "==> Start TEST: drop MV folder" << std::endl; + test_DropNode( m_fNameMV, true ); + std::cout << "++++> End TEST: drop MV folder" << std::endl; + + std::cout << "==> Start TEST: drop folderset" << std::endl; + test_DropNode( m_fsName, false ); + std::cout << "++++> End TEST: drop folderset" << std::endl; + + std::cout << "==> Start TEST: drop database" << std::endl; + test_DropDatabase(); + std::cout << "++++> End TEST: drop database" << std::endl; + + } + + // Skip these tests if the database cannot even be opened + else { + std::cout << "**** SKIP TEST: create new MV folder" << std::endl; + std::cout << "**** SKIP TEST: create new folderset" << std::endl; + std::cout << "**** SKIP TEST: drop SV folder" << std::endl; + std::cout << "**** SKIP TEST: drop MV folder" << std::endl; + std::cout << "**** SKIP TEST: drop folderset" << std::endl; + std::cout << "**** SKIP TEST: drop database" << std::endl; + } + + } + + catch ( cool::Exception& e ) { + std::cout << "cool::Exception caught: '" << e.message()<<"'"<< std::endl; + std::cout << "++++++++++++++++++++++++++++++++++++++++++++" << std::endl; + throw; + } + + catch ( seal::Exception& e ) { + std::cout << "seal::Exception caught: '" << e.message()<<"'"<< std::endl; + std::cout << "++++++++++++++++++++++++++++++++++++++++++++" << std::endl; + throw; + } + + /* + // Comment this out: each CPPUNIT failure is itself an std::exception! + catch ( std::exception& se ) { + std::cout << "std::exception caught: '" << se.what() << "'" << std::endl; + std::cout << "++++++++++++++++++++++++++++++++++++++++++++" << std::endl; + throw; + } + */ + + catch ( ... ) { + std::cout << "UNKNOWN exception caught!" << std::endl; + std::cout << "++++++++++++++++++++++++++++++++++++++++++++" << std::endl; + throw; + } + + std::cout << "++++++++++++++++++++++++++++++++++++++++++++" << std::endl; + } + + //--------------------------------------------------------------------------- + + void testAll_Owner() { + testAll_Role( OWNER ); + } + + void testAll_Reader() { + testAll_Role( READER ); + } + + void testAll_Writer() { + testAll_Role( WRITER ); + } + + void testAll_Tagger() { + testAll_Role( TAGGER ); + } + + void testAll_NoPriv() { + testAll_Role( NOPRIV ); + } + + //--------------------------------------------------------------------------- + + pool::AttributeList dummyPayload( int index ) { + pool::AttributeList payload( m_payloadSpec ); + payload["A_INT"].setValue<int>( index ); + payload["A_FLOAT"].setValue<float>( (float)(index/1000.) ); + std::stringstream s; + s << "Object " << index; + payload["A_STRING"].setValue<std::string>( s.str() ); + return payload; + } + + void setUp() { + m_role = NONE; + m_connectOwner = ""; + m_userOwner = ""; + m_connect = ""; + m_user = ""; + IDatabasePtr dbNull; + m_db = dbNull; + if ( m_payloadSpec.size() == 0 ) { + m_payloadSpec.push_back( "A_INT", "int" ); + m_payloadSpec.push_back( "A_FLOAT", "float" ); + m_payloadSpec.push_back( "A_STRING", "string" ); + } + m_fNameSV = "/my/folderSV"; + m_fNameMV = "/my/folderMV"; + m_fsName = "/my/folderset"; + m_chId = 0; + } + + void tearDown() { + m_db.reset(); + } + + //--------------------------------------------------------------------------- + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( cool::PrivilegesTest ); +#include<CppUnit_testdriver.icpp> + +//----------------------------------------------------------------------------- + + +#endif // NOPORT diff --git a/RelationalCool/tests/ProcMemory/test_ProcMemory.cpp b/RelationalCool/tests/ProcMemory/test_ProcMemory.cpp new file mode 100644 index 000000000..654dab1b8 --- /dev/null +++ b/RelationalCool/tests/ProcMemory/test_ProcMemory.cpp @@ -0,0 +1,51 @@ +// $Id: test_ProcMemory.cpp,v 1.4 2008-08-06 09:33:07 avalassi Exp $ + +// Include files +#include <iostream> +#include <sstream> +#include <string> + +// Local include files +#include "../../src/ProcMemory.h" +#include "src/sleep.h" + +// Message output +#define LOG std::cout << "__main " + +//----------------------------------------------------------------------------- + +int main ( int /* argc */, char* /* argv[] */ ) +{ + long sleepSec = 0; + ProcMemory* mem = new ProcMemory(); + LOG << "-----------------------------------------------------" << std::endl; + LOG << "START of JOB" << std::endl; + mem->printVm(); + LOG << "-----------------------------------------------------" << std::endl; + cool::sleep(sleepSec); + LOG << "malloc 1MB " << std::endl; + void* p1m = malloc( 1048576 ); + mem->printVm(); + LOG << "-----------------------------------------------------" << std::endl; + cool::sleep(sleepSec); + LOG << "malloc 100MB " << std::endl; + void* p100m = malloc( 104857600 ); + mem->printVm(); + LOG << "-----------------------------------------------------" << std::endl; + cool::sleep(sleepSec); + LOG << "free 1MB " << std::endl; + free ( p1m ); + mem->printVm(); + LOG << "-----------------------------------------------------" << std::endl; + cool::sleep(sleepSec); + LOG << "free 100MB " << std::endl; + LOG << "END of JOB" << std::endl; + free ( p100m ); + mem->printVm(); + LOG << "-----------------------------------------------------" << std::endl; + cool::sleep(sleepSec); + delete mem; +} + +//---------------------------------------------------------------------------- + diff --git a/RelationalCool/tests/RalDatabase/README.threads b/RelationalCool/tests/RalDatabase/README.threads new file mode 100644 index 000000000..3b5c8ece6 --- /dev/null +++ b/RelationalCool/tests/RalDatabase/README.threads @@ -0,0 +1,51 @@ +2005.07.14 + +Problem with pthread_mutex_lock is solved! + +It was indeed enough to remove OCI_THREADED in OracleSession.cpp. + +This was tested using a private version of POOL. +With respect to POOL_2_1_1-beta, the following changes were made: + + // AV 2005.07.13 - start + // Test if OCI_THREADED __alone__ is responsible for COOL pthread_mutex_lock + //sword status = OCIEnvCreate( &m_environmentHandle, + // OCI_OBJECT, + // 0,0,0,0,0,0 ); + sword status; + if ( getenv ( "COOL_OCI_THREADED" ) ) + status = OCIEnvCreate( &m_environmentHandle, + OCI_THREADED | OCI_OBJECT, + 0,0,0,0,0,0 ); + else + status = OCIEnvCreate( &m_environmentHandle, + OCI_OBJECT, + 0,0,0,0,0,0 ); + // AV 2005.07.13 - end + +The test RalDatabaseTest::dropDatabase was executed alone +(all tests but dropDatabase were disabled in RalDatabaseTest), +with and without COOL_OCI_THREADED set: + +coolDropDatabase.csh $COOLTESTDB +unsetenv COOL_OCI_THREADED +date ; unitTest_RelationalCool_RalDatabase > & dropDatabaseTest.out.OCI_DEFAULT ; date +setenv COOL_OCI_THREADED on +date ; unitTest_RelationalCool_RalDatabase > & dropDatabaseTest.out.OCI_THREADED ; date +[Interrupted by Ctrl-C] +date +unsetenv COOL_OCI_THREADED +date ; unitTest_RelationalCool_RalDatabase > & dropDatabaseTest.out.OCI_DEFAULT.2 ; date + +The first and third job, with OCI_THREADED disabled, completed successfully +in around 30 seconds. The second job, with OCI_THREADED enabled, got stuck +and was killed with Ctrl-C after 2 minutes. The stack dump shows indeed +the problem with pthread_mutex_lock. + +The outputs from the first and second jobs are included in CVS +(not the output from the third job, which is similar to that +of the first one and was only meant as an additional cross-check). + +Problem solved!! :-) + + diff --git a/RelationalCool/tests/RalDatabase/dropDatabaseTest.out.OCI_DEFAULT b/RelationalCool/tests/RalDatabase/dropDatabaseTest.out.OCI_DEFAULT new file mode 100644 index 000000000..3c79ac646 --- /dev/null +++ b/RelationalCool/tests/RalDatabase/dropDatabaseTest.out.OCI_DEFAULT @@ -0,0 +1,229 @@ +(Start: Thu Jul 14 10:32:06 CEST 2005) +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/afs/cern.ch/user/a/avalassi/private/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +Application Info Instantiate a COOL Application +Application Info Load the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +RalDatabaseSvc Info Load the POOL relational service +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RalDatabaseSvc Info Load the POOL XML authentication service +ConfigurationService Debug Setting property: "AuthenticationFile" to value " "/afs/cern.ch/user/a/avalassi/private/authentication.xml"" in scope "POOL/Services/XMLAuthenticationService" +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RalAuthenticationManager Debug Retrieve COOL authentication credentials for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RalAuthenticationManager Debug Retrieve COOL authentication credentials using an authentication service +RalAuthenticationManager Debug Credentials found for 'oracle://devdb10;schema=lcg_cool' +RalAuthenticationManager Debug COOL authentication credentials successfully retrieved +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 10.1.0.4.0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RalAuthenticationManager Debug Retrieve COOL authentication credentials for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RalAuthenticationManager Debug Retrieve COOL authentication credentials using an authentication service +RalAuthenticationManager Debug Credentials found for 'oracle://devdb10;schema=lcg_cool' +RalAuthenticationManager Debug COOL authentication credentials successfully retrieved +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 10.1.0.4.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ( "DB_ATTRIBUTE_NAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ADD (CONSTRAINT "COOLTEST_DB_ATTRIBUTES_PK" PRIMARY KEY ("DB_ATTRIBUTE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_DB_ATTRIBUTES' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_DB_ATTRIBUTES' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_DB_ATTRIBUTES' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_DB_ATTRIBUTES' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_DB_ATTRIBUTES' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ADD ( "DB_ATTRIBUTE_VALUE" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_NODES" ( "NODE_ID" NUMBER(10), "NODE_PARENTID" NUMBER(10), "NODE_NAME" VARCHAR2(255), "NODE_FULLPATH" VARCHAR2(255), "NODE_DESCRIPTION" VARCHAR2(255), "NODE_ISLEAF" NUMBER(1), "NODE_INSTIME" VARCHAR2(255), "FOLDER_PAYLOADSPEC" VARCHAR2(255), "FOLDER_VERSIONING" NUMBER(10), "FOLDER_IOVTABLENAME" VARCHAR2(255), "FOLDER_TAGTABLENAME" VARCHAR2(255), "FOLDER_IOV2TAGTABLENAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD (CONSTRAINT "COOLTEST_NODES_PK" PRIMARY KEY ("NODE_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD (CONSTRAINT "COOLTEST_NODES_PARENT_FK" FOREIGN KEY ("NODE_PARENTID") REFERENCES "COOLTEST_NODES" ("NODE_ID"))" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE UNIQUE INDEX "LCG_COOL"."COOLTEST_NODES_PATH_UK" ON "LCG_COOL"."COOLTEST_NODES"("NODE_FULLPATH")" +RelationalDatabase Debug Altering table COOLTEST_NODES: modify the SQL type of column FOLDER_PAYLOADSPEC to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_NODES' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_NODES' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_NODES' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_NODES' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_NODES' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_PAYLOADSPEC"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_PAYLOADSPEC" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_VERSIONING"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_VERSIONING" NUMBER(10) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_IOVTABLENAME"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_IOVTABLENAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_TAGTABLENAME"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_TAGTABLENAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_IOV2TAGTABLENAME"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_IOV2TAGTABLENAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_NODES_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES_SEQ" ADD (CONSTRAINT "COOLTEST_NODES_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME") VALUES (:"NODE_ID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_TAGS" ( "TAG_ID" NUMBER(10), "NODE_ID" NUMBER(10), "TAG_NAME" VARCHAR2(255), "TAG_DESCRIPTION" VARCHAR2(255), "SYS_INSTIME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_TAGS" ADD (CONSTRAINT "COOLTEST_TAGS_PK" PRIMARY KEY ("TAG_ID","NODE_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/' +RelationalFolder Debug Delete the RelationalFolder for '/' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_PARENTID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME","FOLDER_PAYLOADSPEC","FOLDER_VERSIONING","FOLDER_IOVTABLENAME","FOLDER_TAGTABLENAME","FOLDER_IOV2TAGTABLENAME") VALUES (:"NODE_ID",:"NODE_PARENTID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME",:"FOLDER_PAYLOADSPEC",:"FOLDER_VERSIONING",:"FOLDER_IOVTABLENAME",:"FOLDER_TAGTABLENAME",:"FOLDER_IOV2TAGTABLENAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" ( "OBJECT_ID" NUMBER(10), "CHANNEL_ID" NUMBER(10), "IOV_SINCE" NUMBER(20), "IOV_UNTIL" NUMBER(20), "SYS_INSTIME" VARCHAR2(255), "ORIGINAL_ID" NUMBER(10), "NEW_HEAD_ID" NUMBER(10), "I" NUMBER(10), "S" VARCHAR2(255), "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" ADD (CONSTRAINT "COOLTEST_F0001_IOVS_PK" PRIMARY KEY ("OBJECT_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0001_IOVS_CO_2INDX" ON "LCG_COOL"."COOLTEST_F0001_IOVS"("CHANNEL_ID","OBJECT_ID")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0001_IOVS_CSU_3INDX" ON "LCG_COOL"."COOLTEST_F0001_IOVS"("CHANNEL_ID","IOV_SINCE","IOV_UNTIL")" +RelationalDatabase Debug Altering table COOLTEST_F0001_IOVS: modify the SQL type of column S to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_F0001_IOVS' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0001_IOVS' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_F0001_IOVS' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_F0001_IOVS' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0001_IOVS' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" DROP COLUMN "S"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" ADD ( "S" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" DROP COLUMN "X"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" ADD ( "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" ADD (CONSTRAINT "COOLTEST_F0001_IOVS_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/f1' +RelationalFolder Debug Delete the RelationalFolder for '/f1' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/' +RelationalFolder Debug Delete the RelationalFolder for '/' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_PARENTID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME","FOLDER_PAYLOADSPEC","FOLDER_VERSIONING","FOLDER_IOVTABLENAME","FOLDER_TAGTABLENAME","FOLDER_IOV2TAGTABLENAME") VALUES (:"NODE_ID",:"NODE_PARENTID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME",:"FOLDER_PAYLOADSPEC",:"FOLDER_VERSIONING",:"FOLDER_IOVTABLENAME",:"FOLDER_TAGTABLENAME",:"FOLDER_IOV2TAGTABLENAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" ( "OBJECT_ID" NUMBER(10), "CHANNEL_ID" NUMBER(10), "IOV_SINCE" NUMBER(20), "IOV_UNTIL" NUMBER(20), "SYS_INSTIME" VARCHAR2(255), "ORIGINAL_ID" NUMBER(10), "NEW_HEAD_ID" NUMBER(10), "I" NUMBER(10), "S" VARCHAR2(255), "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" ADD (CONSTRAINT "COOLTEST_F0002_IOVS_PK" PRIMARY KEY ("OBJECT_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0002_IOVS_CO_2INDX" ON "LCG_COOL"."COOLTEST_F0002_IOVS"("CHANNEL_ID","OBJECT_ID")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0002_IOVS_CSU_3INDX" ON "LCG_COOL"."COOLTEST_F0002_IOVS"("CHANNEL_ID","IOV_SINCE","IOV_UNTIL")" +RelationalDatabase Debug Altering table COOLTEST_F0002_IOVS: modify the SQL type of column S to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_F0002_IOVS' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0002_IOVS' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_F0002_IOVS' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_F0002_IOVS' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0002_IOVS' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" DROP COLUMN "S"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" ADD ( "S" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" DROP COLUMN "X"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" ADD ( "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" ADD (CONSTRAINT "COOLTEST_F0002_IOVS_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/f2' +RelationalFolder Debug Delete the RelationalFolder for '/f2' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/' +RelationalFolder Debug Delete the RelationalFolder for '/' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_PARENTID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME","FOLDER_PAYLOADSPEC","FOLDER_VERSIONING","FOLDER_IOVTABLENAME","FOLDER_TAGTABLENAME","FOLDER_IOV2TAGTABLENAME") VALUES (:"NODE_ID",:"NODE_PARENTID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME",:"FOLDER_PAYLOADSPEC",:"FOLDER_VERSIONING",:"FOLDER_IOVTABLENAME",:"FOLDER_TAGTABLENAME",:"FOLDER_IOV2TAGTABLENAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" ( "OBJECT_ID" NUMBER(10), "CHANNEL_ID" NUMBER(10), "IOV_SINCE" NUMBER(20), "IOV_UNTIL" NUMBER(20), "SYS_INSTIME" VARCHAR2(255), "ORIGINAL_ID" NUMBER(10), "NEW_HEAD_ID" NUMBER(10), "I" NUMBER(10), "S" VARCHAR2(255), "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" ADD (CONSTRAINT "COOLTEST_F0003_IOVS_PK" PRIMARY KEY ("OBJECT_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0003_IOVS_CO_2INDX" ON "LCG_COOL"."COOLTEST_F0003_IOVS"("CHANNEL_ID","OBJECT_ID")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0003_IOVS_CSU_3INDX" ON "LCG_COOL"."COOLTEST_F0003_IOVS"("CHANNEL_ID","IOV_SINCE","IOV_UNTIL")" +RelationalDatabase Debug Altering table COOLTEST_F0003_IOVS: modify the SQL type of column S to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_F0003_IOVS' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0003_IOVS' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_F0003_IOVS' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_F0003_IOVS' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0003_IOVS' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" DROP COLUMN "S"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" ADD ( "S" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" DROP COLUMN "X"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" ADD ( "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" ADD (CONSTRAINT "COOLTEST_F0003_IOVS_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/f3' +RelationalFolder Debug Delete the RelationalFolder for '/f3' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/' +RelationalFolder Debug Delete the RelationalFolder for '/' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_PARENTID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME","FOLDER_PAYLOADSPEC","FOLDER_VERSIONING","FOLDER_IOVTABLENAME","FOLDER_TAGTABLENAME","FOLDER_IOV2TAGTABLENAME") VALUES (:"NODE_ID",:"NODE_PARENTID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME",:"FOLDER_PAYLOADSPEC",:"FOLDER_VERSIONING",:"FOLDER_IOVTABLENAME",:"FOLDER_TAGTABLENAME",:"FOLDER_IOV2TAGTABLENAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" ( "OBJECT_ID" NUMBER(10), "CHANNEL_ID" NUMBER(10), "IOV_SINCE" NUMBER(20), "IOV_UNTIL" NUMBER(20), "SYS_INSTIME" VARCHAR2(255), "ORIGINAL_ID" NUMBER(10), "NEW_HEAD_ID" NUMBER(10), "I" NUMBER(10), "S" VARCHAR2(255), "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" ADD (CONSTRAINT "COOLTEST_F0004_IOVS_PK" PRIMARY KEY ("OBJECT_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0004_IOVS_CO_2INDX" ON "LCG_COOL"."COOLTEST_F0004_IOVS"("CHANNEL_ID","OBJECT_ID")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0004_IOVS_CSU_3INDX" ON "LCG_COOL"."COOLTEST_F0004_IOVS"("CHANNEL_ID","IOV_SINCE","IOV_UNTIL")" +RelationalDatabase Debug Altering table COOLTEST_F0004_IOVS: modify the SQL type of column S to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_F0004_IOVS' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0004_IOVS' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_F0004_IOVS' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_F0004_IOVS' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0004_IOVS' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" DROP COLUMN "S"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" ADD ( "S" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" DROP COLUMN "X"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" ADD ( "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" ADD (CONSTRAINT "COOLTEST_F0004_IOVS_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/f4' +RelationalFolder Debug Delete the RelationalFolder for '/f4' +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_TAGS"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_F0004_IOVS"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DELETE FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_F0003_IOVS"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DELETE FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_F0002_IOVS"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DELETE FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_F0001_IOVS"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DELETE FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_PARENTID"= :"parentId" and "NODE_ISLEAF"= :"isLeaf" ORDER BY "NODE_FULLPATH" ASC" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_PARENTID"= :"parentId" and "NODE_ISLEAF"= :"isLeaf" ORDER BY "NODE_FULLPATH" ASC" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DELETE FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_NODES_SEQ"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_NODES"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_DB_ATTRIBUTES"" + +OK (1) +[OVAL] Cppunit-result =0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +Application Info Delete the COOL Application +RalDatabaseSvc Info Delete the RalDatabaseSvc +(Start: Thu Jul 14 10:32:06 CEST 2005) +(End: Thu Jul 14 10:32:34 CEST 2005) + diff --git a/RelationalCool/tests/RalDatabase/dropDatabaseTest.out.OCI_THREADED b/RelationalCool/tests/RalDatabase/dropDatabaseTest.out.OCI_THREADED new file mode 100644 index 000000000..8a48f0002 --- /dev/null +++ b/RelationalCool/tests/RalDatabase/dropDatabaseTest.out.OCI_THREADED @@ -0,0 +1,306 @@ +(Start: Thu Jul 14 10:32:53 CEST 2005) +Property Catalogue: level[Info] Adding property: OutputLevel = 2 in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: Format = "%-36s %-8s %s" in scope "SEAL/Services/MessageService" +Property Catalogue: level[Info] Adding property: AuthenticationFile = "/afs/cern.ch/user/a/avalassi/private/authentication.xml" in scope "POOL/Services/XMLAuthenticationService" +MessageService callback Debug MessageService output level changed to Debug +ConfigurationService Debug Setting property: "Format" to value " "%-36s %-8s %s"" in scope "SEAL/Services/MessageService" +Application Info Instantiate a COOL Application +Application Info Load the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +RalDatabaseSvc Info Load the POOL relational service +POOL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with implementation "odbc" +POOL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +POOL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +POOL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is "odbc" +POOL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +POOL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +RalDatabaseSvc Info Load the POOL XML authentication service +ConfigurationService Debug Setting property: "AuthenticationFile" to value " "/afs/cern.ch/user/a/avalassi/private/authentication.xml"" in scope "POOL/Services/XMLAuthenticationService" +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RalAuthenticationManager Debug Retrieve COOL authentication credentials for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RalAuthenticationManager Debug Retrieve COOL authentication credentials using an authentication service +RalAuthenticationManager Debug Credentials found for 'oracle://devdb10;schema=lcg_cool' +RalAuthenticationManager Debug COOL authentication credentials successfully retrieved +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 10.1.0.4.0 +RelationalDatabase Info Delete the RalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +POOL/RelationalPlugins/oracle Warning No active transaction to roll back +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Instantiate a RalDatabase for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RalAuthenticationManager Debug Retrieve COOL authentication credentials for 'oracle://devdb10;schema=lcg_cool;dbname=COOLTEST' +RalAuthenticationManager Debug Retrieve COOL authentication credentials using an authentication service +RalAuthenticationManager Debug Credentials found for 'oracle://devdb10;schema=lcg_cool' +RalAuthenticationManager Debug COOL authentication credentials successfully retrieved +POOL/RelationalPlugins/oracle Info Connected to a server running Oracle version 10.1.0.4.0 +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ( "DB_ATTRIBUTE_NAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ADD (CONSTRAINT "COOLTEST_DB_ATTRIBUTES_PK" PRIMARY KEY ("DB_ATTRIBUTE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_DB_ATTRIBUTES' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_DB_ATTRIBUTES' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_DB_ATTRIBUTES' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_DB_ATTRIBUTES' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_DB_ATTRIBUTES' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ADD ( "DB_ATTRIBUTE_VALUE" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_DB_ATTRIBUTES" ("DB_ATTRIBUTE_NAME","DB_ATTRIBUTE_VALUE") VALUES (:"DB_ATTRIBUTE_NAME",:"DB_ATTRIBUTE_VALUE")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_NODES" ( "NODE_ID" NUMBER(10), "NODE_PARENTID" NUMBER(10), "NODE_NAME" VARCHAR2(255), "NODE_FULLPATH" VARCHAR2(255), "NODE_DESCRIPTION" VARCHAR2(255), "NODE_ISLEAF" NUMBER(1), "NODE_INSTIME" VARCHAR2(255), "FOLDER_PAYLOADSPEC" VARCHAR2(255), "FOLDER_VERSIONING" NUMBER(10), "FOLDER_IOVTABLENAME" VARCHAR2(255), "FOLDER_TAGTABLENAME" VARCHAR2(255), "FOLDER_IOV2TAGTABLENAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD (CONSTRAINT "COOLTEST_NODES_PK" PRIMARY KEY ("NODE_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD (CONSTRAINT "COOLTEST_NODES_PARENT_FK" FOREIGN KEY ("NODE_PARENTID") REFERENCES "COOLTEST_NODES" ("NODE_ID"))" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE UNIQUE INDEX "LCG_COOL"."COOLTEST_NODES_PATH_UK" ON "LCG_COOL"."COOLTEST_NODES"("NODE_FULLPATH")" +RelationalDatabase Debug Altering table COOLTEST_NODES: modify the SQL type of column FOLDER_PAYLOADSPEC to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_NODES' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_NODES' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_NODES' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_NODES' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_NODES' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_PAYLOADSPEC"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_PAYLOADSPEC" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_VERSIONING"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_VERSIONING" NUMBER(10) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_IOVTABLENAME"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_IOVTABLENAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_TAGTABLENAME"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_TAGTABLENAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" DROP COLUMN "FOLDER_IOV2TAGTABLENAME"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES" ADD ( "FOLDER_IOV2TAGTABLENAME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_NODES_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_NODES_SEQ" ADD (CONSTRAINT "COOLTEST_NODES_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME") VALUES (:"NODE_ID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_TAGS" ( "TAG_ID" NUMBER(10), "NODE_ID" NUMBER(10), "TAG_NAME" VARCHAR2(255), "TAG_DESCRIPTION" VARCHAR2(255), "SYS_INSTIME" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_TAGS" ADD (CONSTRAINT "COOLTEST_TAGS_PK" PRIMARY KEY ("TAG_ID","NODE_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/' +RelationalFolder Debug Delete the RelationalFolder for '/' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_PARENTID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME","FOLDER_PAYLOADSPEC","FOLDER_VERSIONING","FOLDER_IOVTABLENAME","FOLDER_TAGTABLENAME","FOLDER_IOV2TAGTABLENAME") VALUES (:"NODE_ID",:"NODE_PARENTID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME",:"FOLDER_PAYLOADSPEC",:"FOLDER_VERSIONING",:"FOLDER_IOVTABLENAME",:"FOLDER_TAGTABLENAME",:"FOLDER_IOV2TAGTABLENAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" ( "OBJECT_ID" NUMBER(10), "CHANNEL_ID" NUMBER(10), "IOV_SINCE" NUMBER(20), "IOV_UNTIL" NUMBER(20), "SYS_INSTIME" VARCHAR2(255), "ORIGINAL_ID" NUMBER(10), "NEW_HEAD_ID" NUMBER(10), "I" NUMBER(10), "S" VARCHAR2(255), "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" ADD (CONSTRAINT "COOLTEST_F0001_IOVS_PK" PRIMARY KEY ("OBJECT_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0001_IOVS_CO_2INDX" ON "LCG_COOL"."COOLTEST_F0001_IOVS"("CHANNEL_ID","OBJECT_ID")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0001_IOVS_CSU_3INDX" ON "LCG_COOL"."COOLTEST_F0001_IOVS"("CHANNEL_ID","IOV_SINCE","IOV_UNTIL")" +RelationalDatabase Debug Altering table COOLTEST_F0001_IOVS: modify the SQL type of column S to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_F0001_IOVS' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0001_IOVS' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_F0001_IOVS' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_F0001_IOVS' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0001_IOVS' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" DROP COLUMN "S"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" ADD ( "S" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" DROP COLUMN "X"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS" ADD ( "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" ADD (CONSTRAINT "COOLTEST_F0001_IOVS_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_F0001_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/f1' +RelationalFolder Debug Delete the RelationalFolder for '/f1' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/' +RelationalFolder Debug Delete the RelationalFolder for '/' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_PARENTID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME","FOLDER_PAYLOADSPEC","FOLDER_VERSIONING","FOLDER_IOVTABLENAME","FOLDER_TAGTABLENAME","FOLDER_IOV2TAGTABLENAME") VALUES (:"NODE_ID",:"NODE_PARENTID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME",:"FOLDER_PAYLOADSPEC",:"FOLDER_VERSIONING",:"FOLDER_IOVTABLENAME",:"FOLDER_TAGTABLENAME",:"FOLDER_IOV2TAGTABLENAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" ( "OBJECT_ID" NUMBER(10), "CHANNEL_ID" NUMBER(10), "IOV_SINCE" NUMBER(20), "IOV_UNTIL" NUMBER(20), "SYS_INSTIME" VARCHAR2(255), "ORIGINAL_ID" NUMBER(10), "NEW_HEAD_ID" NUMBER(10), "I" NUMBER(10), "S" VARCHAR2(255), "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" ADD (CONSTRAINT "COOLTEST_F0002_IOVS_PK" PRIMARY KEY ("OBJECT_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0002_IOVS_CO_2INDX" ON "LCG_COOL"."COOLTEST_F0002_IOVS"("CHANNEL_ID","OBJECT_ID")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0002_IOVS_CSU_3INDX" ON "LCG_COOL"."COOLTEST_F0002_IOVS"("CHANNEL_ID","IOV_SINCE","IOV_UNTIL")" +RelationalDatabase Debug Altering table COOLTEST_F0002_IOVS: modify the SQL type of column S to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_F0002_IOVS' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0002_IOVS' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_F0002_IOVS' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_F0002_IOVS' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0002_IOVS' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" DROP COLUMN "S"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" ADD ( "S" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" DROP COLUMN "X"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS" ADD ( "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" ADD (CONSTRAINT "COOLTEST_F0002_IOVS_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_F0002_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/f2' +RelationalFolder Debug Delete the RelationalFolder for '/f2' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/' +RelationalFolder Debug Delete the RelationalFolder for '/' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_PARENTID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME","FOLDER_PAYLOADSPEC","FOLDER_VERSIONING","FOLDER_IOVTABLENAME","FOLDER_TAGTABLENAME","FOLDER_IOV2TAGTABLENAME") VALUES (:"NODE_ID",:"NODE_PARENTID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME",:"FOLDER_PAYLOADSPEC",:"FOLDER_VERSIONING",:"FOLDER_IOVTABLENAME",:"FOLDER_TAGTABLENAME",:"FOLDER_IOV2TAGTABLENAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" ( "OBJECT_ID" NUMBER(10), "CHANNEL_ID" NUMBER(10), "IOV_SINCE" NUMBER(20), "IOV_UNTIL" NUMBER(20), "SYS_INSTIME" VARCHAR2(255), "ORIGINAL_ID" NUMBER(10), "NEW_HEAD_ID" NUMBER(10), "I" NUMBER(10), "S" VARCHAR2(255), "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" ADD (CONSTRAINT "COOLTEST_F0003_IOVS_PK" PRIMARY KEY ("OBJECT_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0003_IOVS_CO_2INDX" ON "LCG_COOL"."COOLTEST_F0003_IOVS"("CHANNEL_ID","OBJECT_ID")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0003_IOVS_CSU_3INDX" ON "LCG_COOL"."COOLTEST_F0003_IOVS"("CHANNEL_ID","IOV_SINCE","IOV_UNTIL")" +RelationalDatabase Debug Altering table COOLTEST_F0003_IOVS: modify the SQL type of column S to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_F0003_IOVS' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0003_IOVS' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_F0003_IOVS' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_F0003_IOVS' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0003_IOVS' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" DROP COLUMN "S"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" ADD ( "S" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" DROP COLUMN "X"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS" ADD ( "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" ADD (CONSTRAINT "COOLTEST_F0003_IOVS_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_F0003_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/f3' +RelationalFolder Debug Delete the RelationalFolder for '/f3' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/' +RelationalFolder Debug Delete the RelationalFolder for '/' +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_NODES_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_NODES_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_NODES" ("NODE_ID","NODE_PARENTID","NODE_NAME","NODE_FULLPATH","NODE_DESCRIPTION","NODE_ISLEAF","NODE_INSTIME","FOLDER_PAYLOADSPEC","FOLDER_VERSIONING","FOLDER_IOVTABLENAME","FOLDER_TAGTABLENAME","FOLDER_IOV2TAGTABLENAME") VALUES (:"NODE_ID",:"NODE_PARENTID",:"NODE_NAME",:"NODE_FULLPATH",:"NODE_DESCRIPTION",:"NODE_ISLEAF",:"NODE_INSTIME",:"FOLDER_PAYLOADSPEC",:"FOLDER_VERSIONING",:"FOLDER_IOVTABLENAME",:"FOLDER_TAGTABLENAME",:"FOLDER_IOV2TAGTABLENAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" ( "OBJECT_ID" NUMBER(10), "CHANNEL_ID" NUMBER(10), "IOV_SINCE" NUMBER(20), "IOV_UNTIL" NUMBER(20), "SYS_INSTIME" VARCHAR2(255), "ORIGINAL_ID" NUMBER(10), "NEW_HEAD_ID" NUMBER(10), "I" NUMBER(10), "S" VARCHAR2(255), "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" ADD (CONSTRAINT "COOLTEST_F0004_IOVS_PK" PRIMARY KEY ("OBJECT_ID") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0004_IOVS_CO_2INDX" ON "LCG_COOL"."COOLTEST_F0004_IOVS"("CHANNEL_ID","OBJECT_ID")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE INDEX "LCG_COOL"."COOLTEST_F0004_IOVS_CSU_3INDX" ON "LCG_COOL"."COOLTEST_F0004_IOVS"("CHANNEL_ID","IOV_SINCE","IOV_UNTIL")" +RelationalDatabase Debug Altering table COOLTEST_F0004_IOVS: modify the SQL type of column S to VARCHAR2(4000) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT ALL_CONS_COLUMNS.COLUMN_NAME FROM ALL_CONSTRAINTS, ALL_CONS_COLUMNS WHERE ALL_CONSTRAINTS.OWNER = 'LCG_COOL' AND ALL_CONSTRAINTS.TABLE_NAME = 'COOLTEST_F0004_IOVS' AND ALL_CONSTRAINTS.CONSTRAINT_TYPE = 'U' AND ALL_CONS_COLUMNS.CONSTRAINT_NAME = ALL_CONSTRAINTS.CONSTRAINT_NAME AND ALL_CONS_COLUMNS.OWNER = ALL_CONSTRAINTS.OWNER AND ALL_CONS_COLUMNS.TABLE_NAME = ALL_CONSTRAINTS.TABLE_NAME" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME, B.COLUMN_NAME FROM ALL_CONSTRAINTS A, ALL_CONS_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0004_IOVS' AND A.CONSTRAINT_TYPE = 'P' AND B.OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND B.CONSTRAINT_NAME = A.CONSTRAINT_NAME ORDER BY B.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.CONSTRAINT_NAME AS FK_NAME, B.TABLE_NAME AS REF_TABLE, C.COLUMN_NAME AS FK_COL, D.COLUMN_NAME AS REF_COL FROM (SELECT CONSTRAINT_NAME, R_CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL' AND TABLE_NAME = 'COOLTEST_F0004_IOVS' AND CONSTRAINT_TYPE='R') A, (SELECT TABLE_NAME, CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER='LCG_COOL') B, (SELECT COLUMN_NAME, CONSTRAINT_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL' AND TABLE_NAME='COOLTEST_F0004_IOVS' ORDER BY POSITION) C, (SELECT COLUMN_NAME, CONSTRAINT_NAME, TABLE_NAME, POSITION FROM ALL_CONS_COLUMNS WHERE OWNER='LCG_COOL') D WHERE A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND B.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.POSITION = D.POSITION ORDER BY FK_NAME, D.POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT A.INDEX_NAME, A.UNIQUENESS, B.COLUMN_NAME FROM ALL_INDEXES A, ALL_IND_COLUMNS B WHERE A.OWNER = 'LCG_COOL' AND A.TABLE_NAME = 'COOLTEST_F0004_IOVS' AND A.GENERATED = 'N' AND A.INDEX_NAME = B.INDEX_NAME AND B.INDEX_OWNER = A.OWNER AND B.TABLE_NAME = A.TABLE_NAME AND A.INDEX_NAME NOT IN (SELECT CONSTRAINT_NAME FROM ALL_CONSTRAINTS WHERE OWNER = A.OWNER AND TABLE_NAME = A.TABLE_NAME AND CONSTRAINT_TYPE = 'P') ORDER BY A.INDEX_NAME, B.COLUMN_POSITION" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" DROP COLUMN "S"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" ADD ( "S" VARCHAR2(4000) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" DROP COLUMN "X"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS" ADD ( "X" BINARY_FLOAT )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "CREATE TABLE "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" ( "SEQUENCE_NAME" VARCHAR2(255), "CURRENT_VALUE" NUMBER(10), "LASTMOD_DATE" VARCHAR2(255) )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "ALTER TABLE "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" ADD (CONSTRAINT "COOLTEST_F0004_IOVS_SEQ_PK" PRIMARY KEY ("SEQUENCE_NAME") )" +POOL/RelationalPlugins/oracle Debug Prepared statement : "INSERT INTO "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" ("SEQUENCE_NAME") VALUES (:"SEQUENCE_NAME")" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" FOR UPDATE" +POOL/RelationalPlugins/oracle Debug Prepared statement : "UPDATE "LCG_COOL"."COOLTEST_F0004_IOVS_SEQ" SET "CURRENT_VALUE"=:"newvalue", "LASTMOD_DATE"=TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'GMT','yyyy-mm-dd_hh24:mi:ss.ff6')||'000 GMT'" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalFolder Debug Instantiate a RelationalFolder for '/f4' +RelationalFolder Debug Delete the RelationalFolder for '/f4' +POOL/RelationalPlugins/oracle Debug Prepared statement : "DROP TABLE "LCG_COOL"."COOLTEST_TAGS"" +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_INSTIME", "FOLDER_PAYLOADSPEC", "FOLDER_VERSIONING", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME" FROM "LCG_COOL"."COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" + +unitTest_RelationalCool_RalDatabase (pid=5443 ppid=9055) received fatal signal 2 (Interrupt) +signal context: + signo = 2, errno = 0, code = 128 (kernel) + pid = 0, uid = 0 + value = (6114303, 0x5d4bff) + stack = (2, 0, (nil)) + + eip: 0023:00e167f9 eflags: 00200202 + eax: fffffffc ebx: 0988d020 ecx: 00000000 edx: 00000002 + esi: 00000000 edi: 09889a20 ebp: bfff730c esp: bfff72f4 + ds: 002b es: 002b fs: 0000 ss: 002b + + signal esp: bfff72f4 trap: 0/0 oldmask: 00000000 cr2: 00000000 + + FPU: control = ffff027f + status = ffff0100 + tag = ffffffff + ip = 0023:01995604 + data = 002b:01db72a4 + state = 00000100 + %fp0 = [0000:0000000000000000] + %fp1 = [0000:0000000000000000] + %fp2 = [0000:0000000000000000] + %fp3 = [0000:0000000000000000] + %fp4 = [0000:0000000000000000] + %fp5 = [400d:000000000000a182] + %fp6 = [4009:0000000000008000] + %fp7 = [400b:0000000000008000] + +stack trace: + 0x003d75ac _ZN4seal9DebugAids10stacktraceEi + 0x60 [/afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealBase.so] + 0x00401ede _ZN4seal6Signal9fatalDumpEiP7siginfoPv + 0xde [/afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealBase.so] + 0x00401909 _ZN4seal6Signal5fatalEiP7siginfoPv + 0xd5 [/afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealBase.so] + 0x00512eb0 ? + 0x512eb0 [/lib/tls/libc.so.6] + 0x005d4bbf pthread_mutex_lock + 0x2f [/lib/tls/libc.so.6] + 0x01b9c4a6 sltsmna + 0x1e [/afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/slc3_ia32_gcc323/lib/libclntsh.so.10.1] + 0x013f5cee kpustmtrelease + 0x8ba [/afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/slc3_ia32_gcc323/lib/libclntsh.so.10.1] + 0x01470a55 OCIStmtRelease + 0xa9 [/afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/slc3_ia32_gcc323/lib/libclntsh.so.10.1] + 0x0098deff _ZN4pool12OracleAccess15OracleStatement5resetEv + 0x31b [/afs/cern.ch/user/a/avalassi/myLCG/POOL_2_1_1/slc3_ia32_gcc323/lib/liblcg_OracleAccess.so] + 0x00983589 _ZN4pool12OracleAccess15OracleStatementD1Ev + 0x1d [/afs/cern.ch/user/a/avalassi/myLCG/POOL_2_1_1/slc3_ia32_gcc323/lib/liblcg_OracleAccess.so] + 0x0096ab23 _ZN4pool12OracleAccess18OracleQueryInTable5resetEv + 0x317 [/afs/cern.ch/user/a/avalassi/myLCG/POOL_2_1_1/slc3_ia32_gcc323/lib/liblcg_OracleAccess.so] + 0x00966fb5 _ZN4pool12OracleAccess18OracleQueryInTableD0Ev + 0x29 [/afs/cern.ch/user/a/avalassi/myLCG/POOL_2_1_1/slc3_ia32_gcc323/lib/liblcg_OracleAccess.so] + 0x00ad9ba0 _ZN4cool11RalDatabase12listAllNodesEb + 0x4b0 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/slc3_ia32_gcc323/lib/liblcg_RelationalCool.so] + 0x00ad5983 _ZN4cool11RalDatabase12dropAllNodesEv + 0x37 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/slc3_ia32_gcc323/lib/liblcg_RelationalCool.so] + 0x00aa9548 _ZN4cool11RalDatabase12dropDatabaseEv + 0xf4 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/slc3_ia32_gcc323/lib/liblcg_RelationalCool.so] + 0x0804ea1a _ZN4cool15RalDatabaseTest17test_dropDatabaseEv + 0x39e [unitTest_RelationalCool_RalDatabase] + 0x080506f8 _ZN7CppUnit10TestCallerIN4cool15RalDatabaseTestENS_19NoExceptionExpectedEE7runTestEv + 0x38 [unitTest_RelationalCool_RalDatabase] + 0x0091411c _ZN7CppUnit8TestCase3runEPNS_10TestResultE + 0x40 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/slc3_ia32_gcc323/lib/libcppunit-1.8.so.0] + 0x0091cf10 _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x38 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/slc3_ia32_gcc323/lib/libcppunit-1.8.so.0] + 0x0091cf10 _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x38 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/slc3_ia32_gcc323/lib/libcppunit-1.8.so.0] + 0x0091cf10 _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x38 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/slc3_ia32_gcc323/lib/libcppunit-1.8.so.0] + 0x0091c643 _ZN7CppUnit6TextUi10TestRunner7runTestEPNS_4TestEb + 0x3f [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/slc3_ia32_gcc323/lib/libcppunit-1.8.so.0] + 0x0091c33d _ZN7CppUnit6TextUi10TestRunner13runTestByNameESsb + 0x39 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/slc3_ia32_gcc323/lib/libcppunit-1.8.so.0] + 0x0091c255 _ZN7CppUnit6TextUi10TestRunner3runESsbbb + 0x49 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/slc3_ia32_gcc323/lib/libcppunit-1.8.so.0] + 0x0804b830 main + 0xb0 [unitTest_RelationalCool_RalDatabase] + 0x0050078a __libc_start_main + 0xda [/lib/tls/libc.so.6] + 0x0804b6f5 _ZN7CppUnit14TypeInfoHelper12getClassNameERKSt9type_info + 0x31 [unitTest_RelationalCool_RalDatabase] + +shared libraries present: + 0x00000000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/slc3_ia32_gcc323/tests/bin/unitTest_RelationalCool_RalDatabase + 0x003ae000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealBase.so + 0x00c86000 /afs/cern.ch/user/a/avalassi/myLCG/POOL_2_1_1/slc3_ia32_gcc323/lib/liblcg_AttributeList.so + 0x0072e000 /afs/cern.ch/user/a/avalassi/myLCG/POOL_2_1_1/slc3_ia32_gcc323/lib/liblcg_POOLCore.so + 0x00111000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_PluginManager.so + 0x00172000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealKernel.so + 0x00de7000 /afs/cern.ch/user/a/avalassi/myLCG/POOL_2_1_1/slc3_ia32_gcc323/lib/liblcg_RelationalAccess.so + 0x00131000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealUtil.so + 0x00a6d000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/slc3_ia32_gcc323/lib/liblcg_RelationalCool.so + 0x0076c000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/slc3_ia32_gcc323/lib/liblcg_CoolApplication.so + 0x0026d000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_Reflection.so + 0x004b0000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealServices.so + 0x00898000 /afs/cern.ch/sw/lcg/external/uuid/1.32/slc3_ia32_gcc323/lib/libuuid.so.1 + 0x00902000 /afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/slc3_ia32_gcc323/lib/libcppunit-1.8.so.0 + 0x0069a000 /afs/cern.ch/sw/lcg/external/pcre/4.4/slc3_ia32_gcc323/lib/libpcre.so.0 + 0x00446000 /lib/libnsl.so.1 + 0x00e4f000 /lib/libcrypt.so.1 + 0x0013e000 /lib/libdl.so.2 + 0x0018c000 /usr/lib/libstdc++.so.5 + 0x00832000 /lib/tls/libm.so.6 + 0x00b5a000 /lib/libgcc_s.so.1 + 0x004eb000 /lib/tls/libc.so.6 + 0x00e0d000 /lib/tls/libpthread.so.0 + 0x00bc1000 /lib/ld-linux.so.2 + 0x00141000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_MyComponent.so + 0x0065a000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_MyBaseComponent.so + 0x00147000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_MyComponent1.so + 0x0014d000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_ExampleComponents.so + 0x00c41000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealStorage.so + 0x0023f000 /afs/cern.ch/sw/lcg/external/Boost/1.32.0/slc3_ia32_gcc323/lib/libboost_thread-gcc-mt.so + 0x00bf7000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealZip.so + 0x00299000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_SealIOTools.so + 0x0015d000 /usr/lib/libz.so.1 + 0x00f86000 /lib/tls/librt.so.1 + 0x00b7e000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/libCMSExamplesDict.so + 0x002bf000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_ReflectionBuilder.so + 0x008cf000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/libCMSExamplesRflx.so + 0x002cf000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/liblcg_Reflex.so + 0x0032c000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/libSealDictDict.so + 0x00772000 /afs/cern.ch/sw/lcg/external/../app/releases/SEAL/SEAL_1_7_0/slc3_ia32_gcc323/lib/libSealDictRflx.so + 0x00430000 /afs/cern.ch/user/a/avalassi/myLCG/POOL_2_1_1/slc3_ia32_gcc323/lib/liblcg_AuthenticationService.so + 0x00f9a000 /afs/cern.ch/sw/lcg/external/XercesC/2.3.0/slc3_ia32_gcc323/lib/libxerces-c.so.23 + 0x0092b000 /afs/cern.ch/user/a/avalassi/myLCG/POOL_2_1_1/slc3_ia32_gcc323/lib/liblcg_OracleAccess.so + 0x0127f000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/slc3_ia32_gcc323/lib/libclntsh.so.10.1 + 0x079e5000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/slc3_ia32_gcc323/lib/libnnz10.so + 0x028fa000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/slc3_ia32_gcc323/lib/libociei.so + 0x003a1000 /lib/libnss_files.so.2 + 0x0016b000 /lib/libnss_dns.so.2 + 0x0045b000 /lib/libresolv.so.2 +(Start: Thu Jul 14 10:32:53 CEST 2005) +(End: Thu Jul 14 10:35:13 CEST 2005) diff --git a/RelationalCool/tests/RalDatabase/test_RalDatabase.cpp b/RelationalCool/tests/RalDatabase/test_RalDatabase.cpp new file mode 100644 index 000000000..f4f2688d6 --- /dev/null +++ b/RelationalCool/tests/RalDatabase/test_RalDatabase.cpp @@ -0,0 +1,3496 @@ +/** + + @file test_RalDatabase.cpp + + @author Sven A. Schmidt and Andrea Valassi and Marco Clemencic + + @date 2004-11-27 + + */ + +#include "src/CoralApplication.h" +#include "src/HvsPathHandlerException.h" +#include "src/RalDatabase.h" +#include "src/RalDatabaseSvc.h" +#include "src/RelationalDatabaseId.h" +#include "src/RelationalException.h" +#include "src/RelationalFolder.h" +#include "src/RelationalFolderUnsupported.h" +#include "src/RelationalFolderSet.h" +#include "src/RelationalFolderSetUnsupported.h" +#include "src/RelationalObject.h" +#include "src/RelationalObjectTable.h" +#include "src/RelationalObjectTableRow.h" +#include "src/RelationalNodeTable.h" +#include "src/RelationalSequence.h" +#include "src/RelationalSequenceMgr.h" +#include "src/RelationalTagMgr.h" +#include "src/RelationalTransaction.h" +#include "src/RelationalDatabaseTable.h" +#include "src/VersionInfo.h" +#include "src/timeToString.h" + +#include "CoolKernel/IField.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/RecordException.h" +#include "CoolKernel/RecordSpecification.h" + +#include "RelationalAccess/IRelationalService.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" +#include "RelationalAccess/ITableDataEditor.h" +#include "RelationalAccess/ITransaction.h" +//#include "RelationalAccess/SessionException.h" + +// ---- this things are needed to force a drop of the connection +//#include "src/RalDatabaseSvc.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" + +#include <string> +using std::cout; +using std::endl; +using std::string; +#include <sstream> +using std::stringstream; +#include <vector> +using std::vector; + +#include "CoolDBUnitTest.h" + +using coral::AttributeList; + +namespace cool { + +/// RalDatabase test class. + +class RalDatabaseTest : public CoolDBUnitTest { + + CPPUNIT_TEST_SUITE( RalDatabaseTest ); + + // Whenever possible the tests are ordered by increasing complexity, + // i.e. dropDatabase depends on dropAllNodes, therefore dropAllNodes + // is tested before dropDatabase. In case of failures one can then start + // to investigate from top down. + // Test execution order is determined by the order in the following + // declarations. + + CPPUNIT_TEST( test_createDatabase ); + CPPUNIT_TEST( test_openDatabase_rw ); + CPPUNIT_TEST( test_openDatabase_ro ); + + CPPUNIT_TEST( test_dbNameLength ); + CPPUNIT_TEST( test_dbNameUppercase ); + CPPUNIT_TEST( test_dbNameLettersAndNumbers ); + CPPUNIT_TEST( test_dbNameStartsWithLetter ); + // AV 04.04.05 Test no longer relevant: input dbname MUST be uppercase + //CPPUNIT_TEST( test_dbName_caseInsensitivity ); + + CPPUNIT_TEST( test_listAllNodes ); + CPPUNIT_TEST( test_listAllTables ); + + CPPUNIT_TEST( test_fetchRootNodeTableRow ); + CPPUNIT_TEST( test_insertNodeTableRow ); + CPPUNIT_TEST( test_fetchNodeTableRow ); + CPPUNIT_TEST( test_fetchNodeTableRow_nestedScope ); + + CPPUNIT_TEST( test_insertNodeTableRow_nonleaf ); + CPPUNIT_TEST( test_insertNodeTableRow_leaf ); + CPPUNIT_TEST( test_dropNode ); + CPPUNIT_TEST( test_dropAllNodes ); + CPPUNIT_TEST( test_dropDatabase ); + + CPPUNIT_TEST( test_existsFolder ); + CPPUNIT_TEST( test_existsFolderSet ); + CPPUNIT_TEST( test_existsNode ); + + CPPUNIT_TEST( test_createFolderSet ); + CPPUNIT_TEST( test_createFolderSet_alreadyExists ); + + CPPUNIT_TEST( test_createFolder_SV ); + CPPUNIT_TEST( test_createFolder_MV ); + + CPPUNIT_TEST( test_createFolder_invalidVersioningMode ); + + CPPUNIT_TEST( test_createFolder_withParents ); + CPPUNIT_TEST( test_createFolder_alreadyExists ); + + CPPUNIT_TEST( test_createFolder_invalidName ); + CPPUNIT_TEST( test_createFolderSet_invalidName ); + //CPPUNIT_TEST( test_createFolder_invalidName_old ); // no longer relevant + //CPPUNIT_TEST( test_createFolderSet_invalidName_old ); // no longer relevant + //CPPUNIT_TEST( test_createFolder_twoSimilarNames ); // no longer relevant + //CPPUNIT_TEST( test_createFolderSet_twoSimilarNames ); // no longer relevant + + CPPUNIT_TEST( test_getFolder ); + CPPUNIT_TEST( test_getFolderSet ); + + CPPUNIT_TEST( test_folderAttributes_MV ); + CPPUNIT_TEST( test_folderAttributes_SV ); + + CPPUNIT_TEST( test_createFolder_description ); + CPPUNIT_TEST( test_createFolderSet_description ); + + CPPUNIT_TEST( test_updateRows ); + CPPUNIT_TEST( test_release_0_1_0 ); + CPPUNIT_TEST( test_release_3_0_0 ); + CPPUNIT_TEST( test_allProdReleases ); + + CPPUNIT_TEST( test_useFolder_2_0_0 ); + CPPUNIT_TEST( test_dropFolder_2_0_0 ); + CPPUNIT_TEST( test_dropDatabaseWithFolder_2_0_0 ); + CPPUNIT_TEST( test_listAllTablesWithFolder_2_0_0 ); + + CPPUNIT_TEST( test_listAllTablesWithNode_1_9_9 ); + + CPPUNIT_TEST( test_useNode_2_0_9 ); + CPPUNIT_TEST( test_dropNode_2_0_9 ); + CPPUNIT_TEST( test_dropDatabaseWithNode_2_0_9 ); + CPPUNIT_TEST( test_listAllTablesWithNode_2_0_9 ); + + CPPUNIT_TEST( test_useNode_2_9_0 ); + CPPUNIT_TEST( test_dropNode_2_9_0 ); + CPPUNIT_TEST( test_dropDatabaseWithNode_2_9_0 ); + CPPUNIT_TEST( test_listAllTablesWithNode_2_9_0 ); + + CPPUNIT_TEST( test_listChannels_SV ); + CPPUNIT_TEST( test_listChannels_MV ); + + //CPPUNIT_TEST( test_listTags_SV ); // moved to RelationalFolder + //CPPUNIT_TEST( test_listTags_MV ); // moved to RelationalFolder + + CPPUNIT_TEST( test_tagInsertionTime_SV ); + + CPPUNIT_TEST( test_tagInsertionTime_MV ); + + CPPUNIT_TEST( test_tagInsertionTime_MV_nonexist ); + CPPUNIT_TEST( test_tagDescription_SV ); + CPPUNIT_TEST( test_tagDescription_MV ); + CPPUNIT_TEST( test_tagDescription_MV_nonexist ); + + CPPUNIT_TEST( test_updateNodeTableDescription ); + + // Takes long to run -- activate if needed + //CPPUNIT_TEST( test_openCursorIssue ); + + CPPUNIT_TEST( test_closeDatabase ); + + CPPUNIT_TEST( test_closeDatabase_exceptional_folder_behavior ); + CPPUNIT_TEST( test_closeDatabase_exceptional_folderset_behavior ); + + CPPUNIT_TEST( test_closeDatabase_exceptional_database_behavior ); + + CPPUNIT_TEST( test_nodeTable_lastModDate ); + + CPPUNIT_TEST( test_openDatabase_ro_updateExceptionBug30500 ); + +#ifdef COOL280 + CPPUNIT_TEST( test_manualTransaction_commit ); + CPPUNIT_TEST( test_manualTransaction_rollback ); + CPPUNIT_TEST( test_manualTransaction_tag_rollback ); + CPPUNIT_TEST( test_manualTransaction_userTag_rollback ); + CPPUNIT_TEST( test_manualTransaction_createFolder ); + CPPUNIT_TEST( test_manualTransaction_createFolderSet ); +#endif + + CPPUNIT_TEST_SUITE_END(); + +public: + + RalDatabase* ralDb; // safely cast pointer to db + + RecordSpecification payloadSpec; + + RalDatabaseTest() + : payloadSpec() { + + payloadSpec.extend("I",StorageType::Int32); + payloadSpec.extend("S",StorageType::String255); + payloadSpec.extend("X",StorageType::Float); + } + + ~RalDatabaseTest() {} + + +#ifdef COOL280 + // Tests manual transaction commit + void test_manualTransaction_commit() + { + setupDb(); + + { // create initial folder + IFolderPtr folder = ralDb->createFolder( "/A1", payloadSpec ); + + folder->storeObject( 0, 10, dummyPayload( 010), 0 ); + folder->storeObject( 10, 25, dummyPayload(1025), 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Count 1", 2u, + folder->countObjects( 0, 100, 0)); + + forceDisconnect(); + } + + { // re-open db + bool readOnlyFlag = false; + openDB(readOnlyFlag); + + ITransactionPtr t = m_db->startTransaction(); + + IFolderPtr folder = m_db->getFolder("/A1"); + folder->storeObject( 25, 30, dummyPayload( 010), 0 ); + folder->storeObject( 30, 40, dummyPayload(1025), 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Count 2", 4u, + folder->countObjects( 0, 100, 0) ); + + t->commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Count 3", 4u, + folder->countObjects( 0, 100, 0) ); + + t->rollback(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Count 4", 4u, + folder->countObjects( 0, 100, 0) ); + } + } + + + // Tests manual transaction rollback + void test_manualTransaction_rollback() + { + setupDb(); + + { // create initial folder + IFolderPtr folder = ralDb->createFolder( "/A1", payloadSpec ); + + folder->storeObject( 0, 10, dummyPayload( 010), 0 ); + folder->storeObject( 10, 25, dummyPayload(1025), 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Count 1", 2u, + folder->countObjects( 0, 100, 0)); + + forceDisconnect(); + } + + { // re-open db + bool readOnlyFlag = false; + openDB(readOnlyFlag); + + ITransactionPtr t = m_db->startTransaction(); + + IFolderPtr folder = m_db->getFolder("/A1"); + folder->storeObject( 25, 30, dummyPayload( 010), 0 ); + folder->storeObject( 30, 40, dummyPayload(1025), 0 ); + + t->rollback(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Count 2", 2u, + folder->countObjects( 0, 100, 0) ); + } + } + + + // Test createFolder behavior in manual transaction mode + void test_manualTransaction_createFolder() { + setupDb(); + + ITransactionPtr t = ralDb->startTransaction(); + + try { + ralDb->createFolder( "/A1", payloadSpec ); + CPPUNIT_FAIL("createFolder in manual transaction mode must fail"); + } catch ( RelationalException& e ) { + std::string expected = "Cannot create folder in manual transaction mode"; + CPPUNIT_ASSERT_EQUAL_MESSAGE("exception caught", + expected, std::string(e.what())); + } + } + + + // Tests createFolderSet behavior in manual transaction mode + void test_manualTransaction_createFolderSet() { + setupDb(); + + ITransactionPtr t = ralDb->startTransaction(); + + try { + ralDb->createFolderSet( "/A1" ); + CPPUNIT_FAIL("createFolderSet in manual transaction mode must fail"); + } catch ( RelationalException& e ) { + std::string expected = "Cannot create folder set in manual " + "transaction mode"; + CPPUNIT_ASSERT_EQUAL_MESSAGE("exception caught", + expected, std::string(e.what())); + } + } + + + // Tests tag rollback in manual transaction mode + void test_manualTransaction_tag_rollback() + { + setupDb(); + + { // create initial folder + IFolderPtr folder = ralDb->createFolder("/A1", + payloadSpec, + "", + FolderVersioning::MULTI_VERSION); + folder->storeObject( 0, 10, dummyPayload( 010), 0 ); + forceDisconnect(); + } + + { // re-open db with auto-transactions disabled + bool readOnlyFlag = false; + openDB(readOnlyFlag); + + ITransactionPtr t = m_db->startTransaction(); + + IFolderPtr folder = m_db->getFolder("/A1"); + + folder->tagCurrentHead("testTag"); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag exists ", + true, m_db->existsTag("testTag")); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Count", 1u, + folder->countObjects(0, 100, + 0, "testTag")); + + + t->rollback(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag rolled back", + false, m_db->existsTag("testTag") ); + } + } + + + // Tests user tag rollback in manual transaction mode + void test_manualTransaction_userTag_rollback() + { + setupDb(); + + { // create initial folder + IFolderPtr folder = ralDb->createFolder("/A1", + payloadSpec, + "", + FolderVersioning::MULTI_VERSION); + folder->storeObject( 0, 10, dummyPayload( 010), 0 ); + forceDisconnect(); + } + + { // re-open db with auto-transactions disabled + bool readOnlyFlag = false; + openDB(readOnlyFlag); + + ITransactionPtr t = m_db->startTransaction(); + + IFolderPtr folder = m_db->getFolder("/A1"); + + folder->storeObject( 35, 40, dummyPayload(2030), 0, "testTag" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE("tag exists ", + true, m_db->existsTag("testTag")); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Count", 1u, + folder->countObjects(0, 100, + 0, "testTag")); + + t->rollback(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("tag rolled back", + false, m_db->existsTag("testTag")); + } + } +#endif + + /// Tests the exception thrown when updating a readonly database (bug #30500) + void test_openDatabase_ro_updateExceptionBug30500() + { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( m_connectionString ); + IDatabasePtr db = dbSvc.createDatabase( m_connectionString ); + db->createFolder( "/a", payloadSpec ); + m_db = dbSvc.openDatabase( m_connectionString ); + CPPUNIT_ASSERT( m_db.get() != 0 ); + CPPUNIT_ASSERT( m_db->isOpen() ); + try + { + m_db->createFolder( "/b", payloadSpec ); + CPPUNIT_FAIL( "createFolder must fail" ); + } + catch ( DatabaseOpenInReadOnlyMode& ) {} + //catch ( coral::InvalidOperationInReadOnlyModeException& ) {} + catch ( std::exception& e ) + { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + try + { + Record dummyRec( payloadSpec ); + IFolderPtr folder = m_db->getFolder( "/a" ); + folder->storeObject( 0, 10, dummyRec, 0 ); + CPPUNIT_FAIL( "storeObject must fail" ); + } + catch ( DatabaseOpenInReadOnlyMode& ) {} + //catch ( coral::InvalidOperationInReadOnlyModeException& ) {} + catch ( std::exception& e ) + { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests LASTMOD_DATE updating for description changes + void test_nodeTable_lastModDate() { + setupDb(); + ralDb->createFolderSet( "/myfolder", "my desc" ); + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalTableRow row = ralDb->fetchNodeTableRow( "/myfolder" ); + CPPUNIT_ASSERT_EQUAL( row["NODE_INSTIME"].data<std::string>(), + row["LASTMOD_DATE"].data<std::string>() ); + transaction.commit(); + } + + // sleep for one second to make sure the update time change is properly + // picked up (MySQL has a 1s granularity for example) + sleep(1); + ralDb->updateNodeTableDescription( "/myfolder", "new desc" ); + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalTableRow row = ralDb->fetchNodeTableRow( "/myfolder" ); + CPPUNIT_ASSERT( row["NODE_INSTIME"].data<std::string>() + != row["LASTMOD_DATE"].data<std::string>() ); + transaction.commit(); + } + } + + + + /// Tests exceptional behavior of a closed database. + void test_closeDatabase_exceptional_database_behavior() { + setupDb(); + ralDb->closeDatabase(); + + try { + ralDb->createFolder( "/b", payloadSpec ); + CPPUNIT_FAIL( "createFolder must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->createFolderSet( "/fs" ); + CPPUNIT_FAIL( "createFolderSet must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->existsFolderSet( "/" ); + CPPUNIT_FAIL( "existsFolderSet must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->getFolderSet( "/" ); + CPPUNIT_FAIL( "getFolderSet must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->createFolder( "/f", payloadSpec ); + CPPUNIT_FAIL( "createFolder must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->existsFolder( "/f" ); + CPPUNIT_FAIL( "existsFolder must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->existsTag( "A" ); + CPPUNIT_FAIL( "existsTag must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->tagNameScope( "A" ); + CPPUNIT_FAIL( "tagScope must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->taggedNodes( "A" ); + CPPUNIT_FAIL( "taggedNodes must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->getFolder( "/f" ); + CPPUNIT_FAIL( "getFolder must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->dropNode( "/" ); + CPPUNIT_FAIL( "dropNode must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->listAllNodes(); + CPPUNIT_FAIL( "listAllNodes must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + ralDb->listAllTables(); + CPPUNIT_FAIL( "listAllTables must fail" ); + } catch ( DatabaseNotOpen& ) { } + + } + + + /// Tests exceptional behavior of folderset with a closed database. + void test_closeDatabase_exceptional_folderset_behavior() { + setupDb(); + IFolderSetPtr root = ralDb->getFolderSet( "/" ); + ralDb->closeDatabase(); + + try { + root->listFolders(); + CPPUNIT_FAIL( "listFolders must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + root->listFolderSets(); + CPPUNIT_FAIL( "listFolderSets must fail" ); + } catch ( DatabaseNotOpen& ) { } + } + + + /// Tests exceptional behavior of folder methods with a closed database. + void test_closeDatabase_exceptional_folder_behavior() { + try { + setupDb(); + IFolderPtr folder = ralDb->createFolder + ( "/b", payloadSpec, "desc", FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, 10, dummyPayload(0), 0 ); + ralDb->closeDatabase(); + + try { + folder->storeObject( 10, 20, dummyPayload(0), 0 ); + CPPUNIT_FAIL( "storeObject must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->setupStorageBuffer(); + folder->storeObject( 10, 20, dummyPayload(0), 0 ); + folder->flushStorageBuffer(); + CPPUNIT_FAIL( "bulk insertion must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->findObject( 5, 0 ); + CPPUNIT_FAIL( "findObject must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0 ); + CPPUNIT_FAIL( "browseObjects 1 must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->findObjects( 0, ChannelSelection::all() ); + CPPUNIT_FAIL( "findObjects 2 must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all() ); + CPPUNIT_FAIL( "browseObjects 3 must fail" ); + } catch ( DatabaseNotOpen& ) { } + + /* + try { + folder->fetchObjects( ValidityKeyMin, ValidityKeyMax ); + CPPUNIT_FAIL( "fetchObjects 1 must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->fetchObjects( 0, ChannelSelection::all() ); + CPPUNIT_FAIL( "fetchObjects 2 must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->fetchObjects( ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all() ); + CPPUNIT_FAIL( "fetchObjects 3 must fail" ); + } catch ( DatabaseNotOpen& ) { } + */ + + try { + folder->countObjects( ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all() ); + CPPUNIT_FAIL( "objectCount must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->listChannels(); + CPPUNIT_FAIL( "listChannels must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->listChannelsWithNames(); + CPPUNIT_FAIL( "listChannelsWithNames must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->tagCurrentHead( "A" ); + CPPUNIT_FAIL( "tagCurrentHead must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->tagHeadAsOfDate( Time(), "A" ); + CPPUNIT_FAIL( "tagHeadAsOfDate must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->insertionTimeOfLastObjectInTag( "A" ); + CPPUNIT_FAIL( "insertionTimeOfLastObjectInTag must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->deleteTag( "A" ); + CPPUNIT_FAIL( "deleteTag must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->setDescription( "" ); + CPPUNIT_FAIL( "setDescription must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->listTags(); + CPPUNIT_FAIL( "listTags must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->tagInsertionTime( "A" ); + CPPUNIT_FAIL( "tagInsertionTime must fail" ); + } catch ( DatabaseNotOpen& ) { } + + try { + folder->tagDescription( "A" ); + CPPUNIT_FAIL( "tagDescription must fail" ); + } catch ( DatabaseNotOpen& ) { } + } catch ( std::exception& e ) { + cout << "Exception caught: " << e.what() << endl; + throw; + } + } + + + /// Tests closeDatabase and reopening. + void test_closeDatabase() { + setupDb(); + CPPUNIT_ASSERT_MESSAGE( "before disconnect", ralDb->isOpen() ); + ralDb->closeDatabase(); + CPPUNIT_ASSERT_MESSAGE( "after disconnect", ! ralDb->isOpen() ); + ralDb->openDatabase(); + CPPUNIT_ASSERT_MESSAGE( "after reconnect", ralDb->isOpen() ); + // make sure writing works + ralDb->createFolder( "/a", payloadSpec ); + } + + + /// Tests the bug report from David Front about cursors not being closed + void test_openCursorIssue() { + try { + setupDb(); + ralDb->setUseTimeout( false ); + int nFolders = 300; + for ( int i = 0; i < nFolders; ++i ) { + stringstream s; s << "/f_" << i; + cout << "Creating folder '" << s.str() << "'" << endl; + ralDb->createFolder( s.str(), payloadSpec ); + } + vector<string> nodes = ralDb->listAllNodes(); + CPPUNIT_ASSERT_EQUAL( nFolders +1, (int)nodes.size() ); + for ( int i = 0; i < nFolders; ++i ) { + stringstream s; s << "/f_" << i; + cout << "Writing into '" << s.str() << "'" << endl; + IFolderPtr f = ralDb->getFolder( s.str() ); + f->setupStorageBuffer(); + for ( int j = 0; j < 10; ++j ) + f->storeObject( j, ValidityKeyMax, dummyPayload( j ), 0 ); + f->flushStorageBuffer(); + //sleep(1); + } + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests updateNodeTableDescription + void test_updateNodeTableDescription() { + setupDb(); + ralDb->createFolderSet( "/myfolder", "my desc" ); + ralDb->updateNodeTableDescription( "/myfolder", "new desc" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalTableRow row = ralDb->fetchNodeTableRow( "/myfolder" ); + transaction.commit(); + CPPUNIT_ASSERT_EQUAL + ( string("new desc"), row["NODE_DESCRIPTION"].data<std::string>() ); + } + + + /// Tests that tagDescription for MV folders for a nonexisting tag + /// throws a TagNotFound exception + void test_tagDescription_MV_nonexist() { + setupDb(); + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), 0 ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + CPPUNIT_ASSERT_THROW( ralDb->tagMgr().tagDescription( relfolder, "A" ), + TagNotFound ); + } + + + /// Tests tagDescription for MV folders + void test_tagDescription_MV() { + setupDb(); + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "A", "desc A" ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + std::string desc = ralDb->tagMgr().tagDescription( relfolder, "A" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag desc", std::string("desc A"), desc ); + } + + + /// Tests that tagDescription for SV folders throws an exception + void test_tagDescription_SV() { + setupDb(); + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + CPPUNIT_ASSERT_THROW( ralDb->tagMgr().tagDescription( relfolder, "any tag" ), + TagNotFound ); + } + + + /// Tests that tagInsertionTime for MV folders for a nonexisting tag + /// throws a TagNotFound exception + void test_tagInsertionTime_MV_nonexist() { + setupDb(); + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), 0 ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + CPPUNIT_ASSERT_THROW( ralDb->tagMgr().tagInsertionTime( relfolder, "A" ), + TagNotFound ); + } + + + /// Tests tagInsertionTime for MV folders + void test_tagInsertionTime_MV() { + try { + setupDb(); + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), 0 ); + + // Create a temporary sequence to get the server SYSDATE before insertion + Time before; + std::string tmpSeqName = string( m_coolDBName + "_TMP_CLOCK" ); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + if ( ralDb->queryMgr().sequenceMgr().existsSequence( tmpSeqName ) ) + ralDb->queryMgr().sequenceMgr().dropSequence( tmpSeqName ); + boost::shared_ptr<RelationalSequence> tmpSeq = + ralDb->queryMgr().sequenceMgr().createSequence( tmpSeqName ); + tmpSeq->nextVal(); + before = stringToTime( tmpSeq->currDate() ); + transaction.commit(); + } + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + // (if test checks for strict < or >; not needed if checks for <= or >=) + sleep(1); + + // Tag the folder + folder->tagCurrentHead( "A" ); + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + // (if test checks for strict < or >; not needed if checks for <= or >=) + sleep(1); + + // Get the server SYSDATE after insertion + Time after; + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> tmpSeq = + ralDb->queryMgr().sequenceMgr().getSequence( tmpSeqName ); + tmpSeq->nextVal(); + after = stringToTime( tmpSeq->currDate() ); + transaction.commit(); + } + + // Cleanup - drop the temporary sequence + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + ralDb->queryMgr().sequenceMgr().dropSequence( tmpSeqName ); + transaction.commit(); + } + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + //std::cout << "*** Windows will throw UNKNOWN exception?" << std::endl; + Time tagTime = + ralDb->tagMgr().tagInsertionTime( relfolder, "A" ); + //std::cout << "*** Windows has thrown UNKNOWN exception?" << std::endl; + CPPUNIT_ASSERT_MESSAGE( "before < tagTime", before < tagTime ); + CPPUNIT_ASSERT_MESSAGE( "tagTime < after", tagTime < after ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } catch ( ... ) { + std::cout << "UNKNOWN Exception caught!" << std::endl; + throw; + } + } + + + /// Tests that tagInsertionTime for SV folders throws an exception + void test_tagInsertionTime_SV() { + setupDb(); + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + CPPUNIT_ASSERT_THROW(ralDb->tagMgr() + .tagInsertionTime( relfolder, "any tag" ), + TagNotFound); + } + + + /// Tests listChannels for MV folders + void test_listChannels_MV() { + setupDb(); + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + ChannelId channel = 1; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 3; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 5; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 3u, (unsigned int)channels.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", (ChannelId)1, channels[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", (ChannelId)3, channels[1] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", (ChannelId)5, channels[2] ); + } + + + /// Tests listChannels for SV folders + void test_listChannels_SV() { + setupDb(); + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + ChannelId channel = 1; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 3; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 5; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 3u, (unsigned int)channels.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", (ChannelId)1, channels[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", (ChannelId)3, channels[1] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", (ChannelId)5, channels[2] ); + } + + + /// Updates the release number in the RELEASE column of the main table + void updateRelease( const std::string& releaseNumber ) + { + RalSessionMgr ralSessMgr( ppConnectionSvc(), m_connectionString, false ); + ralSessMgr.session().transaction().start(); + coral::ISchema& schema = ralSessMgr.session().nominalSchema(); + std::string mainTable = RelationalDatabaseTable::tableName( m_coolDBName ); + coral::ITable& table = schema.tableHandle( mainTable ); + coral::AttributeList updateData; + updateData.extend( "newRelease", "string" ); + updateData.extend( "releaseColumn", "string" ); + updateData["newRelease"].setValue( releaseNumber ); + updateData["releaseColumn"].setValue( string("RELEASE") ); + std::string setClause = "DB_ATTRIBUTE_VALUE = :newRelease"; + std::string whereClause = "DB_ATTRIBUTE_NAME = :releaseColumn"; + int updatedRows = + table.dataEditor().updateRows( setClause, whereClause, updateData ); + ralSessMgr.session().transaction().commit(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string( "release update row count (new release: " ) + + releaseNumber + ")", 1, updatedRows ); + ralSessMgr.disconnect(); + //forceDisconnect(); // NO! This will make ralDb unusable (segfault...)! + } + + + /// Updates the schema version in the SCHEMA_VERSION column of the main table + void updateSchemaVersion( const std::string& schemaVersion ) + { + RalSessionMgr ralSessMgr( ppConnectionSvc(), m_connectionString, false ); + ralSessMgr.session().transaction().start(); + coral::ISchema& schema = ralSessMgr.session().nominalSchema(); + std::string mainTable = RelationalDatabaseTable::tableName( m_coolDBName ); + coral::ITable& table = schema.tableHandle( mainTable ); + coral::AttributeList updateData; + updateData.extend( "newSchemaVersion", "string" ); + updateData.extend( "schemaVersionColumn", "string" ); + updateData["newSchemaVersion"].setValue( schemaVersion ); + updateData["schemaVersionColumn"].setValue( string("SCHEMA_VERSION") ); + std::string setClause = "DB_ATTRIBUTE_VALUE = :newSchemaVersion"; + std::string whereClause = "DB_ATTRIBUTE_NAME = :schemaVersionColumn"; + int updatedRows = + table.dataEditor().updateRows + ( setClause, whereClause, updateData ); + ralSessMgr.session().transaction().commit(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string( "schema version update row count (new schema: " ) + + schemaVersion + ")", 1, updatedRows ); + ralSessMgr.disconnect(); + //forceDisconnect(); // NO! This will make ralDb unusable (segfault...)! + } + + + /// Updates the SCHEMA_VERSION column of the node table for the given node + void updateNodeSchemaVersion( const std::string& fullPath, + const std::string& schemaVersion ) + { + RalSessionMgr ralSessMgr( ppConnectionSvc(), m_connectionString, false ); + ralSessMgr.session().transaction().start(); + coral::ISchema& schema = ralSessMgr.session().nominalSchema(); + coral::ITable& table = schema.tableHandle( ralDb->nodeTableName() ); + coral::AttributeList updateData; + updateData.extend( "newSchemaVersion", "string" ); + updateData.extend( "fullPath", "string" ); + updateData["newSchemaVersion"].setValue( schemaVersion ); + updateData["fullPath"].setValue( fullPath ); + std::string setClause = RelationalNodeTable::columnNames::nodeSchemaVersion + + " = :newSchemaVersion"; + std::string whereClause = RelationalNodeTable::columnNames::nodeFullPath + + " = :fullPath"; + int updatedRows = table.dataEditor().updateRows + ( setClause, whereClause, updateData ); + ralSessMgr.session().transaction().commit(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string( "node schema version update row count (new schema: " ) + + schemaVersion + ")", 1, updatedRows ); + ralSessMgr.disconnect(); + //forceDisconnect(); // NO! This will make ralDb unusable (segfault...)! + } + + + /// Function to test a release version that should _NOT_ be opened. + void checkReleaseFAIL_NoSchemaEvolution(const std::string& rel) { + + createDB(); + updateRelease( rel ); + try { + + openDB(); + + forceDisconnect(); + updateRelease( VersionInfo::release ); + + CPPUNIT_ASSERT_MESSAGE( "exception expected for "+rel, false ); + + } catch ( RelationalException& e ) { + + forceDisconnect(); + updateRelease( VersionInfo::release ); + + std::string expected = "IncompatibleReleaseNumber exception. " + "Release number mismatch - SCHEMA EVOLUTION NOT POSSIBLE: " + "database with OLDER release number " + rel + + " (older than 1.2.0)" + " cannot be opened using CURRENT client release number " + + std::string(VersionInfo::release); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "exception caught", + expected, string( e.what() ) ); + + } catch ( ... ) { + + forceDisconnect(); + updateRelease( VersionInfo::release ); + + throw; + } + } + + /// Function to test a release version that should _NOT_ be opened. + void checkReleaseFAIL_SchemaEvolution(const std::string& rel) { + + createDB(); + updateRelease( rel ); + try { + + openDB(); + + forceDisconnect(); + updateRelease( VersionInfo::release ); + + CPPUNIT_ASSERT_MESSAGE( "exception expected for "+rel, false ); + + } catch ( RelationalException& e ) { + + forceDisconnect(); + updateRelease( VersionInfo::release ); + + std::string expected = "IncompatibleReleaseNumber exception. " + "Release number mismatch - SCHEMA EVOLUTION REQUIRED: " + "database with OLDER release number " + rel + + " cannot be opened using CURRENT client release number " + + std::string(VersionInfo::release); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "exception caught", + expected, string( e.what() ) ); + + } catch ( ... ) { + + forceDisconnect(); + updateRelease( VersionInfo::release ); + + throw; + } + } + + /// Function to test a release version that should be opened. + void checkReleaseOK(const std::string& rel) { + + createDB(); + updateRelease( rel ); + try { + + openDB(); + CPPUNIT_ASSERT( m_db.get() != 0 ); + CPPUNIT_ASSERT( m_db->isOpen() ); + + } catch ( RelationalException& ) { + + forceDisconnect(); + updateRelease( VersionInfo::release ); + + CPPUNIT_ASSERT_MESSAGE( "could not open version "+rel, false ); + + } catch ( ... ) { + + forceDisconnect(); + updateRelease( VersionInfo::release ); + + throw; + } + + forceDisconnect(); + updateRelease( VersionInfo::release ); + } + + /// Cross-check the present release against all production releases + /// REMEMBER TO UPDATE THIS AT EVERY RELEASE! This includes a check against + /// the current release (which will become a former release when the next + /// one is out, and will fail the test if you forget to update it!) + void test_allProdReleases() + { + + std::vector<std::string> not_openable_no_schema_evolution; + not_openable_no_schema_evolution.push_back( "1.0.0" ); + not_openable_no_schema_evolution.push_back( "1.0.1" ); + not_openable_no_schema_evolution.push_back( "1.0.2" ); + not_openable_no_schema_evolution.push_back( "1.1.0" ); + + std::vector<std::string> not_openable_schema_evolution; + not_openable_schema_evolution.push_back( "1.2.0" ); + not_openable_schema_evolution.push_back( "1.2.1" ); + not_openable_schema_evolution.push_back( "1.2.2" ); + not_openable_schema_evolution.push_back( "1.2.3" ); + not_openable_schema_evolution.push_back( "1.2.4" ); + not_openable_schema_evolution.push_back( "1.2.5" ); + not_openable_schema_evolution.push_back( "1.2.6" ); + not_openable_schema_evolution.push_back( "1.2.7" ); + not_openable_schema_evolution.push_back( "1.2.8" ); + not_openable_schema_evolution.push_back( "1.2.9" ); + not_openable_schema_evolution.push_back( "1.3.0" ); + not_openable_schema_evolution.push_back( "1.3.1" ); + not_openable_schema_evolution.push_back( "1.3.2" ); + not_openable_schema_evolution.push_back( "1.3.3" ); + not_openable_schema_evolution.push_back( "1.3.4" ); + + std::vector<std::string> openable; // current can (needs not) be included + openable.push_back( "2.0.0" ); + openable.push_back( "2.1.0" ); + openable.push_back( "2.1.1" ); + openable.push_back( "2.2.0" ); + openable.push_back( "2.2.1" ); + openable.push_back( "2.2.2" ); + openable.push_back( "2.3.0" ); + openable.push_back( "2.3.1" ); + openable.push_back( "2.4.0" ); + openable.push_back( "2.5.0" ); + openable.push_back( "2.6.0" ); + openable.push_back( "2.7.0" ); + + // Check for failure - too old even for schema evolution + std::vector<std::string> ::iterator rel; + for ( rel = not_openable_no_schema_evolution.begin(); + rel != not_openable_no_schema_evolution.end(); + ++rel ) + { + checkReleaseFAIL_NoSchemaEvolution( *rel ); + } + + // Check for failure - need schema evolution + for ( rel = not_openable_schema_evolution.begin(); + rel != not_openable_schema_evolution.end(); + ++rel ) + { + checkReleaseFAIL_SchemaEvolution( *rel ); + } + + // Check for success - forward compatible + for( rel = openable.begin(); rel != openable.end(); ++rel ){ + checkReleaseOK( *rel ); + } + + // Current Version - can be opened + createDB(); + try { + openDB(); + CPPUNIT_ASSERT( m_db.get() != 0 ); + CPPUNIT_ASSERT( m_db->isOpen() ); + } catch ( ... ) { + forceDisconnect(); + throw; + } + forceDisconnect(); + + } + + + /// This is actually a test of the CORAL updateRows method (sr #101074) + void test_updateRows() { + createDB(); + // The following three calls update rows without changing any column + // values: all three calls fail on MySQL if sr #101074 is not fixed, + // because the return value of updateRows is 0 instead of 1 + updateRelease( VersionInfo::release ); + updateSchemaVersion( VersionInfo::schemaVersion ); + openDB(false); + ralDb = dynamic_cast<RalDatabase*>(m_db.get()); + updateNodeSchemaVersion( "/", VersionInfo::schemaVersion ); + } + + + /// Tests that an exception is thrown when the current API is used to + /// access a release 0.1.0 database (the object_id ordering change was + /// data incompatible -- 1.0.0 and later cannot reliably read 0.1.0 data) + void test_release_0_1_0() { + checkReleaseFAIL_NoSchemaEvolution("0.1.0"); + } + + + /// Tests what happens when the current API is used + /// to access a newer release 3.0.0 database + void test_release_3_0_0() + { + std::string newRel("3.0.0"); + std::string newSch("3.0.0"); + std::string oldSch("1.0.0"); + createDB(); + updateRelease( newRel ); + try { + + // 1. Newer release, same schema - it can be opened + openDB(); + + // 2. Newer release, newer schema - it cannot be opened + try { + updateSchemaVersion( newSch ); + openDB(); + CPPUNIT_FAIL( "Exception expected for newer schema " + newSch ); + } + catch ( IncompatibleReleaseNumber& e ) { + std::stringstream s; + s << "IncompatibleReleaseNumber exception. " + << "Release number and schema version mismatch" + << " - SCHEMA NOT BACKWARD COMPATIBLE: " + << "database with NEWER release number " << newRel + << " and NEWER schema version " << newSch + << " cannot be opened using CURRENT client release number " + << VersionInfo::release + << " (CURRENT schema version " << VersionInfo::schemaVersion << ")"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", s.str(), std::string( e.what() ) ); + } + + // 3. Newer release, older schema - panic! + try { + updateSchemaVersion( oldSch ); + openDB(); + CPPUNIT_FAIL( "Exception expected for older schema " + newSch ); + } + catch ( IncompatibleReleaseNumber& e ) { + std::stringstream s; + s << "IncompatibleReleaseNumber exception. " + << "PANIC! Release number and schema version mismatch: " + << "database with NEWER release number " << newRel + << " than CURRENT client release number " << VersionInfo::release + << " has OLDER schema version " << oldSch + << " (CURRENT schema version " << VersionInfo::schemaVersion << ")"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", s.str(), std::string( e.what() ) ); + } + + forceDisconnect(); + updateRelease( VersionInfo::release ); + updateSchemaVersion( VersionInfo::schemaVersion ); + + } catch ( ... ) { + forceDisconnect(); + updateRelease( VersionInfo::release ); + updateSchemaVersion( VersionInfo::schemaVersion ); + throw; + } + + } + + + /// Tests what happens when the current API is used + /// to access a folder with obsolete schema version 2.0.0 + void test_useFolder_2_0_0() + { + setupDb(); + ralDb->createFolderSet( "/my" ); + ralDb->createFolder + ( "/my/folder", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + std::string newSch("2.0.0"); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + + /// 1. Test folder using its original schema version + IFolderPtr folder; + folder = ralDb->getFolder( "/my/folder" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folder name", std::string( "/my/folder" ), folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folder schema", oldFoldSch, folder->folderAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folder->folderSpecification(); // Should not throw + + /// 2. Test folder using an obsolete schema version + updateNodeSchemaVersion( "/my/folder", newSch ); + folder = ralDb->getFolder( "/my/folder" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folder name", std::string( "/my/folder" ), folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folder schema", newSch, folder->folderAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + try { + CPPUNIT_ASSERT_THROW + ( folder->folderSpecification(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->payloadSpecification(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->versioningMode(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->setupStorageBuffer(), UnsupportedFolderSchema ); + Record dummyRec( payloadSpec ); + CPPUNIT_ASSERT_THROW + ( folder->storeObject( 0, 10, dummyRec, 0 ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->flushStorageBuffer(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->findObject( 0, 0 ), UnsupportedFolderSchema ); + ChannelSelection dummyChSel( 0 ); + CPPUNIT_ASSERT_THROW + ( folder->findObjects( 0, dummyChSel ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->setPrefetchAll( true ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->browseObjects( 0, 10, dummyChSel ), + UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->countObjects( 0, 10, dummyChSel ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->renamePayload( "I", "J" ), UnsupportedFolderSchema ); + RecordSpecification extSpec; + extSpec.extend("I",StorageType::Int32); + Record extRec( extSpec ); + CPPUNIT_ASSERT_THROW + ( folder->extendPayloadSpecification( extRec ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->tagCurrentHead( "a" ), UnsupportedFolderSchema ); + Time now; + CPPUNIT_ASSERT_THROW + ( folder->insertionTimeOfLastObjectInTag("a"), + UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->deleteTag( "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->tagHeadAsOfDate( now, "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->existsUserTag( "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->listChannels(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->listChannelsWithNames(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->createChannel( 1, "b" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->setChannelName( 1, "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->channelName( 1 ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->channelId( "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->existsChannel( 0 ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->existsChannel( "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->setChannelDescription( 1, "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->channelDescription( 1 ), UnsupportedFolderSchema ); + } catch (...) { + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + throw; + } + + /// 3. Test folder using its original schema version again + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + folder = ralDb->getFolder( "/my/folder" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folder name", std::string( "/my/folder" ), folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folder schema", oldFoldSch, folder->folderAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folder->folderSpecification(); // Should not throw + + } + + + /// Tests what happens when the current API is used + /// to drop a folder with obsolete schema version 2.0.0 + void test_dropFolder_2_0_0() + { + setupDb(); + ralDb->createFolderSet( "/my" ); + ralDb->createFolder( "/my/folder", payloadSpec ); + std::string newSch("2.0.0"); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + updateNodeSchemaVersion( "/my/folder", newSch ); + try { + CPPUNIT_ASSERT_THROW + ( ralDb->dropNode( "/my/folder" ), Exception ); + } catch (...) { + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + throw; + } + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + } + + + /// Tests listAllTables if there is an obsolete folder version 2.0.0 + void test_listAllTablesWithFolder_2_0_0() + { + // Create folders + setupDb(); + ralDb->createFolderSet( "/f1" ); + ralDb->createFolder( "/f1/folderA", payloadSpec ); + ralDb->createFolder( "/f1/folderB", payloadSpec ); + // Prepare list of expected tables + std::vector<std::string> suffixes; + suffixes.push_back( "_DB_ATTRIBUTES" ); + suffixes.push_back( "_F0000_TAGS_SEQ" ); + suffixes.push_back( "_F0001_TAGS_SEQ" ); + suffixes.push_back( "_F0002_CHANNELS" ); + suffixes.push_back( "_F0002_IOVS" ); + suffixes.push_back( "_F0002_IOVS_SEQ" ); + suffixes.push_back( "_F0003_CHANNELS" ); + suffixes.push_back( "_F0003_IOVS" ); + suffixes.push_back( "_F0003_IOVS_SEQ" ); + suffixes.push_back( "_NODES" ); + suffixes.push_back( "_NODES_SEQ" ); + suffixes.push_back( "_TAG2TAG" ); + suffixes.push_back( "_TAG2TAG_SEQ" ); + suffixes.push_back( "_TAGS" ); + // Change a folder schema to 2.0.0 + std::string newSch("2.0.0"); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + updateNodeSchemaVersion( "/f1/folderA", newSch ); + try { + std::vector<string> tables = ralDb->listAllTables(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tables count", (size_t)14, tables.size() ); + std::vector<std::string>::const_iterator suffix; + for ( suffix = suffixes.begin(); suffix != suffixes.end(); suffix++ ) + { + std::string table; + table = m_coolDBName + *suffix; + CPPUNIT_ASSERT_MESSAGE + ( table, + find( tables.begin(), tables.end(), table ) != tables.end() ); + } + } catch (...) { + updateNodeSchemaVersion( "/f1/folderA", oldFoldSch ); + throw; + } + updateNodeSchemaVersion( "/f1/folderA", oldFoldSch ); + } + + + /// Tests listAllTables if there are obsolete node versions 1.9.9 + void test_listAllTablesWithNode_1_9_9() + { + // Create folders + setupDb(); + ralDb->createFolderSet( "/f1" ); + ralDb->createFolder( "/f1/folderA", payloadSpec ); + ralDb->createFolder( "/f1/folderB", payloadSpec ); + // Change a folder set schema to 1.9.9 + { + std::string newSch("1.9.9"); + std::string oldFsetSch( RelationalFolderSet::folderSetSchemaVersion() ); + updateNodeSchemaVersion( "/f1", newSch ); + try { + CPPUNIT_ASSERT_THROW + ( ralDb->listAllTables(), PanicException ); + } catch (...) { + updateNodeSchemaVersion( "/f1", oldFsetSch ); + throw; + } + updateNodeSchemaVersion( "/f1", oldFsetSch ); + } + // Change a folder schema to 1.9.9 + { + std::string newSch("1.9.9"); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + updateNodeSchemaVersion( "/f1/folderA", newSch ); + try { + CPPUNIT_ASSERT_THROW + ( ralDb->listAllTables(), PanicException ); + } catch (...) { + updateNodeSchemaVersion( "/f1/folderA", oldFoldSch ); + throw; + } + updateNodeSchemaVersion( "/f1/folderA", oldFoldSch ); + } + } + + + /// Tests listAllTables if there are new node versions 2.0.9 + void test_listAllTablesWithNode_2_0_9() + { + // Create folders + setupDb(); + ralDb->createFolderSet( "/f1" ); + ralDb->createFolder( "/f1/folderA", payloadSpec ); + ralDb->createFolder( "/f1/folderB", payloadSpec ); + // Prepare list of expected tables + std::vector<std::string> suffixes; + suffixes.push_back( "_DB_ATTRIBUTES" ); + suffixes.push_back( "_F0000_TAGS_SEQ" ); + suffixes.push_back( "_F0001_TAGS_SEQ" ); + suffixes.push_back( "_F0002_CHANNELS" ); + suffixes.push_back( "_F0002_IOVS" ); + suffixes.push_back( "_F0002_IOVS_SEQ" ); + suffixes.push_back( "_F0003_CHANNELS" ); + suffixes.push_back( "_F0003_IOVS" ); + suffixes.push_back( "_F0003_IOVS_SEQ" ); + suffixes.push_back( "_NODES" ); + suffixes.push_back( "_NODES_SEQ" ); + suffixes.push_back( "_TAG2TAG" ); + suffixes.push_back( "_TAG2TAG_SEQ" ); + suffixes.push_back( "_TAGS" ); + // Change a folder schema and a folder set to 2.0.9 + std::string newSch("2.0.9"); + std::string oldFsetSch( RelationalFolderSet::folderSetSchemaVersion() ); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + updateNodeSchemaVersion( "/f1", newSch ); + updateNodeSchemaVersion( "/f1/folderA", newSch ); + try { + std::vector<string> tables = ralDb->listAllTables(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tables count", (size_t)14, tables.size() ); + std::vector<std::string>::const_iterator suffix; + for ( suffix = suffixes.begin(); suffix != suffixes.end(); suffix++ ) + { + std::string table; + table = m_coolDBName + *suffix; + CPPUNIT_ASSERT_MESSAGE + ( table, + find( tables.begin(), tables.end(), table ) != tables.end() ); + } + } catch (...) { + updateNodeSchemaVersion( "/f1", oldFsetSch ); + updateNodeSchemaVersion( "/f1/folderA", oldFoldSch ); + throw; + } + updateNodeSchemaVersion( "/f1", oldFsetSch ); + updateNodeSchemaVersion( "/f1/folderA", oldFoldSch ); + } + + + /// Tests listAllTables if there are new node versions 2.9.0 + void test_listAllTablesWithNode_2_9_0() + { + // Create folders + setupDb(); + ralDb->createFolderSet( "/f1" ); + ralDb->createFolder( "/f1/folderA", payloadSpec ); + ralDb->createFolder( "/f1/folderB", payloadSpec ); + // Change a folder set schema to 2.9.0 + { + std::string newSch("2.9.0"); + std::string oldFsetSch( RelationalFolderSet::folderSetSchemaVersion() ); + updateNodeSchemaVersion( "/f1", newSch ); + try { + //CPPUNIT_ASSERT_THROW + // ( ralDb->listAllTables(), UnsupportedFolderSetSchema ); + } catch (...) { + updateNodeSchemaVersion( "/f1", oldFsetSch ); + throw; + } + updateNodeSchemaVersion( "/f1", oldFsetSch ); + } + // Change a folder schema to 2.9.0 + { + std::string newSch("2.9.0"); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + updateNodeSchemaVersion( "/f1/folderA", newSch ); + try { + CPPUNIT_ASSERT_THROW + ( ralDb->listAllTables(), UnsupportedFolderSchema ); + } catch (...) { + updateNodeSchemaVersion( "/f1/folderA", oldFoldSch ); + throw; + } + updateNodeSchemaVersion( "/f1/folderA", oldFoldSch ); + } + } + + + /// Tests what happens when the current API is used to drop a database + /// containing a folder with obsolete schema version 2.0.0 + void test_dropDatabaseWithFolder_2_0_0() + { + setupDb(); + ralDb->createFolderSet( "/my" ); + ralDb->createFolder( "/my/folder1", payloadSpec ); + ralDb->createFolder( "/my/folder2", payloadSpec ); + ralDb->createFolder( "/my/folder3", payloadSpec ); + std::string newSch("2.0.0"); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + updateNodeSchemaVersion( "/my/folder2", newSch ); + try { + CPPUNIT_ASSERT_THROW + ( ralDb->dropDatabase(), Exception ); + IFolderSetPtr folderset = ralDb->getFolderSet( "/my" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + IFolderPtr folder; + folder = ralDb->getFolder( "/my/folder1" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + folder = ralDb->getFolder( "/my/folder2" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + folder = ralDb->getFolder( "/my/folder3" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + } catch (...) { + updateNodeSchemaVersion( "/my/folder2", oldFoldSch ); + throw; + } + updateNodeSchemaVersion( "/my/folder2", oldFoldSch ); + } + + + /// Tests what happens when the current API is used + /// to access a node with newer schema version 2.0.9 + void test_useNode_2_0_9() + { + setupDb(); + ralDb->createFolderSet( "/my" ); + ralDb->createFolder + ( "/my/folder", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + std::string newSch("2.0.9"); + //std::string newSch("2.9.0"); // test error recovery in catch(...) clause + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + std::string oldFsetSch( RelationalFolderSet::folderSetSchemaVersion() ); + + /// 1. Test folderset and folder using their original schema version + IFolderSetPtr folderset; + IFolderPtr folder; + folderset = ralDb->getFolderSet( "/my" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folderset name", std::string( "/my" ), folderset->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folderset schema", oldFsetSch, folderset->folderSetAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folderset->listFolders(); // Should not throw + folder = ralDb->getFolder( "/my/folder" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folder name", std::string( "/my/folder" ), folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folder schema", oldFoldSch, folder->folderAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folder->folderSpecification(); // Should not throw + + /// 2. Test folderset and folder using a newer schema version + updateNodeSchemaVersion( "/my", newSch ); + updateNodeSchemaVersion( "/my/folder", newSch ); + folderset = ralDb->getFolderSet( "/my" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folderset name", std::string( "/my" ), folderset->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folderset schema", newSch, folderset->folderSetAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folder = ralDb->getFolder( "/my/folder" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folder name", std::string( "/my/folder" ), folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folder schema", newSch, folder->folderAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + // None of the following methods should throw + try { + folderset->listFolders(); + folderset->listFolderSets(); + folder->folderSpecification(); + folder->payloadSpecification(); + folder->versioningMode(); + folder->setupStorageBuffer(); + Record dummyRec( payloadSpec ); + folder->storeObject( 0, 10, dummyRec, 0 ); + folder->flushStorageBuffer(); + + IObjectPtr obj = folder->findObject( 0, 0 ); + // We cannot use the current time to tag if the client + // and server are not synchronized (see bug #24481 for details) + Time insertion_time = obj->insertionTime(); + obj.reset(); + + ChannelSelection dummyChSel( 0 ); + folder->findObjects( 0, dummyChSel ); + folder->setPrefetchAll( true ); + folder->browseObjects( 0, 10, dummyChSel ); + folder->countObjects( 0, 10, dummyChSel ); + folder->renamePayload( "I", "J" ); + RecordSpecification extSpec; + extSpec.extend("I",StorageType::Int32); + Record extRec( extSpec ); + folder->extendPayloadSpecification( extRec ); + sleep(1); // Patch for the ORA-01466 problem: sleep one second + folder->tagCurrentHead( "a" ); + + // We cannot use the current time if the client and server are not + // synchronized (see bug #24481 for details) + // Time now; + + folder->insertionTimeOfLastObjectInTag("a"); + folder->deleteTag( "a" ); + + // folder->tagHeadAsOfDate( now, "a" ); + folder->tagHeadAsOfDate( insertion_time, "a" ); + + folder->existsUserTag( "a" ); + folder->listChannels(); + folder->listChannelsWithNames(); + folder->createChannel( 1, "b" ); + folder->setChannelName( 1, "a" ); + folder->channelName( 1 ); + folder->channelId( "a" ); + folder->existsChannel( 0 ); + folder->existsChannel( "a" ); + folder->setChannelDescription( 1, "a" ); + folder->channelDescription( 1 ); + } catch (...) { + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + updateNodeSchemaVersion( "/my", oldFsetSch ); + throw; + } + + /// 3. Test folderset and folder using their original schema version again + updateNodeSchemaVersion( "/my", oldFsetSch ); + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + folderset = ralDb->getFolderSet( "/my" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folderset name", std::string( "/my" ), folderset->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folderset schema", oldFsetSch, folderset->folderSetAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folderset->listFolders(); // Should not throw + folder = ralDb->getFolder( "/my/folder" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folder name", std::string( "/my/folder" ), folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folder schema", oldFoldSch, folder->folderAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folder->folderSpecification(); // Should not throw + + } + + + /// Tests what happens when the current API is used + /// to drop a node with newer schema version 2.0.9 + void test_dropNode_2_0_9() + { + setupDb(); + ralDb->createFolderSet( "/my" ); + ralDb->createFolder( "/my/folder", payloadSpec ); + std::string newSch("2.0.9"); + //std::string newSch("2.9.0"); // test error recovery in catch(...) clause + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + std::string oldFsetSch( RelationalFolderSet::folderSetSchemaVersion() ); + updateNodeSchemaVersion( "/my", newSch ); + updateNodeSchemaVersion( "/my/folder", newSch ); + try { + ralDb->dropNode( "/my/folder" ); + ralDb->dropNode( "/my" ); + } catch (...) { + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + updateNodeSchemaVersion( "/my", oldFsetSch ); + throw; + } + } + + + /// Tests what happens when the current API is used + /// to drop a database containing node with newer schema version 2.0.9 + void test_dropDatabaseWithNode_2_0_9() + { + setupDb(); + ralDb->createFolderSet( "/my" ); + ralDb->createFolder( "/my/folder1", payloadSpec ); + ralDb->createFolder( "/my/folder2", payloadSpec ); + ralDb->createFolder( "/my/folder3", payloadSpec ); + std::string newSch("2.0.9"); + //std::string newSch("2.9.0"); // test error recovery in catch(...) clause + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + updateNodeSchemaVersion( "/my/folder2", newSch ); + try { + ralDb->dropDatabase(); + } catch (...) { + updateNodeSchemaVersion( "/my/folder2", oldFoldSch ); + throw; + } + } + + + /// Tests what happens when the current API is used + /// to access a node with newer schema version 2.9.0 + void test_useNode_2_9_0() + { + setupDb(); + ralDb->createFolderSet( "/my" ); + ralDb->createFolder + ( "/my/folder", payloadSpec, "", FolderVersioning::MULTI_VERSION ); + std::string newSch("2.9.0"); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + std::string oldFsetSch( RelationalFolderSet::folderSetSchemaVersion() ); + + /// 1. Test folderset and folder using their original schema version + IFolderSetPtr folderset; + IFolderPtr folder; + folderset = ralDb->getFolderSet( "/my" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folderset name", std::string( "/my" ), folderset->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folderset schema", oldFsetSch, folderset->folderSetAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folderset->listFolders(); // Should not throw + + folder = ralDb->getFolder( "/my/folder" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folder name", std::string( "/my/folder" ), folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1. folder schema", oldFoldSch, folder->folderAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folder->folderSpecification(); // Should not throw + + /// 2. Test folderset and folder using a newer schema version + updateNodeSchemaVersion( "/my", newSch ); + updateNodeSchemaVersion( "/my/folder", newSch ); + folderset = ralDb->getFolderSet( "/my" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folderset name", std::string( "/my" ), folderset->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folderset schema", newSch, folderset->folderSetAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folder = ralDb->getFolder( "/my/folder" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folder name", std::string( "/my/folder" ), folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2. folder schema", newSch, folder->folderAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + try { + CPPUNIT_ASSERT_THROW + ( folderset->listFolders(), UnsupportedFolderSetSchema ); + CPPUNIT_ASSERT_THROW + ( folderset->listFolderSets(), UnsupportedFolderSetSchema ); + CPPUNIT_ASSERT_THROW + ( folder->folderSpecification(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->payloadSpecification(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->versioningMode(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->setupStorageBuffer(), UnsupportedFolderSchema ); + Record dummyRec( payloadSpec ); + CPPUNIT_ASSERT_THROW + ( folder->storeObject( 0, 10, dummyRec, 0 ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->flushStorageBuffer(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->findObject( 0, 0 ), UnsupportedFolderSchema ); + ChannelSelection dummyChSel( 0 ); + CPPUNIT_ASSERT_THROW + ( folder->findObjects( 0, dummyChSel ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->setPrefetchAll( true ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->browseObjects( 0, 10, dummyChSel ), + UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->countObjects( 0, 10, dummyChSel ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->renamePayload( "I", "J" ), UnsupportedFolderSchema ); + RecordSpecification extSpec; + extSpec.extend("I",StorageType::Int32); + Record extRec( extSpec ); + CPPUNIT_ASSERT_THROW + ( folder->extendPayloadSpecification( extRec ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->tagCurrentHead( "a" ), UnsupportedFolderSchema ); + Time now; + CPPUNIT_ASSERT_THROW + ( folder->insertionTimeOfLastObjectInTag("a"), + UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->deleteTag( "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->tagHeadAsOfDate( now, "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->existsUserTag( "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->listChannels(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->listChannelsWithNames(), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->createChannel( 1, "b" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->setChannelName( 1, "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->channelName( 1 ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->channelId( "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->existsChannel( 0 ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->existsChannel( "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->setChannelDescription( 1, "a" ), UnsupportedFolderSchema ); + CPPUNIT_ASSERT_THROW + ( folder->channelDescription( 1 ), UnsupportedFolderSchema ); + } catch (...) { + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + updateNodeSchemaVersion( "/my", oldFsetSch ); + throw; + } + + /// 3. Test folderset and folder using their original schema version again + updateNodeSchemaVersion( "/my", oldFsetSch ); + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + folderset = ralDb->getFolderSet( "/my" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folderset name", std::string( "/my" ), folderset->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folderset schema", oldFsetSch, folderset->folderSetAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folderset->listFolders(); // Should not throw + + folder = ralDb->getFolder( "/my/folder" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folder name", std::string( "/my/folder" ), folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3. folder schema", oldFoldSch, folder->folderAttributes() + ["NODE_SCHEMA_VERSION"].data<std::string>() ); + folder->folderSpecification(); // Should not throw + + } + + + /// Tests what happens when the current API is used + /// to drop a node with newer schema version 2.9.0 + void test_dropNode_2_9_0() + { + setupDb(); + ralDb->createFolderSet( "/my" ); + ralDb->createFolder( "/my/folder", payloadSpec ); + std::string newSch("2.9.0"); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + std::string oldFsetSch( RelationalFolderSet::folderSetSchemaVersion() ); + updateNodeSchemaVersion( "/my", newSch ); + updateNodeSchemaVersion( "/my/folder", newSch ); + try { + CPPUNIT_ASSERT_THROW + ( ralDb->dropNode( "/my/folder" ), Exception ); + CPPUNIT_ASSERT_THROW + ( ralDb->dropNode( "/my" ), Exception ); + } catch (...) { + updateNodeSchemaVersion( "/my", oldFsetSch ); + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + throw; + } + updateNodeSchemaVersion( "/my", oldFsetSch ); + updateNodeSchemaVersion( "/my/folder", oldFoldSch ); + } + + + /// Tests what happens when the current API is used + /// to drop a database containing node with newer schema version 2.9.0 + void test_dropDatabaseWithNode_2_9_0() + { + setupDb(); + ralDb->createFolderSet( "/my" ); + ralDb->createFolder( "/my/folder1", payloadSpec ); + ralDb->createFolder( "/my/folder2", payloadSpec ); + ralDb->createFolder( "/my/folder3", payloadSpec ); + std::string newSch("2.9.0"); + std::string oldFoldSch( RelationalFolder::folderSchemaVersion() ); + updateNodeSchemaVersion( "/my/folder2", newSch ); + try { + CPPUNIT_ASSERT_THROW + ( ralDb->dropDatabase(), Exception ); + IFolderSetPtr folderset = ralDb->getFolderSet( "/my" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + IFolderPtr folder; + folder = ralDb->getFolder( "/my/folder1" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + folder = ralDb->getFolder( "/my/folder2" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + folder = ralDb->getFolder( "/my/folder3" ); + CPPUNIT_ASSERT( folder.get() != 0 ); + } catch (...) { + updateNodeSchemaVersion( "/my/folder2", oldFoldSch ); + throw; + } + updateNodeSchemaVersion( "/my/folder2", oldFoldSch ); + } + + + /// Tests createFolderSet with an invalid name (task #4371 and bug #30751) + void test_createFolderSet_invalidName() + { + setupDb(); + const MSG::Level oldOutputLevel = application().outputLevel(); + application().setOutputLevel( MSG::FATAL ); + try { + CPPUNIT_ASSERT_THROW + ( ralDb->createFolderSet( "/myfolderset " ), + HvsPathHandlerException ); + CPPUNIT_ASSERT_THROW + ( ralDb->createFolderSet( "/my\folderset" ), + HvsPathHandlerException ); + CPPUNIT_ASSERT_THROW + ( ralDb->createFolderSet( "/my folderset" ), + HvsPathHandlerException ); + CPPUNIT_ASSERT_THROW + ( ralDb->createFolderSet( "/my$folderset" ), + HvsPathHandlerException ); + ralDb->createFolderSet( "/my.folderset" ); + ralDb->createFolderSet( "/my-folderset" ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + application().setOutputLevel( oldOutputLevel ); + throw; + } + application().setOutputLevel( oldOutputLevel ); + } + + + /// Tests createFolder with an invalid name (task #4371 and bug #30751) + void test_createFolder_invalidName() + { + setupDb(); + const MSG::Level oldOutputLevel = application().outputLevel(); + application().setOutputLevel( MSG::FATAL ); + try { + CPPUNIT_ASSERT_THROW + ( ralDb->createFolder( "/myfolder ", payloadSpec ), + HvsPathHandlerException ); + CPPUNIT_ASSERT_THROW + ( ralDb->createFolder( "/my\folder", payloadSpec ), + HvsPathHandlerException ); + CPPUNIT_ASSERT_THROW + ( ralDb->createFolder( "/my folder", payloadSpec ), + HvsPathHandlerException ); + CPPUNIT_ASSERT_THROW + ( ralDb->createFolder( "/my$folder", payloadSpec ), + HvsPathHandlerException ); + ralDb->createFolder( "/my.folder", payloadSpec ); + ralDb->createFolder( "/my-folder", payloadSpec ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + application().setOutputLevel( oldOutputLevel ); + throw; + } + application().setOutputLevel( oldOutputLevel ); + } + + + /* + // The following 4 tests are longer relevant after completing task #4371 + // (it is now impossible to create a node with a trailing space). + + /// Tests createFolderSet with an invalid name (task #4371 and bug #30751) + void test_createFolderSet_invalidName_old() + { + setupDb(); + try { + std::string fName; + IFolderSetPtr f; + // Trailing space + fName = "/myfolderset "; + f = ralDb->createFolderSet( fName ); + CPPUNIT_ASSERT( f.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "\"" + fName + "\"", fName, f->fullPath() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests createFolder with an invalid name (task #4371 and bug #30751) + void test_createFolder_invalidName_old() + { + setupDb(); + try { + std::string fName; + IFolderPtr f; + // Trailing space + fName = "/myfolder "; + f = ralDb->createFolder( fName, payloadSpec ); + CPPUNIT_ASSERT( f.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "\"" + fName + "\"", fName, f->fullPath() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests creating two folder sets with the same name, + /// except for a trailing space (task #4371 and bug #30751) + void test_createFolderSet_twoSimilarNames() + { + setupDb(); + try { + std::string fName; + IFolderSetPtr f; + // Trailing space (FIRST) + fName = "/myfolderset "; + f = ralDb->createFolderSet( fName ); + CPPUNIT_ASSERT( f.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "\"" + fName + "\"", fName, f->fullPath() ); + // Normal name (LATER...) + fName = "/myfolderset"; + f = ralDb->createFolderSet( fName ); + CPPUNIT_ASSERT( f.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "\"" + fName + "\"", fName, f->fullPath() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests creating two folders with the same name, + /// except for a trailing space (task #4371 and bug #30751) + void test_createFolder_twoSimilarNames() + { + setupDb(); + try { + std::string fName; + IFolderPtr f; + // Trailing space (FIRST) + fName = "/myfolder "; + f = ralDb->createFolder( fName, payloadSpec ); + CPPUNIT_ASSERT( f.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "\"" + fName + "\"", fName, f->fullPath() ); + // Normal name (LATER...) + fName = "/myfolder"; + f = ralDb->createFolder( fName, payloadSpec ); + CPPUNIT_ASSERT( f.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "\"" + fName + "\"", fName, f->fullPath() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + */ + + + /// Tests writing of the folder description + void test_createFolderSet_description() { + setupDb(); + ralDb->createFolderSet( "/myfolder", "my description" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalTableRow row( ralDb->fetchNodeTableRow( "/myfolder" ) ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "db content", + string("my description"), + row["NODE_DESCRIPTION"].data<std::string>() ); + } + + + /// Tests writing of the folder description + void test_createFolder_description() { + setupDb(); + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "description from create", + std::string("my description"), + folder->description() ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalTableRow row( ralDb->fetchNodeTableRow( "/myfolder" ) ); + transaction.commit(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "db content", + string("my description"), + row["NODE_DESCRIPTION"].data<std::string>() + ); + } + + + /// Tests getFolderSet + /// This test only ensures that the returned pointer is not null. The more + /// detailed test of the folderset read back is in test_RelationalFolderSet. + void test_getFolderSet() { + setupDb(); + ralDb->createFolderSet( "/folderset" ); + + IFolderSetPtr folderset = ralDb->getFolderSet( "/folderset" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "folderset name test", + std::string( "/folderset" ), + folderset->fullPath() ); + } + + + /// Tests getFolder + /// This test only ensures that the returned pointer is not null. The more + /// detailed test of the folder read back is in test_RelationalFolder. + void test_getFolder() { + setupDb(); + std::string folderName( "/myfolder" ); + ralDb->createFolder( folderName, payloadSpec ); + + IFolderPtr folder = ralDb->getFolder( folderName ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "folder name test", + folderName, + folder->fullPath() ); + RelationalFolder* relfolder + = dynamic_cast<RelationalFolder*>(folder.get()); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "compare object table name", + string(m_coolDBName+"_F0001_IOVS"), + relfolder->objectTableName() ); + CPPUNIT_ASSERT_MESSAGE( "compare payload spec", + payloadSpec + == folder->payloadSpecification() ); + } + + + /// Tests folderAttributes for MV folder + void test_folderAttributes_MV() { + try{ + setupDb(); + std::string folderName( "/myfolder" ); + ralDb->createFolder( folderName, + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + IFolderPtr folder = ralDb->getFolder( folderName ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder name test", + folderName, + folder->fullPath() ); + RelationalFolder* relfolder + = dynamic_cast<RelationalFolder*>(folder.get()); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "compare object table name", + string(m_coolDBName+"_F0001_IOVS"), + relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "compare tag table name", + string(m_coolDBName+"_F0001_TAGS"), + relfolder->tagTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "compare object2tag table name", + string(m_coolDBName+"_F0001_IOV2TAG"), + relfolder->object2TagTableName() ); + CPPUNIT_ASSERT_MESSAGE + ( "compare payload spec", + payloadSpec == folder->payloadSpecification() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "compare object table name from folder properties", + string(m_coolDBName+"_F0001_IOVS"), + relfolder->folderAttributes()[ "FOLDER_IOVTABLENAME" ] + .data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "compare tag table name from folder properties", + string(m_coolDBName+"_F0001_TAGS"), + relfolder->folderAttributes()[ "FOLDER_TAGTABLENAME" ] + .data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "compare object2tag table name from folder properties", + string(m_coolDBName+"_F0001_IOV2TAG"), + relfolder->folderAttributes()[ "FOLDER_IOV2TAGTABLENAME" ] + .data<std::string>() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests folderAttributes for SV folder + void test_folderAttributes_SV() { + try{ + setupDb(); + std::string folderName( "/myfolder" ); + ralDb->createFolder( folderName, + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + IFolderPtr folder = ralDb->getFolder( folderName ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder name test", + folderName, + folder->fullPath() ); + RelationalFolder* relfolder + = dynamic_cast<RelationalFolder*>(folder.get()); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "compare object table name", + string(m_coolDBName+"_F0001_IOVS"), + relfolder->objectTableName() ); + CPPUNIT_ASSERT_MESSAGE + ( "compare payload spec", + payloadSpec == folder->payloadSpecification() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "compare object table name from folder properties", + string(m_coolDBName+"_F0001_IOVS"), + relfolder->folderAttributes()[ "FOLDER_IOVTABLENAME" ] + .data<std::string>() ); + try { + relfolder->folderAttributes() + [ "FOLDER_TAGTABLENAME" ].data<std::string>(); + CPPUNIT_ASSERT_MESSAGE + ( "exception expected for FOLDER_TAGTABLENAME", false ); + } catch ( RecordSpecificationUnknownField& e ) { + RecordSpecificationUnknownField exp( "FOLDER_TAGTABLENAME", "" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception message for FOLDER_TAGTABLENAME", + string( exp.what() ), string( e.what() ) ); + } + try { + relfolder->folderAttributes() + [ "FOLDER_IOV2TAGTABLENAME" ].data<std::string>(); + CPPUNIT_ASSERT_MESSAGE + ( "exception expected for FOLDER_IOV2TAGTABLENAME", false ); + } catch ( RecordSpecificationUnknownField& e ) { + RecordSpecificationUnknownField exp( "FOLDER_IOV2TAGTABLENAME", "" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception message for FOLDER_IOV2TAGTABLENAME", + string( exp.what() ), string( e.what() ) ); + } + CPPUNIT_ASSERT_EQUAL + ( string(m_coolDBName+"_F0001_CHANNELS"), + relfolder->folderAttributes + ()[ "FOLDER_CHANNELTABLENAME" ].data<std::string>() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests that an exception is thrown when an invalid versioning mode + /// is specified on folder creation + void test_createFolder_invalidVersioningMode() { + setupDb(); + CPPUNIT_ASSERT_THROW( + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + // invalid mode + (FolderVersioning::Mode)-10 + ), + RelationalException ); + } + + + /// Tests creating a folder in MV mode + void test_createFolder_MV() { + setupDb(); + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "versioning mode", + FolderVersioning::MULTI_VERSION, + folder->versioningMode() ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalTableRow row( ralDb->fetchNodeTableRow( "/myfolder" ) ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_VERSIONING", (int)FolderVersioning::MULTI_VERSION, + row["FOLDER_VERSIONING"].data<int>() ); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + CPPUNIT_ASSERT_MESSAGE + ( "object table existence", + ralDb->queryMgr().existsTable( m_coolDBName + "_F0001_IOVS" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "tag table existence", + ralDb->queryMgr().existsTable( m_coolDBName + "_F0001_TAGS" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "iov2tag table existence", + ralDb->queryMgr().existsTable( m_coolDBName + "_F0001_IOV2TAG" ) ); + transaction.commit(); + } + } + + + /// Tests createFolder in SV mode + void test_createFolder_SV() { + setupDb(); + std::string folderName( "/myfolder" ); + IFolderPtr folder = ralDb->createFolder( folderName, payloadSpec ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "folder name test", + std::string("/myfolder"), + folder->fullPath() ); + + RelationalFolder* relfolder + = dynamic_cast<RelationalFolder*>(folder.get()); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object table name", + string(m_coolDBName+"_F0001_IOVS"), + relfolder->objectTableName() ); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + CPPUNIT_ASSERT_MESSAGE + ( "object table existence", + ralDb->queryMgr().existsTable( m_coolDBName + "_F0001_IOVS" ) ); + CPPUNIT_ASSERT + ( ralDb->queryMgr().existsTable( m_coolDBName + "_F0001_CHANNELS" ) ); + transaction.commit(); + } + } + + + /// Tests createFolder when the given folder already exists + void test_createFolder_alreadyExists() { + setupDb(); + ralDb->createFolder( "/myfolder", payloadSpec ); + // expected to throw a RelationalNodeExists exception + CPPUNIT_ASSERT_THROW( ralDb->createFolder( "/myfolder", payloadSpec ), + NodeExists ); + } + + + /// Tests createFolder with createParents = true + void test_createFolder_withParents() { + setupDb(); + std::string folderName( "/a/b/c" ); + bool createParents = true; + std::string description = ""; + IFolderPtr folder = ralDb->createFolder( folderName, + payloadSpec, + description, + FolderVersioning::SINGLE_VERSION, + createParents ); + CPPUNIT_ASSERT_MESSAGE( "/a/b/c not null", folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/a/b/c folder name test", + std::string("/a/b/c"), + folder->fullPath() ); + IFolderSetPtr folderset = ralDb->getFolderSet( "/a/b" ); + CPPUNIT_ASSERT_MESSAGE( "/a/b not null", folderset.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/a/b folderset name test", + std::string("/a/b"), + folderset->fullPath() ); + folderset = ralDb->getFolderSet( "/a" ); + CPPUNIT_ASSERT_MESSAGE( "/a not null", folderset.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "/a folder name test", + std::string("/a"), + folderset->fullPath() ); + } + + + /// Tests existsNode + void test_existsNode() { + setupDb(); + m_db->createFolder( "/myfolder", payloadSpec ); + m_db->createFolderSet( "/myfolderset" ); + + RelationalTransaction transaction( ralDb->transactionMgr(), true ); + + CPPUNIT_ASSERT_MESSAGE( "myfolder", + ralDb->existsNode( "/myfolder" ) ); + CPPUNIT_ASSERT_MESSAGE( "myfolderset", + ralDb->existsNode( "/myfolderset" ) ); + CPPUNIT_ASSERT_MESSAGE( "negative test", + ! ralDb->existsNode( "/nofolder" ) ); + + transaction.commit(); + } + + + /// Tests existsFolderSet + void test_existsFolderSet() { + setupDb(); + CPPUNIT_ASSERT_MESSAGE( "folderset does not exist yet", + ! ralDb->existsFolderSet( "/myfolderset" ) ); + ralDb->createFolderSet( "/myfolderset" ); + CPPUNIT_ASSERT_MESSAGE( "folderset exists", + ralDb->existsFolderSet( "/myfolderset" ) ); + } + + + /// Tests existsFolder + void test_existsFolder() { + setupDb(); + CPPUNIT_ASSERT_MESSAGE( "folder does not exist yet", + ! ralDb->existsFolder( "/myfolder" ) ); + ralDb->createFolder( "/myfolder", payloadSpec ); + CPPUNIT_ASSERT_MESSAGE( "folder exists", + ralDb->existsFolder( "/myfolder" ) ); + } + + + /// Tests createFolder + void test_createFolderSet_alreadyExists() { + setupDb(); + ralDb->createFolderSet( "/myfolder" ); + // expected to throw a RelationalNodeExists exception + CPPUNIT_ASSERT_THROW( ralDb->createFolderSet( "/myfolder" ), + NodeExists ); + } + + + /// Tests createFolderSet + void test_createFolderSet() { + setupDb(); + + ralDb->createFolderSet( "/myfolderset", "my description" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalTableRow row = ralDb->fetchNodeTableRow( "/myfolderset" ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ID", 1u, + row["NODE_ID"].data<unsigned int>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_PARENTID", 0u, + row["NODE_PARENTID"].data<unsigned int>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_NAME", string("myfolderset"), + row["NODE_NAME"].data<std::string>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_FULLPATH", string("/myfolderset"), + row["NODE_FULLPATH"].data<std::string>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_DESCRIPTION", string("my description"), + row["NODE_DESCRIPTION"].data<std::string>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ISLEAF", false, + row["NODE_ISLEAF"].data<bool>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_INSTIME length", + string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + row["NODE_INSTIME"].data<std::string>().size() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_PAYLOADSPEC", string(""), + row["FOLDER_PAYLOADSPEC"].data<std::string>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_VERSIONING", (int)FolderVersioning::NONE, + row["FOLDER_VERSIONING"].data<int>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_IOVTABLENAME", string(""), + row["FOLDER_IOVTABLENAME"].data<std::string>() ); + } + + + /// Tests dropAllNodes + void test_dropAllNodes() { + setupDb(); + std::vector<string> folderNames; + folderNames.push_back( "/f1" ); + folderNames.push_back( "/f2" ); + folderNames.push_back( "/f3" ); + for ( std::vector<string>::const_iterator f = folderNames.begin(); + f != folderNames.end(); + ++f ) { + ralDb->createFolder( *f, payloadSpec ); + } + + for ( std::vector<string>::const_iterator f = folderNames.begin(); + f != folderNames.end(); + ++f ) { + CPPUNIT_ASSERT_MESSAGE( string("folder exists: ") + *f, + ralDb->existsFolder( *f ) ); + } + + ralDb->dropAllNodes(); + + for ( std::vector<string>::const_iterator f = folderNames.begin(); + f != folderNames.end(); + ++f ) { + CPPUNIT_ASSERT_MESSAGE( string("folder is deleted: ") + *f, + ! ralDb->existsFolder( *f ) ); + } + } + + + /// Tests dropNode + void test_dropNode() { + setupDb(); + try { + { + // Test dropping a SV folder + IFolderPtr + folder = ralDb->createFolder( "/myfolder_sv", payloadSpec ); + + CPPUNIT_ASSERT_MESSAGE( "/myfolder_sv exists", + ralDb->existsFolder( "/myfolder_sv" ) ); + stringstream prefix; + prefix << m_coolDBName << "_F000" << folder->id(); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + CPPUNIT_ASSERT_MESSAGE + ( "SV object table exists", + ralDb->queryMgr().existsTable( prefix.str() + "_IOVS" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "SV object sequence exists", + ralDb->queryMgr().existsTable( prefix.str() + "_IOVS_SEQ" ) ); + transaction.commit(); + } + ralDb->dropNode( "/myfolder_sv" ); + CPPUNIT_ASSERT_MESSAGE + ( "/folder_sv is deleted", + ! ralDb->existsFolder( "/myfolder_sv" ) ); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + CPPUNIT_ASSERT_MESSAGE + ( "SV object table removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_IOVS" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "SV object sequence removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_IOVS_SEQ" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "SV tag table removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_TAGS" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "SV tag sequence removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_TAGS_SEQ" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "SV iov2tag table removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_IOV2TAG" ) ); + transaction.commit(); + } + } + + { + // Test dropping a MV folder + IFolderPtr + folder = ralDb->createFolder( "/myfolder_mv", payloadSpec, + "", FolderVersioning::MULTI_VERSION ); + CPPUNIT_ASSERT_MESSAGE( "/myfolder_mv exists", + ralDb->existsFolder( "/myfolder_mv" ) ); + stringstream prefix; + prefix << m_coolDBName << "_F000" << folder->id(); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + CPPUNIT_ASSERT_MESSAGE + ( "MV object table exists", + ralDb->queryMgr().existsTable( prefix.str() + "_IOVS" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "MV object sequence exists", + ralDb->queryMgr().existsTable( prefix.str() + "_IOVS_SEQ" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "MV tag table exists", + ralDb->queryMgr().existsTable( prefix.str() + "_TAGS" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "MV tag sequence exists", + ralDb->queryMgr().existsTable( prefix.str() + "_TAGS_SEQ" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "MV iov2tag table exists", + ralDb->queryMgr().existsTable( prefix.str() + "_IOV2TAG" ) ); + transaction.commit(); + } + ralDb->dropNode( "/myfolder_mv" ); + CPPUNIT_ASSERT_MESSAGE + ( "/folder_mv is deleted", + ! ralDb->existsFolder( "/myfolder_mv" ) ); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + CPPUNIT_ASSERT_MESSAGE + ( "MV object table removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_IOVS" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "MV object sequence removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_IOVS_SEQ" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "MV tag table removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_TAGS" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "MV tag sequence removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_TAGS_SEQ" ) ); + CPPUNIT_ASSERT_MESSAGE + ( "MV iov2tag table removed", + ! ralDb->queryMgr().existsTable( prefix.str() + "_IOV2TAG" ) ); + transaction.commit(); + } + } + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests listAllNodes + void test_listAllNodes() { + setupDb(); + ralDb->createFolderSet( "/f1" ); + ralDb->createFolderSet( "/f2" ); + ralDb->createFolderSet( "/f3" ); + ralDb->createFolderSet( "/f4" ); + ralDb->createFolder( "/f1/folderA", payloadSpec ); + ralDb->createFolder( "/f1/folderB", payloadSpec ); + ralDb->createFolder( "/f3/folderA", payloadSpec ); + ralDb->createFolder( "/f3/folderB", payloadSpec ); + + std::vector<string> readbackNames = ralDb->listAllNodes(); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "node count", + (size_t)9, readbackNames.size() ); + CPPUNIT_ASSERT_MESSAGE( "/f1", + find( readbackNames.begin(), readbackNames.end(), + "/f1" ) != readbackNames.end() ); + CPPUNIT_ASSERT_MESSAGE( "/f2", + find( readbackNames.begin(), readbackNames.end(), + "/f2" ) != readbackNames.end() ); + CPPUNIT_ASSERT_MESSAGE( "/f3", + find( readbackNames.begin(), readbackNames.end(), + "/f3" ) != readbackNames.end() ); + CPPUNIT_ASSERT_MESSAGE( "/f4", + find( readbackNames.begin(), readbackNames.end(), + "/f4" ) != readbackNames.end() ); + CPPUNIT_ASSERT_MESSAGE( "/f1/folderA", + find( readbackNames.begin(), readbackNames.end(), + "/f1/folderA" ) != readbackNames.end() ); + CPPUNIT_ASSERT_MESSAGE( "/f1/folderB", + find( readbackNames.begin(), readbackNames.end(), + "/f3/folderB" ) != readbackNames.end() ); + CPPUNIT_ASSERT_MESSAGE( "/f3/folderA", + find( readbackNames.begin(), readbackNames.end(), + "/f3/folderA" ) != readbackNames.end() ); + CPPUNIT_ASSERT_MESSAGE( "/f3/folderB", + find( readbackNames.begin(), readbackNames.end(), + "/f3/folderB" ) != readbackNames.end() ); + CPPUNIT_ASSERT_MESSAGE( "root", + find( readbackNames.begin(), readbackNames.end(), + "/" ) != readbackNames.end() ); + } + + + /// Tests listAllTables + void test_listAllTables() { + setupDb(); + ralDb->createFolderSet( "/f1" ); + ralDb->createFolder( "/f1/folderA", payloadSpec ); + ralDb->createFolder( "/f1/folderB", payloadSpec ); + std::vector<string> tables = ralDb->listAllTables(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tables count", (size_t)14, tables.size() ); + std::vector<std::string> suffixes; + suffixes.push_back( "_DB_ATTRIBUTES" ); + suffixes.push_back( "_F0000_TAGS_SEQ" ); + suffixes.push_back( "_F0001_TAGS_SEQ" ); + suffixes.push_back( "_F0002_CHANNELS" ); + suffixes.push_back( "_F0002_IOVS" ); + suffixes.push_back( "_F0002_IOVS_SEQ" ); + suffixes.push_back( "_F0003_CHANNELS" ); + suffixes.push_back( "_F0003_IOVS" ); + suffixes.push_back( "_F0003_IOVS_SEQ" ); + suffixes.push_back( "_NODES" ); + suffixes.push_back( "_NODES_SEQ" ); + suffixes.push_back( "_TAG2TAG" ); + suffixes.push_back( "_TAG2TAG_SEQ" ); + suffixes.push_back( "_TAGS" ); + std::vector<std::string>::const_iterator suffix; + for ( suffix = suffixes.begin(); suffix != suffixes.end(); suffix++ ) + { + std::string table; + table = m_coolDBName + *suffix; + CPPUNIT_ASSERT_MESSAGE + ( table, find( tables.begin(), tables.end(), table ) != tables.end() ); + } + } + + + /// Tests insertNodeTableRow for a leaf node + /// [NB - This test bypasses the public API and causes data corruption!] + /// [Cleanup fails unless exception throwing in dropDatabase() is disabled] + void test_insertNodeTableRow_leaf() { + setupDb(); + bool createParents = true; + bool isLeaf = true; + string payloadSpecDesc = "I:int"; + try { + RelationalTransaction transaction( ralDb->transactionMgr() ); + unsigned int nodeId = + ralDb->insertNodeTableRow( "/a/b/c", + "my description", + createParents, + isLeaf, + payloadSpecDesc, + FolderVersioning::SINGLE_VERSION ); + RelationalTableRow row( ralDb->fetchNodeTableRow( "/a/b/c" ) ); + transaction.commit(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "return value", 3u, nodeId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ID", 3u, + row["NODE_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_PARENTID", 2u, + row["NODE_PARENTID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_NAME", string("c"), + row["NODE_NAME"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_FULLPATH", string("/a/b/c"), + row["NODE_FULLPATH"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_DESCRIPTION", string("my description"), + row["NODE_DESCRIPTION"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ISLEAF", true, + row["NODE_ISLEAF"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_INSTIME length", + string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + row["NODE_INSTIME"].data<std::string>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_PAYLOADSPEC", string("I:int"), + row["FOLDER_PAYLOADSPEC"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_VERSIONING", + (int)FolderVersioning::SINGLE_VERSION, + row["FOLDER_VERSIONING"].data<int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_IOVTABLENAME", + string(m_coolDBName+"_F0003_IOVS"), + row["FOLDER_IOVTABLENAME"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_TAGTABLENAME", + string(m_coolDBName+"_F0003_TAGS"), + row["FOLDER_TAGTABLENAME"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_IOV2TAGTABLENAME", + string(m_coolDBName+"_F0003_IOV2TAG"), + row["FOLDER_IOV2TAGTABLENAME"].data<std::string>() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests insertNodeTableRow for a nonleaf node + void test_insertNodeTableRow_nonleaf() { + setupDb(); + bool createParents = true; + bool isLeaf = false; + string payloadSpecDesc = ""; + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + unsigned int nodeId + = ralDb->insertNodeTableRow( "/a/b/c", + "my description", + createParents, + isLeaf, + payloadSpecDesc, + FolderVersioning::NONE ); + RelationalTableRow row( ralDb->fetchNodeTableRow( "/a/b/c" ) ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "return value", 3u, nodeId ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ID", 3u, + row["NODE_ID"].data<unsigned int>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_PARENTID", 2u, + row["NODE_PARENTID"].data<unsigned int>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_NAME", string("c"), + row["NODE_NAME"].data<std::string>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_FULLPATH", string("/a/b/c"), + row["NODE_FULLPATH"].data<std::string>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_DESCRIPTION", string("my description"), + row["NODE_DESCRIPTION"].data<std::string>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ISLEAF", false, + row["NODE_ISLEAF"].data<bool>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_INSTIME length", + string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + row["NODE_INSTIME"].data<std::string>().size() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_PAYLOADSPEC", string(""), + row["FOLDER_PAYLOADSPEC"].data<std::string>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_VERSIONING", (int)FolderVersioning::NONE, + row["FOLDER_VERSIONING"].data<int>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_IOVTABLENAME", string(""), + row["FOLDER_IOVTABLENAME"].data<std::string>() ); + } + + + /// utility method to test AttributeList handling + RelationalTableRow + nestedScope( RalDatabase* aDb, const std::string& foldername ) { + static int callDepth = 0; + if ( callDepth < 10 ) { + ++callDepth; + return nestedScope( aDb, foldername ); + } else { + callDepth = 0; + return aDb->fetchNodeTableRow( foldername ); + } + } + + + /// Tests copying of AttributeList from the fetch methods + void test_fetchNodeTableRow_nestedScope() { + setupDb(); + bool createParents = true; + bool isLeaf = false; + string payloadSpecDesc = ""; + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + ralDb->insertNodeTableRow( "/myfolder", + "my description", + createParents, + isLeaf, + payloadSpecDesc, + FolderVersioning::NONE ); + + RelationalTableRow row( nestedScope( ralDb, "/myfolder" ) ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL( string("/myfolder"), + row["NODE_FULLPATH"].data<std::string>() ); + } + + + /// Tests fetchNodeTableRow + void test_fetchNodeTableRow() { + try { + setupDb(); + bool createParents = true; + bool isLeaf = false; + string payloadSpecDesc = ""; + RelationalTransaction transaction( ralDb->transactionMgr() ); + ralDb->insertNodeTableRow( "/myfolder", + "my description", + createParents, + isLeaf, + payloadSpecDesc, + FolderVersioning::NONE ); + RelationalTableRow row( ralDb->fetchNodeTableRow( "/myfolder" ) ); + transaction.commit(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ID", 1u, + row["NODE_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_PARENTID", 0u, + row["NODE_PARENTID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_NAME", string("myfolder"), + row["NODE_NAME"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_FULLPATH", string("/myfolder"), + row["NODE_FULLPATH"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_DESCRIPTION", string("my description"), + row["NODE_DESCRIPTION"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ISLEAF", false, + row["NODE_ISLEAF"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_INSTIME length", + string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + row["NODE_INSTIME"].data<std::string>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_PAYLOADSPEC", string(""), + row["FOLDER_PAYLOADSPEC"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_VERSIONING", + (int)FolderVersioning::NONE, + row["FOLDER_VERSIONING"].data<int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "FOLDER_IOVTABLENAME", string(""), + row["FOLDER_IOVTABLENAME"].data<std::string>() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests insertNodeTableRow + /// (if this fails, test_fetchNodeTableRow will also fail) + void test_insertNodeTableRow() { + try { + setupDb(); + bool createParents = true; + bool isLeaf = false; + string payloadSpecDesc = ""; + RelationalTransaction transaction( ralDb->transactionMgr() ); + ralDb->insertNodeTableRow( "/myfolder", + "my description", + createParents, + isLeaf, + payloadSpecDesc, + FolderVersioning::NONE ); + transaction.commit(); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests fetchRootNodeTableRow + /// (if this fails, test_insertNodeTableRow will also fail) + void test_fetchRootNodeTableRow() { + try { + setupDb(); + RelationalTransaction transaction( ralDb->transactionMgr(), true ); + RelationalTableRow row( ralDb->fetchNodeTableRow( "/" ) ); + transaction.commit(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ID", 0u, + row["NODE_ID"].data<unsigned int>() ); + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "NODE_PARENTID", ??, // NULL + // row["NODE_PARENTID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_NAME", string(""), + row["NODE_NAME"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_FULLPATH", string("/"), + row["NODE_FULLPATH"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_DESCRIPTION", string(""), + row["NODE_DESCRIPTION"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_ISLEAF", false, + row["NODE_ISLEAF"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_INSTIME length", + string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + row["NODE_INSTIME"].data<std::string>().size() ); + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "FOLDER_PAYLOADSPEC", string(""), + // row["FOLDER_PAYLOADSPEC"].data<std::string>() ); + CPPUNIT_ASSERT_MESSAGE + ( "FOLDER_PAYLOADSPEC", row["FOLDER_PAYLOADSPEC"].isNull() ); + ////CPPUNIT_ASSERT_EQUAL_MESSAGE + //// ( "FOLDER_VERSIONING", + //// (int)FolderVersioning::NONE, // BUG: null - should be -1! + //// row["FOLDER_VERSIONING"].data<int>() ); + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "FOLDER_IOVTABLENAME", string(""), + // row["FOLDER_IOVTABLENAME"].data<std::string>() ); + CPPUNIT_ASSERT_MESSAGE + ( "FOLDER_IOVTABLENAME", row["FOLDER_IOVTABLENAME"].isNull() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests dropDatabase + void test_dropDatabase() { + std::vector<string> folderNames; + folderNames.push_back( "/f1" ); + folderNames.push_back( "/f2" ); + folderNames.push_back( "/f3" ); + folderNames.push_back( "/f4" ); + std::vector<string> objectTables; + + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( m_connectionString ); + m_db = dbSvc.createDatabase( m_connectionString ); + ralDb = dynamic_cast<RalDatabase*>(m_db.get()); + + for ( std::vector<string>::const_iterator f = folderNames.begin(); + f != folderNames.end(); + ++f ) { + IFolderPtr folder = ralDb->createFolder( *f, payloadSpec ); + RelationalFolder* rf = dynamic_cast<RelationalFolder*>(folder.get()); + objectTables.push_back( rf->objectTableName() ); + } + + ralDb->dropDatabase(); + + bool readOnly = true; + RelationalTransaction transaction( ralDb->transactionMgr(), readOnly ); + coral::ISessionProxy& session = ralDb->session(); + coral::ISchema& schema = session.nominalSchema(); + //coral::ISchema& schema = ralDb->session().nominalSchema(); + + CPPUNIT_ASSERT_MESSAGE( "main table deleted", + ! schema.existsTable( ralDb->mainTableName() ) ); + + string folderSeqName = + RelationalNodeTable::sequenceName( ralDb->nodeTableName() ); + CPPUNIT_ASSERT_MESSAGE( "sequence table deleted", + ! schema.existsTable( folderSeqName ) ); + + CPPUNIT_ASSERT_MESSAGE( "folder table deleted", + ! schema.existsTable( ralDb->nodeTableName() ) ); + + for ( std::vector<string>::const_iterator objTable = objectTables.begin(); + objTable != objectTables.end(); + ++objTable ) { + CPPUNIT_ASSERT_MESSAGE( *objTable + " table deleted", + ! schema.existsTable( *objTable ) ); + } + + CPPUNIT_ASSERT_MESSAGE + ( "tag table deleted", + ! schema.existsTable( ralDb->globalTagTableName() ) ); + + CPPUNIT_ASSERT_MESSAGE + ( "tag2tag table deleted", + ! schema.existsTable( ralDb->tag2TagTableName() ) ); + + } + + /// Tests uppercasing of user provided connect strings + /// TEMPORARY! AV 04.04.05 + /// This test is no longer relevant: input dbname must be uppercase! + /* + const std::string lowercaseString( const std::string& aString ) { + std::string aStringLow = aString; + std::transform + ( aStringLow.begin(), aStringLow.end(), aStringLow.begin(), tolower ); + return aStringLow; + } + void test_dbName_caseInsensitivity() { + RelationalDatabaseId id( m_connectionString ); + string newId = id.technology() + "://"; + newId += id.server() + ";"; + newId += "schema=" + id.schema() + ";"; + if ( id.user() != "" ) { + newId += "user=" + id.user() + ";"; + newId += "password=" + id.password() + ";"; + } + newId += "dbname=" + lowercaseString( id.dbName() ); + + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( newId ); + m_db = dbSvc.createDatabase( newId ); + ralDb = dynamic_cast<RalDatabase*>(m_db.get()); + + m_db->createFolder( "/sv", payloadSpec ); + + CPPUNIT_ASSERT_MESSAGE + ( "object table existence", + ralDb->queryMgr().existsTable( uppercaseString( id.dbName() ) + + "_F0001_IOVS" ) ); + + m_db->createFolder( "/mv", payloadSpec, "desc", + FolderVersioning::MULTI_VERSION ); + + CPPUNIT_ASSERT_MESSAGE + ( "object table existence", + ralDb->queryMgr().existsTable( uppercaseString( id.dbName() ) + + "_F0002_IOVS" ) ); + + CPPUNIT_ASSERT_MESSAGE + ( "tag table existence", + ralDb->queryMgr().existsTable( uppercaseString( id.dbName() ) + + "_F0002_TAGS" ) ); + + CPPUNIT_ASSERT_MESSAGE + ( "iov2tag table existence", + ralDb->queryMgr().existsTable( uppercaseString( id.dbName() ) + + "_F0002_IOV2TAG" ) ); + } + */ + + /// Tests the length of database names + void test_dbNameLength() { + RelationalDatabaseId id( m_connectionString ); + string newId; + if ( id.alias().empty() ) { + newId = id.technology() + "://"; + newId += id.server() + ";"; + newId += "schema=" + id.schema() + ";"; + if ( id.user() != "" ) { + newId += "user=" + id.user() + ";"; + newId += "password=" + id.password() + ";"; + } + newId += "dbname=123456789;"; + } else { + newId = id.alias() + "/123456789"; + } + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( newId ); + m_db = dbSvc.createDatabase( newId ); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( RelationalException& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", + string( "Invalid COOL database name '123456789': " + "the database name length must not exceed 8 characters" ), + string( e.what() ) ); + } + } + + /// Tests that database names are uppercase + void test_dbNameUppercase() { + RelationalDatabaseId id( m_connectionString ); + string newId; + if ( id.alias().empty() ) { + newId = id.technology() + "://"; + newId += id.server() + ";"; + newId += "schema=" + id.schema() + ";"; + if ( id.user() != "" ) { + newId += "user=" + id.user() + ";"; + newId += "password=" + id.password() + ";"; + } + newId += "dbname=aBcDeFgH;"; + } else { + newId = id.alias() + "/aBcDeFgH"; + } + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( newId ); + m_db = dbSvc.createDatabase( newId ); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( RelationalException& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", + string( "Invalid COOL database name 'aBcDeFgH': " + "the database name must be UPPERCASE" ), + string( e.what() ) ); + } + } + + /// Tests that database names only contain letters and numbers + void test_dbNameLettersAndNumbers() { + RelationalDatabaseId id( m_connectionString ); + string newId; + if ( id.alias().empty() ) { + newId = id.technology() + "://"; + newId += id.server() + ";"; + newId += "schema=" + id.schema() + ";"; + if ( id.user() != "" ) { + newId += "user=" + id.user() + ";"; + newId += "password=" + id.password() + ";"; + } + newId += "dbname=ABCD#FGH;"; + } else { + newId = id.alias() + "/ABCD#FGH"; + } + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( newId ); + m_db = dbSvc.createDatabase( newId ); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( RelationalException& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", + string( "Invalid COOL database name 'ABCD#FGH': " + "the database name must contain only letters, numbers" + " or the '_' character" ), + string( e.what() ) ); + } + } + + + /// Tests that database names start with a letter + void test_dbNameStartsWithLetter() { + RelationalDatabaseId id( m_connectionString ); + string newId; + if ( id.alias().empty() ) { + newId = id.technology() + "://"; + newId += id.server() + ";"; + newId += "schema=" + id.schema() + ";"; + if ( id.user() != "" ) { + newId += "user=" + id.user() + ";"; + newId += "password=" + id.password() + ";"; + } + newId += "dbname=1BCDEFGH;"; + } else { + newId = id.alias() + "/1BCDEFGH"; + } + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( newId ); + m_db = dbSvc.createDatabase( newId ); + CPPUNIT_ASSERT_MESSAGE( "exception expected", false ); + } catch ( RelationalException& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception caught", + string( "Invalid COOL database name '1BCDEFGH': " + "the database name must start with a letter" ), + string( e.what() ) ); + } + } + + + /// Tests openDatabase + void test_openDatabase_rw() { + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( m_connectionString ); + dbSvc.createDatabase( m_connectionString ); + m_db = dbSvc.openDatabase( m_connectionString, false ); + CPPUNIT_ASSERT( m_db.get() != 0 ); + CPPUNIT_ASSERT( m_db->isOpen() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + /// Tests openDatabase + void test_openDatabase_ro() { + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( m_connectionString ); + dbSvc.createDatabase( m_connectionString ); + m_db = dbSvc.openDatabase( m_connectionString ); + CPPUNIT_ASSERT( m_db.get() != 0 ); + CPPUNIT_ASSERT( m_db->isOpen() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + /// Tests createDatabase + void test_createDatabase() { + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( m_connectionString ); + m_db = dbSvc.createDatabase( m_connectionString ); + CPPUNIT_ASSERT( m_db.get() != 0 ); + CPPUNIT_ASSERT( m_db->isOpen() ); + { + ralDb = dynamic_cast<RalDatabase*>(m_db.get()); + RelationalDatabaseId id( m_connectionString ); + std::string m_coolDBName = id.dbName(); + RelationalTransaction transaction( ralDb->transactionMgr() ); + CPPUNIT_ASSERT + ( ralDb->queryMgr().existsTable( m_coolDBName + "_DB_ATTRIBUTES" ) ); + CPPUNIT_ASSERT + ( ralDb->queryMgr().existsTable( m_coolDBName + "_F0000_TAGS_SEQ" ) ); + CPPUNIT_ASSERT + ( ralDb->queryMgr().existsTable( m_coolDBName + "_NODES" ) ); + CPPUNIT_ASSERT + ( ralDb->queryMgr().existsTable( m_coolDBName + "_NODES_SEQ" ) ); + CPPUNIT_ASSERT + ( ralDb->queryMgr().existsTable( m_coolDBName + "_TAG2TAG" ) ); + CPPUNIT_ASSERT + ( ralDb->queryMgr().existsTable( m_coolDBName + "_TAG2TAG_SEQ" ) ); + CPPUNIT_ASSERT + ( ralDb->queryMgr().existsTable( m_coolDBName + "_TAGS" ) ); + transaction.commit(); + } + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// setup the database + /// This code is not in setup(), because some of its methods + /// need to be tested in this unit test class and therefore the + /// setup() method that is run before each test cannot rely on them + void setupDb() { + try { + createDB(); + openDB(false); + ralDb = dynamic_cast<RalDatabase*>(m_db.get()); + } catch ( std::exception& e ) { + std::cout << "Exception caught in setupDb(): " << e.what() << std::endl; + throw; + } + } + + + /// Utility method to return a dummy object with a distinct payload + /// (determined by 'index') for a given set of since/until/channel + RelationalObjectPtr dummyObject( int index, + const ValidityKey& since, + const ValidityKey& until, + const ChannelId& channel = 0 ) { + RelationalObjectPtr + obj( new RelationalObject( since, + until, + dummyPayload( index ), + channel ) ); + return obj; + } + + + /// Utility method to generate a distinct payload for a given index + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + + void setUp() { + } + + + void tearDown() { + forceDisconnect(); + } + +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( RalDatabaseTest ); + +} + +COOLTEST_MAIN(RalDatabaseTest) diff --git a/RelationalCool/tests/RalDatabaseSvc/test_RalDatabaseSvc.cpp b/RelationalCool/tests/RalDatabaseSvc/test_RalDatabaseSvc.cpp new file mode 100644 index 000000000..3e4adb146 --- /dev/null +++ b/RelationalCool/tests/RalDatabaseSvc/test_RalDatabaseSvc.cpp @@ -0,0 +1,137 @@ +// $Id: test_RalDatabaseSvc.cpp,v 1.35 2008-04-11 10:02:51 marcocle Exp $ + +// Include files +#include "CoolDBUnitTest.h" +#include "../Common/CppUnit_headers.h" // Disable CppUnit header warnings +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/Exception.h" +#include <iostream> + +// Local include files +#include "src/CoralApplication.h" +#include "src/VersionInfo.h" + +// Forward declaration +namespace cool { + class RalDatabaseSvcTest; +} + +//----------------------------------------------------------------------------- + +class cool::RalDatabaseSvcTest : public cool::CoolDBUnitTest { + + CPPUNIT_TEST_SUITE( RalDatabaseSvcTest ); + + CPPUNIT_TEST( test_getService ); + CPPUNIT_TEST( test_serviceVersion ); + CPPUNIT_TEST( test_createDatabase ); + CPPUNIT_TEST( test_openDatabase ); + CPPUNIT_TEST( test_openDatabase_rw ); + CPPUNIT_TEST( test_openDatabase_nonexisting ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + /// Default constructor + RalDatabaseSvcTest(): + // this test is testing the service, so I cannot get it in the constructor + cool::CoolDBUnitTest(false) + {} + + void setUp() { + } + + void tearDown() { + dropDB(); + } + + + /// Tests openDatabase on a nonexisting database + void test_openDatabase_nonexisting() + { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( m_connectionString ); + CPPUNIT_ASSERT_THROW( dbSvc.openDatabase( m_connectionString ), + DatabaseDoesNotExist ); + } + + + /// Tests openDatabase + void test_openDatabase() { + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + //std::cout << "Drop database..." << std::endl; + dbSvc.dropDatabase( m_connectionString ); + //std::cout << "Drop database... OK" << std::endl; + //std::cout << "Create database..." << std::endl; + dbSvc.createDatabase( m_connectionString ); + //std::cout << "Create database... OK" << std::endl; + //std::cout << "Open database..." << std::endl; + m_db = dbSvc.openDatabase( m_connectionString, true ); + //std::cout << "Open database... OK" << std::endl; + CPPUNIT_ASSERT( m_db.get() != 0 ); + } catch ( std::exception& e ) { + std::cout << e.what() << std::endl; + throw; + } + } + + /// Tests openDatabase + void test_openDatabase_rw() { + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( m_connectionString ); + dbSvc.createDatabase( m_connectionString ); + m_db = dbSvc.openDatabase( m_connectionString, false ); + CPPUNIT_ASSERT( m_db.get() != 0 ); + } catch ( std::exception& e ) { + std::cout << e.what() << std::endl; + throw; + } + } + + /// Tests createDatabase + void test_createDatabase() { + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( m_connectionString ); + m_db = dbSvc.createDatabase( m_connectionString ); + CPPUNIT_ASSERT( m_db.get() != 0 ); + } catch ( std::exception& e ) { + std::cout << e.what() << std::endl; + throw; + } + } + + + /// Tests IDatabaseSvc::serviceVersion() + void test_serviceVersion() { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "IDatabaseSvc version", + std::string(VersionInfo::release), + dbSvc.serviceVersion() ); + } + + + /// Tests the getService method for the RalDatabaseSvc + /// (the seal plugin/context mechanism) + void test_getService() { + CoralApplication app; + app.databaseService(); + //CPPUNIT_ASSERT_MESSAGE( "reach this point without exception", true ); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( cool::RalDatabaseSvcTest ); + +//----------------------------------------------------------------------------- + +COOLTEST_MAIN(RalDatabaseSvcTest) diff --git a/RelationalCool/tests/RalDatabase_extendedSpec/test_RalDatabase_extendedSpec.cpp b/RelationalCool/tests/RalDatabase_extendedSpec/test_RalDatabase_extendedSpec.cpp new file mode 100644 index 000000000..dc9b39036 --- /dev/null +++ b/RelationalCool/tests/RalDatabase_extendedSpec/test_RalDatabase_extendedSpec.cpp @@ -0,0 +1,1181 @@ +// -*- coding: iso-8859-1 -*- +// $Id: test_RalDatabase_extendedSpec.cpp,v 1.101 2008-05-15 16:32:33 avalassi Exp $ + +// Include files +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IField.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordException.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeListException.h" + +// Local include files +#include "CppUnit_headers.h" // tests/Common - disable CppUnit header warnings +#include "src/CoralApplication.h" +#include "src/RelationalException.h" +#include "src/RelationalFolder.h" +#include "src/RelationalDatabase.h" +#include "src/RelationalNodeTable.h" +#include "src/RalDatabase.h" +#include "src/SimpleObject.h" + +// ---- these things are needed to force a drop of the connection +#include "src/RalDatabaseSvc.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" + +namespace cool { + const char* COOLTESTDB = "COOLTESTDB"; + // This line is to avoid error "qualified name does not name a class" + // on gcc 4.1 + class RalDatabaseTest_extendedSpec; +} + +//----------------------------------------------------------------------------- + +class cool::RalDatabaseTest_extendedSpec : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( RalDatabaseTest_extendedSpec ); + + CPPUNIT_TEST( test_payloadSpecDescription ); + CPPUNIT_TEST( test_payloadSpecTooManyFields ); + CPPUNIT_TEST( test_payloadSpecTooManyBlobFields ); + CPPUNIT_TEST( test_payloadSpecTooManyString255Fields ); + CPPUNIT_TEST( test_payloadSpecInvalidFieldName ); + + CPPUNIT_TEST( test_payloadSpecOver8000Bytes ); // fails on MySQL (bug #24646) + + CPPUNIT_TEST( test_default_string4000 ); + + CPPUNIT_TEST( test_extSpec_string255 ); + + CPPUNIT_TEST( test_default_UInt63 ); + + //CPPUNIT_TEST_EXCEPTION( test_unsupportedTypesToken, + // coral::AttributeListException ); + + //CPPUNIT_TEST_EXCEPTION( test_unsupportedTypesChar, + // RelationalTypeConverterInvalidCppType ); + + //CPPUNIT_TEST_EXCEPTION( test_unsupportedTypesLongDouble, + // RelationalTypeConverterInvalidCppType ); + + //CPPUNIT_TEST_EXCEPTION( test_unsupportedTypesLongLong, + // RelationalTypeConverterInvalidCppType ); + + //CPPUNIT_TEST_EXCEPTION( test_unsupportedTypesVector, + // coral::AttributeListException ); + + CPPUNIT_TEST( test_supportedTypes ); + + CPPUNIT_TEST( test_extSpec_allStrings ); + + CPPUNIT_TEST( test_storagObject_special_characters ); + + CPPUNIT_TEST( test_emptyString ); + + CPPUNIT_TEST( test_nullCharInString ); + + CPPUNIT_TEST( test_blob64kOver64k ); + CPPUNIT_TEST( test_blob16MOver64k ); + + CPPUNIT_TEST( test_emptyBlob ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + std::string connectString; + IDatabasePtr db; + RalDatabase* ralDb; // safely cast pointer to db + + RecordSpecification payloadSpec; + + RalDatabaseTest_extendedSpec() + : payloadSpec() { + + payloadSpec.extend("I",StorageType::Int32); + payloadSpec.extend("S",StorageType::String255); + payloadSpec.extend("X",StorageType::Float); + + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + std::cout << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << std::endl; + std::cout << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << std::endl; + std::cout << "Aborting test" << std::endl; + exit(-1); + } + } + + ~RalDatabaseTest_extendedSpec() {} + + + /// Tests storage and retrieval of non-ascii and 'sql-tricky' characters + void test_storagObject_special_characters() { + RecordSpecification spec; + spec.extend( "quotes", StorageType::String255 ); + spec.extend( "umlauts", StorageType::String255 ); + spec.extend( "diacriticals", StorageType::String255 ); + + coral::AttributeList payload = Record( spec ).attributeList(); + IFolderPtr folder = ralDb->createFolder( "/myfolder", spec ); + + + std::string umlauts = "umlauts "; + // octal representation of umlauts in iso-8895-1 + // "������������" + umlauts += "\304\313\317\326\334\337\344\353\357\366\374\377"; + umlauts += " in string"; + std::string diacriticals = "diacriticals "; + // octal representation of other accents in iso-8895-1 + // "��������������������������������������������������" + diacriticals += "\300\301\302\303\305\306\307\310\311\312\314\315\316\320"; + diacriticals += "\321\322\323\324\325\330\331\332\333\335\336\340\341\342"; + diacriticals += "\343\345\346\347\350\351\352\354\355\356\360\361\362\363"; + diacriticals += "\364\365\370\371\372\373\375\376"; + diacriticals += " in string"; + + payload[ "quotes" ].setValue<String255> + ( "quotes '\" in string" ); + payload[ "umlauts" ].setValue<String255> + ( umlauts ); + payload[ "diacriticals" ].setValue<String255> + ( diacriticals ); + folder->storeObject( 5, 15, payload, 0 ); + + IObjectPtr obj = folder->findObject( 10, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "quotes string", + std::string( "quotes '\" in string" ), + obj->payload()["quotes"].data<String255>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "umlauts string", + umlauts, + obj->payload()["umlauts"].data<String255>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "diacriticals string", + diacriticals, + obj->payload()["diacriticals"].data<String255>() ); + + } + + + /// Tests creation of a folder with as many columns as there are + /// C++ types supported in COOL (using default payload hints) + /// [Test all types in pool/AttributeList/src/AttributePredefinedTypes.cpp] + void test_supportedTypes() { + + try { + + // Create a folder with 12 payload columns + typedef std::pair<std::string,StorageType::TypeId> pair_type; + std::vector<pair_type> all_types; + + all_types.push_back(pair_type("A_BOOL", + StorageType::Bool)); + //all_types.push_back(pair_type("A_CHAR",StorageType::Char)); // RAL MySQL error on retrieval + all_types.push_back(pair_type("A_UCHAR", + StorageType::UChar)); + all_types.push_back(pair_type("A_INT16", + StorageType::Int16)); + all_types.push_back(pair_type("A_UINT16", + StorageType::UInt16)); + all_types.push_back(pair_type("A_INT32", + StorageType::Int32)); + all_types.push_back(pair_type("A_UINT32", + StorageType::UInt32)); + all_types.push_back(pair_type("A_UINT63", + StorageType::UInt63)); + all_types.push_back(pair_type("A_INT64", + StorageType::Int64)); + //all_types.push_back(pair_type("A_UINT64", + // StorageType::UInt64)); // SQLite problems + all_types.push_back(pair_type("A_FLOAT", + StorageType::Float)); + all_types.push_back(pair_type("A_DOUBLE", + StorageType::Double)); + all_types.push_back(pair_type("A_STRING255", + StorageType::String255)); + all_types.push_back(pair_type("A_STRING4K", + StorageType::String4k)); + all_types.push_back(pair_type("A_STRING64K", + StorageType::String64k)); + all_types.push_back(pair_type("A_STRING16M", + StorageType::String16M)); + all_types.push_back(pair_type("A_BLOB64K", + StorageType::Blob64k)); + all_types.push_back(pair_type("A_BLOB16M", + StorageType::Blob16M)); + + RecordSpecification spec; + std::vector<pair_type>::iterator i; + for(i = all_types.begin(); i != all_types.end(); ++i ){ + spec.extend(i->first,i->second); + } + IFolderPtr folder = ralDb->createFolder( "/myfolder", spec ); + CPPUNIT_ASSERT( folder.get() != 0 ); + + // Store some data into the IOV table + coral::AttributeList payload1 = Record( spec ).attributeList(); + payload1[ "A_BOOL" ].data<Bool>() = false; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "false=0", false, payload1["A_BOOL"].data<Bool>()); + //payload1[ "A_CHAR" ] + // .setValue<char>( 'a' ); // THIS MUST BE CHARACTER DATA + // .setValue<char>( CHAR_MIN ); // -128 (if signed) + payload1[ "A_UCHAR" ].data<UChar>() = 0; + payload1[ "A_INT16" ].data<Int16>() = Int16Min; // -32768 + payload1[ "A_UINT16" ].data<UInt16>() = 0; + payload1[ "A_INT32" ].data<Int32>() = Int32Min; // -2147483648 + payload1[ "A_UINT32" ].data<UInt32>() = 0; + payload1[ "A_UINT63" ].data<UInt63>() = 0; + payload1[ "A_INT64" ].data<Int64>() = Int64Min; // -9223372036854775808: OCI-22053! + //payload1[ "A_UINT64" ].data<UInt64>() = 0; + payload1[ "A_FLOAT" ].data<Float>() = (Float)0.123456789012345678901234567890; + payload1[ "A_DOUBLE" ].data<Double>() = 0.123456789012345678901234567890; + payload1[ "A_STRING255" ].data<String255>() = "low values"; + payload1[ "A_STRING4K" ].data<String4k>() = "low values"; + payload1[ "A_STRING64K" ].data<String64k>() = "low values"; + payload1[ "A_STRING16M" ].data<String16M>() = "low values"; + payload1[ "A_BLOB64K" ].data<Blob64k>().resize(100); + payload1[ "A_BLOB16M" ].data<Blob16M>().resize(100); + unsigned char * ptr64k = static_cast<unsigned char *> + (payload1[ "A_BLOB64K" ].data<Blob64k>().startingAddress()); + for ( int i = 0 ; i < 100; ++i ) ptr64k[i] = 0; + unsigned char * ptr16M = static_cast<unsigned char *> + (payload1[ "A_BLOB16M" ].data<Blob16M>().startingAddress()); + for ( int i = 0 ; i < 100; ++i ) ptr16M[i] = 0; + folder->storeObject( 5, 15, payload1, 0 ); + + // Store some data into the IOV table + coral::AttributeList payload2 = Record( spec ).attributeList(); + payload2[ "A_BOOL" ].data<Bool>() = true; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "false=0", true, payload2["A_BOOL"].data<Bool>()); + //payload2[ "A_CHAR" ] + // .setValue<char>( 'Z' ); // THIS MUST BE CHARACTER DATA + // .setValue<char>( CHAR_MAX ); // -128 (if signed) + payload2[ "A_UCHAR" ].data<UChar>() = UCHAR_MAX; // 255 + payload2[ "A_INT16" ].data<Int16>() = Int16Max; // 32767 + payload2[ "A_UINT16" ].data<UInt16>() = UInt16Max; // 65535 + payload2[ "A_INT32" ].data<Int32>() = Int32Max; // 2147483647 + payload2[ "A_UINT32" ].data<UInt32>() = UInt32Max; // 4294967295 + payload2[ "A_UINT63" ].data<UInt63>() = Int64Max; // 9223372036854775807 + payload2[ "A_INT64" ].data<Int64>() = Int64Max; // 9223372036854775807 + //payload2[ "A_UINT64" ].data<UInt64>() = UInt64Max; // 18446744073709551615 + payload2[ "A_FLOAT" ].data<Float>() = (Float)0.987654321098765432109876543210; + payload2[ "A_DOUBLE" ].data<Double>() = 0.987654321098765432109876543210; + payload2[ "A_STRING255" ].data<String255>() = "HIGH VALUES"; + payload2[ "A_STRING4K" ].data<String4k>() = "HIGH VALUES"; + payload2[ "A_STRING64K" ].data<String64k>() = "HIGH VALUES"; + payload2[ "A_STRING16M" ].data<String16M>() = "HIGH VALUES"; + payload2[ "A_BLOB64K" ].data<Blob64k>().resize(100); + payload2[ "A_BLOB16M" ].data<Blob16M>().resize(100); + ptr64k = static_cast<unsigned char *> + (payload2[ "A_BLOB64K" ].data<Blob64k>().startingAddress()); + for ( int i = 0 ; i < 100; ++i ) ptr64k[i] = 0xff; + ptr16M = static_cast<unsigned char *> + (payload2[ "A_BLOB16M" ].data<Blob16M>().startingAddress()); + for ( int i = 0 ; i < 100; ++i ) ptr16M[i] = 0xff; + folder->storeObject( 15, 25, payload2, 0 ); + + // Retrieve back the two objects + IObjectPtr obj1 = folder->findObject( 10, 0 ); + CPPUNIT_ASSERT_MESSAGE( "retrieved object 1", obj1.get() != 0 ); + IObjectPtr obj2 = folder->findObject( 20, 0 ); + CPPUNIT_ASSERT_MESSAGE( "retrieved object 2", obj2.get() != 0 ); + + // Printout for bool + if ( false ) { + std::cout << "Payload1 IN -> " + << payload1["A_BOOL"].data<Bool>() << std::endl; + std::cout << "Payload1 OUT -> " + << obj1->payload()["A_BOOL"].data<Bool>() << std::endl; + std::cout << "Payload2 IN -> " + << payload2["A_BOOL"].data<Bool>() << std::endl; + std::cout << "Payload2 OUT -> " + << obj2->payload()["A_BOOL"].data<Bool>() << std::endl; + } + + // Printout for unsigned char + if ( false ) { + UChar u1in = payload1["A_UCHAR"].data<UChar>(); + UChar u1out = obj1->payload()["A_UCHAR"].data<UChar>(); + UChar u2in = payload2["A_UCHAR"].data<UChar>(); + UChar u2out = obj2->payload()["A_UCHAR"].data<UChar>(); + std::cout << "Payload1 IN -> " << u1in << std::endl; + std::cout << "Payload1 OUT -> " << u1out << std::endl; + std::cout << "Payload2 IN -> " << u2in << std::endl; + std::cout << "Payload2 OUT -> " << u2out << std::endl; + std::cout << "Payload1 IN (int) -> " << (int)u1in << std::endl; + std::cout << "Payload1 OUT (int) -> " << (int)u1out << std::endl; + std::cout << "Payload2 IN (int) -> " << (int)u2in << std::endl; + std::cout << "Payload2 OUT (int) -> " << (int)u2out << std::endl; + } + + // Printout for floats and doubles + if ( false ) { + Float f_in = payload1["A_FLOAT"].data<Float>(); + Double d_in = payload1["A_DOUBLE"].data<Double>(); + Float f_out = obj1->payload()["A_FLOAT"].data<Float>(); + Double d_out = obj1->payload()["A_DOUBLE"].data<Double>(); + int p = std::cout.precision(); + std::cout.precision(30); + std::cout << "float1 IN -> " << f_in << std::endl; + std::cout << "float1 OUT -> " << f_out << std::endl; + std::cout << "double1 IN -> " << d_in << std::endl; + std::cout << "double1 OUT -> " << d_out << std::endl; + std::cout.precision(p); + } + + // Compare the input payload to the retrieved payload for object 1 and 2 + for ( unsigned int i=0; i<spec.size(); i++ ) + { + const IFieldSpecification& fldSpec = spec[i]; + std::string val1_in,val2_in; + std::string val1_out,val2_out; + + // Special treatment for floats: compare with 6 digit precision + // TEMPORARY! You should be able to use higher precision! + if ( fldSpec.storageType() == StorageType::Float ) { + unsigned long fPrec = 6; + Float f_in = payload1[ fldSpec.name() ].data<Float>(); + Float f_out = obj1->payload()[ fldSpec.name() ].data<Float>(); + std::ostringstream s1_in, s1_out; + s1_in.precision(fPrec); + s1_out.precision(fPrec); + s1_in << f_in; + s1_out << f_out; + val1_in = s1_in.str(); + val1_out = s1_out.str(); + + f_in = payload2[ fldSpec.name() ].data<Float>(); + f_out = obj2->payload()[ fldSpec.name() ].data<Float>(); + std::ostringstream s2_in, s2_out; + s2_in.precision(fPrec); + s2_out.precision(fPrec); + s2_in << f_in; + s2_out << f_out; + val2_in = s2_in.str(); + val2_out = s2_out.str(); + } + + // Special treatment for doubles: compare with 15 digit precision + // TEMPORARY! You should be able to use higher precision! + else if ( fldSpec.storageType() == StorageType::Double ) { + unsigned long dPrec = 15; + Double d_in = payload1[ fldSpec.name() ].data<Double>(); + Double d_out = obj1->payload()[ fldSpec.name() ].data<Double>(); + std::ostringstream s1_in,s1_out; + s1_in.precision(dPrec); + s1_out.precision(dPrec); + s1_in << d_in; + s1_out << d_out; + val1_in = s1_in.str(); + val1_out = s1_out.str(); + + d_in = payload2[ fldSpec.name() ].data<Double>(); + d_out = obj2->payload()[ fldSpec.name() ].data<Double>(); + std::ostringstream s2_in,s2_out; + s2_in.precision(dPrec); + s2_out.precision(dPrec); + s2_in << d_in; + s2_out << d_out; + val2_in = s2_in.str(); + val2_out = s2_out.str(); + } + + else if ( fldSpec.storageType() == StorageType::Blob64k ) { + // use native comparison for blobs + payload1[ fldSpec.name() ].data<Blob64k>() == + payload2[ fldSpec.name() ].data<Blob64k>(); + } + + else if ( fldSpec.storageType() == StorageType::Blob16M ) { + // use native comparison for blobs + payload1[ fldSpec.name() ].data<Blob16M>() == + payload2[ fldSpec.name() ].data<Blob16M>(); + } + + // Default treatment for all but floats and doubles: compare as strings + else + { + val1_in = toString( payload1[ fldSpec.name() ] ); + val1_out = toString( obj1->payload()[ fldSpec.name() ].attribute() ); + val2_in = toString( payload2[ fldSpec.name() ] ); + val2_out = toString( obj2->payload()[ fldSpec.name() ].attribute() ); + } + + // Compare expected and actual values + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string( "payload1 ['" ) + + fldSpec.name() + "'] of type '" + + fldSpec.storageType().name() + "'", + val1_in, val1_out ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string( "payload2 ['" ) + + fldSpec.name() + "'] of type '" + + fldSpec.storageType().name() + "'", + val2_in, val2_out ); + } + + } catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } catch ( ... ) { + std::cout << "UNKNOWN exception caught!" << std::endl; + throw; + } + + } + + /// Tests creation of a folder with a vector column - should fail + /// PORT: This test used to throw a RelationalTypeConverterInvalidCppType + /// exception from 'createFolder'. However in CORAL, Token is not a + /// supported type and spec->extend( "A_VECTOR", "vector<string>" ) already + /// throws an exception. + /// Marco: With the new RecordSpecification, it is impossible to us an unsupported type +// void test_unsupportedTypesVector() { +// boost::shared_ptr<coral::AttributeListSpecification> +// spec( new coral::AttributeListSpecification(), releaser() ); +// spec->extend( "A_VECTOR", "vector<string>" ); +// IFolderPtr folder = ralDb->createFolder( "/myfolder", *spec ); +// } + + + /// Tests creation of a folder with a Token column - should fail + /// PORT: This test used to throw a RelationalTypeConverterInvalidCppType + /// exception from 'createFolder'. However in CORAL, Token is not a + /// supported type and spec->extend( "A_TOKEN", "Token" ) already throws + /// an exception. + /// Marco: With the new RecordSpecification, it is impossible to us an unsupported type +// void test_unsupportedTypesToken() { +// boost::shared_ptr<coral::AttributeListSpecification> +// spec( new coral::AttributeListSpecification(), releaser() ); +// spec->extend( "A_TOKEN", "Token" ); +// IFolderPtr folder = ralDb->createFolder( "/myfolder", *spec ); +// } + + /// Tests creation of a folder with a long long column - should fail + /// Marco: With the new RecordSpecification, it is impossible to us an unsupported type +// void test_unsupportedTypesLongLong() { +// boost::shared_ptr<coral::AttributeListSpecification> +// spec( new coral::AttributeListSpecification(), releaser() ); +// spec->extend( "A_LONGLONG", "long long" ); +// try { +// IFolderPtr folder = ralDb->createFolder( "/myfolder", *spec ); +// } catch ( std::exception& /*e*/ ) { +// //std::cout << "Exception caught: '" << e.what() << "'" << std::endl; +// throw; +// } +// } + + /// Tests creation of a folder with a char column - should fail + /// Marco: With the new RecordSpecification, it is impossible to us an unsupported type +// void test_unsupportedTypesChar() { +// boost::shared_ptr<coral::AttributeListSpecification> +// spec( new coral::AttributeListSpecification(), releaser() ); +// spec->extend( "A_CHAR", "char" ); +// try { +// IFolderPtr folder = ralDb->createFolder( "/myfolder", *spec ); +// } catch ( std::exception& /*e*/ ) { +// //std::cout << "Exception caught: '" << e.what() << "'" << std::endl; +// throw; +// } +// } + + + /// Tests creation of a folder with a Token column - should fail + /// Marco: With the new RecordSpecification, it is impossible to us an unsupported type +// void test_unsupportedTypesLongDouble() { +// boost::shared_ptr<coral::AttributeListSpecification> +// spec( new coral::AttributeListSpecification(), releaser() ); +// spec->extend( "A_LONGDOUBLE", "long double" ); +// try { +// IFolderPtr folder = ralDb->createFolder( "/myfolder", *spec ); +// } catch ( std::exception& /*e*/ ) { +// //std::cout << "Exception caught: '" << e.what() << "'" << std::endl; +// throw; +// } +// } + + + /// Tests that storing a UInt63 larger than 2^63-1 fails + /// (default for both IOV boundaries and user payload UInt63) + void test_default_UInt63() { + RecordSpecification spec; + std::string attrName = "UInt63"; + StorageType::TypeId attrType = StorageType::UInt63; + spec.extend( attrName, attrType ); + IFolderPtr folder = db->createFolder( "/myfolder", spec ); + // Insert an object with uInt64=2^63-1: this should not throw + coral::AttributeList payload = Record( spec ).attributeList(); + UInt63 attrValue = Int64Max; + payload[ attrName ].data<UInt63>() = attrValue; + folder->storeObject( 0, 1, payload, 0 ); + // Insert an object with uInt64=2^63: this should throw + attrValue = (UInt63)Int64Max+1; + payload[ attrName ].setValue( attrValue ); + CPPUNIT_ASSERT_THROW( folder->storeObject( 1, 2, payload, 0 ), + StorageTypeInvalidValue ); +// std::string msg; +// try { +// std::string attrHint = +// RelationalTypeConverter::defaultUserPayloadHintForCppType( attrType ); +// RelationalTypeConverterInvalidCppValue e0 +// ( payload[attrName], attrHint, "" ); +// msg = e0.what(); +// folder->storeObject( 1, 2, payload, 0 ); +// } catch ( StorageTypeInvalidValue &e ) { +// std::cout << "Exception caught: '" << e.what() << "'" << std::endl; +// CPPUNIT_ASSERT_EQUAL_MESSAGE +// ( "exception error message", msg, std::string( e.what() ) ); +// throw; +// } + } + + + /// Tests creation of a folder with non-default maximum string length of 255 + /// (default has been changed to 4000 for user payload strings) + /// Tests that storing a string of 300 characters fails + void test_extSpec_string255() { + // Create payload specification + RecordSpecification spec; + std::string attrName = "S"; + StorageType::TypeId attrType = StorageType::String255; + spec.extend( attrName, attrType ); + // Create folder with extended payload specification + IFolderPtr folder = ralDb->createFolder( "/myfolder", spec ); + CPPUNIT_ASSERT( folder.get() != 0 ); + // Insert an object with 300 characters: this should throw + coral::AttributeList payload = Record( spec ).attributeList(); + payload[ attrName ].data<String255>() = std::string(300,'x'); + CPPUNIT_ASSERT_THROW( folder->storeObject( 0, 1, payload, 0 ), + StorageTypeInvalidValue ); +// std::string msg; +// try { +// RelationalTypeConverterInvalidCppValue e0 +// ( payload[attrName], attrHint, "" ); +// msg = e0.what(); +// folder->storeObject( 0, 1, payload, 0 ); +// } catch ( RelationalTypeConverterInvalidCppValue& e ) { +// CPPUNIT_ASSERT_EQUAL_MESSAGE +// ( "exception error message", msg, std::string( e.what() ) ); +// throw; +// } + } + + /// Tests creation of a folder with four string columns of all supported + /// maximum lengths (255, 4K, 64K, 16M) using the private API + void test_extSpec_allStrings() { + // Create extended payload specification + typedef std::pair<std::string,StorageType::TypeId> pair_type; + std::vector<pair_type> all_types; + all_types.push_back + (pair_type ("A_STRING255", StorageType::String255 ) ); + all_types.push_back + (pair_type ("A_STRING4K", StorageType::String4k ) ); + all_types.push_back + (pair_type ("A_STRING64K", StorageType::String64k ) ); + all_types.push_back + (pair_type ("A_STRING16M", StorageType::String16M ) ); + RecordSpecification spec; + std::vector<pair_type>::iterator i; + for(i = all_types.begin(); i != all_types.end(); ++i ){ + spec.extend(i->first,i->second); + } + IFolderPtr folder = ralDb->createFolder( "/myfolder", spec ); + CPPUNIT_ASSERT( folder.get() != 0 ); + + coral::AttributeList payload = Record( spec ).attributeList(); + for(i = all_types.begin(); i != all_types.end(); ++i ){ + payload[i->first].data<std::string>() = + std::string(StorageType::storageType(i->second).maxSize(),'x'); + } + folder->storeObject( 0, 100, payload, 0 ); + // Retrieve IOVS from the folder + //std::cout << "MARCO: get object" << std::endl; + IObjectPtr obj = folder->findObject( 10, 0 ); + for(i = all_types.begin(); i != all_types.end(); ++i ){ + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Wrong number of char retrieved", + StorageType::storageType(i->second).maxSize(), + obj->payload()[i->first].data<std::string>().size() ); + } + } + + /// Tests that storing a string longer than 4000 characters fails, + /// while storing a 300 character string succeeds + /// (default has been changed to 4000 for user payload strings) + void test_default_string4000() { + RecordSpecification spec; + std::string attrName = "S"; + StorageType::TypeId attrType = StorageType::String4k; + spec.extend( attrName, attrType ); + IFolderPtr folder = db->createFolder( "/myfolder", spec ); + // Insert an object with 300 characters: this should not throw + coral::AttributeList payload = Record( spec ).attributeList(); + payload[ attrName ].data<std::string>() = std::string(300,'x'); + folder->storeObject( 0, 1, payload, 0 ); + // Insert an object with 5000 characters: this should throw + payload[ attrName ].data<std::string>() = std::string(5000,'x'); + CPPUNIT_ASSERT_THROW( folder->storeObject( 1, 2, payload, 0 ), + StorageTypeInvalidValue ); +// std::string msg; +// try { +// std::string attrHint = +// RelationalTypeConverter::defaultUserPayloadHintForCppType( attrType ); +// RelationalTypeConverterInvalidCppValue e0 +// ( payload[attrName], attrHint, "" ); +// msg = e0.what(); +// folder->storeObject( 1, 2, payload, 0 ); +// } catch ( RelationalTypeConverterInvalidCppValue& e ) { +// CPPUNIT_ASSERT_EQUAL_MESSAGE +// ( "exception error message", msg, std::string( e.what() ) ); +// throw; +// } + } + + + /// Tests that storing a specification with a string representation + /// 65535 characters long always succeeds. + /// Note that the new constraints (<=900 fields with names <=30 characters) + /// imply that the longest description that can be built is only + /// 900*(30+1+9)+899*1=36899 characters ("name:String64k,name:String64k...). + /// This test actually tests that this payload specification can be used. + void test_payloadSpecDescription() + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "PANIC! Unexpected folder payload description maxSize (hint)", + StorageType::String64k, + RelationalNodeTable::columnTypeIds::folderPayloadSpecDesc ); + RecordSpecification spec; + for ( int i = 0; i < 900; ++i ) { + std::stringstream s; + s << "S1234567890123456789012345" << i+1000; + spec.extend( s.str(), StorageType::String64k ); + } + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Payload description size", + (size_t)36899, + RelationalDatabase::encodeRecordSpecification( spec ).size() ); + IFolderPtr folder = db->createFolder( "/myfolder", spec ); + CPPUNIT_ASSERT( folder.get() != 0 ); + } + + + /// Tests that storing a specification with over 900 columns fails + void test_payloadSpecTooManyFields() + { + RecordSpecification spec; + for ( int i = 0; i < 900; ++i ) { + std::stringstream s; + s << "S" << i; + spec.extend( s.str(), StorageType::String4k ); + } + db->createFolder( "/myfolder900", spec ); + { + int i = 900; + std::stringstream s; + s << "S" << i; + spec.extend( s.str(), StorageType::String4k ); + } + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfolder901", spec ), + PayloadSpecificationTooManyFields ); + } + + + /// Tests that storing a specification with over 10 blob columns fails + void test_payloadSpecTooManyBlobFields() + { + RecordSpecification spec; + for ( int i = 0; i < 10; ++i ) { + std::stringstream s; + s << "B" << i; + spec.extend( s.str(), StorageType::Blob64k ); + } + db->createFolder( "/myfolder10blob", spec ); + { + int i = 11; + std::stringstream s; + s << "B" << i; + //spec.extend( s.str(), StorageType::Blob64k ); + spec.extend( s.str(), StorageType::Blob16M ); + } + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfolder11blob", spec ), + PayloadSpecificationTooManyBlobFields ); + } + + + /// Test for bug #24646: storing a specification with over 8000 bytes fails + /// (where each long VARCHAR, TEXT or BLOB counts for 768 bytes) + void test_payloadSpecOver8000Bytes() + { + { + // This succeeds on all backends + RecordSpecification spec; + for ( int i = 0; i < 10; ++i ) + { + std::stringstream s; + s << "CLOB" << i; + spec.extend( s.str(), StorageType::String64k ); + } + IFolderPtr folder = db->createFolder( "/myfolder10clob", spec ); + Record record( spec ); + std::string value = std::string( 1000, 'x' ); + for ( int i = 0; i < 10; ++i ) + { + std::stringstream s; + s << "CLOB" << i; + record[s.str()].setValue( value ); + } + folder->storeObject( 0, 10, record, 0 ); + } + if ( ralDb->sessionMgr()->databaseTechnology() == "MySQL" ) + { + std::cout << std::endl + << "WARNING: '8000 bytes' test disabled for MySQL (bug #24646)" + << std::endl; + } + else + { + // This fails on MySQL (total size is 11*768>8000) with + // "MySQL errno:1030: Got error 139 from storage engine" + RecordSpecification spec; + for ( int i = 0; i < 11; ++i ) + { + std::stringstream s; + s << "CLOB" << i; + spec.extend( s.str(), StorageType::String64k ); + } + IFolderPtr folder = db->createFolder( "/myfolder11clob", spec ); + Record record( spec ); + std::string value = std::string( 1000, 'x' ); + for ( int i = 0; i < 11; ++i ) + { + std::stringstream s; + s << "CLOB" << i; + record[s.str()].setValue( value ); + } + folder->storeObject( 0, 10, record, 0 ); + } + } + + + /// Tests that storing a specification with over 200 string255 columns fails + void test_payloadSpecTooManyString255Fields() + { + RecordSpecification spec; + // Total size on MySQL is 65535 = 257*255 -> at most 257 (user+sys) fields. + // IOV table has two String255 internal columns -> at most 255 user fields. + // But 65535 also includes all numeric fields -> COOL limit is 200. + for ( int i = 0; i < 200; ++i ) { + std::stringstream s; + s << "S" << i; + spec.extend( s.str(), StorageType::String255 ); + } + // Assume long long (BIGINT) are the largest non-VARCHAR (8 bytes) + // See http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html + for ( int i = 0; i < 699; ++i ) { + std::stringstream s; + s << "I" << i; + spec.extend( s.str(), StorageType::Int64 ); + } + db->createFolder( "/myfolder200String255", spec ); + { + int i = 200; + std::stringstream s; + s << "S" << i; + spec.extend( s.str(), StorageType::String255 ); + } + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfolder201String255", spec ), + PayloadSpecificationTooManyString255Fields ); + } + + + /// Tests that storing a specification with invalid field names fails. + void test_payloadSpecInvalidFieldName() + { + // Test that a field name of size 30 succeeds, of size 31 fails + { + RecordSpecification spec; + spec.extend( "S12345678901234567890123456789", StorageType::String255 ); + db->createFolder( "/myfolder", spec ); + spec.extend( "S123456789012345678901234567890", StorageType::String255 ); + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfoldernew", spec ), + PayloadSpecificationInvalidFieldName ); + } + // Test that a field name of size 0 fails + { + RecordSpecification spec; + try { + spec.extend( "", StorageType::String255 ); + CPPUNIT_FAIL( "Creating a field spec with name '' should fail" ); + } catch ( FieldSpecificationInvalidName& ) {} + } + // Test that a field name containing the '-' sign fails + { + RecordSpecification spec; + spec.extend( "is-a", StorageType::String255 ); + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfoldernew", spec ), + PayloadSpecificationInvalidFieldName ); + } + // Test that a field name starting with the '_' sign fails + { + RecordSpecification spec; + spec.extend( "_payload", StorageType::String255 ); + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfoldernew", spec ), + PayloadSpecificationInvalidFieldName ); + } + // Test that a field name starting with a digit fails + { + RecordSpecification spec; + spec.extend( "1payload", StorageType::String255 ); + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfoldernew", spec ), + PayloadSpecificationInvalidFieldName ); + } + // Test that a field name starting with "COOL_" fails + { + RecordSpecification spec; + spec.extend( "COOL_payload", StorageType::String255 ); + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfoldernew", spec ), + PayloadSpecificationInvalidFieldName ); + } + // Test that a field name starting with "cool_" fails + { + RecordSpecification spec; + spec.extend( "cool_payload", StorageType::String255 ); + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfoldernew", spec ), + PayloadSpecificationInvalidFieldName ); + } + // Test that a field name starting with "Cool_" fails + { + RecordSpecification spec; + spec.extend( "Cool_Payload", StorageType::String255 ); + CPPUNIT_ASSERT_THROW( db->createFolder( "/myfoldernew", spec ), + PayloadSpecificationInvalidFieldName ); + } + } + + + /// Tests storing and retrieving empty strings + void test_emptyString() + { + std::string name = "A_STRING255"; + FolderSpecification spec; + spec.payloadSpecification().extend + ( name, StorageType::String255 ); + IFolderPtr folder = ralDb->createFolder( "/myfolder", spec ); + CPPUNIT_ASSERT( folder.get() != 0 ); + Record record( spec.payloadSpecification() ); + // Store value at 0 = "" + std::string value = ""; + record[name].setValue( value ); + folder->storeObject( 0, 10, record, 0 ); + // Store value at 10 = NULL + record[name].setNull(); + folder->storeObject( 10, 20, record, 0 ); + // Retrieve value at 0 = "" + { + IObjectPtr obj = folder->findObject( 0, 0 ); + const IField& fld = obj->payload()[name]; + // This would succeed if setValue("") actually sets the value to NULL (2) + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "Empty string - should be null (new IField!)", + // true, fld.isNull() ); + // This used to fail on Oracle when "" and NULL were different (1) + // This now succeeds on all 3 dbs: setNull() sets the value to "" (3) + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Empty string - should be not null", + false, fld.isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Empty string - size should be 0", + (size_t)0, fld.data<std::string>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Empty string - value should be \"\"", + std::string(""), fld.data<std::string>() ); + } + // Retrieve value at 10 = NULL + { + IObjectPtr obj = folder->findObject( 10, 0 ); + const IField& fld = obj->payload()[name]; + // This used to succeed on all 3 dbs when "" and NULL were different (1) + // This would succeed if setValue("") actually sets the value to NULL (2) + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "Null string - should be null", + // true, fld.isNull() ); + // This now succeeds on all 3 dbs: setNull() sets the value to "" (3) + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Null string - on readback, should be not null", + false, fld.isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Null string - on readback, size should be 0", + (size_t)0, fld.data<std::string>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Null string - on readback, value should be \"\"", + std::string(""), fld.data<std::string>() ); + } + } + + /// Tests storing and retrieving std strings containing the \0 character + /// This fails on all three backends! + /// Note that it also fails on Benthic (but not on sqlplus). + void test_nullCharInString() + { + std::string name = "A_STRING255"; + FolderSpecification spec; + spec.payloadSpecification().extend + ( name, StorageType::String255 ); + IFolderPtr folder = ralDb->createFolder( "/myfolder", spec ); + CPPUNIT_ASSERT( folder.get() != 0 ); + Record record( spec.payloadSpecification() ); + std::string value = ""; + for ( int i=0; i<10; i++ ){ + value += 'A'; + value += '\x00'; + value += 'Z'; + } + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Input value size", + (size_t)30, value.size() ); + try { + record[name].setValue( value ); + CPPUNIT_FAIL( "setValue should fail" ); + } + catch ( StorageTypeStringContainsNullChar& ) {} + catch ( ... ) { + CPPUNIT_FAIL + ( "Wrong exception: expected StorageTypeStringContainsNullChar" ); + } + /* + record[name].setValue( value ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Input field size", + (size_t)30, record[name].data<std::string>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Input field - compare to input value", + value, record[name].data<std::string>() ); + folder->storeObject( 0, 10, record, 0 ); + IObjectPtr obj = folder->findObject( 0, 0 ); + const IField& fld = obj->payload()[name]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Fetched string - should be not null", + false, fld.isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Fetched string - size should be 30", + (size_t)30, fld.data<std::string>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Fetched string - compare to input value", + value, fld.data<std::string>() ); + */ + } + + + /// Tests storing and reading back a BLOB64K longer than 65535 characters. + /// This should fail on MySQL (the BLOB64K SQL type has that limit). + void test_blob64kOver64k() { + RecordSpecification spec; + std::string name = "B"; + StorageType::TypeId attrType = StorageType::Blob64k; + spec.extend( name, attrType ); + IFolderPtr folder = db->createFolder( "/myfolder", spec ); + // Insert a BLOB64K with 65536 bytes or more + int numberOfElements = 65536 / sizeof(float); + if ( 65536 % sizeof(float) != 0 ) numberOfElements++; + Blob64k blob( numberOfElements * sizeof(float) ); + float* addressToElement = static_cast< float* >( blob.startingAddress() ); + for ( int i = 0; i < numberOfElements; ++i, ++addressToElement ) { + *addressToElement = static_cast<float>(i + 0.01); + } + Record record( spec ); + /* + record[name].setValue( blob ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Input field - should be not null", + false, record[name].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Input field size", + blob.size(), record[name].data<Blob64k>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Input field - compare to input value", + true, blob == record[name].data<Blob64k>() ); + folder->storeObject( 0, 1, record, 0 ); + IObjectPtr obj = folder->findObject( 0, 0 ); + const IField& fld = obj->payload()[name]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Fetched field - should be not null", + false, fld.isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Fetched field size", + blob.size(), fld.data<Blob64k>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Fetched field - compare to input value", + true, blob == fld.data<Blob64k>() ); + */ + try { + record[name].setValue( blob ); + CPPUNIT_FAIL( "setValue should fail" ); + } + catch ( StorageTypeBlobTooLong& ) {} + catch ( ... ) { + CPPUNIT_FAIL + ( "Wrong exception: expected StorageTypeBlobTooLong" ); + } + } + + + /// Tests storing and reading back a BLOB16M longer than 65535 characters. + /// This should succeed on all platforms. + void test_blob16MOver64k() { + RecordSpecification spec; + std::string name = "B"; + StorageType::TypeId attrType = StorageType::Blob16M; + spec.extend( name, attrType ); + IFolderPtr folder = db->createFolder( "/myfolder", spec ); + // Insert a BLOB16M with 65536 bytes or more + int numberOfElements = 65536 / sizeof(float); + if ( 65536 % sizeof(float) != 0 ) numberOfElements++; + Blob16M blob( numberOfElements * sizeof(float) ); + float* addressToElement = static_cast< float* >( blob.startingAddress() ); + for ( int i = 0; i < numberOfElements; ++i, ++addressToElement ) { + *addressToElement = static_cast< float >( i + 0.01 ); + } + Record record( spec ); + record[name].setValue( blob ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Input field - should be not null", + false, record[name].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Input field size", + blob.size(), record[name].data<Blob16M>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Input field - compare to input value", + true, blob == record[name].data<Blob16M>() ); + folder->storeObject( 0, 1, record, 0 ); + IObjectPtr obj = folder->findObject( 0, 0 ); + const IField& fld = obj->payload()[name]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Fetched field - should be not null", + false, fld.isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Fetched field size", + blob.size(), fld.data<Blob16M>().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Fetched field - compare to input value", + true, blob == fld.data<Blob16M>() ); + /* + try { + record[name].setValue( blob ); + CPPUNIT_FAIL( "setValue should fail" ); + } + catch ( StorageTypeBlobTooLong& ) {} + catch ( ... ) { + CPPUNIT_FAIL + ( "Wrong exception: expected StorageTypeBlobTooLong" ); + } + */ + } + + + /// Tests storing and retrieving empty blobs + /// This used to fail for SQLite (bug #22485 aka bug #30036) + void test_emptyBlob() + { + std::string name = "A_BLOB"; + FolderSpecification spec; + spec.payloadSpecification().extend + ( name, StorageType::Blob64k ); + IFolderPtr folder = ralDb->createFolder( "/myfolder", spec ); + CPPUNIT_ASSERT( folder.get() != 0 ); + Record record( spec.payloadSpecification() ); + // Insert value at 0 = BLOB with 0 bytes + Blob64k value( 0 ); + record[name].setValue( value ); + folder->storeObject( 0, 10, record, 0 ); + // Insert value at 10 = NULL BLOB + record[name].setNull(); + folder->storeObject( 10, 20, record, 0 ); + // Retrieve value at 0 = BLOB with 0 bytes + { + IObjectPtr obj = folder->findObject( 0, 0 ); + const IField& fld = obj->payload()[name]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Empty blob - should be not null", + false, fld.isNull() ); // Used to fail for sqlite (bug #22485) + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Empty blob - size should be 0", + (long int)0, (long int)fld.data<Blob64k>().size() ); + } + // Retrieve value at 10 = NULL BLOB + { + IObjectPtr obj = folder->findObject( 10, 0 ); + const IField& fld = obj->payload()[name]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Null blob - should be null", + true, fld.isNull() ); + } + } + + + /// Creates a dummy payload AttributeList for a given index + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + std::string toString( const coral::Attribute& a ) + { + std::stringstream s; + const bool valueOnly = true; + a.toOutputStream( s, valueOnly ); + return s.str(); + } + + void setUp() { + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + ralDb = dynamic_cast<RalDatabase*>(db.get()); + } catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } catch ( ... ) { + std::cout << "UNKNOWN exception caught!" << std::endl; + throw; + } + } + + void tearDown() { + db.reset(); + // Here I want to purge the connection pool + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + RalDatabaseSvc* rdbSvc = dynamic_cast<RalDatabaseSvc*>(&dbSvc); + rdbSvc->connectionSvc().configuration().setConnectionTimeOut(-1); + rdbSvc->connectionSvc().purgeConnectionPool(); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( cool::RalDatabaseTest_extendedSpec ); + +//----------------------------------------------------------------------------- + +// Include CppUnit test driver +#include <CppUnit_testdriver.icpp> + + diff --git a/RelationalCool/tests/RalDatabase_versioning/README.segmentationFault b/RelationalCool/tests/RalDatabase_versioning/README.segmentationFault new file mode 100644 index 000000000..4849953c8 --- /dev/null +++ b/RelationalCool/tests/RalDatabase_versioning/README.segmentationFault @@ -0,0 +1,653 @@ +20.03.2005 - COOL_0_1_1-pre2 + +Tried to run the full RalDatabase_versioning test with the previously +chosen configuration (COOL debug, COOL with pthread, POOL nodebug). +I continue to observe problems (mutex locks hanging). +I also have the impression (again..) that the problems take place in +different points of the program depending on whether Debug is on or off. + +=> I take a more radical approach: use the POOL debug libraries also +for rh73_gcc32 and rh73_gcc323 (while keeping COOL debug and pthread). +This seems to solve the problem (all 51 tests pass on Oracle). +I tag this configuration as COOL_0_1_1-pre2. + +All unit tests included in execUnitTests (i.e., RalDatabase_versioning +and others) now pass for both Oracle and MySQL on all of rh73_gcc323, +rh73_gcc323_dbg, rh73_gcc32, slc3_ia32_gcc323. I can now go on with +further developments (int64, CLOBs). + +I will keep rh73_gcc323 and slc3_ia32_gcc323 as main development platforms. + +19.03.2005 - COOL_0_1_1-pre1 + +[The COOL_0_1_1-pre1 configuration is the default to start my studies. +COOL is in nopthread, nodebug mode, POOL in nodebug mode on rh73_gcc323. +It is the one where I get segmentation faults. +The COOL_0_1_1-pre2 configuration is the one where all tests are fixed.] + +The test_fetchObjectTableRows_5c test is the single +most annoying test I have seen recently. +It has generated one full week of work or even more. + +It has given problems on MySQL, allowing us to fix the following bugs: +- the ODBC bulk inserter was randomly adding '\0' at the end of stored strings +- the order in which bind variables are declared to RAL must be the + same as the order in which they are used in the AttributeList +- %i and not %m is the correct format for minutes +- now() has a second granularity, hence you must sleep at least one second + when testing the status of the database in between two insertions + +It has given problems on Oracle, for which we have workarounds but not +yet the real solution. On Oracle, the problem is heavily dependent +on the operating system and the compiler options used for both POOL +and COOL. The test may work correctly, crash with a segmentation fault +or hang in a mutex lock depending on the compilation options. + +To execute the test: + eval `scram runtime -csh` + setenv COOLTESTDB "oracle://devdb;schema=conddb_test;user=conddb_test;password=PASSWORD;dbname=COOLSEGF" + unitTest_RelationalCool_RalDatabase_versioning + +Standard configuration +POOL: slc3_ia32_gcc323 +COOL: slc3_ia32_gcc323 standard (with -pthread) +==> test OK (the 1st time it is executed) +==> test OK (from the 2nd time onwards) + +Standard configuration +POOL: rh73_gcc323 +COOL: rh73_gcc323 standard (no -pthread - COOL default on RH73) +==> segmentation fault (the 1st time it is executed) - trace #1 +==> hangs in mutex lock (from the 2nd time onwards) - trace #2 + +Change the site/tools-CERN.conf, scram setup, eval `scram runtime -csh` +[Also \rm ~/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so +and scram b to see what happens with a new plugin] +POOL: rh73_gcc323_dbg +COOL: rh73_gcc323 standard (no -pthread - COOL default on RH73) +==> test OK (the 1st time it is executed) +==> test OK (from the 2nd time onwards) + +With pthread +POOL: rh73_gcc323_dbg +COOL: rh73_gcc323 with -pthread (modify BuildFile) +==> hangs in mutex lock (the 1st time it is executed) - trace #3 +==> hangs in mutex lock (from the 2nd time) - similar (not identical) trace + +With pthread +POOL: rh73_gcc323 +COOL: rh73_gcc323 with -pthread (modify BuildFile) +==> hangs in mutex lock (the 1st time it is executed) - another trace +==> hangs in mutex lock (from the 2nd time) - another trace + +With pthread and COOL debug +POOL: rh73_gcc323 +COOL: rh73_gcc323 with -pthread and -g instead of -O2 (modify BuildFile) +==> test OK (the 1st time it is executed) +==> test OK (from the 2nd time onwards) + +With pthread and COOL debug +POOL: rh73_gcc323_dbg +COOL: rh73_gcc323 with -pthread and -g instead of -O2 (modify BuildFile) +==> test OK (the 1st time it is executed) +==> test OK (from the 2nd time onwards) + +With COOL debug without pthread +POOL: rh73_gcc323_dbg +COOL: rh73_gcc323 with -g instead of -O2 (modify BuildFile) +==> test OK (the 1st time it is executed) +==> test OK (from the 2nd time onwards) + +With COOL debug without pthread +POOL: rh73_gcc323 +COOL: rh73_gcc323 with -g instead of -O2 (modify BuildFile) +==> segmentation fault (the 1st time it is executed) - trace #4 +==> hangs in mutex lock (from the 2nd time onwards) - trace #5 + +SUMMARY +======= + +POOL COOL COOL RESULT +nodbg nopthread nodbg x (segfault + hangs) +nodbg pthread nodbg x (hangs) +nodbg nopthread dbg x (segfault + hangs) +nodbg pthread dbg OK +dbg nopthread nodbg OK +dbg pthread nodbg x (hangs) +dbg nopthread dbg OK +dbg pthread dbg OK + +For COOL alone: pthread+debug is the only combination that works ok for both +POOL debug and nodebug => use pthread+debug for COOL also in non-debug mode. + +Using POOL debug also helps "save" the situation if pthread is not used. + +This recipe should be cross-checked against MySQL too. +The reason why pthread had been removed in the first place was +a problem in a MyODBC test (can't remember under which circumstances). + setenv COOLTESTDB "mysql://pcitdb59;schema=COOLDB;user=cool;password=PASSWORD;dbname=COOLSEGF" + +Tried it for both POOL debug and nodebug, it works. + +POOL COOL COOL RESULT +nodbg pthread dbg OK +dbg pthread dbg OK + +SOLUTIONS +========= + +- No problem observed for SLC3 + (but cross-checking the POOL code would be useful in any case...) + +- Hack until support for RH73 is discontinued: + use the COOL debug libraries (with pthread) even in non-debug mode + +DETAILS +======= + +Trace #1 +-------- + +The crash happens within the AttributeListSpecification destructor, +called within the OracleQueryWithMultipleTables destructor. + +Note: the crash is avoided (docuble-check this...) if +OracleQueryWithMultipleTables::process() is not called. + +Note: both AttributeList and AttributeListSpecification have only +the default destructors. It may be better (for debug purposes) to +declare them in the .h and implement them empty in the .cpp files. + +Standard configuration +POOL: rh73_gcc323 +COOL: rh73_gcc323 standard (no -pthread - COOL default on RH73) +==> segmentation fault (the 1st time it is executed) - trace #1 +==> hangs in mutex lock (from the 2nd time onwards) - trace #2 + +Here: I may soon crash (seg fault) or hang (mutex lock) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "i"."OBJECT_ID", "i"."CHANNEL_ID", "i"."IOV_SINCE", "i"."IOV_UNTIL", "i"."SYS_INSTIME", "i"."ORIGINAL_ID", "i"."NEW_HEAD_ID", "i"."I", "i"."S", "i"."X" FROM "CONDDB_TEST"."COOLSEGF_F0001_IOVS" "i", "CONDDB_TEST"."COOLSEGF_F0001_IOVS" "o" WHERE :"since" <= "i"."IOV_SINCE" and "i"."IOV_UNTIL" < :"until" and "i"."SYS_INSTIME" <= :"asOfDate1" and "i"."CHANNEL_ID" = :"channel" and ( ( "i"."NEW_HEAD_ID" = :"newHeadId" and "i"."OBJECT_ID" = "o"."OBJECT_ID" ) or ( "i"."NEW_HEAD_ID" = "o"."OBJECT_ID" and "o"."SYS_INSTIME" > :"asOfDate2" ) ) ORDER BY "IOV_SINCE" ASC" + +unitTest_RelationalCool_RalDatabase_versioning (pid=8272 ppid=4571) received fatal signal 11 (Segmentation fault) +signal context: + signo = 11, errno = 0, code = 1 (address not mapped to object) + pid = 2103976551, uid = 135147756 + value = (135147992, 0x80e31d8) + addr = 0x7d682267 + stack = (2, 0, (nil)) + + eip: 0023:40362300 eflags: 00210206 + eax: 7d682267 ebx: 403905b8 ecx: 0805fdc0 edx: 7d682267 + esi: 7d68226f edi: bfffafc0 ebp: bfffafe8 esp: bfffafa0 + ds: 002b es: 002b fs: 0000 ss: 002b + + signal esp: bfffafa0 trap: 14/4 oldmask: 80000000 cr2: 7d682267 + + FPU: control = ffff027f + status = ffff0320 + tag = ffffffff + ip = 0023:4099855e + data = 002b:0810a7c4 + state = 00000320 + %fp0 = [0000:0000000000000000] + %fp1 = [0000:0000000000000000] + %fp2 = [3fdd:7800371b5fe1d0e5] + %fp3 = [3ff6:d000ffff6eff8312] + %fp4 = [0000:0000000000000000] + %fp5 = [0000:0000000000000000] + %fp6 = [3ff6:d000ffff6eff8312] + %fp7 = [3ff6:d000ffff6eff8312] + +stack trace: + 0x4003ef46 _ZN4seal9DebugAids10stacktraceEi + 0x66 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f96a _ZN4seal6Signal9fatalDumpEiP7siginfoPv + 0xda [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f210 _ZN4seal6Signal5fatalEiP7siginfoPv + 0xf0 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x42029180 ? + 0x42029180 [unitTest_RelationalCool_RalDatabase_versioning] + 0x40216f9b _ZNSt6vectorIN4pool22AttributeSpecificationESaIS1_EED1Ev + 0x3b [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x4021781c _ZN5boost6detail20sp_counted_base_implIPN4pool26AttributeListSpecificationENS_15checked_deleterIS3_EEE7disposeEv + 0x2c [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x08054828 _ZN5boost6detail15sp_counted_base7releaseEv + 0x28 [unitTest_RelationalCool_RalDatabase_versioning] + 0x0805489c _ZN5boost6detail12shared_countD1Ev + 0x2c [unitTest_RelationalCool_RalDatabase_versioning] + 0x404062dd _ZN4pool12OracleAccess29OracleQueryWithMultipleTables5resetEv + 0x11d [/afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so] + 0x40405fba _ZN4pool12OracleAccess29OracleQueryWithMultipleTablesD0Ev + 0x2a [/afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so] + 0x401eb8ca _ZN4cool11RalDatabase20fetchObjectTableRowsERKSsRKN4pool26AttributeListSpecificationERKxS8_RKmRKN4seal4TimeE + 0x133a [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x08051a2a _ZN4cool15RalDatabaseTest28test_fetchObjectTableRows_5cEv + 0x122a [unitTest_RelationalCool_RalDatabase_versioning] + 0x08057ead _ZN7CppUnit10TestCallerIN4cool15RalDatabaseTestENS_19NoExceptionExpectedEE7runTestEv + 0x3d [unitTest_RelationalCool_RalDatabase_versioning] + 0x40263cc5 _ZN7CppUnit8TestCase3runEPNS_10TestResultE + 0x45 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026d0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026d0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026d0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026c67a _ZN7CppUnit6TextUi10TestRunner7runTestEPNS_4TestEb + 0x4a [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026c387 _ZN7CppUnit6TextUi10TestRunner13runTestByNameESsb + 0x47 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026c2b2 _ZN7CppUnit6TextUi10TestRunner3runESsbbb + 0x52 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x0804e74f main + 0xdf [unitTest_RelationalCool_RalDatabase_versioning] + 0x42017589 __libc_start_main + 0x95 [unitTest_RelationalCool_RalDatabase_versioning] + 0x0804e581 _ZNK4seal4Time6minuteEb + 0x39 [unitTest_RelationalCool_RalDatabase_versioning] + +shared libraries present: + 0x00000000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/tests/bin/unitTest_RelationalCool_RalDatabase_versioning + 0x40015000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so + 0x4009e000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_AttributeList.so + 0x400c6000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_POOLCore.so + 0x400d6000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_PluginManager.so + 0x400f8000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealKernel.so + 0x40114000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_RelationalAccess.so + 0x4013c000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_Reflection.so + 0x40169000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealServices.so + 0x401a3000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealUtil.so + 0x401b1000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so + 0x40252000 /afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0 + 0x40291000 /lib/libnsl.so.1 + 0x402a6000 /lib/libcrypt.so.1 + 0x402d3000 /lib/libdl.so.2 + 0x402d6000 /afs/cern.ch/sw/lcg/external/pcre/4.4/rh73_gcc323/lib/libpcre.so.0 + 0x402e3000 /afs/cern.ch/sw/lcg/external/uuid/1.32/rh73_gcc323/lib/libuuid.so.1 + 0x402e6000 /usr/local/gcc-alt-3.2.3/lib/libstdc++.so.5 + 0x40397000 /lib/i686/libm.so.6 + 0x403b9000 /usr/local/gcc-alt-3.2.3/lib/libgcc_s.so.1 + 0x00000000 /lib/i686/libc.so.6 + 0x40000000 /lib/ld-linux.so.2 + 0x403c2000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so + 0x40463000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 + 0x40ff3000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libnnz10.so + 0x4027d000 /lib/i686/libpthread.so.0 + 0x42135000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libociei.so + 0x41219000 /lib/libnss_files.so.2 + 0x41223000 /lib/libnss_nisplus.so.2 + 0x4122e000 /lib/libnss_dns.so.2 + 0x41232000 /lib/libresolv.so.2 +Segmentation fault + +Trace #2 (after pressing CTRL-C) +-------- + +Standard configuration +POOL: rh73_gcc323 +COOL: rh73_gcc323 standard (no -pthread - COOL default on RH73) +==> segmentation fault (the 1st time it is executed) - trace #1 +==> hangs in mutex lock (from the 2nd time onwards) - trace #2 + +Here: I may soon crash (seg fault) or hang (mutex lock) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "i"."OBJECT_ID", "i"."CHANNEL_ID", "i"."IOV_SINCE", "i"."IOV_UNTIL", "i"."SYS_INSTIME", "i"."ORIGINAL_ID", "i"."NEW_HEAD_ID", "i"."I", "i"."S", "i"."X" FROM "CONDDB_TEST"."COOLSEGF_F0001_IOVS" "i", "CONDDB_TEST"."COOLSEGF_F0001_IOVS" "o" WHERE :"since" <= "i"."IOV_SINCE" and "i"."IOV_UNTIL" < :"until" and "i"."SYS_INSTIME" <= :"asOfDate1" and "i"."CHANNEL_ID" = :"channel" and ( ( "i"."NEW_HEAD_ID" = :"newHeadId" and "i"."OBJECT_ID" = "o"."OBJECT_ID" ) or ( "i"."NEW_HEAD_ID" = "o"."OBJECT_ID" and "o"."SYS_INSTIME" > :"asOfDate2" ) ) ORDER BY "IOV_SINCE" ASC" + +Ctrl-C + +unitTest_RelationalCool_RalDatabase_versioning (pid=8282 ppid=4571) received fatal signal 2 (Interrupt) +signal context: + signo = 2, errno = 0, code = 128 (kernel) + pid = 0, uid = 0 + value = (0, (nil)) + stack = (2, 0, (nil)) + + eip: 0023:420293d5 eflags: 00200216 + eax: fffffffc ebx: bfffa180 ecx: 00000008 edx: 4213030c + esi: bfffa180 edi: 4028e8e8 ebp: bfffa168 esp: bfffa160 + ds: 002b es: 002b fs: 0000 ss: 002b + + signal esp: bfffa160 trap: 0/0 oldmask: 80000000 cr2: 00000000 + + FPU: control = ffff027f + status = ffff0020 + tag = ffffffff + ip = 0023:40de0a77 + data = 002b:bfff53c8 + state = 00000020 + %fp0 = [0000:0000000000000000] + %fp1 = [0000:0000000000000000] + %fp2 = [0000:0000000000000000] + %fp3 = [3ff5:d000ffff6eff8312] + %fp4 = [0000:0000000000000000] + %fp5 = [4003:00000000c000f44f] + %fp6 = [4005:000000000000c800] + %fp7 = [4005:000000000000c800] + +stack trace: + 0x4003ef46 _ZN4seal9DebugAids10stacktraceEi + 0x66 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f96a _ZN4seal6Signal9fatalDumpEiP7siginfoPv + 0xda [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f210 _ZN4seal6Signal5fatalEiP7siginfoPv + 0xf0 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x42029180 ? + 0x42029180 [unitTest_RelationalCool_RalDatabase_versioning] + 0x40285609 ? + 0x40285609 [/lib/i686/libpthread.so.0] + 0x40287449 ? + 0x40287449 [/lib/i686/libpthread.so.0] + 0x402840d6 __pthread_mutex_lock + 0x66 [/lib/i686/libpthread.so.0] + 0x40409dfa _ZN4pool12OracleAccess29OracleQueryWithMultipleTables7processEv + 0x116a [/afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so] + 0x401eb652 _ZN4cool11RalDatabase20fetchObjectTableRowsERKSsRKN4pool26AttributeListSpecificationERKxS8_RKmRKN4seal4TimeE + 0x10c2 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x08051a2a _ZN4cool15RalDatabaseTest28test_fetchObjectTableRows_5cEv + 0x122a [unitTest_RelationalCool_RalDatabase_versioning] + 0x08057ead _ZN7CppUnit10TestCallerIN4cool15RalDatabaseTestENS_19NoExceptionExpectedEE7runTestEv + 0x3d [unitTest_RelationalCool_RalDatabase_versioning] + 0x40263cc5 _ZN7CppUnit8TestCase3runEPNS_10TestResultE + 0x45 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026d0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026d0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026d0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026c67a _ZN7CppUnit6TextUi10TestRunner7runTestEPNS_4TestEb + 0x4a [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026c387 _ZN7CppUnit6TextUi10TestRunner13runTestByNameESsb + 0x47 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4026c2b2 _ZN7CppUnit6TextUi10TestRunner3runESsbbb + 0x52 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x0804e74f main + 0xdf [unitTest_RelationalCool_RalDatabase_versioning] + 0x42017589 __libc_start_main + 0x95 [unitTest_RelationalCool_RalDatabase_versioning] + 0x0804e581 _ZNK4seal4Time6minuteEb + 0x39 [unitTest_RelationalCool_RalDatabase_versioning] + +shared libraries present: + 0x00000000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/tests/bin/unitTest_RelationalCool_RalDatabase_versioning + 0x40015000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so + 0x4009e000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_AttributeList.so + 0x400c6000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_POOLCore.so + 0x400d6000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_PluginManager.so + 0x400f8000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealKernel.so + 0x40114000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_RelationalAccess.so + 0x4013c000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_Reflection.so + 0x40169000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealServices.so + 0x401a3000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealUtil.so + 0x401b1000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so + 0x40252000 /afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0 + 0x40291000 /lib/libnsl.so.1 + 0x402a6000 /lib/libcrypt.so.1 + 0x402d3000 /lib/libdl.so.2 + 0x402d6000 /afs/cern.ch/sw/lcg/external/pcre/4.4/rh73_gcc323/lib/libpcre.so.0 + 0x402e3000 /afs/cern.ch/sw/lcg/external/uuid/1.32/rh73_gcc323/lib/libuuid.so.1 + 0x402e6000 /usr/local/gcc-alt-3.2.3/lib/libstdc++.so.5 + 0x40397000 /lib/i686/libm.so.6 + 0x403b9000 /usr/local/gcc-alt-3.2.3/lib/libgcc_s.so.1 + 0x00000000 /lib/i686/libc.so.6 + 0x40000000 /lib/ld-linux.so.2 + 0x403c2000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so + 0x40463000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 + 0x40ff3000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libnnz10.so + 0x4027d000 /lib/i686/libpthread.so.0 + 0x42135000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libociei.so + 0x41219000 /lib/libnss_files.so.2 + 0x41223000 /lib/libnss_nisplus.so.2 + 0x4122e000 /lib/libnss_dns.so.2 + 0x41232000 /lib/libresolv.so.2 + +Trace #3 (after pressing CTRL-C) +-------- + +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "CURRENT_VALUE", "LASTMOD_DATE" FROM "CONDDB_TEST"."COOLSEGF_FOLDERS_SEQ" FOR UPDATE" + +Ctrl-C + +unitTest_RelationalCool_RalDatabase_versioning (pid=9127 ppid=4571) received fatal signal 2 (Interrupt) +signal context: + signo = 2, errno = 0, code = 128 (kernel) + pid = 0, uid = 0 + value = (0, (nil)) + stack = (2, 0, (nil)) + + eip: 0023:420293d5 eflags: 00200216 + eax: fffffffc ebx: bfffb810 ecx: 00000008 edx: 4213030c + esi: bfffb810 edi: 402c18e8 ebp: bfffb7f8 esp: bfffb7f0 + ds: 002b es: 002b fs: 0000 ss: 002b + + signal esp: bfffb7f0 trap: 0/0 oldmask: 80000000 cr2: 00000000 + + FPU: control = ffff027f + status = ffff0100 + tag = ffffffff + ip = 0023:40bec604 + data = 002b:4100e2a4 + state = 00000100 + %fp0 = [0000:0000000000000000] + %fp1 = [0000:0000000000000000] + %fp2 = [0000:0000000000000000] + %fp3 = [0000:0000000000000000] + %fp4 = [0000:0000000000000000] + %fp5 = [0000:0000000000000000] + %fp6 = [4009:0000000000008000] + %fp7 = [400b:0000000000008000] + +stack trace: + 0x4003ef46 _ZN4seal9DebugAids10stacktraceEi + 0x66 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f96a _ZN4seal6Signal9fatalDumpEiP7siginfoPv + 0xda [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f210 _ZN4seal6Signal5fatalEiP7siginfoPv + 0xf0 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x42029180 ? + 0x42029180 [unitTest_RelationalCool_RalDatabase_versioning] + 0x402b8609 ? + 0x402b8609 [/lib/i686/libpthread.so.0] + 0x402b9f2c ? + 0x402b9f2c [/lib/i686/libpthread.so.0] + 0x402b70f6 __pthread_mutex_lock + 0x86 [/lib/i686/libpthread.so.0] + 0x40205705 _ZN4cool11RalDatabase23createGlobalFolderTableERKSs + 0xfc5 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x402027e7 _ZN4cool11RalDatabase14createDatabaseERKN4pool13AttributeListE + 0x227 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x40251301 _ZN4cool18RelationalDatabase14createDatabaseEv + 0x371 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x402479df _ZN4cool11RalDatabase14createDatabaseEv + 0x1f [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x40249ec3 _ZN4cool14RalDatabaseSvc14createDatabaseERKSs + 0x43 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x4024a9a7 _ZTv0_n16_N4cool14RalDatabaseSvc14createDatabaseERKSs + 0x37 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x080509b7 _ZN4cool15RalDatabaseTest28test_fetchObjectTableRows_5cEv + 0x57 [unitTest_RelationalCool_RalDatabase_versioning] + 0x0805860d _ZN7CppUnit10TestCallerIN4cool15RalDatabaseTestENS_19NoExceptionExpectedEE7runTestEv + 0x3d [unitTest_RelationalCool_RalDatabase_versioning] + 0x40296cc5 _ZN7CppUnit8TestCase3runEPNS_10TestResultE + 0x45 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x402a00cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x402a00cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x402a00cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4029f67a _ZN7CppUnit6TextUi10TestRunner7runTestEPNS_4TestEb + 0x4a [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4029f387 _ZN7CppUnit6TextUi10TestRunner13runTestByNameESsb + 0x47 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4029f2b2 _ZN7CppUnit6TextUi10TestRunner3runESsbbb + 0x52 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x0804e8af main + 0xdf [unitTest_RelationalCool_RalDatabase_versioning] + 0x42017589 __libc_start_main + 0x95 [unitTest_RelationalCool_RalDatabase_versioning] + 0x0804e6e1 _ZNK4seal4Time6minuteEb + 0x35 [unitTest_RelationalCool_RalDatabase_versioning] + +shared libraries present: + 0x00000000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/tests/bin/unitTest_RelationalCool_RalDatabase_versioning + 0x40015000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so + 0x4009e000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323_dbg/lib/liblcg_AttributeList.so + 0x400d3000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323_dbg/lib/liblcg_POOLCore.so + 0x400ed000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_PluginManager.so + 0x4010f000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealKernel.so + 0x4012b000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323_dbg/lib/liblcg_RelationalAccess.so + 0x4016a000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_Reflection.so + 0x40197000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealServices.so + 0x401d1000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealUtil.so + 0x401df000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so + 0x40285000 /afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0 + 0x402c4000 /lib/libnsl.so.1 + 0x402d9000 /lib/libcrypt.so.1 + 0x40306000 /lib/libdl.so.2 + 0x40309000 /afs/cern.ch/sw/lcg/external/pcre/4.4/rh73_gcc323/lib/libpcre.so.0 + 0x40316000 /afs/cern.ch/sw/lcg/external/uuid/1.32/rh73_gcc323/lib/libuuid.so.1 + 0x40319000 /usr/local/gcc-alt-3.2.3/lib/libstdc++.so.5 + 0x403ca000 /lib/i686/libm.so.6 + 0x403ec000 /usr/local/gcc-alt-3.2.3/lib/libgcc_s.so.1 + 0x00000000 /lib/i686/libc.so.6 + 0x40000000 /lib/ld-linux.so.2 + 0x403f5000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323_dbg/lib/liblcg_OracleAccess.so + 0x404d6000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 + 0x41066000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libnnz10.so + 0x402b0000 /lib/i686/libpthread.so.0 + 0x42135000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libociei.so + 0x4128c000 /lib/libnss_files.so.2 + 0x41296000 /lib/libnss_nisplus.so.2 + 0x412a1000 /lib/libnss_dns.so.2 + 0x412a5000 /lib/libresolv.so.2 + +Trace #4 +-------- + +With COOL debug without pthread +POOL: rh73_gcc323 +COOL: rh73_gcc323 with -g instead of -O2 (modify BuildFile) +==> segmentation fault (the 1st time it is executed) - trace #4 + +Here: I may soon crash (seg fault) or hang (mutex lock) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "i"."OBJECT_ID", "i"."CHANNEL_ID", "i"."IOV_SINCE", "i"."IOV_UNTIL", "i"."SYS_INSTIME", "i"."ORIGINAL_ID", "i"."NEW_HEAD_ID", "i"."I", "i"."S", "i"."X" FROM "CONDDB_TEST"."COOLSEGF_F0001_IOVS" "i", "CONDDB_TEST"."COOLSEGF_F0001_IOVS" "o" WHERE :"since" <= "i"."IOV_SINCE" and "i"."IOV_UNTIL" < :"until" and "i"."SYS_INSTIME" <= :"asOfDate1" and "i"."CHANNEL_ID" = :"channel" and ( ( "i"."NEW_HEAD_ID" = :"newHeadId" and "i"."OBJECT_ID" = "o"."OBJECT_ID" ) or ( "i"."NEW_HEAD_ID" = "o"."OBJECT_ID" and "o"."SYS_INSTIME" > :"asOfDate2" ) ) ORDER BY "IOV_SINCE" ASC" + +unitTest_RelationalCool_RalDatabase_versioning (pid=11582 ppid=4571) received fatal signal 11 (Segmentation fault) +signal context: + signo = 11, errno = 0, code = 1 (address not mapped to object) + pid = 538976304, uid = 135041708 + value = (135041944, 0x80c9398) + addr = 0x20202030 + stack = (2, 0, (nil)) + + eip: 0023:0805bb39 eflags: 00210202 + eax: 2020202c ebx: 08061f64 ecx: 080666d0 edx: 402493f0 + esi: 08066718 edi: 08066718 ebp: bfffc088 esp: bfffc070 + ds: 002b es: 002b fs: 0000 ss: 002b + + signal esp: bfffc070 trap: 14/4 oldmask: 80000000 cr2: 20202030 + + FPU: control = ffff027f + status = ffff0320 + tag = ffffffff + ip = 0023:409a555e + data = 002b:08101144 + state = 00000320 + %fp0 = [0000:0000000000000000] + %fp1 = [0000:0000000000000000] + %fp2 = [3fdd:7800371b5fe1d0e5] + %fp3 = [3ff6:d000ffff6eff8312] + %fp4 = [0000:0000000000000000] + %fp5 = [0000:0000000000000000] + %fp6 = [3ff6:d000ffff6eff8312] + %fp7 = [3ff6:d000ffff6eff8312] + +stack trace: + 0x4003ef46 _ZN4seal9DebugAids10stacktraceEi + 0x66 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f96a _ZN4seal6Signal9fatalDumpEiP7siginfoPv + 0xda [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f210 _ZN4seal6Signal5fatalEiP7siginfoPv + 0xf0 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x42029180 ? + 0x42029180 [unitTest_RelationalCool_RalDatabase_versioning] + 0x08059542 _ZN4pool26AttributeListSpecificationD1Ev + 0x20 [unitTest_RelationalCool_RalDatabase_versioning] + 0x4021f4d3 _ZN5boost14checked_deleteIN4pool26AttributeListSpecificationEEEvPT_ + 0x29 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x4021e4ab _ZNK5boost15checked_deleterIN4pool26AttributeListSpecificationEEclEPS2_ + 0x1d [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x40224248 _ZN5boost6detail20sp_counted_base_implIPN4pool26AttributeListSpecificationENS_15checked_deleterIS3_EEE7disposeEv + 0x2a [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x0805af9a _ZN5boost6detail15sp_counted_base7releaseEv + 0x38 [unitTest_RelationalCool_RalDatabase_versioning] + 0x0805935b _ZN5boost6detail12shared_countD1Ev + 0x27 [unitTest_RelationalCool_RalDatabase_versioning] + 0x404132dd _ZN4pool12OracleAccess29OracleQueryWithMultipleTables5resetEv + 0x11d [/afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so] + 0x40412fba _ZN4pool12OracleAccess29OracleQueryWithMultipleTablesD0Ev + 0x2a [/afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so] + 0x4021ad68 _ZNSt8auto_ptrIN4pool34IRelationalQueryWithMultipleTablesEED1Ev + 0x24 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x401ff5be _ZN4cool11RalDatabase20fetchObjectTableRowsERKSsRKN4pool26AttributeListSpecificationERKxS8_RKmRKN4seal4TimeE + 0x1aba [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x0805571e _ZN4cool15RalDatabaseTest28test_fetchObjectTableRows_5cEv + 0x9b6 [unitTest_RelationalCool_RalDatabase_versioning] + 0x0805ac8c _ZN7CppUnit10TestCallerIN4cool15RalDatabaseTestENS_19NoExceptionExpectedEE7runTestEv + 0x62 [unitTest_RelationalCool_RalDatabase_versioning] + 0x40270cc5 _ZN7CppUnit8TestCase3runEPNS_10TestResultE + 0x45 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4027a0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4027a0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4027a0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4027967a _ZN7CppUnit6TextUi10TestRunner7runTestEPNS_4TestEb + 0x4a [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x40279387 _ZN7CppUnit6TextUi10TestRunner13runTestByNameESsb + 0x47 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x402792b2 _ZN7CppUnit6TextUi10TestRunner3runESsbbb + 0x52 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x08053107 main + 0x137 [unitTest_RelationalCool_RalDatabase_versioning] + 0x42017589 __libc_start_main + 0x95 [unitTest_RelationalCool_RalDatabase_versioning] + 0x08052ee1 _ZN7CppUnit14TypeInfoHelper12getClassNameERKSt9type_info + 0x8d [unitTest_RelationalCool_RalDatabase_versioning] + +shared libraries present: + 0x00000000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/tests/bin/unitTest_RelationalCool_RalDatabase_versioning + 0x40015000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so + 0x4009e000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_AttributeList.so + 0x400c6000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_POOLCore.so + 0x400d6000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_PluginManager.so + 0x400f8000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealKernel.so + 0x40114000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_RelationalAccess.so + 0x4013c000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_Reflection.so + 0x40169000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealServices.so + 0x401a3000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealUtil.so + 0x401b1000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so + 0x4025f000 /afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0 + 0x4029e000 /lib/libnsl.so.1 + 0x402b3000 /lib/libcrypt.so.1 + 0x402e0000 /lib/libdl.so.2 + 0x402e3000 /afs/cern.ch/sw/lcg/external/pcre/4.4/rh73_gcc323/lib/libpcre.so.0 + 0x402f0000 /afs/cern.ch/sw/lcg/external/uuid/1.32/rh73_gcc323/lib/libuuid.so.1 + 0x402f3000 /usr/local/gcc-alt-3.2.3/lib/libstdc++.so.5 + 0x403a4000 /lib/i686/libm.so.6 + 0x403c6000 /usr/local/gcc-alt-3.2.3/lib/libgcc_s.so.1 + 0x00000000 /lib/i686/libc.so.6 + 0x40000000 /lib/ld-linux.so.2 + 0x403cf000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so + 0x40470000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 + 0x41000000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libnnz10.so + 0x4028a000 /lib/i686/libpthread.so.0 + 0x42135000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libociei.so + 0x41226000 /lib/libnss_files.so.2 + 0x41230000 /lib/libnss_nisplus.so.2 + 0x4123b000 /lib/libnss_dns.so.2 + 0x4123f000 /lib/libresolv.so.2 +Segmentation fault + +Trace 5 (after CTRL-C) +------- + +With COOL debug without pthread +POOL: rh73_gcc323 +COOL: rh73_gcc323 with -g instead of -O2 (modify BuildFile) +==> segmentation fault (the 1st time it is executed) - trace #4 +==> hangs in mutex lock (from the 2nd time onwards) - trace #5 + +Here: I may soon crash (seg fault) or hang (mutex lock) +POOL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "i"."OBJECT_ID", "i"."CHANNEL_ID", "i"."IOV_SINCE", "i"."IOV_UNTIL", "i"."SYS_INSTIME", "i"."ORIGINAL_ID", "i"."NEW_HEAD_ID", "i"."I", "i"."S", "i"."X" FROM "CONDDB_TEST"."COOLSEGF_F0001_IOVS" "i", "CONDDB_TEST"."COOLSEGF_F0001_IOVS" "o" WHERE :"since" <= "i"."IOV_SINCE" and "i"."IOV_UNTIL" < :"until" and "i"."SYS_INSTIME" <= :"asOfDate1" and "i"."CHANNEL_ID" = :"channel" and ( ( "i"."NEW_HEAD_ID" = :"newHeadId" and "i"."OBJECT_ID" = "o"."OBJECT_ID" ) or ( "i"."NEW_HEAD_ID" = "o"."OBJECT_ID" and "o"."SYS_INSTIME" > :"asOfDate2" ) ) ORDER BY "IOV_SINCE" ASC" + +unitTest_RelationalCool_RalDatabase_versioning (pid=11599 ppid=4571) received fatal signal 2 (Interrupt) +signal context: + signo = 2, errno = 0, code = 128 (kernel) + pid = 0, uid = 0 + value = (0, (nil)) + stack = (2, 0, (nil)) + + eip: 0023:420293d5 eflags: 00200216 + eax: fffffffc ebx: bfffa660 ecx: 00000008 edx: 4213030c + esi: bfffa660 edi: 4029b8e8 ebp: bfffa648 esp: bfffa640 + ds: 002b es: 002b fs: 0000 ss: 002b + + signal esp: bfffa640 trap: 0/0 oldmask: 80000000 cr2: 00000000 + + FPU: control = ffff027f + status = ffff0020 + tag = ffffffff + ip = 0023:40deda77 + data = 002b:bfff59b8 + state = 00000020 + %fp0 = [0000:0000000000000000] + %fp1 = [0000:0000000000000000] + %fp2 = [0000:0000000000000000] + %fp3 = [3ff5:d000ffff6eff8312] + %fp4 = [0000:0000000000000000] + %fp5 = [4003:00000000c000f44f] + %fp6 = [4005:000000000000c800] + %fp7 = [4005:000000000000c800] + +stack trace: + 0x4003ef46 _ZN4seal9DebugAids10stacktraceEi + 0x66 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f96a _ZN4seal6Signal9fatalDumpEiP7siginfoPv + 0xda [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x4006f210 _ZN4seal6Signal5fatalEiP7siginfoPv + 0xf0 [/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so] + 0x42029180 ? + 0x42029180 [unitTest_RelationalCool_RalDatabase_versioning] + 0x40292609 ? + 0x40292609 [/lib/i686/libpthread.so.0] + 0x40294449 ? + 0x40294449 [/lib/i686/libpthread.so.0] + 0x402910d6 __pthread_mutex_lock + 0x66 [/lib/i686/libpthread.so.0] + 0x40416dfa _ZN4pool12OracleAccess29OracleQueryWithMultipleTables7processEv + 0x116a [/afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so] + 0x401ff255 _ZN4cool11RalDatabase20fetchObjectTableRowsERKSsRKN4pool26AttributeListSpecificationERKxS8_RKmRKN4seal4TimeE + 0x1751 [/afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so] + 0x0805571e _ZN4cool15RalDatabaseTest28test_fetchObjectTableRows_5cEv + 0x9b6 [unitTest_RelationalCool_RalDatabase_versioning] + 0x0805ac8c _ZN7CppUnit10TestCallerIN4cool15RalDatabaseTestENS_19NoExceptionExpectedEE7runTestEv + 0x62 [unitTest_RelationalCool_RalDatabase_versioning] + 0x40270cc5 _ZN7CppUnit8TestCase3runEPNS_10TestResultE + 0x45 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4027a0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4027a0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4027a0cd _ZN7CppUnit9TestSuite3runEPNS_10TestResultE + 0x3d [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x4027967a _ZN7CppUnit6TextUi10TestRunner7runTestEPNS_4TestEb + 0x4a [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x40279387 _ZN7CppUnit6TextUi10TestRunner13runTestByNameESsb + 0x47 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x402792b2 _ZN7CppUnit6TextUi10TestRunner3runESsbbb + 0x52 [/afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0] + 0x08053107 main + 0x137 [unitTest_RelationalCool_RalDatabase_versioning] + 0x42017589 __libc_start_main + 0x95 [unitTest_RelationalCool_RalDatabase_versioning] + 0x08052ee1 _ZN7CppUnit14TypeInfoHelper12getClassNameERKSt9type_info + 0x8d [unitTest_RelationalCool_RalDatabase_versioning] + +shared libraries present: + 0x00000000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/tests/bin/unitTest_RelationalCool_RalDatabase_versioning + 0x40015000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealBase.so + 0x4009e000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_AttributeList.so + 0x400c6000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_POOLCore.so + 0x400d6000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_PluginManager.so + 0x400f8000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealKernel.so + 0x40114000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_RelationalAccess.so + 0x4013c000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_Reflection.so + 0x40169000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealServices.so + 0x401a3000 /afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_6_1/rh73_gcc323/lib/liblcg_SealUtil.so + 0x401b1000 /afs/cern.ch/user/a/avalassi/myLCG/COOL_HEAD/rh73_gcc323/lib/liblcg_RelationalCool.so + 0x4025f000 /afs/cern.ch/sw/lcg/external/CppUnit/1.8.0/rh73_gcc323/lib/libcppunit-1.8.so.0 + 0x4029e000 /lib/libnsl.so.1 + 0x402b3000 /lib/libcrypt.so.1 + 0x402e0000 /lib/libdl.so.2 + 0x402e3000 /afs/cern.ch/sw/lcg/external/pcre/4.4/rh73_gcc323/lib/libpcre.so.0 + 0x402f0000 /afs/cern.ch/sw/lcg/external/uuid/1.32/rh73_gcc323/lib/libuuid.so.1 + 0x402f3000 /usr/local/gcc-alt-3.2.3/lib/libstdc++.so.5 + 0x403a4000 /lib/i686/libm.so.6 + 0x403c6000 /usr/local/gcc-alt-3.2.3/lib/libgcc_s.so.1 + 0x00000000 /lib/i686/libc.so.6 + 0x40000000 /lib/ld-linux.so.2 + 0x403cf000 /afs/cern.ch/sw/lcg/app/releases/POOL/POOL_2_0_2/rh73_gcc323/lib/liblcg_OracleAccess.so + 0x40470000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libclntsh.so.10.1 + 0x41000000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libnnz10.so + 0x4028a000 /lib/i686/libpthread.so.0 + 0x42135000 /afs/cern.ch/sw/lcg/external/oracle/10.1.0.3-1/rh73_gcc323/lib/libociei.so + 0x41226000 /lib/libnss_files.so.2 + 0x41230000 /lib/libnss_nisplus.so.2 + 0x4123b000 /lib/libnss_dns.so.2 + 0x4123f000 /lib/libresolv.so.2 + diff --git a/RelationalCool/tests/RalSequence/test_RalSequence.cpp b/RelationalCool/tests/RalSequence/test_RalSequence.cpp new file mode 100644 index 000000000..6da7d3ef5 --- /dev/null +++ b/RelationalCool/tests/RalSequence/test_RalSequence.cpp @@ -0,0 +1,136 @@ +// $Id: test_RalSequence.cpp,v 1.19 2008-04-10 13:57:42 avalassi Exp $ +/** + + @file test_RalSequence.cpp + + @author COOL Core Team + + @date 2005-12-09 + + */ + +// Include files +#include "RelationalAccess/ISchema.h" + +// Local include files +#include "CoolDBUnitTest.h" +#include "src/RalDatabase.h" +#include "src/RelationalQueryMgr.h" +#include "src/RelationalSequence.h" +#include "src/RelationalSequenceMgr.h" +#include "src/RelationalTransaction.h" + +namespace cool { + + +/** + RalSequenceTest tests the behavior of RalSequence +*/ + +class RalSequenceTest : public cool::CoolDBUnitTest { + + CPPUNIT_TEST_SUITE( RalSequenceTest ); + + CPPUNIT_TEST( test_createSequence ); + CPPUNIT_TEST( test_nextVal ); + CPPUNIT_TEST( test_currVal ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + RalDatabase* ralDb; + + void test_currVal() { + try { + RelationalTransaction transaction( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> + seq( ralDb->queryMgr().sequenceMgr().createSequence + ( std::string( m_coolDBName + "_SEQ" ) ) ); + unsigned long id = seq->nextVal(); + CPPUNIT_ASSERT_EQUAL( 0ul, id ); + id = seq->currVal(); + CPPUNIT_ASSERT_EQUAL( 0ul, id ); + transaction.commit(); + } catch ( std::exception& e ) { + std::cout << e.what() << std::endl; + throw; + } + } + + + void test_nextVal() { + try { + RelationalTransaction transaction( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> + seq( ralDb->queryMgr().sequenceMgr().createSequence + ( std::string( m_coolDBName + "_SEQ" ) ) ); + unsigned long id = seq->nextVal(); + CPPUNIT_ASSERT_EQUAL( 0ul, id ); + id = seq->nextVal(); + CPPUNIT_ASSERT_EQUAL( 1ul, id ); + id = seq->nextVal(); + CPPUNIT_ASSERT_EQUAL( 2ul, id ); + transaction.commit(); + } catch ( std::exception& e ) { + std::cout << e.what() << std::endl; + throw; + } + } + + + void test_createSequence() { + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> + nodeSeq( ralDb->queryMgr().sequenceMgr().createSequence + ( std::string( m_coolDBName + "_SEQ" ) ) ); + transaction.commit(); + } + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + CPPUNIT_ASSERT( ralDb->session().nominalSchema().existsTable + ( std::string( m_coolDBName + "_SEQ" ) ) ); + transaction.commit(); + } + } + + + void setUp() + { + try + { + ralDb = new RalDatabase( ppConnectionSvc(), m_connectionString, false ); + } + catch ( std::exception& e ) + { + ralDb = NULL; + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + void tearDown() + { + if ( ralDb ) + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + ralDb->session().nominalSchema().dropIfExistsTable + ( std::string( m_coolDBName + "_SEQ" ) ); + transaction.commit(); + delete ralDb; + ralDb = 0; + } + } + + RalSequenceTest() : cool::CoolDBUnitTest( false ) // no dbSvc is needed + { + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( RalSequenceTest ); + +} // namespace + +COOLTEST_MAIN(RalSequenceTest) diff --git a/RelationalCool/tests/RelationalDatabaseId/test_RelationalDatabaseId.cpp b/RelationalCool/tests/RelationalDatabaseId/test_RelationalDatabaseId.cpp new file mode 100644 index 000000000..37a2e520f --- /dev/null +++ b/RelationalCool/tests/RelationalDatabaseId/test_RelationalDatabaseId.cpp @@ -0,0 +1,195 @@ +// $Id: test_RelationalDatabaseId.cpp,v 1.8 2009-02-04 10:57:58 avalassi Exp $ +/** + + @file test_RelationalDatabaseId.cpp + + @author Marco Clemencic + + @date 2004-11-04 + + */ + +#include "../Common/CppUnit_headers.h" // Disable CppUnit header warnings + +#include "src/RelationalDatabaseId.h" +#include "src/RelationalException.h" + +namespace cool { + + +/** + RelationalDatabaseId test class. +*/ + +class RelationalDatabaseIdTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( RelationalDatabaseIdTest ); + + CPPUNIT_TEST( test_technologies ); + CPPUNIT_TEST( test_alias ); + CPPUNIT_TEST( test_alias_role ); + CPPUNIT_TEST( test_user ); + CPPUNIT_TEST( test_password ); + CPPUNIT_TEST( test_cached_urls ); + CPPUNIT_TEST( test_cached_urls_alias ); + CPPUNIT_TEST( test_cached_urls_alias_role ); + CPPUNIT_TEST( test_order ); + + CPPUNIT_TEST( test_missing ); + CPPUNIT_TEST( test_bad_url ); + + CPPUNIT_TEST( test_middleTier ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + void setUp() {} + + void tearDown() {} + + /// Test + void basic_test( const std::string connString, + const std::string middleTier, + const std::string tech, + const std::string server, + const std::string schema, + const std::string dbname, + const std::string user="", + const std::string password="", + const std::string alias="", + const std::string role="") + { + RelationalDatabaseId id(connString); + + std::string msg = "Failed to parse '" + connString + "'"; + + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, middleTier, id.middleTier() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, tech, id.technology() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, server, id.server() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, schema, id.schema() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, dbname, id.dbName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, user, id.user() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, password, id.password() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, alias, id.alias() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, role, id.role() ); + } + + void test_technologies() + { + basic_test("oracle://server;schema=theSchema;dbname=DBNAME", + "","oracle","server","theSchema","DBNAME"); + basic_test("mysql://server;schema=theSchema;dbname=DBNAME", + "","mysql","server","theSchema","DBNAME"); + basic_test("sqlite://server;schema=theSchema;dbname=DBNAME", + "","sqlite","server","theSchema","DBNAME"); + } + + void test_middleTier() + { + basic_test + ("coralxxx://host:port&oracle://server;schema=theSchema;dbname=DBNAME", + "coralxxx://host:port&","oracle","server","theSchema","DBNAME"); + try + { + RelationalDatabaseId + id("xxx://host:port&oracle://server;schema=theSchema;dbname=DBNAME"); + CPPUNIT_FAIL( "middleTier prefix starting with xxx should fail" ); + } + catch ( RelationalException& ){} + } + + void test_alias() + { + basic_test("alias/DBNAME", + "","","","","DBNAME","","","alias"); + } + + void test_alias_role() + { + basic_test("alias(role)/DBNAME", + "","","","","DBNAME","","","alias","role"); + } + + void test_user() + { + basic_test("oracle://server;schema=theSchema;dbname=DBNAME;user=theUser", + "","oracle","server","theSchema","DBNAME","theUser"); + } + + void test_password() + { + basic_test + ("oracle://server;schema=theSchema;dbname=DBNAME;password=thePassword", + "","oracle","server","theSchema","DBNAME","","thePassword"); + } + + void test_cached_urls() + { + RelationalDatabaseId id("oracle://server;schema=theSchema;dbname=DBNAME;user=theUser;password=thePassword"); + CPPUNIT_ASSERT_EQUAL(std::string("oracle://server;schema=theSchema;dbname=DBNAME;user=theUser;password=thePassword"), + id.url()); + CPPUNIT_ASSERT_EQUAL(std::string("oracle://server;schema=theSchema;dbname=DBNAME;user=theUser;password=********"), + id.urlHidePswd()); + CPPUNIT_ASSERT_EQUAL(std::string("oracle://server;schema=theSchema;user=theUser;password=thePassword"), + id.urlNoDbname()); + } + + void test_cached_urls_alias() + { + RelationalDatabaseId id("alias/DBNAME"); + CPPUNIT_ASSERT_EQUAL(std::string("alias/DBNAME"), + id.url()); + CPPUNIT_ASSERT_EQUAL(std::string("alias/DBNAME"), + id.urlHidePswd()); + CPPUNIT_ASSERT_EQUAL(std::string("alias"), + id.urlNoDbname()); + } + + void test_cached_urls_alias_role() + { + RelationalDatabaseId id("alias(role)/DBNAME"); + CPPUNIT_ASSERT_EQUAL(std::string("alias(role)/DBNAME"), + id.url()); + CPPUNIT_ASSERT_EQUAL(std::string("alias(role)/DBNAME"), + id.urlHidePswd()); + CPPUNIT_ASSERT_EQUAL(std::string("alias(role)"), + id.urlNoDbname()); + } + + void test_order() + { + CPPUNIT_ASSERT_EQUAL(std::string("oracle://server;schema=theSchema;dbname=DBNAME;user=theUser;password=thePassword"), + RelationalDatabaseId("oracle://server;user=theUser;dbname=DBNAME;schema=theSchema;password=thePassword") + .url()); + } + + void test_missing() + { + CPPUNIT_ASSERT_THROW(RelationalDatabaseId("oracle://server;dbname=DBNAME;user=theUser;password=thePassword"), + RelationalException); + CPPUNIT_ASSERT_THROW(RelationalDatabaseId("oracle://server;schema=theSchema;user=theUser;password=thePassword"), + RelationalException); + CPPUNIT_ASSERT_THROW(RelationalDatabaseId("alias/"), + RelationalException); + } + + void test_bad_url() + { + CPPUNIT_ASSERT_THROW(RelationalDatabaseId("abcd://server;schema=theSchema;dbname=DBNAME;user=theUser;password=thePassword"), + RelationalException); + CPPUNIT_ASSERT_THROW(RelationalDatabaseId("bad:url"), + RelationalException); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( RelationalDatabaseIdTest ); + +} // namespace + +// sas: This file is from the OPAL package I believe. It allows for +// shorter test classes and prepares the test class for OPAL +#include<CppUnit_testdriver.icpp> + + diff --git a/RelationalCool/tests/RelationalFolder/README.tests b/RelationalCool/tests/RelationalFolder/README.tests new file mode 100755 index 000000000..011a1e0bb --- /dev/null +++ b/RelationalCool/tests/RelationalFolder/README.tests @@ -0,0 +1,40 @@ +The four log files contain the results of the tests executed by building +a stripped down version of test_RelationalFolder.cpp, i.e. essentially +test_RelationalFolder.cpp.gmtime (only test_gmtime_timegm enabled, with +verbose output, empty setup, and tests enabled for isdst=0, -1 and +1). + +- out.Windows.p1.adjustTimeZone + +From test_RelationalFolder.cpp.gmtime (both +1 and -1 tests enabled). +It fails on isdst=+1 in January. +Executed with PC clock set to "automatically adjust summer time". + +- out.Windows.m1.adjustTimeZone + +From test_RelationalFolder.cpp.gmtime modified so that the isdst=+1 +test is disabled. It fails on isdst=-1 in April. +Executed with PC clock set to "automatically adjust summer time". + +- out.Windows.noTest.adjustTimeZone + +From test_RelationalFolder.cpp.gmtime modified so that the isdst=+1 +and isdst=-1 tests are both disabled. It succeeds but prints out all. +Executed with PC clock set to "automatically adjust summer time". + +- out.Windows.doNotAdjustTimeZone + +From test_RelationalFolder.cpp.gmtime (both +1 and -1 tests enabled), +i.e. the same setup as for out.Windows.p1.adjustTimeZone. It succeeds. +Executed with PC clock set to "DO NOT automatically adjust summer time". + +------------------------------------------------------------------------------- + +For reference, the executable is rebuilt using the following two commands: + +cl.exe /nologo /c /I\\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\src\RelationalCool /I\\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\src\CoolKernel /I\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\src\Foundation\SealBase /IL:\cygwin\win32_vc71_dbg\include /I\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\src\Foundation\SealPlatform /I\\afs\all\cern.ch\sw\lcg\app\releases\POOL\POOL_2_1_0\src\AttributeList /I\\afs\all\cern.ch\sw\lcg\app\releases\POOL\POOL_2_1_0\src\POOLCore /I\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\src\Framework\SealKernel /I\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\src\Foundation\PluginManager /I\\afs\all\cern.ch\sw\lcg\app\releases\POOL\POOL_2_1_0\src\RelationalAccess /I\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\src\Foundation\SealUtil /I\\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\src\CoolApplication /I\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\src\Dictionary\Reflection /I\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\src\Framework\SealServices /I\\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\src\RelationalCool\tests\Common /I\\afs\all\cern.ch\sw\lcg\external\uuid\1.32\win32_vc71\include /I\\afs\all\cern.ch\sw\lcg\external\Boost\1.31.0\win32_vc71\include\boost-1_31 /I\\afs\all\cern.ch\sw\lcg\external\CppUnit\1.8.0\win32_vc71\include /I\\afs\all\cern.ch\sw\lcg\external\pcre\4.4\win32_vc71\include /I\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\src /I\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\win32_vc71_dbg\include /I\\afs\all\cern.ch\sw\lcg\app\releases\POOL\POOL_2_1_0\src /Ic:\Program\ Files\Microsoft\ Visual\ Studio\ .NET\ 2003\VC7\include /Ic:\Program\ Files\Microsoft\ Visual\ Studio\ .NET\ 2003\VC7\PlatformSDK\Include /D_GNU_SOURCE /DGNU_SOURCE /DWIN32 /D_MBCS /D_WINDOWS /DSEAL_KERNEL_BUILD_ARCHIVE /D_DEBUG /W3 /WL /GR /GX /GF /GS /MD /Zm500 /Od /Z7 /Fo\\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\tmp\win32_vc71_dbg\src\RelationalCool\tests\RelationalFolder\test_RelationalFolder.obj \\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\src\RelationalCool\tests\RelationalFolder\test_RelationalFolder.cpp + +link.exe /NOLOGO /OUT:\\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\win32_vc71_dbg\tests\bin\unitTest_RelationalCool_RelationalFolder.exe /EXETYPE:DYNAMIC /DEBUG /INCREMENTAL:NO /LIBPATH:\\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\win32_vc71_dbg\lib /LIBPATH:\\afs\all\cern.ch\sw\lcg\external\uuid\1.32\win32_vc71\lib /LIBPATH:\\afs\all\cern.ch\sw\lcg\external\Boost\1.31.0\win32_vc71\lib /LIBPATH:\\afs\all\cern.ch\sw\lcg\external\CppUnit\1.8.0\win32_vc71\lib /LIBPATH:\\afs\all\cern.ch\sw\lcg\external\pcre\4.4\win32_vc71\lib /LIBPATH:\\afs\all\cern.ch\sw\lcg\app\releases\SEAL\SEAL_1_6_3\win32_vc71_dbg\lib /LIBPATH:\\afs\all\cern.ch\sw\lcg\app\releases\POOL\POOL_2_1_0\win32_vc71_dbg\lib /LIBPATH:c:\Program\ Files\Microsoft\ Visual\ Studio\ .NET\ 2003\VC7\lib /LIBPATH:c:\Program\ Files\Microsoft\ Visual\ Studio\ .NET\ 2003\VC7\PlatformSDK\Lib lcg_SealBase.lib lcg_AttributeList.lib lcg_POOLCore.lib lcg_PluginManager.lib lcg_SealKernel.lib lcg_RelationalAccess.lib lcg_SealUtil.lib lcg_RelationalCool.lib lcg_CoolApplication.lib lcg_Reflection.lib lcg_SealServices.lib uuid.lib cppunit_dll.lib libpcre.lib /nodefaultlib kernel32.lib user32.lib msvcprt.lib msvcrt.lib oldnames.lib \\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\tmp\win32_vc71_dbg\src\RelationalCool\tests\RelationalFolder\test_RelationalFolder.obj + + + + diff --git a/RelationalCool/tests/RelationalFolder/out.Windows.doNotAdjustTimeZone b/RelationalCool/tests/RelationalFolder/out.Windows.doNotAdjustTimeZone new file mode 100755 index 000000000..3847dab88 --- /dev/null +++ b/RelationalCool/tests/RelationalFolder/out.Windows.doNotAdjustTimeZone @@ -0,0 +1,183 @@ +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-1-3 12:1:2 +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +aTm = 1970-1-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 216062 +aTmM1 = 1970-1-3 12:1:2 (DST=0) +aTimet0 = 216062 +aTm0 = 1970-1-3 12:1:2 (DST=0) +aTimetP1 = 216062 +aTmP1 = 1970-1-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-2-3 12:1:2 +Before calling timegm: aTm = 1970-2-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-2-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +aTm = 1970-2-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 2894462 +aTmM1 = 1970-2-3 12:1:2 (DST=0) +aTimet0 = 2894462 +aTm0 = 1970-2-3 12:1:2 (DST=0) +aTimetP1 = 2894462 +aTmP1 = 1970-2-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-3-3 12:1:2 +Before calling timegm: aTm = 1970-3-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-3-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +aTm = 1970-3-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 5313662 +aTmM1 = 1970-3-3 12:1:2 (DST=0) +aTimet0 = 5313662 +aTm0 = 1970-3-3 12:1:2 (DST=0) +aTimetP1 = 5313662 +aTmP1 = 1970-3-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-4-3 12:1:2 +Before calling timegm: aTm = 1970-4-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-4-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-4-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-4-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-4-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-4-3 12:1:2 (DST=0) +aTm = 1970-4-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 7992062 +aTmM1 = 1970-4-3 12:1:2 (DST=0) +aTimet0 = 7992062 +aTm0 = 1970-4-3 12:1:2 (DST=0) +aTimetP1 = 7992062 +aTmP1 = 1970-4-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-5-3 12:1:2 +Before calling timegm: aTm = 1970-5-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-5-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-5-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-5-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-5-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-5-3 12:1:2 (DST=0) +aTm = 1970-5-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 10584062 +aTmM1 = 1970-5-3 12:1:2 (DST=0) +aTimet0 = 10584062 +aTm0 = 1970-5-3 12:1:2 (DST=0) +aTimetP1 = 10584062 +aTmP1 = 1970-5-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-6-3 12:1:2 +Before calling timegm: aTm = 1970-6-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-6-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-6-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-6-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-6-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-6-3 12:1:2 (DST=0) +aTm = 1970-6-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 13262462 +aTmM1 = 1970-6-3 12:1:2 (DST=0) +aTimet0 = 13262462 +aTm0 = 1970-6-3 12:1:2 (DST=0) +aTimetP1 = 13262462 +aTmP1 = 1970-6-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-7-3 12:1:2 +Before calling timegm: aTm = 1970-7-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-7-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-7-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-7-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-7-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-7-3 12:1:2 (DST=0) +aTm = 1970-7-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 15854462 +aTmM1 = 1970-7-3 12:1:2 (DST=0) +aTimet0 = 15854462 +aTm0 = 1970-7-3 12:1:2 (DST=0) +aTimetP1 = 15854462 +aTmP1 = 1970-7-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-8-3 12:1:2 +Before calling timegm: aTm = 1970-8-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-8-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-8-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-8-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-8-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-8-3 12:1:2 (DST=0) +aTm = 1970-8-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 18532862 +aTmM1 = 1970-8-3 12:1:2 (DST=0) +aTimet0 = 18532862 +aTm0 = 1970-8-3 12:1:2 (DST=0) +aTimetP1 = 18532862 +aTmP1 = 1970-8-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-9-3 12:1:2 +Before calling timegm: aTm = 1970-9-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-9-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-9-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-9-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-9-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-9-3 12:1:2 (DST=0) +aTm = 1970-9-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 21211262 +aTmM1 = 1970-9-3 12:1:2 (DST=0) +aTimet0 = 21211262 +aTm0 = 1970-9-3 12:1:2 (DST=0) +aTimetP1 = 21211262 +aTmP1 = 1970-9-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-10-3 12:1:2 +Before calling timegm: aTm = 1970-10-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-10-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-10-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-10-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-10-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-10-3 12:1:2 (DST=0) +aTm = 1970-10-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 23803262 +aTmM1 = 1970-10-3 12:1:2 (DST=0) +aTimet0 = 23803262 +aTm0 = 1970-10-3 12:1:2 (DST=0) +aTimetP1 = 23803262 +aTmP1 = 1970-10-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-11-3 12:1:2 +Before calling timegm: aTm = 1970-11-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-11-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-11-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-11-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-11-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-11-3 12:1:2 (DST=0) +aTm = 1970-11-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 26481662 +aTmM1 = 1970-11-3 12:1:2 (DST=0) +aTimet0 = 26481662 +aTm0 = 1970-11-3 12:1:2 (DST=0) +aTimetP1 = 26481662 +aTmP1 = 1970-11-3 12:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-12-3 12:1:2 +Before calling timegm: aTm = 1970-12-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-12-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-12-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-12-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-12-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-12-3 12:1:2 (DST=0) +aTm = 1970-12-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 29073662 +aTmM1 = 1970-12-3 12:1:2 (DST=0) +aTimet0 = 29073662 +aTm0 = 1970-12-3 12:1:2 (DST=0) +aTimetP1 = 29073662 +aTmP1 = 1970-12-3 12:1:2 (DST=0) + +OK (1) +[OVAL] Cppunit-result =0 diff --git a/RelationalCool/tests/RelationalFolder/out.Windows.m1.adjustTimeZone b/RelationalCool/tests/RelationalFolder/out.Windows.m1.adjustTimeZone new file mode 100755 index 000000000..33cc7477d --- /dev/null +++ b/RelationalCool/tests/RelationalFolder/out.Windows.m1.adjustTimeZone @@ -0,0 +1,74 @@ +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-1-3 12:1:2 +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-1-3 11:1:2 (DST=0) +aTm = 1970-1-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 216062 +aTmM1 = 1970-1-3 12:1:2 (DST=0) +aTimet0 = 216062 +aTm0 = 1970-1-3 12:1:2 (DST=0) +aTimetP1 = 212462 +aTmP1 = 1970-1-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-2-3 12:1:2 +Before calling timegm: aTm = 1970-2-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-2-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-2-3 11:1:2 (DST=0) +aTm = 1970-2-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 2894462 +aTmM1 = 1970-2-3 12:1:2 (DST=0) +aTimet0 = 2894462 +aTm0 = 1970-2-3 12:1:2 (DST=0) +aTimetP1 = 2890862 +aTmP1 = 1970-2-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-3-3 12:1:2 +Before calling timegm: aTm = 1970-3-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-3-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-3-3 11:1:2 (DST=0) +aTm = 1970-3-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 5313662 +aTmM1 = 1970-3-3 12:1:2 (DST=0) +aTimet0 = 5313662 +aTm0 = 1970-3-3 12:1:2 (DST=0) +aTimetP1 = 5310062 +aTmP1 = 1970-3-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-4-3 12:1:2 +Before calling timegm: aTm = 1970-4-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-4-3 12:1:2 (DST=1) +Before calling timegm: aTm = 1970-4-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-4-3 13:1:2 (DST=1) +Before calling timegm: aTm = 1970-4-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-4-3 12:1:2 (DST=1) +aTm = 1970-4-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 7988462 +aTmM1 = 1970-4-3 11:1:2 (DST=0) +aTimet0 = 7992062 +aTm0 = 1970-4-3 12:1:2 (DST=0) +aTimetP1 = 7988462 +aTmP1 = 1970-4-3 11:1:2 (DST=0) + +\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\src\RelationalCool\tests\RelationalFolder\test_RelationalFolder.cpp(284) : Assertion +Test name: cool::RelationalFolderTest.test_gmtime_timegm +- Expected : 12 + +- Actual : 11 + +gmtime(timegm(tm,isDst=-1))==tm : hour (Month[0-11]=3) + + +Failures !!! +Run: 1 Failure total: 1 Failures: 1 Errors: 0 +Error: CppUnit Failures +[OVAL] Cppunit-result =1 diff --git a/RelationalCool/tests/RelationalFolder/out.Windows.noTest.adjustTimeZone b/RelationalCool/tests/RelationalFolder/out.Windows.noTest.adjustTimeZone new file mode 100755 index 000000000..59c485efb --- /dev/null +++ b/RelationalCool/tests/RelationalFolder/out.Windows.noTest.adjustTimeZone @@ -0,0 +1,183 @@ +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-1-3 12:1:2 +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-1-3 11:1:2 (DST=0) +aTm = 1970-1-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 216062 +aTmM1 = 1970-1-3 12:1:2 (DST=0) +aTimet0 = 216062 +aTm0 = 1970-1-3 12:1:2 (DST=0) +aTimetP1 = 212462 +aTmP1 = 1970-1-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-2-3 12:1:2 +Before calling timegm: aTm = 1970-2-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-2-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-2-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-2-3 11:1:2 (DST=0) +aTm = 1970-2-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 2894462 +aTmM1 = 1970-2-3 12:1:2 (DST=0) +aTimet0 = 2894462 +aTm0 = 1970-2-3 12:1:2 (DST=0) +aTimetP1 = 2890862 +aTmP1 = 1970-2-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-3-3 12:1:2 +Before calling timegm: aTm = 1970-3-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-3-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-3-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-3-3 11:1:2 (DST=0) +aTm = 1970-3-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 5313662 +aTmM1 = 1970-3-3 12:1:2 (DST=0) +aTimet0 = 5313662 +aTm0 = 1970-3-3 12:1:2 (DST=0) +aTimetP1 = 5310062 +aTmP1 = 1970-3-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-4-3 12:1:2 +Before calling timegm: aTm = 1970-4-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-4-3 12:1:2 (DST=1) +Before calling timegm: aTm = 1970-4-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-4-3 13:1:2 (DST=1) +Before calling timegm: aTm = 1970-4-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-4-3 12:1:2 (DST=1) +aTm = 1970-4-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 7988462 +aTmM1 = 1970-4-3 11:1:2 (DST=0) +aTimet0 = 7992062 +aTm0 = 1970-4-3 12:1:2 (DST=0) +aTimetP1 = 7988462 +aTmP1 = 1970-4-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-5-3 12:1:2 +Before calling timegm: aTm = 1970-5-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-5-3 12:1:2 (DST=1) +Before calling timegm: aTm = 1970-5-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-5-3 13:1:2 (DST=1) +Before calling timegm: aTm = 1970-5-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-5-3 12:1:2 (DST=1) +aTm = 1970-5-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 10580462 +aTmM1 = 1970-5-3 11:1:2 (DST=0) +aTimet0 = 10584062 +aTm0 = 1970-5-3 12:1:2 (DST=0) +aTimetP1 = 10580462 +aTmP1 = 1970-5-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-6-3 12:1:2 +Before calling timegm: aTm = 1970-6-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-6-3 12:1:2 (DST=1) +Before calling timegm: aTm = 1970-6-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-6-3 13:1:2 (DST=1) +Before calling timegm: aTm = 1970-6-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-6-3 12:1:2 (DST=1) +aTm = 1970-6-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 13258862 +aTmM1 = 1970-6-3 11:1:2 (DST=0) +aTimet0 = 13262462 +aTm0 = 1970-6-3 12:1:2 (DST=0) +aTimetP1 = 13258862 +aTmP1 = 1970-6-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-7-3 12:1:2 +Before calling timegm: aTm = 1970-7-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-7-3 12:1:2 (DST=1) +Before calling timegm: aTm = 1970-7-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-7-3 13:1:2 (DST=1) +Before calling timegm: aTm = 1970-7-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-7-3 12:1:2 (DST=1) +aTm = 1970-7-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 15850862 +aTmM1 = 1970-7-3 11:1:2 (DST=0) +aTimet0 = 15854462 +aTm0 = 1970-7-3 12:1:2 (DST=0) +aTimetP1 = 15850862 +aTmP1 = 1970-7-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-8-3 12:1:2 +Before calling timegm: aTm = 1970-8-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-8-3 12:1:2 (DST=1) +Before calling timegm: aTm = 1970-8-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-8-3 13:1:2 (DST=1) +Before calling timegm: aTm = 1970-8-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-8-3 12:1:2 (DST=1) +aTm = 1970-8-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 18529262 +aTmM1 = 1970-8-3 11:1:2 (DST=0) +aTimet0 = 18532862 +aTm0 = 1970-8-3 12:1:2 (DST=0) +aTimetP1 = 18529262 +aTmP1 = 1970-8-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-9-3 12:1:2 +Before calling timegm: aTm = 1970-9-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-9-3 12:1:2 (DST=1) +Before calling timegm: aTm = 1970-9-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-9-3 13:1:2 (DST=1) +Before calling timegm: aTm = 1970-9-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-9-3 12:1:2 (DST=1) +aTm = 1970-9-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 21207662 +aTmM1 = 1970-9-3 11:1:2 (DST=0) +aTimet0 = 21211262 +aTm0 = 1970-9-3 12:1:2 (DST=0) +aTimetP1 = 21207662 +aTmP1 = 1970-9-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-10-3 12:1:2 +Before calling timegm: aTm = 1970-10-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-10-3 12:1:2 (DST=1) +Before calling timegm: aTm = 1970-10-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-10-3 13:1:2 (DST=1) +Before calling timegm: aTm = 1970-10-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-10-3 12:1:2 (DST=1) +aTm = 1970-10-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 23799662 +aTmM1 = 1970-10-3 11:1:2 (DST=0) +aTimet0 = 23803262 +aTm0 = 1970-10-3 12:1:2 (DST=0) +aTimetP1 = 23799662 +aTmP1 = 1970-10-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-11-3 12:1:2 +Before calling timegm: aTm = 1970-11-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-11-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-11-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-11-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-11-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-11-3 11:1:2 (DST=0) +aTm = 1970-11-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 26481662 +aTmM1 = 1970-11-3 12:1:2 (DST=0) +aTimet0 = 26481662 +aTm0 = 1970-11-3 12:1:2 (DST=0) +aTimetP1 = 26478062 +aTmP1 = 1970-11-3 11:1:2 (DST=0) +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-12-3 12:1:2 +Before calling timegm: aTm = 1970-12-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-12-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-12-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-12-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-12-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-12-3 11:1:2 (DST=0) +aTm = 1970-12-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 29073662 +aTmM1 = 1970-12-3 12:1:2 (DST=0) +aTimet0 = 29073662 +aTm0 = 1970-12-3 12:1:2 (DST=0) +aTimetP1 = 29070062 +aTmP1 = 1970-12-3 11:1:2 (DST=0) + +OK (1) +[OVAL] Cppunit-result =0 diff --git a/RelationalCool/tests/RelationalFolder/out.Windows.p1.adjustTimeZone b/RelationalCool/tests/RelationalFolder/out.Windows.p1.adjustTimeZone new file mode 100755 index 000000000..afa8f0956 --- /dev/null +++ b/RelationalCool/tests/RelationalFolder/out.Windows.p1.adjustTimeZone @@ -0,0 +1,29 @@ +Test test_gmtime_timegm +Before setting isdst: aTm = 1970-1-3 12:1:2 +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=-1) +After calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +After calling timegm: aTm = 1970-1-3 12:1:2 (DST=0) +Before calling timegm: aTm = 1970-1-3 12:1:2 (DST=1) +After calling timegm: aTm = 1970-1-3 11:1:2 (DST=0) +aTm = 1970-1-3 12:1:2 (DST=-1,0,+1) +aTimetM1 = 216062 +aTmM1 = 1970-1-3 12:1:2 (DST=0) +aTimet0 = 216062 +aTm0 = 1970-1-3 12:1:2 (DST=0) +aTimetP1 = 212462 +aTmP1 = 1970-1-3 11:1:2 (DST=0) + +\afs\all\cern.ch\sw\lcg\app\releases\COOL\COOL_1_2_0\src\RelationalCool\tests\RelationalFolder\test_RelationalFolder.cpp(287) : Assertion +Test name: cool::RelationalFolderTest.test_gmtime_timegm +- Expected : 12 + +- Actual : 11 + +gmtime(timegm(tm,isDst=+1))==tm : hour (Month[0-11]=0) + + +Failures !!! +Run: 1 Failure total: 1 Failures: 1 Errors: 0 +Error: CppUnit Failures +[OVAL] Cppunit-result =1 diff --git a/RelationalCool/tests/RelationalFolder/test_RelationalFolder.cpp b/RelationalCool/tests/RelationalFolder/test_RelationalFolder.cpp new file mode 100644 index 000000000..b6bf8defe --- /dev/null +++ b/RelationalCool/tests/RelationalFolder/test_RelationalFolder.cpp @@ -0,0 +1,5604 @@ +/** + + @file test_RelationalFolder.cpp + + @author Sven A. Schmidt + + @date 2004-11-05 + + */ + + +// Mysterious warning: always line (?) 35 even if I add lines in between! +// ../tests/RelationalFolder/test_RelationalFolder.cpp:35: instantiated from here +// cppunit/extensions/ExceptionTestCaseDecorator.h:96: warning: unused parameter 'e' + +#include "CoolDBUnitTest.h" + +#include "RelationalAccess/IRelationalService.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeListException.h" + +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/CompositeSelection.h" +#include "CoolKernel/FieldSelection.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IField.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/IRecordSelection.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordException.h" +#include "CoolKernel/RecordSelectionException.h" +#include "CoolKernel/RecordSpecification.h" + +#include "src/CoralApplication.h" +#include "src/RalDatabase.h" +#include "src/RelationalChannelTable.h" +#include "src/RelationalException.h" +#include "src/RelationalFolder.h" +#include "src/RelationalTableRow.h" +#include "src/RelationalTransaction.h" +#include "src/RelationalPayloadQuery.h" + + +#include "src/timeToString.h" + +// ---- this things are needed to force a drop of the connection +#include "src/RalDatabaseSvc.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" + +using coral::AttributeList; +using coral::AttributeListSpecification; + +#include <string> +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +#include <vector> +using std::vector; + +namespace cool { + +//! \brief RelationalFolder test class. +class RelationalFolderTest : public CoolDBUnitTest { + + CPPUNIT_TEST_SUITE( RelationalFolderTest ); + + CPPUNIT_TEST( test_getFolder ); + + CPPUNIT_TEST( test_folderSpecification ); + + CPPUNIT_TEST( test_findObject ); + CPPUNIT_TEST( test_findObject_MV ); + + CPPUNIT_TEST( test_findObject_wrongChannel ); + + CPPUNIT_TEST( test_findObject_after_dropNode_SV ); + CPPUNIT_TEST( test_findObject_after_dropNode_MV ); + + CPPUNIT_TEST( test_access_outofscope_db ); + CPPUNIT_TEST( test_flushStorageBuffer ); + + CPPUNIT_TEST( test_storeObject_bulk_SV ); + CPPUNIT_TEST( test_storeObject_bulk_SV_listReused ); + + // This takes: ~30sec Oracle, ~120sec MySQL, ~30sec sqlite + CPPUNIT_TEST( test_storeObject_bulk_70k ); + // This takes: ~60sec Oracle, ~240sec MySQL, ~60sec sqlite (after fixing bug #17903) + CPPUNIT_TEST( test_tagObject_bulk_70k ); // keep this disabled + + CPPUNIT_TEST( test_storeObject_bulk_MV ); + + CPPUNIT_TEST( test_MV_tag_and_retrieve ); + CPPUNIT_TEST( test_deleteTag_andRetag ); + + CPPUNIT_TEST( test_deleteTag_HEAD ); + + CPPUNIT_TEST( test_tagExistsElsewhere ); + CPPUNIT_TEST( test_tagNameScope ); + CPPUNIT_TEST( test_taggedNodes ); + CPPUNIT_TEST( test_tagName_case_sensitivity ); + + CPPUNIT_TEST( test_multiple_folders ); + + CPPUNIT_TEST( test_ValidityKey_boundaries ); + CPPUNIT_TEST( test_ValidityKeyException ); + + CPPUNIT_TEST( test_flushStorageBuffer_exception ); + CPPUNIT_TEST( test_flushStorageBuffer_exception_bug22474 ); + + CPPUNIT_TEST( test_browseObjects_SV ); + CPPUNIT_TEST( test_browseObjects_SV_lowercasePayload ); + CPPUNIT_TEST( test_browseObjects_SV_bug42101 ); + CPPUNIT_TEST( test_browseObjects_MV ); + CPPUNIT_TEST( test_browseObjects_MV_tag ); + + CPPUNIT_TEST( test_listTags_MV ); + CPPUNIT_TEST( test_listTags_SV ); + CPPUNIT_TEST( test_tagInsertionTime ); + CPPUNIT_TEST( test_tagDescription ); + + CPPUNIT_TEST( test_storeObjects_bulk_multichannel ); + + CPPUNIT_TEST( test_setDescription ); + + CPPUNIT_TEST( test_storeObject_SV_overlap ); + CPPUNIT_TEST( test_storeObject_SV_overlap_bulk ); + + CPPUNIT_TEST( test_storeObject_SV_unordered_closed ); + CPPUNIT_TEST( test_storeObject_SV_unordered_open ); + CPPUNIT_TEST( test_storeObject_SV_unordered_bulk_closed ); + CPPUNIT_TEST( test_storeObject_SV_unordered_bulk_open ); + CPPUNIT_TEST( test_storeObject_SV_unordered_bulk_open_2 ); + CPPUNIT_TEST( test_storeObject_SV_unordered_bulk_open_3 ); + CPPUNIT_TEST( test_storeObject_SV_unordered_MC_closed ); + CPPUNIT_TEST( test_storeObject_SV_unordered_MC_bulk_closed ); + CPPUNIT_TEST( test_storeObject_SV_unordered_MC_bulk_closed_oneperchannel ); + CPPUNIT_TEST( test_storeObject_SV_unordered_MC_bulk_closed_oneperchannel_2 ); + CPPUNIT_TEST( test_storeObject_SV_unordered_bulk_closed_oneback ); + CPPUNIT_TEST( test_storeObject_SV_unordered_has_new_data_flag ); + + CPPUNIT_TEST( test_browseObjects_channel_range_SV ); + CPPUNIT_TEST( test_browseObjects_all_channels_SV ); + CPPUNIT_TEST( test_browseObjects_channel_range_MV ); + CPPUNIT_TEST( test_browseObjects_all_channels_MV ); + + CPPUNIT_TEST( test_objectCount_SV ); + CPPUNIT_TEST( test_objectCount_MV ); + + CPPUNIT_TEST( test_node_nameclash ); + + CPPUNIT_TEST( test_existsUserTag ); + CPPUNIT_TEST( test_userTag_browseObjects_HEAD_insulation ); + CPPUNIT_TEST( test_browseObjects_userTag ); + CPPUNIT_TEST( test_userTag_example1 ); + CPPUNIT_TEST( test_storeObject_userTag_SV ); + CPPUNIT_TEST( test_tag_with_userTag ); + CPPUNIT_TEST( test_userTag_with_tag ); + + CPPUNIT_TEST( test_storeObject_userTag_userTagOnly ); + CPPUNIT_TEST( test_storeObject_userTag_userTagOnly_exceptions ); + + CPPUNIT_TEST( test_userTag_HEAD ); + + CPPUNIT_TEST( test_attribute_names ); + CPPUNIT_TEST( test_attribute_names_isa ); + CPPUNIT_TEST( test_attribute_name_order_string ); + + CPPUNIT_TEST( test_renamePayload ); + + CPPUNIT_TEST( test_extendPayloadSpecification ); + CPPUNIT_TEST( test_extendPayloadSpecificationExceptions ); + + CPPUNIT_TEST( test_storeObject_emptyRecord ); + + CPPUNIT_TEST( test_browseObjects_channelName_SV_all ); + CPPUNIT_TEST( test_browseObjects_channelName_SV_range ); + CPPUNIT_TEST( test_browseObjects_channelName_MV_all ); + CPPUNIT_TEST( test_browseObjects_channelName_MV_tag ); + CPPUNIT_TEST( test_browseObjects_channelName_MV_userTag ); + + CPPUNIT_TEST( test_findObjects_channelName_SV ); + CPPUNIT_TEST( test_findObjects_channelName_MV ); + CPPUNIT_TEST( test_findObjects_channelName_MV_tag ); + CPPUNIT_TEST( test_findObjects_channelName_MV_userTag ); + + CPPUNIT_TEST( test_countObjects_channelName_SV_all ); + CPPUNIT_TEST( test_countObjects_channelName_SV_range ); + CPPUNIT_TEST( test_countObjects_channelName_MV_all ); + CPPUNIT_TEST( test_countObjects_channelName_MV_tag ); + CPPUNIT_TEST( test_countObjects_channelName_MV_userTag ); + + CPPUNIT_TEST( test_setTagDescription_currentHeadTag ); + CPPUNIT_TEST( test_setTagDescription_headAsOfDateTag ); + CPPUNIT_TEST( test_setTagDescription_userTag ); + CPPUNIT_TEST( test_setTagDescription_TagNotFound ); + CPPUNIT_TEST( test_setTagDescription_256 ); + CPPUNIT_TEST( test_setTagDescription_headTag ); // bug #33989 + + CPPUNIT_TEST( test_cloneHeadTag ); + +#ifdef COOL280 + CPPUNIT_TEST( test_manualTransaction_renamePayload ); + CPPUNIT_TEST( test_manualTransaction_extendPayloadSpecification ); +#endif + + CPPUNIT_TEST( test_RecordSelectionBrowseObjects ); + + CPPUNIT_TEST( test_truncateIOV ); + + CPPUNIT_TEST( test_browseObjects_bug42708 ); + CPPUNIT_TEST( test_browseObjects_bug42708_exception ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + RecordSpecification payloadSpec; + + void test_browseObjects_bug42708_exception() + { + IFolderPtr folder = m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION); + + for ( int i = 0; i < 100; ++i ) + folder->storeObject( 0, 10, dummyPayload( i ), (ChannelId)i ); + + ChannelSelection channels( 0 ); + for ( int i = 1; i < 51; ++i ) + channels.addRange( 2*i, 2*i ); // [0,0], [2,2]... [100,100] (51 ranges) + + try + { + IObjectIteratorPtr objs = folder->browseObjects(0, + ValidityKeyMax, + channels ); + CPPUNIT_FAIL("browsing with 51 non-contiguous channel selection ranges " + "must fail"); + } catch ( RelationalException& e ) { + std::string expected = "Non-contiguous channel selection only " + "supported for up to 50 ranges"; + CPPUNIT_ASSERT_EQUAL_MESSAGE("exception caught", + expected, std::string(e.what())); + } + + } + + void test_browseObjects_bug42708() { + IFolderPtr folder = m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION); + + for ( int i = 0; i < 100; ++i ) + folder->storeObject( 0, 10, dummyPayload( i ), (ChannelId)i ); + + ChannelSelection channels( 0 ); + for ( int i = 1; i < 50; ++i ) + channels.addRange( 2*i, 2*i ); // [0,0], [2,2]... [98,98] (50 ranges) + + IObjectIteratorPtr objs = folder->browseObjects(0, + ValidityKeyMax, + channels ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 50u, + (unsigned int)objs->size() ); + + // Only test the first 5 objects + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 channel", + (ChannelId)0, obj->channelId() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 channel", + (ChannelId)2, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 channel", + (ChannelId)4, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 4 payload", + dummyPayload( 6 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 channel", + (ChannelId)6, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 5 payload", + dummyPayload( 8 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 channel", + (ChannelId)8, obj->channelId() ); + } + +#ifdef COOL280 + /// Tests renamePayload behavior in manual transaction mode + void test_manualTransaction_renamePayload() { + IFolderPtr folder = m_db->createFolder( "/A1", payloadSpec ); + + ITransactionPtr t = m_db->startTransaction(); + + try { + folder->renamePayload("I", "J"); + CPPUNIT_FAIL("renamePayload in manual transaction mode must fail"); + } catch ( RelationalException& e ) { + std::string expected = "Cannot rename payload fields in manual " + "transaction mode"; + CPPUNIT_ASSERT_EQUAL_MESSAGE("exception caught", + expected, std::string(e.what())); + } + } + + + /// Tests extendPayloadSpecification behavior in manual transaction mode + void test_manualTransaction_extendPayloadSpecification() { + IFolderPtr folder = m_db->createFolder( "/A1", payloadSpec ); + + ITransactionPtr t = m_db->startTransaction(); + + try { + RecordSpecification newFields; + newFields.extend("Y", StorageType::Int32); + folder->extendPayloadSpecification(Record(newFields)); + CPPUNIT_FAIL("extendPayloadSpecification in manual transaction mode " + "must fail"); + } catch ( RelationalException& e ) { + std::string expected = ("Cannot extend payload specification in manual " + "transaction mode"); + CPPUNIT_ASSERT_EQUAL_MESSAGE("exception caught", + expected, std::string(e.what())); + } + } +#endif + + /// Tests setTagDescription for the HEAD tag (bug #33989) + void test_setTagDescription_headTag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + + try { + folder->setTagDescription( "HEAD", "desc" ); + CPPUNIT_FAIL( "setTagDescription for HEAD tag should fail!" ); + } + catch ( Exception& ) {} + } + + + /// Tests setTagDesction for a description exceeding the 255 character limit + /// (task #6394). + void test_setTagDescription_256() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0, "user tag" ); + + std::string s256(256, '*'); + try { + folder->setTagDescription( "user tag", s256 ); + CPPUNIT_FAIL( "setTagDescription with >255 chars should fail!" ); + } + catch ( Exception& ) {} + } + + + /// Tests setTagDesction for a non-existing tag (task #6394). + void test_setTagDescription_TagNotFound() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0, "user tag" ); + + try + { + folder->setTagDescription( "non-existing tag", "new description" ); + CPPUNIT_FAIL( "setTagDescription with non-existing tag should fail!" ); + } + catch ( TagNotFound& ) {} + } + + + /// Tests setTagDesction for a user tag (task #6394). + void test_setTagDescription_userTag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0, "user tag" ); + + folder->setTagDescription( "user tag", "new description" ); + + CPPUNIT_ASSERT_EQUAL( std::string("new description"), + folder->tagDescription("user tag") ); + } + + + /// Tests setTagDesction for an 'asof' date tag (task #6394). + void test_setTagDescription_headAsOfDateTag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + IObjectPtr obj = folder->findObject( 0, 0 ); + folder->tagHeadAsOfDate( obj->insertionTime(), + "head tag", "original description" ); + + CPPUNIT_ASSERT_EQUAL( std::string("original description"), + folder->tagDescription("head tag") ); + + folder->setTagDescription( "head tag", "new description" ); + + CPPUNIT_ASSERT_EQUAL( std::string("new description"), + folder->tagDescription("head tag") ); + } + + + /// Tests setTagDesction for a current head tag (task #6394). + void test_setTagDescription_currentHeadTag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "head tag", "original description" ); + + CPPUNIT_ASSERT_EQUAL( std::string("original description"), + folder->tagDescription("head tag") ); + + folder->setTagDescription( "head tag", "new description" ); + + CPPUNIT_ASSERT_EQUAL( std::string("new description"), + folder->tagDescription("head tag") ); + } + + + /// Tests countObjects (MV folder) via the channel name interface + /// selecting user tagged IOVs + void test_countObjects_channelName_MV_userTag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0, "user tag" ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0, "user tag" ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0, "user tag" ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1, "user tag" ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1, "user tag" ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1, "user tag" ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2, "user tag" ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2, "user tag" ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2, "user tag" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + + ChannelSelection chsel( "ch 1" ); + unsigned int count = folder->countObjects( 0, + ValidityKeyMax, + chsel, + "user tag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, count ); + } + + + /// Tests countObjects (MV folder) via the channel name interface + /// selecting tagged IOVs + void test_countObjects_channelName_MV_tag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + folder->tagCurrentHead( "tag" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + + ChannelSelection chsel( "ch 1" ); + unsigned int count = folder->countObjects( 0, + ValidityKeyMax, + chsel, + "tag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, count ); + } + + + /// Tests countObjects (MV folder) via the channel name interface + /// selecting all IOVs + void test_countObjects_channelName_MV_all() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + ChannelSelection chsel( "ch 1" ); + unsigned int count = folder->countObjects( 0, ValidityKeyMax, chsel ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, count ); + } + + + /// Tests countObjects (SV folder) via the channel name interface + /// selecting a range of IOVs + void test_countObjects_channelName_SV_range() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + ChannelSelection chsel( "ch 1" ); + unsigned int count = folder->countObjects( 5, 15, chsel ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, count ); + } + + + /// Tests countObjects (SV folder) via the channel name interface + /// selecting all IOVs + void test_countObjects_channelName_SV_all() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + ChannelSelection chsel( "ch 1" ); + unsigned int count = folder->countObjects( 0, ValidityKeyMax, chsel ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, count ); + } + + IObjectPtr getNext( IObjectIteratorPtr objs) { + if (!objs->goToNext()) + CPPUNIT_FAIL("objs has no next row"); + return IObjectPtr( objs->currentRef().clone() ); + }; + + /// Tests findObjects for a MV folder with the channel name interface + /// selecting from a user tag. + void test_findObjects_channelName_MV_userTag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0, "user tag" ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0, "user tag" ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0, "user tag" ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1, "user tag" ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1, "user tag" ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1, "user tag" ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2, "user tag" ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2, "user tag" ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2, "user tag" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + + ChannelSelection chsel( "ch 1" ); + IObjectIteratorPtr objs = folder->findObjects( 5, chsel, "user tag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 1u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests findObjects for a MV folder with the channel name interface + /// selecting from a tag. + void test_findObjects_channelName_MV_tag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + folder->tagCurrentHead( "tag" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + + ChannelSelection chsel( "ch 1" ); + IObjectIteratorPtr objs = folder->findObjects( 5, chsel, "tag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 1u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests findObjects for a MV folder with the channel name interface + void test_findObjects_channelName_MV() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + ChannelSelection chsel( "ch 1" ); + IObjectIteratorPtr objs = folder->findObjects( 5, chsel ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 1u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests findObjects for a SV folder with the channel name interface + void test_findObjects_channelName_SV() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + ChannelSelection chsel( "ch 1" ); + IObjectIteratorPtr objs = folder->findObjects( 5, chsel ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 1u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests object browsing (MV folder) via the channel name interface + /// selecting user tagged IOVs + void test_browseObjects_channelName_MV_userTag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0, "user tag" ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0, "user tag" ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0, "user tag" ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1, "user tag" ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1, "user tag" ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1, "user tag" ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2, "user tag" ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2, "user tag" ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2, "user tag" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + + ChannelSelection chsel( "ch 1" ); + IObjectIteratorPtr objs = folder->browseObjects( 0, + ValidityKeyMax, + chsel, + "user tag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL( ValidityKeyMax, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests object browsing (MV folder) via the channel name interface + /// selecting tagged IOVs + void test_browseObjects_channelName_MV_tag() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + folder->tagCurrentHead( "tag" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + + ChannelSelection chsel( "ch 1" ); + IObjectIteratorPtr objs = folder->browseObjects( 0, + ValidityKeyMax, + chsel, + "tag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL( ValidityKeyMax, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests object browsing (MV folder) via the channel name interface + /// selecting all IOVs + void test_browseObjects_channelName_MV_all() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + ChannelSelection chsel( "ch 1" ); + IObjectIteratorPtr objs = folder->browseObjects( 0, ValidityKeyMax, chsel ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL( ValidityKeyMax, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests object browsing (SV folder) via the channel name interface + /// selecting a range of IOVs + void test_browseObjects_channelName_SV_range() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + ChannelSelection chsel( "ch 1" ); + IObjectIteratorPtr objs = folder->browseObjects( 5, 15, chsel ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests object browsing (SV folder) via the channel name interface + /// selecting all IOVs + void test_browseObjects_channelName_SV_all() { + IFolderPtr folder = + m_db->createFolder("/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION); + folder->createChannel( 1, "ch 1" ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 1 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 1 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 1 ); + folder->storeObject( 0, 10, dummyPayload( 0 ), 2 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 2 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 2 ); + + ChannelSelection chsel( "ch 1" ); + IObjectIteratorPtr objs = folder->browseObjects( 0, ValidityKeyMax, chsel ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL( ValidityKeyMax, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests creating and retrieving a folder. + /// This test is implemented in more detail with respect to the folder + /// attributes in test_RalDatabase + void test_folderSpecification() { + try { + m_db->createFolder( "/f_sv", payloadSpec, "a description" ); + m_db->createFolder( "/f_mv", payloadSpec, "a description", + FolderVersioning::MULTI_VERSION ); + + FolderSpecification fs_sv( FolderVersioning::SINGLE_VERSION, + payloadSpec ); + FolderSpecification fs_mv( FolderVersioning::MULTI_VERSION, + payloadSpec ); + + m_db->createFolder( "/fs_sv", fs_sv, "a description" ); + m_db->createFolder( "/fs_mv", fs_mv, "a description" ); + + IFolderPtr folder = m_db->getFolder( "/f_sv" ); + CPPUNIT_ASSERT( fs_sv == folder->folderSpecification() ); + + folder = m_db->getFolder( "/f_mv" ); + CPPUNIT_ASSERT( fs_mv == folder->folderSpecification() ); + + folder = m_db->getFolder( "/fs_sv" ); + CPPUNIT_ASSERT( fs_sv == folder->folderSpecification() ); + + folder = m_db->getFolder( "/fs_mv" ); + CPPUNIT_ASSERT( fs_mv == folder->folderSpecification() ); + } catch ( Exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + /// Tests storeObject using an empty Record (bug #24464) + /// Also test the payloadValue templated method (task #2859) + void test_storeObject_emptyRecord() { + IFolderPtr folder = m_db->createFolder + ( "/f1", payloadSpec, "", FolderVersioning::SINGLE_VERSION ); + Record payload10; + Record payload20( dummyPayload( 20 ) ); + Record payload30; + RecordSpecification payload40Spec; // reshuffle the order + { + payload40Spec.extend("X",StorageType::Float); + payload40Spec.extend("I",StorageType::Int32); + payload40Spec.extend("S",StorageType::String255); + } + Record payload40( payload40Spec ); + { + int index = 40; + payload40["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload40["S"].setValue<String255>( s.str() ); + payload40["X"].setValue<Float>( (float)(index/1000.) ); + } + Record payload50; + ChannelId chId = 1; + folder->setupStorageBuffer(); + folder->storeObject( 10, 20, payload10, chId ); + folder->storeObject( 20, 30, payload20, chId ); + folder->storeObject( 30, 40, payload30, chId ); + folder->storeObject( 40, 50, payload40, chId ); + folder->storeObject( 50, 60, payload50, chId ); + folder->flushStorageBuffer(); + + IObjectPtr obj = folder->findObject( 10, chId ); + CPPUNIT_ASSERT( obj.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p10 size", (UInt32)3, obj->payload().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p10[I] null", true, obj->payload()["I"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p10[I] value", std::string("NULL"), obj->payloadValue("I") ); + CPPUNIT_ASSERT_THROW + ( obj->payloadValue<Int32>("I"), FieldIsNull ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p10[X] null", true, obj->payload()["X"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p10[X] value", std::string("NULL"), obj->payloadValue("X") ); + CPPUNIT_ASSERT_THROW + ( obj->payloadValue<Float>("X"), FieldIsNull ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p10[S]", std::string(""), obj->payload()["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p10[S] null", false, obj->payload()["S"].isNull() ); // "", not null + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p10[S] value", std::string(""), obj->payloadValue("S") ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p10[S] val<>", std::string(""), obj->payloadValue<String255>("S") ); + + // Warning: hardcode string representations of dummyPayload + obj = folder->findObject( 20, chId ); + CPPUNIT_ASSERT( obj.get() != 0 ); + CPPUNIT_ASSERT_MESSAGE( "p20", obj->payload() == payload20 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p20[I] value", std::string("20"), obj->payloadValue("I") ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p20[I] val<>", 20, obj->payloadValue<Int32>("I") ); + CPPUNIT_ASSERT_THROW + ( obj->payloadValue<Float>("I"), FieldWrongCppType ); + CPPUNIT_ASSERT_THROW + ( obj->payloadValue<String255>("I"), FieldWrongCppType ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p20[X] value", std::string("0.02"), obj->payloadValue("X") ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p20[X] val<>", (Float)0.02, obj->payloadValue<Float>("X") ); + CPPUNIT_ASSERT_THROW + ( obj->payloadValue<Int32>("X"), FieldWrongCppType ); + CPPUNIT_ASSERT_THROW + ( obj->payloadValue<String255>("X"), FieldWrongCppType ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p20[S] value", std::string("Object 20"), obj->payloadValue("S") ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p20[S] val<>", std::string("Object 20"), + obj->payloadValue<String255>("S") ); + CPPUNIT_ASSERT_THROW + ( obj->payloadValue<Int32>("S"), FieldWrongCppType ); + CPPUNIT_ASSERT_THROW + ( obj->payloadValue<Float>("S"), FieldWrongCppType ); + + obj = folder->findObject( 30, chId ); + CPPUNIT_ASSERT( obj.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p30 size", (UInt32)3, obj->payload().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p30[I] null", true, obj->payload()["I"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p30[X] null", true, obj->payload()["X"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p30[S]", std::string(""), obj->payload()["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p30[S] null", false, obj->payload()["S"].isNull() ); // "", not null + + obj = folder->findObject( 40, chId ); + CPPUNIT_ASSERT( obj.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p40 size", (UInt32)3, obj->payload().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p40[I] null", false, obj->payload()["I"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p40[I]", payload40["I"].data<int>(), + obj->payload()["I"].data<int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p40[X] null", false, obj->payload()["X"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p40[X]", payload40["X"].data<float>(), + obj->payload()["X"].data<float>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p40[S] null", false, obj->payload()["S"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p40[S]", payload40["S"].data<std::string>(), + obj->payload()["S"].data<std::string>() ); + + obj = folder->findObject( 50, chId ); + CPPUNIT_ASSERT( obj.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p50 size", (UInt32)3, obj->payload().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p50[I] null", true, obj->payload()["I"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p50[X] null", true, obj->payload()["X"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p50[S]", std::string(""), obj->payload()["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "p50[S] null", false, obj->payload()["S"].isNull() ); // "", not null + } + + + /// Tests a special case (bug) related to an order column in conjunction + /// with a string type field. (Related to bug #16189.) + void test_attribute_name_order_string() { + RecordSpecification spec; + spec.extend( "order", StorageType::String255 ); + IFolderPtr f = m_db->createFolder( "/f", spec ); + CPPUNIT_ASSERT( m_db->existsFolder( "/f" ) ); + coral::AttributeList payload = Record( spec ).attributeList(); + f->storeObject( 0, 2, payload, 0 ); + IObjectPtr obj = f->findObject( 1, 0 ); + CPPUNIT_ASSERT( obj.get() != 0 ); + } + + + /// Related to bug #15871. + /// As of COOL_2_0_0 it is impossible to create a payload name "is-a". + void test_attribute_names_isa() + { + RecordSpecification spec; + spec.extend( "is-a", StorageType::Int32 ); + CPPUNIT_ASSERT_THROW( m_db->createFolder( "/f", spec ), + PayloadSpecificationInvalidFieldName ); + CPPUNIT_ASSERT( ! m_db->existsFolder( "/f" ) ); + } + + + /// Tests that attribute names are properly quoted by the backends, + /// i.e. that for example reserved words like 'order' can be used as + /// attribute names. (Related to bug #16189.) + void test_attribute_names() { + RecordSpecification spec; + + spec.extend( "select", StorageType::Int32 ); + spec.extend( "from", StorageType::Int32 ); + spec.extend( "where", StorageType::Int32 ); + spec.extend( "order", StorageType::Int32 ); + spec.extend( "by", StorageType::Int32 ); + spec.extend( "in", StorageType::Int32 ); + spec.extend( "group", StorageType::Int32 ); + spec.extend( "delete", StorageType::Int32 ); + spec.extend( "drop", StorageType::Int32 ); + spec.extend( "int", StorageType::Int32 ); + spec.extend( "float", StorageType::Int32 ); + spec.extend( "double", StorageType::Int32 ); + spec.extend( "varchar", StorageType::Int32 ); + spec.extend( "varchar2", StorageType::Int32 ); + spec.extend( "char", StorageType::Int32 ); + spec.extend( "number", StorageType::Int32 ); + spec.extend( "decimal", StorageType::Int32 ); + spec.extend( "blob", StorageType::Int32 ); + spec.extend( "clob", StorageType::Int32 ); + spec.extend( "string", StorageType::Int32 ); + IFolderPtr f = m_db->createFolder( "/f", spec ); + CPPUNIT_ASSERT( m_db->existsFolder( "/f" ) ); + coral::AttributeList payload = Record( spec ).attributeList(); + f->storeObject( 0, 2, payload, 0 ); + IObjectPtr obj = f->findObject( 1, 0 ); + CPPUNIT_ASSERT( obj.get() != 0 ); + } + + + /// Tests user tag behavior with the reserved name 'HEAD' + void test_userTag_HEAD() { + try { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + ChannelId ch = 0; + folder->storeObject( 0, 10, dummyPayload( 1 ), ch, "HEAD" ); + // AV The above should not trow: "" and "HEAD" are equivalent, + // this is the default argument for storing IOVs with no user tag! + //CPPUNIT_FAIL( "Using HEAD as a user tag should fail" ); + } + //catch ( ReservedHeadTag& ) {} + catch ( std::exception& e ) { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + } + + void test_cloneHeadTag() + { + try + { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + + folder->storeObject( 0, 10, dummyPayload( 0010 ), 0); + folder->storeObject( 5, 20, dummyPayload( 0520 ), 0); + folder->storeObject( 3, 30, dummyPayload( 0330 ), 1); + folder->storeObject( 20, 40, dummyPayload( 2040 ), 1); + folder->storeObject( 3, 30, dummyPayload( 0330 ), 9); + folder->storeObject( 20, 40, dummyPayload( 2040 ), 9); + folder->storeObject( 40, 60, dummyPayload( 2040 ), 9); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Count ", + 2u, folder->countObjects(0,100,0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Count ", + 2u, folder->countObjects(0,100,1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Count ", + 3u, folder->countObjects(0,100,9)); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Exist ", false, + m_db->existsTag("A1") ); + + folder->tagCurrentHead("A1","tag1"); + + folder->storeObject( 35, 50, dummyPayload( 3550 ), 1); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Count ", + 3u, folder->countObjects(0,100,1)); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Exist ", false, + m_db->existsTag("A1_clone") ); + folder->cloneTagAsUserTag("A1","A1_clone","clone of tag A1"); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Exist ", true, + m_db->existsTag("A1_clone") ); + + // check if A1_clone is correct + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5 Count ", 2u, folder->countObjects(0,100,0,"A1_clone")); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6 Count ", 2u, folder->countObjects(0,100,1,"A1_clone")); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "7 Count ", 3u, folder->countObjects(0,100,9,"A1_clone")); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Clone tag description ", + std::string("clone of tag A1"), + folder->tagDescription("A1_clone")); + + // head remains unchanged + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 Count ", + 2u, folder->countObjects(0,100,0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 Count ", + 3u, folder->countObjects(0,100,1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 Count ", + 3u, folder->countObjects(0,100,9)); + + // inserting into head still works without bulk buffer + folder->storeObject( 55, 70, dummyPayload( 5570 ), 9); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "11 Count ", + 4u, folder->countObjects(0,100,9)); + + // can't reuse tag names for cloning + CPPUNIT_ASSERT_THROW( folder->cloneTagAsUserTag( "HEAD", "A1" ), + TagExists); + CPPUNIT_ASSERT_THROW( folder->cloneTagAsUserTag( "HEAD", "A1_clone" ), + TagExists); + + // but we can force to overwrite user tags + folder->cloneTagAsUserTag( "HEAD", "A1_clone", + "updated clone of tag HEAD",true); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "12 Count ", 2u, folder->countObjects(0,100,0,"A1_clone")); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "13 Count ", 3u, folder->countObjects(0,100,1,"A1_clone")); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "14 Count ", 4u, folder->countObjects(0,100,9,"A1_clone")); + + } + catch ( std::exception& e ) + { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + } + + /// Tests tagging behavior for user tagging with an already issued tag + void test_userTag_with_tag() { + try { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + ChannelId ch = 0; + folder->storeObject( 0, 10, dummyPayload( 1 ), ch ); + folder->tagCurrentHead( "A" ); + CPPUNIT_ASSERT_MESSAGE( "tag exists", m_db->existsTag( "A" ) ); + folder->storeObject( 0, 10, dummyPayload( 1 ), ch, "A" ); + CPPUNIT_FAIL( "this point should not be reached - exception expected" ); + } catch ( TagExists& e ) { + CPPUNIT_ASSERT_EQUAL( string("Tag 'A' already exists"), + string( e.what() ) ); + } + } + + + /// Tests tagging behavior for tagging with an already issued user tag + void test_tag_with_userTag() { + try { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + ChannelId ch = 0; + folder->storeObject( 0, 10, dummyPayload( 1 ), ch, "A" ); + CPPUNIT_ASSERT_MESSAGE( "user tag exists", + folder->existsUserTag( "A" ) ); + folder->tagCurrentHead( "A" ); + CPPUNIT_FAIL( "this point should not be reached - exception expected" ); + } catch ( TagExists& e ) { + CPPUNIT_ASSERT_EQUAL( string("Tag 'A' already exists"), + string( e.what() ) ); + } + } + + + /// Tests that storeObjects with a user tag on a SV folder throws an + /// exception. + void test_storeObject_userTag_SV() { + try { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::SINGLE_VERSION); + ChannelId ch = 0; + folder->storeObject( 0, 10, dummyPayload( 1 ), ch, "A" ); + CPPUNIT_FAIL( "this point should not be reached - exception expected" ); + } catch ( FolderIsSingleVersion& e ) { + FolderIsSingleVersion + eExp( "/a", "Cannot store a SV object with user tag: A", "" ); + CPPUNIT_ASSERT_EQUAL + ( std::string( eExp.what() ), std::string( e.what() ) ); + } + } + + + /// Tests storeObjects with a user tag and flag userTagOnly==true + void test_storeObject_userTag_userTagOnly() + { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + ChannelId ch = 0; + try + { + folder->storeObject( 0, 100, dummyPayload( 1 ), ch, "A", false ); + folder->storeObject( 10, 20, dummyPayload( 2 ), ch, "", false ); + folder->storeObject( 80, 90, dummyPayload( 3 ), ch, "A", true ); + folder->storeObject( 10, 90, dummyPayload( 4 ), ch, "B", true ); + folder->storeObject( 30, 70, dummyPayload( 5 ), ch, "B", false ); + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ch, + "" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 5u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 id", 8u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)10, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 id", 7u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)20, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 id", 26u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)30, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 id", 25u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 4 payload", + dummyPayload( 5 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 since", + (ValidityKey)30, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 until", + (ValidityKey)70, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 id", 27u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 5 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 since", + (ValidityKey)70, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 until", + (ValidityKey)100, obj->until() ); + } + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ch, + "A" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 id", 17u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)80, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 id", 16u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)80, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)90, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 id", 18u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)90, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)100, obj->until() ); + } + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ch, + "B" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 id", 29u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)30, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 id", 28u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 5 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)30, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)70, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 id", 30u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)70, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)90, obj->until() ); + } + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + + } + + + /// Tests exceptions from storeObjects with a user tag + /// and flag userTagOnly==true + void test_storeObject_userTag_userTagOnly_exceptions() + { + IFolderPtr fSV = m_db->createFolder( "/sv", + payloadSpec, + "desc", + FolderVersioning::SINGLE_VERSION); + IFolderPtr fMV = m_db->createFolder( "/mv", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + ChannelId ch = 0; + + // SV exceptions + { + try + { + bool userTagOnly = true; + fSV->storeObject( 0, 10, dummyPayload( 1 ), ch, "A", userTagOnly ); + CPPUNIT_FAIL( "userTagOnly==true should throw for SV" ); + } + catch ( RelationalException& ){} + } + + // MV exception - userTag="" + { + try + { + bool userTagOnly = true; + fMV->storeObject( 0, 10, dummyPayload( 1 ), ch, "", userTagOnly ); + CPPUNIT_FAIL( "userTagOnly==true should throw for HEAD" ); + } + catch ( RelationalException& ){} + } + + // MV exception - mix in bulk insertion + { + fMV->setupStorageBuffer( true ); + bool userTagOnly = true; + fMV->storeObject( 0, 10, dummyPayload( 1 ), ch, "A", userTagOnly ); + try + { + userTagOnly = false; + fMV->storeObject( 10, 20, dummyPayload( 2 ), ch, "A", userTagOnly ); + CPPUNIT_FAIL( "userTagOnly should throw if mixed" ); + } + catch ( RelationalException& ){} + userTagOnly = true; + fMV->storeObject( 20, 30, dummyPayload( 3 ), ch, "A", userTagOnly ); + fMV->flushStorageBuffer(); + } + + } + + + // Tests the user tag implementation for example #1 + void test_userTag_example1() { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + ChannelId ch = 0; + folder->storeObject( 0, 10, dummyPayload( 1 ), ch ); + folder->storeObject( 1, 5, dummyPayload( 2 ), ch, "A" ); + folder->storeObject( 3, 8, dummyPayload( 3 ), ch, "B" ); + folder->storeObject( 2, 4, dummyPayload( 4 ), ch, "A" ); + folder->storeObject( 3, 7, dummyPayload( 5 ), ch, "B" ); + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ch ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD object count", 6u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)1, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)1, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)2, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)3, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 4 payload", + dummyPayload( 5 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 since", + (ValidityKey)3, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 until", + (ValidityKey)7, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 5 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 since", + (ValidityKey)7, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 until", + (ValidityKey)8, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 6 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 since", + (ValidityKey)8, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 until", + (ValidityKey)10, obj->until() ); + } + + { + CPPUNIT_ASSERT_MESSAGE( "tag 'A'", m_db->existsTag( "A" ) ); + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ch, + "A"); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag A object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)1, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)5, obj->until() ); + } + + { + CPPUNIT_ASSERT_MESSAGE( "tag 'B'", m_db->existsTag( "B" ) ); + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ch, + "B" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag B object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 5 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)3, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)7, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)7, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)8, obj->until() ); + } + } + + + /// Tests browsing a user tag selection + void test_browseObjects_userTag() { + try { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + ChannelId ch = 0; + folder->storeObject( 0, 10, dummyPayload( 1 ), ch, "A" ); + folder->storeObject( 1, 5, dummyPayload( 2 ), ch, "A" ); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ch, + "A" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 id", 11u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)1, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 id", 10u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)1, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)5, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 id", 12u, obj->objectId() ); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)10, obj->until() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + // Tests that user tag insertion is treated like normal insertion + // with respect to the HEAD + // In other words when the HEAD is browsed the following two insertions + // are absolutely identical: + // 1) + // folder->storeObject( 0, 10, dummyPayload( 1 ), ch ); + // folder->storeObject( 1, 5, dummyPayload( 2 ), ch ); + // 2) + // folder->storeObject( 0, 10, dummyPayload( 1 ), ch ); + // folder->storeObject( 1, 5, dummyPayload( 2 ), ch, "A" ); + void test_userTag_browseObjects_HEAD_insulation() { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + ChannelId ch = 0; + folder->storeObject( 0, 10, dummyPayload( 1 ), ch ); + folder->storeObject( 1, 5, dummyPayload( 2 ), ch, "A" ); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ch ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)1, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)1, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)5, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)10, obj->until() ); + } + + + /// Tests existsUserTag + void test_existsUserTag() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + CPPUNIT_ASSERT_MESSAGE( "no user tag yet", + ! folder->existsUserTag( "A" ) ); + CPPUNIT_ASSERT_MESSAGE( "no tag yet", ! m_db->existsTag( "A" ) ); + + folder->storeObject( 0, 10, dummyPayload( 1 ), (ChannelId)0, "A" ); + + CPPUNIT_ASSERT_MESSAGE( "user tag exists", + folder->existsUserTag( "A" ) ); + CPPUNIT_ASSERT_MESSAGE( "tag exists", m_db->existsTag( "A" ) ); + } + + + /// Tests behavior when nodes with conflicting names are attempted to be + /// created + /// Issue raised by Shaun Roe 2005-12-14. Bug #14248 + void test_node_nameclash() { + try { + IFolderPtr folder = m_db->createFolder( "/a", payloadSpec ); + folder = m_db->createFolder( "/a/b", payloadSpec ); + CPPUNIT_FAIL( "exception expected" ); + } catch ( cool::RelationalException& e ) { + std::string msg = "Cannot create node '/a/b', because the parent " + "path contains a leaf node"; + CPPUNIT_ASSERT_EQUAL( msg, std::string( e.what() ) ); + } + } + + + /// Tests countObject for a MV folder + void test_objectCount_MV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), ch ); + folder->storeObject( 2, ValidityKeyMax, dummyPayload( 2 ), ch ); + folder->storeObject( 3, ValidityKeyMax, dummyPayload( 3 ), ch ); + folder->storeObject( 4, ValidityKeyMax, dummyPayload( 4 ), ch ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "A" ); + + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "B" ); + + ValidityKey since = 1; + ValidityKey until = 3; + ChannelSelection channels( 2, 3 ); + + int count = folder->countObjects( since, until, channels, "A" ); + + CPPUNIT_ASSERT_EQUAL( 6, count ); + } + + + /// Tests countObject for a SV folder + void test_objectCount_SV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), ch ); + folder->storeObject( 2, ValidityKeyMax, dummyPayload( 2 ), ch ); + folder->storeObject( 3, ValidityKeyMax, dummyPayload( 3 ), ch ); + folder->storeObject( 4, ValidityKeyMax, dummyPayload( 4 ), ch ); + } + folder->flushStorageBuffer(); + + ValidityKey since = 1; + ValidityKey until = 3; + ChannelSelection channels( 2, 3 ); + + int count = folder->countObjects( since, until, channels ); + + CPPUNIT_ASSERT_EQUAL( 6, count ); + } + + + /// Tests storing unordered, non-overlapping SV IOVS (all closed). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #3 is provided + /// (back-insertion is allowed for single-IOV single-channel insertion). + void test_storeObject_SV_unordered_closed() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + } + + + /// Tests that the HAS_NEW_DATA flag is properly reset for back-inserted + /// IOVs. + void test_storeObject_SV_unordered_has_new_data_flag() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + + /// We don't typically go below the public/relational interface layer + /// in this unit test suite. For that reason this test belongs more in + /// test_RalObjectMgr. However, with respect to what functionality is + /// being tested this test is more at home here. + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + RalDatabase* ralDb = dynamic_cast<RalDatabase*>(m_db.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalChannelTable channelTable( *ralDb, *relfolder ); + RelationalTableRow row = channelTable.fetchRowForId( 0 ); + CPPUNIT_ASSERT_EQUAL + ( (ChannelId)0, row["CHANNEL_ID"].data<ChannelId>() ); + CPPUNIT_ASSERT_EQUAL + ( 1u, row["LAST_OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL + ( false, row["HAS_NEW_DATA"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), row["CHANNEL_NAME"].data<std::string>() ); + transaction.commit(); + } + + + /// Tests storing unordered, non-overlapping SV IOVS (all closed but one). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #3 is provided + /// (back-insertion is allowed for single-IOV single-channel insertion). + void test_storeObject_SV_unordered_open() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->storeObject( 4, ValidityKeyMax, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 3, dummyPayload( 2 ), 0 ); + folder->storeObject( 5, 6, dummyPayload( 3 ), 0 ); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)3, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)5, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)6, obj->until() ); + } + + + /// Tests storing unordered, non-overlapping SV IOVS (all closed). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #1 is NOT YET provided + /// (back-insertion is not yet allowed for bulk inserting + /// more than one IOV per channel - in single or multi channel mode). + void test_storeObject_SV_unordered_bulk_closed() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->setupStorageBuffer(); + folder->storeObject( 2, 4, dummyPayload( 2 ), 0 ); + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + try + { + folder->flushStorageBuffer(); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 until", + string( "Overlapping intervals " + "not allowed in SINGLE_VERSION mode" ), + string( e.what() ) ); + } + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 0u, + (unsigned int)objs->size() ); + /* + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + */ + } + + + /// Tests storing unordered, non-overlapping SV IOVS (all closed but one). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #1 is NOT YET provided + /// (back-insertion is not yet allowed for bulk inserting + /// more than one IOV per channel - in single or multi channel mode). + void test_storeObject_SV_unordered_bulk_open() + { + IFolderPtr folder = m_db->createFolder( "/f2", payloadSpec ); + folder->setupStorageBuffer(); + folder->storeObject( 4, ValidityKeyMax, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 5, 6, dummyPayload( 1 ), 0 ); + try + { + folder->flushStorageBuffer(); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 until", + string( "Overlapping intervals " + "not allowed in SINGLE_VERSION mode" ), + //string( "Back-insertion not possible " + // "due to multiple objects in channel" ), + string( e.what() ) ); + } + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 0u, + (unsigned int)objs->size() ); + /* + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)3, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)5, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)6, obj->until() ); + */ + } + + + /// Tests storing unordered, non-overlapping SV IOVS (all closed but one). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #1 is NOT YET provided + /// (back-insertion is not yet allowed for bulk inserting + /// more than one IOV per channel - in single or multi channel mode). + /// NB - note the different exception message with respect to the + /// previous test (different code segments)... is this correct? + /// sas: Yes, that's intentional to + /// a) provide better feedback for the user in case of an exception. By + /// giving them a clear idea what went wrong they can rearrange + /// insertion to comply with the implemented case #1 more easily + /// b) allow me/us to find which part is actually throwing the exception + /// while we try to extend the functionality + void test_storeObject_SV_unordered_bulk_open_2() + { + IFolderPtr folder = m_db->createFolder( "/f2", payloadSpec ); + folder->storeObject( 4, ValidityKeyMax, dummyPayload( 1 ), 0 ); + folder->setupStorageBuffer(); + folder->storeObject( 2, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 5, 6, dummyPayload( 1 ), 0 ); + try + { + folder->flushStorageBuffer(); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 until", + //string( "Overlapping intervals " + // "not allowed in SINGLE_VERSION mode" ), + string( "Back-insertion not possible " + "due to multiple objects in channel" ), + string( e.what() ) ); + } + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 1u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + ValidityKeyMax, obj->until() ); + /* + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)3, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)5, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)6, obj->until() ); + */ + } + + + /// Tests storing unordered, non-overlapping SV IOVS (all closed but one). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #1 is NOT YET provided + /// (back-insertion is not yet allowed for bulk inserting + /// more than one IOV per channel - in single or multi channel mode). + void test_storeObject_SV_unordered_bulk_open_3() + { + IFolderPtr folder = m_db->createFolder( "/f2", payloadSpec ); + folder->setupStorageBuffer(); + folder->storeObject( 4, ValidityKeyMax, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 3, dummyPayload( 1 ), 0 ); + try + { + folder->flushStorageBuffer(); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4 until", + string( "Overlapping intervals " + "not allowed in SINGLE_VERSION mode" ), + //string( "Back-insertion not possible " + // "due to multiple objects in channel" ), + string( e.what() ) ); + } + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 0u, + (unsigned int)objs->size() ); + /* + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)3, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)5, obj->until() ); + */ + } + + + /// Tests storing unordered, non-overlapping SV MC IOVS (all closed). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #3 is provided + /// (back-insertion is allowed for single-IOV multi-channel insertion). + void test_storeObject_SV_unordered_MC_closed() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->storeObject( 0, 2, dummyPayload( 1 ), 1 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 1 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 2 ); + folder->storeObject( 0, 2, dummyPayload( 1 ), 2 ); + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + } + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 2 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + } + } + + + /// Tests storing unordered, non-overlapping SV MC IOVS (all closed). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #1 is NOT YET provided + /// (back-insertion is not yet allowed for bulk inserting + /// more than one IOV per channel - in single or multi channel mode). + void test_storeObject_SV_unordered_MC_bulk_closed() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->setupStorageBuffer(); + folder->storeObject( 0, 2, dummyPayload( 1 ), 1 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 1 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 2 ); + folder->storeObject( 0, 2, dummyPayload( 1 ), 2 ); + try + { + folder->flushStorageBuffer(); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "multichannel", + string( "Overlapping intervals " + "not allowed in SINGLE_VERSION mode" ), + string( e.what() ) ); + } + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 0u, + (unsigned int)objs->size() ); + /* + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + */ + } + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 2 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 0u, + (unsigned int)objs->size() ); + /* + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 2 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + */ + } + } + + + /// Tests storing unordered, non-overlapping SV MC IOVS (all closed). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #2 is provided + /// (back-insertion is allowed for bulk inserting + /// at most one IOV per channel - in multi channel mode). + void test_storeObject_SV_unordered_MC_bulk_closed_oneperchannel() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->setupStorageBuffer(); + folder->storeObject( 2, 4, dummyPayload( 2 ), 1 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 2 ); + folder->flushStorageBuffer(); + folder->storeObject( 0, 2, dummyPayload( 1 ), 1 ); + folder->storeObject( 0, 2, dummyPayload( 1 ), 2 ); + folder->flushStorageBuffer(); // Bulk-back-insert two IOVs (one per ch) + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + } + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 2 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + } + } + + + /// Tests storing unordered, non-overlapping SV MC IOVS (all closed). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #2 is provided + /// (back-insertion is allowed for bulk inserting + /// at most one IOV per channel - in multi channel mode: + /// it is also allowed for inserting several IOVs per channel, + /// as long as there is only IOV per channel in the channels + /// where one IOV is back-inserted). + void test_storeObject_SV_unordered_MC_bulk_closed_oneperchannel_2() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->setupStorageBuffer(); + folder->storeObject( 2, 4, dummyPayload( 2 ), 1 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 2 ); + folder->flushStorageBuffer(); + folder->storeObject( 0, 2, dummyPayload( 1 ), 1 ); + folder->storeObject( 4, 6, dummyPayload( 3 ), 2 ); + folder->storeObject( 6, 8, dummyPayload( 4 ), 2 ); + folder->flushStorageBuffer(); // Bulk-back-insert three IOVs + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + } + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 2 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)6, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 4 payload", + dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 since", + (ValidityKey)6, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 until", + (ValidityKey)8, obj->until() ); + } + } + + + /// Tests storing unordered, non-overlapping SV IOVS (all closed). + /// See https://savannah.cern.ch/task/?func=detailitem&item_id=3138: + /// tests that the functionality of use case #1 is NOT YET provided + /// (back-insertion is not yet allowed for bulk inserting + /// more than one IOV per channel - in single or multi channel mode, + /// even if only one IOV is back-inserted and the others are not). + void test_storeObject_SV_unordered_bulk_closed_oneback() + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 0 ); + folder->setupStorageBuffer(); + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + folder->storeObject( 4, 6, dummyPayload( 3 ), 0 ); + try + { + folder->flushStorageBuffer(); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6 until", + string( "Back-insertion not possible " + "due to multiple objects in channel" ), + string( e.what() ) ); + } + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 1u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + /* + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)2, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)4, obj->until() ); + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)6, obj->until() ); + */ + } + + + /// Tests storeObject with overlapping intervals + /// bug #9212 reported 2005-06-24 by Federico + void test_storeObject_SV_overlap_bulk() + { + try + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->setupStorageBuffer(); + folder->storeObject( 300, 400, dummyPayload( 1 ), 0 ); + folder->storeObject( 200, 400, dummyPayload( 1 ), 0 ); + folder->flushStorageBuffer(); + CPPUNIT_FAIL( "400 until exception expected" ); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "400 until", + string( "Overlapping intervals " + "not allowed in SINGLE_VERSION mode" ), + string( e.what() ) ); + } + try + { + IFolderPtr folder = m_db->createFolder( "/f2", payloadSpec ); + folder->setupStorageBuffer(); + folder->storeObject( 300, 350, dummyPayload( 1 ), 0 ); + folder->storeObject( 200, 400, dummyPayload( 1 ), 0 ); + folder->flushStorageBuffer(); + CPPUNIT_FAIL( "non-equal until exception expected" ); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "non-equal until", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + string( e.what() ) ); + } + try + { + IFolderPtr folder = m_db->createFolder( "/f3", payloadSpec ); + folder->setupStorageBuffer(); + folder->storeObject( 300, ValidityKeyMax, dummyPayload( 1 ), 0 ); + folder->storeObject( 200, ValidityKeyMax, dummyPayload( 1 ), 0 ); + folder->flushStorageBuffer(); + CPPUNIT_FAIL( "ValidityKeyMax until exception expected" ); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMax until", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + string( e.what() ) ); + } + } + + + /// Tests storeObject with overlapping intervals + /// bug #9212 reported 2005-06-24 by Federico + void test_storeObject_SV_overlap() + { + try + { + IFolderPtr folder = m_db->createFolder( "/f1", payloadSpec ); + folder->storeObject( 300, 400, dummyPayload( 1 ), 0 ); + folder->storeObject( 200, 400, dummyPayload( 1 ), 0 ); + CPPUNIT_FAIL( "400 until exception expected" ); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "400 until", + string( "Back-insertion collision: overlapping intervals " + "not allowed in SINGLE_VERSION mode" ), + string( e.what() ) ); + } + try + { + IFolderPtr folder = m_db->createFolder( "/f2", payloadSpec ); + folder->storeObject( 300, 350, dummyPayload( 1 ), 0 ); + folder->storeObject( 200, 400, dummyPayload( 1 ), 0 ); + CPPUNIT_FAIL( "non-equal until exception expected" ); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "non-equal until", + string( "Back-insertion collision: overlapping intervals " + "not allowed in SINGLE_VERSION mode" ), + string( e.what() ) ); + } + try + { + IFolderPtr folder = m_db->createFolder( "/f3", payloadSpec ); + folder->storeObject( 300, ValidityKeyMax, dummyPayload( 1 ), 0 ); + folder->storeObject( 200, ValidityKeyMax, dummyPayload( 1 ), 0 ); + CPPUNIT_FAIL( "ValidityKeyMax until exception expected" ); + } + catch ( std::exception& e ) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMax until", + string( "Back-insertion collision: overlapping intervals " + "not allowed in SINGLE_VERSION mode" ), + string( e.what() ) ); + } + } + + + /// Tests updating the folder description + void test_setDescription() { + { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "a description" ); + folder->setDescription( "new description" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "internal desc update", + string( "new description" ), + folder->description() ); + } + { + IFolderPtr folder = m_db->getFolder( "/myfolder" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "db desc update", + string( "new description" ), + folder->description() ); + } + } + + /// Tests bulk insertion into multiple channels (SV mode) + void test_storeObjects_bulk_multichannel() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + + folder->setupStorageBuffer(); + + ChannelId nChannels = 10; + { + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + folder->storeObject( (ValidityKey)0, ValidityKeyMax, + dummyPayload( (int)ch ), ch ); + } + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + folder->storeObject( (ValidityKey)5, ValidityKeyMax, + dummyPayload( (int)ch ), ch ); + } + } + + folder->flushStorageBuffer(); + + unsigned int nObjsPerChannel = 2; + IObjectPtr obj; + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + for ( unsigned int i = 0; i < nObjsPerChannel; ++i ) { + stringstream s; + s << "object " << i << ", channel " << ch << " "; + + ValidityKey pointInTime = 5 * i; // 0, 5 + obj = folder->findObject( pointInTime, ch ); + + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( (int)ch ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + pointInTime, obj->since() ); + + // until of last extends to ValidityKeyMax + if ( i < nObjsPerChannel-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + pointInTime +5, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + } + } + + + /// Tests tagDescription (MultiVersion only, SingleVersion does not have + /// tags and throws a RelationalException) + void test_tagDescription() { + try { + IFolderPtr folder = m_db->createFolder + ( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "A", "desc A" ); + + std::string desc = folder->tagDescription( "A" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag desc", std::string("desc A"), desc ); + + try { + folder->tagDescription( "nonexisting tag" ); + CPPUNIT_FAIL( "exception not thrown for nonexisting tag" ); + } catch ( TagNotFound& /* ignored */ ) { } + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + + } + + + /// Tests tagInsertionTime (MultiVersion only, SingleVersion does not have + /// tags and throws a RelationalException) + void test_tagInsertionTime() { + try{ + IFolderPtr folder = m_db->createFolder + ( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), 0 ); + + folder->tagCurrentHead( "A" ); + + Time tagTime = folder->tagInsertionTime( "A" ); + + // the real time functionality test + // is implemented in test_RalDatabase.cpp + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tagTime size", + string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(tagTime).size() ); + + try { + folder->tagInsertionTime( "nonexisting tag" ); + CPPUNIT_FAIL( "exception not thrown for nonexisting tag" ); + } catch ( TagNotFound& /* ignored */ ) { } + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + + } + + + /// Tests listTags for MV folders + void test_listTags_MV() { + try { + IFolderPtr folder = + m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "A" ); + folder->tagCurrentHead( "B" ); + std::vector<std::string> tags = folder->listTags(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag count", 2u, (unsigned int)tags.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag 1", std::string("A"), tags[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag 2", std::string("B"), tags[1] ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests listTags for SV folders: there are no tags + void test_listTags_SV() { + try { + IFolderPtr folder = + m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + std::vector<std::string> tags = folder->listTags(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag count", 0u, (unsigned int)tags.size() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests object browsing in tags (MV folders) + void test_browseObjects_MV_tag() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + + folder->tagCurrentHead( "mytag" ); + + { + IObjectIteratorPtr objs = folder->browseObjects( 5, 15, 0, "mytag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 until", + (ValidityKey)20, obj->until() ); + } + + { + IObjectIteratorPtr objs = folder->browseObjects( 10, 20, 0, "mytag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2.1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + (ValidityKey)20, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2.2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + ValidityKeyMax, obj->until() ); + } + + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + 0, "mytag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 until", + (ValidityKey)10, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 until", + (ValidityKey)20, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3.3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 until", + ValidityKeyMax, obj->until() ); + } + } + + + /// Tests object browsing (MV folders) + void test_browseObjects_MV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + + { + IObjectIteratorPtr objs = folder->browseObjects( 5, 15, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 until", + (ValidityKey)20, obj->until() ); + } + + { + IObjectIteratorPtr objs = folder->browseObjects( 10, 20, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2.1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + (ValidityKey)20, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2.2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + ValidityKeyMax, obj->until() ); + } + + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 until", + (ValidityKey)10, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 until", + (ValidityKey)20, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3.3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 until", + ValidityKeyMax, obj->until() ); + } + } + + + /// Tests object browsing all channels (MV folders) + void test_browseObjects_all_channels_MV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + int index = 0; + for ( int i = 0; i < 3; ++i ) { + folder->storeObject( 0, 10, dummyPayload( index++ ), (ChannelId)i ); + folder->storeObject( 10, 20, dummyPayload( index++ ), (ChannelId)i ); + folder->storeObject( 20, ValidityKeyMax, + dummyPayload( index++ ), (ChannelId)i ); + } + + { + ValidityKey since = 5; + ValidityKey until = 15; + IObjectIteratorPtr + objs = folder->browseObjects( since, until, + ChannelSelection::all() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 6u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 channel", + (ChannelId)0, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 channel", + (ChannelId)0, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 channel", + (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 4 payload", + dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 channel", + (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 5 payload", + dummyPayload( 6 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 channel", + (ChannelId)2, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 6 payload", + dummyPayload( 7 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 6 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 6 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 channel", + (ChannelId)2, obj->channelId() ); + } + + } + + + /// Tests object browsing a channel range (MV folders) + void test_browseObjects_channel_range_MV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + int index = 0; + for ( int i = 0; i < 5; ++i ) { + folder->storeObject( 0, 10, dummyPayload( index++ ), (ChannelId)i ); + folder->storeObject( 10, 20, dummyPayload( index++ ), (ChannelId)i ); + folder->storeObject( 20, ValidityKeyMax, + dummyPayload( index++ ), (ChannelId)i ); + } + + { + ValidityKey since = 5; + ValidityKey until = 15; + ChannelSelection channels( 2, 3 ); + IObjectIteratorPtr objs = folder->browseObjects( since, + until, + channels ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 4u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 6 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 channel", + (ChannelId)2, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 7 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 channel", + (ChannelId)2, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 9 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 channel", + (ChannelId)3, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 4 payload", + dummyPayload( 10 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 channel", + (ChannelId)3, obj->channelId() ); + } + + } + + + /// Tests object browsing all channels (SV folders) + void test_browseObjects_all_channels_SV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + + int index = 0; + for ( int i = 0; i < 3; ++i ) { + folder->storeObject( 0, 10, dummyPayload( index++ ), (ChannelId)i ); + folder->storeObject( 10, 20, dummyPayload( index++ ), (ChannelId)i ); + folder->storeObject( 20, ValidityKeyMax, + dummyPayload( index++ ), (ChannelId)i ); + } + + { + ValidityKey since = 5; + ValidityKey until = 15; + IObjectIteratorPtr + objs = folder->browseObjects( since, until, + ChannelSelection::all() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 6u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 channel", + (ChannelId)0, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 channel", + (ChannelId)0, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 channel", + (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 4 payload", + dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 channel", + (ChannelId)1, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 5 payload", + dummyPayload( 6 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 5 channel", + (ChannelId)2, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 6 payload", + dummyPayload( 7 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 6 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 6 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 channel", + (ChannelId)2, obj->channelId() ); + } + + } + + + /// Tests object browsing a channel range (SV folders) + void test_browseObjects_channel_range_SV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + + int index = 0; + for ( int i = 0; i < 5; ++i ) { + folder->storeObject( 0, 10, dummyPayload( index++ ), (ChannelId)i ); + folder->storeObject( 10, 20, dummyPayload( index++ ), (ChannelId)i ); + folder->storeObject( 20, ValidityKeyMax, + dummyPayload( index++ ), (ChannelId)i ); + } + + { + ValidityKey since = 5; + ValidityKey until = 15; + ChannelSelection channels( 2, 3 ); + IObjectIteratorPtr objs = folder->browseObjects( since, + until, + channels ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 4u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 6 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1 channel", + (ChannelId)2, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 7 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2 channel", + (ChannelId)2, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3 payload", + dummyPayload( 9 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 until", + (ValidityKey)10, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3 channel", + (ChannelId)3, obj->channelId() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 4 payload", + dummyPayload( 10 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 until", + (ValidityKey)20, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 4 channel", + (ChannelId)3, obj->channelId() ); + } + + } + + + /// Tests object browsing (SV folders) + void test_browseObjects_SV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + + { + IObjectIteratorPtr objs = folder->browseObjects( 5, 15, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 until", + (ValidityKey)20, obj->until() ); + } + + { + IObjectIteratorPtr objs = folder->browseObjects( 10, 20, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2.1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + (ValidityKey)20, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2.2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + ValidityKeyMax, obj->until() ); + } + + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 until", + (ValidityKey)10, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 until", + (ValidityKey)20, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 3.3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 until", + ValidityKeyMax, obj->until() ); + } + } + + + /// Tests browsing a SV selection with lowercase payload + /// Test for Richard's ORA-00904 bug report + void test_browseObjects_SV_lowercasePayload() + { + RecordSpecification payloadSpecNew( payloadSpec ); + payloadSpecNew.extend( "float2", StorageType::Float); + Record payload( payloadSpecNew ); + payload["I"].setValue<Int32>( 123 ); + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpecNew, + "my description", + FolderVersioning::SINGLE_VERSION ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 until", + (ValidityKey)10, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 until", + (ValidityKey)20, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 until", + ValidityKeyMax, obj->until() ); + } + } + + + /// Tests object browsing (SV folders) + void test_browseObjects_SV_bug42101() + { + IFolderPtr folder = + m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + + folder->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + + IObjectIteratorPtr objs = folder->browseObjects( 5, 15, 0, "HEAD" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object count", 2u, (unsigned int)objs->size() ); + } + + + /// Tests that the storage buffer is cleared and none of the objects + /// is stored if an exception is thrown during the bulk operation + /// 'flushStorageBuffer' (for instance, because one IOV has until<since) + void test_flushStorageBuffer_exception() + { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + + folder->setupStorageBuffer(); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), 0 ); + folder->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder->flushStorageBuffer(); + + folder->setupStorageBuffer(); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ), 0 ); + folder->storeObject( 30, 20, dummyPayload( 3 ), 0 ); // INVALID! + folder->storeObject( 40, 50, dummyPayload( 4 ), 0 ); + bool flushFailed = false; + try { + folder->flushStorageBuffer(); + } catch ( ValidityKeyException& /* dummy */ ) { + flushFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "second insertion not OK", flushFailed ); + + folder->setupStorageBuffer(); + folder->storeObject( 50, ValidityKeyMax, dummyPayload( 5 ), 0 ); + folder->storeObject( 60, 70, dummyPayload( 6 ), 0 ); + folder->flushStorageBuffer(); + + IObjectPtr obj0 = folder->findObject( 0, 0 ); + CPPUNIT_ASSERT_MESSAGE( "object 0 found", + dummyPayload(0) == obj0->payload() ); + IObjectPtr obj1 = folder->findObject( 10, 0 ); + CPPUNIT_ASSERT_MESSAGE( "object 1 found", + dummyPayload(1) == obj1->payload() ); + + bool objectNotFound = false; + try { + IObjectPtr obj2 = folder->findObject( 20, 0 ); + std::cout << "ERROR! Found object2: " << obj2 << std::endl; + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "object 2 not found", objectNotFound ); + + objectNotFound = false; + try { + folder->findObject( 30, 0 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "object 3 not found", objectNotFound ); + + objectNotFound = false; + try { + folder->findObject( 40, 0 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "object 4 not found", objectNotFound ); + + IObjectPtr obj5 = folder->findObject( 50, 0 ); + CPPUNIT_ASSERT_MESSAGE( "object 5 found", + dummyPayload(5) == obj5->payload() ); + IObjectPtr obj6 = folder->findObject( 60, 0 ); + CPPUNIT_ASSERT_MESSAGE( "object 6 found", + dummyPayload(6) == obj6->payload() ); + + } + + /// Tests that the storage buffer is cleared and none of the objects + /// is stored if an exception is thrown during the bulk operation + /// 'flushStorageBuffer' (for instance, because one IOV has until<since), + /// even if more than maxBufferSize objects are stored (bug #22474) + void test_flushStorageBuffer_exception_bug22474() + { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + unsigned maxBufferSize = relfolder->maxBufferSize(); + + folder->setupStorageBuffer(); + for ( unsigned key = 0; key < maxBufferSize; key++ ) + { + folder->storeObject( key*10, (key+1)*10, dummyPayload( key ), 0 ); + } + folder->storeObject( 1, 0, dummyPayload( 0 ), 0 ); // INVALID! + + bool flushFailed = false; + try { + folder->flushStorageBuffer(); + } catch ( ValidityKeyException& /* dummy */ ) { + flushFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "Flush should have failed", flushFailed ); + + bool objectNotFound = false; + try { + IObjectPtr obj = folder->findObject( 0, 0 ); + std::cout << "ERROR! Found object at 0: " << obj << std::endl; + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "Object at 0 should not exist", objectNotFound ); + } + + /// Tests that a ValidityKeyException is thrown when since>until + /// and when since or until are out of boundaries + void test_ValidityKeyException() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + + bool storeFailed = false; + try { + folder->storeObject( 100, 0, dummyPayload( 0 ), 0 ); + } catch ( ValidityKeyException& /* dummy */ ) { + storeFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "exception for [100,0]", storeFailed ); + + storeFailed = false; + try { + folder->storeObject( 100, 100, dummyPayload( 0 ), 0 ); + } catch ( ValidityKeyException& /* dummy */ ) { + storeFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "exception for [100,100]", storeFailed ); + + storeFailed = false; + try { + // Split the following line on two lines (Windows compiler warning) + //ValidityKey since = ValidityKeyMin-1; + ValidityKey since = ValidityKeyMin; + since = since-1; + ValidityKey until = ValidityKeyMin; + // NB: Now (ValidityKey=long_long, ValidityKeyMin=LONG_LONG_MIN) + // ==> LONG_LONG_MIN-1 is an invalid int64 LONG_LONG_MAX > since + // NB: Previously (ValidityKey=long_long, ValidityKeyMin=LONG_MIN) + // ==> LONG_MIN-1 is an invalid int64 > LONG_MIN=ValidityKeyMin + folder->storeObject( since, until, dummyPayload( 0 ), 0 ); + } catch ( ValidityKeyException& /* dummy */ ) { + storeFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "exception for [min-1,min]", storeFailed ); + + storeFailed = false; + try { + ValidityKey since = ValidityKeyMax; + // Split the following line on two lines (Windows compiler warning) + //ValidityKey until = ValidityKeyMax+1; + ValidityKey until = ValidityKeyMax; + until = until+1; + // NB: Now (ValidityKey=long_long, ValidityKeyMin=LONG_LONG_MIN) + // ==> LONG_LONG_MIN-1 is an invalid int64 LONG_LONG_MAX > since + // NB: Previously (ValidityKey=long_long, ValidityKeyMin=LONG_MIN) + // ==> LONG_MIN-1 is an invalid int64 > LONG_MIN=ValidityKeyMin + folder->storeObject( since, until, dummyPayload( 0 ), 0 ); + } catch ( ValidityKeyException& /* dummy */ ) { + storeFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "exception for [max,max+1]", storeFailed ); + + } + + /// Tests that the ValidityKey boundaries are those we expect + /// (use hardcoded numerical values) + void test_ValidityKey_boundaries() { + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "ValidityKeyMin hardcoded", + // (ValidityKey)0, ValidityKeyMin + 9223372036854775808ULL ); + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "ValidityKeyMax hardcoded", + // (ValidityKey)0, ValidityKeyMax - 18446744073709551615ULL ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMin hardcoded", + (ValidityKey)0, ValidityKeyMin ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMax hardcoded", + (ValidityKey)0, + (ValidityKey)(ValidityKeyMax - 9223372036854775807LL) ); + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "ValidityKeyMin Int64Min", + // (ValidityKey)Int64Min, ValidityKeyMin ); + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "ValidityKeyMin UInt64Max", + // (ValidityKey)UInt64Max, ValidityKeyMax ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMin UInt64Min", + (ValidityKey)UInt64Min, ValidityKeyMin ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMin Int64Max", + (ValidityKey)Int64Max, ValidityKeyMax ); + } + + + /// Stores objects to multiple folders and retrieves them in a loop + /// Tests against a problem first reported by Marco Clemencic on + /// 2005-01-27 -- cannot reproduce at the moment + void test_multiple_folders() { + bool showPrintout = false; + + int nFolders = 5; + vector<string> foldernames; + for ( int i = 0; i < nFolders; ++i ) { + stringstream s; + s << "/f_" << i; + foldernames.push_back( s.str() ); + } + + long nObjs = 100; + + for ( vector<string>::const_iterator fname = foldernames.begin(); + fname != foldernames.end(); ++fname ) { + IFolderPtr folder = m_db->createFolder( *fname, payloadSpec ); + } + + for ( vector<string>::const_iterator fname = foldernames.begin(); + fname != foldernames.end(); ++fname ) { + IFolderPtr folder = m_db->getFolder( *fname ); + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ), 0 ); + } + folder->flushStorageBuffer(); + + if ( showPrintout ) + cout << "wrote " << nObjs + << " objects in folder '" << *fname << endl; + } + + for ( vector<string>::const_iterator fname = foldernames.begin(); + fname != foldernames.end(); ++fname ) { + IFolderPtr folder = m_db->getFolder( *fname ); + IObjectIteratorPtr objs + = folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0, "" ); + + CPPUNIT_ASSERT_MESSAGE( "not empty", objs->size() > 0 ); + + long objIndex = 0; + //for ( IObjectIterator::const_iterator + // i = objs->begin(); i != objs->end(); ++i ) { + // const IObjectPtr& obj = *i; + while ( objs->goToNext() ) { + IObjectPtr obj( objs->currentRef().clone() ); + + stringstream s; + s << "folder " << *fname << ": object " << objIndex << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( objIndex ) + == obj->payload() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + objIndex, (long)obj->since() ); + + // last object's until extends to ValidityKeyMax + if ( objIndex < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + objIndex+1, (long)obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + + ++objIndex; + } + + if ( showPrintout ) + cout << "checked " << objIndex + << " objects in folder " << *fname << endl; + } + } + + + /// Tests tagging and retagging when a tag exists in another folder + void test_tagExistsElsewhere() { + IFolderPtr folder1 = m_db->createFolder( "/myfolder1", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + IFolderPtr folder2 = m_db->createFolder( "/myfolder2", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder1->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder2->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder2->storeObject( 20, 30, dummyPayload( 2 ), 0 ); + + std::string tagA = "tagA"; + std::string descA = "tagA description"; + std::string tagB = "tagB"; + std::string descB = "tagB description"; + + // TagA cannot be created in folder2 if it exists in folder1 already + folder1->tagCurrentHead( tagA, descA ); + try { + folder2->tagCurrentHead( tagA, descA ); + CPPUNIT_FAIL( "exception expected" ); + } + catch ( cool::TagExists& /*dummy*/) { + try { + folder2->deleteTag( tagA ); + folder2->tagCurrentHead( tagA, descA ); + } + catch ( cool::TagNotFound& /*e*/ ) { + //std::cout << "Caught as expected: " << e.what() << std::endl; + } + catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + // Create tagB in folder2: this has the same tagId=1 as tagA in folder1 + // BUG in COOL_1_2_2: folder1->delete(tagA) also deletes tagB and fails + folder2->tagCurrentHead( tagB, descB ); + try { + folder1->deleteTag( tagA ); + } + catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + + } + + + /// Tests IDatabase::tagNameScope + void test_tagNameScope() { + std::string path1 = "/myfolder1"; + std::string path2 = "/myfolder2"; + IFolderPtr folder1 = m_db->createFolder( path1, + payloadSpec, + "folder description", + FolderVersioning::MULTI_VERSION ); + IFolderPtr folder2 = m_db->createFolder( path2, + payloadSpec, + "folder description", + FolderVersioning::MULTI_VERSION ); + + folder1->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder2->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder2->storeObject( 20, 30, dummyPayload( 2 ), 0 ); + + std::string tag1A = "tag1A"; + std::string tag1B = "tag1B"; + std::string tag1C = "tag1C"; + std::string tag2A = "tag2A"; + std::string tag2B = "tag2B"; + std::string tag2C = "tag2C"; + + folder1->tagCurrentHead( tag1A, "tag description" ); + folder1->tagCurrentHead( tag1B, "tag description" ); + folder1->tagCurrentHead( tag1C, "tag description" ); + folder2->tagCurrentHead( tag2A, "tag description" ); + folder2->tagCurrentHead( tag2B, "tag description" ); + folder2->tagCurrentHead( tag2C, "tag description" ); + + try { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag1A scope", IHvsNode::LEAF_NODE, m_db->tagNameScope( tag1A ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag1B scope", IHvsNode::LEAF_NODE, m_db->tagNameScope( tag1B ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag1C scope", IHvsNode::LEAF_NODE, m_db->tagNameScope( tag1C ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag2A scope", IHvsNode::LEAF_NODE, m_db->tagNameScope( tag2A ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag2B scope", IHvsNode::LEAF_NODE, m_db->tagNameScope( tag2B ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag2C scope", IHvsNode::LEAF_NODE, m_db->tagNameScope( tag2C ) ); + } + catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests IDatabase::taggedNodes + void test_taggedNodes() { + std::string path1 = "/myfolder1"; + std::string path2 = "/myfolder2"; + IFolderPtr folder1 = m_db->createFolder( path1, + payloadSpec, + "folder description", + FolderVersioning::MULTI_VERSION ); + IFolderPtr folder2 = m_db->createFolder( path2, + payloadSpec, + "folder description", + FolderVersioning::MULTI_VERSION ); + + folder1->storeObject( 0, 10, dummyPayload( 0 ), 0 ); + folder2->storeObject( 10, 20, dummyPayload( 1 ), 0 ); + folder2->storeObject( 20, 30, dummyPayload( 2 ), 0 ); + + std::string tag1A = "tag1A"; + std::string tag1B = "tag1B"; + std::string tag1C = "tag1C"; + std::string tag2A = "tag2A"; + std::string tag2B = "tag2B"; + std::string tag2C = "tag2C"; + + folder1->tagCurrentHead( tag1A, "tag description" ); + folder1->tagCurrentHead( tag1B, "tag description" ); + folder1->tagCurrentHead( tag1C, "tag description" ); + folder2->tagCurrentHead( tag2A, "tag description" ); + folder2->tagCurrentHead( tag2B, "tag description" ); + folder2->tagCurrentHead( tag2C, "tag description" ); + + try { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag1A scope", path1, m_db->taggedNodes( tag1A )[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag1B scope", path1, m_db->taggedNodes( tag1B )[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag1C scope", path1, m_db->taggedNodes( tag1C )[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag2A scope", path2, m_db->taggedNodes( tag2A )[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag2B scope", path2, m_db->taggedNodes( tag2B )[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag2C scope", path2, m_db->taggedNodes( tag2C )[0] ); + } + catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests deleting a tag and retagging + void test_deleteTag_andRetag() { + try { + IFolderPtr folder = + m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + // First version of tagA + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "tagA", "an optional description" ); + { + IObjectIteratorPtr objs1a = folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, (ChannelId)0, "tagA" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tagA1 object count", 1u, (unsigned int)objs1a->size() ); + IObjectPtr obj1a = getNext(objs1a); + CPPUNIT_ASSERT_MESSAGE( "tagA1 obj 1 payload", + dummyPayload( 0 ) == obj1a->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA1 obj 1 since", + (ValidityKey)0, obj1a->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA1 obj 1 until", + (ValidityKey)4, obj1a->until() ); + } + + // Retagging as tagA will fail now + try { + folder->tagCurrentHead( "tagA", "an optional description" ); + CPPUNIT_FAIL( "retag as tagA succeeeds even with no deleteTag" ); + } catch ( TagExists& /* dummy */ ) { + } + + // Second version of tagA + folder->storeObject( 2, 6, dummyPayload( 1 ), 0 ); + folder->deleteTag( "tagA" ); + CPPUNIT_ASSERT_MESSAGE( "tagA deleted", ! m_db->existsTag( "tagA" ) ); + folder->tagCurrentHead( "tagA", "an optional description" ); + { + IObjectIteratorPtr objs2a = folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, (ChannelId)0, "tagA" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tagA2 object count", 2u, (unsigned int)objs2a->size() ); + IObjectPtr obj2a = getNext(objs2a); + CPPUNIT_ASSERT_MESSAGE( "tagA2 obj 1 payload", + dummyPayload( 0 ) == obj2a->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA2 obj 1 since", + (ValidityKey)0, obj2a->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA2 obj 1 until", + (ValidityKey)2, obj2a->until() ); + obj2a = getNext(objs2a); + CPPUNIT_ASSERT_MESSAGE( "tagA2 obj 2 payload", + dummyPayload( 1 ) == obj2a->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA2 obj 2 since", + (ValidityKey)2, obj2a->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA2 obj 2 until", + (ValidityKey)6, obj2a->until() ); + } + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests that attempting to delete the reserved HEAD tag throws + /// an exception. + void test_deleteTag_HEAD() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "tagA", "an optional description" ); + CPPUNIT_ASSERT_THROW( folder->deleteTag( "HEAD" ), + ReservedHeadTag ); + } + + + /// Tests MV tagging and retrieving + void test_MV_tag_and_retrieve() { + try { + IFolderPtr folder = + m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->setupStorageBuffer(); + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->storeObject( 2, 6, dummyPayload( 1 ), 0 ); + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "tagA", "an optional description" ); + Time asOfDate = folder->findObject( 0, 0 )->insertionTime(); + + // MySQL now() has 1 second granularity: sleep at least 1 second + sleep(1); + + folder->setupStorageBuffer(); + folder->storeObject( 3, 7, dummyPayload( 2 ), 0 ); + folder->storeObject( 5, 9, dummyPayload( 3 ), 0 ); + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "tagB" ); + folder->tagHeadAsOfDate( asOfDate, "tagC" ); // == tagA + + // fetch tagA + //std::cout << "Fetch tagA" << std::endl; + { + IObjectIteratorPtr objs = + folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, (ChannelId)0, "tagA" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagA obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagA obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 2 until", + (ValidityKey)6, obj->until() ); + } + + // fetch tagB + //std::cout << "Fetch tagB" << std::endl; + { + IObjectIteratorPtr objs = + folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, (ChannelId)0, "tagB" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB object count", 4u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagB obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagB obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 2 until", + (ValidityKey)3, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagB obj 3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 3 since", + (ValidityKey)3, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 3 until", + (ValidityKey)5, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagB obj 4 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 4 since", + (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 4 until", + (ValidityKey)9, obj->until() ); + } + + // fetch head + //std::cout << "Fetch HEAD" << std::endl; + { + IObjectIteratorPtr objs = + folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, (ChannelId)0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD object count", 4u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "HEAD obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "HEAD obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 2 until", + (ValidityKey)3, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "HEAD obj 3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 3 since", + (ValidityKey)3, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 3 until", + (ValidityKey)5, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "HEAD obj 4 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 4 since", + (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 4 until", + (ValidityKey)9, obj->until() ); + } + + // fetch tagC + //std::cout << "Fetch tagC" << std::endl; + { + IObjectIteratorPtr objs = + folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, (ChannelId)0, "tagC" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagC obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagC obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC obj 2 until", + (ValidityKey)6, obj->until() ); + } + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + /// Tests bulk storeObject of MV objects + void test_storeObject_bulk_MV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + unsigned int nObjs = 10; + for ( unsigned int i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ), 0 ); + } + + // cppunit 1.8.0 does not have CPPUNIT_ASSERT_EXCEPTION + bool objectNotFound = false; + try { + folder->findObject( 0, 0 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "no objects", objectNotFound ); + + folder->flushStorageBuffer(); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", + 10u, (unsigned int)objs->size() ); + + for ( unsigned int i = 0; i < objs->size(); ++i ) { + IObjectPtr obj = getNext(objs); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( i ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + (ValidityKey)i, obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + (ValidityKey)i+1, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + } + + + + + /// Tests tag name case sensitivity + void test_tagName_case_sensitivity() { + try { + IFolderPtr folder = + m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + + folder->tagCurrentHead( "tagA" ); + + folder->storeObject( 0, 4, dummyPayload( 1 ), 0 ); + + folder->tagCurrentHead( "taga" ); + + // fetch tagA + { + IObjectIteratorPtr objs = + folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, (ChannelId)0, "tagA" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA object count", 1u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagA obj payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj until", + (ValidityKey)4, obj->until() ); + } + + // fetch taga + { + IObjectIteratorPtr objs = + folder->browseObjects + ( ValidityKeyMin, ValidityKeyMax, (ChannelId)0, "taga" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "taga object count", 1u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "taga obj payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "taga obj since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "taga obj until", + (ValidityKey)4, obj->until() ); + } + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + + } + + + /// Tests bulk storeObject of 70k objects: this used to cause ORA-24381 + /// before a workaround was added in RelationalFolder::flushStorageBuffer + /// (this is now fixed in CORAL for bulk inserts, but we keep our hack + /// in COOL because of better performance with 10k bulks in MySQL). + void test_storeObject_bulk_70k() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + + folder->setupStorageBuffer(); + long nObjs = 70*1000; + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ), 0 ); + } + + folder->flushStorageBuffer(); + + IObjectPtr obj; + for ( long i = 0; i < nObjs; i += 1000 ) { + obj = folder->findObject( i, 0 ); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( i ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + i, (long)obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + i+1, (long)obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + LONG_MAX, (long)obj->until() ); + } + } + } + + + /// More recently the problem above reappeared for bulk updates: see bug + /// #17755, due to CORAL bug #17757, which is now also fixed (only bulk + /// inserts had been fixed, not bulk updates). In this case we do not + /// have an internal COOL hack, we rely on CORAL: we test this here too. + /// Keep the above test stand-alone because SV is much faster! + /// The tagBulk70k test is disabled because it is very slow + /// (roughly twice as slow as the storeObject_bulk_70k after fixing bug #17903) + /// and it tests CORAL code already covered by storeObject_bulk_70k. + void test_tagObject_bulk_70k() + { + IFolderPtr folder = m_db->createFolder + ( "/myfolder", payloadSpec, "", FolderVersioning::MULTI_VERSION); + + folder->setupStorageBuffer(); + long nObjs = 70*1000; + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, i+1, dummyPayload( i ), 0 ); + } + + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "MYTAG" ); + + IObjectPtr obj; + for ( long i = 0; i < nObjs; i += 1000 ) { + obj = folder->findObject( i, 0, "MYTAG" ); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( i ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + i, (long)obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + i+1, (long)obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + LONG_MAX, (long)obj->until() ); + } + } + } + + + /// Tests bulk storeObject of SV objects with a reused AttributeList + /// This test ensures that the payload data is copied, not referenced + /// inside the storage buffer. + void test_storeObject_bulk_SV_listReused() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + + Record payload = dummyPayload( 0 ); + + folder->setupStorageBuffer(); + unsigned int nObjs = 100; + for ( unsigned int i = 0; i < nObjs; ++i ) { + payload["I"].setValue<int>( (int)i ); + folder->storeObject( i, ValidityKeyMax, payload, 0 ); + } + + // cppunit 1.8.0 does not have CPPUNIT_ASSERT_EXCEPTION + bool objectNotFound = false; + try { + folder->findObject( 0, 0 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "no objects", objectNotFound ); + + folder->flushStorageBuffer(); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", + 100u, (unsigned int)objs->size() ); + + for ( unsigned int i = 0; i < objs->size(); ++i ) { + IObjectPtr obj = getNext(objs); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload I" ).c_str(), + (int)i == obj->payload()["I"].data<int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + (ValidityKey)i, obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + (ValidityKey)i+1, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + + } + + + /// Tests bulk storeObject of SV objects + void test_storeObject_bulk_SV() { + try { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + + folder->setupStorageBuffer(); + unsigned int nObjs = 100; + for ( unsigned int i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ), 0 ); + } + + // cppunit 1.8.0 does not have CPPUNIT_ASSERT_EXCEPTION + bool objectNotFound = false; + try { + folder->findObject( 0, 0 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "no objects", objectNotFound ); + + folder->flushStorageBuffer(); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", + 100u, (unsigned int)objs->size() ); + + for ( unsigned int i = 0; i < objs->size(); ++i ) { + IObjectPtr obj = getNext(objs); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( i ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + (ValidityKey)i, obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + (ValidityKey)i+1, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + /// Tests bulk operation 'flushStorageBuffer' + void test_flushStorageBuffer() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + + folder->setupStorageBuffer(); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), 0 ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), 0 ); + + // cppunit 1.8.0 does not have CPPUNIT_ASSERT_EXCEPTION + bool objectNotFound = false; + try { + folder->findObject( 1, 0 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "no objects", objectNotFound ); + + try { + folder->flushStorageBuffer(); + } catch ( RelationalException& e ) { + cout << e.what() << endl; + throw; + } + + IObjectPtr obj0 = folder->findObject( 0, 0 ); + CPPUNIT_ASSERT_MESSAGE( "object 1 found", obj0.get() != 0 ); + IObjectPtr obj1 = folder->findObject( 1, 0 ); + CPPUNIT_ASSERT_MESSAGE( "object 1 found", obj1.get() != 0 ); + } + + + /// Tests reading back of a folder from a db handle that went out of scope + void test_access_outofscope_db() { + IFolderPtr folder; + + { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + IDatabasePtr db1 = dbSvc.openDatabase( m_connectionString, false ); + folder = db1->createFolder( "/myfolder", payloadSpec ); + // db1 isgoing of of scope here but folder keeps + // its own handle to the db + } + + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + } + + + /// Tests reading back of an Object from a deleted MV folder + void test_findObject_after_dropNode_MV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION); + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + m_db->dropNode( "/myfolder" ); + CPPUNIT_ASSERT_THROW( folder->findObject( 1, 0 ), + RelationalException ); + } + + + /// Tests reading back of an Object from a deleted SV folder + void test_findObject_after_dropNode_SV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + m_db->dropNode( "/myfolder" ); + // This is expected to throw a cool::TableNotFound exception + CPPUNIT_ASSERT_THROW( folder->findObject( 1, 0 ), + RelationalException ); + } + + + /// Tests reading back of an Object from a channel that does not exist + void test_findObject_wrongChannel() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + ChannelId channel1 = 1; + ChannelId channel2 = 2; + folder->storeObject( 0, 2, dummyPayload( 1 ), channel1 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), channel1 ); + CPPUNIT_ASSERT_THROW( IObjectPtr obj1 = folder->findObject( 1, channel2 ), + ObjectNotFound ); + } + + + /// Tests storing and reading back of an Object in a MultiVersion folder + /// This test is implemented in more detail with respect to the object + /// attributes in test_RalDatabase + void test_findObject_MV() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 0 ); + + IObjectPtr obj1 = folder->findObject( 1, 0 ); + CPPUNIT_ASSERT_MESSAGE( "first object", + dummyPayload( 1 ) == obj1->payload() ); + + IObjectPtr obj2 = folder->findObject( 3, 0 ); + CPPUNIT_ASSERT_MESSAGE( "second object", + dummyPayload( 2 ) == obj2->payload() ); + } + + + /// Tests storing and reading back of an Object + /// This test is implemented in more detail with respect to the object + /// attributes in test_RalDatabase + void test_findObject() { + IFolderPtr folder = m_db->createFolder( "/myfolder", payloadSpec ); + + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 0 ); + + IObjectPtr obj1 = folder->findObject( 1, 0 ); + CPPUNIT_ASSERT_MESSAGE( "first object", + dummyPayload( 1 ) == obj1->payload() ); + + IObjectPtr obj2 = folder->findObject( 3, 0 ); + CPPUNIT_ASSERT_MESSAGE( "second object", + dummyPayload( 2 ) == obj2->payload() ); + } + + + /// Tests creating and retrieving a folder. + /// This test is implemented in more detail with respect to the folder + /// attributes in test_RalDatabase + void test_getFolder() { + try { + string folderName( "/myfolder" ); + m_db->createFolder( folderName, payloadSpec, "a description" ); + + IFolderPtr folder = m_db->getFolder( folderName ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "name", folderName, folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "description", string( "a description" ), folder->description() ); + CPPUNIT_ASSERT_MESSAGE + ( "isLeaf", folder->isLeaf() ); + CPPUNIT_ASSERT_MESSAGE + ( "isStored", folder->isStored() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "insertionTime", string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(folder->insertionTime()).size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "id", 1u, folder->id() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "parentId", 0u, folder->parentId() ); + + } catch ( Exception& e ) { + cout << e.what() << endl; + throw; + } + } + + void test_renamePayload() + { + string folderName( "/myfolder" ); + IFolderPtr folder = + m_db->createFolder( folderName, payloadSpec, "a description" ); + + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + + folder->renamePayload("I","NewColumn"); + folder.reset(); + + // Avoid ORA-01466: table definition has changed + sleep(1); + + folder = m_db->getFolder( folderName ); + IObjectPtr obj = folder->findObject( 1, 0 ); + + CPPUNIT_ASSERT_THROW( obj->payload()["I"] , + cool::RecordSpecificationUnknownField ); + + CPPUNIT_ASSERT( obj->payload()["NewColumn"].data<Int32>() == 1 ); + + CPPUNIT_ASSERT_THROW( folder->renamePayload("S","X"), + cool::RelationalException ); + + CPPUNIT_ASSERT_THROW( folder->renamePayload("Z","DoesNotExists"), + cool::RelationalException ); + + CPPUNIT_ASSERT_THROW( folder->renamePayload("X","not-allowed name"), + cool::RelationalException ); + + } + + + void test_extendPayloadSpecificationExceptions() + { + string folderName( "/myfolder" ); + IFolderPtr folder = + m_db->createFolder( folderName, payloadSpec, "a description" ); + + { + RecordSpecification spec; + spec.extend("I",StorageType::Int32); // already exists + Record rec( spec ); + CPPUNIT_ASSERT_THROW + ( folder->extendPayloadSpecification( rec ), + cool::RelationalException ); + } + + { + RecordSpecification spec; + CPPUNIT_ASSERT_THROW + ( spec.extend("",StorageType::Int32), + cool::FieldSpecificationInvalidName ); + //spec.extend("",StorageType::Int32); + //Record rec( spec ); + //CPPUNIT_ASSERT_THROW + // ( folder->extendPayloadSpecification( rec ), + // cool::RelationalException ); + } + + { + RecordSpecification spec; + spec.extend("not-allowed name",StorageType::Int32); + Record rec( spec ); + CPPUNIT_ASSERT_THROW + ( folder->extendPayloadSpecification( rec ), + cool::RelationalException ); + } + + } + + + void test_extendPayloadSpecification() + { + string folderName( "/myfolder" ); + IFolderPtr folder = + m_db->createFolder( folderName, payloadSpec, "a description" ); + + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + + RecordSpecification spec; + spec.extend( "J1", StorageType::Int32 ); + spec.extend( "J2", StorageType::Int32 ); + spec.extend( "J3", StorageType::Int32 ); + Record rec( spec ); + rec["J1"].setValue<Int32>( 1 ); + rec["J2"].setNull(); + rec["J3"].setValue<Int32>( 3 ); + + folder->extendPayloadSpecification(rec); + folder.reset(); + + // Avoid ORA-01466: table definition has changed + sleep(1); + + folder = m_db->getFolder( folderName ); + IObjectPtr obj = folder->findObject( 1, 0 ); + + CPPUNIT_ASSERT( !obj->payload()["J1"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "J1", 1, obj->payload()["J1"].data<Int32>() ); + CPPUNIT_ASSERT( obj->payload()["J2"].isNull() ); + CPPUNIT_ASSERT( !obj->payload()["J3"].isNull() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "J3", 3, obj->payload()["J3"].data<Int32>() ); + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + IObjectVectorPtr RecordSelect( const IRecordSelection& sel, + IObjectIteratorPtr iter) + { + IObjectVectorPtr objects( new IObjectVector() ); + while( iter->goToNext() ) + { + IObjectPtr obj( iter->currentRef().clone() ); + if (sel.select(obj->payload())) + objects->push_back( obj ); + } + return objects; + } + + void test_RecordSelectionBrowseObjects() + { + try + { + RecordSpecification spec; + spec.extend ("I", StorageType::Int32); + spec.extend ("S", StorageType::String4k); + spec.extend ("X", StorageType::Float); + IFolderPtr folder = m_db->createFolder + ( "/a", spec, "desc", FolderVersioning::MULTI_VERSION); + + // fill with some test data + for ( int i=0; i<10; i++ ) + { + Record rec( spec ); + rec["I"].setValue<Int32>( i ); + rec["X"].setValue<Float>( 1 - ((float)i)/10 ); + std::stringstream str_value; + str_value << "Payload #" << i; + rec["S"].setValue<String4k>( str_value.str() ); + folder->storeObject( i, i+2, rec, 0 ); + } + + // store a null record + Record null_rec(spec); + null_rec["I"].setNull(); + null_rec["X"].setNull(); + null_rec["S"].setNull(); + folder->storeObject(10,12,null_rec,0); + + // invalid selection (I is not a Float in this folder) + FieldSelection invalid_sel + ( "I", StorageType::Float, FieldSelection::EQ, (Float)6.0 ); + CPPUNIT_ASSERT_THROW + ( folder->countObjects( 0, 300, 0, "", &invalid_sel ), + RelationalException ); + + // invalid selection (DUMMY does not exist in this folder) + FieldSelection invalid_sel2 + ( "DUMMY", StorageType::Float, FieldSelection::EQ, (Float)6.0 ); + CPPUNIT_ASSERT_THROW + ( folder->countObjects( 0, 300, 0, "", &invalid_sel2 ), + RelationalException ); + + + // To test untrusted user selections, we wrap a class + // around FieldSelection + class SelectionWrapper : public IRecordSelection + { + public: + IRecordSelection *sel; + + SelectionWrapper( const IRecordSelection * sel) { + this->sel=sel->clone(); + }; + + virtual ~SelectionWrapper() { + delete sel; + }; + + bool canSelect( const IRecordSpecification& spec ) const + { + return sel->canSelect( spec ); + }; + + bool select( const IRecord& record ) const + { + return sel->select( record ); + }; + + IRecordSelection* clone( ) const + { + return new SelectionWrapper( sel ); + }; + + }; + + // switch on prefetching of rows to allow browseObject()->size() + // (otherwise this will throw on untrusted selections) + folder->setPrefetchAll(true); + + + // selections on int (all 6 relations) + IObjectIteratorPtr objects; + { + FieldSelection sel + ( "I", StorageType::Int32, FieldSelection::EQ, (Int32)5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1-I-EQ count objects", + 1u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 1-I-EQ count objects", + 1u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1-I-EQ browse Objects size", + (size_t)1, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "I", StorageType::Int32, FieldSelection::NE, (Int32)5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2-I-NE count objects", + 9u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 2-I-NE count objects", + 9u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2-I-NE browse Objects size", + (size_t)9, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "I", StorageType::Int32, FieldSelection::GT, (Int32)5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3-I-GT count objects", + 4u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 3-I-GT count objects", + 4u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3-I-GT browse Objects size", + (size_t)4, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "I", StorageType::Int32, FieldSelection::GE, (Int32)5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4-I-GE count objects", + 5u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 4-I-GE count objects", + 5u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4-I-GE browse Objects size", + (size_t)5, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "I", StorageType::Int32, FieldSelection::LT, (Int32)5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5-I-LT count objects", + 5u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 5-I-LT count objects", + 5u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5-I-LT browse Objects size", + (size_t)5, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "I", StorageType::Int32, FieldSelection::LE, (Int32)5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6-I-LE count objects", + 6u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 6-I-LE count objects", + 6u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6-I-LE browse Objects size", + (size_t)6, RecordSelect(sel, objects )->size() ); + } + + // selections on int (nullness checks) + { + FieldSelection sel + ( "I", StorageType::Int32, FieldSelection::IS_NULL ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "7-I-NULL count objects", + 1u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 7-I-NULL count objects", + 1u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "7-I-NULL browse Objects size", + (size_t)1, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "I", StorageType::Int32, FieldSelection::IS_NOT_NULL ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "8-I-NOTNULL count objects", + 10u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 8-I-NOTNULL count objects", + 10u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "8-I-NOTNULL browse Objects size", + (size_t)10, RecordSelect(sel, objects )->size() ); + } + + // selections on float (all 6 relations) + { + FieldSelection sel + ( "X", StorageType::Float, FieldSelection::EQ, (Float)0.5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1-X-EQ count objects", + 1u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1-X-EQ count objects", + 1u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1-X-EQ browse Objects size", + (size_t)1, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "X", StorageType::Float, FieldSelection::NE, (Float)0.5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2-X-NE count objects", + 9u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "unstrusted 2-X-NE count objects", + 9u, folder->browseObjects( 0, 300, 0, "", &sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2-X-NE browse Objects size", + (size_t)9, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "X", StorageType::Float, FieldSelection::GT, (Float)0.5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3-X-GT count objects", + 5u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 3-X-GT count objects", + 5u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3-X-GT browse Objects size", + (size_t)5, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "X", StorageType::Float, FieldSelection::GE, (Float)0.5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4-X-GE count objects", + 6u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 4-X-GE count objects", + 6u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "4-X-GE browse Objects size", + (size_t)6, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "X", StorageType::Float, FieldSelection::LT, (Float)0.5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5-X-LT count objects", + 4u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 5-X-LT count objects", + 4u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "5-X-LT browse Objects size", + (size_t)4, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "X", StorageType::Float, FieldSelection::LE, (Float)0.5 ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6-X-LE count objects", + 5u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 6-X-LE count objects", + 5u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "6-X-LE browse Objects size", + (size_t)5, RecordSelect(sel, objects )->size() ); + } + + // selections on float (nullness checks) + { + FieldSelection sel + ( "X", StorageType::Float, FieldSelection::IS_NULL ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "7-X-NULL count objects", + 1u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 7-X-NULL count objects", + 1u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "7-X-NULL browse Objects size", + (size_t)1, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "X", StorageType::Float, FieldSelection::IS_NOT_NULL ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "8-X-NOTNULL count objects", + 10u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 8-X-NOTNULL count objects", + 10u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "8-X-NOTNULL browse Objects size", + (size_t)10, RecordSelect(sel, objects )->size() ); + } + + // composite selections + { + FieldSelection sel1 + ( "X", StorageType::Float, FieldSelection::IS_NULL ); + FieldSelection sel2 + ( "X", StorageType::Float, FieldSelection::LT, (Float)0.5 ); + CompositeSelection comp( &sel1, CompositeSelection::OR, &sel2 ); + SelectionWrapper u_sel(&comp); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "X-OR count objects", + 5u, folder->countObjects( 0, 300, 0, "", &comp) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted X-OR count objects", + 5u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "X-OR browse Objects size", + (size_t)5, RecordSelect(comp, objects )->size() ); + } + { + FieldSelection sel1 + ( "X", StorageType::Float, FieldSelection::GT, (Float)0.21 ); + FieldSelection sel2 + ( "X", StorageType::Float, FieldSelection::LT, (Float)0.49 ); + CompositeSelection comp( &sel1, CompositeSelection::AND, &sel2 ); + SelectionWrapper u_sel(&comp); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "X-AND count objects", + 2u, folder->countObjects( 0, 300, 0, "", &comp) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted X-AND count objects", + 2u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "X-AND browse Objects size", + (size_t)2, RecordSelect(comp, objects )->size() ); + } + { + FieldSelection sel1 + ( "X", StorageType::Float, FieldSelection::GT, (Float)0.21 ); + FieldSelection sel2 + ( "X", StorageType::Float, FieldSelection::LT, (Float)0.49 ); + FieldSelection sel3 + ( "I", StorageType::Int32, FieldSelection::EQ, (Int32)0 ); + CompositeSelection comp12( &sel1, CompositeSelection::AND, &sel2 ); + CompositeSelection comp( &comp12, CompositeSelection::OR, &sel3 ); + SelectionWrapper u_sel(&comp); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "AND-OR count objects", + 3u, folder->countObjects( 0, 300, 0, "", &comp) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "AND-OR count objects", + 3u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "AND-OR browse Objects size", + (size_t)3, RecordSelect(comp, objects )->size() ); + } + { + std::vector<const IRecordSelection *> sel_vec(5); + for ( int i=0; i<5; i++ ) + { + FieldSelection sel + ( "I", StorageType::Int32, FieldSelection::EQ, (Int32)i ); + sel_vec[i] = sel.clone(); + } + CompositeSelection comp( CompositeSelection::OR, sel_vec ); + SelectionWrapper u_sel(&comp); + //objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "OR-vec count objects", + 5u, folder->countObjects( 0, 300, 0, "", &comp) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "OR-vec count objects", + 5u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "OR-vec browse Objects size", + (size_t)5, RecordSelect(comp, objects )->size() ); + for ( int i=0; i<5; i++ ) + { + delete sel_vec[i]; + } + } + + // selections on string (only 2 of 6 relations allowed) + { + FieldSelection sel + ( "S", StorageType::String4k, FieldSelection::EQ, + (String4k)"Payload #1" ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1-S-EQ count objects", + 1u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 1-S-EQ count objects", + 1u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1-S-EQ browse Objects size", + (size_t)1, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "S", StorageType::String4k, FieldSelection::NE, + (String4k)"Payload #1" ); + SelectionWrapper u_sel(&sel); + // NB: the NULL value (stored as "") is counted ("" != "Payload #1") + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2-S-NE count objects", + 10u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 2-S-NE count objects", + 10u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2-S-NE browse Objects size", + (size_t)10, RecordSelect(sel, objects )->size() ); + } + { + CPPUNIT_ASSERT_THROW + ( FieldSelection( "S", StorageType::String4k, FieldSelection::GT, + (String4k)"Payload #1" ), + RecordSelectionException ); + } + { + CPPUNIT_ASSERT_THROW + ( FieldSelection( "S", StorageType::String4k, FieldSelection::GE, + (String4k)"Payload #1" ), + RecordSelectionException ); + } + { + CPPUNIT_ASSERT_THROW + ( FieldSelection( "S", StorageType::String4k, FieldSelection::LT, + (String4k)"Payload #1" ), + RecordSelectionException ); + } + { + CPPUNIT_ASSERT_THROW + ( FieldSelection( "S", StorageType::String4k, FieldSelection::LE, + (String4k)"Payload #1" ), + RecordSelectionException ); + } + + // selections on string (nullness checks) + { + CPPUNIT_ASSERT_THROW + ( FieldSelection sel + ( "S", StorageType::String4k, FieldSelection::IS_NULL ), + RecordSelectionException ); + } + { + CPPUNIT_ASSERT_THROW + ( FieldSelection sel + ( "S", StorageType::String4k, FieldSelection::IS_NOT_NULL ), + RecordSelectionException ); + } + { + FieldSelection sel + ( "S", StorageType::String4k, FieldSelection::EQ, (String4k)"" ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "7-S-EQ-EMPTYSTRING count objects", + 1u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 7-S-EQ-EMPTYSTRING count objects", + 1u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "7-S-EQ-EMPTYSTRING browse Objects size", + (size_t)1, RecordSelect(sel, objects )->size() ); + } + { + FieldSelection sel + ( "S", StorageType::String4k, FieldSelection::NE, (String4k)"" ); + SelectionWrapper u_sel(&sel); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "8-S-NE-EMPTYSTRING count objects", + 10u, folder->countObjects( 0, 300, 0, "", &sel) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "untrusted 8-S-NE-EMPTYSTRING count objects", + 10u, folder->browseObjects( 0, 300, 0, "", &u_sel)->size() ); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "8-S-NE-EMPTYSTRING browse Objects size", + (size_t)10, RecordSelect(sel, objects )->size() ); + } + + class UserPayloadSelection : public IRecordSelection + { + public: + + UserPayloadSelection() {}; + + virtual ~UserPayloadSelection() {}; + + /// Can the selection be applied to a record with the given spec? + bool canSelect( const IRecordSpecification& spec ) const + { + return spec.exists("I") && + spec["I"].storageType()==StorageType::Int32; + }; + + /// Apply the selection to the given record. + bool select( const IRecord& record ) const + { + return !record["I"].isNull() && record["I"].data<Int32>()%2 ==0; + }; + + /// Clone the record selection (and any objects referenced therein). + IRecordSelection* clone( ) const + { + return new UserPayloadSelection(); + }; + + }; + + { + UserPayloadSelection untrusted_sel; + + // countObject throws on untrusted selections + CPPUNIT_ASSERT_THROW + ( folder->countObjects( 0, 300, 0, "",&untrusted_sel), + RelationalException); + objects = folder->browseObjects( 0, 300, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "UserSel browse Objects size", + (size_t)5, RecordSelect(untrusted_sel, objects )->size() ); + folder->setPrefetchAll(true); + objects = folder->browseObjects( 0, 300, 0, "", &untrusted_sel ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "UserSel Objects size", 5u, objects->size() ); + folder->setPrefetchAll(false); + objects = folder->browseObjects( 0, 300, 0 ,"",&untrusted_sel); + + // can't query the size of the iterator for untrusted selections + // if prefetching is disabled + CPPUNIT_ASSERT_THROW( objects->size(), RelationalException ); + + } + } + catch ( std::exception& e ) + { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + void test_truncateIOV() + { + try + { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::SINGLE_VERSION); + + folder->storeObject( 0, 10, dummyPayload( 0010 ), 0); + folder->storeObject( 10, ValidityKeyMax, dummyPayload( 0520 ), 0); + folder->storeObject( 3, 30, dummyPayload( 0330 ), 1); + folder->storeObject( 30, 40000, dummyPayload( 2040 ), 1); + folder->storeObject( 3, 30, dummyPayload( 0330 ), 2); + folder->storeObject( 30, 40, dummyPayload( 2040 ), 2); + folder->storeObject( 40, ValidityKeyMax, dummyPayload( 2040 ), 2); + + + folder->storeObject( 0, 50000, dummyPayload( 2040 ), 3); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 2040 ), 4); + folder->storeObject( 0, 10, dummyPayload( 2040 ), 5); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 2040 ), 6); + folder->storeObject( 0, 80000, dummyPayload( 2040 ), 7); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 Count ", + 2u, folder->countObjects(0,100,0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 Count ", + 2u, folder->countObjects(0,100,1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 Count ", + 3u, folder->countObjects(0,100,2)); + + // test truncating of a single channel + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 Count ", + 1u, folder->countObjects(40,100,0)); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 IOV until ", + ValidityKeyMax, + folder->findObject(10,0)->until()); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 truncate ", + 1,folder->truncateObjectValidity( 35, 0)); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 Count ", + 0u, folder->countObjects(40,100,0)); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 IOV until ", + (ValidityKey)35, + folder->findObject(10,0)->until()); + + // can't truncate this IOV again + CPPUNIT_ASSERT_THROW( folder->truncateObjectValidity( 34, 0 ), + RelationalException ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 truncate ", + 0, + folder->truncateObjectValidity( 45, 0 ) ); + + // truncating of an IOV with until < ValidityKeyMax doesn't work + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 Count ", + 1u, folder->countObjects(40,100,1)); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 IOV until ", + (ValidityKey)40000, + folder->findObject(30,1)->until()); + + CPPUNIT_ASSERT_THROW( folder->truncateObjectValidity( 35, 1), + RelationalException ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 Count ", + 1u, folder->countObjects(40,100,1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 IOV until ", + (ValidityKey)40000, + folder->findObject(30,1)->until()); + + + // truncating of an IOV with until < ValidityKeyMax doesn't work + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 IOV until ", + (ValidityKey)40, + folder->findObject(30,2)->until()); + + CPPUNIT_ASSERT_THROW( folder->truncateObjectValidity( 35, 1), + RelationalException ); + + // check that nothing has changed + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 IOV until ", + (ValidityKey)40, + folder->findObject(30,2)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 IOV until ", + ValidityKeyMax, + folder->findObject(40,2)->until() ); + + // but truncating [40, ValidityKeyMax[ works + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 truncate", + 1, + folder->truncateObjectValidity( 45, 2) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 IOV until ", + (ValidityKey)45, + folder->findObject(40,2)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 IOV until ", + (ValidityKey)40, + folder->findObject(30,2)->until() ); + + // truncate more channels at once + + CPPUNIT_ASSERT_EQUAL_MESSAGE("10 IOV until ", + (ValidityKey) 50000, + folder->findObject( 80, 3)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("9 IOV until ", + ValidityKeyMax, + folder->findObject( 80, 4)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("10 IOV until ", + (ValidityKey) 10, + folder->findObject( 5, 5)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("11 IOV until ", + ValidityKeyMax, + folder->findObject( 80, 6)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("12 IOV until ", + (ValidityKey)80000, + folder->findObject( 80, 7)->until() ); + + CPPUNIT_ASSERT_THROW( folder->truncateObjectValidity( 70, + ChannelSelection::all() ), + RelationalException ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("10 IOV until ", + (ValidityKey) 50000, + folder->findObject( 80, 3)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("9 IOV until ", + ValidityKeyMax, + folder->findObject( 80, 4)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("10 IOV until ", + (ValidityKey) 10, + folder->findObject( 5, 5)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("11 IOV until ", + ValidityKeyMax, + folder->findObject( 80, 6)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("12 IOV until ", + (ValidityKey)80000, + folder->findObject( 80, 7)->until() ); + + ChannelSelection csel(4,6); + CPPUNIT_ASSERT_EQUAL_MESSAGE("4 truncate", + 2, + folder->truncateObjectValidity( 70, + csel ) ); + + CPPUNIT_ASSERT_THROW( folder->findObject( 80, 4), ObjectNotFound ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("13 IOV until ", + (ValidityKey)70, + folder->findObject( 50, 4)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("14 IOV until ", + (ValidityKey) 50000, + folder->findObject( 50, 3)->until() ); + + CPPUNIT_ASSERT_THROW( folder->findObject( 80, 4), ObjectNotFound ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("15 IOV until ", + (ValidityKey)70, + folder->findObject( 50, 4)->until() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("16 IOV until ", + (ValidityKey)80000, + folder->findObject( 50, 7)->until() ); + + // multi version folders are not allowed + IFolderPtr folderM = m_db->createFolder( "/a1", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + + folderM->storeObject( 0, 10, dummyPayload( 0010 ), 0); + folderM->storeObject( 10, ValidityKeyMax, dummyPayload( 0520 ), 0); + CPPUNIT_ASSERT_THROW( folderM->truncateObjectValidity(30,0), + RelationalException ); + + } + catch ( std::exception& e ) + { + std::cout << "Exception caught: '" << e.what() << "'" << std::endl; + throw; + } + } + + /// Creates a dummy payload AttributeList for a given index + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + RelationalFolderTest() + : CoolDBUnitTest(), payloadSpec() + { + payloadSpec.extend( "I", StorageType::Int32 ); + payloadSpec.extend( "S", StorageType::String255 ); + payloadSpec.extend( "X", StorageType::Float ); + } + + void setUp() { + dropDB(); + createDB(); + openDB(); + } + + void tearDown() { + closeDB(); // Fix for bug #27650 on OSX + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( RelationalFolderTest ); + +} // namespace + +COOLTEST_MAIN(RelationalFolderTest) diff --git a/RelationalCool/tests/RelationalFolder/test_RelationalFolder.cpp.gmtime b/RelationalCool/tests/RelationalFolder/test_RelationalFolder.cpp.gmtime new file mode 100755 index 000000000..e7f622eda --- /dev/null +++ b/RelationalCool/tests/RelationalFolder/test_RelationalFolder.cpp.gmtime @@ -0,0 +1,1738 @@ +/** + + @file test_RelationalFolder.cpp + + @author Sven A. Schmidt + + @date 2004-11-05 + + */ + + +#include<cppunit/extensions/HelperMacros.h> + +#include "SealServices/Application.h" +#include "SealKernel/ComponentLoader.h" +#include "RelationalAccess/IRelationalService.h" + +#include "CoolApplication/DatabaseSvcFactory.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/IDatabaseSvc.h" + +#include "src/RelationalException.h" +#include "src/RelationalFolder.h" +#include "src/timeToString.h" + +using pool::AttributeList; +using pool::AttributeListSpecification; + +// include for 'sleep' (ORA-01466 workaround) +#include "SealBase/TimeInfo.h" + +#include <string> +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +#include <vector> +using std::vector; + +// Needed for _tzset on Windows +#ifdef WIN32 +#include <time.h> +#endif + +// Needed for gmtime and timegm on Windows +#ifdef WIN32 +#include <time.h> +inline static time_t timegm (struct tm *t) +{ + // This code is copied as-is from SEAL Time.cpp + time_t t1 = mktime (t); + struct tm gmt = *gmtime (&t1); + time_t t2 = mktime (&gmt); + return t1 + (t1 - t2); +} +#endif + +namespace cool { + +const char* COOLTESTDB = "COOLTESTDB"; + +//! \brief RelationalFolder test class. +class RelationalFolderTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( RelationalFolderTest ); + + // The second test in this pair is kept only for reference: I thought that + // (not) calling tzset/_tzset would influence the result, but it does not! + //CPPUNIT_TEST( test_sealTimeFromDate ); + //CPPUNIT_TEST( test_sealTimeFromDate_tzset ); + + //CPPUNIT_TEST( test_timegm_gmtime ); + CPPUNIT_TEST( test_gmtime_timegm ); + /* + CPPUNIT_TEST( test_timeToString ); + + CPPUNIT_TEST( test_getFolder ); + CPPUNIT_TEST( test_findObject ); + CPPUNIT_TEST( test_findObject_MV ); + + CPPUNIT_TEST_EXCEPTION( test_findObject_wrongChannel, ObjectNotFound ); + + CPPUNIT_TEST_EXCEPTION( test_findObject_after_dropNode_SV, FolderNotFound ); + CPPUNIT_TEST_EXCEPTION( test_findObject_after_dropNode_MV, FolderNotFound ); + + CPPUNIT_TEST( test_access_outofscope_db ); + CPPUNIT_TEST( test_flushStorageBuffer ); + CPPUNIT_TEST( test_storeObject_bulk_SV ); + CPPUNIT_TEST( test_storeObject_bulk_SV_listReused ); + + CPPUNIT_TEST( test_storeObject_bulk_70k ); + + CPPUNIT_TEST( test_storeObject_bulk_MV ); + CPPUNIT_TEST( test_MV_tag_and_retrieve ); + + CPPUNIT_TEST( test_multiple_folders ); + + CPPUNIT_TEST( test_validityKeyBoundaries ); + + CPPUNIT_TEST( test_validityKeyException ); + CPPUNIT_TEST( test_exceptionInFlushStorageBuffer ); + + CPPUNIT_TEST( test_browseObjects_SV ); + CPPUNIT_TEST( test_browseObjects_MV ); + CPPUNIT_TEST( test_browseObjects_MV_tag ); + + CPPUNIT_TEST( test_listChannels ); + + CPPUNIT_TEST( test_listTags ); + CPPUNIT_TEST( test_tagInsertionTime ); + CPPUNIT_TEST( test_tagDescription ); + + CPPUNIT_TEST( test_storeObjects_bulk_multichannel ); + + CPPUNIT_TEST( test_setDescription ); + + CPPUNIT_TEST( test_storeObject_SV_overlap ); + CPPUNIT_TEST( test_storeObject_SV_overlap_bulk ); + CPPUNIT_TEST( test_storeObject_SV_unordered ); + */ + CPPUNIT_TEST_SUITE_END(); + +public: + + AttributeListSpecification payloadSpec1; + string connectString; + IDatabasePtr db; + + + /// Tests that timegm( gmtime ( time_t ) ) = ( time_t ) + /// NB: tm_years are #years after 1900 + /// NB: time_t measures seconds after 1970-1-1 + /// On Windows use private implementation of timegm (see SEAL Time.cpp) + void test_timegm_gmtime() { + time_t aTimet = (31+2)*86400+12*3600+62; // 2894462 (1970-2-3 12:01:02) + struct tm aTm = *gmtime( &aTimet ); + time_t aTimetNew = timegm( &aTm ); + bool verbose = false; + if ( verbose ) { + std::cout << "Test test_timegm_gmtime" << std::endl; + std::cout << "aTimet = " << aTimet << std::endl; + std::cout + << "aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + std::cout << "aTimetNew = " << aTimetNew << std::endl; + } + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "timegm(gmtime(time_t))==time_t", aTimet, aTimetNew ); + } + + /// Tests that gmtime( gmtime ( tm ) ) = ( tm ) + /// On Windows use private implementation of timegm (see SEAL Time.cpp) + void test_gmtime_timegm() { + bool verbose = true; + struct tm aTm; + int month; // Months in [0-11] + for ( month = 0; month < 12; month++ ) { + int year = 70; // Years after 1900 + int day = 03; + int hour = 12; + int minute = 01; + int second = 02; + // It seems that the +1 case should fail, but I fail with -1... why???! + memset (&aTm, sizeof(aTm), 0); // As in SEAL Time.cpp + aTm.tm_year = year; + aTm.tm_mon = month; + aTm.tm_mday = day; + aTm.tm_hour = hour; + aTm.tm_min = minute; + aTm.tm_sec = second; + if ( verbose ) { + std::cout << "Test test_gmtime_timegm" << std::endl; + std::cout + << "Before setting isdst: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << std::endl; + } + // Test with tm_idst = -1 + aTm.tm_isdst = -1; + if ( verbose ) std::cout + << "Before calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + time_t aTimetM1 = timegm( &aTm ); + if ( verbose ) std::cout + << "After calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + struct tm aTmM1; + aTmM1 = *gmtime( &aTimetM1 ); + // Test with tm_idst = 0 + aTm.tm_year = year; + aTm.tm_mon = month; + aTm.tm_mday = day; + aTm.tm_hour = hour; + aTm.tm_min = minute; + aTm.tm_sec = second; + aTm.tm_isdst = 0; + if ( verbose ) std::cout + << "Before calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + time_t aTimet0 = timegm( &aTm ); + if ( verbose ) std::cout + << "After calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + struct tm aTm0; + aTm0 = *gmtime( &aTimet0 ); + // Test with tm_idst = +1 + aTm.tm_year = year; + aTm.tm_mon = month; + aTm.tm_mday = day; + aTm.tm_hour = hour; + aTm.tm_min = minute; + aTm.tm_sec = second; + aTm.tm_isdst = +1; + if ( verbose ) std::cout + << "Before calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + time_t aTimetP1 = timegm( &aTm ); + if ( verbose ) std::cout + << "After calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + struct tm aTmP1; + aTmP1 = *gmtime( &aTimetP1 ); + // Verbose printout + if ( verbose ) { + std::cout + << "aTm = " + << 1900+year << "-" << month+1 << "-" << day + << " " << hour << ":" << minute << ":" << second + << " (DST=-1,0,+1)" << std::endl; + std::cout << "aTimetM1 = " << aTimetM1 << std::endl; + std::cout + << "aTmM1 = " + << 1900+aTmM1.tm_year << "-" << aTmM1.tm_mon+1 + << "-" <<aTmM1.tm_mday + << " " << aTmM1.tm_hour << ":" << aTmM1.tm_min + << ":" << aTmM1.tm_sec + << " (DST=" << aTmM1.tm_isdst << ")" << std::endl; + std::cout << "aTimet0 = " << aTimet0 << std::endl; + std::cout + << "aTm0 = " + << 1900+aTm0.tm_year << "-" << aTm0.tm_mon+1 + << "-" << aTm0.tm_mday + << " " << aTm0.tm_hour << ":" << aTm0.tm_min + << ":" << aTm0.tm_sec + << " (DST=" << aTm0.tm_isdst << ")" << std::endl; + std::cout << "aTimetP1 = " << aTimetP1 << std::endl; + std::cout + << "aTmP1 = " + << 1900+aTmP1.tm_year << "-" << aTmP1.tm_mon+1 + << "-" <<aTmP1.tm_mday + << " " << aTmP1.tm_hour << ":" << aTmP1.tm_min + << ":" << aTmP1.tm_sec + << " (DST=" << aTmP1.tm_isdst << ")" << std::endl; + } + // Actual tests + // Do NOT test isdst: gmtime ALWAYS returns isdst=0! + std::stringstream msg; + msg << " (Month[0-11]=" << month << ")"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("gmtime(timegm(tm,isDst=0))==tm : hour")+msg.str(), + hour, aTm0.tm_hour ); +//#ifndef WIN32 + // The following tests FAIL on Windows!!! + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("gmtime(timegm(tm,isDst=-1))==tm : hour")+msg.str(), + hour, aTmM1.tm_hour ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("gmtime(timegm(tm,isDst=+1))==tm : hour")+msg.str(), + hour, aTmP1.tm_hour ); +//#endif + } + } + + + /// Tests seal::Time constructor from y,mo,d,h,mi,s,ns,local + /// The test fails on Windows only for months from April onwards + void test_sealTimeFromDate() { + bool local = false; // Use UTC-GMT times + int month; // Months in [0-11] + for ( month = 0; month < 12; month++ ) { + int year = 1970; // Years after 1900 + int day = 03; + int hour = 12; + int minute = 01; + int second = 02; + long nsecond = 123456789; + // AV 28.06.2005 BUG in seal::Time constructor! + //seal::Time time( year, month, day, hour, minute, second, + // (seal::Time::ValueType)nsecond, local ); + seal::Time time = + mySealTimeConstructor( year, month, day, hour, minute, second, + (seal::Time::ValueType)nsecond, local ); + time_t s1970 = (31+2)*86400+12*3600+62; // 2894462 (1970-2-3 12:01:02) + if ( month == 0 ) s1970 -= 31*86400; // Remove January + if ( month >= 2 ) s1970 += 28*86400; // Add February (365 day year) + if ( month >= 3 ) s1970 += 31*86400; // Add March + if ( month >= 4 ) s1970 += 30*86400; // Add April + if ( month >= 5 ) s1970 += 31*86400; // Add May + if ( month >= 6 ) s1970 += 30*86400; // Add June + if ( month >= 7 ) s1970 += 31*86400; // Add July + if ( month >= 8 ) s1970 += 31*86400; // Add August + if ( month >= 9 ) s1970 += 30*86400; // Add September + if ( month >= 10 ) s1970 += 31*86400; // Add October + if ( month >= 11 ) s1970 += 30*86400; // Add November + std::stringstream msg; + msg << " (Month[0-11]=" << month << ")"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("ns from 1900")+msg.str(), + (seal::Time::ValueType)s1970*1000000000 + nsecond, time.ns() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("year")+msg.str(), year, time.year(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("month")+msg.str(), month, time.month(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("day")+msg.str(), day, time.day(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("hour")+msg.str(), hour, time.hour(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("minute")+msg.str(), minute, time.minute(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("second")+msg.str(), second, time.second(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("nsecond")+msg.str(), nsecond, time.nsecond() ); + } + } + + + /// Tests seal::Time constructor AFTER CALLING tzset() + void test_sealTimeFromDate_tzset() { +#ifdef WIN32 + _tzset(); +#else + tzset(); +#endif + test_sealTimeFromDate(); + } + + + /// Tests timeToString and stringToTime conversions + void test_timeToString() { + std::string aString1 = "2005-06-21_12:00:01.123456789 GMT"; + seal::Time aTime1 = stringToTime( aString1 ); + std::string aString2 = timeToString( aTime1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "string 2 == string 1", aString1, aString2 ); + seal::Time aTime2 = stringToTime( aString2 ); + std::string aString3 = timeToString( aTime2 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "string 3 == string 2", aString2, aString3 ); + } + + + /// Tests that storing SV objects 'non-ordered', i.e. without increasing + /// 'since' throws exceptions in both bulk and single object mode + void test_storeObject_SV_unordered() { + try { + IFolderPtr folder = db->createFolder( "/f1", payloadSpec1 ); + folder->storeObject( 4, ValidityKeyMax, dummyPayload( 1 ) ); + folder->storeObject( 2, 3, dummyPayload( 1 ) ); + folder->storeObject( 5, 6, dummyPayload( 1 ) ); + CPPUNIT_FAIL( "exception expected" ); + } catch ( seal::Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "exception text", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + e.message() ); + } + + try { + IFolderPtr folder = db->createFolder( "/f2", payloadSpec1 ); + folder->setupStorageBuffer(); + folder->storeObject( 4, ValidityKeyMax, dummyPayload( 1 ) ); + folder->storeObject( 2, 3, dummyPayload( 1 ) ); + folder->storeObject( 5, 6, dummyPayload( 1 ) ); + folder->flushStorageBuffer(); + CPPUNIT_FAIL( "unordered bulk exception expected" ); + } catch ( seal::Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "unordered bulk exception text", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + e.message() ); + } + } + + + /// Tests storeObject with overlapping intervals + /// bug #9212 reported 2005-06-24 by Federico + void test_storeObject_SV_overlap_bulk() { + try { + IFolderPtr folder = db->createFolder( "/f1", payloadSpec1 ); + folder->setupStorageBuffer(); + folder->storeObject( 300, 400, dummyPayload( 1 ) ); + folder->storeObject( 200, 400, dummyPayload( 1 ) ); + folder->flushStorageBuffer(); + CPPUNIT_FAIL( "400 until exception expected" ); + } catch ( seal::Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "400 until", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + e.message() ); + } + + try { + IFolderPtr folder = db->createFolder( "/f2", payloadSpec1 ); + folder->setupStorageBuffer(); + folder->storeObject( 300, 350, dummyPayload( 1 ) ); + folder->storeObject( 200, 400, dummyPayload( 1 ) ); + folder->flushStorageBuffer(); + CPPUNIT_FAIL( "non-equal until exception expected" ); + } catch ( seal::Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "non-equal until", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + e.message() ); + } + + try { + IFolderPtr folder = db->createFolder( "/f3", payloadSpec1 ); + folder->setupStorageBuffer(); + folder->storeObject( 300, ValidityKeyMax, dummyPayload( 1 ) ); + folder->storeObject( 200, ValidityKeyMax, dummyPayload( 1 ) ); + folder->flushStorageBuffer(); + CPPUNIT_FAIL( "ValidityKeyMax until exception expected" ); + } catch ( seal::Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMax until", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + e.message() ); + } + } + + + /// Tests storeObject with overlapping intervals + /// bug #9212 reported 2005-06-24 by Federico + void test_storeObject_SV_overlap() { + try { + IFolderPtr folder = db->createFolder( "/f1", payloadSpec1 ); + folder->storeObject( 300, 400, dummyPayload( 1 ) ); + folder->storeObject( 200, 400, dummyPayload( 1 ) ); + CPPUNIT_FAIL( "400 until exception expected" ); + } catch ( seal::Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "400 until", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + e.message() ); + } + + try { + IFolderPtr folder = db->createFolder( "/f2", payloadSpec1 ); + folder->storeObject( 300, 350, dummyPayload( 1 ) ); + folder->storeObject( 200, 400, dummyPayload( 1 ) ); + CPPUNIT_FAIL( "non-equal until exception expected" ); + } catch ( seal::Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "non-equal until", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + e.message() ); + } + + try { + IFolderPtr folder = db->createFolder( "/f3", payloadSpec1 ); + folder->storeObject( 300, ValidityKeyMax, dummyPayload( 1 ) ); + folder->storeObject( 200, ValidityKeyMax, dummyPayload( 1 ) ); + CPPUNIT_FAIL( "ValidityKeyMax until exception expected" ); + } catch ( seal::Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMax until", + string( "Overlapping intervals not allowed in SINGLE_VERSION mode" ), + e.message() ); + } + } + + + /// Tests updating the folder description + void test_setDescription() { + { + IFolderPtr folder = db->createFolder( "/myfolder", + payloadSpec1, + "a description" ); + folder->setDescription( "new description" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "internal desc update", + string( "new description" ), + folder->description() ); + } + { + IFolderPtr folder = db->getFolder( "/myfolder" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "db desc update", + string( "new description" ), + folder->description() ); + } + } + + /// Tests bulk insertion into multiple channels (SV mode) + void test_storeObjects_bulk_multichannel() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + + folder->setupStorageBuffer(); + + ChannelId nChannels = 10; + { + vector<IObjectPtr> objs; + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + folder->storeObject( (ValidityKey)0, ValidityKeyMax, + dummyPayload( (int)ch ), ch ); + } + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + folder->storeObject( (ValidityKey)5, ValidityKeyMax, + dummyPayload( (int)ch ), ch ); + } + } + + folder->flushStorageBuffer(); + + unsigned int nObjsPerChannel = 2; + IObjectPtr obj; + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + for ( unsigned int i = 0; i < nObjsPerChannel; ++i ) { + stringstream s; + s << "object " << i << ", channel " << ch << " "; + + ValidityKey pointInTime = 5 * i; // 0, 5 + obj = folder->findObject( pointInTime, ch ); + + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( (int)ch ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + pointInTime, obj->since() ); + + // until of last extends to ValidityKeyMax + if ( i < nObjsPerChannel-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + pointInTime +5, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + } + } + + + /// Tests tagDescription (MultiVersion only, SingleVersion does not have + /// tags and throws a RelationalException) + void test_tagDescription() { + try { + IFolderPtr folder = db->createFolder + ( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ) ); + folder->tag( "A", "desc A" ); + + std::string desc = folder->tagDescription( "A" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag desc", std::string("desc A"), desc ); + + try { + folder->tagDescription( "nonexisting tag" ); + CPPUNIT_FAIL( "exception not thrown for nonexisting tag" ); + } catch ( TagNotFound& /* ignored */ ) { } + + } catch ( seal::Exception& e ) { + std::cout << "Exception caught: " << e.message() << std::endl; + throw; + } + + } + + + /// Tests tagInsertionTime (MultiVersion only, SingleVersion does not have + /// tags and throws a RelationalException) + void test_tagInsertionTime() { + try{ + IFolderPtr folder = db->createFolder + ( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ) ); + + folder->tag( "A" ); + + seal::Time tagTime = folder->tagInsertionTime( "A" ); + + // the real time functionality test + // is implemented in test_RalDatabase.cpp + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tagTime size", + string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(tagTime).size() ); + + try { + folder->tagInsertionTime( "nonexisting tag" ); + CPPUNIT_FAIL( "exception not thrown for nonexisting tag" ); + } catch ( TagNotFound& /* ignored */ ) { } + + } catch ( seal::Exception& e ) { + std::cout << "Exception caught: " << e.message() << std::endl; + throw; + } + + } + + + /// Tests listTags (MultiVersion only, SingleVersion does not have tags + /// and returns an empty vector) + void test_listTags() { + IFolderPtr folder = db->createFolder( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ) ); + folder->tag( "A" ); + folder->tag( "B" ); + + std::vector<std::string> tags = folder->listTags(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag count", 2ul, (unsigned long)tags.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag 1", std::string("A"), tags[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag 2", std::string("B"), tags[1] ); + } + + + /// Tests listChannels (SingleVersion only, MultiVersion test in + /// test_RalDatabase) + void test_listChannels() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + ChannelId channel = 1; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 3; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + channel = 5; + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), channel ); + + std::vector<ChannelId> channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel count", 3ul, (unsigned long)channels.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", (ChannelId)1, channels[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", (ChannelId)3, channels[1] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", (ChannelId)5, channels[2] ); + + // check exceptional behavior + folder = db->createFolder( "/empty_folder", payloadSpec1 ); + + // a folder without data has no channels + channels = folder->listChannels(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel list size", 0ul, (unsigned long)channels.size() ); + } + + + /// Tests object browsing in tags (MV folders) + void test_browseObjects_MV_tag() { + IFolderPtr folder = db->createFolder( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, 10, dummyPayload( 0 ) ); + folder->storeObject( 10, 20, dummyPayload( 1 ) ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ) ); + + folder->tag( "mytag" ); + + { + IObjectIteratorPtr objs = folder->browseObjects( 5, 15, 0, "mytag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 1.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 until", + (ValidityKey)20, obj->until() ); + } + + { + IObjectIteratorPtr objs = folder->browseObjects( 10, 20, 0, "mytag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 2.1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + (ValidityKey)20, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 2.2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + ValidityKeyMax, obj->until() ); + } + + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + 0, "mytag" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 3.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 until", + (ValidityKey)10, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 3.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 until", + (ValidityKey)20, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 3.3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 until", + ValidityKeyMax, obj->until() ); + } + } + + + /// Tests object browsing (MV folders) + void test_browseObjects_MV() { + IFolderPtr folder = db->createFolder( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, 10, dummyPayload( 0 ) ); + folder->storeObject( 10, 20, dummyPayload( 1 ) ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ) ); + + { + IObjectIteratorPtr objs = folder->browseObjects( 5, 15 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 1.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 until", + (ValidityKey)20, obj->until() ); + } + + { + IObjectIteratorPtr objs = folder->browseObjects( 10, 20 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 2.1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + (ValidityKey)20, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 2.2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + ValidityKeyMax, obj->until() ); + } + + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 3.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 until", + (ValidityKey)10, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 3.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 until", + (ValidityKey)20, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 3.3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 until", + ValidityKeyMax, obj->until() ); + } + } + + + /// Tests object browsing (SV folders) + void test_browseObjects_SV() { + IFolderPtr folder = db->createFolder( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::SINGLE_VERSION ); + + folder->storeObject( 0, 10, dummyPayload( 0 ) ); + folder->storeObject( 10, 20, dummyPayload( 1 ) ); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ) ); + + { + IObjectIteratorPtr objs = folder->browseObjects( 5, 15 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 1.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 until", + (ValidityKey)20, obj->until() ); + } + + { + IObjectIteratorPtr objs = folder->browseObjects( 10, 20 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 2ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 2.1 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + (ValidityKey)20, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 2.2 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 2.1 until", + ValidityKeyMax, obj->until() ); + } + + + { + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", 3ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 3.1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.1 until", + (ValidityKey)10, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 3.2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 since", + (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.2 until", + (ValidityKey)20, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "obj 3.3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 since", + (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 3.3 until", + ValidityKeyMax, obj->until() ); + } + } + + /// Tests that the storage buffer is cleared and none of the objects + /// is stored if an exception is thrown during the bulk operation + /// 'flushStorageBuffer' (for instance, because one IOV has until<since) + void test_exceptionInFlushStorageBuffer() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + + folder->setupStorageBuffer(); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ) ); + folder->storeObject( 10, 20, dummyPayload( 1 ) ); + bool flushFailed = false; + try { + folder->flushStorageBuffer(); + } catch ( ValidityKeyException& /* dummy */ ) { + flushFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "first insertion OK", ! flushFailed ); + + folder->setupStorageBuffer(); + folder->storeObject( 20, ValidityKeyMax, dummyPayload( 2 ) ); + folder->storeObject( 30, 20, dummyPayload( 3 ) ); // INVALID! + folder->storeObject( 40, 50, dummyPayload( 4 ) ); + flushFailed = false; + try { + folder->flushStorageBuffer(); + } catch ( ValidityKeyException& /* dummy */ ) { + flushFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "second insertion not OK", flushFailed ); + + folder->setupStorageBuffer(); + folder->storeObject( 50, ValidityKeyMax, dummyPayload( 5 ) ); + folder->storeObject( 60, 70, dummyPayload( 6 ) ); + flushFailed = false; + try { + folder->flushStorageBuffer(); + } catch ( ValidityKeyException& /* dummy */ ) { + flushFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "third insertion OK", ! flushFailed ); + + IObjectPtr obj0 = folder->findObject( 0 ); + CPPUNIT_ASSERT_MESSAGE( "object 0 found", obj0.get() != 0 ); + IObjectPtr obj1 = folder->findObject( 10 ); + CPPUNIT_ASSERT_MESSAGE( "object 1 found", obj1.get() != 0 ); + + bool objectNotFound = false; + try { + folder->findObject( 20 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "object 2 not found", objectNotFound ); + + objectNotFound = false; + try { + folder->findObject( 30 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "object 3 not found", objectNotFound ); + + objectNotFound = false; + try { + folder->findObject( 40 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "object 4 not found", objectNotFound ); + + IObjectPtr obj5 = folder->findObject( 50 ); + CPPUNIT_ASSERT_MESSAGE( "object 5 found", obj5.get() != 0 ); + IObjectPtr obj6 = folder->findObject( 60 ); + CPPUNIT_ASSERT_MESSAGE( "object 6 found", obj6.get() != 0 ); + + } + + /// Tests that a ValidityKeyException is thrown when since>until + /// and when since or until are out of boundaries + void test_validityKeyException() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + + bool storeFailed = false; + try { + folder->storeObject( 100, 0, dummyPayload( 0 ) ); + } catch ( ValidityKeyException& /* dummy */ ) { + storeFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "exception for [100,0]", storeFailed ); + + storeFailed = false; + try { + folder->storeObject( 100, 100, dummyPayload( 0 ) ); + } catch ( ValidityKeyException& /* dummy */ ) { + storeFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "exception for [100,100]", storeFailed ); + + storeFailed = false; + try { + // Split the following line on two lines (Windows compiler warning) + //ValidityKey since = ValidityKeyMin-1; + ValidityKey since = ValidityKeyMin; + since = since-1; + ValidityKey until = ValidityKeyMin; + // NB: Now (ValidityKey=long_long, ValidityKeyMin=LONG_LONG_MIN) + // ==> LONG_LONG_MIN-1 is an invalid int64 LONG_LONG_MAX > since + // NB: Previously (ValidityKey=long_long, ValidityKeyMin=LONG_MIN) + // ==> LONG_MIN-1 is an invalid int64 > LONG_MIN=ValidityKeyMin + folder->storeObject( since, until, dummyPayload( 0 ) ); + } catch ( ValidityKeyException& /* dummy */ ) { + storeFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "exception for [min-1,min]", storeFailed ); + + storeFailed = false; + try { + ValidityKey since = ValidityKeyMax; + // Split the following line on two lines (Windows compiler warning) + //ValidityKey until = ValidityKeyMax+1; + ValidityKey until = ValidityKeyMax; + until = until+1; + // NB: Now (ValidityKey=long_long, ValidityKeyMin=LONG_LONG_MIN) + // ==> LONG_LONG_MIN-1 is an invalid int64 LONG_LONG_MAX > since + // NB: Previously (ValidityKey=long_long, ValidityKeyMin=LONG_MIN) + // ==> LONG_MIN-1 is an invalid int64 > LONG_MIN=ValidityKeyMin + folder->storeObject( since, until, dummyPayload( 0 ) ); + } catch ( ValidityKeyException& /* dummy */ ) { + storeFailed = true; + } + CPPUNIT_ASSERT_MESSAGE( "exception for [max,max+1]", storeFailed ); + + } + + /// Tests that the ValidityKey boundaries are those we expect + /// (use hardcoded numerical values) + void test_validityKeyBoundaries() { + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "ValidityKeyMin hardcoded", + // (ValidityKey)0, ValidityKeyMin + 9223372036854775808ULL ); + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "ValidityKeyMax hardcoded", + // (ValidityKey)0, ValidityKeyMax - 18446744073709551615ULL ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMin hardcoded", + (ValidityKey)0, ValidityKeyMin ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMax hardcoded", + (ValidityKey)0, ValidityKeyMax - 9223372036854775807LL ); + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "ValidityKeyMin sInt64Min", + // (ValidityKey)sInt64Min, ValidityKeyMin ); + //CPPUNIT_ASSERT_EQUAL_MESSAGE + // ( "ValidityKeyMin uInt64Max", + // (ValidityKey)uInt64Max, ValidityKeyMax ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMin uInt64Min", + (ValidityKey)uInt64Min, ValidityKeyMin ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "ValidityKeyMin sInt64Max", + (ValidityKey)sInt64Max, ValidityKeyMax ); + } + + + /// Stores objects to multiple folders and retrieves them in a loop + /// Tests against a problem first reported by Marco Clemencic on + /// 2005-01-27 -- cannot reproduce at the moment + void test_multiple_folders() { + bool showPrintout = false; + + int nFolders = 5; + vector<string> foldernames; + for ( int i = 0; i < nFolders; ++i ) { + stringstream s; + s << "/f_" << i; + foldernames.push_back( s.str() ); + } + + long nObjs = 100; + + for ( vector<string>::const_iterator fname = foldernames.begin(); + fname != foldernames.end(); ++fname ) { + IFolderPtr folder = db->createFolder( *fname, payloadSpec1 ); + } + + for ( vector<string>::const_iterator fname = foldernames.begin(); + fname != foldernames.end(); ++fname ) { + IFolderPtr folder = db->getFolder( *fname ); + folder->setupStorageBuffer(); + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ) ); + } + folder->flushStorageBuffer(); + + if ( showPrintout ) + cout << "wrote " << nObjs + << " objects in folder '" << *fname << endl; + } + + for ( vector<string>::const_iterator fname = foldernames.begin(); + fname != foldernames.end(); ++fname ) { + IFolderPtr folder = db->getFolder( *fname ); + IObjectIteratorPtr objs + = folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0, "" ); + + objs->goToStart(); + + CPPUNIT_ASSERT_MESSAGE( "hasNext", objs->hasNext() ); + + long objIndex = 0; + while ( objs->hasNext() ) { + IObjectPtr obj = objs->next(); + + stringstream s; + s << "folder " << *fname << ": object " << objIndex << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( objIndex ) + == obj->payload() ); + + if ( showPrintout && objIndex % 10 == 0 ) { + for ( AttributeList::const_iterator attr = obj->payload().begin(); + attr != obj->payload().end(); ++attr ) { + cout << *fname << "[" << objIndex << "]: " + << attr->spec().name() << ", " + << attr->spec().type_name() << ", " + << attr->getValueAsString() << endl; + } + } + + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + objIndex, (long)obj->since() ); + + // last object's until extends to ValidityKeyMax + if ( objIndex < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + objIndex+1, (long)obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + + ++objIndex; + } + + if ( showPrintout ) + cout << "checked " << objIndex + << " objects in folder " << *fname << endl; + } + } + + + /// Tests MV tagging and retrieving + void test_MV_tag_and_retrieve() { + IFolderPtr folder = db->createFolder( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + folder->storeObject( 0, 4, dummyPayload( 0 ) ); + folder->storeObject( 2, 6, dummyPayload( 1 ) ); + folder->flushStorageBuffer(); + + folder->tag( "tagA", "an optional description" ); + seal::Time asOfDate = folder->findObject( 0 )->insertionTime(); + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + seal::TimeInfo::sleep(1); + + folder->setupStorageBuffer(); + folder->storeObject( 3, 7, dummyPayload( 2 ) ); + folder->storeObject( 5, 9, dummyPayload( 3 ) ); + folder->flushStorageBuffer(); + + folder->tag( "tagB" ); + folder->tag( asOfDate, "tagC" ); // == tagA + + // fetch tagA + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + (ChannelId)0, + "tagA" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA object count", 2ul, objs->size() ); + + IObjectPtr obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "tagA obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "tagA obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 2 until", + (ValidityKey)6, obj->until() ); + + // fetch tagB + objs = folder->browseObjects( ValidityKeyMin, ValidityKeyMax, + (ChannelId)0, "tagB" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB object count", 4ul, objs->size() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "tagB obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "tagB obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 2 until", + (ValidityKey)3, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "tagB obj 3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 3 since", + (ValidityKey)3, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 3 until", + (ValidityKey)5, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "tagB obj 4 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 4 since", + (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagB obj 4 until", + (ValidityKey)9, obj->until() ); + + // fetch head + objs = folder->browseObjects( ValidityKeyMin, ValidityKeyMax, + (ChannelId)0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD object count", 4ul, objs->size() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "HEAD obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "HEAD obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 2 until", + (ValidityKey)3, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "HEAD obj 3 payload", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 3 since", + (ValidityKey)3, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 3 until", + (ValidityKey)5, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "HEAD obj 4 payload", + dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 4 since", + (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "HEAD obj 4 until", + (ValidityKey)9, obj->until() ); + + // fetch tagC + objs = folder->browseObjects( ValidityKeyMin, ValidityKeyMax, + (ChannelId)0, "tagC" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC object count", 2ul, objs->size() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "tagC obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = objs->next(); + CPPUNIT_ASSERT_MESSAGE( "tagC obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagC obj 2 until", + (ValidityKey)6, obj->until() ); + } + + + /// Tests bulk storeObject of MV objects + void test_storeObject_bulk_MV() { + IFolderPtr folder = db->createFolder( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + unsigned long nObjs = 10; + for ( unsigned long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ) ); + } + + // cppunit 1.8.0 does not have CPPUNIT_ASSERT_EXCEPTION + bool objectNotFound = false; + try { + folder->findObject( 0 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "no objects", objectNotFound ); + + folder->flushStorageBuffer(); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax ); + + for ( unsigned long i = 0; i < objs->size(); ++i ) { + IObjectPtr obj = objs->next(); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( i ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + (ValidityKey)i, obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + (ValidityKey)i+1, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + + } + + + /// Tests bulk storeObject of 70k objects: this caused an ORA-24381 + /// error before a sub-batching fix was applied + void test_storeObject_bulk_70k() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + + folder->setupStorageBuffer(); + long nObjs = 70*1000; + for ( long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ) ); + } + + folder->flushStorageBuffer(); + + IObjectPtr obj; + for ( long i = 0; i < nObjs; i += 1000 ) { + obj = folder->findObject( i ); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( i ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + i, (long)obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + i+1, (long)obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + LONG_MAX, (long)obj->until() ); + } + } + + } + + + /// Tests bulk storeObject of SV objects with a reused AttributeList + /// This test ensures that the payload data is copied, not referenced + /// inside the storage buffer. + void test_storeObject_bulk_SV_listReused() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + + AttributeList payload = dummyPayload( 0 ); + + folder->setupStorageBuffer(); + unsigned long nObjs = 100; + for ( unsigned long i = 0; i < nObjs; ++i ) { + payload["I"].setValue<int>( (int)i ); + folder->storeObject( i, ValidityKeyMax, payload ); + } + + // cppunit 1.8.0 does not have CPPUNIT_ASSERT_EXCEPTION + bool objectNotFound = false; + try { + folder->findObject( 0 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "no objects", objectNotFound ); + + folder->flushStorageBuffer(); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax ); + + for ( unsigned long i = 0; i < objs->size(); ++i ) { + IObjectPtr obj = objs->next(); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload I" ).c_str(), + (int)i == obj->payloadValue<int>( "I" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + (ValidityKey)i, obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + (ValidityKey)i+1, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + + } + + + /// Tests bulk storeObject of SV objects + void test_storeObject_bulk_SV() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + + folder->setupStorageBuffer(); + unsigned long nObjs = 100; + for ( unsigned long i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ) ); + } + + // cppunit 1.8.0 does not have CPPUNIT_ASSERT_EXCEPTION + bool objectNotFound = false; + try { + folder->findObject( 0 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "no objects", objectNotFound ); + + folder->flushStorageBuffer(); + + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax ); + + for ( unsigned long i = 0; i < objs->size(); ++i ) { + IObjectPtr obj = objs->next(); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( i ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + (ValidityKey)i, obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + (ValidityKey)i+1, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + + } + + + /// Tests bulk operation 'flushStorageBuffer' + void test_flushStorageBuffer() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + + folder->setupStorageBuffer(); + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ) ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ) ); + + // cppunit 1.8.0 does not have CPPUNIT_ASSERT_EXCEPTION + bool objectNotFound = false; + try { + folder->findObject( 1 ); + } catch( ObjectNotFound& /* dummy */ ) { + objectNotFound = true; + } + CPPUNIT_ASSERT_MESSAGE( "no objects", objectNotFound ); + + try { + folder->flushStorageBuffer(); + } catch ( RelationalException& e ) { + cout << e.message() << endl; + throw; + } + + IObjectPtr obj0 = folder->findObject( 0 ); + CPPUNIT_ASSERT_MESSAGE( "object 1 found", obj0.get() != 0 ); + IObjectPtr obj1 = folder->findObject( 1 ); + CPPUNIT_ASSERT_MESSAGE( "object 1 found", obj1.get() != 0 ); + } + + + /// Tests reading back of a folder from a db handle that went out of scope + void test_access_outofscope_db() { + IFolderPtr folder; + + { + IDatabaseSvc& dbSvc = DatabaseSvcFactory::databaseService(); + IDatabasePtr db1 = dbSvc.openDatabase( connectString, false ); + folder = db1->createFolder( "/myfolder", payloadSpec1 ); + // db1 isgoing of of scope here but folder keeps + // its own handle to the db + } + + folder->storeObject( 0, 2, dummyPayload( 1 ) ); + } + + + /// Tests reading back of an Object from a deleted MV folder + void test_findObject_after_dropNode_MV() { + IFolderPtr folder = db->createFolder( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::MULTI_VERSION); + folder->storeObject( 0, 2, dummyPayload( 1 ) ); + db->dropNode( "/myfolder" ); + + // this is expected to throw a FolderNotFound exception + IObjectPtr obj = folder->findObject( 1 ); + } + + + /// Tests reading back of an Object from a SV deleted folder + void test_findObject_after_dropNode_SV() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + folder->storeObject( 0, 2, dummyPayload( 1 ) ); + db->dropNode( "/myfolder" ); + + // this is expected to throw a FolderNotFound exception + IObjectPtr obj = folder->findObject( 1 ); + } + + + /// Tests reading back of an Object from a channel that does not exist + void test_findObject_wrongChannel() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + ChannelId channel1 = 1; + ChannelId channel2 = 2; + folder->storeObject( 0, 2, dummyPayload( 1 ), channel1 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), channel1 ); + try { + // This is expected to throw an exception + IObjectPtr obj1 = folder->findObject( 1, channel2 ); + } catch ( seal::Exception& /*e*/ ) { + //std::cout << "Exception caught: " << e.message() << std::endl; + throw; + } + } + + + /// Tests storing and reading back of an Object in a MultiVersion folder + /// This test is implemented in more detail with respect to the object + /// attributes in test_RalDatabase + void test_findObject_MV() { + IFolderPtr folder = db->createFolder( "/myfolder", + payloadSpec1, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, 2, dummyPayload( 1 ) ); + folder->storeObject( 2, 4, dummyPayload( 2 ) ); + + IObjectPtr obj1 = folder->findObject( 1 ); + CPPUNIT_ASSERT_MESSAGE( "first object", + dummyPayload( 1 ) == obj1->payload() ); + + IObjectPtr obj2 = folder->findObject( 3 ); + CPPUNIT_ASSERT_MESSAGE( "second object", + dummyPayload( 2 ) == obj2->payload() ); + } + + + /// Tests storing and reading back of an Object + /// This test is implemented in more detail with respect to the object + /// attributes in test_RalDatabase + void test_findObject() { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec1 ); + + folder->storeObject( 0, 2, dummyPayload( 1 ) ); + folder->storeObject( 2, 4, dummyPayload( 2 ) ); + + IObjectPtr obj1 = folder->findObject( 1 ); + CPPUNIT_ASSERT_MESSAGE( "first object", + dummyPayload( 1 ) == obj1->payload() ); + + IObjectPtr obj2 = folder->findObject( 3 ); + CPPUNIT_ASSERT_MESSAGE( "second object", + dummyPayload( 2 ) == obj2->payload() ); + } + + + /// Tests creating and retrieving a folder. + /// This test is implemented in more detail with respect to the folder + /// attributes in test_RalDatabase + void test_getFolder() { + try { + string folderName( "/myfolder" ); + db->createFolder( folderName, payloadSpec1, "a description" ); + + IFolderPtr folder = db->getFolder( folderName ); + CPPUNIT_ASSERT( folder.get() != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "name", folderName, folder->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "description", string( "a description" ), folder->description() ); + CPPUNIT_ASSERT_MESSAGE + ( "isLeaf", folder->isLeaf() ); + CPPUNIT_ASSERT_MESSAGE + ( "isStored", folder->isStored() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "insertionTime", string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(folder->insertionTime()).size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "id", 1ul, folder->id() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "parentId", 0ul, folder->parentId() ); + + } catch ( Exception& e ) { + cout << e.message() << endl; + e.rethrow(); + } + } + + + /// Creates a dummy payload AttributeList for a given index + AttributeList dummyPayload( int index ) { + AttributeList payload( payloadSpec1 ); + payload["I"].setValue<int>( index ); + stringstream s; + s << "Object " << index; + payload["S"].setValue<std::string>( s.str() ); + payload["X"].setValue<float>( (float)(index/1000.) ); + return payload; + } + + void setUp() { + /* + try { + + if ( payloadSpec1.size() == 0 ) { + payloadSpec1.push_back("I","int"); + payloadSpec1.push_back("S","string"); + payloadSpec1.push_back("X","float"); + } + + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + cout << "Please provide a connect string by specifying " + << "one in the environment variable COOLTESTDB, e.g." + << endl; + cout << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" + << endl; + cout << "Aborting test" << endl; + exit(-1); + } + + IDatabaseSvc& dbSvc = DatabaseSvcFactory::databaseService(); + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + + } catch ( seal::Exception& e ) { + cout << e.message() << endl; + throw; + } + */ + } + + void tearDown() { + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( RelationalFolderTest ); + +} // namespace + +// sas: This file is from the OPAL package I believe. It allows for +// shorter test classes and prepares the test class for OPAL +#include<CppUnit_testdriver.icpp> + + diff --git a/RelationalCool/tests/RelationalFolderSet/test_RelationalFolderSet.cpp b/RelationalCool/tests/RelationalFolderSet/test_RelationalFolderSet.cpp new file mode 100644 index 000000000..9d39febf4 --- /dev/null +++ b/RelationalCool/tests/RelationalFolderSet/test_RelationalFolderSet.cpp @@ -0,0 +1,332 @@ +/** + + @file test_RelationalFolderSet.cpp + + @author Sven A. Schmidt and Andrea Valassi + + @date 2005-06-08 + + */ + +#include "../Common/CppUnit_headers.h" // Disable CppUnit header warnings + +#include "src/CoralApplication.h" + +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IFolderSet.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoolKernel/types.h" + +#include "CoralBase/AttributeList.h" +#include "CoralBase/Attribute.h" +using coral::AttributeList; + +#include <iostream> + +#include <string> +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +#include <vector> +using std::vector; + +#include "src/timeToString.h" + +namespace cool { + +const char* COOLTESTDB = "COOLTESTDB"; + +//! \brief RelationalFolderSet test class. +class RelationalFolderSetTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( RelationalFolderSetTest ); + + CPPUNIT_TEST( test_getFolderSet ); + + CPPUNIT_TEST( test_listFolders ); + CPPUNIT_TEST( test_listFolderSets ); + + CPPUNIT_TEST( test_setDescription ); + + CPPUNIT_TEST( test_dropNode_nonempty_folderset ); + + CPPUNIT_TEST( test_setTagDescription ); + CPPUNIT_TEST( test_setTagDescription_bug33989 ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + string connectString; + IDatabasePtr db; + + RecordSpecification payloadSpec; + + + void test_setTagDescription_bug33989() + { + IFolderSetPtr fsetroot = db->getFolderSet("/"); + IFolderSetPtr fset = db->createFolderSet("/A"); + IFolderPtr f = db->createFolder("/A/f1", payloadSpec, "", + FolderVersioning::MULTI_VERSION); + f->storeObject(0, 2, dummyPayload(0), 0); + f->tagCurrentHead("F1"); + f->createTagRelation("A", "F1"); + try + { + f->setTagDescription("A", "new desc"); // should fail! + CPPUNIT_FAIL( "setTagDescription from child should fail!" ); + } + catch( Exception& /*e*/ ){} + try + { + fsetroot->setTagDescription("A", "new desc"); // should fail! + CPPUNIT_FAIL( "setTagDescription from parent should fail!" ); + } + catch( Exception& /*e*/ ){} + } + + void test_setTagDescription() { + IFolderSetPtr fsetroot = db->getFolderSet("/"); + IFolderSetPtr fset = db->createFolderSet("/A"); + IFolderPtr f = db->createFolder("/A/f1", payloadSpec, "", + FolderVersioning::MULTI_VERSION); + f->storeObject(0, 2, dummyPayload(0), 0); + f->tagCurrentHead("F1"); + f->createTagRelation("A", "F1"); + CPPUNIT_ASSERT_EQUAL(std::string(""), fset->tagDescription("A")); + //f->setTagDescription("A", "new desc"); // should fail! + fset->setTagDescription("A", "new desc"); + CPPUNIT_ASSERT_EQUAL(std::string("new desc"), fset->tagDescription("A")); + fset->createTagRelation("ROOT", "A"); + CPPUNIT_ASSERT_EQUAL(std::string(""), fsetroot->tagDescription("ROOT")); + //f->setTagDescription("ROOT", "new desc2"); // should fail! + fsetroot->setTagDescription("ROOT", "new desc2"); + CPPUNIT_ASSERT_EQUAL(std::string("new desc2"), fsetroot->tagDescription("ROOT")); + } + + + /// Tests behavior of dropNode being called on a nonempty folder set + void test_dropNode_nonempty_folderset() { + // Test dropping with a contained folderset + db->createFolderSet( "/folderset_1" ); + db->createFolderSet( "/folderset_1/folderset_1" ); + + try { + db->dropNode( "/folderset_1" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "error message (containing folderset)", + string( "Cannot drop folderset '/folderset_1', " + "because it is not empty" ), + string( e.what() ) ); + } + + // Test dropping with a contained folder + db->createFolderSet( "/folderset_2" ); + db->createFolder( "/folderset_2/folder", payloadSpec ); + + try { + db->dropNode( "/folderset_2" ); + } catch ( Exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "error message (containing folderset)", + string( "Cannot drop folderset '/folderset_2', " + "because it is not empty" ), + string( e.what() ) ); + } + } + + + /// Tests updating the folder description + void test_setDescription() { + { + IFolderSetPtr folderset = db->createFolderSet( "/myfolderset", + "a description" ); + folderset->setDescription( "new description" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "internal desc update", + string( "new description" ), + folderset->description() ); + } + { + IFolderSetPtr folderset = db->getFolderSet( "/myfolderset" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "db desc update", + string( "new description" ), + folderset->description() ); + } + } + + /// Tests listFolderSets + void test_listFolderSets() { + try { + IFolderSetPtr folderset = db->createFolderSet( "/folderset" ); + db->createFolderSet( "/folderset/folderset_2" ); + db->createFolderSet( "/folderset/folderset_3" ); + db->createFolderSet( "/folderset/folderset_1" ); + db->createFolder( "/folderset/folder", payloadSpec ); + + bool ascending = true; + vector<string> foldersets = folderset->listFolderSets( ascending ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folderset count", 3u, (unsigned int)foldersets.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folderset_1", string( "/folderset/folderset_1" ), foldersets[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folderset_2", string( "/folderset/folderset_2" ), foldersets[1] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folderset_3", string( "/folderset/folderset_3" ), foldersets[2] ); + + ascending = false; + foldersets = folderset->listFolderSets( ascending ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folderset_1", string( "/folderset/folderset_3" ), foldersets[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folderset_2", string( "/folderset/folderset_2" ), foldersets[1] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folderset_3", string( "/folderset/folderset_1" ), foldersets[2] ); + + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + + /// Tests listFolders + void test_listFolders() { + try { + IFolderSetPtr folderset = db->createFolderSet( "/folderset" ); + db->createFolder( "/folderset/folder_2", payloadSpec ); + db->createFolder( "/folderset/folder_3", payloadSpec ); + db->createFolder( "/folderset/folder_1", payloadSpec ); + db->createFolderSet( "/folderset/folderset" ); + + bool ascending = true; + vector<string> folders = folderset->listFolders( ascending ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder count", 3u, (unsigned int)folders.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder_1", string( "/folderset/folder_1" ), folders[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder_2", string( "/folderset/folder_2" ), folders[1] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder_3", string( "/folderset/folder_3" ), folders[2] ); + + ascending = false; + folders = folderset->listFolders( ascending ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder_1", string( "/folderset/folder_3" ), folders[0] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder_2", string( "/folderset/folder_2" ), folders[1] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder_3", string( "/folderset/folder_1" ), folders[2] ); + + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + + /// Tests creating and retrieving a folderset. + void test_getFolderSet() { + try { + db->createFolderSet( "/folderset", "a description" ); + + IFolderSetPtr folderset = db->getFolderSet( "/folderset" ); + CPPUNIT_ASSERT( folderset.get() != 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "name", string( "/folderset" ), folderset->fullPath() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "description", string( "a description" ), folderset->description() ); + CPPUNIT_ASSERT_MESSAGE + ( "isLeaf", ! folderset->isLeaf() ); + CPPUNIT_ASSERT_MESSAGE + ( "isStored", folderset->isStored() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "insertionTime", string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(folderset->insertionTime()).size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "id", 1u, folderset->id() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "parentId", 0u, folderset->parentId() ); + + } catch ( Exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + + + /// Creates a dummy payload AttributeList for a given index + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + RelationalFolderSetTest() + : payloadSpec() { + + payloadSpec.extend("I",StorageType::Int32); + payloadSpec.extend("S",StorageType::String255); + payloadSpec.extend("X",StorageType::Float); + + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + std::cout << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << std::endl; + std::cout << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << std::endl; + std::cout << "Aborting test" << std::endl; + exit(-1); + } + } + + ~RelationalFolderSetTest() {} + + void setUp() { + try + { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + } + catch ( std::exception& e ) + { + cout << e.what() << endl; + throw; + } + } + + void tearDown() { + db.reset(); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( RelationalFolderSetTest ); + +} // namespace + +// sas: This file is from the OPAL package I believe. It allows for +// shorter test classes and prepares the test class for OPAL +#include<CppUnit_testdriver.icpp> + + diff --git a/RelationalCool/tests/RelationalObjectIterator/test_RelationalObjectIterator.cpp b/RelationalCool/tests/RelationalObjectIterator/test_RelationalObjectIterator.cpp new file mode 100644 index 000000000..04b2adf81 --- /dev/null +++ b/RelationalCool/tests/RelationalObjectIterator/test_RelationalObjectIterator.cpp @@ -0,0 +1,585 @@ +// $Id: test_RelationalObjectIterator.cpp,v 1.2 2008-10-30 16:07:41 avalassi Exp $ +/** + + @file test_RalObjectIterator.cpp + + @author Core Team + + @date 2005-10-21 + + */ + +#include "../Common/CppUnit_headers.h" // Disable CppUnit header warnings + +#include "src/CoralApplication.h" + +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoralBase/Attribute.h" + +#include "../Performance/Benchmark.h" +#include "../../src/attributeListToString.h" +#include "../../src/IteratorException.h" + +// ---- these things are needed to force a drop of the connection +#include "src/RalDatabaseSvc.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" + +using coral::AttributeList; + +#include <string> +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +namespace cool { + + const char* COOLTESTDB = "COOLTESTDB"; + +/** + RalObjectIterator test class +*/ + +class RalObjectIteratorTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( RalObjectIteratorTest ); + + CPPUNIT_TEST( test_browseObjects ); + CPPUNIT_TEST( test_begin ); + CPPUNIT_TEST( test_iterator_prefix_increment ); + CPPUNIT_TEST( test_end ); + CPPUNIT_TEST( test_for_loop ); + CPPUNIT_TEST( test_cursor_read_concurrency ); + CPPUNIT_TEST( test_cursor_read_concurrency2 ); + CPPUNIT_TEST( test_cursor_write_concurrency ); + CPPUNIT_TEST( test_goToNext ); + CPPUNIT_TEST( test_close ); + CPPUNIT_TEST( test_destructor ); + CPPUNIT_TEST( test_reverse ); + + CPPUNIT_TEST( test_bug36646 ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + // PORT This is a workaround to ease migration. We need to review the + // whole ALS issue (best eliminate it) + RecordSpecification payloadSpec; + string connectString; + IDatabasePtr db; + IFolderPtr folder; + + + /// Test for bug #36646 in ConstRecordAdapter + void test_bug36646() + { + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec ); + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + folder->setPrefetchAll( false ); + IObjectIteratorPtr objs = + folder->browseObjects( 0, 10, ChannelSelection::all() ); + objs->goToNext(); + const IObject& obj1 = objs->currentRef(); + CPPUNIT_ASSERT_MESSAGE + ( "first object", dummyPayload( 1 ) == obj1.payload() ); + const IRecord& p = obj1.payload(); + const coral::AttributeList& a = p.attributeList(); + try + { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "payload IRecord.size == AttributeList.size", + (int)p.specification().size(), (int)a.size() ); + } + catch( ... ) + { + std::cout << "\npayload(): " << p << std::endl; + std::cout << "payload().attributeList(): " + << attributeListToString(a) << std::endl; + throw; + } + } + + IObjectPtr getNext( IObjectIteratorPtr objs) { + if (!objs->goToNext()) + CPPUNIT_FAIL("no next object"); + return IObjectPtr( objs->currentRef().clone() ); + } + + /// Tests basic reverse iterator behavior. + /// More complex scenarios are tested in higher level tests. + void test_reverse() { + ChannelSelection ch( 0, 0, ChannelSelection::sinceDescBeforeChannel ); + IObjectIteratorPtr objs = folder->browseObjects( 0, 30, ch, "" ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object count", + 3u, (unsigned int)objs->size() ); + IObjectPtr iter = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 2 payload", + dummyPayload( 2 ) == iter->payload() ); + iter = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 1 payload", + dummyPayload( 1 ) == iter->payload() ); + iter = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "obj 0 payload", + dummyPayload( 0 ) == iter->payload() ); + } + + + /// Tests that the destructor ends the transaction + void test_destructor() { + try { + folder->setPrefetchAll( false ); + IObjectIteratorPtr objs = folder->browseObjects( 5, 25, 0 ); + IObjectIteratorPtr null; + //std::cout << "Delete iterator" << std::endl; + objs = null; + //std::cout << "Deleted iterator" << std::endl; + objs = folder->browseObjects( 5, 25, 0 ); + CPPUNIT_ASSERT_MESSAGE( "goToNext", objs->goToNext() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests that close ends the transaction + void test_close() { + try { + folder->setPrefetchAll( false ); + IObjectIteratorPtr objs = folder->browseObjects( 5, 25, 0 ); + //std::cout << "Close iterator" << std::endl; + objs->close(); + //std::cout << "Closed iterator" << std::endl; + objs = folder->browseObjects( 5, 25, 0 ); + CPPUNIT_ASSERT_MESSAGE( "goToNext", objs->goToNext() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Test goToNext + void test_goToNext() { + IObjectIteratorPtr objs = folder->browseObjects( 5, 25, 0 ); + CPPUNIT_ASSERT_MESSAGE( "goToNext", objs->goToNext() ); + } + + + void test_browse_performance() { + folder->setPrefetchAll( false ); + int nObjs = 100; + IFolderPtr folder = db->createFolder( "/myfolder", payloadSpec ); + + { + folder->setupStorageBuffer(); + + for ( int i = 0; i < nObjs; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ), 0 ); + } + + folder->flushStorageBuffer(); + + } + + if (1) { + Benchmark b; + b.start(); + + IObjectIteratorPtr objs = + folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0 ); + + int nReadObjects = 0; + //for ( IObjectIterator::const_iterator + // i = objs->begin(); i != objs->end(); ++i ) { + // ++nReadObjects; + //} + while ( objs->goToNext() ) { + ++nReadObjects; + } + + double secElapsed = b.stop(); + + cout << "** browsing " << nObjs << " objects **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + + /* + if (1) { + Benchmark b; + b.start(); + + IObjectIteratorPtr objs = + folder->browseObjects( ValidityKeyMin, ValidityKeyMax, 0, "" ); + + long nReadObjects = objs->size(); + + double secElapsed = b.stop(); + + cout << "** reading " << nObjs << " objects **" << endl; + cout << "read back " << nReadObjects << " objects" << endl; + cout << "sec total: " << secElapsed << endl; + cout << "obj/s: " << nReadObjects/secElapsed << endl; + } + */ + + } + + + /// Tests behavior of a cursor with a concurrent write operation. + void test_cursor_write_concurrency() { + folder->setPrefetchAll( false ); + IObjectIteratorPtr objs1 = folder->browseObjects( 5, 25, 0 ); + objs1->goToNext(); + try { + folder->storeObject( 0, 2, dummyPayload( 0 ), 0 ); + CPPUNIT_FAIL( "exception expected" ); + } catch ( std::exception& e ) { + CPPUNIT_ASSERT_EQUAL + ( string( "Cannot start a concurrent write transaction" ), + string( e.what() ) ); + } + } + + + /// Tests behavior of concurrent read-only cursors. + void test_cursor_read_concurrency() + { + bool debug = false; + folder->setPrefetchAll( false ); + + IObjectIteratorPtr objs1 = folder->browseObjects( 5, 25, 0 ); + if ( debug ) std::cout << "1st iterator started" << std::endl; + + try + { + IObjectIteratorPtr objs2 = folder->browseObjects( 5, 25, 0 ); + if ( debug ) std::cout << "2nd iterator started" << std::endl; + CPPUNIT_FAIL( "Should not be able to retrieve/start 2nd iterator" ); + + // What follows is the old COOL210 test + // (which succeeded before fixing bug #25151) + IObjectPtr obj; + CPPUNIT_ASSERT( objs1->goToNext() ); + obj = IObjectPtr( objs1->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + if ( debug ) std::cout << "1st iterator: next() executed" << std::endl; + + CPPUNIT_ASSERT( objs2->goToNext() ); + obj = IObjectPtr( objs2->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + if ( debug ) std::cout << "2nd iterator: next() executed" << std::endl; + + CPPUNIT_ASSERT( objs1->goToNext() ); + obj = IObjectPtr( objs1->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + if ( debug ) std::cout << "1st iterator: next() executed" << std::endl; + + CPPUNIT_ASSERT( objs2->goToNext() ); + obj = IObjectPtr( objs2->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + if ( debug ) std::cout << "2nd iterator: next() executed" << std::endl; + + CPPUNIT_ASSERT( objs1->goToNext() ); + obj = IObjectPtr( objs1->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 2 ) == obj->payload() ); + if ( debug ) std::cout << "1st iterator: next() executed" << std::endl; + + CPPUNIT_ASSERT( objs2->goToNext() ); + obj = IObjectPtr( objs2->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 2 ) == obj->payload() ); + if ( debug ) std::cout << "2nd iterator: next() executed" << std::endl; + } + catch ( TooManyIterators& ){} + } + + + /// Tests behavior of concurrent read-only cursors + /// (when one is closed before the end). + /// This fails catastrophically (abort and stack trace) in COOL210. + void test_cursor_read_concurrency2() + { + bool debug = false; + folder->setPrefetchAll( false ); + + IObjectIteratorPtr objs1 = folder->browseObjects( 5, 25, 0 ); + if ( debug ) std::cout << "1st iterator started" << std::endl; + + try + { + IObjectIteratorPtr objs2 = folder->browseObjects( 5, 25, 0 ); + if ( debug ) std::cout << "2nd iterator started" << std::endl; + CPPUNIT_FAIL( "Should not be able to retrieve/start 2nd iterator" ); + + // What follows is the old COOL210 test + // (which succeeded before fixing bug #25151) + IObjectPtr obj; + CPPUNIT_ASSERT( objs1->goToNext() ); + obj = IObjectPtr( objs1->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + if ( debug ) + std::cout << "1st iterator: currentRef().clone() executed" << std::endl; + + CPPUNIT_ASSERT( objs2->goToNext() ); + obj = IObjectPtr( objs2->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 0 ) == obj->payload() ); + if ( debug ) + std::cout << "2nd iterator: currentRef().clone() executed" << std::endl; + + CPPUNIT_ASSERT( objs1->goToNext() ); + obj = IObjectPtr( objs1->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + if ( debug ) + std::cout << "1st iterator: currentRef().clone() executed" << std::endl; + + CPPUNIT_ASSERT( objs2->goToNext() ); + objs2->close(); + if ( debug ) + std::cout << "2nd iterator: close() executed" << std::endl; + + CPPUNIT_ASSERT( objs1->goToNext() ); + obj = IObjectPtr( objs1->currentRef().clone() ); + CPPUNIT_ASSERT( dummyPayload( 2 ) == obj->payload() ); + if ( debug ) + std::cout << "1st iterator: currentRef().clone() executed" << std::endl; + } + catch ( TooManyIterators& ){} + } + + + /// Tests correct for-loop behavior. + void test_for_loop() { + folder->setPrefetchAll( false ); + IObjectIteratorPtr objs = folder->browseObjects( 5, 25, 0 ); + + int loop_count = 0; + //for ( IObjectIterator::const_iterator + // obj = objs->begin(); obj != objs->end(); ++obj ) { + while ( objs->goToNext() ) { + IObjectPtr obj( objs->currentRef().clone() ); + CPPUNIT_ASSERT_MESSAGE + ( "obj payload", dummyPayload( loop_count ) == obj->payload() ); + ++loop_count; + } + CPPUNIT_ASSERT_EQUAL_MESSAGE( "loop count", 3, loop_count ); + } + + + + /// Tests that the iterator correctly points at the end after the container + /// has been exhausted. + void test_end() { + folder->setPrefetchAll( false ); + try { + IObjectIteratorPtr objs = folder->browseObjects( 5, 25, 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object count", 3u, (unsigned int)objs->size() ); + //IObjectIterator::const_iterator iter = objs->begin(); + objs->goToNext(); + //CPPUNIT_ASSERT_MESSAGE + // ( "Iterator different from end()", iter != objs->end() ); + //CPPUNIT_ASSERT_MESSAGE + // ( "Iterator different from end()", objs->hasNext() ); + //++iter; + //++iter; + //++iter; + objs->goToNext(); + objs->goToNext(); + //objs->next(); // next() can be called ONLY three times! + //CPPUNIT_ASSERT_MESSAGE + // ( "Iterator pointing at end", iter == objs->end() ); + CPPUNIT_ASSERT_MESSAGE + ( "Iterator pointing at end", !objs->goToNext() ); + try { + objs->currentRef(); // goToNext() can be called ONLY three times! + CPPUNIT_FAIL( "exception expected" ); + } catch ( IteratorHasNoCurrentItem& ) { + } catch ( std::exception& e ) { + CPPUNIT_FAIL + ( "Exception caught (IteratorHasNoCurrentItem expected): " + + std::string( e.what() ) ); + } catch ( ... ) { + CPPUNIT_FAIL + ( "Unknown exception caught, IteratorHasNoNextItem expected" ); + } + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests that prefix operator++ correctly iterates through the container. + void test_iterator_prefix_increment() { + folder->setPrefetchAll( false ); + IObjectIteratorPtr objs = folder->browseObjects( 5, 25, 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object count", 3u, (unsigned int)objs->size() ); + + //IObjectIterator::const_iterator iter = objs->begin(); + IObjectPtr iter; + + //++iter; + iter=getNext( objs ); + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == iter->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, iter->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, iter->until() ); + + //++iter; + iter = getNext( objs ); + CPPUNIT_ASSERT_MESSAGE( "obj 1.2 payload", + dummyPayload( 1 ) == iter->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 since", + (ValidityKey)10, iter->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 until", + (ValidityKey)20, iter->until() ); + + //++iter; + iter= getNext( objs ); + CPPUNIT_ASSERT_MESSAGE( "obj 1.3 payload", + dummyPayload( 2 ) == iter->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.3 since", + (ValidityKey)20, iter->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.3 until", + ValidityKeyMax, iter->until() ); + } + + + /// Tests that begin returns an iterator pointing at the first item. + void test_begin() + { + folder->setPrefetchAll( false ); + try { + IObjectIteratorPtr objs = folder->browseObjects( 5, 25, 0 ); + + CPPUNIT_ASSERT_MESSAGE( "no cursor", objs != 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object count", 3u, (unsigned int)objs->size() ); + + //IObjectIterator::const_iterator iter = objs->begin(); + IObjectPtr iter; + iter=getNext( objs ); + + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == iter->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, iter->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, iter->until() ); + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + + } + + + /// Tests that browseObjects does not fail + /// (if this fails, test_begin will also fail) + void test_browseObjects() + { + folder->setPrefetchAll( false ); + try { + IObjectIteratorPtr objs = folder->browseObjects( 5, 25, 0 ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Creates a dummy payload AttributeList for a given index + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + RalObjectIteratorTest() + : payloadSpec() { + + payloadSpec.extend("I",StorageType::Int32); + payloadSpec.extend("S",StorageType::String255); + payloadSpec.extend("X",StorageType::Float); + + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + cout << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << endl; + cout << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << endl; + cout << "Aborting test" << endl; + exit(-1); + } + + } + + ~RalObjectIteratorTest() {} + + + void setUp() { + try { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + + string folderName( "/folder_1" ); + folder = db->createFolder( folderName, payloadSpec ); + for ( int i = 0; i < 3; ++i ) { + ValidityKey since = i*10; + ValidityKey until = ValidityKeyMax; + Record payload = dummyPayload( i ); + folder->storeObject( since, until, payload, 0 ); + } + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + void tearDown() { + db.reset(); + folder.reset(); + // Here I want to purge the connection pool + //cool::sleep(1); + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + RalDatabaseSvc* rdbSvc = dynamic_cast<RalDatabaseSvc*>(&dbSvc); + rdbSvc->connectionSvc().configuration().setConnectionTimeOut(-1); + rdbSvc->connectionSvc().purgeConnectionPool(); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( RalObjectIteratorTest ); + +} // namespace + +// sas: This file is from the OPAL package I believe. It allows for +// shorter test classes and prepares the test class for OPAL +#include<CppUnit_testdriver.icpp> + + diff --git a/RelationalCool/tests/RelationalObjectMgr/test_RelationalObjectMgr.cpp b/RelationalCool/tests/RelationalObjectMgr/test_RelationalObjectMgr.cpp new file mode 100644 index 000000000..cf0afd4a1 --- /dev/null +++ b/RelationalCool/tests/RelationalObjectMgr/test_RelationalObjectMgr.cpp @@ -0,0 +1,4938 @@ +// $Id: test_RelationalObjectMgr.cpp,v 1.3 2008-11-03 15:34:10 avalassi Exp $ +/** + + @file test_RelationalObjectMgr.cpp + + @author Sven A. Schmidt + + @date 2006-04-19 + + */ + +#include "CoolDBUnitTest.h" + +#include "src/HvsTagRecord.h" +#include "src/RalDatabase.h" +#include "src/RelationalObjectMgr.h" +#include "src/RalQueryMgr.h" +#include "src/RalSequenceMgr.h" +#include "src/RelationalChannelTable.h" +#include "src/RelationalObject.h" +#include "src/RelationalObjectTable.h" +#include "src/RelationalObjectTableRow.h" +#include "src/RelationalSequence.h" +#include "src/RelationalTagMgr.h" +#include "src/RelationalTransaction.h" +#include "src/SimpleObject.h" +#include "src/timeToString.h" + +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/types.h" + +#include "RelationalAccess/ICursor.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" + +using coral::AttributeList; +using coral::AttributeListSpecification; + +#include <string> +using std::cout; +using std::endl; +using std::string; +#include <sstream> +using std::stringstream; +#include <vector> +using std::vector; + +namespace cool +{ + + inline Time addOneNsToTime( ITime& time ) + { + return Time( time.year(), + time.month(), + time.day(), + time.hour(), + time.minute(), + time.second(), + time.nanosecond()+1 ); + } + +class RelationalObjectMgrTest : public CoolDBUnitTest +{ + + CPPUNIT_TEST_SUITE( RelationalObjectMgrTest ); + + CPPUNIT_TEST( test_bulkUpdateObjectTableIov ); + + CPPUNIT_TEST( test_findObject ); + + CPPUNIT_TEST( test_storeObjects_SV ); + CPPUNIT_TEST( test_storeObjects_SV_different_channel ); + CPPUNIT_TEST( test_storeObjects_empty_list ); + CPPUNIT_TEST( test_storeObjects_bulk_100 ); + + CPPUNIT_TEST( test_browseObjects_SV ); + CPPUNIT_TEST( test_browseObjects_MV ); + CPPUNIT_TEST( test_browseObjects_SV_reverse ); + CPPUNIT_TEST( test_browseObjects_MV_reverse ); + + CPPUNIT_TEST( test_mv_UInt64Max_iov ); + CPPUNIT_TEST( test_sv_UInt64Max_iov ); + + CPPUNIT_TEST( test_storeObjects_bulk_multichannel ); + + // ------ MV tests ------ + + CPPUNIT_TEST( test_SimpleObject_filter ); + CPPUNIT_TEST( test_SimpleObject_intersect ); + CPPUNIT_TEST( test_SimpleObject_visisbleThrough ); + CPPUNIT_TEST( test_SimpleObject_visisbleThrough2 ); + + CPPUNIT_TEST( test_processMultiVersionObjects_case_0a ); + CPPUNIT_TEST( test_processMultiVersionObjects_case_0b ); + CPPUNIT_TEST( test_processMultiVersionObjects_case_1a ); + CPPUNIT_TEST( test_processMultiVersionObjects_case_1b ); + CPPUNIT_TEST( test_processMultiVersionObjects_case_1c ); + CPPUNIT_TEST( test_processMultiVersionObjects_case_2 ); + CPPUNIT_TEST( test_processMultiVersionObjects_case_3 ); + CPPUNIT_TEST( test_processMultiVersionObjects_case_4 ); + CPPUNIT_TEST( test_processMultiVersionObjects_case_5b ); + + CPPUNIT_TEST( test_updateObjectTableNewHeadId_1 ); + CPPUNIT_TEST( test_updateObjectTableNewHeadId_2 ); + CPPUNIT_TEST( test_updateObjectTableNewHeadId_3 ); + + // new algo, with prefetch + CPPUNIT_TEST( test_mergeWithHead_case_1a_prefetch ); + CPPUNIT_TEST( test_mergeWithHead_case_1b_prefetch ); + CPPUNIT_TEST( test_mergeWithHead_case_3_prefetch ); + + CPPUNIT_TEST( test_storeObjects_MV_newInsert_prefetch ); + + CPPUNIT_TEST( test_storeObjects_MV_case_0a_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_0b_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_1a_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_2_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_3_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_4_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_5b_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_6_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_0a_channels_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_5b_6_channels_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_identicalIov_case_1_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_identicalIov_case_2_prefetch ); + +#ifndef WIN32 + // old algo, without prefetch (except on Windows) + CPPUNIT_TEST( test_mergeWithHead_case_1a_no_prefetch ); + CPPUNIT_TEST( test_mergeWithHead_case_1b_no_prefetch ); + CPPUNIT_TEST( test_mergeWithHead_case_3_no_prefetch ); + + CPPUNIT_TEST( test_storeObjects_MV_newInsert_no_prefetch ); + + CPPUNIT_TEST( test_storeObjects_MV_case_0a_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_0b_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_1a_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_2_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_3_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_4_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_5b_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_6_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_0a_channels_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_case_5b_6_channels_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_identicalIov_case_1_no_prefetch ); + CPPUNIT_TEST( test_storeObjects_MV_identicalIov_case_2_no_prefetch ); +#endif + + /// \todo these should be in a TagMgr test instead + CPPUNIT_TEST( test_insertTagTableRow_fetchTagTableRow ); + CPPUNIT_TEST( test_insertTagTableRow_exists ); + CPPUNIT_TEST( test_insertTagTableRow_HEAD ); + CPPUNIT_TEST( test_fetchTagTableRow_notFound ); + + CPPUNIT_TEST( test_existsTag_global ); + + CPPUNIT_TEST( test_insertObject2TagTableRows_fetchObject2TagTableRow ); + + CPPUNIT_TEST( test_tag_asOfDate_5c ); + CPPUNIT_TEST( test_tag_HEAD_5c ); + CPPUNIT_TEST( test_tag_exists ); + + CPPUNIT_TEST( test_findObject_tag_5c ); + CPPUNIT_TEST( test_findObject_HEAD_5c ); + + CPPUNIT_TEST( test_insertGlobalTagTableRow_fetchGlobalTagTableRow ); + CPPUNIT_TEST( test_tag_differentFolders_sameTag ); + + CPPUNIT_TEST( test_tag_asOfObjectId_userObject_5c ); + + CPPUNIT_TEST( test_deleteObject2TagTableRows ); + CPPUNIT_TEST( test_deleteTagTableRow ); + CPPUNIT_TEST( test_deleteGlobalTagTableRow ); + CPPUNIT_TEST( test_deleteTag ); + CPPUNIT_TEST( test_deleteTag_nonexisting ); + + CPPUNIT_TEST( test_insertionTimeOfLastObjectInTag ); + + CPPUNIT_TEST( test_updateObjectTableNewHeadId_userTag ); + CPPUNIT_TEST( test_existsUserTag ); + CPPUNIT_TEST( test_existsUserTag_normal_tag ); + CPPUNIT_TEST( test_userTag_systemObjects ); + + // ----------- Channels table tests ----------- + + CPPUNIT_TEST( test_insertChannelTableRow ); + CPPUNIT_TEST( test_updateChannelTable ); + CPPUNIT_TEST( test_bulkUpdateChannelTable ); + CPPUNIT_TEST( test_fetchLastRowsWithNewData ); + CPPUNIT_TEST( test_channelTableFK ); + + // ----------- lastUpdate tests --------------- + + CPPUNIT_TEST( test_lastUpdate_SV ); + CPPUNIT_TEST( test_lastUpdate_MV ); + + CPPUNIT_TEST_SUITE_END(); + +private: + + bool updateObjectTableNewHeadId + ( RelationalObjectMgr* mgr, + const std::string& objectTableName, + const std::string& channelTableName, + const ValidityKey& since, + const ValidityKey& until, + const ChannelId& channelId, + const unsigned int newHeadId, + const unsigned int userTagId = 0 ) + { + SOVector newHeadUpdaters; + SimpleObject so( newHeadId, // NOTE THE MISUSE... + channelId, + since, + until ); + newHeadUpdaters.push_back( so ); + return mgr->bulkUpdateObjectTableNewHeadId( objectTableName, + channelTableName, + newHeadUpdaters, + userTagId ); + } + +public: + + inline void storeObjects + ( RelationalFolder* folder, + const std::vector<RelationalObjectPtr>& objects, + const bool userTagOnly = false ) const + { + RelationalTransaction transaction( ralDb->transactionMgr() ); // read-write + objMgr->__storeObjects( folder, objects, userTagOnly ); + transaction.commit(); + } + + RalDatabase* ralDb; // safely cast pointer to db + std::auto_ptr<RelationalObjectMgr> objMgr; + + RecordSpecification payloadSpec; + + RelationalObjectMgrTest() + : payloadSpec() { + + payloadSpec.extend("I",StorageType::Int32); + payloadSpec.extend("S",StorageType::String255); + payloadSpec.extend("X",StorageType::Float); + } + + ~RelationalObjectMgrTest() {} + +#ifndef WIN32 +#define TEST_WITH_AND_WITHOUT_PREFETCH(test) \ + void test##_prefetch() { \ + char *env=getenv("COOL_MVINSERTION_PREFETCH_MAXROWS"); \ + unsetenv("COOL_MVINSERTION_PREFETCH_MAXROWS"); \ + test(); \ + if (env) { \ + setenv("COOL_MVINSERTION_PREFETCH_MAXROWS",env,1);\ + }; \ + }; \ + void test##_no_prefetch() { \ + char *env=getenv("COOL_MVINSERTION_PREFETCH_MAXROWS"); \ + setenv("COOL_MVINSERTION_PREFETCH_MAXROWS","0",1); \ + test(); \ + if (env) { \ + setenv("COOL_MVINSERTION_PREFETCH_MAXROWS",env,1);\ + } \ + else unsetenv("COOL_MVINSERTION_PREFETCH_MAXROWS");\ + } +#else + // Test only the default case on Windows +#define TEST_WITH_AND_WITHOUT_PREFETCH(test) \ + void test##_prefetch() { \ + test(); \ + } +#endif + + // test with old and new algo (with and without prefetch) + TEST_WITH_AND_WITHOUT_PREFETCH( test_mergeWithHead_case_1a ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_mergeWithHead_case_1b ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_mergeWithHead_case_3 ); + + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_newInsert ); + + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_0a ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_0b ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_1a ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_2 ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_3 ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_4 ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_5b ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_6 ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_0a_channels ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_case_5b_6_channels ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_identicalIov_case_1 ); + TEST_WITH_AND_WITHOUT_PREFETCH( test_storeObjects_MV_identicalIov_case_2 ); + + + + /// Tests findObject + void test_findObject() { + try{ + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + // Create a temporary sequence to get the server SYSDATE before insertion + Time timeBef; + std::string tmpSeqName = string( m_coolDBName + "_TMP_CLOCK" ); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + if ( ralDb->queryMgr().sequenceMgr().existsSequence( tmpSeqName ) ) + ralDb->queryMgr().sequenceMgr().dropSequence( tmpSeqName ); + boost::shared_ptr<RelationalSequence> tmpSeq = + ralDb->queryMgr().sequenceMgr().createSequence( tmpSeqName ); + tmpSeq->nextVal(); + timeBef = stringToTime( tmpSeq->currDate() ); // Time before insertion + //std::cout << "Time before insertion: " << timeBef << std::endl; + transaction.commit(); + } + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + // (if test checks for strict < or >; not needed if checks for <= or >=) + sleep(1); + + // Insert the objects into the folder + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 0, 2 ) ); + objs.push_back( dummyObject( 2, 2, 4 ) ); + storeObjects( relfolder, objs ); + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + // (if test checks for strict < or >; not needed if checks for <= or >=) + sleep(1); + + // Get the server SYSDATE after insertion + Time timeAft; + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> tmpSeq = + ralDb->queryMgr().sequenceMgr().getSequence( tmpSeqName ); + tmpSeq->nextVal(); + timeAft = stringToTime( tmpSeq->currDate() ); // Time before insertion + //std::cout << "Time after insertion: " << timeAft << std::endl; + transaction.commit(); + } + + // Cleanup - drop the temporary sequence + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + ralDb->queryMgr().sequenceMgr().dropSequence( tmpSeqName ); + transaction.commit(); + } + + // Retrieve the first object + IObjectPtr obj1 = objMgr->findObject( relfolder, 1, 0 ); + CPPUNIT_ASSERT_MESSAGE( "first object", + dummyPayload( 1 ) == obj1->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "first object since", + (ValidityKey)0, obj1->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "first object until", + (ValidityKey)2, obj1->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "first object id", + 1u, obj1->objectId() ); + + // Analyse the object insertion time + Time timeIns = obj1->insertionTime(); + //std::cout << "Time before insertion: " << timeBef << std::endl; + //std::cout << "Time at insertion: " << timeIns << std::endl; + //std::cout << "Time after insertion: " << timeAft << std::endl; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "year of insertion time is 200x", + 200, timeIns.year()/10 ); + CPPUNIT_ASSERT_MESSAGE( "insertion time > time before insertion", + timeIns > timeBef ); + CPPUNIT_ASSERT_MESSAGE( "insertion time < time after insertion", + timeIns < timeAft ); + + // Retrieve the second object + IObjectPtr obj2 = objMgr->findObject( relfolder, 3, 0 ); + CPPUNIT_ASSERT_MESSAGE( "second object", + dummyPayload( 2 ) == obj2->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "second object since", + (ValidityKey)2, obj2->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "second object until", + (ValidityKey)4, obj2->until() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + + } + + + /// Tests storeObject for SV objects + void test_storeObjects_SV() { + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + { + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 2, 2, ValidityKeyMax ) ); + objs.push_back( dummyObject( 4, 4, ValidityKeyMax ) ); + storeObjects( relfolder, objs ); + } + { + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 6, 6, ValidityKeyMax ) ); + objs.push_back( dummyObject( 8, 8, ValidityKeyMax ) ); + storeObjects( relfolder, objs ); + } + + IObjectPtr obj = objMgr->findObject( relfolder, 2, 0 ); + CPPUNIT_ASSERT_MESSAGE( "first object", + dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "first object since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "first object until", + (ValidityKey)4, obj->until() ); + + obj = objMgr->findObject( relfolder, 4, 0 ); + CPPUNIT_ASSERT_MESSAGE( "second object", + dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "second object since", + (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "second object until", + (ValidityKey)6, obj->until() ); + + obj = objMgr->findObject( relfolder, 6, 0 ); + CPPUNIT_ASSERT_MESSAGE( "third object", + dummyPayload( 6 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "third object since", + (ValidityKey)6, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "third object until", + (ValidityKey)8, obj->until() ); + + obj = objMgr->findObject( relfolder, 8, 0 ); + CPPUNIT_ASSERT_MESSAGE( "fourth object", + dummyPayload( 8 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "fourth object since", + (ValidityKey)8, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "fourth object until", + ValidityKeyMax, obj->until() ); + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests storeObject for SV objects in different channels + void test_storeObjects_SV_different_channel() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + relfolder->createChannel( 0, "0" ); + relfolder->createChannel( 1, "1" ); + + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 0, ValidityKeyMax, 0 ) ); + objs.push_back( dummyObject( 2, 2, ValidityKeyMax, 0 ) ); + storeObjects( relfolder, objs ); + objs.clear(); + objs.push_back( dummyObject( 3, 4, ValidityKeyMax, 0 ) ); + storeObjects( relfolder, objs ); + objs.clear(); + objs.push_back( dummyObject( 4, 0, ValidityKeyMax, 1 ) ); + objs.push_back( dummyObject( 5, 2, ValidityKeyMax, 1 ) ); + storeObjects( relfolder, objs ); + objs.clear(); + objs.push_back( dummyObject( 6, 4, ValidityKeyMax, 1 ) ); + storeObjects( relfolder, objs ); + + IObjectPtr obj = objMgr->findObject( relfolder, 0, 0 ); + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)2, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)0, obj->channelId() ); + + obj = objMgr->findObject( relfolder, 2, 0 ); + CPPUNIT_ASSERT( dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)4, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)0, obj->channelId() ); + + obj = objMgr->findObject( relfolder, 4, 0 ); + CPPUNIT_ASSERT( dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL( ValidityKeyMax, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)0, obj->channelId() ); + + obj = objMgr->findObject( relfolder, 0, 1 ); + CPPUNIT_ASSERT( dummyPayload( 4 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)2, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = objMgr->findObject( relfolder, 2, 1 ); + CPPUNIT_ASSERT( dummyPayload( 5 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)4, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + + obj = objMgr->findObject( relfolder, 4, 1 ); + CPPUNIT_ASSERT( dummyPayload( 6 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)4, obj->since() ); + CPPUNIT_ASSERT_EQUAL( ValidityKeyMax, obj->until() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)1, obj->channelId() ); + } + + + /// Tests storeObject with an empty list of objects + void test_storeObjects_empty_list() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + vector<RelationalObjectPtr> objs; + storeObjects( relfolder, objs ); + + CPPUNIT_ASSERT_MESSAGE( "reached without exception", true ); + } + + + /// Tests storeObject for bulk r/w of 100 SV objects + void test_storeObjects_bulk_100() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + vector<RelationalObjectPtr> objs; + unsigned int nObjs = 100; + for ( unsigned int i = 0; i < nObjs; ++i ) { + objs.push_back( dummyObject( i, i, ValidityKeyMax ) ); + } + storeObjects( relfolder, objs ); + + IObjectPtr obj; + for ( unsigned int i = 0; i < nObjs; ++i ) { + obj = objMgr->findObject( relfolder, i, 0 ); + stringstream s; + s << "object " << i << " "; + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( i ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + (ValidityKey)i, obj->since() ); + // last object's until extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + (ValidityKey)i+1, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + } + + IObjectPtr getNext( IObjectIteratorPtr objs) { + if (!objs->goToNext()) + CPPUNIT_FAIL("no next object"); + return IObjectPtr( objs->currentRef().clone() ); + } + + /// Tests bulkUpdateObjectTableIov + void test_bulkUpdateObjectTableIov() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 0, 1 ) ); + objs.push_back( dummyObject( 2, 10, 11 ) ); + objs.push_back( dummyObject( 3, 20, 21 ) ); + storeObjects( relfolder, objs ); + + std::map<unsigned int,ValidityKey> objectIdNewUntil; + objectIdNewUntil[1] = 9; + objectIdNewUntil[2] = 19; + objectIdNewUntil[3] = 29; + + RelationalTransaction transaction( ralDb->transactionMgr() ); + objMgr->bulkUpdateObjectTableIov( relfolder->objectTableName(), + objectIdNewUntil ); + transaction.commit(); + + { + IObjectIteratorPtr objs = + relfolder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all() ); + + CPPUNIT_ASSERT_EQUAL( 3u, objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Payload size", dummyPayload( 1 ).size(), obj->payload().size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Payload[I]", dummyPayload( 1 )["I"], obj->payload()["I"] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Payload[S]", dummyPayload( 1 )["S"], obj->payload()["S"] ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Payload[X]", dummyPayload( 1 )["X"], obj->payload()["X"] ); + try { + CPPUNIT_ASSERT( dummyPayload( 1 ) == obj->payload() ); + } + catch (...) { + std::cout << "Expected: " << dummyPayload( 1 ) << std::endl; + std::cout << "Actual: " << obj->payload() << std::endl; + throw; + } + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "Payload", (const IRecord&)dummyPayload( 1 ), obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)9, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 2 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)10, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)19, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT( dummyPayload( 3 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)20, obj->since() ); + CPPUNIT_ASSERT_EQUAL( (ValidityKey)29, obj->until() ); + } + } + + + /// Tests browseObjects for a SV folder in reverse order + void test_browseObjects_SV_reverse() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + unsigned int nObjs = 100; + + for ( ChannelId channel = 0; channel < 5; ++channel ) { + vector<RelationalObjectPtr> objs; + for ( unsigned int i = 0; i < nObjs; ++i ) { + objs.push_back( dummyObject( i, i, ValidityKeyMax, channel ) ); + } + storeObjects( relfolder, objs ); + } + + try { + ValidityKey since = 50; + ValidityKey until = 70; + ChannelSelection channels( 2, 2, + ChannelSelection::sinceDescBeforeChannel ); + string tag = ""; + IObjectIteratorPtr cursor = + objMgr->browseObjects( relfolder, since, until, channels, tag ); + + CPPUNIT_ASSERT_MESSAGE( "no cursor", cursor != 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 21u, + (unsigned int)cursor->size() ); + + // test content + unsigned int nBObjs = 0; + while ( cursor->goToNext() ) { + IObjectPtr obj( cursor->currentRef().clone() ); + + stringstream s; + s << "object " << nBObjs << " "; + + CPPUNIT_ASSERT_MESSAGE + ( ( s.str() + "payload" ).c_str(), + dummyPayload( (int)(until - nBObjs) ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + until - nBObjs, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + until - nBObjs +1, obj->until() ); + + ++nBObjs; + } + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "number of objects", 21u, nBObjs ); + + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + /// Tests browseObjects for a MV folder in reverse order + void test_browseObjects_MV_reverse() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + unsigned int nObjs = 100; + + for ( ChannelId channel = 0; channel < 5; ++channel ) { + vector<RelationalObjectPtr> objs; + for ( unsigned int i = 0; i < nObjs; ++i ) { + objs.push_back( dummyObject( i, i, ValidityKeyMax, channel ) ); + } + storeObjects( relfolder, objs ); + } + + try { + ValidityKey since = 50; + ValidityKey until = 70; + ChannelSelection channels( 2, 2, + ChannelSelection::sinceDescBeforeChannel ); + string tag = ""; + IObjectIteratorPtr cursor = + objMgr->browseObjects( relfolder, since, until, channels, tag ); + + CPPUNIT_ASSERT_MESSAGE( "no cursor", cursor != 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 21u, + (unsigned int)cursor->size() ); + + // test content + unsigned int nBObjs = 0; + while ( cursor->goToNext() ) { + IObjectPtr obj( cursor->currentRef().clone() ); + + stringstream s; + s << "object " << nBObjs << " "; + + CPPUNIT_ASSERT_MESSAGE + ( ( s.str() + "payload" ).c_str(), + dummyPayload( (int)(until - nBObjs) ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + until - nBObjs, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + until - nBObjs + 1, obj->until() ); + + nBObjs++; + } + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "number of objects", 21u, nBObjs ); + + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + /// Tests browseObjects for a SV folder + void test_browseObjects_SV() + { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + unsigned int nObjs = 100; + + for ( ChannelId channel = 0; channel < 5; ++channel ) { + vector<RelationalObjectPtr> objs; + for ( unsigned int i = 0; i < nObjs; ++i ) { + objs.push_back( dummyObject( i, i, ValidityKeyMax, channel ) ); + } + storeObjects( relfolder, objs ); + } + + try { + ValidityKey since = 50; + ValidityKey until = 70; + ChannelSelection channels( 2, 2 ); + string tag = ""; + + IObjectIteratorPtr cursor = + objMgr->browseObjects( relfolder, since, until, channels, tag ); + + CPPUNIT_ASSERT_MESSAGE( "no cursor", cursor != 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 21u, + (unsigned int)cursor->size() ); + + // test content + unsigned int nBObjs = 0; + //for ( IObjectIterator::const_iterator i = cursor->begin(); + // i != cursor->end(); ++ i ) { + // IObjectPtr obj = *i; + while ( cursor->goToNext() ) { + IObjectPtr obj( cursor->currentRef().clone() ); + + stringstream s; + s << "object " << nBObjs << " "; + + CPPUNIT_ASSERT_MESSAGE + ( ( s.str() + "payload" ).c_str(), + dummyPayload( (int)(since+nBObjs) ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + since + nBObjs, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + since + nBObjs + 1, obj->until() ); + + nBObjs++; + } + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "number of objects", 21u, nBObjs ); + + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + /// Tests browseObjects for a MV folder + void test_browseObjects_MV() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + unsigned int nObjs = 100; + + for ( ChannelId channel = 0; channel < 5; ++channel ) { + vector<RelationalObjectPtr> objs; + for ( unsigned int i = 0; i < nObjs; ++i ) { + objs.push_back( dummyObject( i, i, ValidityKeyMax, channel ) ); + } + storeObjects( relfolder, objs ); + } + + try { + ValidityKey since = 50; + ValidityKey until = 70; + ChannelSelection channels( 2, 2 ); + string tag = ""; + + IObjectIteratorPtr cursor = + objMgr->browseObjects( relfolder, since, until, channels, tag ); + + CPPUNIT_ASSERT_MESSAGE( "no cursor", cursor != 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 21u, + (unsigned int)cursor->size() ); + + // test content + unsigned int nBObjs = 0; + //for ( IObjectIterator::const_iterator + // i = cursor->begin(); i != cursor->end(); ++ i ) { + // IObjectPtr obj = *i; + while ( cursor->goToNext() ) { + IObjectPtr obj( cursor->currentRef().clone() ); + + stringstream s; + s << "object " << nBObjs << " "; + + CPPUNIT_ASSERT_MESSAGE + ( ( s.str() + "payload" ).c_str(), + dummyPayload( (int)(since+nBObjs) ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + since + nBObjs, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + since + nBObjs + 1, obj->until() ); + + nBObjs++; + } + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "number of objects", 21u, nBObjs ); + + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + /// Checks that storing an until value of more that int63 (the current + /// limitation) throws a ValidityKeyOutOfBoundaries exception (SV storage) + void test_sv_UInt64Max_iov() { + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::SINGLE_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + RelationalObjectPtr object + ( new RelationalObject( 0, UInt64Max, dummyPayload( 0 ), 0 ) ); + vector<RelationalObjectPtr> objs( 1, object ); + CPPUNIT_ASSERT_THROW(storeObjects( relfolder, objs ), + ValidityKeyOutOfBoundaries); + } + + + + /// Checks that storing an until value of more that int63 (the current + /// limitation) throws a ValidityKeyOutOfBoundaries exception (MV storage) + void test_mv_UInt64Max_iov() { + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + RelationalObjectPtr object + ( new RelationalObject( 0, UInt64Max, dummyPayload( 0 ), 0 ) ); + vector<RelationalObjectPtr> objs( 1, object ); + CPPUNIT_ASSERT_THROW(storeObjects( relfolder, objs ), + ValidityKeyOutOfBoundaries); + } + + + + /// Tests storeObject for bulk r/w into multiple channels (SV mode) + void test_storeObjects_bulk_multichannel() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + ChannelId nChannels = 10; + { + vector<RelationalObjectPtr> objs; + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + objs.push_back( dummyObject( (int)ch, (ValidityKey)0, ValidityKeyMax, + ch ) ); + } + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + objs.push_back( dummyObject( (int)ch, (ValidityKey)5, ValidityKeyMax, + ch ) ); + } + storeObjects( relfolder, objs ); + } + { + vector<RelationalObjectPtr> objs; + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + objs.push_back( dummyObject( (int)ch, (ValidityKey)10, ValidityKeyMax, + ch ) ); + } + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + objs.push_back( dummyObject( (int)ch, (ValidityKey)15, ValidityKeyMax, + ch ) ); + } + storeObjects( relfolder, objs ); + } + + unsigned int nObjs = 4; + IObjectPtr obj; + for ( ChannelId ch = 0; ch < nChannels; ++ch ) { + for ( unsigned int i = 0; i < nObjs; ++i ) { + stringstream s; + s << "object " << i << ", channel " << ch << " "; + + ValidityKey pointInTime = 5 * i; // 0, 5, 10, 15 + obj = objMgr->findObject( relfolder, pointInTime, ch ); + + CPPUNIT_ASSERT_MESSAGE( ( s.str() + "payload" ).c_str(), + dummyPayload( (int)ch ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "since" ).c_str(), + pointInTime, obj->since() ); + + // until of object 3 extends to ValidityKeyMax + if ( i < nObjs-1 ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + pointInTime +5, obj->until() ); + } else { + CPPUNIT_ASSERT_EQUAL_MESSAGE( ( s.str() + "until" ).c_str(), + ValidityKeyMax, obj->until() ); + } + } + } + } + + + /// Tests SimpleObject::filter + void test_SimpleObject_filter() { + SOVector i; + + i = SimpleObject( 1, 0, 2, 3 ).filter( SimpleObject( 1, 0, 1, 2 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 size", 1u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)2, i[0].until ); + + i = SimpleObject( 1, 0, 1, 2 ).filter( SimpleObject( 1, 0, 2, 3 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 size", 1u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)3, i[0].until ); + + i = SimpleObject( 1, 0, 1, 3 ).filter( SimpleObject( 1, 0, 1, 2 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 size", 0u, (unsigned int)i.size() ); + + i = SimpleObject( 1, 0, 1, 3 ).filter( SimpleObject( 1, 0, 2, 3 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 size", 0u, (unsigned int)i.size() ); + + i = SimpleObject( 1, 0, 1, 2 ).filter( SimpleObject( 1, 0, 1, 2 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 size", 0u, (unsigned int)i.size() ); + + i = SimpleObject( 1, 0, 1, 4 ).filter( SimpleObject( 1, 0, 2, 3 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 size", 0u, (unsigned int)i.size() ); + + i = SimpleObject( 1, 0, 2, 3 ).filter( SimpleObject( 1, 0, 1, 4 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 size", 2u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 since", (ValidityKey)1, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 until", (ValidityKey)2, i[0].until ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 since", (ValidityKey)3, i[1].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 until", (ValidityKey)4, i[1].until ); + + i = SimpleObject( 1, 0, 2, 3 ).filter( SimpleObject( 1, 0, 1, 3 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 size", 1u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 since", (ValidityKey)1, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 until", (ValidityKey)2, i[0].until ); + + i = SimpleObject( 1, 0, 1, 2 ).filter( SimpleObject( 1, 0, 1, 3 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 size", 1u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 since", (ValidityKey)2, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 until", (ValidityKey)3, i[0].until ); + } + + + /// Tests SimpleObject::intersect + void test_SimpleObject_intersect() { + SOVector v( 1, SimpleObject( 1, 0, 2, 4 ) ); + SOVector i = SimpleObject( 2, 0, 2, 4 ).intersect( v ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 1u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "objectId", 1u, i[0].objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)2, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)4, i[0].until ); + } + + + /// Tests SimpleObject::visibleThrough + void test_SimpleObject_visisbleThrough() { + SOVector v( 1, SimpleObject( 1, 0, 2, 4 ) ); + SOVector i = SimpleObject( 2, 0, 2, 4 ).visibleThrough( v ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 0u, (unsigned int)i.size() ); + + v.clear(); + v.push_back( SimpleObject( 1, 0, 1, 2 ) ); + v.push_back( SimpleObject( 1, 0, 3, 4 ) ); + + i = SimpleObject( 2, 0, 1, 4 ).visibleThrough( v ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 1u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)2, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)3, i[0].until ); + + v.clear(); + v.push_back( SimpleObject( 1, 0, 2, 3 ) ); + + i = SimpleObject( 2, 0, 1, 4 ).visibleThrough( v ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 2u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)1, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)2, i[0].until ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)3, i[1].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)4, i[1].until ); + + v.clear(); + v.push_back( SimpleObject( 1, 0, 2, 4 ) ); + + i = SimpleObject( 2, 0, 2, 4 ).visibleThrough( v ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 0u, (unsigned int)i.size() ); + + v.clear(); + v.push_back( SimpleObject( 1, 0, 1, 3 ) ); + v.push_back( SimpleObject( 1, 0, 6, 8 ) ); + + i = SimpleObject( 2, 0, 2, 4 ).visibleThrough( v ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 1u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)3, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)4, i[0].until ); + } + + + /// Tests SimpleObject::visibleThrough + void test_SimpleObject_visisbleThrough2() { + SOVector v; + v.push_back( SimpleObject( 1, 0, 1, 3 ) ); + v.push_back( SimpleObject( 1, 0, 6, 8 ) ); + + SOVector i = SimpleObject( 2, 0, 2, 4 ).visibleThrough( v ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 1u, (unsigned int)i.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)3, i[0].since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)4, i[0].until ); + } + + + /// Tests processMultiVersionObjects + void test_processMultiVersionObjects_case_0a() { + RelationalDatabasePtr dbPtr; + + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 1, 2 ) ); + objects.push_back( dummyObject( 2, 1, 2 ) ); + + std::vector<RelationalObjectTableRow> rows; + + unsigned int idOffset = 1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> splitters + = objMgr->processMultiVersionObjects( objects, rows, + idOffset, idToIndex ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "splitters size", + 1u, (unsigned int)splitters.size() ); + SimpleObject s = splitters[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 object id", 1u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 since", (ValidityKey)1, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 until", (ValidityKey)2, s.until ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 2u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + } + + + /// Tests processMultiVersionObjects + void test_processMultiVersionObjects_case_0b() { + RelationalDatabasePtr dbPtr; + + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 2, 3 ) ); + objects.push_back( dummyObject( 2, 1, 4 ) ); + + std::vector<RelationalObjectTableRow> rows; + + unsigned int idOffset = 1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> splitters + = objMgr->processMultiVersionObjects( objects, rows, + idOffset, idToIndex ); + + /*cout << "splitters:\n"; + copy( splitters.begin(), splitters.end(), + std::ostream_iterator<SimpleObject>( cout, "\n" ) );*/ + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "splitters size", + 3u, (unsigned int)splitters.size() ); + + SimpleObject s = splitters[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 object id", 1u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 since", (ValidityKey)2, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 until", (ValidityKey)3, s.until ); + s = splitters[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 object id", 7u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 since", (ValidityKey)1, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 until", (ValidityKey)2, s.until ); + s = splitters[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 3 object id", 7u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 3 since", (ValidityKey)3, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 3 until", (ValidityKey)4, s.until ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 2u, + (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + } + + + /// Tests processMultiVersionObjects + void test_processMultiVersionObjects_case_1a() { + RelationalDatabasePtr dbPtr; + + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 1, 3 ) ); + objects.push_back( dummyObject( 2, 2, 4 ) ); + + std::vector<RelationalObjectTableRow> rows; + + unsigned int idOffset = 1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> splitters + = objMgr->processMultiVersionObjects( objects, rows, + idOffset, idToIndex ); + + //copy( splitters.begin(), splitters.end(), + // std::ostream_iterator<SimpleObject>( cout, "\n" ) ); + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "splitters size", + 2u, (unsigned int)splitters.size() ); + SimpleObject s = splitters[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 object id", 1u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 since", (ValidityKey)1, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 until", (ValidityKey)3, s.until ); + s = splitters[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 object id", 7u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 since", (ValidityKey)3, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 until", (ValidityKey)4, s.until ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 3u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + } + + + /// Tests processMultiVersionObjects + void test_processMultiVersionObjects_case_1b() { + RelationalDatabasePtr dbPtr; + + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 2, 4 ) ); + objects.push_back( dummyObject( 2, 1, 3 ) ); + + std::vector<RelationalObjectTableRow> rows; + + unsigned int idOffset = 1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> splitters + = objMgr->processMultiVersionObjects( objects, rows, + idOffset, idToIndex ); + + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "splitters size", + 2u, (unsigned int)splitters.size() ); + SimpleObject s = splitters[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 object id", 1u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 since", (ValidityKey)2, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 until", (ValidityKey)4, s.until ); + s = splitters[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 object id", 7u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 since", (ValidityKey)1, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 until", (ValidityKey)2, s.until ); + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 3u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 9u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + } + + + /// Tests processMultiVersionObjects + void test_processMultiVersionObjects_case_1c() { + RelationalDatabasePtr dbPtr; + + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 1, 4 ) ); + objects.push_back( dummyObject( 2, 2, 3 ) ); + + std::vector<RelationalObjectTableRow> rows; + + unsigned int idOffset = 1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> splitters + = objMgr->processMultiVersionObjects( objects, rows, + idOffset, idToIndex ); + + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "splitters size", + 1u, (unsigned int)splitters.size() ); + SimpleObject s = splitters[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 object id", 1u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 since", (ValidityKey)1, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 until", (ValidityKey)4, s.until ); + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 4u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 9u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 0u, row.newHeadId() ); + } + + + /// Tests processMultiVersionObjects + void test_processMultiVersionObjects_case_2() { + RelationalDatabasePtr dbPtr; + + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 1, 5 ) ); + objects.push_back( dummyObject( 2, 3, 6 ) ); + objects.push_back( dummyObject( 3, 2, 4 ) ); + + std::vector<RelationalObjectTableRow> rows; + + unsigned int idOffset = 1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> splitters + = objMgr->processMultiVersionObjects( objects, rows, + idOffset, idToIndex ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "splitters size", + 2u, (unsigned int)splitters.size() ); + SimpleObject s = splitters[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 object id", 1u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 since", (ValidityKey)1, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 until", (ValidityKey)5, s.until ); + s = splitters[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 object id", 7u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 since", (ValidityKey)5, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 until", (ValidityKey)6, s.until ); + + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 6u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 13u, row.newHeadId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 13u, row.newHeadId() ); + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 0u, row.newHeadId() ); + + row = rows[4]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 8u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 0u, row.newHeadId() ); + + row = rows[5]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 15u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)4, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + } + + + /// Tests processMultiVersionObjects + void test_processMultiVersionObjects_case_3() { + RelationalDatabasePtr dbPtr; + + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 1, 8 ) ); + objects.push_back( dummyObject( 2, 2, 5 ) ); + objects.push_back( dummyObject( 3, 3, 6 ) ); + objects.push_back( dummyObject( 4, 4, 7 ) ); + + std::vector<RelationalObjectTableRow> rows; + + unsigned int idOffset = 1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> splitters + = objMgr->processMultiVersionObjects( objects, rows, + idOffset, idToIndex ); + + /*cout << "splitters:\n"; + copy( splitters.begin(), splitters.end(), + std::ostream_iterator<SimpleObject>( cout, "\n" ) ); + cout << "rows:\n"; + copy( rows.begin(), rows.end(), + std::ostream_iterator<RelationalObjectTableRow>( cout, "\n" ) );*/ + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "splitters size", + 1u, (unsigned int)splitters.size() ); + SimpleObject s = splitters[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 object id", 1u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 since", (ValidityKey)1, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 until", (ValidityKey)8, s.until ); + + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 10u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 13u, row.newHeadId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 9u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 13u, row.newHeadId() ); + + row = rows[4]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 19u, row.newHeadId() ); + + row = rows[5]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + + row = rows[6]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 object id", 15u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 original id", 9u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 new head id", 19u, row.newHeadId() ); + + row = rows[7]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 since", (ValidityKey)4, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 new head id", 0u, row.newHeadId() ); + + row = rows[8]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 object id", 20u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 original id", 13u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 new head id", 0u, row.newHeadId() ); + + row = rows[9]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 object id", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 since", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 original id", 15u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 new head id", 0u, row.newHeadId() ); + } + + + /// Tests processMultiVersionObjects + void test_processMultiVersionObjects_case_4() { + RelationalDatabasePtr dbPtr; + + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 1, 4 ) ); + objects.push_back( dummyObject( 2, 3, 7 ) ); + objects.push_back( dummyObject( 3, 6, 8 ) ); + objects.push_back( dummyObject( 4, 2, 5 ) ); + + std::vector<RelationalObjectTableRow> rows; + + unsigned int idOffset = 1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> splitters + = objMgr->processMultiVersionObjects( objects, rows, + idOffset, idToIndex ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "splitters size", + 3u, (unsigned int)splitters.size() ); + SimpleObject s = splitters[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 object id", 1u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 since", (ValidityKey)1, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 until", (ValidityKey)4, s.until ); + s = splitters[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 object id", 7u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 since", (ValidityKey)4, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 until", (ValidityKey)7, s.until ); + s = splitters[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 3 object id", 13u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 3 since", (ValidityKey)7, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 3 until", (ValidityKey)8, s.until ); + + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 8u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 13u, row.newHeadId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 19u, row.newHeadId() ); + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 0u, row.newHeadId() ); + + row = rows[4]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 19u, row.newHeadId() ); + + row = rows[5]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + + row = rows[6]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 object id", 20u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 original id", 8u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 new head id", 0u, row.newHeadId() ); + + row = rows[7]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 object id", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 original id", 14u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 new head id", 0u, row.newHeadId() ); + } + + + /// Tests processMultiVersionObjects + void test_processMultiVersionObjects_case_5b() { + RelationalDatabasePtr dbPtr; + + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 1, 3 ) ); + objects.push_back( dummyObject( 2, 6, 8 ) ); + objects.push_back( dummyObject( 3, 2, 4 ) ); + objects.push_back( dummyObject( 4, 5, 7 ) ); + + std::vector<RelationalObjectTableRow> rows; + + unsigned int idOffset = 1; + std::map<unsigned int, unsigned int> idToIndex; + + std::vector<SimpleObject> splitters + = objMgr->processMultiVersionObjects( objects, rows, + idOffset, idToIndex ); + + /*cout << "splitters:\n"; + copy( splitters.begin(), splitters.end(), + std::ostream_iterator<SimpleObject>( cout, "\n" ) ); + cout << "rows:\n"; + copy( rows.begin(), rows.end(), + std::ostream_iterator<RelationalObjectTableRow>( cout, "\n" ) );*/ + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "splitters size", + 4u, (unsigned int)splitters.size() ); + + SimpleObject s = splitters[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 object id", 1u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 since", (ValidityKey)1, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 1 until", (ValidityKey)3, s.until ); + s = splitters[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 object id", 7u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 since", (ValidityKey)6, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 until", (ValidityKey)8, s.until ); + s = splitters[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 3 object id", 13u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 3 since", (ValidityKey)3, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 3 until", (ValidityKey)4, s.until ); + s = splitters[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 object id", 19u, s.objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 since", (ValidityKey)5, s.since ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "int 2 until", (ValidityKey)6, s.until ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 6u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 13u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 19u, row.newHeadId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 0u, row.newHeadId() ); + + row = rows[4]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 0u, row.newHeadId() ); + + row = rows[5]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + + } + + + /// Tests updateObjectTableNewHeadId + void test_updateObjectTableNewHeadId_1() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3 ) ); + storeObjects( relfolder, objs ); + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 1", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 1", 0u, row.newHeadId() ); + transaction.commit(); + } + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + + // now update the new head id + updateObjectTableNewHeadId( objMgr.get(), + relfolder->objectTableName(), + relfolder->channelTableName(), + (ValidityKey)2, + (ValidityKey)4, + (ChannelId)0, + 5u ); + transaction.commit(); + } + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 2", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 2", 5u, row.newHeadId() ); + transaction.commit(); + } + } + + + /// Tests updateObjectTableNewHeadId + void test_updateObjectTableNewHeadId_2() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 0, 2 ) ); + objs.push_back( dummyObject( 2, 2, 4 ) ); + storeObjects( relfolder, objs ); + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + bool fetchPayload = true; + + RelationalObjectTableRow + row1( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 1", 1u, row1.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 1", 0u, row1.newHeadId() ); + + RelationalObjectTableRow + row2( objectTable.fetchRowForId( 2u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 2", 2u, row2.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 2", 0u,row2.newHeadId() ); + transaction.commit(); + } + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + + // now update the new head id + updateObjectTableNewHeadId( objMgr.get(), + relfolder->objectTableName(), + relfolder->channelTableName(), + (ValidityKey)1, + (ValidityKey)2, + (ChannelId)0, + 5u ); + transaction.commit(); + } + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + bool fetchPayload = true; + + RelationalObjectTableRow + row1( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 3", 1u, row1.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 3", 5u, row1.newHeadId() ); + + RelationalObjectTableRow + row2( objectTable.fetchRowForId( 2u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 4", 2u, row2.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 4", 0u, row2.newHeadId() ); + transaction.commit(); + } + } + + + /// Tests updateObjectTableNewHeadId + void test_updateObjectTableNewHeadId_3() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 2, 4 ) ); + storeObjects( relfolder, objs ); + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 1", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 1", 0u, row.newHeadId() ); + transaction.commit(); + } + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + + // now update the new head id + updateObjectTableNewHeadId( objMgr.get(), + relfolder->objectTableName(), + relfolder->channelTableName(), + (ValidityKey)1, + (ValidityKey)3, + (ChannelId)0, + 5u ); + transaction.commit(); + } + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 2", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 2", 5u, row.newHeadId() ); + transaction.commit(); + } + } + + + /// Tests mergeWithHead + void test_mergeWithHead_case_3() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + // Prepare a persistent HEAD + { vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 1, 8 ) ); + storeObjects( relfolder, objects ); + } + + // Run the prerequisite logic of storeMultiVersionObjects + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 2, 2, 5 ) ); + objects.push_back( dummyObject( 3, 3, 6 ) ); + objects.push_back( dummyObject( 4, 4, 7 ) ); + + std::vector<RelationalObjectTableRow> rows; + + RelationalTransaction transaction( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + unsigned int objectIdOffset = seq->currVal() +1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> intersectors + = objMgr->processMultiVersionObjects( objects, rows, + objectIdOffset, idToIndex ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count 1", + 5u, (unsigned int)rows.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "intersector count", + 3u, (unsigned int)intersectors.size() ); + + objMgr->mergeWithHead( relfolder, intersectors, + rows, idToIndex ); + sort( rows.begin(), rows.end(), lt_objectId() ); + + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count 2", + 9u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 13u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 9u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 13u, row.newHeadId() ); + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 19u, row.newHeadId() ); + + row = rows[4]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + + row = rows[5]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 object id", 15u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 original id", 9u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 new head id", 19u, row.newHeadId() ); + + row = rows[6]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 since", (ValidityKey)4, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 new head id", 0u, row.newHeadId() ); + + row = rows[7]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 object id", 20u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 original id", 13u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 new head id", 0u, row.newHeadId() ); + + row = rows[8]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 object id", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 since", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 original id", 15u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 new head id", 0u, row.newHeadId() ); + } + + + /// Tests mergeWithHead + void test_mergeWithHead_case_1b() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + // Prepare a persistent HEAD + { vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 2, 4 ) ); + storeObjects( relfolder, objects ); + } + + // Run the prerequisite logic of storeMultiVersionObjects + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 2, 1, 3 ) ); + + std::vector<RelationalObjectTableRow> rows; + + RelationalTransaction transaction( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + unsigned int objectIdOffset = seq->currVal() +1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> intersectors + = objMgr->processMultiVersionObjects( objects, rows, + objectIdOffset, idToIndex ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count 1", 1u, + (unsigned int)rows.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "intersector count", + 1u, (unsigned int)intersectors.size() ); + + objMgr->mergeWithHead( relfolder, intersectors, + rows, idToIndex ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count 2", 2u, + (unsigned int)rows.size() ); + + // check the persistent head + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + // and the transient rows + row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 9u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + } + + + /// Tests mergeWithHead + void test_mergeWithHead_case_1a() { + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + // Prepare a persistent HEAD + { vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 1, 1, 3 ) ); + storeObjects( relfolder, objects ); + } + + // Run the prerequisite logic of storeMultiVersionObjects + vector<RelationalObjectPtr> objects; + objects.push_back( dummyObject( 2, 2, 4 ) ); + + std::vector<RelationalObjectTableRow> rows; + + RelationalTransaction transaction( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + unsigned int objectIdOffset = seq->currVal() +1; + std::map<unsigned int, unsigned int> idToIndex; + std::vector<SimpleObject> intersectors + = objMgr->processMultiVersionObjects( objects, rows, + objectIdOffset, idToIndex ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count 1", + 1u, (unsigned int)rows.size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "intersector count", + 1u, (unsigned int)intersectors.size() ); + + objMgr->mergeWithHead( relfolder, intersectors, + rows, idToIndex ); + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count 2", + 2u, (unsigned int)rows.size() ); + + // check the persistent head + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + // and the transient rows + row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + /// Tests the writing of all object attributes in the MV mode + void test_storeObjects_MV_newInsert() { + try { + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 2, 2, 10 ) ); + storeObjects( relfolder, objs ); + + unsigned int object_id = 1; + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( object_id, fetchPayload ) ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)10, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "instime", string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "field I", 2, + row["I"].data<int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "field S", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "field X", 0.002f, + row["X"].data<float>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head id", 0u, row.newHeadId() ); + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + /// Tests storeObjects in MV mode when inserting over an object with + /// identical IOVs + /// Followup on bug report by Marco Clemencic 2005-03-17 + void test_storeObjects_MV_identicalIov_case_2() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 0, 2 ) ); + objs.push_back( dummyObject( 2, 2, 4 ) ); + storeObjects( relfolder, objs ); + } + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 0, 2 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = + ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 3u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 13u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 13u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + } + + + /// Tests storeObjects in MV mode when inserting over an object with + /// identical IOVs + /// Followup on bug report by Marco Clemencic 2005-03-17 + void test_storeObjects_MV_identicalIov_case_1() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 0, 2 ) ); + objs.push_back( dummyObject( 2, 2, 4 ) ); + storeObjects( relfolder, objs ); + } + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 2, 4 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = + ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 3u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 13u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 13u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + } + + + /// Tests storeObjects in MV mode for different channels + /// This stores the same objects as the single channel test case_5b + /// into channel 1 and those from case_6 into channel 0 + void test_storeObjects_MV_case_5b_6_channels() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { // begin case_5b storage in channel 1 + ChannelId ch = 1; + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3, ch ) ); + objs.push_back( dummyObject( 2, 6, 8, ch ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 2, 4, ch ) ); + objs.push_back( dummyObject( 4, 5, 7, ch ) ); + storeObjects( relfolder, objs ); + } + } // end + + { // begin case_6 storage in channel 2 + ChannelId ch = 2; + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 7, 9, ch ) ); + objs.push_back( dummyObject( 2, 6, 7, ch ) ); + objs.push_back( dummyObject( 3, 1, 5, ch ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 4, 2, 3, ch ) ); + objs.push_back( dummyObject( 5, 4, 8, ch ) ); + storeObjects( relfolder, objs ); + } + } // end + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = + ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 15u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + // read back objects in channel 1 + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 channel id", 1u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 13u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 1u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 19u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 13u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 channel id", 1u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 14u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 channel id", 1u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 19u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 channel id", 1u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 21u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 channel id", 1u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + + // read back objects in channel 2 + row = objectTable.fetchRowForId( 25u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 object id", 25u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 since", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 until", (ValidityKey)9, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 new head id", 49u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 31u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 object id", 31u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 new head id", 49u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 37u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 object id", 37u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 new head id", 43u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 43u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 object id", 43u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 44u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "11 object id", 44u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "11 channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "11 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "11 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "11 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "11 original id", 37u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "11 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 45u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "12 object id", 45u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "12 channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "12 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "12 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "12 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "12 original id", 37u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "12 new head id", 49u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 49u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "13 object id", 49u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "13 channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "13 since", (ValidityKey)4, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "13 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "13 payload", string("Object 5"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "13 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "13 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 50u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "14 object id", 50u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "14 channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "14 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "14 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "14 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "14 original id", 45u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "14 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 51u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "15 object id", 51u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "15 channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "15 since", (ValidityKey)8, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "15 until", (ValidityKey)9, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "15 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "15 original id", 25u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "15 new head id", 0u, row.newHeadId() ); + + } + + /// Tests storeObjects in MV mode in different channels + void test_storeObjects_MV_case_0a_channels() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + ChannelId ch = 0; + objs.push_back( dummyObject( 1, 2, 4, ch ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + ChannelId ch = 1; + objs.push_back( dummyObject( 2, 2, 4, ch ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 2u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 1u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + } + + + + /// Tests storeObjects in MV mode + void test_storeObjects_MV_case_6() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 7, 9 ) ); + objs.push_back( dummyObject( 2, 6, 7 ) ); + objs.push_back( dummyObject( 3, 1, 5 ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 4, 2, 3 ) ); + objs.push_back( dummyObject( 5, 4, 8 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 9u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)9, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 25u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 25u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 13u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 19u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 19u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 20u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 20u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 13u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 21u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 13u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 25u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 25u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 object id", 25u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 since", (ValidityKey)4, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 payload", string("Object 5"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 26u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 object id", 26u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 original id", 21u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 27u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 object id", 27u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 since", (ValidityKey)8, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 until", (ValidityKey)9, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 new head id", 0u, row.newHeadId() ); + } + + + /// Tests storeObjects in MV mode + void test_storeObjects_MV_case_5b() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3 ) ); + objs.push_back( dummyObject( 2, 6, 8 ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 2, 4 ) ); + objs.push_back( dummyObject( 4, 5, 7 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 6u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 13u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 19u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 13u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 14u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 19u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 21u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + } + + + /// Tests storeObjects in MV mode + void test_storeObjects_MV_case_4() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 4 ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 2, 3, 7 ) ); + objs.push_back( dummyObject( 3, 6, 8 ) ); + objs.push_back( dummyObject( 4, 2, 5 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 8u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 13u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 8u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 19u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 13u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 14u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 19u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 19u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 20u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 object id", 20u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 original id", 8u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 21u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 object id", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 original id", 14u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 new head id", 0u, row.newHeadId() ); + } + + + /// Tests storeObjects in MV mode + void test_storeObjects_MV_case_3() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 8 ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 2, 2, 5 ) ); + objs.push_back( dummyObject( 3, 3, 6 ) ); + objs.push_back( dummyObject( 4, 4, 7 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 10u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 13u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 8u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 9u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 9u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 13u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 13u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 19u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 14u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 15u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 object id", 15u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 original id", 9u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "7 new head id", 19u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 19u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 since", (ValidityKey)4, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 until", (ValidityKey)7, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 payload", string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "8 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 20u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 object id", 20u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 original id", 13u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "9 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 21u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 object id", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 since", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 original id", 15u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "10 new head id", 0u, row.newHeadId() ); + transaction.commit(); + } + + + /// Tests storeObjects in MV mode + void test_storeObjects_MV_case_2() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 5 ) ); + objs.push_back( dummyObject( 2, 3, 6 ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 2, 4 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 6u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 13u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 8u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 13u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 13u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 payload", string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 14u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 original id", 8u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "5 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 15u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 object id", 15u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 since", (ValidityKey)4, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 until", (ValidityKey)6, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 original id", 7u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "6 new head id", 0u, row.newHeadId() ); + } + + + /// Tests storeObjects in MV mode + void test_storeObjects_MV_case_1a() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> + objs( 1, dummyObject( 1, 1, 3 ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> + objs( 1, dummyObject( 2, 2, 4 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 3u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 8u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 new head id", 0u, row.newHeadId() ); + } + + + /// Tests storeObjects in MV mode + void test_storeObjects_MV_case_0b() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 2, 3 ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 2, 1, 4 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& objectTable = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 2u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + } + + + /// Tests storeObjects in MV mode + void test_storeObjects_MV_case_0a() { + try{ + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + { + vector<RelationalObjectPtr> + objs( 1, dummyObject( 1, 2, 4 ) ); + storeObjects( relfolder, objs ); + } + { + vector<RelationalObjectPtr> + objs( 1, dummyObject( 2, 2, 4 ) ); + storeObjects( relfolder, objs ); + } + RelationalTransaction transaction( ralDb->transactionMgr() ); + { + coral::ITable& objectTable = + ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", + 2u, rowCount( objectTable ) ); + } + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 7u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + } + + + /// Tests a combination of insertTagTableRow and fetchTagTableRow + void test_insertTagTableRow_fetchTagTableRow() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + unsigned int tagId = + ralDb->tagMgr().createTag( relfolder->id(), "mytagA", "desc A" ).id(); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag A id", 1u, tagId ); + + tagId = + ralDb->tagMgr().createTag( relfolder->id(), "mytagB", "desc B" ).id(); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag B id", 2u, tagId ); + + RelationalTableRow row = + ralDb->tagMgr().fetchGlobalTagTableRows( "mytagB" )[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "id", 2u, row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "name", string("mytagB"), row["TAG_NAME"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "description", string("desc B"), + row["TAG_DESCRIPTION"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "instime", string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + row["SYS_INSTIME"].data<std::string>().size() ); + + transaction.commit(); + } + + + /// Tests insertTagTableRow if a tag already exists + void test_insertTagTableRow_exists() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + ralDb->tagMgr().createTag( relfolder->id(), "mytagA", "desc A" ); + CPPUNIT_ASSERT_THROW( ralDb->tagMgr().createTag( relfolder->id(), + "mytagA", "desc A" ), + TagExists ); + transaction.commit(); + } + + + /// Tests insertTagTableRow to confirm that trying to insert "HEAD" + /// throws an exception + void test_insertTagTableRow_HEAD() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + try { + ralDb->tagMgr().createTag( relfolder->id(), "HEAD", "" ); + CPPUNIT_FAIL( "inserting HEAD tag did not throw" ); + } catch ( TagExists& /* ignored */ ) { } + + try { + ralDb->tagMgr().createTag( relfolder->id(), "head", "" ); + CPPUNIT_FAIL( "inserting head tag did not throw" ); + } catch ( TagExists& /* ignored */ ) { } + + try { + ralDb->tagMgr().createTag( relfolder->id(), "Head", "" ); + CPPUNIT_FAIL( "inserting Head tag did not throw" ); + } catch ( TagExists& /* ignored */ ) { } + + transaction.commit(); + } + + + /// Tests fetchTagTableRow for a nonexisting tag + void test_fetchTagTableRow_notFound() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + ralDb->tagMgr().createTag( relfolder->id(), "mytagA", "desc A" ); + CPPUNIT_ASSERT_THROW( ralDb->tagMgr().fetchGlobalTagTableRows( "mytagB" )[0], + TagNotFound ); + transaction.commit(); + } + + + /// Tests the global version of existsTag + void test_existsTag_global() { + IFolderPtr folder = ralDb->createFolder( "/myfolder1", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "mytagA", "" ); + + CPPUNIT_ASSERT_MESSAGE( "positive", ralDb->existsTag( "mytagA" ) ); + CPPUNIT_ASSERT_MESSAGE( "negative", ! ralDb->existsTag( "mytagB" ) ); + + folder = ralDb->createFolder( "/myfolder2", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "mytagC", "" ); + + CPPUNIT_ASSERT_MESSAGE( "positive", ralDb->existsTag( "mytagC" ) ); + } + + + /// Tests a combination of insertObject2TagTableRows and + /// fetchObject2TagTableRow + void test_insertObject2TagTableRows_fetchObject2TagTableRow() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3 ) ); + objs.push_back( dummyObject( 2, 6, 8 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + Time now = stringToTime( seq->currDate() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + vector<RelationalObjectTableRow> rows = + objectTable.fetchRowsForTaggingHeadAsOfDate( now ); + + unsigned int tagId = + ralDb->tagMgr().createTag( relfolder->id(), "mytagA", "desc A" ).id(); + + string insertionTime = seq->currDate(); + relfolder->insertObject2TagTableRows( relfolder->object2TagTableName(), + tagId, + insertionTime, + rows ); + + coral::ITable& table = + ralDb->session().nominalSchema().tableHandle + ( relfolder->object2TagTableName() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 2u, rowCount( table ) ); + + unsigned int objectId = 1; + RelationalTableRow row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 tag id", 1u, row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 obj id", 1u, row["OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 channel", (ChannelId)0, row["CHANNEL_ID"].data<ChannelId>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)1, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)3, row["IOV_UNTIL"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "instime", insertionTime, row["SYS_INSTIME"].data<std::string>() ); + + objectId = 7; + row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 tag id", 1u, row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 obj id", 7u, row["OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 channel", (ChannelId)0, row["CHANNEL_ID"].data<ChannelId>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 since", (ValidityKey)6, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 until", (ValidityKey)8, row["IOV_UNTIL"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "instime", insertionTime, row["SYS_INSTIME"].data<std::string>() ); + + transaction.commit(); + } + + + /// Tests tagging the HEAD as of a given date + void test_tag_asOfDate_5c() { + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3 ) ); + objs.push_back( dummyObject( 2, 6, 8 ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction t1( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + Time asOfDate = stringToTime( seq->currDate() ); + asOfDate = addOneNsToTime( asOfDate ); + t1.commit(); + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + sleep(1); + //cout << "### Before 2nd insert: " << timeToString(asOfDate) << endl; + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 2, 4 ) ); + objs.push_back( dummyObject( 4, 3, 5 ) ); + storeObjects( relfolder, objs ); + } + + relfolder->tagHeadAsOfDate( asOfDate, "mytagA", "a tag A" ); + relfolder->tagHeadAsOfDate( asOfDate, "mytagB", "a tag B" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + { + coral::ITable& table = + ralDb->session().nominalSchema().tableHandle + ( relfolder->tagTableName() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag table row count", + 2u, rowCount( table ) ); + + // check tag table content (more detailed test in the insert/fetch test) + RelationalTableRow row = + ralDb->tagMgr().fetchGlobalTagTableRows( "mytagB" )[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "id", 2u, row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "name", string("mytagB"), row["TAG_NAME"].data<std::string>() ); + } + + { + coral::ITable& table = + ralDb->session().nominalSchema().tableHandle + ( relfolder->object2TagTableName() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj2tag table row count", + 4u, rowCount( table ) ); + + // check tag2iov table content + unsigned int tagId = 2; + RelationalTableRow row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, 1u ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)1, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)3, row["IOV_UNTIL"].data<ValidityKey>() ); + + row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, 7u ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)6, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)8, row["IOV_UNTIL"].data<ValidityKey>() ); + } + } catch ( std::exception& e ) { + cout << endl << e.what() << endl; + throw; + } + } + + + + /// Tests tagging the HEAD + void test_tag_HEAD_5c() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3 ) ); + objs.push_back( dummyObject( 2, 6, 8 ) ); + storeObjects( relfolder, objs ); + } + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 2, 4 ) ); + objs.push_back( dummyObject( 4, 3, 5 ) ); + storeObjects( relfolder, objs ); + } + + folder->tagCurrentHead( "mytagA", "a tag A" ); + folder->tagCurrentHead( "mytagB", "a tag B" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& table = + ralDb->session().nominalSchema().tableHandle( relfolder->tagTableName() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag table row count", + 2u, rowCount( table ) ); + + // check tag table content (more detailed test in the insert/fetch test) + RelationalTableRow row = + ralDb->tagMgr().fetchGlobalTagTableRows( "mytagB" )[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "id", 2u, row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "name", string("mytagB"), row["TAG_NAME"].data<std::string>() ); + } + + { + coral::ITable& table = + ralDb->session().nominalSchema().tableHandle + ( relfolder->object2TagTableName() ); + + // 4 rows from each tag + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj2tag table row count", + 8u, rowCount( table ) ); + + // check tag2iov table content + unsigned int tagId = 2; + RelationalTableRow row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, 14u ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)1, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)2, row["IOV_UNTIL"].data<ValidityKey>() ); + + row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, 20u ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)2, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)3, row["IOV_UNTIL"].data<ValidityKey>() ); + + row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, 19u ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)3, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)5, row["IOV_UNTIL"].data<ValidityKey>() ); + + row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, 7u ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)6, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)8, row["IOV_UNTIL"].data<ValidityKey>() ); + } + } + + + /// Tests tagging with an existing tag throws an exception + void test_tag_exists() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3 ) ); + objs.push_back( dummyObject( 2, 6, 8 ) ); + storeObjects( relfolder, objs ); + + folder->tagCurrentHead( "mytagA", "a tag A" ); + CPPUNIT_ASSERT_THROW( folder->tagCurrentHead( "mytagA", "a tag A" ), + TagExists ); + } + + + /// Tests findObject for a tag + void test_findObject_tag_5c() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3 ) ); + objs.push_back( dummyObject( 2, 6, 8 ) ); + storeObjects( relfolder, objs ); + } + + folder->tagCurrentHead( "mytagA", "a tag A" ); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 2, 4 ) ); + objs.push_back( dummyObject( 4, 3, 5 ) ); + storeObjects( relfolder, objs ); + } + + IObjectPtr obj + = objMgr->findObject( relfolder, + (ValidityKey)2, + (ChannelId)0, + "mytagA" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 1u, obj->objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel id", 0u, obj->channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)1, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)3, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 1"), + obj->payload()["S"].data<std::string>() ); + } + + + + /// Tests findObject for the HEAD + void test_findObject_HEAD_5c() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3 ) ); + objs.push_back( dummyObject( 2, 6, 8 ) ); + storeObjects( relfolder, objs ); + } + + folder->tagCurrentHead( "mytagA", "a tag A" ); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 2, 4 ) ); + objs.push_back( dummyObject( 4, 3, 5 ) ); + storeObjects( relfolder, objs ); + } + + IObjectPtr obj + = objMgr->findObject( relfolder, + (ValidityKey)2, + (ChannelId)0, + "HEAD" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 20u, obj->objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel id", 0u, obj->channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)3, obj->until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 3"), + obj->payload()["S"].data<std::string>() ); + } + + + /// Tests a combination of insertGlobalTagTableRow and fetchGlobalTagTableRow + void test_insertGlobalTagTableRow_fetchGlobalTagTableRow() + { + ralDb->createFolderSet( "/fs1" ); // Make sure node 1 exists + ralDb->createFolderSet( "/fs1/fs2" ); // Needed to create node 3 + ralDb->createFolderSet( "/fs1/fs2/fs3" ); // Make sure node 3 exists + RelationalTransaction transaction( ralDb->transactionMgr() ); + Time now; + ralDb->tagMgr().insertGlobalTagTableRow + ( 1, 1, "mytagA", HvsTagLock::UNLOCKED, "desc A", timeToString( now ) ); + ralDb->tagMgr().insertGlobalTagTableRow + ( 3, 2, "mytagB", HvsTagLock::UNLOCKED, "desc B", timeToString( now ) ); + RelationalTableRow row = + ralDb->tagMgr().fetchGlobalTagTableRows( "mytagB" )[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "folder id", 3u, + row["NODE_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag id", 2u, + row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "name", string("mytagB"), + row["TAG_NAME"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "description", string("desc B"), + row["TAG_DESCRIPTION"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "instime", string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + row["SYS_INSTIME"].data<std::string>().size() ); + transaction.commit(); + } + + + /// Tests global uniqueness of tags -- tagging in a folder with a tag + /// that exists in another foder throws an exception + void test_tag_differentFolders_sameTag() { + IFolderPtr folder1 = ralDb->createFolder( "/myfolderA", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* f1 = dynamic_cast<RelationalFolder*>(folder1.get()); + + IFolderPtr folder2 = ralDb->createFolder( "/myfolderB", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* f2 = dynamic_cast<RelationalFolder*>(folder2.get()); + + f1->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + f2->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + f1->tagCurrentHead( "tag A", "desc" ); + CPPUNIT_ASSERT_THROW( f2->tagCurrentHead( "tag A", "desc" ), TagExists ); + } + + + /// Tests tagging the HEAD as of a given object_id (for a user object) + void test_tag_asOfObjectId_userObject_5c() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 1, 3 ) ); + objs.push_back( dummyObject( 2, 6, 8 ) ); + storeObjects( relfolder, objs ); + } + + { vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 3, 2, 4 ) ); + objs.push_back( dummyObject( 4, 3, 5 ) ); + storeObjects( relfolder, objs ); + } + + // Ultimately this could be set from a storeObjects return value: + // objectId = storeObjects( relfolder, objs ); + unsigned int objectId = 7; + // WARNING! The tag asOfDate and asOfObjectId used to take compatible + // arguments (implicit conversion from unsigned int to Time) + relfolder->tagHeadAsOfObjectId + ( objectId, "mytagA", "tag from user object" ); + relfolder->tagHeadAsOfObjectId + ( objectId+1, "mytagB", "tag from left sys object" ); + relfolder->tagHeadAsOfObjectId + ( objectId+2, "mytagC", "tag from right sys object" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + coral::ITable& table = + ralDb->session().nominalSchema().tableHandle( relfolder->tagTableName() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag table row count", + 3u, rowCount( table ) ); + + // check tag table content (more detailed test in the insert/fetch test) + RelationalTableRow row = + ralDb->tagMgr().fetchGlobalTagTableRows( "mytagB" )[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "id", 2u, row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "name", string("mytagB"), row["TAG_NAME"].data<std::string>() ); + } + + { + coral::ITable& table = + ralDb->session().nominalSchema().tableHandle + ( relfolder->object2TagTableName() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj2tag table row count", + 6u, rowCount( table ) ); + + // check tag2iov table content + unsigned int tagId = 2; + RelationalTableRow row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, 1u ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)1, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)3, row["IOV_UNTIL"].data<ValidityKey>() ); + + row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, 7u ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)6, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)8, row["IOV_UNTIL"].data<ValidityKey>() ); + } + } + + + /// Tests that deleteTag throws a TagNotFound exception when deleting + /// a nonexisting tag. + void test_deleteTag_nonexisting() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "tagA" ); + CPPUNIT_ASSERT_THROW( folder->deleteTag( "nonexisting tag" ), + TagNotFound ); + } + + + /// Tests deleteTag + void test_deleteTag() { + try { + IFolderPtr folder = + m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->tagCurrentHead( "tagA" ); + folder->tagCurrentHead( "tagB" ); + + folder->deleteTag( "tagA" ); + + CPPUNIT_ASSERT_MESSAGE( "tagA deleted", ! m_db->existsTag( "tagA" ) ); + + folder->storeObject( 2, 6, dummyPayload( 1 ), 0 ); + folder->tagCurrentHead( "tagA" ); + + // fetch tagA + //std::cout << "fetch objects in tagA" << std::endl; + IObjectIteratorPtr objs = folder->browseObjects( ValidityKeyMin, + ValidityKeyMax, + (ChannelId)0, + "tagA" ); + + //std::cout << "tagA object count is " << objs->size() << std::endl; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA object count", 2u, + (unsigned int)objs->size() ); + + IObjectPtr obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagA obj 1 payload", + dummyPayload( 0 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 1 since", + (ValidityKey)0, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 1 until", + (ValidityKey)2, obj->until() ); + + obj = getNext(objs); + CPPUNIT_ASSERT_MESSAGE( "tagA obj 2 payload", + dummyPayload( 1 ) == obj->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 2 since", + (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tagA obj 2 until", + (ValidityKey)6, obj->until() ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests deleteGlobalTagTableRow + void test_deleteGlobalTagTableRow() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->storeObject( 2, 6, dummyPayload( 1 ), 0 ); + folder->storeObject( 4, 8, dummyPayload( 2 ), 0 ); + folder->tagCurrentHead( "tagA" ); + + folder->storeObject( 0, 5, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 7, dummyPayload( 4 ), 0 ); + folder->storeObject( 5, 9, dummyPayload( 5 ), 0 ); + folder->tagCurrentHead( "tagB" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + coral::ITable& table = ralDb->session().nominalSchema().tableHandle + ( ralDb->globalTagTableName() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count before delete", + 2u, rowCount( table ) ); + + // Delete the first tagA (we know it has id = 1 in a new db) + // We need to delete from the object2tag table first or we violate + // the integrity constraint. + unsigned int tagId = 1; + ralDb->tagMgr().deleteGlobalTagTableRow( folder->id(), tagId ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count after delete", + 1u, rowCount( table ) ); + + // Check the values of the remaining row + RelationalTableRow row = + ralDb->tagMgr().fetchGlobalTagTableRows( "tagB" )[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag id", 2u, + row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "tag name", string("tagB"), + row["TAG_NAME"].data<std::string>() ); + transaction.commit(); + } + + + /// Tests deleteTagTableRow + void test_deleteTagTableRow() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->storeObject( 2, 6, dummyPayload( 1 ), 0 ); + folder->storeObject( 4, 8, dummyPayload( 2 ), 0 ); + folder->tagCurrentHead( "tagA" ); + + folder->storeObject( 0, 5, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 7, dummyPayload( 4 ), 0 ); + folder->storeObject( 5, 9, dummyPayload( 5 ), 0 ); + folder->tagCurrentHead( "tagB" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + coral::ITable& table = ralDb->session().nominalSchema().tableHandle + ( ralDb->globalTagTableName() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count before delete", + 2u, rowCount( table ) ); + + // Delete the first tagA (we know it has id = 1 in a new db) + // We need to delete from the object2tag table first or we violate + // the integrity constraint. + unsigned int tagId = 1; + relfolder->deleteObject2TagTableRows + ( relfolder->object2TagTableName(), tagId ); + ralDb->tagMgr().deleteGlobalTagTableRow( folder->id(), tagId ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count after delete", + 1u, rowCount( table ) ); + + // Check the values of the remaining row + RelationalTableRow row + = ralDb->tagMgr().fetchGlobalTagTableRows( "tagB" )[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 tag id", 2u, + row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 obj id", string("tagB"), + row["TAG_NAME"].data<std::string>() ); + transaction.commit(); + } + + + + /// Tests deleteObject2TagTableRows + void test_deleteObject2TagTableRows() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->storeObject( 2, 6, dummyPayload( 1 ), 0 ); + folder->storeObject( 4, 8, dummyPayload( 2 ), 0 ); + folder->tagCurrentHead( "tagA" ); + + folder->storeObject( 0, 5, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 7, dummyPayload( 4 ), 0 ); + folder->storeObject( 5, 9, dummyPayload( 5 ), 0 ); + folder->tagCurrentHead( "tagB" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + coral::ITable& table = ralDb->session().nominalSchema().tableHandle + ( relfolder->object2TagTableName() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count before delete", + 6u, rowCount( table ) ); + + // Delete the first tagA (we know it has id = 1 in a new db) + unsigned int tagId = 1; + relfolder->deleteObject2TagTableRows + ( relfolder->object2TagTableName(), tagId ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count after delete", + 3u, rowCount( table ) ); + + // Check the values of the remaining rows (tagB == tagId 2) + tagId = 2; + unsigned int objectId = 26; + RelationalTableRow row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 tag id", 2u, row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 obj id", 26u, row["OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 since", (ValidityKey)0, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 until", (ValidityKey)3, row["IOV_UNTIL"].data<ValidityKey>() ); + objectId = 31; + + row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 tag id", 2u, row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 obj id", 31u, row["OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 since", (ValidityKey)5, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 until", (ValidityKey)9, row["IOV_UNTIL"].data<ValidityKey>() ); + + objectId = 32; + row = ralDb->fetchObject2TagTableRow + ( relfolder->object2TagTableName(), tagId, objectId ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 tag id", 2u, row["TAG_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 obj id", 32u, row["OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 since", (ValidityKey)3, row["IOV_SINCE"].data<ValidityKey>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "3 until", (ValidityKey)5, row["IOV_UNTIL"].data<ValidityKey>() ); + + transaction.commit(); + } + + + + /// Tests insertionTimeOfLastObjectInTag (bug #40812) + void test_insertionTimeOfLastObjectInTag() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + IObjectPtr obj = folder->findObject( 1, 0 ); + Time lastObjectInsTime = obj->insertionTime(); + folder->tagCurrentHead( "tag A" ); + + folder->storeObject( 1, 5, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 6, dummyPayload( 2 ), 0 ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "tag time", + lastObjectInsTime, + folder->insertionTimeOfLastObjectInTag( "tag A" ) ); + + // test user tags + folder->storeObject( 3, 8, dummyPayload( 3 ), 0, "tag B" ); + IObjectPtr obj2 = folder->findObject( 3, 0, "tag B" ); + Time lastObjectInsTime2 = obj2->insertionTime(); + folder->storeObject( 4, 9, dummyPayload( 3 ), 0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "user tag time", + lastObjectInsTime2, + folder->insertionTimeOfLastObjectInTag( "tag B" ) ); + + } + + + /// Tests that user tagged objects correctly create system objects + /// in their 'tag space' + void test_userTag_systemObjects() { + IFolderPtr folder = m_db->createFolder( "/a", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + ChannelId ch = 0; + folder->storeObject( 0, 10, dummyPayload( 1 ), ch, "A" ); + folder->storeObject( 1, 5, dummyPayload( 2 ), ch, "A" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + coral::ITable& table = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 8u, rowCount( table ) ); + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)10 + + , row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "user tag id", 0u, row.userTagId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 7u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 4u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 4u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)10, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "user tag id", 1u, row.userTagId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 10u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "user tag id", 0u, row.userTagId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 8u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 8u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "user tag id", 0u, row.userTagId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 9u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 9u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)10, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "user tag id", 0u, row.userTagId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 10u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 10u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "user tag id", 1u, row.userTagId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 11u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 11u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "user tag id", 1u, row.userTagId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 4u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 0u, row.newHeadId() ); + + row = objectTable.fetchRowForId( 12u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 12u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)10, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "user tag id", 1u, row.userTagId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 4u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 0u, row.newHeadId() ); + + transaction.commit(); + } + + + /// Tests existsUserTag behavior in concert with normal tags + void test_existsUserTag_normal_tag() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + CPPUNIT_ASSERT_MESSAGE( "no user tag yet", + ! relfolder->existsUserTag( "A" ) ); + CPPUNIT_ASSERT_MESSAGE( "no tag yet", ! ralDb->existsTag( "A" ) ); + + folder->storeObject( 0, 10, dummyPayload( 1 ), (ChannelId)0 ); + folder->tagCurrentHead( "A" ); + + CPPUNIT_ASSERT_MESSAGE( "user tag does not exist", + ! relfolder->existsUserTag( "A" ) ); + CPPUNIT_ASSERT_MESSAGE( "tag exists", ralDb->existsTag( "A" ) ); + } + + + /// Tests existsUserTag + void test_existsUserTag() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + CPPUNIT_ASSERT_MESSAGE( "no user tag yet", + ! relfolder->existsUserTag( "A" ) ); + CPPUNIT_ASSERT_MESSAGE( "no tag yet", ! ralDb->existsTag( "A" ) ); + + folder->storeObject( 0, 10, dummyPayload( 1 ), (ChannelId)0, "A" ); + + CPPUNIT_ASSERT_MESSAGE( "user tag exists", + relfolder->existsUserTag( "A" ) ); + CPPUNIT_ASSERT_MESSAGE( "tag exists", ralDb->existsTag( "A" ) ); + } + + + /// Tests updateObjectTableNewHeadId for a given user tag id and makes + /// sure the userTagId parameter correctly selects the intended row + /// for updating. + void test_updateObjectTableNewHeadId_userTag() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = dynamic_cast<RelationalFolder*>(folder.get()); + + // this creates two objects, ids 1 (tagId 0) and 4 (tagId 1) + folder->storeObject( 0, 10, dummyPayload( 1 ), (ChannelId)0, "A" ); + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 1", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 1", 0u,row.newHeadId() ); + row = objectTable.fetchRowForId( 4u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 2", 4u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 2", 0u,row.newHeadId() ); + transaction.commit(); + } + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + + // now update the new head ids + unsigned int newHeadId = 5; + unsigned int userTagId = 0; + updateObjectTableNewHeadId( objMgr.get(), + relfolder->objectTableName(), + relfolder->channelTableName(), + (ValidityKey)2, + (ValidityKey)4, + (ChannelId)0, + newHeadId, + userTagId ); + newHeadId = 6; + userTagId = 1; + updateObjectTableNewHeadId( objMgr.get(), + relfolder->objectTableName(), + relfolder->channelTableName(), + (ValidityKey)2, + (ValidityKey)4, + (ChannelId)0, + newHeadId, + userTagId ); + transaction.commit(); + } + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1u, fetchPayload ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 3", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 3", 5u,row.newHeadId() ); + row = objectTable.fetchRowForId( 4u, fetchPayload ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id 4", 4u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new_head_id 4", 6u,row.newHeadId() ); + transaction.commit(); + } + } + + + + // ----------------------------------------------------------------------- + + void test_insertChannelTableRow() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + RelationalObjectMgr objMgr( *ralDb ); + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + objMgr.insertChannelTableRow( relfolder->channelTableName(), + (ChannelId)1, + 2u, + true, + "ch name", + "ch desc" ); + transaction.commit(); + } + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalChannelTable channelTable( *ralDb, *relfolder ); + RelationalTableRow row = channelTable.fetchRowForId( 1 ); + CPPUNIT_ASSERT_EQUAL + ( (ChannelId)1, row["CHANNEL_ID"].data<ChannelId>() ); + CPPUNIT_ASSERT_EQUAL + ( 2u, row["LAST_OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL + ( true, row["HAS_NEW_DATA"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL + ( std::string("ch name"), row["CHANNEL_NAME"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL + ( std::string("ch desc"), row["DESCRIPTION"].data<std::string>() ); + transaction.commit(); + } + } + + // ----------------------------------------------------------------------- + + + void test_updateChannelTable() { + try{ + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + RelationalObjectMgr objMgr( *ralDb ); + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + objMgr.updateChannelTable + ( relfolder->channelTableName(), (ChannelId)2, 0, true ); + transaction.commit(); + } + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalChannelTable channelTable( *ralDb, *relfolder ); + RelationalTableRow row = channelTable.fetchRowForId( 2 ); + CPPUNIT_ASSERT_EQUAL + ( (ChannelId)2, row["CHANNEL_ID"].data<ChannelId>() ); + CPPUNIT_ASSERT_EQUAL + ( 0u, row["LAST_OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL + ( true, row["HAS_NEW_DATA"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), row["CHANNEL_NAME"].data<std::string>() ); + transaction.commit(); + } + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + // ----------------------------------------------------------------------- + + + void test_bulkUpdateChannelTable() { + try{ + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + RelationalObjectMgr objMgr( *ralDb ); + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + // use updateChannelTable to populate the channels table + objMgr.updateChannelTable + ( relfolder->channelTableName(), (ChannelId)2, 0, true ); + objMgr.updateChannelTable + ( relfolder->channelTableName(), (ChannelId)3, 0, false ); + objMgr.updateChannelTable + ( relfolder->channelTableName(), (ChannelId)4, 0, true ); + objMgr.updateChannelTable + ( relfolder->channelTableName(), (ChannelId)5, 0, false ); + + std::map< ChannelId, unsigned int > updateDataMap; + updateDataMap[3] = 30; + updateDataMap[4] = 40; + objMgr.bulkUpdateChannelTable + ( relfolder->channelTableName(), updateDataMap, false ); + transaction.commit(); + } + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalChannelTable channelTable( *ralDb, *relfolder ); + RelationalTableRow row = channelTable.fetchRowForId( 2 ); + CPPUNIT_ASSERT_EQUAL + ( (ChannelId)2, row["CHANNEL_ID"].data<ChannelId>() ); + CPPUNIT_ASSERT_EQUAL + ( 0u, row["LAST_OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL + ( true, row["HAS_NEW_DATA"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), row["CHANNEL_NAME"].data<std::string>() ); + transaction.commit(); + } + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalChannelTable channelTable( *ralDb, *relfolder ); + RelationalTableRow row = channelTable.fetchRowForId( 3 ); + CPPUNIT_ASSERT_EQUAL + ( (ChannelId)3, row["CHANNEL_ID"].data<ChannelId>() ); + CPPUNIT_ASSERT_EQUAL + ( 30u, row["LAST_OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL + ( false, row["HAS_NEW_DATA"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), row["CHANNEL_NAME"].data<std::string>() ); + transaction.commit(); + } + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalChannelTable channelTable( *ralDb, *relfolder ); + RelationalTableRow row = channelTable.fetchRowForId( 4 ); + CPPUNIT_ASSERT_EQUAL + ( (ChannelId)4, row["CHANNEL_ID"].data<ChannelId>() ); + CPPUNIT_ASSERT_EQUAL + ( 40u, row["LAST_OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL + ( false, row["HAS_NEW_DATA"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), row["CHANNEL_NAME"].data<std::string>() ); + transaction.commit(); + } + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalChannelTable channelTable( *ralDb, *relfolder ); + RelationalTableRow row = channelTable.fetchRowForId( 5 ); + CPPUNIT_ASSERT_EQUAL + ( (ChannelId)5, row["CHANNEL_ID"].data<ChannelId>() ); + CPPUNIT_ASSERT_EQUAL + ( 0u, row["LAST_OBJECT_ID"].data<unsigned int>() ); + CPPUNIT_ASSERT_EQUAL + ( false, row["HAS_NEW_DATA"].data<bool>() ); + CPPUNIT_ASSERT_EQUAL + ( std::string(""), row["CHANNEL_NAME"].data<std::string>() ); + transaction.commit(); + } + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + // ----------------------------------------------------------------------- + + + void test_fetchLastRowsWithNewData() + { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + RelationalObjectMgr objMgr( *ralDb ); + + std::vector<RelationalObjectTableRow> rows; + for ( int i = 0; i < 10; ++i ) + { + ChannelId ch = i; + rows.push_back( RelationalObjectTableRow( dummyObject( i, 0, 1, ch ) ) ); + rows[rows.size()-1].setObjectId( i ); + } + { + // First fill the channels table + RelationalTransaction transaction( ralDb->transactionMgr() ); + // use updateChannelTable to populate the channels table + for ( int i = 0; i < 10; ++i ) + { + objMgr.updateChannelTable + ( relfolder->channelTableName(), (ChannelId)i, 0, false ); + } + transaction.commit(); + } + { + // Then populate the object table + RelationalTransaction transaction( ralDb->transactionMgr() ); + objMgr.bulkInsertObjectTableRows( relfolder->objectTableName(), + rows, + folder->payloadSpecification() ); + transaction.commit(); + } + { + // Update rows with new data in the channels table + RelationalTransaction transaction( ralDb->transactionMgr() ); + std::map< ChannelId, unsigned int > updateDataMap; + updateDataMap[2] = 2; + updateDataMap[3] = 3; + objMgr.bulkUpdateChannelTable + ( relfolder->channelTableName(), updateDataMap, false ); + objMgr.updateChannelTable + ( relfolder->channelTableName(), (ChannelId)2, 0, true ); + objMgr.updateChannelTable + ( relfolder->channelTableName(), (ChannelId)3, 0, true ); + transaction.commit(); + } + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + std::vector<RelationalObjectTableRow> rows; + objMgr.fetchLastRowsWithNewData( relfolder, rows ); + CPPUNIT_ASSERT_EQUAL( (size_t)2, rows.size() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)2, rows[0].channelId() ); + CPPUNIT_ASSERT_EQUAL( (ChannelId)3, rows[1].channelId() ); + transaction.commit(); + } + } + + + // ----------------------------------------------------------------------- + + + void test_channelTableFK() + { + const MSG::Level oldOutputLevel = application().outputLevel(); + // Remove "ORA-02291 integrity constraint violated" printout from CORAL + application().setOutputLevel( MSG::FATAL ); + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + RelationalObjectMgr objMgr( *ralDb ); + // Prepare some rows to insert into the IOV table + std::vector<RelationalObjectTableRow> rows; + for ( int i = 0; i < 10; ++i ) + { + ChannelId ch = i; + rows.push_back( RelationalObjectTableRow( dummyObject(i,0,1,ch) ) ); + rows[rows.size()-1].setObjectId( i ); + } + // Try to populate the IOV table without first filling the channel table + try + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + objMgr.bulkInsertObjectTableRows( relfolder->objectTableName(), + rows, + folder->payloadSpecification() ); + transaction.commit(); + } + // Warning: the test will succeed on Oracle (exception is caught), + // but it will print an error message from OracleAccess anyway + catch ( std::exception& ) + { + if ( ralDb->sessionMgr()->databaseTechnology() == "SQLite" ) + CPPUNIT_FAIL( "Expected FK not to be enforced on sqlite...???" ); + } + } + catch ( ... ) + { + application().setOutputLevel( oldOutputLevel ); + throw; + } + application().setOutputLevel( oldOutputLevel ); + } + + + // ----------------------------------------------------------------------- + + + void test_lastUpdate_SV() { + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + { + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 0, ValidityKeyMax ) ); + storeObjects( relfolder, objs ); + } + // sleep for one second to make sure the update time change is properly + // picked up (MySQL has a 1s granularity for example) + sleep(1); + { + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 2, 10, ValidityKeyMax ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow row = + objectTable.fetchRowForId( 1u, fetchPayload ); + CPPUNIT_ASSERT( row.insertionTime() < row.lastModDate() ); + row = objectTable.fetchRowForId( 2u, fetchPayload ); + CPPUNIT_ASSERT( row.insertionTime() == row.lastModDate() ); + transaction.commit(); + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + // ----------------------------------------------------------------------- + + + void test_lastUpdate_MV() { + try { + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + { + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 1, 0, ValidityKeyMax ) ); + storeObjects( relfolder, objs ); + } + // sleep for one second to make sure the update time change is properly + // picked up (MySQL has a 1s granularity for example) + sleep(1); + { + vector<RelationalObjectPtr> objs; + objs.push_back( dummyObject( 2, 10, ValidityKeyMax ) ); + storeObjects( relfolder, objs ); + } + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow row = + objectTable.fetchRowForId( 1u, fetchPayload ); + CPPUNIT_ASSERT( row.insertionTime() < row.lastModDate() ); + row = objectTable.fetchRowForId( 7u, fetchPayload ); + CPPUNIT_ASSERT( row.insertionTime() == row.lastModDate() ); + transaction.commit(); + + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + // ----------------------------------------------------------------------- + + + unsigned int rowCount( const coral::ITable& tableHandle ) + { + // TEMPORARY -- working around a bug in the sqlite backend + if ( ralDb->sessionMgr()->databaseTechnology() == "SQLite" ) { + std::auto_ptr<coral::IQuery> query( tableHandle.newQuery() ); + + coral::AttributeList output; + output.extend( "count(*)", "unsigned int" ); + query->addToOutputList( "count(*)" ); + query->defineOutput( output ); + + coral::ICursor& cursor = query->execute(); + + if ( cursor.next() ) { + const coral::AttributeList& row( cursor.currentRow() ); + return row["count(*)"].data<unsigned int>(); + } else { + throw RelationalException + ( "Could not fetch row count", "RalObjectTable" ); + } + } else { + std::auto_ptr<coral::IQuery> query( tableHandle.newQuery() ); + + query->addToOutputList( "count(*)", "count" ); + + coral::ICursor& cursor = query->execute(); + + if ( cursor.next() ) { + const coral::Attribute& count = cursor.currentRow()["count"]; + if ( count.specification().type() == typeid(int) ) + return count.data<int>(); + else if ( count.specification().type() == typeid(long) ) + return static_cast<unsigned int>( count.data<long>() ); + else if ( count.specification().type() == typeid(double) ) + return static_cast<unsigned int>( count.data<double>() ); + else + return static_cast<unsigned int> + ( count.data<Int64>() ); + } else { + throw RelationalException( "Could not fetch row count", + "RalObjectTable" ); + } + } + } + + + /// Utility method to return a dummy object with a distinct payload + /// (determined by 'index') for a given set of since/until/channel + RelationalObjectPtr dummyObject( int index, + const ValidityKey& since, + const ValidityKey& until, + const ChannelId& channel = 0 ) { + RelationalObjectPtr + obj( new RelationalObject( since, + until, + dummyPayload( index ), + channel ) ); + return obj; + } + + + /// Utility method to generate a distinct payload for a given index + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + void setUp() { + try { + createDB(); + openDB(false); + ralDb = dynamic_cast<RalDatabase*>(m_db.get()); + objMgr = std::auto_ptr<RelationalObjectMgr>( new RelationalObjectMgr( *ralDb ) ); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + void tearDown() { + forceDisconnect(); + } + + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( RelationalObjectMgrTest ); + +} // namespace + + +COOLTEST_MAIN(RelationalObjectMgrTest) + diff --git a/RelationalCool/tests/RelationalObjectSet/test_RelationalObjectSet.cpp b/RelationalCool/tests/RelationalObjectSet/test_RelationalObjectSet.cpp new file mode 100644 index 000000000..8a84d1fcd --- /dev/null +++ b/RelationalCool/tests/RelationalObjectSet/test_RelationalObjectSet.cpp @@ -0,0 +1,244 @@ +// $Id: test_RelationalObjectSet.cpp,v 1.24 2008-04-10 08:32:52 avalassi Exp $ + +// Disable CppUnit header warnings from gcc41 nightlies (task #5837) +#include "../Common/CppUnit_headers.h" + +// Include files +#include <iostream> +#include <string> +#include <cppunit/extensions/HelperMacros.h> +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/types.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoralBase/Attribute.h" + +// Local include files +#include "src/CoralApplication.h" +#include "src/timeToString.h" + +namespace cool { + const char* COOLTESTDB = "COOLTESTDB"; + class ObjectSetTest; +} + +//----------------------------------------------------------------------------- + +class cool::ObjectSetTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( ObjectSetTest ); + + CPPUNIT_TEST( test_begin ); + CPPUNIT_TEST( test_iterator_prefix_increment ); + CPPUNIT_TEST( test_end ); + CPPUNIT_TEST( test_iterator_equality ); + CPPUNIT_TEST( test_iterator_copy_constructor ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + std::string connectString; + IDatabasePtr db; + IFolderPtr folder; + + RecordSpecification payloadSpec; + + // Tests that iterator copies are equal and iterate independently. + void test_iterator_copy_constructor() { + folder->setPrefetchAll( true ); + IObjectVectorPtr objs = folder->browseObjects( 5, 25, 0 )->fetchAllAsVector(); + IObjectVector::const_iterator iter = objs->begin(); + + IObjectVector::const_iterator + iter_copy = IObjectVector::const_iterator( iter ); + + CPPUNIT_ASSERT_MESSAGE( "iter_copy before increment", + dummyPayload( 0 ) == (*iter_copy)->payload() ); + + ++iter; + + CPPUNIT_ASSERT_MESSAGE( "iter after after first increment", + dummyPayload( 1 ) == (*iter)->payload() ); + CPPUNIT_ASSERT_MESSAGE( "iter_copy after first increment", + dummyPayload( 0 ) == (*iter_copy)->payload() ); + + ++iter_copy; + + CPPUNIT_ASSERT_MESSAGE( "iter after second increment", + dummyPayload( 1 ) == (*iter)->payload() ); + CPPUNIT_ASSERT_MESSAGE( "iter_copy after second increment", + dummyPayload( 1 ) == (*iter_copy)->payload() ); + } + + + /// Tests const_iterator::operator==. + void test_iterator_equality() { + folder->setPrefetchAll( true ); + IObjectVectorPtr objs = folder->browseObjects( 5, 25, 0 )->fetchAllAsVector(); + IObjectVector::const_iterator i1 = objs->begin(); + IObjectVector::const_iterator i2 = objs->begin(); + + CPPUNIT_ASSERT_MESSAGE( "before increment", i1 == i2 ); + + ++i1; + + CPPUNIT_ASSERT_MESSAGE( "iter after i1 increment", i1 != i2 ); + + ++i2; + + CPPUNIT_ASSERT_MESSAGE( "iter after i2 increment", i1 == i2 ); + } + + + /// Tests that the iterator correctly points at the end after the container + /// has been exhausted. + void test_end() { + folder->setPrefetchAll( true ); + IObjectVectorPtr objs = folder->browseObjects( 5, 25, 0 )->fetchAllAsVector(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object count", 3ul, (unsigned long)objs->size() ); + + IObjectVector::const_iterator iter = objs->begin(); + ++iter; + ++iter; + ++iter; + CPPUNIT_ASSERT_MESSAGE + ( "Iterator pointing at end", iter == objs->end() ); + } + + + /// Tests that prefix operator++ correctly iterates through the container. + void test_iterator_prefix_increment() { + folder->setPrefetchAll( true ); + IObjectVectorPtr objs = folder->browseObjects( 5, 25, 0 )->fetchAllAsVector(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object count", 3ul, (unsigned long)objs->size() ); + + IObjectVector::const_iterator iter = objs->begin(); + + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == (*iter)->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, (*iter)->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, (*iter)->until() ); + + ++iter; + CPPUNIT_ASSERT_MESSAGE( "obj 1.2 payload", + dummyPayload( 1 ) == (*iter)->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 since", + (ValidityKey)10, (*iter)->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.2 until", + (ValidityKey)20, (*iter)->until() ); + + ++iter; + CPPUNIT_ASSERT_MESSAGE( "obj 1.3 payload", + dummyPayload( 2 ) == (*iter)->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.3 since", + (ValidityKey)20, (*iter)->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.3 until", + ValidityKeyMax, (*iter)->until() ); + } + + + /// Tests that begin returns an iterator pointing to the first item. + void test_begin() { + folder->setPrefetchAll( true ); + IObjectVectorPtr objs = folder->browseObjects( 5, 25, 0 )->fetchAllAsVector(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object count", 3ul, (unsigned long)objs->size() ); + + IObjectVector::const_iterator iter = objs->begin(); + + CPPUNIT_ASSERT_MESSAGE( "obj 1.1 payload", + dummyPayload( 0 ) == (*iter)->payload() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 since", + (ValidityKey)0, (*iter)->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "obj 1.1 until", + (ValidityKey)10, (*iter)->until() ); + } + + + /// Creates a dummy payload AttributeList for a given index + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + ObjectSetTest() + : payloadSpec() { + + payloadSpec.extend("I",StorageType::Int32); + payloadSpec.extend("S",StorageType::String255); + payloadSpec.extend("X",StorageType::Float); + + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + std::cout << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << std::endl; + std::cout << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << std::endl; + std::cout << "Aborting test" << std::endl; + exit(-1); + } + } + + ~ObjectSetTest() {} + + void setUp() + { + try + { + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + std::string folderName( "/folder_1" ); + folder = db->createFolder( folderName, payloadSpec ); + for ( int i = 0; i < 3; ++i ) + { + ValidityKey since = i*10; + ValidityKey until = ValidityKeyMax; + Record payload = dummyPayload( i ); + folder->storeObject( since, until, payload, 0 ); + } + } + catch ( std::exception& e ) + { + std::cout << e.what() << std::endl; + throw; + } + } + + + void tearDown() { + // add cleanup code here (e.g. deletion of table data, releasing of + // resources) + // setup() and tearDown() will be called before and after *each test* + db.reset(); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( cool::ObjectSetTest ); + +//----------------------------------------------------------------------------- + +// Include CppUnit test driver +#include <CppUnit_testdriver.icpp> diff --git a/RelationalCool/tests/RelationalObjectTable/test_RelationalObjectTable.cpp b/RelationalCool/tests/RelationalObjectTable/test_RelationalObjectTable.cpp new file mode 100644 index 000000000..7d90d8800 --- /dev/null +++ b/RelationalCool/tests/RelationalObjectTable/test_RelationalObjectTable.cpp @@ -0,0 +1,3002 @@ +// $Id: test_RelationalObjectTable.cpp,v 1.1 2008-09-26 17:46:47 avalassi Exp $ + +// Include files +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/Record.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoralBase/AttributeListException.h" +#include "CoralBase/Exception.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" +#include "RelationalAccess/ITableDataEditor.h" + +// Local include files +#include "src/HvsTagRecord.h" +#include "src/IRelationalQueryDefinition.h" +#include "src/RalDatabase.h" +#include "src/RelationalChannelTable.h" +#include "src/RelationalObjectMgr.h" +#include "src/RelationalObjectTable.h" +#include "src/RelationalObjectTableRow.h" +#include "src/RelationalFolder.h" +#include "src/RelationalSequence.h" +#include "src/RelationalSequenceMgr.h" +#include "src/RelationalTagMgr.h" +#include "src/RelationalTransaction.h" +#include "src/timeToString.h" + +// Test Base Class +#include "CoolDBUnitTest.h" + +//----------------------------------------------------------------------------- + +namespace cool +{ + // Forward declaration (needed by gcc4.1 on slc4_ia32_gcc41 + // to avoid the error "qualified name does not name a class") + class RelationalObjectTableTest; +} + +//----------------------------------------------------------------------------- + +namespace cool +{ + inline Time addOneNsToTime( ITime& time ) + { + return Time( time.year(), + time.month(), + time.day(), + time.hour(), + time.minute(), + time.second(), + time.nanosecond()+1 ); + } +} + +//--------------------------------------------------------------------------- + +class cool::RelationalObjectTableTest : public cool::CoolDBUnitTest +{ + CPPUNIT_TEST_SUITE( RelationalObjectTableTest ); + + CPPUNIT_TEST( test_fetchRowForId_data ); + + // AV 19.05.2006 This method is not used anymore + //CPPUNIT_TEST( test_fetchRowAtTimeSV ); + //CPPUNIT_TEST( test_fetchRowAtTimeSV64bit ); + + CPPUNIT_TEST( test_fetchRowForId ); + + //CPPUNIT_TEST( test_fetchRowsSV_channel_range ); + //CPPUNIT_TEST( test_fetchRowsSV_channel_range_ordering ); + //CPPUNIT_TEST( test_fetchRowsSV_all_channels ); + + //CPPUNIT_TEST( test_fetchLastRowSV ); + CPPUNIT_TEST( test_fetchLastRowForTagId ); + + CPPUNIT_TEST( test_fetchRowAtTimeInHead_5b ); + CPPUNIT_TEST( test_fetchRowAtTimeInHead_5b_with_userTag ); + CPPUNIT_TEST( test_findObjectAtTimeInTag_5b ); + CPPUNIT_TEST( test_fetchRowAtTimeInTag_5c ); + + CPPUNIT_TEST( test_fetchRowsForTaggingCurrentHead_5c ); + CPPUNIT_TEST( test_fetchRowsForTaggingCurrentHead_5c_with_userTag ); + + CPPUNIT_TEST( test_fetchRowsForTaggingHeadAsOfDate_5c ); + CPPUNIT_TEST( test_fetchRowsForTaggingHeadAsOfDate_5c_with_userTag ); + + CPPUNIT_TEST( test_fetchRowsForTaggingHeadAsOfObjectId_5c ); + CPPUNIT_TEST( test_fetchRowsForTaggingHeadAsOfObjectId_duplIOV ); + + CPPUNIT_TEST( test_fetchRowsForTaggingHeadAsOfObjectId_5c_with_userTag ); + + CPPUNIT_TEST( test_fetchRowsInHead_5c ); + CPPUNIT_TEST( test_fetchRowsInHead_identicalRange ); + CPPUNIT_TEST( test_fetchRowsInHead_channel_range ); + CPPUNIT_TEST( test_fetchRowsInHead_channel_range_ordering ); + CPPUNIT_TEST( test_fetchRowsInHead_all_channels ); + + CPPUNIT_TEST( test_fetchRowsInTag ); + CPPUNIT_TEST( test_fetchRowsInTag_channel_range ); + CPPUNIT_TEST( test_fetchRowsInTag_channel_range_ordering ); + CPPUNIT_TEST( test_fetchRowsInTag_all_channels ); + + // This is the test that may crash or hang on RH73 + // Interesting: this is also the test that used to fail on Windows before + // the COOL_1_2_0 release because of the bug in the Time constructor + CPPUNIT_TEST( test_fetchRowsInPastHead_5c ); + CPPUNIT_TEST( test_fetchRowsInPastHead_identicalRange ); + + CPPUNIT_TEST( test_fetchRowsInPastHead_5c_with_userTag ); + + CPPUNIT_TEST( test_objectCountSV_all_channels ); + CPPUNIT_TEST( test_objectCountSV_channel_range ); + CPPUNIT_TEST( test_objectCountSV_iov_range ); + + CPPUNIT_TEST( test_objectCountInHead_all_channels ); + CPPUNIT_TEST( test_objectCountInHead_channel_range ); + CPPUNIT_TEST( test_objectCountInHead_iov_range ); + CPPUNIT_TEST( test_objectCountInHead_hidden_objects ); + + CPPUNIT_TEST( test_objectCountInTag_all_channels ); + CPPUNIT_TEST( test_objectCountInTag_channel_range ); + CPPUNIT_TEST( test_objectCountInTag_iov_range ); + + //CPPUNIT_TEST( test_rowCount ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + RalDatabase* ralDb; // safely cast pointer to db + + RecordSpecification payloadSpec; + + //------------------------------------------------------------------------- + + std::vector<RelationalObjectTableRow> fetchRowsInTag + ( RelationalObjectTable& objectTable, + const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels, + const std::string& tagName ) + { + //std::cout << "Fetch tag '" << tagName << "'" + // << " from table " << objectTable.objectTableName() + // << " for channel=[" << channels.firstChannel() + // << "," << channels.lastChannel() << "]" + // << ", since=" << since + // << ", until=" << until + // << std::endl; + const std::auto_ptr<IRelationalQueryDefinition> + def( objectTable.queryDefinitionTag( since, until, channels, tagName ) ); + try + { + std::string desc = ""; + const std::vector<RelationalTableRow> rows + ( objectTable.queryMgr().fetchOrderedRows( *def, desc ) ); + std::vector<RelationalObjectTableRow> objectRows; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + RelationalObjectTableRow objectRow( *row ); + objectRows.push_back( objectRow ); + } + return objectRows; + } + catch( NoRowsFound& ) + { + std::stringstream s; + throw ObjectNotFound + ( s.str(), objectTable.objectTableName(), "test_RelationalObjectTable" ); + } + } + + //------------------------------------------------------------------------- + + std::vector<RelationalObjectTableRow> fetchRowsInHead + ( RelationalObjectTable& objectTable, + const ValidityKey& since, + const ValidityKey& until, + const ChannelSelection& channels ) + { + //std::cout << "Fetch HEAD from table " << objectTable.objectTableName() + // << " for channel=[" << channels.firstChannel() + // << "," << channels.lastChannel() << "]" + // << ", since=" << since + // << ", until=" << until + // << std::endl; + std::string tagName = "HEAD"; + const std::auto_ptr<IRelationalQueryDefinition> + def( objectTable.queryDefinitionHeadAndUserTag + ( since, until, channels, tagName ) ); + try + { + std::string desc = ""; + const std::vector<RelationalTableRow> rows + ( objectTable.queryMgr().fetchOrderedRows( *def, desc ) ); + std::vector<RelationalObjectTableRow> objectRows; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + RelationalObjectTableRow objectRow( *row ); + objectRows.push_back( objectRow ); + } + return objectRows; + } + catch( NoRowsFound& ) + { + std::stringstream s; + throw ObjectNotFound + ( s.str(), objectTable.objectTableName(), "RelationalObjectTable" ); + } + } + + //------------------------------------------------------------------------- + + std::vector<RelationalObjectTableRow> fetchRowsInPastHead + ( RelationalObjectTable& objectTable, + const ValidityKey& since, + const ValidityKey& until, + const ChannelId& channelId, + const ITime& asOfDate ) + { + // Define the list of tables to query + // NB Use UPPERCASE table aliases for Frontier (see task #3536) + RelationalQueryMgr::TableNamesWithAliases tables; + tables.push_back + ( RelationalQueryMgr::TableNameWithAlias + ( objectTable.objectTableName(), "I" ) ); + tables.push_back + ( RelationalQueryMgr::TableNameWithAlias + ( objectTable.objectTableName(), "O" ) ); + // Add all columns to the output list and define the output format + RelationalQueryMgr::SelectListWithRSetSpec columns = + RelationalQueryMgr::columnList + ( objectTable.tableSpecification(), "I." ); + // Define the WHERE clause for the selection using bind variables + // MIND THE ORDER! For MySQL, match the order in which they are bound! + RecordSpecification spec; + spec.extend( "userTagId", + RelationalObjectTable::columnTypeIds::userTagId ); + spec.extend( "since1", + RelationalObjectTable::columnTypeIds::iovSince ); + spec.extend( "since2", + RelationalObjectTable::columnTypeIds::iovSince ); + spec.extend( "since3", + RelationalObjectTable::columnTypeIds::iovSince ); + spec.extend( "until", + RelationalObjectTable::columnTypeIds::iovUntil ); + spec.extend( "asOfDate1", + RelationalObjectTable::columnTypeIds::sysInsTime ); + spec.extend( "channel", + RelationalObjectTable::columnTypeIds::channelId ); + spec.extend( "newHeadId", + RelationalObjectTable::columnTypeIds::newHeadId ); + spec.extend( "asOfDate2", + RelationalObjectTable::columnTypeIds::sysInsTime ); + Record whereData( spec ); + whereData["userTagId"].setValue( 0u ); + whereData["since1"].setValue( since ); + whereData["since2"].setValue( since ); + whereData["since3"].setValue( since ); + whereData["until"].setValue( until ); + whereData["asOfDate1"].setValue( timeToString( asOfDate ) ); + whereData["channel"].setValue( (unsigned int)channelId ); + whereData["newHeadId"].setValue( 0u ); + whereData["asOfDate2"].setValue( timeToString( asOfDate ) ); + // Also see SimpleObject::overlaps for this clause + // but note that the upper end is *included* (<= :until) + std::string s = RelationalObjectTable::columnNames::iovSince(); + std::string u = RelationalObjectTable::columnNames::iovUntil(); + std::string ch = RelationalObjectTable::columnNames::channelId(); + std::string ins = RelationalObjectTable::columnNames::sysInsTime(); + std::string oid = RelationalObjectTable::columnNames::objectId(); + std::string nhid = RelationalObjectTable::columnNames::newHeadId(); + std::string + whereClause = "I." + RelationalObjectTable::columnNames::userTagId(); + whereClause += "= :userTagId"; + whereClause += " AND "; + whereClause += "("; + whereClause += " ( ( I." + s + " <= :since1 )"; + whereClause += " AND ( :since2 < I." + u + " ) )"; + whereClause += " OR "; + whereClause += " ( ( :since3 <= I." + s + " )"; + whereClause += " AND ( I." + s + " <= :until ) )"; + whereClause += ")"; + whereClause += " AND I." + ins + " <= :asOfDate1"; + whereClause += " AND I." + ch + " = :channel"; + whereClause += " AND ( "; + whereClause += "( I." + nhid + " = :newHeadId"; + whereClause += " AND I." + oid + " = O." + oid; // constrains self join + whereClause += " ) "; + whereClause += " OR "; + whereClause += "( I." + nhid + " = O." + oid; + whereClause += " AND O." + ins + " > :asOfDate2"; + whereClause += " ) "; + whereClause += ")"; + /// Results are ordered by ascending values of the "since" start of IOV + std::vector<std::string> orderBy; + orderBy.push_back + ( std::string("I.") + + RelationalObjectTable::columnNames::iovSince() + " ASC" ); + // Delegate the query to the RalQueryMgr + std::string desc = ""; + std::vector<RelationalTableRow> rows = + objectTable.queryMgr().fetchOrderedRowsFromTables + ( tables, columns, + whereClause, whereData.attributeList(), orderBy, desc ); + // TEMPORARY? Conversion to RelationalObjectTableRow + std::vector<RelationalObjectTableRow> objectRows; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + RelationalObjectTableRow objectRow( *row ); + objectRows.push_back( objectRow ); + } + // Return the results + return objectRows; + } + + //------------------------------------------------------------------------- + + /* + /// Tests rowCount + void test_rowCount() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + // this creates three rows per channel: the two inserted ones plus a + // system object + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), ch ); + } + folder->flushStorageBuffer(); + + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + } + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + int count = objectTable.rowCount(); + + CPPUNIT_ASSERT_EQUAL( 20, count ); + } + */ + + /// Tests countObjectInTag for all channels + void test_objectCountInTag_all_channels() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), ch ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "A" ); + + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "B" ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionTag( ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all(), + "A" ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + + CPPUNIT_ASSERT_EQUAL( 10, count ); + } + + + /// Tests countObjectInTag for a channel range + void test_objectCountInTag_channel_range() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), ch ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "A" ); + + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "B" ); + + ChannelSelection channels( 2, 3 ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionTag( ValidityKeyMin, + ValidityKeyMax, + channels, + "A" ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + + CPPUNIT_ASSERT_EQUAL( 4, count ); + } + + + /// Tests countObjectInTag for an IOV range + void test_objectCountInTag_iov_range() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + for ( int i = 0; i < 10; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ), 0 ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "A" ); + + for ( int i = 0; i < 5; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ), 0 ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "B" ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionTag( (ValidityKey)3, + (ValidityKey)5, + ChannelSelection::all(), + "A" ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + CPPUNIT_ASSERT_EQUAL( 3, count ); + } + + + /// Tests countObjectInHead for all channels + void test_objectCountInHead_all_channels() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), ch ); + } + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionHeadAndUserTag( ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all(), + "HEAD" ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + CPPUNIT_ASSERT_EQUAL( 10, count ); + } + + + /// Tests countObjectInHead for a channel range + void test_objectCountInHead_channel_range() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), ch ); + } + folder->flushStorageBuffer(); + + ChannelSelection channels( 2, 3 ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionHeadAndUserTag( ValidityKeyMin, + ValidityKeyMax, + channels, + "HEAD" ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + CPPUNIT_ASSERT_EQUAL( 4, count ); + } + + + /// Tests countObjectInHead for an IOV range + void test_objectCountInHead_iov_range() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + for ( int i = 0; i < 10; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ), 0 ); + } + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionHeadAndUserTag( (ValidityKey)3, + (ValidityKey)5, + ChannelSelection::all(), + "HEAD" ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + CPPUNIT_ASSERT_EQUAL( 3, count ); + } + + + /// Tests countObjectInHead with some objects being fully overlapped by + /// later insertions. + void test_objectCountInHead_hidden_objects() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + for ( int i = 0; i < 6; ++i ) { + folder->storeObject( i, i+1, dummyPayload( i ), 0 ); + } + folder->flushStorageBuffer(); + + folder->storeObject( 0, 3, dummyPayload( 0 ), 0 ); + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionHeadAndUserTag( ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all(), + "HEAD" ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + CPPUNIT_ASSERT_EQUAL( 4, count ); + } + + + /// Tests countObjectSV for all channels + void test_objectCountSV_all_channels() { + try{ + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), ch ); + } + folder->flushStorageBuffer(); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionSV( ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all() ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + + CPPUNIT_ASSERT_EQUAL( 10, count ); + } + catch( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests countObjectSV for a channel range + void test_objectCountSV_channel_range() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 0 ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( 1 ), ch ); + } + folder->flushStorageBuffer(); + + ChannelSelection channels( 2, 3 ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionSV( ValidityKeyMin, + ValidityKeyMax, + channels ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + + CPPUNIT_ASSERT_EQUAL( 4, count ); + } + + + /// Tests countObjectSV for an IOV range + void test_objectCountSV_iov_range() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + + folder->setupStorageBuffer(); + for ( int i = 0; i < 10; ++i ) { + folder->storeObject( i, ValidityKeyMax, dummyPayload( i ), 0 ); + } + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + std::auto_ptr<IRelationalQueryDefinition> pQueryDef = + objectTable.queryDefinitionSV( (ValidityKey)3, + (ValidityKey)5, + ChannelSelection::all() ); + int count = objectTable.queryMgr().countRows( *pQueryDef ); + + CPPUNIT_ASSERT_EQUAL( 3, count ); + } + + + /// Tests fetchRowAtTimeInHead + void test_fetchRowAtTimeInHead_5b_with_userTag() { + try{ + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), (ChannelId)0, "A" ); + folder->storeObject( 2, 4, dummyPayload( 3 ), (ChannelId)0, "B" ); + folder->storeObject( 5, 7, dummyPayload( 4 ), (ChannelId)0, "A" ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + RelationalObjectTableRow row = + objectTable.fetchRowAtTimeInHead( (ValidityKey)1, + (ChannelId)0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 1", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 1", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 1", (ValidityKey)2, row.until() ); + + row = objectTable.fetchRowAtTimeInHead( (ValidityKey)3, + (ChannelId)0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 2", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 2", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 2", (ValidityKey)4, row.until() ); + + try { + row = objectTable.fetchRowAtTimeInHead( (ValidityKey)4, + (ChannelId)0 ); + CPPUNIT_FAIL( "expected RelationalObjectNotFound exception" ); + } catch ( ObjectNotFound& /* ignored */ ) { } + + row = objectTable.fetchRowAtTimeInHead( (ValidityKey)5, + (ChannelId)0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 4", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 4", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 4", (ValidityKey)7, row.until() ); + + row = objectTable.fetchRowAtTimeInHead( (ValidityKey)7, + (ChannelId)0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 5", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 5", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 5", (ValidityKey)8, row.until() ); + + transaction.commit(); + } + catch( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests fetchRowAtTimeInHead + void test_fetchRowAtTimeInHead_5b() { + try{ + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->setupStorageBuffer(); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), 0 ); + folder->storeObject( 2, 4, dummyPayload( 3 ), 0 ); + folder->storeObject( 5, 7, dummyPayload( 4 ), 0 ); + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + RelationalObjectTableRow row = + objectTable.fetchRowAtTimeInHead( (ValidityKey)1, + (ChannelId)0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 1", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 1", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 1", (ValidityKey)2, row.until() ); + + row = objectTable.fetchRowAtTimeInHead( (ValidityKey)3, + (ChannelId)0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 2", 13u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 2", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 2", (ValidityKey)4, row.until() ); + + try { + row = objectTable.fetchRowAtTimeInHead( (ValidityKey)4, + (ChannelId)0 ); + CPPUNIT_FAIL( "expected RelationalObjectNotFound exception" ); + } catch ( ObjectNotFound& /* ignored */ ) { } + + row = objectTable.fetchRowAtTimeInHead( (ValidityKey)5, + (ChannelId)0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 4", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 4", (ValidityKey)5, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 4", (ValidityKey)7, row.until() ); + + row = objectTable.fetchRowAtTimeInHead( (ValidityKey)7, + (ChannelId)0 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 5", 21u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 5", (ValidityKey)7, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 5", (ValidityKey)8, row.until() ); + + transaction.commit(); + } + catch( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests tags in a way similar to fetchRowAtTimeInHead_5b (bug #33256) + void test_findObjectAtTimeInTag_5b() { + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->setupStorageBuffer(); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), 0 ); + folder->storeObject( 2, 4, dummyPayload( 3 ), 0 ); + folder->storeObject( 5, 7, dummyPayload( 4 ), 0 ); + folder->flushStorageBuffer(); + + std::string mytag = "mytag"; + folder->tagCurrentHead( mytag ); + + IObjectPtr obj = + folder->findObject( (ValidityKey)1, (ChannelId)0, mytag ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 1", 14u, obj->objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 1", (ValidityKey)1, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 1", (ValidityKey)2, obj->until() ); + + obj = folder->findObject( (ValidityKey)3, (ChannelId)0, mytag ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 2", 13u, obj->objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 2", (ValidityKey)2, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 2", (ValidityKey)4, obj->until() ); + + try { + obj = folder->findObject( (ValidityKey)4, (ChannelId)0, mytag ); + CPPUNIT_FAIL( "expected ObjectNotFound exception" ); + } catch ( ObjectNotFound& /* ignored */ ) { } + + obj = folder->findObject( (ValidityKey)5, (ChannelId)0, mytag ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 4", 19u, obj->objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 4", (ValidityKey)5, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 4", (ValidityKey)7, obj->until() ); + + obj = folder->findObject( (ValidityKey)7, (ChannelId)0, mytag ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id time 5", 21u, obj->objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "since time 5", (ValidityKey)7, obj->since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "until time 5", (ValidityKey)8, obj->until() ); + + } + catch( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests fetchRowsInPastHead for case 5c and selection + /// between T2 and T3 in the context of user tags + void test_fetchRowsInPastHead_5c_with_userTag() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 1, 3, dummyPayload( 1 ), (ChannelId)0, "A" ); + folder->storeObject( 6, 8, dummyPayload( 2 ), (ChannelId)0, "B" ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction t1( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + Time asOfDate = stringToTime( seq->currDate() ); + asOfDate = addOneNsToTime( asOfDate ); + t1.commit(); + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + sleep(1); + + folder->storeObject( 2, 4, dummyPayload( 3 ), (ChannelId)0, "A" ); + folder->storeObject( 3, 5, dummyPayload( 4 ), (ChannelId)0, "B" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + ralDb->log() + << "rh7 issue: I may soon crash (seg fault) or hang (mutex lock)" + << coral::MessageStream::endmsg; + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInPastHead( objectTable, + ValidityKeyMin, + ValidityKeyMax, + (ChannelId)0, + asOfDate ); + + ralDb->log() << "rh7 issue: I did not crash or hang" << coral::MessageStream::endmsg; + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 2u, (unsigned int)rows.size() ); + + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", std::string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 13u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", std::string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + } + + + + /// Tests fetchRowsInPastHead for case 5c and selection + /// between T2 and T3 + void test_fetchRowsInPastHead_5c() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction t1( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + Time asOfDate = stringToTime( seq->currDate() ); + asOfDate = addOneNsToTime( asOfDate ); + t1.commit(); + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + sleep(1); + + folder->storeObject( 2, 4, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 5, dummyPayload( 4 ), 0 ); + folder->flushStorageBuffer(); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + ralDb->log() + << "rh7 issue: I may soon crash (seg fault) or hang (mutex lock)" + << coral::MessageStream::endmsg; + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInPastHead( objectTable, + ValidityKeyMin, + ValidityKeyMax, + (ChannelId)0, + asOfDate ); + + ralDb->log() << "rh7 issue: I did not crash or hang" << coral::MessageStream::endmsg; + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 2u, (unsigned int)rows.size() ); + + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", std::string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 13u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", std::string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + } + + + + /// Tests fetchRowsInTag + void test_fetchRowsInTag() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 1 ), 0 ); + folder->tagCurrentHead( "mytagA", "a tag A" ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInTag( objectTable, + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection( 0, 0 ), + "mytagA" ); + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 1u, + (unsigned int)rows.size() ); + + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", std::string("Object 1"), + row["S"].data<std::string>() ); + } + + + + /// Tests fetchRowsInPastHead + void test_fetchRowsInPastHead_identicalRange() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 1 ), 0 ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + Time asOfDate = stringToTime( seq->currDate() ); + asOfDate = addOneNsToTime( asOfDate ); + + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInPastHead( objectTable, + ValidityKeyMin, + ValidityKeyMax, + (ChannelId)0, + asOfDate ); + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 1u, + (unsigned int)rows.size() ); + + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", std::string("Object 1"), + row["S"].data<std::string>() ); + } + + + + /// Tests fetchRowsInHead + void test_fetchRowsInHead_5c() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + folder->storeObject( 2, 4, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 5, dummyPayload( 4 ), 0 ); + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInHead( objectTable, + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection( 0, 0 ) ); + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 4u, + (unsigned int)rows.size() ); + + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", std::string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 original id", 1u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 new head id", 0u, row.newHeadId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 20u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", std::string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 13u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)5, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", std::string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 payload", std::string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 new head id", 0u, row.newHeadId() ); + } + + + + /// Tests fetchRowsHead + void test_fetchRowsInHead_identicalRange() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 0, ValidityKeyMax, dummyPayload( 1 ), 0 ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInHead( objectTable, + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection( 0, 0 ) ); + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "row count", 1u, + (unsigned int)rows.size() ); + + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 payload", std::string("Object 1"), + row["S"].data<std::string>() ); + } + + + + /// Tests fetchRowsForTaggingCurrentHead in the context of user tags + void test_fetchRowsForTaggingCurrentHead_5c_with_userTag() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), (ChannelId)0, "A" ); + + folder->storeObject( 2, 4, dummyPayload( 3 ), (ChannelId)0, "B" ); + folder->storeObject( 3, 5, dummyPayload( 4 ), (ChannelId)0, "A" ); + + folder->storeObject( 1, 5, dummyPayload( 5 ), (ChannelId)1 ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + objectTable.fetchRowsForTaggingCurrentHead(); + sort( rows.begin(), rows.end(), lt_objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "row count", 5u, (unsigned int)rows.size() ); + + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "0 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "0 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "0 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "0 until", (ValidityKey)8, row.until() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)2, row.until() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)5, row.until() ); + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 20u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)3, row.until() ); + + row = rows[4]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 25u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 channel id", 1u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)5, row.until() ); + } + + + /// Tests fetchRowsForTaggingCurrentHead + void test_fetchRowsForTaggingCurrentHead_5c() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + folder->setupStorageBuffer(); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + folder->storeObject( 2, 4, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 5, dummyPayload( 4 ), 0 ); + folder->flushStorageBuffer(); + + folder->storeObject( 1, 5, dummyPayload( 5 ), (ChannelId)1 ); + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + objectTable.fetchRowsForTaggingCurrentHead(); + sort( rows.begin(), rows.end(), lt_objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "row count", 5u, (unsigned int)rows.size() ); + + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "0 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "0 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "0 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "0 until", (ValidityKey)8, row.until() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)2, row.until() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 19u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)5, row.until() ); + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 object id", 20u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "3 until", (ValidityKey)3, row.until() ); + + row = rows[4]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 object id", 25u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 channel id", 1u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "4 until", (ValidityKey)5, row.until() ); + } + + + /// Tests fetchRowsForTaggingHeadAsOfDate in the context of user tags + void test_fetchRowsForTaggingHeadAsOfDate_5c_with_userTag() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 1, 3, dummyPayload( 1 ), (ChannelId)0, "A" ); + folder->storeObject( 6, 8, dummyPayload( 2 ), (ChannelId)0, "B" ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction t1( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + Time asOfDate = stringToTime( seq->currDate() ); + asOfDate = addOneNsToTime( asOfDate ); + t1.commit(); + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + sleep(1); + + folder->storeObject( 2, 4, dummyPayload( 3 ), (ChannelId)0, "A" ); + folder->storeObject( 3, 5, dummyPayload( 4 ), (ChannelId)0, "B" ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + objectTable.fetchRowsForTaggingHeadAsOfDate( asOfDate ); + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "row count", 2u, (unsigned int)rows.size() ); + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + } + + + /// Tests fetchRowsForTaggingHeadAsOfDate + void test_fetchRowsForTaggingHeadAsOfDate_5c() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction t1( ralDb->transactionMgr() ); + boost::shared_ptr<RelationalSequence> seq + ( ralDb->queryMgr().sequenceMgr().getSequence + ( RelationalObjectTable::sequenceName + ( relfolder->objectTableName() ) ) ); + Time asOfDate = stringToTime( seq->currDate() ); + asOfDate = addOneNsToTime( asOfDate ); + t1.commit(); + + // MySQL now() has 1 second granularity: need to sleep at least 1 second + sleep(1); + + folder->storeObject( 2, 4, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 5, dummyPayload( 4 ), 0 ); + folder->flushStorageBuffer(); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + objectTable.fetchRowsForTaggingHeadAsOfDate( asOfDate ); + + //copy( rows.begin(), rows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "row count", 2u, (unsigned int)rows.size() ); + RelationalObjectTableRow& row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + } + + + /// Tests fetchRowsInTag of all channels + void test_fetchRowsInTag_all_channels() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + + int index = 0; + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 2; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "A" ); + + for ( ChannelId ch = 0; ch < 2; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInTag( objectTable, + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all(), + "A" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 4, (int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 0", + std::string("Object 0"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 0", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 0", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 0", + (ChannelId)0, row.channelId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 1", + std::string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 1", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 1", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", + (ChannelId)0, row.channelId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 2", + std::string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 2", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 2", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", + (ChannelId)1, row.channelId() ); + + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 3", + std::string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 3", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 3", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", + (ChannelId)1, row.channelId() ); + + } + + + + /// Tests fetchRowsInTag with a channel range and + /// since-before-channel ordering + void test_fetchRowsInTag_channel_range_ordering() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + + int index = 0; + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "A" ); + + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + ChannelSelection channels( 2, 3, ChannelSelection::sinceBeforeChannel ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInTag( objectTable, + ValidityKeyMin, + ValidityKeyMax, + channels, + "A" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 4, (int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 0", + std::string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 0", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 0", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 0", + (ChannelId)2, row.channelId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 1", + std::string("Object 6"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 1", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 1", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", + (ChannelId)3, row.channelId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 2", + std::string("Object 5"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 2", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 2", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", + (ChannelId)2, row.channelId() ); + + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 3", + std::string("Object 7"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 3", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 3", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", + (ChannelId)3, row.channelId() ); + + } + + + + + + /// Tests fetchRowsInTag with a channel range + void test_fetchRowsInTag_channel_range() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + + int index = 0; + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "A" ); + + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInTag( objectTable, + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection( 2, 3 ), + "A" ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 4, (int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 0", + std::string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 0", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 0", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 0", + (ChannelId)2, row.channelId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 1", + std::string("Object 5"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 1", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 1", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", + (ChannelId)2, row.channelId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 2", + std::string("Object 6"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 2", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 2", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", + (ChannelId)3, row.channelId() ); + + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 3", + std::string("Object 7"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 3", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 3", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", + (ChannelId)3, row.channelId() ); + + } + + + + /// Tests fetchRowsInHead of all channels + void test_fetchRowsInHead_all_channels() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + + int index = 0; + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 2; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInHead( objectTable, + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 4, (int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 0", + std::string("Object 0"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 0", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 0", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 0", + (ChannelId)0, row.channelId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 1", + std::string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 1", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 1", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", + (ChannelId)0, row.channelId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 2", + std::string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 2", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 2", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", + (ChannelId)1, row.channelId() ); + + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 3", + std::string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 3", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 3", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", + (ChannelId)1, row.channelId() ); + + } + + + + + /// Tests fetchRowsInHead with a channel range and + /// since-before-channel ordering + void test_fetchRowsInHead_channel_range_ordering() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + + int index = 0; + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + ChannelSelection channels( 2, 3, ChannelSelection::sinceBeforeChannel ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInHead( objectTable, + ValidityKeyMin, + ValidityKeyMax, + channels ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 4, (int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 0", + std::string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 0", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 0", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 0", + (ChannelId)2, row.channelId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 1", + std::string("Object 6"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 1", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 1", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", + (ChannelId)3, row.channelId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 2", + std::string("Object 5"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 2", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 2", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", + (ChannelId)2, row.channelId() ); + + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 3", + std::string("Object 7"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 3", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 3", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", + (ChannelId)3, row.channelId() ); + + } + + + + + /// Tests fetchRowsInHead with a channel range + void test_fetchRowsInHead_channel_range() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "desc", + FolderVersioning::MULTI_VERSION ); + + int index = 0; + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + fetchRowsInHead( objectTable, + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection( 2, 3 ) ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 4, (int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 0", + std::string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 0", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 0", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 0", + (ChannelId)2, row.channelId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 1", + std::string("Object 5"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 1", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 1", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", + (ChannelId)2, row.channelId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 2", + std::string("Object 6"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 2", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 2", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", + (ChannelId)3, row.channelId() ); + + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 3", + std::string("Object 7"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 3", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 3", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", + (ChannelId)3, row.channelId() ); + + } + + + + /// Tests fetchRowAtTimeInTag + void test_fetchRowAtTimeInTag_5c() + { + try + { + IFolderPtr folder = + ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "mytagA", "a tag A" ); + + folder->storeObject( 2, 4, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 5, dummyPayload( 4 ), 0 ); + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + + //RelationalObjectTableRow row = + // objectTable.fetchRowAtTimeInTag( (ValidityKey)2, + // (ChannelId)0, + // "mytagA" ); + RelationalTableRow row0; + { + const ValidityKey pointInTime = (ValidityKey)2; + const ChannelId channelId = (ChannelId)0; + const std::string tagName = "mytagA"; + const std::auto_ptr<IRelationalQueryDefinition> + def( objectTable.queryDefinitionTag + ( pointInTime, pointInTime, channelId, tagName ) ); + // Delegate the query to the RalQueryMgr + try + { + std::string desc = ""; + const std::vector<RelationalTableRow> rows + ( objectTable.queryMgr().fetchOrderedRows( *def, desc, 1 ) ); + row0 = rows[0]; + } + catch( NoRowsFound& ) + { + std::stringstream s; + s << pointInTime; + throw ObjectNotFound + ( s.str(), objectTable.objectTableName(), "RelationalObjectTable" ); + } + } + + RelationalObjectTableRow row(row0); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", std::string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "original id", 0u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 13u, row.newHeadId() ); + } + catch ( std::exception& e ) + { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + + + /// Tests test_fetchRowsForTaggingHeadAsOfObjectId_5c in the context of user + /// tags + void test_fetchRowsForTaggingHeadAsOfObjectId_5c_with_userTag() { + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->storeObject( 1, 3, dummyPayload( 1 ), (ChannelId)0, "A" ); + folder->storeObject( 6, 8, dummyPayload( 2 ), (ChannelId)0, "B" ); + + folder->storeObject( 2, 4, dummyPayload( 3 ), (ChannelId)0, "A" ); + folder->storeObject( 3, 5, dummyPayload( 4 ), (ChannelId)0, "B" ); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + unsigned int uObjectId = 7; // user object + unsigned int lObjectId = 8; // left system object + unsigned int rObjectId = 9; // right system object + std::vector<RelationalObjectTableRow> uRows = + objectTable.fetchRowsForTaggingHeadAsOfObjectId( uObjectId ); + std::vector<RelationalObjectTableRow> lRows = + objectTable.fetchRowsForTaggingHeadAsOfObjectId( lObjectId ); + std::vector<RelationalObjectTableRow> rRows = + objectTable.fetchRowsForTaggingHeadAsOfObjectId( rObjectId ); + + //copy( uRows.begin(), uRows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(u) row count", 2u, (unsigned int)uRows.size() ); + RelationalObjectTableRow& row = uRows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(u) 1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + row = uRows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(u) 2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + + //copy( lRows.begin(), lRows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(l) row count", 2u, (unsigned int)lRows.size() ); + row = lRows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(l) 1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + row = lRows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(l) 2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + + //copy( rRows.begin(), rRows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(r) row count", 2u, (unsigned int)rRows.size() ); + row = rRows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(r) 1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + row = rRows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(r) 2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + } catch ( std::exception& e ) { + std::cout << e.what() << std::endl; + throw; + } + } + + + /// Tests test_fetchRowsForTaggingHeadAsOfObjectId_5c + void test_fetchRowsForTaggingHeadAsOfObjectId_5c() { + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + folder->storeObject( 2, 4, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 5, dummyPayload( 4 ), 0 ); + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + unsigned int uObjectId = 7; // user object + unsigned int lObjectId = 8; // left system object + unsigned int rObjectId = 9; // right system object + std::vector<RelationalObjectTableRow> uRows = + objectTable.fetchRowsForTaggingHeadAsOfObjectId( uObjectId ); + std::vector<RelationalObjectTableRow> lRows = + objectTable.fetchRowsForTaggingHeadAsOfObjectId( lObjectId ); + std::vector<RelationalObjectTableRow> rRows = + objectTable.fetchRowsForTaggingHeadAsOfObjectId( rObjectId ); + + //copy( uRows.begin(), uRows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(u) row count", 2u, (unsigned int)uRows.size() ); + RelationalObjectTableRow& row = uRows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(u) 1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + row = uRows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(u) 2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + + //copy( lRows.begin(), lRows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(l) row count", 2u, (unsigned int)lRows.size() ); + row = lRows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(l) 1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + row = lRows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(l) 2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + + //copy( rRows.begin(), rRows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(r) row count", 2u, (unsigned int)rRows.size() ); + row = rRows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(r) 1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + row = rRows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(r) 2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + } catch ( std::exception& e ) { + std::cout << e.what() << std::endl; + throw; + } + } + + + /// Tests fetchRowsForTaggingHeadAsOfObjectId for a duplicate IOV + void test_fetchRowsForTaggingHeadAsOfObjectId_duplIOV() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + + folder->setupStorageBuffer(); + folder->storeObject( 1, 3, dummyPayload( 1 ), 0 ); + folder->storeObject( 6, 8, dummyPayload( 2 ), 0 ); + // DUPLICATE! + folder->storeObject( 6, 8, dummyPayload( 5 ), 0 ); + folder->flushStorageBuffer(); + + folder->storeObject( 2, 4, dummyPayload( 3 ), 0 ); + folder->storeObject( 3, 5, dummyPayload( 4 ), 0 ); + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + unsigned int uObjectId = 7; // user object + unsigned int lObjectId = 8; // left system object + unsigned int rObjectId = 9; // right system object + std::vector<RelationalObjectTableRow> uRows = + objectTable.fetchRowsForTaggingHeadAsOfObjectId( uObjectId ); + std::vector<RelationalObjectTableRow> lRows = + objectTable.fetchRowsForTaggingHeadAsOfObjectId( lObjectId ); + std::vector<RelationalObjectTableRow> rRows = + objectTable.fetchRowsForTaggingHeadAsOfObjectId( rObjectId ); + + //copy( uRows.begin(), uRows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(u) row count", 2u, (unsigned int)uRows.size() ); + RelationalObjectTableRow& row = uRows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(u) 1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + row = uRows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(u) 2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(u) 2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + + //copy( lRows.begin(), lRows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(l) row count", 2u, (unsigned int)lRows.size() ); + row = lRows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(l) 1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + row = lRows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(l) 2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(l) 2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + + //copy( rRows.begin(), rRows.end(), + // std::ostream_iterator<RelationalObjectTableRow>( std::cout, "\n" ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(r) row count", 2u, (unsigned int)rRows.size() ); + row = rRows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 object id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 1 until", (ValidityKey)3, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(r) 1 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + row = rRows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 object id", 7u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "(r) 2 until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "(r) 2 instime", std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + } + + + /// Tests fetchLastRowForTagId (bug #40812) + void test_fetchLastRowForTagId() { + IFolderPtr folder = m_db->createFolder( "/myfolder", + payloadSpec, + "my description", + FolderVersioning::MULTI_VERSION ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + folder->setupStorageBuffer(); + folder->storeObject( 0, 4, dummyPayload( 0 ), 0 ); + folder->storeObject( 1, 5, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 6, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + folder->tagCurrentHead( "tag A" ); + + folder->storeObject( 1, 5, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 6, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + folder->storeObject( 3, 8, dummyPayload( 3 ), 0, "tag B"); + folder->storeObject( 2, 6, dummyPayload( 4 ), 0, "tag B"); + folder->flushStorageBuffer(); + folder->storeObject( 4, 5, dummyPayload( 5 ), 0); + folder->flushStorageBuffer(); + + // test IOV tag + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + unsigned int tagId = 1; + bool fetchPayload = true; + RelationalObjectTableRow row = + objectTable.fetchLastRowForTagId( tagId, fetchPayload ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "objectId", 14u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)2, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", + std::string( "Object 1" ), + row["S"].data<std::string>() ); + // test user tag + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + unsigned int tagId = 2; + bool fetchPayload = true; + RelationalObjectTableRow row = + objectTable.fetchLastRowForTagId( tagId, fetchPayload ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "objectId", 42u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since", (ValidityKey)6, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until", (ValidityKey)8, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload", + std::string( "Object 3" ), + row["S"].data<std::string>() ); + } + } + + /* + /// Tests fetchRowAtTimeSV + void test_fetchRowAtTimeSV() { + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + folder->setupStorageBuffer(); + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + RelationalObjectTableRow + row( objectTable.fetchRowAtTimeSV( (ValidityKey)3, + (ChannelId)0 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id", 2u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "iov since", (ValidityKey)2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "iov until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "instime length", + std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "field I", 2, row["I"].data<int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "field S", std::string("Object 2"), row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "field X", 0.002f, row["X"].data<float>() ); + transaction.commit(); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + */ + + /* + /// Test for bug #16903 - all three backends fail with "No rows selected" + /// (Oracle with "ORA-01455: converting column overflows integer datatype") + void test_fetchRowAtTimeSV64bit() { + try { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + ValidityKey vk0 = ValidityKeyMax-10; + folder->setupStorageBuffer(); + folder->storeObject( vk0, vk0+2, dummyPayload( 1 ), 0 ); + folder->storeObject( vk0+2, vk0+4, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + RelationalObjectTableRow + row( objectTable.fetchRowAtTimeSV( vk0+3, (ChannelId)0 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id", 2u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel id", 0u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "iov since", vk0+2, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "iov until", vk0+4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "instime length", + std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row.insertionTime()).size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "field I", 2, row["I"].data<int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "field S", std::string("Object 2"), row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "field X", 0.002f, row["X"].data<float>() ); + transaction.commit(); + } catch ( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + } + */ + + /// Tests fetchRowForId + void test_fetchRowForId() { + + try { + + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + folder->setupStorageBuffer(); + folder->storeObject( 0, 2, dummyPayload( 1 ), 0 ); + folder->storeObject( 2, 4, dummyPayload( 2 ), 0 ); + folder->flushStorageBuffer(); + + unsigned int object_id = 1; + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row1( objectTable.fetchRowForId( object_id, fetchPayload ) ); + fetchPayload = false; + RelationalObjectTableRow + row2( objectTable.fetchRowForId( object_id, fetchPayload ) ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id", 1u, row1.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel id", 0u, row1.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "iov since", (ValidityKey)0, row1.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "iov until", (ValidityKey)2, row1.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_INSTIME length", + std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row1.insertionTime()).size() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "field I", 1, row1["I"].data<int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "field S", std::string("Object 1"), row1["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "field X", 0.001f, row1["X"].data<float>() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "object_id", 1u, row2.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "channel id", 0u, row2.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "iov since", (ValidityKey)0, row2.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "iov until", (ValidityKey)2, row2.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "NODE_INSTIME length", + std::string("yyyy-mm-dd_hh:mm:ss.nnnnnnnnn GMT").size(), + timeToString(row2.insertionTime()).size() ); + + try { row2["I"]; CPPUNIT_FAIL( "row2[I] - no exception thrown" ); } + catch ( coral::AttributeListException& ) {} + catch ( ... ) { CPPUNIT_FAIL( "row2[I] - unknown exception caught" ); } + + try { row2["S"]; CPPUNIT_FAIL( "row2[S] - no exception thrown" ); } + catch ( coral::AttributeListException& ) {} + catch ( ... ) { CPPUNIT_FAIL( "row2[S] - unknown exception caught" ); } + + try { row2["X"]; CPPUNIT_FAIL( "row2[X] - no exception thrown" ); } + catch ( coral::AttributeListException& ) {} + catch ( ... ) { CPPUNIT_FAIL( "row2[X] - unknown exception caught" ); } + + } + catch( std::exception& e ) { + std::cout << "Exception caught: " << e.what() << std::endl; + throw; + } + + } + + + /* + /// Tests fetchLastRowSV + void test_fetchLastRowSV() { + IFolderPtr folder = + ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + folder->setupStorageBuffer(); + folder->storeObject( 0, 2, dummyPayload( 0 ), 1 ); + folder->storeObject( 2, 4, dummyPayload( 0 ), 1 ); + + folder->storeObject( 0, 2, dummyPayload( 0 ), 2 ); + folder->storeObject( 2, 4, dummyPayload( 0 ), 2 ); + + folder->storeObject( 0, 2, dummyPayload( 0 ), 3 ); + folder->storeObject( 2, 4, dummyPayload( 0 ), 3 ); + + folder->storeObject( 4, 6, dummyPayload( 0 ), 1 ); + folder->flushStorageBuffer(); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + + { + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + RelationalObjectTableRow + row( objectTable.fetchLastRowSV( (ChannelId)1 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "first channel", 7u, row.objectId() ); + } + + { + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + RelationalObjectTableRow + row( objectTable.fetchLastRowSV( (ChannelId)2 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "second channel", 4u, row.objectId() ); + } + + { + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + RelationalObjectTableRow + row( objectTable.fetchLastRowSV( (ChannelId)3 ) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "third channel", 6u, row.objectId() ); + } + + transaction.commit(); + } + */ + + + /// Tests fetchRowForId for a directly stored row (not via the API) + void test_fetchRowForId_data() { + IFolderPtr folder = + ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + + coral::ITable& chTable = ralDb->session().nominalSchema().tableHandle + ( relfolder->channelTableName() ); + RecordSpecification chSpec = + RelationalChannelTable::tableSpecification(); + coral::AttributeList chData = Record( chSpec ).attributeList(); + chData["CHANNEL_ID"].setValue( 2u ); + chTable.dataEditor().insertRow( chData ); + + coral::ITable& table = ralDb->session().nominalSchema().tableHandle + ( relfolder->objectTableName() ); + RecordSpecification spec = + RelationalObjectTable::tableSpecification( payloadSpec ); + coral::AttributeList data = Record( spec ).attributeList(); + data["OBJECT_ID"].setValue( 1u ); + data["CHANNEL_ID"].setValue( 2u ); + data["IOV_SINCE"].setValue( (ValidityKey)3 ); + data["IOV_UNTIL"].setValue( (ValidityKey)4 ); + data["USER_TAG_ID"].setValue( 5u ); + std::string insertionTime = "2006-03-04_18:38:59.803342000 GMT"; + data["SYS_INSTIME"].setValue( insertionTime ); + data["ORIGINAL_ID"].setValue( 6u ); + data["NEW_HEAD_ID"].setValue( 7u ); + data["I"].setValue( 8 ); + data["S"].setValue( std::string( "9" ) ); + data["X"].setValue( 10.0f ); + table.dataEditor().insertRow( data ); + + transaction.commit(); + } + { + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + bool fetchPayload = true; + RelationalObjectTableRow + row( objectTable.fetchRowForId( 1, fetchPayload ) ); + transaction.commit(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "object_id", 1u, row.objectId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel id", 2u, row.channelId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "iov since", (ValidityKey)3, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "iov until", (ValidityKey)4, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "user_tag_id", 5u, row.userTagId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("NODE_INSTIME"), + std::string("2006-03-04_18:38:59.803342000 GMT"), + timeToString(row.insertionTime()) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "orignal id", 6u, row.originalId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "new head id", 7u, row.newHeadId() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "field I", 8, row["I"].data<int>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "field S", std::string("9"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "field X", 10.0f, row["X"].data<float>() ); + } + } + + + /* + /// Tests fetchRowsSV with a channel range and + /// since-before-channel ordering + void test_fetchRowsSV_channel_range_ordering() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + int index = 0; + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + ChannelSelection channels( 2, 3, ChannelSelection::sinceBeforeChannel ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + objectTable.fetchRowsSV( relfolder->payloadSpecification(), + ValidityKeyMin, + ValidityKeyMax, + channels ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 4, (int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 0", + std::string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 0", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 0", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 0", + (ChannelId)2, row.channelId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 1", + std::string("Object 6"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 1", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 1", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", + (ChannelId)3, row.channelId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 2", + std::string("Object 5"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 2", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 2", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", + (ChannelId)2, row.channelId() ); + + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 3", + std::string("Object 7"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 3", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 3", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", + (ChannelId)3, row.channelId() ); + + } + + + + /// Tests fetchRowsSV with a channel range + void test_fetchRowsSV_channel_range() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + + int index = 0; + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 5; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + ChannelSelection channels( 2, 3 ); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + objectTable.fetchRowsSV( relfolder->payloadSpecification(), + ValidityKeyMin, + ValidityKeyMax, + channels ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 4u, (unsigned int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 0", + std::string("Object 4"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 0", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 0", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 0", + (ChannelId)2, row.channelId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 1", + std::string("Object 5"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 1", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 1", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", + (ChannelId)2, row.channelId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 2", + std::string("Object 6"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 2", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 2", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", + (ChannelId)3, row.channelId() ); + + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 3", + std::string("Object 7"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 3", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 3", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", + (ChannelId)3, row.channelId() ); + + } + + + + /// Tests fetchRowsSV of all channels + void test_fetchRowsSV_all_channels() { + IFolderPtr folder = ralDb->createFolder( "/myfolder", payloadSpec ); + + int index = 0; + folder->setupStorageBuffer(); + for ( ChannelId ch = 0; ch < 2; ++ch ) { + folder->storeObject( 0, ValidityKeyMax, dummyPayload( index++ ), ch ); + folder->storeObject( 1, ValidityKeyMax, dummyPayload( index++ ), ch ); + } + folder->flushStorageBuffer(); + + RelationalFolder* relfolder = + dynamic_cast<RelationalFolder*>(folder.get()); + + RelationalTransaction transaction( ralDb->transactionMgr() ); + RelationalObjectTable + objectTable( &(ralDb->queryMgr()), false, *relfolder ); + std::vector<RelationalObjectTableRow> rows = + objectTable.fetchRowsSV( relfolder->payloadSpecification(), + ValidityKeyMin, + ValidityKeyMax, + ChannelSelection::all() ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "size", 4, (int)rows.size() ); + + RelationalObjectTableRow row = rows[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 0", + std::string("Object 0"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 0", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 0", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 0", + (ChannelId)0, row.channelId() ); + + row = rows[1]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 1", + std::string("Object 1"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 1", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 1", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 1", + (ChannelId)0, row.channelId() ); + + row = rows[2]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 2", + std::string("Object 2"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 2", + (ValidityKey)0, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 2", + (ValidityKey)1, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 2", + (ChannelId)1, row.channelId() ); + + + row = rows[3]; + CPPUNIT_ASSERT_EQUAL_MESSAGE( "payload 3", + std::string("Object 3"), + row["S"].data<std::string>() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "since 3", + (ValidityKey)1, row.since() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "until 3", + ValidityKeyMax, row.until() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "channel 3", + (ChannelId)1, row.channelId() ); + + } + */ + + /// Utility method to generate a distinct payload for a given index + Record dummyPayload( int index ) + { + Record payload( payloadSpec ); + payload["I"].setValue<Int32>( index ); + std::stringstream s; + s << "Object " << index; + payload["S"].setValue<String255>( s.str() ); + payload["X"].setValue<Float>( (float)(index/1000.) ); + return payload; + } + + RelationalObjectTableTest() + : payloadSpec() + { + payloadSpec.extend("I",StorageType::Int32); + payloadSpec.extend("S",StorageType::String255); + payloadSpec.extend("X",StorageType::Float); + + if ( getenv( COOLTESTDB ) ) { + m_connectionString = getenv( COOLTESTDB ); + } else { + std::cout + << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << std::endl; + std::cout + << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << std::endl; + std::cout << "Aborting test" << std::endl; + exit(-1); + } + } + + void setUp() + { + createDB(); + openDB(); + ralDb = dynamic_cast<RalDatabase*>(m_db.get()); + } + + void tearDown() + { + forceDisconnect(); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( cool::RelationalObjectTableTest ); + +//----------------------------------------------------------------------------- + +COOLTEST_MAIN(RelationalObjectTableTest) + diff --git a/RelationalCool/tests/SchemaDump/coolSchemaDump.csh b/RelationalCool/tests/SchemaDump/coolSchemaDump.csh new file mode 100755 index 000000000..eb8098477 --- /dev/null +++ b/RelationalCool/tests/SchemaDump/coolSchemaDump.csh @@ -0,0 +1,150 @@ +#!/bin/csh -f + +#--------------------------------------------------------------------------- +# NB: Make sure $HOME/private/authentication.xml contains YOUR credentials! +#--------------------------------------------------------------------------- + +# The path ${HOME}/private/authentication.xml is set in seal.opts.error +if ( ! -f ${HOME}/private/authentication.xml ) then + echo "ERROR! File ${HOME}/private/authentication.xml not found!" + exit 1 +endif + +#----------------------------------------------------------------------------- + +if ( "$1" == "" || "$2" != "" ) then + echo Usage: $0 dbId + echo Example: $0 '"oracle://devdb10;schema=lcg_cool;dbname=COOL_REF"'; + #echo Example: $0 '"mysql://SERVER;schema=SCHEMA;dbname=DB"'; + exit 1 +endif + +unsetenv ORACLE_HOME +unsetenv SCRAM_HOME +setenv PATH /afs/cern.ch/sw/lcg/app/spi/scram:"${PATH}" + +eval `scram runtime -csh` +setenv TNS_ADMIN ${LOCALRT}/src/RelationalCool/tests +setenv SEAL_CONFIGURATION_FILE ${LOCALRT}/src/RelationalCool/tests/seal.opts.error + +#----------------------------------------------------------------------------- +# 1. Create reference schema + +#setenv COOLTESTDB "$1" +#unitTest_RelationalCool_SchemaDump + +#----------------------------------------------------------------------------- +# 2. Dump reference schema + +set theAuth = `coolAuthentication "$1" | & grep '==>'` +set theAuth = `echo "$theAuth ==>"` +#echo "theAuth = $theAuth" + +set theUrl = `echo "$theAuth" | awk '{str=$0; sep="==> urlHidePswd = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; print substr(str,0,ind);};'` +#echo "theUrl = $theUrl" + +if ( "$theUrl" == "" ) then + echo "ERROR! Could not dump schema for COOL database "\""$1"\" + echo "ERROR! Invalid COOL databaseId or missing authentication credentials" + exit 1 +endif + +echo Dump schema for COOL database \""$theUrl"\" + +set theTech = `echo "$theAuth" | awk '{str=$0; sep="==> technology = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; print substr(str,0,ind);};'` +set theHost = `echo "$theAuth" | awk '{str=$0; sep="==> server = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; print substr(str,0,ind);};'` +set theSchema = `echo "$theAuth" | awk '{str=$0; sep="==> schema = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; print substr(str,0,ind);};'` +set theUser = `echo "$theAuth" | awk '{str=$0; sep="==> user = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; print substr(str,0,ind);};'` +set thePswd = `echo "$theAuth" | awk '{str=$0; sep="==> password = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; print substr(str,0,ind);};'` +set theDbName = `echo "$theAuth" | awk '{str=$0; sep="==> dbname = "; ind=index(str,sep)+length(sep); str=substr(str,ind); sep=" ==>"; ind=index(str,sep)-1; print substr(str,0,ind);};'` + +#echo "theTech = $theTech" +#echo "theHost = $theHost" +#echo "theSchema = $theSchema" +#echo "theUser = $theUser" +#echo "thePswd = $thePswd" +#echo "theDbName = $theDbName" +#exit + +#-------- +# Oracle +#-------- +if ( "$theTech" == "oracle" ) then + + set theScript = `which $0` + set theSqlDir = `dirname ${theScript}`/sql + #echo "theScript = $theScript" + #echo "theSqlDir = $theSqlDir" + + # HACK on Windows (limit to the size of file names) + pushd $theSqlDir > /dev/null + set theSqlDir = . + #echo "theSqlDir = $theSqlDir" + + # No special treatment is needed for the user/password@host:port/service + # syntax: this is supported out-of-the-box by Oracle EasyConnect + + set theSchema = `echo $theSchema | awk '{print toupper($1)}'` + set theDbName = `echo $theDbName | awk '{print toupper($1)}'` + ###echo Dump Oracle schema + + #set theHtml = "OFF" + set theHtml = "ON" + + if ( "$theHtml" == "ON" ) then + set theOutFile = oracleRefSchema.html + set theOut = `cd ..; pwd`/$theOutFile + \rm -f ${theOut} + echo Results will be in ${theOut} + echo "<center><h1>" > ${theOut} + echo Schema for COOL database \""$theUrl"\" >> ${theOut} + echo "</h1></center><br>" >> ${theOut} + else + set theOut = /dev/stdout + endif + sqlplus -S -L -M "HTML ${theHtml}" ${theUser}/${thePswd}@${theHost} @${theSqlDir}/oracleSchemaDump.sql ${theSchema} ${theDbName} | grep -v "rows selected" >> ${theOut} + + set theTables = `sqlplus -S -L ${theUser}/${thePswd}@${theHost} @${theSqlDir}/oracleShowTables.sql ${theSchema} ${theDbName} | grep ${theDbName}_` + #echo "theTables = $theTables" + foreach aTable ( $theTables ) + #echo Describe Oracle table ${aTable} + sqlplus -S -L -M "HTML ${theHtml}" ${theUser}/${thePswd}@${theHost} @${theSqlDir}/oracleDescTable.sql ${aTable} "${theSchema}.${aTable}" >> ${theOut} + end + + # Copy the results in a directory visible from the Web + if ( "${USER}" == "avalassi" ) then + \cp ${theOut} ~/myLCG/www/tmp/${theOutFile} + echo "Results can be browsed on" + echo " http://lcgapp.cern.ch/project/CondDB/tmp/${theOutFile}" + endif + + # HACK on Windows + popd > /dev/null + +#------- +# MySQL +#------- +else if ( "$theTech" == "mysql" ) then + + # A special treatment is needed for the host:port syntax: + # the port number must be parsed out and passed explicitly + set thePort = `echo "$theHost" | awk '{str=$0; sep=":"; ind=index(str,sep); if (ind>0) print "-P" substr(str,ind+length(sep)); else print "";};'` + set theHost = `echo "$theHost" | awk '{str=$0; sep=":"; ind=index(str,sep); if (ind>0) print substr(str,0,ind-length(sep)); else print str;};'` + #echo "theHost = $theHost" + #echo "thePort = $thePort" + + ###echo Dump MySQL schema + #mysql -u${theUser} -p${thePswd} -h${theHost} ${thePort} ${theSchema} -e "drop table ${aTable};" + echo NOT YET SUPPORTED + +#-------- +# SQLite +#-------- +else if ( "$theTech" == "sqlite" ) then + + ###echo Dump SQLite schema + echo NOT YET SUPPORTED + +endif + + diff --git a/RelationalCool/tests/SchemaDump/oracleRefSchema.html b/RelationalCool/tests/SchemaDump/oracleRefSchema.html new file mode 100644 index 000000000..ea9f638bc --- /dev/null +++ b/RelationalCool/tests/SchemaDump/oracleRefSchema.html @@ -0,0 +1,2377 @@ +<center><h1> +Schema for COOL database "oracle://devdb10;schema=lcg_cool;dbname=COOL_REF" +</h1></center><br> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLES</h2> +<br> +<p> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +TABLE_NAME +</th> +</tr> +<tr> +<td> +COOL_REF_DB_ATTRIBUTES +</td> +</tr> +<tr> +<td> +COOL_REF_NODES +</td> +</tr> +<tr> +<td> +COOL_REF_NODES_SEQ +</td> +</tr> +<tr> +<td> +COOL_REF_TAGS +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS_SEQ +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS_SEQ +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_TAGS +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_TAGS_SEQ +</td> +</tr> +</table> +<p> + +<br> + + +<h2>INDEXES</h2> +<br> +<p> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +TABLE_NAME +</th> +<th scope="col"> +INDEX_NAME +</th> +<th scope="col"> +UNIQUENES +</th> +</tr> +<tr> +<td> +COOL_REF_DB_ATTRIBUTES +</td> +<td> +COOL_REF_DB_ATTRIBUTES_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_NODES +</td> +<td> +COOL_REF_NODES_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_NODES_SEQ +</td> +<td> +COOL_REF_NODES_SEQ_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_TAGS +</td> +<td> +COOL_REF_TAGS_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_CO_2INDX +</td> +<td> +NONUNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_CSU_3INDX +</td> +<td> +NONUNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS_SEQ +</td> +<td> +COOL_REF_F0002_IOVS_SEQ_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_CO_2INDX +</td> +<td> +NONUNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_CSU_3INDX +</td> +<td> +NONUNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_4INDX +</td> +<td> +NONUNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_OCSU_4INDX +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS_SEQ +</td> +<td> +COOL_REF_F0003_IOVS_SEQ_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_TAGS +</td> +<td> +COOL_REF_F0003_TAGS_PK +</td> +<td> +UNIQUE +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_TAGS_SEQ +</td> +<td> +COOL_REF_F0003_TAGS_SEQ_PK +</td> +<td> +UNIQUE +</td> +</tr> +</table> +<p> + +<br> + + +<h2>CONSTRAINTS</h2> +<br> +<p> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +TABLE_NAME +</th> +<th scope="col"> +CONSTRAINT_NAME +</th> +<th scope="col"> +TYPE +</th> +<th scope="col"> +R_CONSTRAINT_NAME +</th> +<th scope="col"> +INDEX_NAME +</th> +</tr> +<tr> +<td> +COOL_REF_DB_ATTRIBUTES +</td> +<td> +COOL_REF_DB_ATTRIBUTES_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_DB_ATTRIBUTES_PK +</td> +</tr> +<tr> +<td> +COOL_REF_NODES +</td> +<td> +COOL_REF_NODES_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_NODES_PK +</td> +</tr> +<tr> +<td> +COOL_REF_NODES_SEQ +</td> +<td> +COOL_REF_NODES_SEQ_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_NODES_SEQ_PK +</td> +</tr> +<tr> +<td> +COOL_REF_TAGS +</td> +<td> +COOL_REF_TAGS_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_TAGS_PK +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_F0002_IOVS_PK +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS_SEQ +</td> +<td> +COOL_REF_F0002_IOVS_SEQ_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_F0002_IOVS_SEQ_PK +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_F0003_IOVS_PK +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_F0003_IOV2TAG_PK +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS_SEQ +</td> +<td> +COOL_REF_F0003_IOVS_SEQ_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_F0003_IOVS_SEQ_PK +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_TAGS +</td> +<td> +COOL_REF_F0003_TAGS_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_F0003_TAGS_PK +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_TAGS_SEQ +</td> +<td> +COOL_REF_F0003_TAGS_SEQ_PK +</td> +<td> +P +</td> +<td> + +</td> +<td> +COOL_REF_F0003_TAGS_SEQ_PK +</td> +</tr> +<tr> +<td> +COOL_REF_NODES +</td> +<td> +COOL_REF_NODES_PARENT_FK +</td> +<td> +R +</td> +<td> +COOL_REF_NODES_PK +</td> +<td> + +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_O_FK +</td> +<td> +R +</td> +<td> +COOL_REF_F0003_IOVS_PK +</td> +<td> + +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_T_FK +</td> +<td> +R +</td> +<td> +COOL_REF_F0003_TAGS_PK +</td> +<td> + +</td> +</tr> +</table> +<p> + +<br> + + +<h2>INDEXED COLUMNS</h2> +<br> +<p> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +TABLE_NAME +</th> +<th scope="col"> +INDEX_NAME +</th> +<th scope="col"> +COL_NAME +</th> +<th scope="col"> +COL_POS +</th> +<th scope="col"> +DESC +</th> +</tr> +<tr> +<td> +COOL_REF_DB_ATTRIBUTES +</td> +<td> +COOL_REF_DB_ATTRIBUTES_PK +</td> +<td> +DB_ATTRIBUTE_NAME +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_NODES +</td> +<td> +COOL_REF_NODES_PK +</td> +<td> +NODE_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_NODES_SEQ +</td> +<td> +COOL_REF_NODES_SEQ_PK +</td> +<td> +SEQUENCE_NAME +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_TAGS +</td> +<td> +COOL_REF_TAGS_PK +</td> +<td> +TAG_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_TAGS +</td> +<td> +COOL_REF_TAGS_PK +</td> +<td> +NODE_ID +</td> +<td align="right"> + 2 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_CO_2INDX +</td> +<td> +CHANNEL_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_CO_2INDX +</td> +<td> +OBJECT_ID +</td> +<td align="right"> + 2 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_CSU_3INDX +</td> +<td> +CHANNEL_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_CSU_3INDX +</td> +<td> +IOV_SINCE +</td> +<td align="right"> + 2 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_CSU_3INDX +</td> +<td> +IOV_UNTIL +</td> +<td align="right"> + 3 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS +</td> +<td> +COOL_REF_F0002_IOVS_PK +</td> +<td> +OBJECT_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0002_IOVS_SEQ +</td> +<td> +COOL_REF_F0002_IOVS_SEQ_PK +</td> +<td> +SEQUENCE_NAME +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_CO_2INDX +</td> +<td> +CHANNEL_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_CO_2INDX +</td> +<td> +OBJECT_ID +</td> +<td align="right"> + 2 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_CSU_3INDX +</td> +<td> +CHANNEL_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_CSU_3INDX +</td> +<td> +IOV_SINCE +</td> +<td align="right"> + 2 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_CSU_3INDX +</td> +<td> +IOV_UNTIL +</td> +<td align="right"> + 3 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_PK +</td> +<td> +OBJECT_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_4INDX +</td> +<td> +TAG_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_4INDX +</td> +<td> +CHANNEL_ID +</td> +<td align="right"> + 2 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_4INDX +</td> +<td> +IOV_SINCE +</td> +<td align="right"> + 3 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_4INDX +</td> +<td> +IOV_UNTIL +</td> +<td align="right"> + 4 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_PK +</td> +<td> +TAG_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_PK +</td> +<td> +OBJECT_ID +</td> +<td align="right"> + 2 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_OCSU_4INDX +</td> +<td> +OBJECT_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_OCSU_4INDX +</td> +<td> +CHANNEL_ID +</td> +<td align="right"> + 2 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_OCSU_4INDX +</td> +<td> +IOV_SINCE +</td> +<td align="right"> + 3 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS +</td> +<td> +COOL_REF_F0003_IOVS_OCSU_4INDX +</td> +<td> +IOV_UNTIL +</td> +<td align="right"> + 4 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOVS_SEQ +</td> +<td> +COOL_REF_F0003_IOVS_SEQ_PK +</td> +<td> +SEQUENCE_NAME +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_TAGS +</td> +<td> +COOL_REF_F0003_TAGS_PK +</td> +<td> +TAG_ID +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_TAGS_SEQ +</td> +<td> +COOL_REF_F0003_TAGS_SEQ_PK +</td> +<td> +SEQUENCE_NAME +</td> +<td align="right"> + 1 +</td> +<td> +ASC +</td> +</tr> +</table> +<p> + +<br> + + +<h2>FOREIGN KEY COLUMNS</h2> +<br> +<p> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +TABLE_NAME +</th> +<th scope="col"> +CONSTRAINT_NAME +</th> +<th scope="col"> +R_CONSTRAINT_NAME +</th> +<th scope="col"> +COL_NAME +</th> +<th scope="col"> +COL_POS +</th> +<th scope="col"> +R_COL_NAME +</th> +<th scope="col"> +R_COL_POS +</th> +</tr> +<tr> +<td> +COOL_REF_NODES +</td> +<td> +COOL_REF_NODES_PARENT_FK +</td> +<td> +COOL_REF_NODES_PK +</td> +<td> +NODE_PARENTID +</td> +<td align="right"> + 1 +</td> +<td> +NODE_ID +</td> +<td align="right"> + 1 +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_O_FK +</td> +<td> +COOL_REF_F0003_IOVS_PK +</td> +<td> +OBJECT_ID +</td> +<td align="right"> + 1 +</td> +<td> +OBJECT_ID +</td> +<td align="right"> + 1 +</td> +</tr> +<tr> +<td> +COOL_REF_F0003_IOV2TAG +</td> +<td> +COOL_REF_F0003_IOV2TAG_T_FK +</td> +<td> +COOL_REF_F0003_TAGS_PK +</td> +<td> +TAG_ID +</td> +<td align="right"> + 1 +</td> +<td> +TAG_ID +</td> +<td align="right"> + 1 +</td> +</tr> +</table> +<p> + +<br><hr><br> +<br> +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_DB_ATTRIBUTES</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +DB_ATTRIBUTE_NAME +</td> +<td> +NOT NULL +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +DB_ATTRIBUTE_VALUE +</td> +<td> + +</td> +<td> +VARCHAR2(4000) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_NODES</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +NODE_ID +</td> +<td> +NOT NULL +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +NODE_PARENTID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +NODE_NAME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +NODE_FULLPATH +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +NODE_DESCRIPTION +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +NODE_ISLEAF +</td> +<td> + +</td> +<td> +NUMBER(1) +</td> +</tr> +<tr> +<td> +NODE_INSTIME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +FOLDER_PAYLOADSPEC +</td> +<td> + +</td> +<td> +VARCHAR2(4000) +</td> +</tr> +<tr> +<td> +FOLDER_VERSIONING +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +FOLDER_IOVTABLENAME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +FOLDER_TAGTABLENAME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +FOLDER_IOV2TAGTABLENAME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_NODES_SEQ</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +SEQUENCE_NAME +</td> +<td> +NOT NULL +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +CURRENT_VALUE +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +LASTMOD_DATE +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_TAGS</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +TAG_ID +</td> +<td> +NOT NULL +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +NODE_ID +</td> +<td> +NOT NULL +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +TAG_NAME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +TAG_DESCRIPTION +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +SYS_INSTIME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_F0002_IOVS</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +OBJECT_ID +</td> +<td> +NOT NULL +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +CHANNEL_ID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +IOV_SINCE +</td> +<td> + +</td> +<td> +NUMBER(20) +</td> +</tr> +<tr> +<td> +IOV_UNTIL +</td> +<td> + +</td> +<td> +NUMBER(20) +</td> +</tr> +<tr> +<td> +USER_TAG_ID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +SYS_INSTIME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +ORIGINAL_ID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +NEW_HEAD_ID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_BOOL +</td> +<td> + +</td> +<td> +NUMBER(1) +</td> +</tr> +<tr> +<td> +A_SHRT +</td> +<td> + +</td> +<td> +NUMBER(5) +</td> +</tr> +<tr> +<td> +A_USHRT +</td> +<td> + +</td> +<td> +NUMBER(5) +</td> +</tr> +<tr> +<td> +A_INT +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_UINT +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_LONG +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_ULONG +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_ULONGLONG +</td> +<td> + +</td> +<td> +NUMBER(20) +</td> +</tr> +<tr> +<td> +A_FLOAT +</td> +<td> + +</td> +<td> +BINARY_FLOAT +</td> +</tr> +<tr> +<td> +A_DOUBLE +</td> +<td> + +</td> +<td> +BINARY_DOUBLE +</td> +</tr> +<tr> +<td> +A_STRING +</td> +<td> + +</td> +<td> +VARCHAR2(4000) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_F0002_IOVS_SEQ</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +SEQUENCE_NAME +</td> +<td> +NOT NULL +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +CURRENT_VALUE +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +LASTMOD_DATE +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_F0003_IOV2TAG</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +TAG_ID +</td> +<td> +NOT NULL +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +OBJECT_ID +</td> +<td> +NOT NULL +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +CHANNEL_ID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +IOV_SINCE +</td> +<td> + +</td> +<td> +NUMBER(20) +</td> +</tr> +<tr> +<td> +IOV_UNTIL +</td> +<td> + +</td> +<td> +NUMBER(20) +</td> +</tr> +<tr> +<td> +SYS_INSTIME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_F0003_IOVS</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +OBJECT_ID +</td> +<td> +NOT NULL +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +CHANNEL_ID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +IOV_SINCE +</td> +<td> + +</td> +<td> +NUMBER(20) +</td> +</tr> +<tr> +<td> +IOV_UNTIL +</td> +<td> + +</td> +<td> +NUMBER(20) +</td> +</tr> +<tr> +<td> +USER_TAG_ID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +SYS_INSTIME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +ORIGINAL_ID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +NEW_HEAD_ID +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_BOOL +</td> +<td> + +</td> +<td> +NUMBER(1) +</td> +</tr> +<tr> +<td> +A_SHRT +</td> +<td> + +</td> +<td> +NUMBER(5) +</td> +</tr> +<tr> +<td> +A_USHRT +</td> +<td> + +</td> +<td> +NUMBER(5) +</td> +</tr> +<tr> +<td> +A_INT +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_UINT +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_LONG +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_ULONG +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +A_ULONGLONG +</td> +<td> + +</td> +<td> +NUMBER(20) +</td> +</tr> +<tr> +<td> +A_FLOAT +</td> +<td> + +</td> +<td> +BINARY_FLOAT +</td> +</tr> +<tr> +<td> +A_DOUBLE +</td> +<td> + +</td> +<td> +BINARY_DOUBLE +</td> +</tr> +<tr> +<td> +A_STRING +</td> +<td> + +</td> +<td> +VARCHAR2(4000) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_F0003_IOVS_SEQ</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +SEQUENCE_NAME +</td> +<td> +NOT NULL +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +CURRENT_VALUE +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +LASTMOD_DATE +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_F0003_TAGS</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +TAG_ID +</td> +<td> +NOT NULL +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +TAG_NAME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +TAG_DESCRIPTION +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +SYS_INSTIME +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +</table> +<p> + +</body> +</html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> +<meta name="generator" content="SQL*Plus 10.2.0"> +<style type='text/css'> body {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} p {font:10pt Arial,Helvetica,sans-serif; color:black; background:White;} table,tr,td {font:10pt Arial,Helvetica,sans-serif; color:Black; background:#f7f7e7; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;} th {font:bold 10pt Arial,Helvetica,sans-serif; color:#336699; background:#cccc99; padding:0px 0px 0px 0px;} h1 {font:16pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; border-bottom:1px solid #cccc99; margin-top:0pt; margin-bottom:0pt; padding:0px 0px 0px 0px;} h2 {font:bold 10pt Arial,Helvetica,Geneva,sans-serif; color:#336699; background-color:White; margin-top:4pt; margin-bottom:0pt;} a {font:9pt Arial,Helvetica,sans-serif; color:#663300; background:#ffffff; margin-top:0pt; margin-bottom:0pt; vertical-align:top;}</style><title>SQL*Plus Report</title> +</head> +<body> + +<h2>TABLE COOL_REF_F0003_TAGS_SEQ</h2> +<br> +<table border='1' width='90%' align='center' summary='Script output'> +<tr> +<th scope="col"> +Name +</th> +<th scope="col"> +Null? +</th> +<th scope="col"> +Type +</th> +</tr> +<tr> +<td> +SEQUENCE_NAME +</td> +<td> +NOT NULL +</td> +<td> +VARCHAR2(255) +</td> +</tr> +<tr> +<td> +CURRENT_VALUE +</td> +<td> + +</td> +<td> +NUMBER(10) +</td> +</tr> +<tr> +<td> +LASTMOD_DATE +</td> +<td> + +</td> +<td> +VARCHAR2(255) +</td> +</tr> +</table> +<p> + +</body> +</html> diff --git a/RelationalCool/tests/SchemaDump/schemaDump.cpp b/RelationalCool/tests/SchemaDump/schemaDump.cpp new file mode 100644 index 000000000..5a5eb9a47 --- /dev/null +++ b/RelationalCool/tests/SchemaDump/schemaDump.cpp @@ -0,0 +1,169 @@ +// $Id: schemaDump.cpp,v 1.10 2008-08-27 09:34:30 avalassi Exp $ + +// Include files +#include <iostream> +#include <sstream> +#include <string> +#include "CoolKernel/DatabaseId.h" +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoralBase/AttributeList.h" +#include "src/CoralApplication.h" +#include "src/sleep.h" +#include "src/timeToString.h" +#include "src/uppercaseString.h" +#include "../Common/releaser.h" + +// Environment variable name (connection string) +namespace cool { + const char* COOLTESTDB = "COOLTESTDB"; +} + +// Namespace +using namespace cool; + +// Message output +#define LOG std::cout << "__main " + +//----------------------------------------------------------------------------- + +int main ( int /*argc*/, char* /*argv[]*/ ) +{ + + LOG << "Entering main" << std::endl; + int status = -1; + + try { + + //------------------------ + // DEFINE THE DATABASE ID + //------------------------ + + // Command line input: connection string + std::string dbIdString; + if ( getenv( COOLTESTDB ) ) { + dbIdString = getenv( COOLTESTDB ); + } else { + std::cout << "ERROR! Please provide a connect string " + << "in the environment variable COOLTESTDB" << std::endl; + exit(-1); + } + cool::DatabaseId dbId = dbIdString; + + //------------------------------- + // RETRIEVE THE DATABASE SERVICE + //------------------------------- + + LOG << "Get a handle to the COOL database service" << std::endl; + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + + //-------------------------------- + // DROP THE DATABASE IF IT EXISTS + //-------------------------------- + + // Drop the COOL conditions database if it already exists + LOG << "Drop if it exists the conditions database: " << dbId << std::endl; + dbSvc.dropDatabase( dbId ); + + //----------------------- + // CREATE A NEW DATABASE + //----------------------- + + // Create a new COOL conditions database + LOG << "Create a new conditions database: " << dbId << std::endl; + cool::IDatabasePtr db = dbSvc.createDatabase( dbId ); + LOG << "Conditions database created: " << std::endl; + LOG << "-> Database ID: " << db->databaseId() << std::endl; + std::ostringstream dbAttr; + db->databaseAttributes().toOutputStream( dbAttr ); + LOG << "-> Database attributes: " << dbAttr.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::sleep(1); + + // Create two new folders (one SV, one MV) with the same payload spec + boost::shared_ptr<coral::AttributeListSpecification> + spec( new coral::AttributeListSpecification(), releaser() ); + spec->extend( "A_BOOL", "bool" ); + //spec->extend( "A_CHAR", "char" ); // RAL MySQL error on retrieval + //spec->extend( "A_UCHAR", "unsigned char" ); // Bad RAL MYSQL mapping + spec->extend( "A_SHRT", "short" ); + spec->extend( "A_USHRT", "unsigned short" ); + spec->extend( "A_INT", "int" ); + spec->extend( "A_UINT", "unsigned int" ); + spec->extend( "A_LONG", "long" ); + spec->extend( "A_ULONG", "unsigned long" ); + //spec->extend( "A_LONGLONG", "long long" ); // OCI-22053 must be fixed + spec->extend( "A_ULONGLONG", "unsigned long long" ); + spec->extend( "A_FLOAT", "float" ); + spec->extend( "A_DOUBLE", "double" ); + //spec->extend( "A_LONGDOUBLE", "long double" ); // NO RAL MySQL DEFAULT + spec->extend( "A_STRING", "string" ); + //spec->extend( "A_TOKEN", "Token" ); // THIS WILL NOT BE SUPPORTED! + + // Create SV folder + std::string folderNameSV( "/myfolders/SV" ); + cool::IFolderPtr folderSV = db->createFolder + ( folderNameSV, *spec, "", FolderVersioning::SINGLE_VERSION, true ); + LOG << "Folder created: " << std::endl; + LOG << "-> Folder name: " << folderSV->fullPath() << std::endl; + //std::ostringstream folderAttrSV; + //folderSV->payloadSpecification().print( folderAttrSV ); + //LOG << "-> Folder payload specification: " + // << folderAttrSV.str() << std::endl; + + // Create MV folder + std::string folderNameMV( "/myfolders/MV" ); + cool::IFolderPtr folderMV = db->createFolder + ( folderNameMV, *spec, "", FolderVersioning::MULTI_VERSION, true ); + LOG << "Folder created: " << std::endl; + LOG << "-> Folder name: " << folderMV->fullPath() << std::endl; + //std::ostringstream folderAttrMV; + //folderMV->payloadSpecification().print( folderAttrMV ); + //LOG << "-> Folder payload specification: " + // << folderAttrMV.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::sleep(1); + + /* + // Print the list of folders + std::vector<std::string> folderList; + std::vector<std::string>::iterator folderIt; + folderList = db->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + */ + + // Successful completion + LOG << "Program terminating succesfully" << std::endl; + status = 0; + + } + catch(std::exception& e) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + status = 1; + } + catch(...) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + status = 1; + } + + // Program termination + LOG << "Exiting main" << std::endl; + return status; + +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/tests/SchemaDump/sql/oracleDescTable.sql b/RelationalCool/tests/SchemaDump/sql/oracleDescTable.sql new file mode 100644 index 000000000..a2a651619 --- /dev/null +++ b/RelationalCool/tests/SchemaDump/sql/oracleDescTable.sql @@ -0,0 +1,7 @@ +SET MARKUP HTML ENTMAP OFF +prompt <h2>TABLE &1</h2> +SET MARKUP HTML ENTMAP ON + +desc &2 + +quit; diff --git a/RelationalCool/tests/SchemaDump/sql/oracleDumpConstraints.sql b/RelationalCool/tests/SchemaDump/sql/oracleDumpConstraints.sql new file mode 100755 index 000000000..cfcc8940e --- /dev/null +++ b/RelationalCool/tests/SchemaDump/sql/oracleDumpConstraints.sql @@ -0,0 +1,15 @@ +define owner = "&1"; +define dbname = "&2"; + +--column table_name format a30; +--column constraint_name format a30; +--column constraint_type format a10; +--column r_constraint_name format a30; +--column index_name format a30; + +select table_name, constraint_name, --last_change ddl_date, +constraint_type||' ' type, r_constraint_name, index_name +from all_constraints +where owner = '&owner' +and table_name like '&dbname%' +order by constraint_type, last_change, constraint_name; diff --git a/RelationalCool/tests/SchemaDump/sql/oracleDumpFKColumns.sql b/RelationalCool/tests/SchemaDump/sql/oracleDumpFKColumns.sql new file mode 100755 index 000000000..e88240ef4 --- /dev/null +++ b/RelationalCool/tests/SchemaDump/sql/oracleDumpFKColumns.sql @@ -0,0 +1,29 @@ +define owner = "&1"; +define dbname = "&2"; + +--column table_name format a30; +--column constraint_name format a30; +--column r_constraint_name format a30; +--column ddl_date format a15; +--column col_name format a15; +--column r_col_name format a15; + +select table_name, constraint_name, r_constraint_name, --ddl_date, +col_name, col_pos, r_col_name, r_col_pos +from ( +select c.table_name, c.constraint_name, o.r_constraint_name, +o.last_change ddl_date, +c.column_name col_name, c.position col_pos, +(select r.column_name from user_ind_columns r +where r.index_name=o.r_constraint_name) r_col_name, +(select r.column_position from user_ind_columns r +where r.index_name=o.r_constraint_name) r_col_pos +from all_cons_columns c, all_constraints o +where c.constraint_name=o.constraint_name +and o.owner = '&owner' +and c.owner = '&owner' +and c.table_name like '&dbname%' +and o.constraint_type like 'R' +) order by ddl_date, +table_name, constraint_name, col_pos; + diff --git a/RelationalCool/tests/SchemaDump/sql/oracleDumpIndColumns.sql b/RelationalCool/tests/SchemaDump/sql/oracleDumpIndColumns.sql new file mode 100755 index 000000000..2ccf3fb3f --- /dev/null +++ b/RelationalCool/tests/SchemaDump/sql/oracleDumpIndColumns.sql @@ -0,0 +1,20 @@ +define owner = "&1"; +define dbname = "&2"; + +--column table_name format a30; +--column index_name format a30; +--column ddl_date format a15; +--column col_name format a20; +--column descend format a10; + +select table_name, index_name, --ddl_date, +col_name, col_pos, descend +from ( +select c.table_name, c.index_name, o.last_ddl_time ddl_date, +c.column_name col_name, c.column_position col_pos, c.descend +from all_ind_columns c, all_objects o +where c.index_name=o.object_name +and o.owner = '&owner' +and c.table_owner = '&owner' +and c.table_name like '&dbname%' +) order by ddl_date, table_name, index_name, col_pos; diff --git a/RelationalCool/tests/SchemaDump/sql/oracleDumpIndexes.sql b/RelationalCool/tests/SchemaDump/sql/oracleDumpIndexes.sql new file mode 100755 index 000000000..8f0c93568 --- /dev/null +++ b/RelationalCool/tests/SchemaDump/sql/oracleDumpIndexes.sql @@ -0,0 +1,18 @@ +define owner = "&1"; +define dbname = "&2"; + +--column table_name format a30; +--column index_name format a30; +--column ddl_date format a15; +--column uniqueness format a15; + +select i.table_name, o.object_name index_name, +--o.last_ddl_time ddl_date, +i.uniqueness +from all_objects o, all_indexes i +where o.object_type='INDEX' +and o.object_name=i.index_name +and o.owner = '&owner' +and i.owner = '&owner' +and i.table_name like '&dbname%' +order by o.last_ddl_time, o.object_name; diff --git a/RelationalCool/tests/SchemaDump/sql/oracleDumpTables.sql b/RelationalCool/tests/SchemaDump/sql/oracleDumpTables.sql new file mode 100755 index 000000000..8f10483a5 --- /dev/null +++ b/RelationalCool/tests/SchemaDump/sql/oracleDumpTables.sql @@ -0,0 +1,12 @@ +define owner = "&1"; +define dbname = "&2"; + +--column table_name format a30; +--column ddl_date format a15; + +select object_name table_name --, last_ddl_time ddl_date +from all_objects +where object_type='TABLE' +and owner = '&owner' +and object_name like '&dbname%' +order by last_ddl_time, object_name; diff --git a/RelationalCool/tests/SchemaDump/sql/oracleSchemaDump.sql b/RelationalCool/tests/SchemaDump/sql/oracleSchemaDump.sql new file mode 100644 index 000000000..a4e94799b --- /dev/null +++ b/RelationalCool/tests/SchemaDump/sql/oracleSchemaDump.sql @@ -0,0 +1,35 @@ +set verify off; + +--set linesize 132; +set pagesize 10000; + +SET MARKUP HTML ENTMAP OFF +prompt <h2>TABLES</h2> +SET MARKUP HTML ENTMAP ON +@oracleDumpTables.sql &1 &2 + +SET MARKUP HTML ENTMAP OFF +prompt <h2>INDEXES</h2> +SET MARKUP HTML ENTMAP ON +@oracleDumpIndexes.sql &1 &2 + +SET MARKUP HTML ENTMAP OFF +prompt <h2>CONSTRAINTS</h2> +SET MARKUP HTML ENTMAP ON +@oracleDumpConstraints.sql &1 &2 + +SET MARKUP HTML ENTMAP OFF +prompt <h2>INDEXED COLUMNS</h2> +SET MARKUP HTML ENTMAP ON +@oracleDumpIndColumns.sql &1 &2 + +SET MARKUP HTML ENTMAP OFF +prompt <h2>FOREIGN KEY COLUMNS</h2> +SET MARKUP HTML ENTMAP ON +@oracleDumpFKColumns.sql &1 &2 + +SET MARKUP HTML ENTMAP OFF +prompt <br><hr><br> +SET MARKUP HTML ENTMAP ON + +quit; \ No newline at end of file diff --git a/RelationalCool/tests/SchemaDump/sql/oracleShowTables.sql b/RelationalCool/tests/SchemaDump/sql/oracleShowTables.sql new file mode 100644 index 000000000..714608fb4 --- /dev/null +++ b/RelationalCool/tests/SchemaDump/sql/oracleShowTables.sql @@ -0,0 +1,6 @@ +set pagesize 1000; +select object_name table_name from all_objects +where object_type='TABLE' +and owner='&1' and object_name like '&2%' +order by last_ddl_time, table_name; +exit; diff --git a/RelationalCool/tests/Skeleton/test_Skeleton.cpp b/RelationalCool/tests/Skeleton/test_Skeleton.cpp new file mode 100644 index 000000000..de805476d --- /dev/null +++ b/RelationalCool/tests/Skeleton/test_Skeleton.cpp @@ -0,0 +1,52 @@ +// $Id: test_Skeleton.cpp,v 1.8 2006-05-19 09:39:37 marcocle Exp $ +#include "CoolUnitTest.h" + +// Include files + +namespace cool { + class SkeletonTest:public CoolUnitTest { + + CPPUNIT_TEST_SUITE( SkeletonTest ); + + CPPUNIT_TEST( test_myTest ); + + CPPUNIT_TEST_SUITE_END(); + + public: + + void setUp() { + /// prepare for the test + } + + void tearDown(){ + /// clean up after the test + } + + // ------------------------------------------------------ + // The tests + // ------------------------------------------------------ + + // ------------------------------------------------------ + void test_myTest() { + // ------------------------------------------------------ + + /// do the test + + // -- allowed macros + // CPPUNIT_ASSERT(condition) + // CPPUNIT_ASSERT_MESSAGE(message,condition) + // CPPUNIT_ASSERT_EQUAL(expected,actual) + // CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,actual) + // CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,actual,delta) + // CPPUNIT_ASSERT_THROW( expression, ExceptionType ) + // CPPUNIT_ASSERT_NO_THROW( expression ) + + } + + }; + +CPPUNIT_TEST_SUITE_REGISTRATION( SkeletonTest ); + +} + +COOLTEST_MAIN(SkeletonTest) diff --git a/RelationalCool/tests/Skeleton/test_SkeletonDb.cpp b/RelationalCool/tests/Skeleton/test_SkeletonDb.cpp new file mode 100644 index 000000000..64844a67a --- /dev/null +++ b/RelationalCool/tests/Skeleton/test_SkeletonDb.cpp @@ -0,0 +1,51 @@ +// $Id: test_SkeletonDb.cpp,v 1.1 2006-05-19 09:39:37 marcocle Exp $ +#include "CoolDBUnitTest.h" + +// Include files + +namespace cool { + class SkeletonDbTest:public CoolDBUnitTest { + + CPPUNIT_TEST_SUITE( SkeletonDbTest ); + + CPPUNIT_TEST( test_myTest ); + + CPPUNIT_TEST_SUITE_END(); + + public: + + void setUp() { + /// prepare for the test + } + + void tearDown(){ + /// clean up after the test + } + + // ------------------------------------------------------ + // The tests + // ------------------------------------------------------ + + // ------------------------------------------------------ + void test_myTest() { + // ------------------------------------------------------ + + /// do the test + + // -- allowed macros + // CPPUNIT_ASSERT(condition) + // CPPUNIT_ASSERT_MESSAGE(message,condition) + // CPPUNIT_ASSERT_EQUAL(expected,actual) + // CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,actual) + // CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,actual,delta) + // CPPUNIT_ASSERT_THROW( expression, ExceptionType ) + // CPPUNIT_ASSERT_NO_THROW( expression ) + } + + }; + +CPPUNIT_TEST_SUITE_REGISTRATION( SkeletonDbTest ); + +} + +COOLTEST_MAIN(SkeletonDbTest) diff --git a/RelationalCool/tests/StressTest/stressTest.cpp b/RelationalCool/tests/StressTest/stressTest.cpp new file mode 100644 index 000000000..487fa77a9 --- /dev/null +++ b/RelationalCool/tests/StressTest/stressTest.cpp @@ -0,0 +1,245 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +// $Id: stressTest.cpp,v 1.8 2008-08-27 09:34:30 avalassi Exp $ + +// Include files +#include <iostream> +#include <sstream> +#include <string> +#include "AttributeList/AttributeList.h" +#include "CoolKernel/DatabaseId.h" +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "SealKernel/Exception.h" +#include "SealUtil/SealTimer.h" +#include "SealUtil/TimingItem.h" +#include "src/CoralApplication.h" +#include "src/sleep.h" +#include "src/TimingReport.h" +#include "src/timeToString.h" +#include "src/uppercaseString.h" + +// Namespace +using namespace cool; + +// Message output +#define LOG std::cout << "__main " + +// Global settings +#define DBCREATE false + +//----------------------------------------------------------------------------- + +int main ( int argc, char* argv[] ) +{ + + LOG << "Entering main" << std::endl; + int status = -1; + + // Global settings + bool dbCreate = DBCREATE; + bool dbWrite = dbCreate; + bool dbRead = ! dbWrite; + + try { + + //------------------------ + // DEFINE THE DATABASE ID + //------------------------ + + // Command line input: connection string + std::string dbIdString; + if ( argc == 1 || argc > 2 ) { + LOG << "Usage: " << argv[0] << " dbId" << std::endl; + LOG << "Example: " << argv[0] + << " 'oracle://cooldev;schema=lcg_cool;dbname=STRESTST'" + << std::endl; + return 1; + } else { + dbIdString = argv[1]; + } + cool::DatabaseId dbId = dbIdString; + + //------------------------------- + // RETRIEVE THE DATABASE SERVICE + //------------------------------- + + LOG << "Get a handle to the COOL database service" << std::endl; + CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + + //----------------------- + // CREATE A NEW DATABASE + //----------------------- + + std::string folderName = "/myfolders/SV"; + + if ( dbCreate ) { + + // Drop the COOL conditions database if it already exists + LOG << "Drop if it exists the conditions database: " << dbId + << std::endl; + dbSvc.dropDatabase( dbId ); + + // Create a new COOL conditions database + LOG << "Create a new conditions database: " << dbId << std::endl; + cool::IDatabasePtr db = dbSvc.createDatabase( dbId ); + LOG << "Conditions database created: " << std::endl; + LOG << "-> Database ID: " << db->databaseId() << std::endl; + std::ostringstream dbAttr; + db->databaseAttributes().print( dbAttr ); + LOG << "-> Database attributes: " << dbAttr.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::Sleep(1); + + // Create SV folder + pool::AttributeListSpecification spec; + spec.push_back( "A_STRING", "string" ); + std::string folderNameSV( folderName ); + cool::IFolderPtr folderSV = db->createFolder + ( folderNameSV, spec, "", FolderVersioning::SINGLE_VERSION, true ); + LOG << "Folder created: " << std::endl; + LOG << "-> Folder name: " << folderSV->fullPath() << std::endl; + std::ostringstream folderAttrSV; + folderSV->payloadSpecification().print( folderAttrSV ); + LOG << "-> Folder payload specification: " + << folderAttrSV.str() << std::endl; + + // TEMPORARY? Patch for the ORA-01466 problem: sleep one second + cool::Sleep(1); + + /* + // Print the list of folders + std::vector<std::string> folderList; + std::vector<std::string>::iterator folderIt; + folderList = db->listFolders(); + LOG << "-> List of folders in the database:" << std::endl; + for( folderIt = folderList.begin(); + folderIt != folderList.end(); + folderIt++ ) { + std::cout << *folderIt << std::endl; + } + */ + + } + + //--------------------------- + // OPEN AN EXISTING DATABASE + //--------------------------- + + // Open an existing COOL conditions database + LOG << "Open an existing conditions database: " << dbId << std::endl; + cool::IDatabasePtr db = dbSvc.openDatabase( dbId, false ); + LOG << "Conditions database opened: " << std::endl; + LOG << "-> Database ID: " << db->databaseId() << std::endl; + LOG << "Retrieve folder: " << folderName << std::endl; + IFolderPtr folder = db->getFolder( folderName ); + LOG << "Folder retrieved" << std::endl; + + //------------ + // WRITE DATA + //------------ + + if ( dbWrite ) { + + unsigned nBulks = 100; + unsigned nInBulk = 1000; + + unsigned iBulk; + unsigned iInBulk; + + // HERE WAS A BUG! THIS HAD BEEN FORGOTTEN! :-( + folder->setupStorageBuffer( nInBulk ); + + // Bulk-insert data + LOG << "INSERT DATA" << std::endl; + ValidityKey plusInfinity = ValidityKeyMax; + pool::AttributeList payload( folder->payloadSpecification() ); + payload["A_STRING"].setValue<std::string>( "DUMMY" ); + for ( iBulk=0; iBulk<nBulks; iBulk++ ) { + cool::TimingReport timeReport; + std::stringstream msg; + msg << "Bulk insertion # " << iBulk+1 + << " of " << nInBulk << " IOVS each"; + seal::TimingItem& timeItem = timeReport.item( msg.str() ); + seal::SealTimer* timer = new seal::SealTimer( timeItem ); + LOG << "Bulk insertion #" << iBulk+1 << std::endl; + for ( iInBulk=0; iInBulk<nInBulk; iInBulk++ ) { + ValidityKey bulkSince = iBulk*nInBulk + iInBulk; + folder->storeObject( bulkSince*1000, plusInfinity, payload, 1 ); + } + folder->flushStorageBuffer(); + delete timer; + timeReport.dumpFull(); + } + LOG << "INSERTED DATA" << std::endl; + } + + //------------ + // WRITE DATA + //------------ + + if ( dbRead ) { + + unsigned nBulks = 100; + unsigned nInBulk = 1000; + + unsigned iBulk; + unsigned iInBulk; + + // READ DATA one by one + LOG << "READ DATA (one IOV by one IOV)" << std::endl; + for ( iBulk=0; iBulk<nBulks; iBulk++ ) { + cool::TimingReport timeReport; + std::stringstream msg; + msg << "Reading group # " << iBulk+1 + << " of " << nInBulk << " IOVS each"; + seal::TimingItem& timeItem = timeReport.item( msg.str() ); + seal::SealTimer* timer = new seal::SealTimer( timeItem ); + LOG << "Reading group #" << iBulk+1 << std::endl; + for ( iInBulk=0; iInBulk<nInBulk; iInBulk++ ) { + ValidityKey bulkSince = iBulk*nInBulk + iInBulk; + folder->findObject( bulkSince*1000+1, 1 ); + } + delete timer; + timeReport.dumpFull(); + } + LOG << "READ DATA" << std::endl; + } + + // Successful completion + LOG << "Program terminating succesfully" << std::endl; + status = 0; + + } + catch(seal::Exception& se) + { + LOG << "ERROR! Seal Exception: '" << se << "'" << std::endl; + status = 1; + } + catch(std::exception& e) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + status = 1; + } + catch(...) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + status = 1; + } + + // Program termination + LOG << "Exiting main" << std::endl; + return status; + +} + +//----------------------------------------------------------------------------- + +#endif // NOPORT diff --git a/RelationalCool/tests/TransactionHandling/test_TransactionHandling.cpp b/RelationalCool/tests/TransactionHandling/test_TransactionHandling.cpp new file mode 100644 index 000000000..b0c08bbc6 --- /dev/null +++ b/RelationalCool/tests/TransactionHandling/test_TransactionHandling.cpp @@ -0,0 +1,282 @@ +// PORT -- temporarily disabled: not part of our official test suite +int main() { return 0; } +#ifdef NOPORT + +/** + +@file test_TransactionHandling.cpp + +@author Sven A. Schmidt, Ulrich Moosbrugger + +@date 2005-09-30 + +*/ + + +#include<cppunit/extensions/HelperMacros.h> + +#include "CoolKernel/IFolder.h" +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/Exception.h" +#include "src/RalDatabase.h" +#include "src/RelationalTransaction.h" + +#include "AttributeList/AttributeValueAccessor.h" +using coral::AttributeList; +using coral::AttributeListSpecification; +typedef boost::shared_ptr<AttributeListSpecification> SpecPtr; + +#include "src/sleep.h" + +#include <string> +using std::cout; +using std::cerr; +using std::endl; +using std::string; +using std::stringstream; + +#include <vector> +using std::vector; + +#ifndef WIN32 + +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <pthread.h> + +#else + +#include <windows.h> + +#endif + +namespace cool { + + /// Function to be excuted by the secondary thread. + /// To avoid extra C++ packages for multithreading support, + /// the standard c- pthread library has been used. Therefore + /// this method has to be static. + +#ifndef WIN32 + void* +#else + DWORD WINAPI +#endif + fetch( void* folder ) { + try { + IFolder* ifolder = static_cast<IFolder*>(folder); + ifolder->browseObjects( (ValidityKey)0, ValidityKeyMax ); + } catch ( std::exception& e ) { + cout << "std::exception (secondary thread): " << e.what() << endl; + throw e; + } + +#ifndef WIN32 + pthread_exit(0); +#else + ExitThread(0); +#endif + } + + const char* COOLTESTDB = "COOLTESTDB"; + + /// Multiple transactions test class + class MultipleTransaction : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( MultipleTransaction ); + +#ifndef WIN32 + CPPUNIT_TEST( test_Fork ); +#endif + CPPUNIT_TEST( test_RelationalTransaction ); + CPPUNIT_TEST( test_MultiThread ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + AttributeListSpecification mixedPayloadSpec; + string connectString; + IDatabasePtr db; + + //---------------------------------------------------------------------------- + + /// Start two RAL transactions to provoke a seal exception + void test_RelationalTransaction() + { + bool readOnly = true; + RalDatabase* ralDb; // safely cast pointer to db + ralDb = dynamic_cast<RalDatabase*>(db.get()); + + try { + RelationalTransaction t1( ralDb->transactionMgr(), readOnly ); + RelationalTransaction t2( ralDb->transactionMgr(), readOnly ); + CPPUNIT_FAIL( "expected exception" ); + } catch ( std::exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "expected transaction related exception", + string( "Could not start a new read-only transaction" ), + string( e.what() ) ); + } + } + + +#ifndef WIN32 + /// Test transaction behavior from a forked process. Note that while this + /// (currently) works in the read only case, it probably does because + /// the read only case is safe. Forking copies the process and we are + /// probably tricking RAL to think that it has only one transaction open + /// as we copy its state with only one transaction open. + /// Most likely this will break horribly if one process does writing. This + /// should be implemented in a separate test. + /// There is no easy way to assert the test condition with CPPUNIT macros. + /// It therefore relies on the printout to be inspected. + void test_Fork() + { + cout << "** test_Fork start **" << endl; + + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + folder->setupStorageBuffer(); + for ( long i = 0; i < 5000; ++i ) { + folder->storeObject( (ValidityKey)i, ValidityKeyMax, + mixedPayload( i ) ); + } + folder->flushStorageBuffer(); + + // Get a child process. + int pid, status; + if ( (pid = fork()) < 0 ) + { + cerr << "Could not fork process!" << endl; + exit(1); + } + + // The child executes the code inside the if. + if (pid == 0) + { + cout << "Child process (PID " << pid << ") starts browseObjects" + << endl; + folder->browseObjects( (ValidityKey)0, ValidityKeyMax ); + cout << "Finished child process " << pid << endl; + exit(1); + } + + // The parent executes the same browseObject and then waits. + if (pid != 0) + { + cout << "Parent process (PID " << pid << " ) starts browseObjects" + << endl; + folder->browseObjects( (ValidityKey)0, ValidityKeyMax ); + cout << "Finished parent process " << pid << endl; + } + + while ( wait(&status) != pid); + + cout << "This test passed if the second process successfully started a " + << "browseObjects operation before the first process finished its " + << "own." << endl; + cout << "** test_Fork end **" << endl; + } +#endif + + /// Check on multi threaded access + /// and provoke a seal exception + void test_MultiThread() { + IFolderPtr folder = db->createFolder( "/myfolder", mixedPayloadSpec ); + + folder->setupStorageBuffer(); + for ( long i = 0; i < 5000; ++i ) { + folder->storeObject( (ValidityKey)i, ValidityKeyMax, + mixedPayload( i ) ); + } + folder->flushStorageBuffer(); + + // pthread_create expects void* as argument + void* threadFolderPtr = folder.get(); +#ifndef WIN32 + pthread_t helper; + pthread_create(&helper, NULL, fetch, threadFolderPtr ); +#else + HANDLE a_thread; + DWORD a_threadId; + DWORD thread_result; + a_thread = CreateThread(NULL, 0, fetch, threadFolderPtr,0, &a_threadId); +#endif + + try { + // try to assure that the main thread tries to open the + // second transaction and hence throws the exception + // which can be caught by the CPPUNIT framework + // If 1s is not sufficient, increase the number of objects + // in the folder. + cool::sleep(1); + folder->browseObjects( (ValidityKey)0, ValidityKeyMax ); + CPPUNIT_FAIL( "expected exception" ); + } catch ( std::exception& e ) { + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "expected transaction related exception", + string( "Could not start a new read-only transaction" ), + string( e.what() ) ); + } + +#ifndef WIN32 + pthread_join(helper, NULL); +#else + if (WaitForSingleObject(a_thread, INFINITE) != WAIT_OBJECT_0) { + CPPUNIT_FAIL("Thread join failed"); + } +#endif + } + + /// Creates a dummy payload AttributeList for a given index + AttributeList mixedPayload( int index ) { + AttributeList payload( mixedPayloadSpec ); + payload["I"].setValue<int>( index ); + return payload; + } + + + /// Setup prerequisites for all unit tests + void setUp() + { + if ( mixedPayloadSpec.size() == 0 ) + { + mixedPayloadSpec.push_back("I","int"); + } + + if ( getenv( COOLTESTDB ) ) { + connectString = getenv( COOLTESTDB ); + } else { + cout << "Please provide a connect string by " + << "specifying one in the environment variable COOLTESTDB, e.g." + << endl; + cout << "setenv COOLTESTDB " + << "\"oracle://devdb10;schema=lcg_cool;dbname=COOLTEST\"" << endl; + cout << "Aborting test" << endl; + exit(-1); + } + + static CoralApplication app; + IDatabaseSvc& dbSvc = app.databaseService(); + dbSvc.dropDatabase( connectString ); + db = dbSvc.createDatabase( connectString ); + } + + void tearDown() { + db.reset(); + } + + }; + + CPPUNIT_TEST_SUITE_REGISTRATION( MultipleTransaction ); + +} // namespace + +// sas: This file is from the OPAL package I believe. It allows for +// shorter test classes and prepares the test class for OPAL +#include<CppUnit_testdriver.icpp> + +#endif // NOPORT diff --git a/RelationalCool/tests/VersionNumber/test_VersionNumber.cpp b/RelationalCool/tests/VersionNumber/test_VersionNumber.cpp new file mode 100644 index 000000000..3bc24262e --- /dev/null +++ b/RelationalCool/tests/VersionNumber/test_VersionNumber.cpp @@ -0,0 +1,114 @@ +// $Id: test_VersionNumber.cpp,v 1.2 2006-11-28 08:35:30 avalassi Exp $ +#include "CoolUnitTest.h" + +// Include files +#include "../../src/VersionNumber.h" + +namespace cool { + class VersionNumberTest:public CoolUnitTest { + + CPPUNIT_TEST_SUITE( VersionNumberTest ); + + CPPUNIT_TEST( test_constructor ); + CPPUNIT_TEST( test_conversion ); + CPPUNIT_TEST( test_print ); + CPPUNIT_TEST( test_comparison ); + + CPPUNIT_TEST_SUITE_END(); + + public: + + void setUp() { + /// prepare for the test + } + + void tearDown(){ + /// clean up after the test + } + + // ------------------------------------------------------ + // The tests + // ------------------------------------------------------ + + // -- allowed macros + // CPPUNIT_ASSERT(condition) + // CPPUNIT_ASSERT_MESSAGE(message,condition) + // CPPUNIT_ASSERT_EQUAL(expected,actual) + // CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,actual) + // CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,actual,delta) + // CPPUNIT_ASSERT_THROW( expression, ExceptionType ) + // CPPUNIT_ASSERT_NO_THROW( expression ) + + // ------------------------------------------------------ + void test_constructor() { + // ------------------------------------------------------ + VersionNumber a("1.2.3"); + CPPUNIT_ASSERT_MESSAGE("char * constructor failed", + a.majorVersion() == 1 + && a.minorVersion() == 2 + && a.patchVersion() == 3); + + VersionNumber b(std::string("3.4.5")); + CPPUNIT_ASSERT_MESSAGE("std::string constructor failed", + b.majorVersion() == 3 + && b.minorVersion() == 4 + && b.patchVersion() == 5); + + CPPUNIT_ASSERT_THROW( VersionNumber("x.y") , std::runtime_error ); + } + + // ------------------------------------------------------ + void test_conversion() { + // ------------------------------------------------------ + VersionNumber a("1.2.3"); + std::string s = a; + CPPUNIT_ASSERT( s == "1.2.3" ); + } + + // ------------------------------------------------------ + void test_print() { + // ------------------------------------------------------ + VersionNumber a("9.8.7"); + std::ostringstream o; + o << a; + CPPUNIT_ASSERT( o.str() == (std::string)a ); + } + +#define TEST_CMP_LT(A,B) CPPUNIT_ASSERT_MESSAGE \ + ( A " < " B, VersionNumber(A) < B ) + +#define TEST_CMP_EQ(A,B) CPPUNIT_ASSERT_MESSAGE \ + ( A " == " B, VersionNumber(A) == B ) + +#define TEST_CMP_GT(A,B) CPPUNIT_ASSERT_MESSAGE \ + ( A " > " B, VersionNumber(A) > B ) + +#define TEST_CMP(A,B) TEST_CMP_LT(A,B);\ + TEST_CMP_EQ(A,A);\ + TEST_CMP_EQ(B,B);\ + TEST_CMP_GT(B,A); + // ------------------------------------------------------ + void test_comparison() { + // ------------------------------------------------------ + + TEST_CMP( "1.0.0", "2.0.0" ); + TEST_CMP( "0.1.0", "0.2.0" ); + TEST_CMP( "0.0.1", "0.0.2" ); + + TEST_CMP( "0.999.0", "1.0.2" ); + TEST_CMP( "0.0.999", "0.1.0" ); + + } + +#undef TEST_CMP_LT +#undef TEST_CMP_EQ +#undef TEST_CMP_GT +#undef TEST_CMP + + }; + +CPPUNIT_TEST_SUITE_REGISTRATION( VersionNumberTest ); + +} + +COOLTEST_MAIN(VersionNumberTest) diff --git a/RelationalCool/tests/authentication.xml b/RelationalCool/tests/authentication.xml new file mode 100755 index 000000000..de4a031e7 --- /dev/null +++ b/RelationalCool/tests/authentication.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" ?> +<connectionlist> + +<!-- Oracle server for COOL tests --> +<connection name="oracle://lcg_cool_nightly/lcg_cool_nightly"> + <parameter name="user" value="lcg_cool_nightly" /> + <parameter name="password" value="PASSWORD" /> +</connection> + +<!-- MySQL server for COOL tests --> +<connection name="mysql://itrac424.cern.ch:3306/LCG_COOL_NIGHTLY"> + <parameter name="user" value="LCG_COOL_NIGHTLY" /> + <parameter name="password" value="PASSWORD" /> +</connection> + +</connectionlist> diff --git a/RelationalCool/tests/dblookup.xml b/RelationalCool/tests/dblookup.xml new file mode 100644 index 000000000..b2611d913 --- /dev/null +++ b/RelationalCool/tests/dblookup.xml @@ -0,0 +1,124 @@ +<?xml version="1.0" ?> +<servicelist> + + + <logicalservice name="Oracle-avalassi"> + <service name="oracle://lcg_cool_nightly/lcg_cool" accessMode="update" authentication="password" /> + </logicalservice> + + <logicalservice name="Oracle-marcocle"> + <service name="oracle://lcg_cool_nightly/marcocle" accessMode="update" authentication="password" /> + <!--service name="oracle://devdb10/lhcb_lcg_cool_dev" accessMode="update" authentication="password" /--> + </logicalservice> + + <logicalservice name="Oracle-clemenci"> + <service name="oracle://lcg_cool_nightly/marcocle" accessMode="update" authentication="password" /> + </logicalservice> + + <logicalservice name="Oracle-sas"> + <service name="oracle://devdb10/atlas_cool_sas" accessMode="update" authentication="password" /> + </logicalservice> + + + <logicalservice name="MySQL-avalassi"> + <service name="mysql://itrac424.cern.ch:3306/LCG_COOL" accessMode="update" authentication="password" /> + <!--service name="mysql://pcitdb59/COOLDB" accessMode="update" authentication="password" /--> + <!--service name="mysql://pclhcb55.cern.ch/AVALASSI" accessMode="update" authentication="password" /--> + </logicalservice> + + <logicalservice name="MySQL-marcocle"> + <service name="mysql://pclhcb55.cern.ch/MARCOCLE" accessMode="update" authentication="password" /> + </logicalservice> + + <logicalservice name="MySQL-clemenci"> + <service name="mysql://pclhcb55.cern.ch/MARCOCLE" accessMode="update" authentication="password" /> + </logicalservice> + + <logicalservice name="MySQL-sas"> + <service name="mysql://localhost/cooltest" accessMode="update" authentication="password" /> + </logicalservice> + + + <!-- Oracle on pdbr, Frontier and squid on frontier3d:8080 and :8000 --> + <logicalservice name="Frontier-avalassi"> + <!--service name="frontier://frontier3d:8080/lcg_cool_nightly/lcg_cool" accessMode="readonly" authentication="password" /--> + <!-- DISABLE THE CLIENT-SIDE CACHE (clientcachemaxresultsize=0) --> + <service name="frontier://(serverurl=http://frontier3d:8080/lcg_cool_nightly)(clientcachemaxresultsize=0)/lcg_cool" accessMode="readonly" authentication="password" /> + <service name="oracle://lcg_cool_nightly/lcg_cool" accessMode="update" authentication="password" /> + </logicalservice> + + <logicalservice name="FrontierCache-avalassi"> + <!--service name="frontier://frontier3d:8000/lcg_cool_nightly/lcg_cool" accessMode="readonly" authentication="password" /--> + <!-- DISABLE THE CLIENT-SIDE CACHE (clientcachemaxresultsize=0) --> + <!-- USE ENV VARIABLE FRONTIER_FORCERELOAD TO DETERMINE RELOAD SETTINGS --> + <service name="frontier://(serverurl=http://frontier3d:8000/lcg_cool_nightly)(clientcachemaxresultsize=0)/lcg_cool" accessMode="readonly" authentication="password" /> + <!-- DISABLE THE CLIENT-SIDE CACHE (clientcachemaxresultsize=0) --> + <!-- DO NOT FORCE IMMEDIATE RELOAD OF ANY QUERIES (forcereload=none) --> + <!--service name="frontier://(serverurl=http://frontier3d:8000/lcg_cool_nightly)(clientcachemaxresultsize=0)(forcereload=none)/lcg_cool" accessMode="readonly" authentication="password" /--> + <!-- DISABLE THE CLIENT-SIDE CACHE (clientcachemaxresultsize=0) --> + <!-- FORCE IMMEDIATE RELOAD OF SHORT-LIVED QUERIES (forcereload=short) --> + <!--service name="frontier://(serverurl=http://frontier3d:8000/lcg_cool_nightly)(clientcachemaxresultsize=0)(forcereload=short)/lcg_cool" accessMode="readonly" authentication="password" /--> + <!-- DISABLE THE CLIENT-SIDE CACHE (clientcachemaxresultsize=0) --> + <!-- FORCE IMMEDIATE RELOAD OF ALL QUERIES (forcereload=long) --> + <!--service name="frontier://(serverurl=http://frontier3d:8000/lcg_cool_nightly)(clientcachemaxresultsize=0)(forcereload=long)/lcg_cool" accessMode="readonly" authentication="password" /--> + <service name="oracle://lcg_cool_nightly/lcg_cool" accessMode="update" authentication="password" /> + </logicalservice> + + <!--logicalservice name="FrontierR-avalassi"> + <service name="frontier://frontier3d:8080/lcg_cool_nightly/lcg_cool" accessMode="readonly" authentication="password" /> + </logicalservice--> + + <!-- Oracle on pdbr, Frontier and squid on frontier3d:8080 and :8000 --> + <logicalservice name="Frontier-marcocle"> + <!--service name="frontier://frontier3d:8080/lcg_cool_nightly/marcocle" accessMode="readonly" authentication="password" /--> + <service name="frontier://(serverurl=http://frontier3d:8080/lcg_cool_nightly)(clientcachemaxresultsize=0)/marcocle" accessMode="readonly" authentication="password" /> + <service name="oracle://lcg_cool_nightly/marcocle" accessMode="update" authentication="password" /> + </logicalservice> + + <logicalservice name="FrontierCache-marcocle"> + <service name="frontier://(serverurl=http://frontier3d:8000/lcg_cool_nightly)(clientcachemaxresultsize=0)/marcocle" accessMode="readonly" authentication="password" /> + <service name="oracle://lcg_cool_nightly/marcocle" accessMode="update" authentication="password" /> + </logicalservice> + + <!--logicalservice name="FrontierR-marcocle"> + <service name="frontier://frontier3d:8080/lcg_cool_nightly/marcocle" accessMode="readonly" authentication="password" /> + </logicalservice--> + + <!-- Coral Server tests --> + <logicalservice name="/tests/db_ora/admin"> + <service name="oracle://lcg_cool_nightly/lcg_cool" accessMode="update" authentication="password" /> + </logicalservice> + <logicalservice name="/tests/db_cor/admin"> + <service name="coral://localhost:8080|oracle://lcg_cool_nightly/lcg_cool" accessMode="update" authentication="password" /> + </logicalservice> + + <!-- COOL nightly tests - START --> + + <logicalservice name="Oracle-lcgnight"> + <service name="oracle://lcg_cool_nightly/lcg_cool_nightly" accessMode="update" authentication="password" /> + </logicalservice> + + <logicalservice name="MySQL-lcgnight"> + <service name="mysql://itrac424.cern.ch:3306/LCG_COOL_NIGHTLY" accessMode="update" authentication="password" /> + </logicalservice> + + <logicalservice name="Frontier-lcgnight"> + <!--service name="frontier://frontier3d:8080/lcg_cool_nightly/lcg_cool_nightly" accessMode="readonly" authentication="password" /--> + <!-- DISABLE THE CLIENT-SIDE CACHE (clientcachemaxresultsize=0) --> + <service name="frontier://(serverurl=http://frontier3d:8080/lcg_cool_nightly)(clientcachemaxresultsize=0)/lcg_cool_nightly" accessMode="readonly" authentication="password" /> + <service name="oracle://lcg_cool_nightly/lcg_cool_nightly" accessMode="update" authentication="password" /> + </logicalservice> + + <logicalservice name="FrontierCache-lcgnight"> + <service name="frontier://(serverurl=http://frontier3d:8000/lcg_cool_nightly)(clientcachemaxresultsize=0)/lcg_cool_nightly" accessMode="readonly" authentication="password" /> + <service name="oracle://lcg_cool_nightly/lcg_cool_nightly" accessMode="update" authentication="password" /> + </logicalservice> + + <!-- This is only needed for LCG54 (dev3) tests --> + <logicalservice name="FrontierR-lcgnight"> + <service name="frontier://frontier3d:8080/lcg_cool_nightly/lcg_cool_nightly" accessMode="readonly" authentication="password" /> + </logicalservice> + + <!-- COOL nightly tests - END --> + +</servicelist> diff --git a/RelationalCool/tests/seal.opts b/RelationalCool/tests/seal.opts new file mode 100644 index 000000000..a9a384d9a --- /dev/null +++ b/RelationalCool/tests/seal.opts @@ -0,0 +1,19 @@ +// SEAL MessageService verbosity level +// Verbose=1, Debug=2, Info=3, Warning=4, Error=5, Fatal=6 +SEAL/Services/MessageService.OutputLevel=2; + +// SEAL MessageService output format +// Note: MessageService.cpp implements reportMessage() using Msg::LevelTxt[] +// Note: MessageStream.cpp defines Msg::LevelTxt[] using lowercase strings +SEAL/Services/MessageService.Format="%-36s %-8s %s"; + +// CORAL XMLAuthenticationService authentication file +// The path to this file may be set in the CORAL_AUTH_PATH environment variable +CORAL/Services/XMLAuthenticationService.AuthenticationFile="$CORAL_AUTH_PATH/authentication.xml"; + +// CORAL XMLLookupService db file +// The path to this file may be set in the CORAL_DBLOOKUP_PATH environment variable +CORAL/Services/XMLLookupService.LookupFile="$CORAL_DBLOOKUP_PATH/dblookup.xml"; + +// CORAL ConnectionService connection pool purge frequency (seconds) +CORAL/Services/ConnectionService.PoolCleanUpPeriod = 1; diff --git a/RelationalCool/tests/seal.opts.error b/RelationalCool/tests/seal.opts.error new file mode 100644 index 000000000..44f7fb580 --- /dev/null +++ b/RelationalCool/tests/seal.opts.error @@ -0,0 +1,19 @@ +// SEAL MessageService verbosity level +// Verbose=1, Debug=2, Info=3, Warning=4, Error=5, Fatal=6 +SEAL/Services/MessageService.OutputLevel=5; + +// SEAL MessageService output format +// Note: MessageService.cpp implements reportMessage() using Msg::LevelTxt[] +// Note: MessageStream.cpp defines Msg::LevelTxt[] using lowercase strings +SEAL/Services/MessageService.Format="%-36s %-8s %s"; + +// CORAL XMLAuthenticationService authentication file +// The path to this file may be set in the CORAL_AUTH_PATH environment variable +CORAL/Services/XMLAuthenticationService.AuthenticationFile="$CORAL_AUTH_PATH/authentication.xml"; + +// CORAL XMLLookupService db file +// The path to this file may be set in the CORAL_DBLOOKUP_PATH environment variable +CORAL/Services/XMLLookupService.LookupFile="$CORAL_DBLOOKUP_PATH/dblookup.xml"; + +// CORAL ConnectionService connection pool purge frequency (seconds) +CORAL/Services/ConnectionService.PoolCleanUpPeriod = 1; diff --git a/RelationalCool/tests/seal.opts.info b/RelationalCool/tests/seal.opts.info new file mode 100644 index 000000000..329ac1961 --- /dev/null +++ b/RelationalCool/tests/seal.opts.info @@ -0,0 +1,19 @@ +// SEAL MessageService verbosity level +// Verbose=1, Debug=2, Info=3, Warning=4, Error=5, Fatal=6 +SEAL/Services/MessageService.OutputLevel=3; + +// SEAL MessageService output format +// Note: MessageService.cpp implements reportMessage() using Msg::LevelTxt[] +// Note: MessageStream.cpp defines Msg::LevelTxt[] using lowercase strings +SEAL/Services/MessageService.Format="%-36s %-8s %s"; + +// CORAL XMLAuthenticationService authentication file +// The path to this file may be set in the CORAL_AUTH_PATH environment variable +CORAL/Services/XMLAuthenticationService.AuthenticationFile="$CORAL_AUTH_PATH/authentication.xml"; + +// CORAL XMLLookupService db file +// The path to this file may be set in the CORAL_DBLOOKUP_PATH environment variable +CORAL/Services/XMLLookupService.LookupFile="$CORAL_DBLOOKUP_PATH/dblookup.xml"; + +// CORAL ConnectionService connection pool purge frequency (seconds) +CORAL/Services/ConnectionService.PoolCleanUpPeriod = 1; diff --git a/RelationalCool/tests/seal.opts.verbose b/RelationalCool/tests/seal.opts.verbose new file mode 100644 index 000000000..ae374f8c9 --- /dev/null +++ b/RelationalCool/tests/seal.opts.verbose @@ -0,0 +1,19 @@ +// SEAL MessageService verbosity level +// Verbose=1, Debug=2, Info=3, Warning=4, Error=5, Fatal=6 +SEAL/Services/MessageService.OutputLevel=1; + +// SEAL MessageService output format +// Note: MessageService.cpp implements reportMessage() using Msg::LevelTxt[] +// Note: MessageStream.cpp defines Msg::LevelTxt[] using lowercase strings +SEAL/Services/MessageService.Format="%-36s %-8s %s"; + +// CORAL XMLAuthenticationService authentication file +// The path to this file may be set in the CORAL_AUTH_PATH environment variable +CORAL/Services/XMLAuthenticationService.AuthenticationFile="$CORAL_AUTH_PATH/authentication.xml"; + +// CORAL XMLLookupService db file +// The path to this file may be set in the CORAL_DBLOOKUP_PATH environment variable +CORAL/Services/XMLLookupService.LookupFile="$CORAL_DBLOOKUP_PATH/dblookup.xml"; + +// CORAL ConnectionService connection pool purge frequency (seconds) +CORAL/Services/ConnectionService.PoolCleanUpPeriod = 1; diff --git a/RelationalCool/tests/seal.opts.warning b/RelationalCool/tests/seal.opts.warning new file mode 100644 index 000000000..492314cad --- /dev/null +++ b/RelationalCool/tests/seal.opts.warning @@ -0,0 +1,19 @@ +// SEAL MessageService verbosity level +// Verbose=1, Debug=2, Info=3, Warning=4, Error=5, Fatal=6 +SEAL/Services/MessageService.OutputLevel=4; + +// SEAL MessageService output format +// Note: MessageService.cpp implements reportMessage() using Msg::LevelTxt[] +// Note: MessageStream.cpp defines Msg::LevelTxt[] using lowercase strings +SEAL/Services/MessageService.Format="%-36s %-8s %s"; + +// CORAL XMLAuthenticationService authentication file +// The path to this file may be set in the CORAL_AUTH_PATH environment variable +CORAL/Services/XMLAuthenticationService.AuthenticationFile="$CORAL_AUTH_PATH/authentication.xml"; + +// CORAL XMLLookupService db file +// The path to this file may be set in the CORAL_DBLOOKUP_PATH environment variable +CORAL/Services/XMLLookupService.LookupFile="$CORAL_DBLOOKUP_PATH/dblookup.xml"; + +// CORAL ConnectionService connection pool purge frequency (seconds) +CORAL/Services/ConnectionService.PoolCleanUpPeriod = 1; diff --git a/RelationalCool/tests/setupLocalTns.csh b/RelationalCool/tests/setupLocalTns.csh new file mode 100644 index 000000000..04f8dd025 --- /dev/null +++ b/RelationalCool/tests/setupLocalTns.csh @@ -0,0 +1 @@ +setenv TNS_ADMIN /$LOCALRT/src/RelationalCool/tests diff --git a/RelationalCool/tests/sqlnet.ora b/RelationalCool/tests/sqlnet.ora new file mode 100644 index 000000000..169f717d9 --- /dev/null +++ b/RelationalCool/tests/sqlnet.ora @@ -0,0 +1,2 @@ +IFILE = /afs/cern.ch/project/oracle/admin/sqlnet.ora + diff --git a/RelationalCool/tests/test_SealPluginDump.sh b/RelationalCool/tests/test_SealPluginDump.sh new file mode 100755 index 000000000..1167e4717 --- /dev/null +++ b/RelationalCool/tests/test_SealPluginDump.sh @@ -0,0 +1,183 @@ +#! /bin/bash + +# Welcome printout +echo "Executing SealPluginDump test" + +# Check SCRAM vs CMT +if [ -z "$SCRAM_ARCH" ] && [ -n "$CMTCONFIG" ]; then + echo "SealPluginDump test will use CMT" + export SCRAM_ARCH="$CMTCONFIG" + export USECMT=yes +else + echo "SealPluginDump test will use SCRAM" +fi + +# Check O/S +if [ "$OS" = "Windows_NT" ]; then + if [ "${SCRAM_ARCH:0:5}" != "win32" ]; then + echo "ERROR! Invalid SCRAM_ARCH $SCRAM_ARCH on $OS for $0" + exit 1 + fi +fi + +# Make sure LOCALRT is defined +if [ -z "$USECMT" ]; then + export PATH=/afs/cern.ch/sw/lcg/app/spi/scram:"${PATH}" + eval `scram runtime -sh` + if [ "$LOCALRT" = "" ] ; then + echo "ERROR! Undefined LOCALRT - are you in a valid SCRAM directory?" + exit 1 + fi +else + export LOCALRT=`dirname $0` + export LOCALRT=`cd $LOCALRT/../../..; pwd` +fi +export theLOCALRT=$LOCALRT + +# Keep the current SEAL options file if already defined +export SEAL_CONFIGURATION_FILE_OLD=${SEAL_CONFIGURATION_FILE} + +# Load common functions +if [ -r $theLOCALRT/config/test_functions.sh ] ; then + . $theLOCALRT/config/test_functions.sh +elif [ -r $theLOCALRT/src/config/scram/test_functions.sh ] ; then + . $theLOCALRT/src/config/scram/test_functions.sh +else + echo "ERROR! Cannot find common test functions" + exit 1 +fi + +# Prepare the environment +set_preliminar_env +if [ -z "$USECMT" ]; then + eval `scram runtime -sh` + export SEAL_CONFIGURATION_FILE=${theLOCALRT}/src/RelationalCool/tests/seal.opts.error + export unixToWinPathWine=${theLOCALRT}/src/config/scram/unixToWinPathWine.py +else + source ${theLOCALRT}/src/config/cmt/setup.sh # NB this redefines LOCALRT +fi +fix_win_paths +if [ "${SCRAM_ARCH:0:3}" = "win" ]; then + echo Time zone setting is TZ=\"$TZ\" +fi + +# Keep the current SEAL options file if already defined +if [ "$SEAL_CONFIGURATION_FILE_OLD" != "" ] ; then + export SEAL_CONFIGURATION_FILE=$SEAL_CONFIGURATION_FILE_OLD +fi + +# Delete the COOL cache to test this test script +###\rm $theLOCALRT/SCRAM/$SCRAM_ARCH/lib/modules/.cache + +# Execute SealPluginDump once to load the COOL plugins if not yet done +cmd_wrapper SealPluginDump > /dev/null 2>&1 + +# Make a temporary directory +tmpDir=`mktemp -d -t tmp.XXXXXXXXXX` + +# Execute SealPluginDump again and check the output +( cmd_wrapper SealPluginDump > ${tmpDir}/stdout ) 2> ${tmpDir}/stderr + +# Fix problems under Wine +dos2unix ${tmpDir}/stdout > /dev/null 2>&1 +dos2unix ${tmpDir}/stderr > /dev/null 2>&1 + +# Analyse stderr: this should be empty +###echo "*** STDERR: ***"; more ${tmpDir}/stderr +if [ -s ${tmpDir}/stderr ]; then + more ${tmpDir}/stderr + echo "ERROR! Standard error is not empty!" + echo "" + echo "Failures !!!" + echo "Run: 1 Failure total: 1 Failures: 1 Errors: 0" + echo "[OVAL] Cppunit-result =1" + \rm -rf ${tmpDir} + exit 1 +fi + +# Analyse stdout: this should contain all relevant plugins +###echo "*** STDOUT: ***"; more ${tmpDir}/stdout +if [ "${SCRAM_ARCH:0:3}" = "win" ]; then + # Windows: all plugins but Frontier and LFC + expPlugins="COOL/Services/DatabaseService\ + CORAL/RelationalPlugins/mysql\ + CORAL/RelationalPlugins/oracle\ + CORAL/RelationalPlugins/sqlite\ + CORAL/Services/ConnectionService\ + CORAL/Services/EnvironmentAuthenticationService\ + CORAL/Services/MonitoringService\ + CORAL/Services/RelationalService\ + CORAL/Services/XMLAuthenticationService\ + CORAL/Services/XMLLookupService\ + CORAL/mysql/TypeConverter\ + SEAL/Services/ConfigurationService\ + SEAL/Services/DictionaryService\ + SEAL/Services/MessageService\ + SEAL/Services/PropertyCatalogue" +elif [ "${SCRAM_ARCH:0:3}" = "osx" ]; then + # MacOSX: all plugins but Oracle and LFC + expPlugins="COOL/Services/DatabaseService\ + CORAL/RelationalPlugins/frontier\ + CORAL/RelationalPlugins/mysql\ + CORAL/RelationalPlugins/sqlite\ + CORAL/Services/ConnectionService\ + CORAL/Services/EnvironmentAuthenticationService\ + CORAL/Services/MonitoringService\ + CORAL/Services/RelationalService\ + CORAL/Services/XMLAuthenticationService\ + CORAL/Services/XMLLookupService\ + CORAL/mysql/TypeConverter\ + SEAL/Services/ConfigurationService\ + SEAL/Services/DictionaryService\ + SEAL/Services/MessageService\ + SEAL/Services/PropertyCatalogue" +else + # Linux: all plugins + expPlugins="COOL/Services/DatabaseService\ + CORAL/RelationalPlugins/frontier\ + CORAL/RelationalPlugins/mysql\ + CORAL/RelationalPlugins/oracle\ + CORAL/RelationalPlugins/sqlite\ + CORAL/Services/ConnectionService\ + CORAL/Services/EnvironmentAuthenticationService\ + CORAL/Services/LFCLookupService\ + CORAL/Services/LFCReplicaService\ + CORAL/Services/MonitoringService\ + CORAL/Services/RelationalService\ + CORAL/Services/XMLAuthenticationService\ + CORAL/Services/XMLLookupService\ + CORAL/mysql/TypeConverter\ + SEAL/Services/ConfigurationService\ + SEAL/Services/DictionaryService\ + SEAL/Services/MessageService\ + SEAL/Services/PropertyCatalogue" +fi +obsPlugins=`cat ${tmpDir}/stdout | grep -v "Category Loadable Component:"` +for expPlugin in $expPlugins; do + found=0 + ###echo Looking for \"$expPlugin\" + for obsPlugin in $obsPlugins; do + ###echo Testing \"$obsPlugin\" + if [ $expPlugin = $obsPlugin ]; then + found=1 + echo Found $expPlugin + fi + done + if [ $found != 1 ]; then + more ${tmpDir}/stdout + echo "ERROR! Plugin $expPlugin not found!" + echo "" + echo "Failures !!!" + echo "Run: 1 Failure total: 1 Failures: 1 Errors: 0" + echo "[OVAL] Cppunit-result =1" + \rm -rf ${tmpDir} + exit 1 + fi +done + +# Success +echo "" +echo "OK (1)" +echo "[OVAL] Cppunit-result =0" +\rm -rf ${tmpDir} +exit 0 diff --git a/RelationalCool/tests/tnsnames.ora b/RelationalCool/tests/tnsnames.ora new file mode 100644 index 000000000..8dd5b0863 --- /dev/null +++ b/RelationalCool/tests/tnsnames.ora @@ -0,0 +1,24 @@ +# Add here the description of your private server +# myserver = +# (DESCRIPTION = +# (ADDRESS_LIST = +# (ADDRESS = (PROTOCOL = TCP)(HOST = myhost.cern.ch)(PORT = 1521)) +# ) +# (CONNECT_DATA = +# (SERVICE_NAME = myservicename) +# ) +# ) + +# 3D Frontier test server +bd3d = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = lxfs6043.cern.ch)(PORT = 1521)) + (CONNECT_DATA = + (SID = bd3d) + ) + ) + +# Under cygwin, this path MUST start with '//' +# Under Linux, both '/' and '//' would work +IFILE = //afs/cern.ch/project/oracle/admin/tnsnames.ora + diff --git a/RelationalCool/tests/utility_methods/test_utilities.cpp b/RelationalCool/tests/utility_methods/test_utilities.cpp new file mode 100644 index 000000000..841a68bf0 --- /dev/null +++ b/RelationalCool/tests/utility_methods/test_utilities.cpp @@ -0,0 +1,347 @@ +/** + +@file test_utilities.cpp + +@author Sven A. Schmidt and Andrea Valassi + +@date 2004-12-08 + +*/ + +#include "../Common/CppUnit_headers.h" // Disable CppUnit header warnings + +#include "src/timeToString.h" +#include "CoolKernel/ChannelSelection.h" +#include "CoolKernel/../src/SealTime.h" + +#include <cstring> // for memset +#include <iostream> +using std::string; +using std::cout; +using std::endl; + +// Needed for _tzset on Windows +#ifdef WIN32 +#include <time.h> +#endif + +// Needed for gmtime and timegm on Windows +#ifdef WIN32 +#include <time.h> +inline static time_t timegm (struct tm *t) +{ + // This code is copied as-is from SEAL Time.cpp + time_t t1 = mktime (t); + struct tm gmt = *gmtime (&t1); + time_t t2 = mktime (&gmt); + return t1 + (t1 - t2); +} +#endif + + +namespace cool { + + + /// Test class for utility_methods + + class utility_methodsTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( utility_methodsTest ); + + CPPUNIT_TEST( test_stringToTime ); + CPPUNIT_TEST( test_timeToString ); + + // The second test in this pair is kept only for reference: I thought that + // (not) calling tzset/_tzset would influence the result, but it does not! + CPPUNIT_TEST( test_sealTimeFromDate ); + CPPUNIT_TEST( test_sealTimeFromDate_tzset ); + + CPPUNIT_TEST( test_timegm_gmtime ); + CPPUNIT_TEST( test_gmtime_timegm ); + + CPPUNIT_TEST_SUITE_END(); + +public: + + void setUp() { + } + + void tearDown() { + } + + + /// Tests that timegm( gmtime ( time_t ) ) = ( time_t ) + /// NB: tm_years are # years after 1900 + /// NB: time_t measures seconds after 1970-1-1 + /// On Windows use private implementation of timegm (see SEAL Time.cpp) + void test_timegm_gmtime() { + time_t aTimet = (31+2)*86400+12*3600+62; // 2894462 (1970-2-3 12:01:02) + struct tm aTm = *gmtime( &aTimet ); + time_t aTimetNew = timegm( &aTm ); + bool verbose = false; + if ( verbose ) { + std::cout << "Test test_timegm_gmtime" << std::endl; + std::cout << "aTimet = " << aTimet << std::endl; + std::cout + << "aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + std::cout << "aTimetNew = " << aTimetNew << std::endl; + } + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "timegm(gmtime(time_t))==time_t", aTimet, aTimetNew ); + } + + /// Tests that gmtime( gmtime ( tm ) ) = ( tm ) + /// On Windows use private implementation of timegm (see SEAL Time.cpp) + void test_gmtime_timegm() { + bool verbose = false; + struct tm aTm; + int month; // Months in [0-11] + for ( month = 0; month < 12; month++ ) { + int year = 70; // Years after 1900 + int day = 03; + int hour = 12; + int minute = 01; + int second = 02; + // It seems that the +1 case should fail, but I fail with -1... why???! + memset (&aTm, sizeof(aTm), 0); // As in SEAL Time.cpp + aTm.tm_year = year; + aTm.tm_mon = month; + aTm.tm_mday = day; + aTm.tm_hour = hour; + aTm.tm_min = minute; + aTm.tm_sec = second; + if ( verbose ) { + std::cout << "Test test_gmtime_timegm" << std::endl; + std::cout + << "Before setting isdst: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << std::endl; + } + // Test with tm_idst = -1 + aTm.tm_isdst = -1; + if ( verbose ) std::cout + << "Before calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + time_t aTimetM1 = timegm( &aTm ); + if ( verbose ) std::cout + << "After calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + struct tm aTmM1; + aTmM1 = *gmtime( &aTimetM1 ); + // Test with tm_idst = 0 + aTm.tm_year = year; + aTm.tm_mon = month; + aTm.tm_mday = day; + aTm.tm_hour = hour; + aTm.tm_min = minute; + aTm.tm_sec = second; + aTm.tm_isdst = 0; + if ( verbose ) std::cout + << "Before calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + time_t aTimet0 = timegm( &aTm ); + if ( verbose ) std::cout + << "After calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + struct tm aTm0; + aTm0 = *gmtime( &aTimet0 ); + // Test with tm_idst = +1 + aTm.tm_year = year; + aTm.tm_mon = month; + aTm.tm_mday = day; + aTm.tm_hour = hour; + aTm.tm_min = minute; + aTm.tm_sec = second; + aTm.tm_isdst = +1; + if ( verbose ) std::cout + << "Before calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + time_t aTimetP1 = timegm( &aTm ); + if ( verbose ) std::cout + << "After calling timegm: aTm = " + << 1900+aTm.tm_year << "-" << aTm.tm_mon+1 << "-" << aTm.tm_mday + << " " << aTm.tm_hour << ":" << aTm.tm_min << ":" << aTm.tm_sec + << " (DST=" << aTm.tm_isdst << ")" << std::endl; + struct tm aTmP1; + aTmP1 = *gmtime( &aTimetP1 ); + // Verbose printout + if ( verbose ) { + std::cout + << "aTm = " + << 1900+year << "-" << month+1 << "-" << day + << " " << hour << ":" << minute << ":" << second + << " (DST=-1,0,+1)" << std::endl; + std::cout << "aTimetM1 = " << aTimetM1 << std::endl; + std::cout + << "aTmM1 = " + << 1900+aTmM1.tm_year << "-" << aTmM1.tm_mon+1 + << "-" <<aTmM1.tm_mday + << " " << aTmM1.tm_hour << ":" << aTmM1.tm_min + << ":" << aTmM1.tm_sec + << " (DST=" << aTmM1.tm_isdst << ")" << std::endl; + std::cout << "aTimet0 = " << aTimet0 << std::endl; + std::cout + << "aTm0 = " + << 1900+aTm0.tm_year << "-" << aTm0.tm_mon+1 + << "-" << aTm0.tm_mday + << " " << aTm0.tm_hour << ":" << aTm0.tm_min + << ":" << aTm0.tm_sec + << " (DST=" << aTm0.tm_isdst << ")" << std::endl; + std::cout << "aTimetP1 = " << aTimetP1 << std::endl; + std::cout + << "aTmP1 = " + << 1900+aTmP1.tm_year << "-" << aTmP1.tm_mon+1 + << "-" <<aTmP1.tm_mday + << " " << aTmP1.tm_hour << ":" << aTmP1.tm_min + << ":" << aTmP1.tm_sec + << " (DST=" << aTmP1.tm_isdst << ")" << std::endl; + } + // Actual tests + // Do NOT test isdst: gmtime ALWAYS returns isdst=0! + std::stringstream msg; + msg << " (Month[0-11]=" << month << ")"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("gmtime(timegm(tm,isDst=0))==tm : hour")+msg.str(), + hour, aTm0.tm_hour ); +#ifndef WIN32 + // The following tests FAIL on Windows!!! + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("gmtime(timegm(tm,isDst=-1))==tm : hour")+msg.str(), + hour, aTmM1.tm_hour ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("gmtime(timegm(tm,isDst=+1))==tm : hour")+msg.str(), + hour, aTmP1.tm_hour ); +#endif + } + } + + + /// Tests seal::Time constructor from y,mo,d,h,mi,s,ns,local + /// The test fails on Windows only for months from April onwards + void test_sealTimeFromDate() { + bool local = false; // Use UTC-GMT times + int month; // Months in [0-11] + for ( month = 0; month < 12; month++ ) { + int year = 1970; // Years after 1900 + int day = 03; + int hour = 12; + int minute = 01; + int second = 02; + long nsecond = 123456789; + // AV 28.06.2005 Test for the BUG in seal::Time constructor... + // AV 18.01.2007 cool::SealTime uses months in [1-12]!!! + SealTime cTime( year, month+1, day, hour, minute, second, nsecond ); + seal::Time sTime = cTime.sealTime(); + time_t s1970 = (31+2)*86400+12*3600+62; // 2894462 (1970-2-3 12:01:02) + if ( month == 0 ) s1970 -= 31*86400; // Remove January + if ( month >= 2 ) s1970 += 28*86400; // Add February (365 day year) + if ( month >= 3 ) s1970 += 31*86400; // Add March + if ( month >= 4 ) s1970 += 30*86400; // Add April + if ( month >= 5 ) s1970 += 31*86400; // Add May + if ( month >= 6 ) s1970 += 30*86400; // Add June + if ( month >= 7 ) s1970 += 31*86400; // Add July + if ( month >= 8 ) s1970 += 31*86400; // Add August + if ( month >= 9 ) s1970 += 30*86400; // Add September + if ( month >= 10 ) s1970 += 31*86400; // Add October + if ( month >= 11 ) s1970 += 30*86400; // Add November + std::stringstream msg; + msg << " (Month[0-11]=" << month << ")"; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("ns from 1900")+msg.str(), + (seal::Time::ValueType)s1970*1000000000 + nsecond, sTime.ns() ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("year")+msg.str(), year, sTime.year(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("month")+msg.str(), month, sTime.month(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("day")+msg.str(), day, sTime.day(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("hour")+msg.str(), hour, sTime.hour(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("minute")+msg.str(), minute, sTime.minute(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("second")+msg.str(), second, sTime.second(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("nsecond")+msg.str(), nsecond, sTime.nsecond() ); + } + } + + + /// Tests seal::Time constructor AFTER CALLING tzset() + void test_sealTimeFromDate_tzset() { +#ifdef WIN32 + _tzset(); +#else + tzset(); +#endif + test_sealTimeFromDate(); + } + + + /// Tests timeToString and stringToTime conversions + void test_timeToString() { + std::string aString1 = "2005-06-21_12:00:01.123456789 GMT"; + Time aTime1 = stringToTime( aString1 ); + std::string aString2 = timeToString( aTime1 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "string 2 == string 1", aString1, aString2 ); + Time aTime2 = stringToTime( aString2 ); + std::string aString3 = timeToString( aTime2 ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( "string 3 == string 2", aString2, aString3 ); + } + + + /// tests stringToTime + void test_stringToTime() { + try { + string s = "1970-02-03_12:01:02.123456789 GMT"; + SealTime cTime = stringToTime( s ); + seal::Time sTime = cTime.sealTime(); + bool local = false; + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("year"), 1970, sTime.year(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("month"), 2, sTime.month(local)+1 ); // month in [1-12] + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("day"), 3, sTime.day(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("hour"), 12, sTime.hour(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("minute"), 01, sTime.minute(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("second"), 02, sTime.second(local) ); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( std::string("nanoseconds"), (long)123456789, sTime.nsecond() ); + } catch ( std::exception& e ) { + cout << e.what() << endl; + throw; + } + + } + + }; + + CPPUNIT_TEST_SUITE_REGISTRATION( utility_methodsTest ); + +} // namespace + +// sas: This file is from the OPAL package I believe. It allows for +// shorter test classes and prepares the test class for OPAL +#include<CppUnit_testdriver.icpp> + + diff --git a/RelationalCool/utilities/DBA/oracleCreateGenericReader.sql b/RelationalCool/utilities/DBA/oracleCreateGenericReader.sql new file mode 100644 index 000000000..e7fbb5b7e --- /dev/null +++ b/RelationalCool/utilities/DBA/oracleCreateGenericReader.sql @@ -0,0 +1,38 @@ +-- Experiment prefix +--define EXPERIMENT=ATLAS; +define EXPERIMENT=TESTEXP; + +-- Data tablespace +define DATA_TS=USERS; +--define DATA_TS=DATA01; + +-- Temp tablespace +define TEMP_TS=TEMP; +--define TEMP_TS=TEMP01; + +-- Generic reader user +define USER_R_SUFFIX=_COOL_READER +define USER_R=&EXPERIMENT&USER_R_SUFFIX; + +-- Password +define PSWD_SUFFIX=_password +define PSWD_R=&USER_R&PSWD_SUFFIX + +-- CROSS CHECK! +--select '&EXPERIMENT', '&DATA_TS', '&TEMP_TS', '&USER_R', '&PSWD_R' from DUAL; + +/* +--DROP USER &USER_R CASCADE; +--*/ + +--/* +-- Create generic reader +CREATE USER &USER_R +PROFILE CERN_APP_PROFILE +IDENTIFIED BY &PSWD_R +DEFAULT TABLESPACE &DATA_TS +TEMPORARY TABLESPACE &TEMP_TS +QUOTA 10M ON &DATA_TS; + +GRANT CERN_APP_ROLE TO &USER_R; +--*/ diff --git a/RelationalCool/utilities/DBA/oracleCreateSchemaOwner.sql b/RelationalCool/utilities/DBA/oracleCreateSchemaOwner.sql new file mode 100644 index 000000000..de3d45c59 --- /dev/null +++ b/RelationalCool/utilities/DBA/oracleCreateSchemaOwner.sql @@ -0,0 +1,105 @@ +-- Experiment prefix +--define EXPERIMENT=ATLAS; +define EXPERIMENT=TESTEXP; + +-- Temp tablespace +define TEMP_TS=TEMP; +--define TEMP_TS=TEMP01; + +-- Generic reader user +define USER_R_SUFFIX=_COOL_READER +define USER_R=&EXPERIMENT&USER_R_SUFFIX; + +/* For tests */ +define DETECTOR=TESTDET; + +/* Accounts created on 2005/07/26 */ +--define DETECTOR=INDET; +--define DETECTOR=TRT; +--define DETECTOR=LAR; +--define DETECTOR=TILE; +--define DETECTOR=MUON; +--define DETECTOR=MUONALIGN; +--define DETECTOR=MDT; +--define DETECTOR=TDAQ; +--define DETECTOR=DCS; +--define DETECTOR=GLOBAL; + +/* Accounts created on 2005/09/29 */ +--define DETECTOR=SCT; +--define DETECTOR=PIXEL; + +-- Owner user +define USER_SUFFIX=_COOL_ +define USER_O=&EXPERIMENT&USER_SUFFIX&DETECTOR; + +-- Data tablespace +define DATA_TS_SUFFIX=_DATA01; +define DATA_TS=&USER_O&DATA_TS_SUFFIX; + +-- Password +define PSWD_SUFFIX=_password +define PSWD_O=&USER_O&PSWD_SUFFIX + +-- Roles +define R_ROLE_SUFFIX=_R; +define R_ROLE=R_&USER_O&R_ROLE_SUFFIX; +define W_ROLE_SUFFIX=_W; +define W_ROLE=R_&USER_O&W_ROLE_SUFFIX; +define T_ROLE_SUFFIX=_T; +define T_ROLE=R_&USER_O&T_ROLE_SUFFIX; + +-- Writer user +define USER_W=&USER_O&W_ROLE_SUFFIX; +define PSWD_W=&USER_W&PSWD_SUFFIX + +-- CROSS CHECK! +--select '&DETECTOR', '&USER_R', '&USER_O', '&DATA_TS', '&R_ROLE', '&W_ROLE', '&T_ROLE', '&USER_W', '&PSWD_O', '&PSWD_W' from DUAL; + +/* +--DROP TABLESPACE &DATA_TS INCLUDING CONTENTS AND DATAFILES; +--DROP USER &USER_O CASCADE; +--DROP ROLE &R_ROLE; +--DROP ROLE &W_ROLE; +--DROP ROLE &T_ROLE; +--DROP USER &USER_W CASCADE; +--*/ + +--/* +-- Create tablespace +CREATE TABLESPACE &DATA_TS +DATAFILE SIZE 128M AUTOEXTEND ON NEXT 128M MAXSIZE 8192M LOGGING +EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO; + +-- Create owner +CREATE USER &USER_O +PROFILE CERN_DEV_PROFILE +IDENTIFIED BY &PSWD_O +DEFAULT TABLESPACE &DATA_TS +TEMPORARY TABLESPACE &TEMP_TS +QUOTA UNLIMITED ON &DATA_TS; + +GRANT CERN_DEV_ROLE TO &USER_O; + +-- Create roles +CREATE ROLE &R_ROLE; +CREATE ROLE &W_ROLE; +CREATE ROLE &T_ROLE; + +-- Create writer +CREATE USER &USER_W +PROFILE CERN_APP_PROFILE +IDENTIFIED BY &PSWD_W +DEFAULT TABLESPACE &DATA_TS +TEMPORARY TABLESPACE &TEMP_TS +QUOTA 10M ON &DATA_TS; + +GRANT CERN_APP_ROLE TO &USER_W; + +GRANT &R_ROLE TO &USER_W; +GRANT &W_ROLE TO &USER_W; +GRANT &T_ROLE TO &USER_W; + +-- Grant reader role to generic reader +GRANT &R_ROLE TO &USER_R; +--*/ diff --git a/RelationalCool/utilities/coolAuthentication/coolAuthentication.cpp b/RelationalCool/utilities/coolAuthentication/coolAuthentication.cpp new file mode 100644 index 000000000..e5548b49d --- /dev/null +++ b/RelationalCool/utilities/coolAuthentication/coolAuthentication.cpp @@ -0,0 +1,389 @@ +// $Id: coolAuthentication.cpp,v 1.19 2009-02-09 18:56:15 avalassi Exp $ + +// Include files +#include <iostream> +#include "CoolKernel/Exception.h" +#include "CoolKernel/InternalErrorException.h" +#include "RelationalAccess/AuthenticationServiceException.h" +#include "RelationalAccess/IAuthenticationService.h" +#include "RelationalAccess/IAuthenticationCredentials.h" +#include "RelationalAccess/IDatabaseServiceSet.h" +#include "RelationalAccess/IDatabaseServiceDescription.h" +#include "RelationalAccess/ILookupService.h" +#include "CoralKernel/Context.h" + +// Local include files +#include "../../src/RalSessionMgr.h" +#include "../../src/RelationalDatabaseId.h" + +// Namespace +using namespace cool; + +// Message output +#define LOG std::cout + +// flag to know if we already loaded the LFCReplicaSvc +static bool lfcReplicaSvcLoaded = false; + +static coral::Context& context() { + static coral::Context& context = coral::Context::instance(); + return context; +} +static void load(const std::string &component) { + context().loadComponent(component); +} + +//----------------------------------------------------------------------------- + +coral::IHandle<coral::ILookupService> lookupSvc() +{ + std::string svc_name; + // If we can access a LFC and the user is not explicitely forbidding it, + // we try to use CORAL LFCReplicaService + if ( ::getenv("COOL_IGNORE_LFC") == NULL && ::getenv("LFC_HOST") != NULL ) { + svc_name = "CORAL/Services/LFCReplicaService"; + if ( ! lfcReplicaSvcLoaded ) { + // try to load CORAL LFCReplicaService + load( svc_name ); + lfcReplicaSvcLoaded = true; + } + } else { + // We should check if the component is already loaded before loading it, + // but I know that it will be loaded only once by the application + svc_name = "CORAL/Services/XMLLookupService"; + load( svc_name ); + } + + coral::IHandle<coral::ILookupService> svc = + context().query<coral::ILookupService>(); + if ( ! svc.isValid() ) + throw Exception + ( "Could not retrieve "+svc_name, "coolAuthentication" ); + return svc; +} + +//----------------------------------------------------------------------------- + +coral::IHandle<coral::IAuthenticationService> authSvc() +{ + std::string svc_name; + // If we can access a LFC and the user is not explicitely forbidding it, + // we try to use CORAL LFCReplicaService + if ( ::getenv("COOL_IGNORE_LFC") == NULL && ::getenv("LFC_HOST") != NULL ) { + svc_name = "CORAL/Services/LFCReplicaService"; + if ( ! lfcReplicaSvcLoaded ) { + // try to load CORAL LFCReplicaService + load( svc_name ); + lfcReplicaSvcLoaded = true; + } + } else { + // We should check if the component is already loaded before loading it, + // but I know that it will be loaded only once by the application + svc_name = "CORAL/Services/XMLAuthenticationService"; + load( svc_name ); + } + + coral::IHandle<coral::IAuthenticationService> svc = + context().query<coral::IAuthenticationService>(); + if ( ! svc.isValid() ) + throw Exception + ( "Could not retrieve "+svc_name, "coolAuthentication" ); + return svc; +} + +//----------------------------------------------------------------------------- + +void authenticate( const std::string& coralReplica, + const std::string& technology, + std::string& user, + std::string& password ) +{ + try + { + // Get the authentication credentials from CORAL + const coral::IAuthenticationCredentials& cred = + authSvc()->credentials( coralReplica ); + user = cred.valueForItem( "user" ); + password = cred.valueForItem( "password" ); + if ( user == "" ) + throw Exception + ( "Empty username credentials '' found for " + coralReplica, + "coolAuthentication" ); + if ( password == "" ) + throw Exception + ( "Empty password credentials '' found for " + coralReplica, + "coolAuthentication" ); + } + catch( coral::UnknownConnectionException& /*exc*/ ) + { + if ( technology == "sqlite" || technology == "frontier" ) + { + //LOG << "WARNING: '" << exc.what() << "'" << std::endl; + //LOG << "WARNING: set DUMMY user and DUMMY password" << std::endl; + user = "DUMMY"; + password = "DUMMY"; + } + else throw; + } +} + +//----------------------------------------------------------------------------- + +void printOut( const std::string& coralReplica, + const std::string& coralMode, + const std::string& technology, + const std::string& server, + const std::string& schema, + const std::string& user, + const std::string& password ) +{ + // Print out the database server properties + LOG << "==> coralReplica = " << coralReplica << std::endl; + LOG << "==> coralMode = " << coralMode << std::endl; + LOG << "==> technology = " << technology << std::endl; + LOG << "==> server = " << server << std::endl; + LOG << "==> schema = " << schema << std::endl; + + // Print out the authentication credentials + //LOG << "CORAL authentication credentials:" << std::endl; + LOG << "==> user = " << user << std::endl; + LOG << "==> password = " << password << std::endl; +} + +//----------------------------------------------------------------------------- + +int main( int argc, char** argv ) +{ + + // *** TRY *** + + try { + + // Get the COOL database identifier + bool rwOnly = false; + bool firstOnly = false; + std::string dbId; + if ( argc == 3 && std::string(argv[1]) == "-1" ) + { + firstOnly = true; + dbId = argv[2]; + } + else if ( argc == 3 && std::string(argv[1]) == "-1RW" ) + { + rwOnly = true; + firstOnly = true; + dbId = argv[2]; + } + else if ( argc == 2 ) + { + dbId = argv[1]; + } + else + { + LOG << "Usage: " << argv[0] << " [-1|-1RW] dbId" << std:: endl; + LOG << "[Option -1: display only the first replica]" << std::endl; + LOG << "[Option -1RW: display only the first RW replica]" << std::endl; + std::string dbId1 = + "oracle://SERVER;schema=SCHEMA;user=USER;password=PSWD;dbname=DB"; + std::string dbId2 = + "oracle://SERVER;schema=SCHEMA;dbname=DB"; + std::string dbId3 = + "alias/DB"; + LOG << std::endl; + LOG << "Example: " << argv[0] << " '" << dbId1 << "'\n" + << "[Decode user and password from explicit credentials]" + << std::endl; + LOG << std::endl; + LOG << "Example: " << argv[0] << " '" << dbId2 << "'\n" + << "[Get user and password from authentication service]" + << std::endl; + LOG << std::endl; + LOG << "Example: " << argv[0] << " '" << dbId3 << "'\n" + << "[Get alias translation from dblookup service]" + << std::endl + << "[Get user and password from authentication service]" + << std::endl; + return 1; + } + + // --- TRANSLATE COOL URL into CORAL alias or explicit replica + + // Parse the dbId URL as RelationalDatabaseId connection parameters + RelationalDatabaseId relationalDbId( dbId ); + + // Print out the database identification + LOG << "COOL databaseId" << std::endl; + LOG << "==> middleTier = " + << relationalDbId.middleTier() << std::endl; + LOG << "==> url = " + << relationalDbId.url() << std::endl; + LOG << "==> urlHidePswd = " + << relationalDbId.urlHidePswd() << std::endl; + + // Extract the connection parameters from the RelationalDbId + std::string middleTier ( relationalDbId.middleTier() ); + std::string technology ( relationalDbId.technology() ); + std::string server ( relationalDbId.server() ); + std::string schema ( relationalDbId.schema() ); + std::string dbName ( relationalDbId.dbName() ); + std::string user ( relationalDbId.user() ); + std::string password ( relationalDbId.password() ); + + // PANIC if the database name is not given explicitly + // (RelationalDatabaseId should have already failed!) + if ( dbName == "" ) + throw InternalErrorException + ( "PANIC! No database name specified in COOL database URL", + "coolAuthentication" ); + LOG << "==> dbName = " + << dbName << std::endl; + + // Get the CORAL connection string + std::string coralUrl; + if ( middleTier == "" ) + coralUrl = RalConnectionString( relationalDbId ); + else + coralUrl = RalConnectionString( relationalDbId.url() ); + std::string coralMode = "N/A"; + + // --- Case 1: CORAL alias (loop over replicas) + + // If the connection string looks like an alias, pass it to the LookupSvc + if ( coralUrl.find("://") == std::string::npos && + coralUrl.substr(0,12) != "sqlite_file:" ) + { + LOG << "CORAL logical alias" << std::endl; + LOG << "==> coralAlias = " << coralUrl << std::endl; + + // PANIC if technology, server, schema, user or password + // are defined at this point (this should never happen!) + if ( technology != "" ) + throw InternalErrorException + ( "PANIC! COOL URL based on CORAL alias explicitly contains " + "technology '" + technology + "'", + "coolAuthentication" ); + if ( server != "" ) + throw InternalErrorException + ( "PANIC! COOL URL based on CORAL alias explicitly contains " + "server '" + server + "'", + "coolAuthentication" ); + if ( schema != "" ) + throw InternalErrorException + ( "PANIC! COOL URL based on CORAL alias explicitly contains " + "schema '" + schema + "'", + "coolAuthentication" ); + if ( user != "" ) + throw InternalErrorException + ( "PANIC! COOL URL based on CORAL alias explicitly contains " + "user '" + user + "'", + "coolAuthentication" ); + if ( password != "" ) + throw InternalErrorException + ( "PANIC! COOL URL based on CORAL alias explicitly contains " + "password '" + password + "'", + "coolAuthentication" ); + + // Lookup the replicas + coral::AccessMode mode = ( rwOnly ? coral::Update : coral::ReadOnly ); + std::auto_ptr<coral::IDatabaseServiceSet> replicas + ( lookupSvc()->lookup( coralUrl, mode ) ); + int nReplicas = replicas->numberOfReplicas(); + if ( nReplicas == 0 ) + throw Exception + ( "No dblookup replicas found for " + coralUrl, + "coolAuthentication" ); + + // Loop over the replicas + // Reuse variables coralUrl, technology, server, schema, user, password + for ( int iReplica = 0; iReplica < nReplicas; iReplica++ ) + { + const coral::IDatabaseServiceDescription& + dsd = replicas->replica( iReplica ); + coralUrl = dsd.connectionString(); + coralMode = ( dsd.accessMode() == coral::ReadOnly ? "R/O" : "R/W" ); + + // Extract technology, server and schema + if ( coralUrl.substr(0,12) == "sqlite_file:" ) + { + // Special case for SQLite + technology = "sqlite"; + server = ""; + schema = coralUrl.substr(12); + } + else + { + // Backends other than SQLite + std::string::size_type pos = coralUrl.find("://"); + if ( pos == std::string::npos ) + throw Exception + ( "The connection string returned by the lookup service " + "does not contain \"://\": " + coralUrl, + "coolAuthentication" ); + technology = coralUrl.substr(0,pos); + pos += 3; + std::string::size_type pos2 = coralUrl.find_last_of('/'); + if ( pos2 == std::string::npos ) + throw Exception + ( "The connection string returned by the lookup service " + "does not contain the schema name: " + coralUrl, + "coolAuthentication" ); + server = coralUrl.substr(pos,pos2 - pos); + schema = coralUrl.substr(pos2+1); + } + + // Retrieve user and password using the authentication service + user = ""; + password = ""; + authenticate( coralUrl, technology, user, password ); + + // Print out the results + LOG << "CORAL physical replica (" + << iReplica+1 << " of " << nReplicas << ")" << std::endl; + printOut(coralUrl,coralMode,technology,server,schema,user,password ); + + // Use only the first replica if required + if ( firstOnly ) break; + + } + + } + + // --- Case 2: explicit CORAL replica + + else + + { + + // If the user name or password are not given explicitly, + // retrieve them using the CORAL authentication service + if ( user == "" || password == "" ) + authenticate( coralUrl, technology, user, password ); + + // Print out the results + LOG << "CORAL physical replica (1 of 1)" << std::endl; + printOut(coralUrl,coralMode,technology,server,schema,user,password ); + + } + + } + + // *** CATCH exceptions *** + + catch( std::exception& e ) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( ... ) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + return 1; + } + + // Successful program termination + return 0; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/utilities/coolDropDB/coolDropDB.cpp b/RelationalCool/utilities/coolDropDB/coolDropDB.cpp new file mode 100644 index 000000000..2cb670eaf --- /dev/null +++ b/RelationalCool/utilities/coolDropDB/coolDropDB.cpp @@ -0,0 +1,233 @@ +// $Id: coolDropDB.cpp,v 1.24 2008-04-10 15:31:14 avalassi Exp $ + +// Include files +#include <iostream> +#include "CoolKernel/Exception.h" +#include "CoralBase/Exception.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" +#include "RelationalAccess/ISessionProxy.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITransaction.h" + +// Local include files +#include "../../src/CoralApplication.h" +#include "../../src/CoralConnectionServiceProxy.h" +#include "../../src/RalSessionMgr.h" +#include "../../src/RelationalDatabaseId.h" + +// Message output +#define LOG std::cout + +//----------------------------------------------------------------------------- + +int main( int argc, char** argv ) +{ + + try + { + + // Have all tables been dropped successfully? + bool success = true; + + // Get the command line arguments + std::string dbId; + if ( argc == 2 ) { + dbId = argv[1]; + } else { + LOG << "Usage: " << argv[0] << " dbId" << std:: endl; + std::string dbId1 = + "oracle://SERVER;schema=SCHEMA;user=USER;password=PSWD;dbname=DB"; + std::string dbId2 = + "oracle://SERVER;schema=SCHEMA;dbname=DB"; + LOG << std::endl; + LOG << "Example: " << argv[0] << " '" << dbId1 << "'\n" + << "[Decode user and password from explicit credentials]" + << std::endl; + LOG << std::endl; + LOG << "Example: " << argv[0] << " '" << dbId2 << "'\n" + << "[Get user and password from authentication service]" + << std::endl; + return 1; + } + + // Decode and print out the database URL + cool::RelationalDatabaseId relationalDbId(dbId); + std::string dbName = relationalDbId.dbName(); + LOG << "Drop COOL database \"" << relationalDbId.urlHidePswd() << "\"" + << std::endl; + + // Instantiate a COOL Application + cool::CoralApplication app; + + // Disable CORAL automatic pool clean up thread + LOG << "Getting CORAL Connection Service configurator" << std::endl; + coral::IConnectionServiceConfiguration &connSvcConf = + app.connectionSvc().configuration(); + + // If we can access a LFC and the user is not explicitely forbidding it, + // we try to use CORAL LFCReplicaService + if ( ::getenv("COOL_IGNORE_LFC") == NULL && + ::getenv("LFC_HOST") != NULL ) { + // use CORAL LFCReplicaService + connSvcConf.setAuthenticationService("CORAL/Services/LFCReplicaService"); + connSvcConf.setLookupService("CORAL/Services/LFCReplicaService"); + } + + LOG << "Disabling CORAL connection automatic clean up" << std::endl; + connSvcConf.disablePoolAutomaticCleanUp(); + connSvcConf.setConnectionTimeOut( 0 ); + + // Create a session manager and start a transaction + const bool readOnly = false; + cool::CoralConnectionServiceProxyPtr ppConnSvc + ( new cool::CoralConnectionServiceProxy( &app.connectionSvc() ) ); + cool::RalSessionMgr rsm( ppConnSvc, dbId, readOnly ); + LOG << "Start transaction." << std::endl; + rsm.session().transaction().start(); + std::set<std::string> existingTables = + rsm.session().nominalSchema().listTables(); + + // Mark for deletion all tables whose names start with dbName + "_" + // Tables must be deleted in a specific order because of FK constraints + std::string signature = dbName + "_"; + std::list<std::string> tablesToDelete; + // Management tables are deleted last (and in a specific order) + std::list<std::string> mgmtTables; + mgmtTables.push_back( signature + "DB_ATTRIBUTES" ); + // *** START *** 3.0.0 schema extensions (task #4307) + mgmtTables.push_back( signature + "IOVTABLES" ); + mgmtTables.push_back( signature + "CHANNELTABLES" ); + // **** END **** 3.0.0 schema extensions (task #4307) + mgmtTables.push_back( signature + "NODES" ); + mgmtTables.push_back( signature + "NODES_SEQ" ); + mgmtTables.push_back( signature + "TAGS" ); + // *** START *** 3.0.0 schema extensions (task #4396) + mgmtTables.push_back( signature + "USERTAGS" ); + mgmtTables.push_back( signature + "HEADTAGS" ); + // **** END **** 3.0.0 schema extensions (task #4396) + mgmtTables.push_back( signature + "TAG2TAG" ); + mgmtTables.push_back( signature + "TAG2TAG_SEQ" ); + mgmtTables.push_back( signature + "TAGS_SEQ" ); + mgmtTables.push_back( signature + "IOVS_SEQ" ); + std::list<std::string>::const_iterator mgmtTable; + for ( mgmtTable = mgmtTables.begin(); + mgmtTable != mgmtTables.end(); + ++mgmtTable ) + { + if ( existingTables.find( *mgmtTable ) != existingTables.end() ) + { + existingTables.erase( *mgmtTable ); + // First inserted will be at the back of the list - and deleted last + tablesToDelete.push_front( *mgmtTable ); + } + } + // Tables that are not associated to individual nodes (and are not + // management tables either) are deleted before the management tables + // [NB: There should be no such tables, but delete them anyway!] + std::set<std::string>::reverse_iterator existingTable; + for ( existingTable = existingTables.rbegin(); + existingTable != existingTables.rend(); + ++existingTable ) + { + if ( existingTable->find( signature ) == 0 && + existingTable->find( signature+"F" ) != 0 ) + { + // First inserted will be at the back of the list - and deleted last + // [i.e. delete these tables in alphabetical order - as in COOL133c] + tablesToDelete.push_front( *existingTable ); + } + } + // Tables that are associated to individual nodes are deleted first + // Delete all channel tables last, because of FK constraints + // (first inserted will be at the back of the list, and deleted last) + for ( existingTable = existingTables.rbegin(); + existingTable != existingTables.rend(); + ++existingTable ) + { + if ( existingTable->find( signature ) == 0 && + existingTable->find( signature+"F" ) == 0 && + existingTable->rfind( "_CHANNELS" ) == existingTable->size()-9 ) + { + tablesToDelete.push_front( *existingTable ); + } + } + // Tables that are associated to individual nodes are deleted first + // Delete all tables other than the channel tables first + for ( existingTable = existingTables.rbegin(); + existingTable != existingTables.rend(); + ++existingTable ) + { + if ( existingTable->find( signature ) == 0 && + existingTable->find( signature+"F" ) == 0 && + existingTable->rfind( "_CHANNELS" ) != existingTable->size()-9 ) + { + // First inserted will be at the back of the list - and deleted last + // [i.e. delete these tables in alphabetical order - as in COOL133c] + tablesToDelete.push_front( *existingTable ); + } + } + + // Drop the tables + std::list<std::string>::iterator tableToDelete; + for ( tableToDelete = tablesToDelete.begin(); + tableToDelete != tablesToDelete.end(); + ++tableToDelete ) + { + LOG << "Dropping table \"" << *tableToDelete << "\" ... " << std::flush; + try { + rsm.session().nominalSchema().dropTable(*tableToDelete); + LOG << "done." << std::endl; + } + catch(...){ + LOG << "failed." << std::endl; + success = false; + } + } + + // Commit the transaction + LOG << "Commit transaction." << std::endl; + rsm.session().transaction().commit(); + + // Close the session manager access to the CORAL connection service + ppConnSvc->purgeConnectionPool(); + ppConnSvc->resetICS(); + + // Have all tables been dropped successfully? + if ( success ) + LOG << "All database tables have been dropped successfully." + << std::endl; + else + LOG << "WARNING! One or more database tables could not be dropped." + << std::endl; + } + + catch( cool::Exception& e ) + { + LOG << "ERROR! Cool Exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( coral::Exception& e ) + { + LOG << "ERROR! Coral Exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( std::exception& e ) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( ... ) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + return 1; + } + + // Successful program termination + return 0; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/utilities/coolDumpSchema/coolDumpSchema.cpp b/RelationalCool/utilities/coolDumpSchema/coolDumpSchema.cpp new file mode 100755 index 000000000..62779af17 --- /dev/null +++ b/RelationalCool/utilities/coolDumpSchema/coolDumpSchema.cpp @@ -0,0 +1,110 @@ +// $Id: coolDumpSchema.cpp,v 1.9 2008-04-10 15:31:15 avalassi Exp $ + +// Include files +#include <algorithm> +#include <iostream> +#include "RelationalAccess/IColumn.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" +#include "RelationalAccess/ISessionProxy.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" +#include "RelationalAccess/ITableDescription.h" +#include "RelationalAccess/ITransaction.h" + +// Local include files +#include "../../src/CoralApplication.h" +#include "../../src/CoralConnectionServiceProxy.h" +#include "../../src/RalSessionMgr.h" +#include "../../src/RelationalDatabaseId.h" + +// Message output +#define LOG std::cout + +int main( int argc, char** argv ) { + + std::string dbId; + if ( argc == 2 ) { + dbId = argv[1]; + } else { + LOG << "Usage: " << argv[0] << " dbId" << std:: endl; + std::string dbId1 = + "oracle://SERVER;schema=SCHEMA;user=USER;password=PSWD;dbname=DB"; + std::string dbId2 = + "oracle://SERVER;schema=SCHEMA;dbname=DB"; + LOG << std::endl; + LOG << "Example: " << argv[0] << " '" << dbId1 << "'\n" + << "[Decode user and password from explicit credentials]" + << std::endl; + LOG << std::endl; + LOG << "Example: " << argv[0] << " '" << dbId2 << "'\n" + << "[Get user and password from authentication service]" + << std::endl; + return 1; + } + + // Instantiate a COOL Application + cool::CoralApplication app; + + // If we can access a LFC and the user is not explicitely forbidding it, + // we try to use CORAL LFCReplicaService + if ( ::getenv("COOL_IGNORE_LFC") == NULL && + ::getenv("LFC_HOST") != NULL ) { + // try to load CORAL LFCReplicaService + coral::IConnectionServiceConfiguration &connSvcConf = + app.connectionSvc().configuration(); + connSvcConf.setAuthenticationService("CORAL/Services/LFCReplicaService"); + connSvcConf.setLookupService("CORAL/Services/LFCReplicaService"); + } + + cool::RelationalDatabaseId relationalDbId(dbId); + std::string dbName = relationalDbId.dbName(); + + LOG << "Dump COOL database schema \"" << relationalDbId.urlHidePswd() << "\"" << std::endl; + + const bool readOnly = false; + cool::CoralConnectionServiceProxyPtr ppConnSvc + ( new cool::CoralConnectionServiceProxy( &app.connectionSvc() ) ); + cool::RalSessionMgr rsm( ppConnSvc, dbId, readOnly ); + LOG << "Start transaction." << std::endl; + rsm.session().transaction().start(); + std::set<std::string> tableSet = rsm.session().nominalSchema().listTables(); + + // need to copy this over as set sorting does not work + std::vector<std::string> tables; + for ( std::set<std::string>::const_iterator + t = tableSet.begin(); t != tableSet.end(); ++t ){ + tables.push_back( *t ); + } + sort( tables.begin(), tables.end() ); + + std::string signature = dbName + "_"; + for ( std::vector<std::string>::const_iterator + t = tables.begin(); t != tables.end(); ++t ){ + if ( t->find(signature) == 0 ){ // table name starts with dbName + "_" + LOG << "------------------------------------------------" << std::endl; + LOG << "Table " << *t << std::endl; + LOG << "------------------------------------------------" << std::endl; + coral::ITable& table( rsm.session().nominalSchema().tableHandle( *t ) ); + const coral::ITableDescription& tableDescription( table.description() ); + std::vector<std::string> colNames; + for ( int i = 0; i < tableDescription.numberOfColumns(); ++i ) { + const coral::IColumn& col( tableDescription.columnDescription( i ) ); + colNames.push_back( col.name() ); + } + sort( colNames.begin(), colNames.end() ); + for ( std::vector<std::string>::const_iterator + n = colNames.begin(); n != colNames.end(); ++n ) { + const coral::IColumn& col( tableDescription.columnDescription( *n ) ); + LOG << col.name() << "\t" << col.type() << "\t" << col.size() + << std::endl; + } + } + } + + rsm.session().transaction().commit(); + ppConnSvc->purgeConnectionPool(); + ppConnSvc->resetICS(); + + return 0; +} diff --git a/RelationalCool/utilities/coolEvolveSchema/RalSchemaEvolution.cpp b/RelationalCool/utilities/coolEvolveSchema/RalSchemaEvolution.cpp new file mode 100644 index 000000000..9c0fd2a8d --- /dev/null +++ b/RelationalCool/utilities/coolEvolveSchema/RalSchemaEvolution.cpp @@ -0,0 +1,2263 @@ +// $Id: RalSchemaEvolution.cpp,v 1.106 2009-01-16 11:08:53 avalassi Exp $ + +// Include files +#include "CoolKernel/Record.h" +#include "CoralBase/Attribute.h" +#include "RelationalAccess/IColumn.h" +#include "RelationalAccess/IIndex.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" +#include "RelationalAccess/ITableDataEditor.h" +#include "RelationalAccess/ITableSchemaEditor.h" +#include "RelationalAccess/SchemaException.h" + +// Local include files +#include "RalSchemaEvolution.h" +#include "../../src/HvsPathHandler.h" +#include "../../src/ObjectId.h" +#include "../../src/RalDatabase.h" +#include "../../src/RelationalChannelTable.h" +#include "../../src/RelationalDatabaseTable.h" +#include "../../src/RelationalException.h" +#include "../../src/RelationalFolder.h" +#include "../../src/RelationalGlobalTagTable.h" +#include "../../src/RelationalIovSharedSequenceTable.h" +#include "../../src/RelationalNodeTable.h" +#include "../../src/RelationalObjectTable.h" +#include "../../src/RelationalObjectTableRow.h" +#include "../../src/RelationalQueryMgr.h" +#include "../../src/RelationalSchemaMgr.h" +#include "../../src/RelationalTagSequence.h" +#include "../../src/RelationalTagSharedSequenceTable.h" +#include "../../src/RelationalTag2TagTable.h" +#include "../../src/RelationalTableRow.h" +#include "../../src/RelationalTransaction.h" +#include "../../src/VersionInfo.h" + +// Additional VersionInfo specific to RalSchemaEvolution.cpp +namespace cool +{ + namespace VersionInfo { + const std::string cvsCheckout = "$Name: not supported by cvs2svn $"; + const std::string cvsCheckin = "$Id: RalSchemaEvolution.cpp,v 1.106 2009-01-16 11:08:53 avalassi Exp $"; + } +} + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RalSchemaEvolution::RalSchemaEvolution( CoralConnectionServiceProxyPtr ppConnSvc, + const DatabaseId& dbId ) + : m_db( new RalDatabase( ppConnSvc, dbId, false ) ) + , m_log( new coral::MessageStream( "RalSchemaEvolution" ) ) +{ + log() << coral::Info + << "Instantiate a RalSchemaEvolution manager for '" + << m_db->databaseId() << "'" << coral::MessageStream::endmsg; + + // DIRTY HACK - open the database + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + m_db->m_dbAttr = db().fetchDatabaseAttributes(); + transaction.commit(); + m_db->m_isOpen = true; +} + +//----------------------------------------------------------------------------- + +RalSchemaEvolution::~RalSchemaEvolution() +{ + log() << coral::Info + << "Delete the RalSchemaEvolution manager for '" + << m_db->databaseId() << "'" << coral::MessageStream::endmsg; + if ( m_db ) delete m_db; +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RalSchemaEvolution::log() +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::evolveDatabase() +{ + // WELCOME + log() << coral::Info << "Evolve database schema... START" << coral::MessageStream::endmsg; + RelationalTransaction transaction( db().transactionMgr(), false ); // r/w + + // Can the schema of this database be evolved? Does it need to? + const Record& dbAttr = db().databaseAttributes(); + std::string releaseNumber = + dbAttr[RelationalDatabaseTable::attributeNames::release] + .data<std::string>(); + std::string schemaVersion = + dbAttr[RelationalDatabaseTable::attributeNames::schemaVersion]. + data<std::string>(); + bool dbNeedsEvolution = false; + try + { + dbNeedsEvolution = + !db().areReleaseAndSchemaCompatible( releaseNumber, schemaVersion ); + } catch ( IncompatibleReleaseNumber& e ) { + log() << coral::Error << "Exception caught: '" + << e.what() << "'" << std::endl; + log() << coral::Error + << "Schema evolution is not possible for this database - abort" + << coral::MessageStream::endmsg; + throw e; + } + + // DATABASE NEEDS SCHEMA EVOLUTION FROM 130 TO 200 + if ( dbNeedsEvolution ) + { + log() << coral::Info + << "Database needs schema evolution: proceed" + << coral::MessageStream::endmsg; + if ( schemaVersion == "1.2.0" ) { + std::stringstream msg; + msg << "Schema evolution from schema version " << schemaVersion + << " is not possible using this tool from release " + << VersionInfo::release << ". Please evolve the schema in two steps:" + << " first to 1.3.0 using the tools from the COOL 1.3 releases," + << " and then to 2.0.0 using the tools from the current release."; + msg << " Schema evolution is not possible for this database - abort"; + log() << coral::Error << msg.str() << coral::MessageStream::endmsg; + throw IncompatibleReleaseNumber( msg.str(), "RalSchemaEvolution" ); + } else if ( schemaVersion == "1.3.0" ) { +#ifndef _WIN32 + evolveDatabase_130_to_200(); +#else + // Schema evolution from 1.3.x is not supported any longer on Windows + std::stringstream msg; + msg << "ERROR! Schema evolution from COOL 1.3.x to " + << VersionInfo::release << " is not supported on Windows: " + << "please perform schema evolution " + << "on a COOL 1.3.x supported platform"; + log() << coral::Error << msg.str() << coral::MessageStream::endmsg; + throw RelationalException + ( msg.str(), "RalSchemaEvolution" ); +#endif + } else { + std::stringstream msg; + msg << "Unsupported schema version: '" << schemaVersion << "'."; + msg << " Schema evolution is not possible for this database - abort"; + log() << coral::Error << msg.str() << coral::MessageStream::endmsg; + throw IncompatibleReleaseNumber( msg.str(), "RalSchemaEvolution" ); + } + } + // DATABASE DOES NOT NEED SCHEMA EVOLUTION FROM 130 TO 200 + else + { + log() << coral::Info + << "Database does not need schema evolution" << coral::MessageStream::endmsg; + } + + // CHECK INDIVIDUAL NODES FOR SCHEMA EVOLUTION FROM 200 TO 220 + log() << coral::Info + << "Alter MySQL SQL types and " + << "check if individual nodes need schema evolution" << coral::MessageStream::endmsg; + evolveDatabase_200_to_220(); + + // GOODBYE + transaction.commit(); + log() << coral::Info << "Evolve database schema... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::evolveDatabase_130_to_200() +{ + log() << coral::Info + << "Evolve database schema (130->200)..." << coral::MessageStream::endmsg; + + // ------------------------------------------------------------------- + // Alter selected SQL types of columns in all existing tables: + // (1a) Alter MySQL "VARCHAR(255) BINARY" into "VARCHAR(255) BINARY" + // *** NB: This is actually a no-op in evolving schemas from COOL1xx to 200. + // *** BINARY was by mistake added in versions COOL200 to 211 (bug #24393, + // *** aka bug #26484). Schema version number remains 2.0.0 in the change + // *** from COOL211 to 220 (there are no production databases on MySQL). + // (1b) %%% DISABLED %%% Alter MySQL "TEXT" into "TEXT BINARY" + // ( 2) Alter SQLite "LONG" into "INT" + // ( 3) Alter SQLite "UNSIGNEDLONG" into "UNSIGNEDINT" + // ------------------------------------------------------------------- + + i_alterSqlTypes_130_to_200(); + + // ------------------------------------------------------------------- + // Evolve the node table: + // ( 4) Change the FOLDER_PAYLOADSPEC column size from 4k to 64k + // ( 5) Add the FOLDER_PAYLOAD_INLINE column (default: NULL) + // ( 6) Add the FOLDER_PAYLOAD_EXTREF column (default: NULL) + // ( 7) Add the FOLDER_CHANNELSPEC column (default: NULL) + // ( 8) Add the FOLDER_CHANNEL_EXTREF column (default: NULL) + // ( 9) Add the FOLDER_CHANNELTABLENAME column (default: NULL) + // (10) Add the LASTMOD_DATE column (default: NOW) + // (11) Add the SCHEMA_VERSION column (default: 2.0.0) + // (12) Update the versioning mode of the root "/" folder set to -1 + // (13) Add the UK constraint on (nodeFullPath) + // (14) Add the UK constraint on (nodeId, nodeParentId) + // ------------------------------------------------------------------- + + i_evolveNodeTable_130_200(); + + // ------------------------------------------------------------------- + // Evolve the global tag table: + // (15) Add the TAG_LOCK_STATUS column (default: 0) + // (16) Recreate the PK on (nodeId, tagId) - invert the present order + // (17) Add the UK constraint on tagName + // (18) Add the FK constraint on nodeId to the NODES table + // ------------------------------------------------------------------- + + i_evolveGlobalTagTable_130_200(); + + // ------------------------------------------------------------------- + // Evolve the tag2tag table: + // (19) Add the FK constraint on the parent tag to the TAGS table + // (20) Add the FK constraint on the child tag to the TAGS table + // (21) Add the FK constraint on the parent/child to the NODES table + // ------------------------------------------------------------------- + + i_evolveTag2TagTable_130_200(); + + // ------------------------------------------------------------------- + // (22) Create the tag shared sequence + // ------------------------------------------------------------------- + + i_createTagSharedSequence_130_200(); + + // ------------------------------------------------------------------- + // (23) Create the IOV shared sequence + // ------------------------------------------------------------------- + + i_createIovSharedSequence_130_200(); + + // ------------------------------------------------------------------- + // Evolve each folder from 130 to 200 + // (24) Add the LASTMOD_DATE column (default: NOW) to each IOV table + // (25) Create each channels table + // (26) Update the node table with each channels table name + // ------------------------------------------------------------------- + { + // List all folders ordered by nodeId + coral::AttributeList whereData; + whereData.extend + ( "isLeaf", + typeIdToCoralType(RelationalNodeTable::columnTypeIds::nodeIsLeaf) ); + whereData["isLeaf"].setValue + ( true ); // select folders only + std::string whereClause = RelationalNodeTable::columnNames::nodeIsLeaf; + whereClause += "= :isLeaf"; + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeId; + orderClause += " ASC"; + orderBy.push_back( orderClause ); + std::vector<RelationalTableRow> rows = + db().queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db().nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification + ( VersionNumber( "1.3.0" ) ) ), + whereClause, whereData, orderBy, "" ); + // Evolve all folders one by one + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + i_evolveIovTable_130_to_200( *row ); + i_createChannelsTable_130_to_200( *row ); + i_fillChannelsTableSV_130_to_200( *row ); + i_updateNodeTable_130_to_200( *row ); + } + } + + // ------------------------------------------------------------------- + // Update the main database table + // (27) Insert schema evolution metadata + // (28) Update current database schema to 2.0.0 + // (29) Insert names of new top-level tables + // ------------------------------------------------------------------- + + i_evolveMainTable_130_to_200(); + + // Success + log() << coral::Info + << "Evolve database schema (130->200)... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_evolveNodeTable_130_200() +{ + log() << coral::Info + << "Evolve node table schema (130->200)... START" << coral::MessageStream::endmsg; + std::string nodeTableName = db().nodeTableName(); + + // 1. Change the folderPayloadSpecDesc column size from 4k to 64k + // First attempt - this fails with ORA-22858 on Oracle + // (cannot ALTER a non-CLOB column into a CLOB column) + if ( false ) { + std::string columnName = + RelationalNodeTable::columnNames::folderPayloadSpecDesc; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::folderPayloadSpecDesc; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": alter type of column '" << columnName + << "' in table '" << nodeTableName + << "' to type '" << columnType.name() << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().changeColumnType + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to alter type of column '" << columnName + << "' in table '" << nodeTableName + << "' to type '" << columnType.name() << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + // Second attempt - workaround: rename the 4k column, add a new 64k column + // with the correct name, copy the contents, then drop the old column + if ( true ) { + std::string columnName = + RelationalNodeTable::columnNames::folderPayloadSpecDesc; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::folderPayloadSpecDesc; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": alter type of column '" << columnName + << "' in table '" << nodeTableName + << "' to type '" << columnType.name() << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + // Rename the old 4k column + std::string columnName4k = + RelationalNodeTable::columnNames::folderPayloadSpecDesc + "_TMP"; + table.schemaEditor().renameColumn( columnName, columnName4k ); + // Add a new 64k column + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + // Copy the value of the old 4k column into the new 64k column + std::string whereClause = ""; // No WHERE clause + std::string setClause = columnName + "=" + columnName4k; + coral::AttributeList updateData; // No bind variables + db().queryMgr().updateTableRows + ( nodeTableName, setClause, whereClause, updateData ); + // Drop the old 4k column + table.schemaEditor().dropColumn( columnName4k ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to alter type of column '" << columnName + << "' in table '" << nodeTableName + << "' to type '" << columnType.name() << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 2. Add the folderPayloadInline column. + { + std::string columnName = + RelationalNodeTable::columnNames::folderPayloadInline; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::folderPayloadInline; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 3. Add the folderPayloadExtRef column. + { + std::string columnName = + RelationalNodeTable::columnNames::folderPayloadExtRef; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::folderPayloadExtRef; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 4. Add the folderChannelSpecDesc column. + { + std::string columnName = + RelationalNodeTable::columnNames::folderChannelSpecDesc; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::folderChannelSpecDesc; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 5. Add the folderChannelExtRef column. + { + std::string columnName = + RelationalNodeTable::columnNames::folderChannelExtRef; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::folderChannelExtRef; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 6. Add the folderChannelTableName column. + { + std::string columnName = + RelationalNodeTable::columnNames::folderChannelTableName; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::folderChannelTableName; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 7. Add the lastModDate column and set its value to NOW. + { + std::string columnName = + RelationalNodeTable::columnNames::lastModDate; + // Add the lastModDate column. + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::lastModDate; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + // Set the value of the lastModDate column to NOW. + try { + std::string whereClause = ""; // No WHERE clause + std::string columnValue = RelationalQueryMgr::serverTimeClause + ( db().sessionMgr()->databaseTechnology() ); + std::string setClause = columnName + "=" + columnValue; + coral::AttributeList updateData; // No bind variables + db().queryMgr().updateTableRows + ( nodeTableName, setClause, whereClause, updateData ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to update table '" << nodeTableName << "'" + << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 8. Add the SCHEMA_VERSION column and set its value to 2.0.0. + { + std::string columnName = + RelationalNodeTable::columnNames::nodeSchemaVersion; + // Add the nodeSchemaVersion column. + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::nodeSchemaVersion; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + // Set the value of the nodeSchemaVersion column to 2.0.0. + // *** NB Hardcode the value to '2.0.0' (as in COOL_2_0_0): for folders + // *** (but not for folder sets), this will be changed later to '2.0.1'. + try { + std::string whereClause; // No WHERE clause + std::string setClause = + columnName + "='" + std::string( VersionInfo::schemaVersion ) + "'"; + coral::AttributeList updateData; // No bind variables + db().queryMgr().updateTableRows + ( nodeTableName, setClause, whereClause, updateData ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to update table '" << nodeTableName << "'" + << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 9. Update the versioning mode of the root "/" folder set to -1 + { + std::string columnName = + RelationalNodeTable::columnNames::folderVersioningMode; + HvsPathHandler handler; + std::stringstream noneMode; + noneMode << FolderVersioning::NONE; + std::string rootFullPath = handler.rootFullPath(); + log() << coral::Info + << "Node table needs schema evolution" + << ": set value of column '" << columnName + << "' to '" << noneMode.str() + << "' for the root folder set '" << rootFullPath << "'" + << coral::MessageStream::endmsg; + try { + std::string whereClause = + RelationalNodeTable::columnNames::nodeFullPath + + "='" + rootFullPath + "'"; + std::string setClause = columnName + "=" + noneMode.str(); + coral::AttributeList updateData; // No bind variables + db().queryMgr().updateTableRows + ( nodeTableName, setClause, whereClause, updateData, 1 ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to update table '" << nodeTableName << "'" + << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 10. Add the UK constraint on (nodeFullPath) + { + log() << coral::Info + << "Node table needs schema evolution" + << ": create UK constraint on (nodeFullPath)" + << " in table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + table.schemaEditor().setUniqueConstraint + ( RelationalNodeTable::columnNames::nodeFullPath, + nodeTableName+"_FULLPATH_UK" ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create UK constraint on (nodeFullPath)" + << " in table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 11. Add the UK constraint on (nodeId, nodeParentId) + { + std::vector<std::string> ukColumns; + ukColumns.push_back( RelationalNodeTable::columnNames::nodeId ); + ukColumns.push_back( RelationalNodeTable::columnNames::nodeParentId ); + log() << coral::Info + << "Node table needs schema evolution" + << ": create UK constraint on (nodeId, parentId)" + << " in table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( nodeTableName ); + try { + table.schemaEditor().setUniqueConstraint + ( ukColumns, nodeTableName+"_PARENT_UK" ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create UK constraint on (nodeId, parentId)" + << " in table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // Success + log() << coral::Info + << "Evolve node table schema (130->200)... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_evolveGlobalTagTable_130_200() +{ + log() << coral::Info + << "Evolve global tag table schema (130->200)... START" << coral::MessageStream::endmsg; + std::string globalTagTableName = db().globalTagTableName(); + + // 1. Add the tagLockStatus column and set its value to 0. + { + std::string columnName = + RelationalGlobalTagTable::columnNames::tagLockStatus; + const StorageType::TypeId columnTypeId = + RelationalGlobalTagTable::columnTypeIds::tagLockStatus; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + // Add the tagLockStatus column. + log() << coral::Info + << "Global tag table needs schema evolution" + << ": add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( globalTagTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + // Set the value of the tagLockStatus column to 0. + try { + std::string whereClause; // No WHERE clause + std::string setClause = columnName + "=0"; + coral::AttributeList updateData; // No bind variables + db().queryMgr().updateTableRows + ( globalTagTableName, setClause, whereClause, updateData ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to update table '" << globalTagTableName << "'" + << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 2. Recreate the PK on (nodeId, tagId) - invert the present order + { + log() << coral::Info + << "Global tag table needs schema evolution" + << ": recreate PK on (nodeId, tagId)" + << " in table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + std::vector<std::string> pkColumns; + pkColumns.push_back( RelationalGlobalTagTable::columnNames::nodeId ); + pkColumns.push_back( RelationalGlobalTagTable::columnNames::tagId ); + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( globalTagTableName ); + try { + table.schemaEditor().dropPrimaryKey(); + table.schemaEditor().setPrimaryKey( pkColumns ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to recreate PK on (nodeId, tagId)" + << " in table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 3. Add the UK constraint on tagName + { + log() << coral::Info + << "Global tag table needs schema evolution" + << ": create UK constraint on (tagName)" + << " in table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( globalTagTableName ); + try { + table.schemaEditor().setUniqueConstraint + ( RelationalTagTable::columnNames::tagName, + globalTagTableName+"_TAGNAME_UK" ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create UK constraint on (tagName)" + << " in table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 4. Add the FK constraint on nodeId to the NODES table + { + std::string columnNameSrc = + RelationalGlobalTagTable::columnNames::nodeId; + std::string columnNameTgt = + RelationalNodeTable::columnNames::nodeId; + std::string nodeTableName = db().nodeTableName(); + log() << coral::Info + << "Global tag table needs schema evolution" + << ": create FK reference from '" << columnNameSrc + << "' in table '" << globalTagTableName + << "' to '" << columnNameTgt + << "' in table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( globalTagTableName ); + try { + table.schemaEditor().createForeignKey + ( globalTagTableName + "_NODEID_FK", columnNameSrc, + nodeTableName, columnNameTgt ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create FK reference from '" << columnNameSrc + << "' in table '" << globalTagTableName + << "' to '" << columnNameTgt + << "' in table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // Success + log() << coral::Info + << "Evolve global tag table schema (130->200)... DONE" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_evolveTag2TagTable_130_200() +{ + log() << coral::Info + << "Evolve tag2tag table schema (130->200)... START" << coral::MessageStream::endmsg; + std::string tag2TagTableName = db().tag2TagTableName(); + + // 1. Add the FK constraint on the parent tag to the TAGS table + { + std::string globalTagTableName = db().globalTagTableName(); + std::vector<std::string> fkColumnsSrc; + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::parentNodeId ); + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::parentTagId ); + std::vector<std::string> fkColumnsTgt; + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::nodeId ); + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::tagId ); + log() << coral::Info + << "Tag2tag table needs schema evolution" + << ": create FK reference from parent tag" + << " in table '" << tag2TagTableName + << "' to parent tag" + << " in table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( tag2TagTableName ); + try { + table.schemaEditor().createForeignKey + ( tag2TagTableName + "_PTAG_FK", fkColumnsSrc, + globalTagTableName, fkColumnsTgt ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create FK reference from parent tag" + << " in table '" << tag2TagTableName + << "' to parent tag" + << " in table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 2. Add the FK constraint on the child tag to the TAGS table + { + std::string globalTagTableName = db().globalTagTableName(); + std::vector<std::string> fkColumnsSrc; + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::childNodeId ); + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::childTagId ); + std::vector<std::string> fkColumnsTgt; + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::nodeId ); + fkColumnsTgt.push_back + ( RelationalGlobalTagTable::columnNames::tagId ); + log() << coral::Info + << "Tag2tag table needs schema evolution" + << ": create FK reference from child tag" + << " in table '" << tag2TagTableName + << "' to child tag" + << " in table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( tag2TagTableName ); + try { + table.schemaEditor().createForeignKey + ( tag2TagTableName + "_CTAG_FK", fkColumnsSrc, + globalTagTableName, fkColumnsTgt ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create FK reference from child tag" + << " in table '" << tag2TagTableName + << "' to child tag" + << " in table '" << globalTagTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 3. Add the FK constraint on the parent/child to the NODES table + { + std::string nodeTableName = db().nodeTableName(); + std::vector<std::string> fkColumnsSrc; + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::childNodeId ); + fkColumnsSrc.push_back + ( RelationalTag2TagTable::columnNames::parentNodeId ); + std::vector<std::string> fkColumnsTgt; + fkColumnsTgt.push_back + ( RelationalNodeTable::columnNames::nodeId ); + fkColumnsTgt.push_back + ( RelationalNodeTable::columnNames::nodeParentId ); + log() << coral::Info + << "Tag2tag table needs schema evolution" + << ": create FK reference from parent/child" + << " in table '" << tag2TagTableName + << "' to parent/child" + << " in table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( tag2TagTableName ); + try { + table.schemaEditor().createForeignKey + ( tag2TagTableName + "_NODES_FK", fkColumnsSrc, + nodeTableName, fkColumnsTgt ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create FK reference from parent/child" + << " in table '" << tag2TagTableName + << "' to parent/child" + << " in table '" << nodeTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // Success + log() << coral::Info + << "Evolve tag2tag table schema (130->200)... DONE" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_createTagSharedSequence_130_200() +{ + log() << coral::Info + << "Create tag shared sequence (130->200)... START" << coral::MessageStream::endmsg; + const Record& dbAttr = db().databaseAttributes(); + std::string defaultTablePrefix = + dbAttr[RelationalDatabaseTable::attributeNames::defaultTablePrefix] + .data<std::string>(); + std::string tagSharedSequenceName = + RelationalTagSharedSequenceTable::defaultTableName( defaultTablePrefix ); + + // 1. Create the tag shared sequence + { + std::string nodeTableName = db().nodeTableName(); + log() << coral::Info + << "Database needs schema evolution" + << ": create tag shared sequence" + << " table '" << tagSharedSequenceName << "'" << coral::MessageStream::endmsg; + try { + db().schemaMgr().createSharedSequence + ( tagSharedSequenceName, nodeTableName ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create tag shared sequence" + << " table '" << tagSharedSequenceName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // Success + log() << coral::Info + << "Create tag shared sequence (130->200)... DONE" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_createIovSharedSequence_130_200() +{ + log() << coral::Info + << "Create IOV shared sequence (130->200)... START" << coral::MessageStream::endmsg; + const Record& dbAttr = db().databaseAttributes(); + std::string defaultTablePrefix = + dbAttr[RelationalDatabaseTable::attributeNames::defaultTablePrefix] + .data<std::string>(); + std::string iovSharedSequenceName = + RelationalIovSharedSequenceTable::defaultTableName( defaultTablePrefix ); + + // 1. Create the IOV shared sequence + { + std::string nodeTableName = db().nodeTableName(); + log() << coral::Info + << "Database needs schema evolution" + << ": create IOV shared sequence" + << " table '" << iovSharedSequenceName << "'" << coral::MessageStream::endmsg; + try { + db().schemaMgr().createSharedSequence + ( iovSharedSequenceName, nodeTableName ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create IOV shared sequence" + << " table '" << iovSharedSequenceName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // Success + log() << coral::Info + << "Create IOV shared sequence (130->200)... DONE" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_evolveIovTable_130_to_200 +( const RelationalTableRow& row ) +{ + log() << coral::Info + << "Evolve IOV table schema (130->200)... START" << coral::MessageStream::endmsg; + std::string fullPath = + row[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + std::string objectTableName = + row[RelationalNodeTable::columnNames::folderObjectTableName] + .data<std::string>(); + + // 1. Add the lastModDate column and set its value to NOW. + std::string columnName = RelationalObjectTable::columnNames::lastModDate(); + // Add the lastModDate column. + // This is done by simply altering the table to add the column at the end: + // with respect to tables created by COOL14x, the column order is different. + const StorageType::TypeId columnTypeId = + RelationalObjectTable::columnTypeIds::lastModDate; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + log() << coral::Info + << "Folder '" << fullPath << "' needs schema evolution" + << ": add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << objectTableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( objectTableName ); + try { + const bool fixedSize = false; + table.schemaEditor().insertColumn + ( columnName, + coral::AttributeSpecification::typeNameForId( columnType.cppType() ), + columnType.maxSize(), fixedSize ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to add column '" << columnName + << "' of type '" << columnType.name() + << "' to table '" << objectTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + // Set the value of the lastModDate column to NOW. + try { + std::string whereClause = ""; // No WHERE clause + std::string columnValue = RelationalQueryMgr::serverTimeClause + ( db().sessionMgr()->databaseTechnology() ); + std::string setClause = columnName + "=" + columnValue; + coral::AttributeList updateData; // No bind variables + db().queryMgr().updateTableRows + ( objectTableName, setClause, whereClause, updateData ); + } catch ( std::exception& e ) { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to update table '" << objectTableName << "'" + << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + + // Success + log() << coral::Info + << "Evolve IOV table schema (130->200)... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_evolveMainTable_130_to_200() +{ + log() << coral::Info + << "Evolve main table schema (130->200)... START" << coral::MessageStream::endmsg; + std::string mainTableName = db().mainTableName(); + + // 1a. Insert new rows: + // X_Y_Z_SE_OLD_RELEASE (previous RELEASE before X_Y_Z upgrade) + // X_Y_Z_SE_OLD_SCHEMA_VERSION (previous SCHEMA_VERSION before X_Y_Z upgrade) + // X_Y_Z_SE_TIME (time of the X_Y_Z upgrade) + RelationalDatabaseTable::columnTypes::attributeName attrName; + RelationalDatabaseTable::columnTypes::attributeValue attrValue; + try{ + const Record& dbAttr = db().databaseAttributes(); + std::string defaultTablePrefix = + dbAttr[RelationalDatabaseTable::attributeNames::defaultTablePrefix] + .data<std::string>(); + std::string oldRelease = + dbAttr[RelationalDatabaseTable::attributeNames::release] + .data<std::string>(); + std::string oldSchemaVersion = + dbAttr[RelationalDatabaseTable::attributeNames::schemaVersion] + .data<std::string>(); + coral::AttributeList data; + data.extend + ( RelationalDatabaseTable::columnNames::attributeName, + typeIdToCoralType + ( RelationalDatabaseTable::columnTypeIds::attributeName ) ); + data.extend + ( RelationalDatabaseTable::columnNames::attributeValue, + typeIdToCoralType + ( RelationalDatabaseTable::columnTypeIds::attributeValue ) ); + + // X_Y_Z_SE_OLD_RELEASE (previous RELEASE before X_Y_Z upgrade) + attrName = VersionInfo::schemaEvolutionPrefix + "OLD_" + + RelationalDatabaseTable::attributeNames::release; + attrValue = oldRelease; + data[RelationalDatabaseTable::columnNames::attributeName] + .setValue( attrName ); + data[RelationalDatabaseTable::columnNames::attributeValue] + .setValue( attrValue ); + db().queryMgr().insertTableRow( mainTableName, data ); + + // X_Y_Z_SE_OLD_SCHEMA_VERSION (previous SCHEMA_VERSION before XYZ upgrade) + attrName = VersionInfo::schemaEvolutionPrefix + "OLD_" + + RelationalDatabaseTable::attributeNames::schemaVersion; + attrValue = oldSchemaVersion; + data[RelationalDatabaseTable::columnNames::attributeName] + .setValue( attrName ); + data[RelationalDatabaseTable::columnNames::attributeValue] + .setValue( attrValue ); + db().queryMgr().insertTableRow( mainTableName, data ); + + // X_Y_Z_SE_TIME (time of the X_Y_Z upgrade) + // NB THIS ONLY INSERTS THE ROW - need SQL injection via UPDATE statement + attrName = VersionInfo::schemaEvolutionPrefix + "TIME"; + attrValue = RelationalQueryMgr::serverTimeClause + ( db().sessionMgr()->databaseTechnology() ); + RelationalQueryMgr::serverTimeClause + ( db().sessionMgr()->databaseTechnology() ); + data[RelationalDatabaseTable::columnNames::attributeName] + .setValue( attrName ); + data[RelationalDatabaseTable::columnNames::attributeValue] + .setValue( attrValue ); + db().queryMgr().insertTableRow( mainTableName, data ); + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to insert schema evolution metadata" + << " into table '" << mainTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + + // 1b. Update the value of X_Y_Z_SE_TIME + try + { + std::string whereClause = + RelationalDatabaseTable::columnNames::attributeName + + "='" + attrName + "'"; + std::string setClause = + RelationalDatabaseTable::columnNames::attributeValue + + "=" + attrValue; + coral::AttributeList updateData; // No bind variables + db().queryMgr().updateTableRows + ( mainTableName, setClause, whereClause, updateData, 1 ); + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to update table '" << mainTableName << "'" + << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + + // 2. Update the values of already existing rows. + try + { + coral::AttributeList updateData; + updateData.extend + ( "newAttrValue", + typeIdToCoralType + ( RelationalDatabaseTable::columnTypeIds::attributeValue ) ); + updateData.extend + ( "attrName", + typeIdToCoralType + ( RelationalDatabaseTable::columnTypeIds::attributeName ) ); + std::string setClause = + RelationalDatabaseTable::columnNames::attributeValue + "=:newAttrValue"; + std::string whereClause = + RelationalDatabaseTable::columnNames::attributeName + "=:attrName"; + // RELEASE (after X_Y_Z upgrade) + updateData["newAttrValue"].setValue<std::string> + ( VersionInfo::release ); + updateData["attrName"].setValue + ( RelationalDatabaseTable::attributeNames::release ); + db().queryMgr().updateTableRows + ( mainTableName, setClause, whereClause, updateData, 1 ); + // SCHEMA_VERSION (after X_Y_Z upgrade) + updateData["newAttrValue"].setValue<std::string> + ( VersionInfo::schemaVersion ); + updateData["attrName"].setValue + ( RelationalDatabaseTable::attributeNames::schemaVersion ); + db().queryMgr().updateTableRows + ( mainTableName, setClause, whereClause, updateData, 1 ); + // CVS_CHECKOUT (after X_Y_Z upgrade) + updateData["newAttrValue"].setValue<std::string> + ( VersionInfo::cvsCheckout ); + updateData["attrName"].setValue + ( RelationalDatabaseTable::attributeNames::cvsCheckout ); + db().queryMgr().updateTableRows + ( mainTableName, setClause, whereClause, updateData, 1 ); + // CVS_CHECKIN (after X_Y_Z upgrade) + updateData["newAttrValue"].setValue<std::string> + ( VersionInfo::cvsCheckin ); + updateData["attrName"].setValue + ( RelationalDatabaseTable::attributeNames::cvsCheckin ); + db().queryMgr().updateTableRows + ( mainTableName, setClause, whereClause, updateData, 1 ); + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to update table '" << mainTableName << "'" + << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + + // 3. Insert new rows with the names of the new top-level tables + try + { + const Record& dbAttr = db().databaseAttributes(); + std::string defaultTablePrefix = + dbAttr[RelationalDatabaseTable::attributeNames::defaultTablePrefix] + .data<std::string>(); + std::string tagSharedSequenceName = + RelationalTagSharedSequenceTable::defaultTableName( defaultTablePrefix ); + std::string iovSharedSequenceName = + RelationalIovSharedSequenceTable::defaultTableName( defaultTablePrefix ); + coral::AttributeList data; + data.extend + ( RelationalDatabaseTable::columnNames::attributeName, + typeIdToCoralType + ( RelationalDatabaseTable::columnTypeIds::attributeName ) ); + data.extend + ( RelationalDatabaseTable::columnNames::attributeValue, + typeIdToCoralType + ( RelationalDatabaseTable::columnTypeIds::attributeValue ) ); + RelationalDatabaseTable::columnTypes::attributeName attrName; + RelationalDatabaseTable::columnTypes::attributeValue attrValue; + + // Tag shared sequence name + attrName = RelationalDatabaseTable::attributeNames::tagSharedSequenceName; + attrValue = tagSharedSequenceName; + data[RelationalDatabaseTable::columnNames::attributeName] + .setValue( attrName ); + data[RelationalDatabaseTable::columnNames::attributeValue] + .setValue( attrValue ); + db().queryMgr().insertTableRow( mainTableName, data ); + + // IOV shared sequence name + attrName = RelationalDatabaseTable::attributeNames::iovSharedSequenceName; + attrValue = iovSharedSequenceName; + data[RelationalDatabaseTable::columnNames::attributeName] + .setValue( attrName ); + data[RelationalDatabaseTable::columnNames::attributeValue] + .setValue( attrValue ); + db().queryMgr().insertTableRow( mainTableName, data ); + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to insert names of new top-level tables" + << " into table '" << mainTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + + // Success + log() << coral::Info + << "Evolve main table schema (130->200)... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_createChannelsTable_130_to_200 +( const RelationalTableRow& row ) +{ + unsigned int nodeId = + row[RelationalNodeTable::columnNames::nodeId].data<unsigned int>(); + std::string channelTableName = + RelationalChannelTable::defaultTableName + ( db().defaultTablePrefix(), nodeId ); + log() << coral::Info + << "Creating channels table " << channelTableName + << " (130->200)..." << coral::MessageStream::endmsg; + db().schemaMgr().createChannelTable( channelTableName ); + log() << coral::Info + << "Creating channels table " << channelTableName + << " (130->200)... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_fillChannelsTableSV_130_to_200 +( const RelationalTableRow& row ) +{ + int folderVersioningMode = + row[RelationalNodeTable::columnNames::folderVersioningMode].data<int>(); + + // Only SV folders need to be updated + if ( folderVersioningMode != FolderVersioning::SINGLE_VERSION ) return; + + unsigned int nodeId = + row[RelationalNodeTable::columnNames::nodeId].data<unsigned int>(); + std::string channelTableName = + RelationalChannelTable::defaultTableName + ( db().defaultTablePrefix(), nodeId ); + log() << coral::Info + << "Fill the SV channels table " << channelTableName + << " (130->200)..." << coral::MessageStream::endmsg; + + std::string objectTableName = + row[RelationalNodeTable::columnNames::folderObjectTableName] + .data<std::string>(); + std::vector<ChannelId> channels = listChannels( objectTableName ); + + for ( std::vector<ChannelId>::const_iterator + ch = channels.begin(); ch != channels.end(); ++ch ) + { + //std::cout << "Channel: " << *ch << std::endl; + RelationalObjectTableRow objRow = fetchLastRow( objectTableName, *ch ); + bool hasNewData = false; + std::string channelName = ""; + std::string description = ""; + insertChannelTableRow( channelTableName, + *ch, + objRow.objectId(), + hasNewData, + channelName, + description ); + } + + log() << coral::Info + << "Fill the SV channels table " << channelTableName + << " (130->200)... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_updateNodeTable_130_to_200 +( const RelationalTableRow& row ) +{ + unsigned int nodeId = + row[RelationalNodeTable::columnNames::nodeId].data<unsigned int>(); + + // 1. Update FOLDER_CHANNELTABLENAME + { + std::string channelTableName = + RelationalChannelTable::defaultTableName + ( db().defaultTablePrefix(), nodeId ); + log() << coral::Info + << "Updating channels table name " << channelTableName + << " in node table (130->200)..." << coral::MessageStream::endmsg; + std::string columnName = + RelationalNodeTable::columnNames::folderChannelTableName; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::folderChannelTableName; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + coral::AttributeList updateData; + updateData.extend + ( "channelTableName", columnType.cppType() ); + updateData.extend + ( "nodeId", + StorageType::storageType + ( RelationalNodeTable::columnTypeIds::nodeId ).cppType() ); + updateData["channelTableName"] + .setValue<RelationalNodeTable::columnTypes::folderChannelTableName> + ( channelTableName ); + updateData["nodeId"]. + setValue<RelationalNodeTable::columnTypes::nodeId> + ( nodeId ); + std::string setClause = columnName + "=:channelTableName"; + std::string whereClause = + RelationalNodeTable::columnNames::nodeId + "=:nodeId"; + unsigned int expectedRows = 1; + if ( ! db().queryMgr().updateTableRows + ( db().nodeTableName(), setClause, whereClause, + updateData, expectedRows ) ) + { + log() << coral::Error + << "Failed to set value to in column '" << columnName + << "' of table '" << db().nodeTableName() << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + log() << coral::Info + << "Updating channels table name " << channelTableName + << " in node table (130->200)... DONE!" << coral::MessageStream::endmsg; + } + + // 2. Update FOLDER_PAYLOADSPEC + { + log() << coral::Info + << "Updating folder payload specification " + << " in node table (130->200)..." << coral::MessageStream::endmsg; + std::string oldSpecDesc = + row[RelationalNodeTable::columnNames::folderPayloadSpecDesc] + .data<std::string>(); + RecordSpecification spec = decodeRecordSpecification130( oldSpecDesc ); + std::string newSpecDesc = + RelationalDatabase::encodeRecordSpecification( spec ); + std::string columnName = + RelationalNodeTable::columnNames::folderPayloadSpecDesc; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::folderPayloadSpecDesc; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + coral::AttributeList updateData; + updateData.extend + ( "payloadSpecDesc", columnType.cppType() ); + updateData.extend + ( "nodeId", + StorageType::storageType + ( RelationalNodeTable::columnTypeIds::nodeId ).cppType() ); + updateData["payloadSpecDesc"] + .setValue<RelationalNodeTable::columnTypes::folderChannelTableName> + ( newSpecDesc ); + updateData["nodeId"]. + setValue<RelationalNodeTable::columnTypes::nodeId> + ( nodeId ); + std::string setClause = columnName + "=:payloadSpecDesc"; + std::string whereClause = + RelationalNodeTable::columnNames::nodeId + "=:nodeId"; + unsigned int expectedRows = 1; + if ( ! db().queryMgr().updateTableRows + ( db().nodeTableName(), setClause, whereClause, + updateData, expectedRows ) ) + { + log() << coral::Error + << "Failed to set value to in column '" << columnName + << "' of table '" << db().nodeTableName() << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + log() << coral::Info + << "Updating folder payload specification " + << " in node table (130->200)... DONE!" << coral::MessageStream::endmsg; + } +} + +//----------------------------------------------------------------------------- + +const RecordSpecification +RalSchemaEvolution::decodeRecordSpecification130 +( const std::string& encodedEALS ) +{ + RecordSpecification recordSpec; + if ( !encodedEALS.empty() ) { + std::string::size_type pos = 0; + while ( pos != encodedEALS.npos ) { + std::string::size_type newpos = encodedEALS.find( ',', pos ); + std::string item_str; + if ( newpos != encodedEALS.npos ) + item_str = encodedEALS.substr(pos,newpos-pos); + else + item_str = encodedEALS.substr(pos); + std::string::size_type separator_pos = item_str.find(':'); + if ( separator_pos == item_str.npos ) + throw RelationalException + ( std::string + ( "Bad format, ':' not found in encoded EALSpecification '" ) + + encodedEALS + "'", "RalSchemaEvolution" ); + recordSpec.extend + ( item_str.substr( 0, separator_pos ), + RalSchemaEvolution::storageType130 + ( item_str.substr( separator_pos+1 ) ) ); + pos = ( newpos != encodedEALS.npos ) ? newpos+1 : newpos; + } + } + return recordSpec; +} + +//----------------------------------------------------------------------------- + +const StorageType& +RalSchemaEvolution::storageType130( const std::string& name ) +{ + if ( name == "bool:DEF" ) + return StorageType::storageType( StorageType::Bool ); + //if ( name == "..." ) + // return StorageType::storageType( StorageType::Char ); // NOT IN 2.0.0 + if ( name == "unsigned char:DEF" ) + return StorageType::storageType( StorageType::UChar ); + if ( name == "short:DEF" ) + return StorageType::storageType( StorageType::Int16 ); + if ( name == "unsigned short:DEF" ) + return StorageType::storageType( StorageType::UInt16 ); + if ( name == "int:DEF" ) + return StorageType::storageType( StorageType::Int32 ); + if ( name == "long:DEF" ) + return StorageType::storageType( StorageType::Int32 ); // ONLY IN 1.3.0 + if ( name == "unsigned int:DEF" ) + return StorageType::storageType( StorageType::UInt32 ); + if ( name == "unsigned long:DEF" ) + return StorageType::storageType( StorageType::UInt32 ); // ONLY IN 1.3.0 + if ( name == "unsigned long long:uInt63" ) + return StorageType::storageType( StorageType::UInt63 ); + //if ( name == "..." ) + // return StorageType::storageType( StorageType::Int64 ); // NEW IN 2.0.0! + //if ( name == "..." ) + // return StorageType::storageType( StorageType::UInt64 ); // NOT IN 2.0.0 + if ( name == "float:DEF" ) + return StorageType::storageType( StorageType::Float ); + if ( name == "double:DEF" ) + return StorageType::storageType( StorageType::Double ); + if ( name == "string:255" ) + return StorageType::storageType( StorageType::String255 ); + if ( name == "string:4000" ) + return StorageType::storageType( StorageType::String4k ); + if ( name == "string:64K" ) + return StorageType::storageType( StorageType::String64k ); + if ( name == "string:16M" ) + return StorageType::storageType( StorageType::String16M ); + //if ( name == "..." ) + // return StorageType::storageType( StorageType::Blob64k ); // NEW IN 2.2.0! + //if ( name == "..." ) + // return StorageType::storageType( StorageType::Blob16M ); // NEW IN 2.2.0! + throw RelationalException + ( "PANIC! No 200 StorageType corresponds to 130 encoded type " + name, + "RalSchemaEvolution" ); +} + +//----------------------------------------------------------------------------- + +const std::vector<ChannelId> +RalSchemaEvolution::listChannels( const std::string& objectTableName ) const +{ + RecordSpecification rsetSpec; + std::string channelIdLabel = std::string( "DISTINCT " ) + + RelationalObjectTable::columnNames::channelId(); + rsetSpec.extend + ( channelIdLabel, RelationalObjectTable::columnTypeIds::channelId ); + std::string whereClause; + coral::AttributeList whereData; + std::vector<std::string> orderBy; + orderBy.push_back + ( RelationalObjectTable::columnNames::channelId() + " ASC" ); + std::vector<RelationalTableRow> rows = + db().queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( objectTableName ), + RelationalQueryMgr::columnList( rsetSpec ), + whereClause, whereData, orderBy, "" ); + std::vector<ChannelId> channels; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + ChannelId channel = + ( *row )[ channelIdLabel ] + .data<ChannelId>(); // PORT: possibly <unsigned int> needed here instead + channels.push_back( channel ); + } + return channels; +} + +//----------------------------------------------------------------------------- + +RelationalObjectTableRow +RalSchemaEvolution::fetchLastRow( const std::string& objectTableName, + const ChannelId& channelId ) +{ + // The "last object" inserted in each channel of a SV folder is retrieved + // as the object with the highest objectId in that channel (two possible + // alternatives could be to use the highest iovSince or iovUntil). + // The present algorithm uses two queries: + // 1. First, select max(objectId) in the given channel + // 2. Then, retrieve the full row for the object wih id=maxId + + // QUERY 1: select max(objectId) for the given channel + std::string maxObjectIdName = + std::string("MAX(") + RelationalObjectTable::columnNames::objectId() + ")"; + + RecordSpecification spec; + spec.extend( maxObjectIdName, + RelationalObjectTable::columnTypeIds::objectId ); + coral::AttributeList whereData; + whereData.extend + ( "channel", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::channelId) ); + whereData["channel"] + .data<RelationalObjectTable::columnTypes::channelId>() = channelId; + std::string whereClause = RelationalObjectTable::columnNames::channelId(); + whereClause += "= :channel"; + + // Delegate the query to the RalQueryMgr + ObjectId maxObjectId; + try { + std::string desc = ""; + RelationalTableRow maxObjectIdRow = db().queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( objectTableName ), + RelationalQueryMgr::columnList( spec ), + whereClause, whereData, desc ); + maxObjectId = maxObjectIdRow[ maxObjectIdName ].data<ObjectId>(); + } catch( NoRowsFound& ) { + throw ObjectNotFound + ( "max(objectId)", objectTableName, "RalSchemaEvolution" ); + } + + // QUERY 2: select * for objectId = max(objectId) + return + fetchRowForId( objectTableName, maxObjectId ); + +} + +//--------------------------------------------------------------------------- + +void RalSchemaEvolution::i_alterSqlTypes_130_to_200() +{ + log() << coral::Info + << "Alter SQL types (130->200)... START" << coral::MessageStream::endmsg; + + // Schema evolution of SQL types is only needed for MySQL and SQLite + std::string tech = db().sessionMgr()->databaseTechnology(); + if ( tech == "Oracle" ) + { + log() << coral::Info + << "Schema evolution of SQL types is NOT needed for technology '" + << tech << "'" << coral::MessageStream::endmsg; + } + else if ( tech == "frontier" ) + { + log() << coral::Error + << "Schema evolution is not possible for read/only technology '" + << tech << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + else if ( tech != "MySQL" && tech != "SQLite" ) + { + log() << coral::Error + << "Unknown technology '" << tech << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + else + { + log() << coral::Info + << "Schema evolution of SQL types is needed for technology '" + << tech << "'" << coral::MessageStream::endmsg; + const std::vector<std::string> tables = db().__listAllTables(); + std::vector<std::string>::const_iterator iTable; + for ( iTable = tables.begin(); iTable != tables.end(); iTable++ ) + { + std::string tableName = *iTable; + log() << coral::Info + << "Scan columns of table '" << tableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( tableName ); + int nCol = table.description().numberOfColumns(); + for ( int iCol = 0; iCol < nCol; iCol++ ) + { + const coral::IColumn& column = + table.description().columnDescription(iCol); + //log() << coral::Verbose + // << "--> Column '" << column.name() << "'" + // << ", type '" << column.type() << "'" + // << ", size=" << column.size() + // << ", isSizeFixed '" << column.isSizeFixed() << "'" + // << coral::MessageStream::endmsg; + const std::string name = column.name(); + std::string type = column.type(); + long size = column.size(); + const bool isSizeFixed = column.isSizeFixed(); + if ( ( tech=="SQLite" && ( type=="long" || type=="unsigned long" ) ) || + ( tech=="MySQL" && ( type=="string" && size==255 ) ) ) + //( tech=="MySQL" && ( type=="string" ) ) ) // disable TEXT BINARY + { + log() << coral::Info + << "Alter SQL type of column '" << name << "'" + << " (type " << type << ", size " << size << ")" + << " in table '" << tableName << "'" << coral::MessageStream::endmsg; + if ( tech=="SQLite" && type=="long" ) type="int"; + if ( tech=="SQLite" && type=="unsigned long" ) type="unsigned int"; + table.schemaEditor().changeColumnType + ( name, type, size, isSizeFixed ); + } + } + } + } + + // Success + log() << coral::Info + << "Alter SQL types (130->200)... DONE" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +const RelationalObjectTableRow +RalSchemaEvolution::fetchRowForId( const std::string& objectTableName, + const unsigned int objectId ) const +{ + // Define the WHERE clause for the selection using bind variables + coral::AttributeList whereData; + whereData.extend + ( "objectId", + typeIdToCoralType(RelationalObjectTable::columnTypeIds::objectId) ); + whereData["objectId"].setValue( objectId ); + std::string whereClause = RelationalObjectTable::columnNames::objectId(); + whereClause += "= :objectId"; + + // Delegate the query to the RelationalQueryMgr + try { + std::string desc = ""; + // Fetch only the IOV metadata, not the payload + return RelationalObjectTableRow + ( db().queryMgr().fetchRowFromTables + ( RelationalQueryMgr::tableList( objectTableName ), + RelationalQueryMgr::columnList + ( RelationalObjectTable::defaultSpecification() ), + whereClause, whereData, desc ) ); + } catch( NoRowsFound& ) { + std::stringstream s; + s << "object_id: " << objectId; + throw ObjectNotFound + ( s.str(), objectTableName, "RalSchemaEvolution" ); + } +} + +//--------------------------------------------------------------------------- + +void RalSchemaEvolution::insertChannelTableRow +( const std::string& channelTableName, + const ChannelId& channelId, + const unsigned int lastObjectId, + const bool hasNewData, + const std::string& channelName, + const std::string& description ) const +{ + coral::AttributeList data = + Record( RelationalChannelTable::tableSpecification() ).attributeList(); + data[RelationalChannelTable::columnNames::channelId()].setValue + ( channelId ); + data[RelationalChannelTable::columnNames::lastObjectId()].setValue + ( lastObjectId ); + data[RelationalChannelTable::columnNames::hasNewData()].setValue + ( hasNewData ); + if ( channelName != "" ) + data[RelationalChannelTable::columnNames::channelName()].setValue + ( channelName ); + else + data[RelationalChannelTable::columnNames::channelName()].setNull(); + data[RelationalChannelTable::columnNames::description()].setValue + ( description ); + db().queryMgr().insertTableRow( channelTableName, data ); +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::evolveDatabase_200_to_220() +{ + log() << coral::Info + << "Evolve database schema (200->220)..." << coral::MessageStream::endmsg; + + // ------------------------------------------------------------------- + // Alter selected SQL types of columns in all existing tables: + // ( 1) Alter MySQL "VARCHAR(255)" into "VARCHAR(255) BINARY" + // ------------------------------------------------------------------- + + i_alterSqlTypes_200_to_220(); + + // ------------------------------------------------------------------- + // Evolve each folder from 200 to 220 + // ( 1) Fill the channels tables of all MV folders + // (2a) Create the 5-column index for user tags (task #4381) if needed + // (2b) Add FK constraints (on channelId) to each IOV table + // ( 3) Update the node table with new folder schema versions '2.0.1' + // ------------------------------------------------------------------- + + i_evolveNodes_200_to_220(); + + // Success + log() << coral::Info + << "Evolve database schema (200->220)... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_alterSqlTypes_200_to_220() +{ + log() << coral::Info + << "Alter SQL types (200->220)... START" << coral::MessageStream::endmsg; + + // Schema evolution of SQL types is only needed for MySQL + std::string tech = db().sessionMgr()->databaseTechnology(); + if ( tech == "Oracle" || tech == "SQLite") + { + log() << coral::Info + << "Schema evolution of SQL types is NOT needed for technology '" + << tech << "'" << coral::MessageStream::endmsg; + } + else if ( tech == "frontier" ) + { + log() << coral::Error + << "Schema evolution is not possible for read/only technology '" + << tech << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + else if ( tech != "MySQL" ) + { + log() << coral::Error + << "Unknown technology '" << tech << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + else + { + log() << coral::Info + << "Schema evolution of SQL types is needed for technology '" + << tech << "'" << coral::MessageStream::endmsg; + const std::vector<std::string> tables = db().__listAllTables(); + std::vector<std::string>::const_iterator iTable; + for ( iTable = tables.begin(); iTable != tables.end(); iTable++ ) + { + std::string tableName = *iTable; + log() << coral::Info + << "Scan columns of table '" << tableName << "'" << coral::MessageStream::endmsg; + coral::ITable& table = db().sessionMgr()->session() + .nominalSchema().tableHandle( tableName ); + int nCol = table.description().numberOfColumns(); + for ( int iCol = 0; iCol < nCol; iCol++ ) + { + const coral::IColumn& column = + table.description().columnDescription(iCol); + //log() << coral::Verbose + // << "--> Column '" << column.name() << "'" + // << ", type '" << column.type() << "'" + // << ", size=" << column.size() + // << ", isSizeFixed '" << column.isSizeFixed() << "'" + // << coral::MessageStream::endmsg; + const std::string name = column.name(); + std::string type = column.type(); + long size = column.size(); + const bool isSizeFixed = column.isSizeFixed(); + if ( ( tech=="MySQL" && ( type=="string" && size==255 ) ) ) + { + log() << coral::Info + << "Alter SQL type of column '" << name << "'" + << " (type " << type << ", size " << size << ")" + << " in table '" << tableName << "'" << coral::MessageStream::endmsg; + if ( tech=="SQLite" && type=="long" ) type="int"; + if ( tech=="SQLite" && type=="unsigned long" ) type="unsigned int"; + table.schemaEditor().changeColumnType + ( name, type, size, isSizeFixed ); + } + } + } + } + + // Success + log() << coral::Info + << "Alter SQL types (200->220)... DONE" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_evolveNodes_200_to_220() +{ + log() << coral::Info + << "Evolve individual nodes (200->220) if needed..." << coral::MessageStream::endmsg; + + { + // List all folders ordered by nodeId + coral::AttributeList whereData; + whereData.extend + ( "isLeaf", + typeIdToCoralType(RelationalNodeTable::columnTypeIds::nodeIsLeaf) ); + whereData["isLeaf"].setValue + ( true ); // select folders only + std::string whereClause = RelationalNodeTable::columnNames::nodeIsLeaf; + whereClause += "= :isLeaf"; + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeId; + orderClause += " ASC"; + orderBy.push_back( orderClause ); + std::vector<RelationalTableRow> rows = + db().queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db().nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification + ( VersionNumber( "2.0.0" ) ) ), + whereClause, whereData, orderBy, "" ); + // Evolve all folders one by one + bool evolveNone = true; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + std::string fullPath = + (*row)[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + std::string nodeSchemaVersion = + (*row)[RelationalNodeTable::columnNames::nodeSchemaVersion] + .data<std::string>(); + if ( nodeSchemaVersion != + std::string( RelationalFolder::folderSchemaVersion() ) ) + { + evolveNone = false; + log() << coral::Info + << "Folder '" << fullPath << "' needs schema evolution" + << " from schema version '" << nodeSchemaVersion + << "' to '" << RelationalFolder::folderSchemaVersion() + << "'" << coral::MessageStream::endmsg; + i_fillChannelsTableMV_200_to_220( *row ); + i_evolveIovTable_200_to_220( *row ); + i_updateNodeTable_200_to_220( *row ); + } + else + { + log() << coral::Verbose + << "Folder '" << fullPath << "' is already schema version '" + << RelationalFolder::folderSchemaVersion() + << "' and needs no schema evolution" << coral::MessageStream::endmsg; + } + } + if ( evolveNone ) + log() << coral::Info + << "All folders are already schema version '" + << RelationalFolder::folderSchemaVersion() + << "' and need no schema evolution" << coral::MessageStream::endmsg; + } + + // Success + log() << coral::Info + << "Evolve individual nodes (200->220) if needed... DONE!" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_fillChannelsTableMV_200_to_220 +( const RelationalTableRow& row ) +{ + int folderVersioningMode = + row[RelationalNodeTable::columnNames::folderVersioningMode].data<int>(); + + // Only MV folders need to be updated + if ( folderVersioningMode != FolderVersioning::MULTI_VERSION ) return; + + unsigned int nodeId = + row[RelationalNodeTable::columnNames::nodeId].data<unsigned int>(); + std::string channelTableName = + RelationalChannelTable::defaultTableName + ( db().defaultTablePrefix(), nodeId ); + log() << coral::Info + << "Fill the MV channels table " << channelTableName + << " (200->220)..." << coral::MessageStream::endmsg; + + std::string objectTableName = + row[RelationalNodeTable::columnNames::folderObjectTableName] + .data<std::string>(); + std::vector<ChannelId> channels = listChannels( objectTableName ); + + for ( std::vector<ChannelId>::const_iterator + ch = channels.begin(); ch != channels.end(); ++ch ) + { + log() << coral::Verbose + << "Fill the MV channels table " << channelTableName + << " (200->220)..." + << " Insert channel: " << *ch << coral::MessageStream::endmsg; + RelationalObjectTableRow objRow = fetchLastRow( objectTableName, *ch ); + bool hasNewData = false; + std::string channelName = ""; + std::string description = ""; + // Avoid CORAL error messages by changing the output level + coral::MsgLevel outputLevel = coral::MessageStream::msgVerbosity(); + try + { + //coral::MessageStream::setMsgVerbosity( coral::Fatal ); + insertChannelTableRow( channelTableName, + *ch, + objRow.objectId(), + hasNewData, + channelName, + description ); + coral::MessageStream::setMsgVerbosity( outputLevel ); + } + // Ignore any rows already present in the channels table (fix bug #30361) + catch ( coral::DuplicateEntryInUniqueKeyException& ) + { + coral::MessageStream::setMsgVerbosity( outputLevel ); // OK? + log() << coral::Warning + << "Fill the MV channels table " << channelTableName + << " (200->220)..." + << " channel " << *ch << " already exists" << coral::MessageStream::endmsg; + } + // Debug printout for bug #45716 + catch ( std::exception& e ) + { + coral::MessageStream::setMsgVerbosity( outputLevel ); // OK? + log() << coral::Warning + << "Fill the MV channels table " << channelTableName + << " (200->220)..." + << " Exception caught while inserting channel " << *ch + << ": " << e.what() << coral::MessageStream::endmsg; + log() << coral::Warning + << "Exception will be rethrown" << coral::MessageStream::endmsg; + throw; + } + } + + log() << coral::Info + << "Fill the MV channels table " << channelTableName + << " (200->220)... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_evolveIovTable_200_to_220 +( const RelationalTableRow& row ) +{ + log() << coral::Info + << "Evolve IOV table schema (200->220)... START" << coral::MessageStream::endmsg; + std::string fullPath = + row[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + std::string objectTableName = + row[RelationalNodeTable::columnNames::folderObjectTableName] + .data<std::string>(); + std::string channelTableName = + row[RelationalNodeTable::columnNames::folderChannelTableName] + .data<std::string>(); + + // 1. Add the 5-column index for user tags (task #4381) if needed + { + std::string indexName = objectTableName + "_UTAG_5INDX"; + log() << coral::Info + << "Folder '" << fullPath << "' needs schema evolution" + << ": add index '" << indexName + << "' to table '" << objectTableName + << "' if needed" << coral::MessageStream::endmsg; + try + { + coral::ITable& objectTable = db().sessionMgr()->session() + .nominalSchema().tableHandle( objectTableName ); + const coral::ITableDescription& description = objectTable.description(); + unsigned int nInd = description.numberOfIndices(); + bool indexExists = false; + for ( unsigned iInd = 0; iInd < nInd; iInd++ ) + { + if ( description.index( iInd ).name() == indexName ) + indexExists = true; + } + if ( !indexExists ) + { + coral::ITableSchemaEditor& editor = objectTable.schemaEditor(); + std::vector<std::string> indColumns; + indColumns.push_back + ( RelationalObjectTable::columnNames::userTagId() ); + indColumns.push_back + ( RelationalObjectTable::columnNames::newHeadId() ); + indColumns.push_back + ( RelationalObjectTable::columnNames::channelId() ); + indColumns.push_back + ( RelationalObjectTable::columnNames::iovSince() ); + indColumns.push_back + ( RelationalObjectTable::columnNames::iovUntil() ); + bool unique = true; + editor.createIndex( indexName, indColumns, unique ); + } + else + { + log() << coral::Info + << "Index '" << indexName << "' already exists in table '" + << objectTableName << coral::MessageStream::endmsg; + } + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed add index '" << indexName + << "' to table '" << objectTableName << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // 2. Add the FK constraint from the object table to the channel table + { + log() << coral::Info + << "Folder '" << fullPath << "' needs schema evolution" + << ": create FK reference from channels" + << " in table '" << objectTableName + << "' to channels" + << " in table '" << channelTableName << "'" << coral::MessageStream::endmsg; + try + { + db().schemaMgr().createObjectChannelFK + ( objectTableName, channelTableName ); + } + catch ( std::exception& e ) + { + log() << coral::Error + << "Exception caught: '" << e.what() << "'" << coral::MessageStream::endmsg; + log() << coral::Error + << "Failed to create FK reference from channels" + << " in table '" << objectTableName + << "' to channels" + << " in table '" << channelTableName << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + } + + // Success + log() << coral::Info + << "Evolve IOV table schema (200->220)... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaEvolution::i_updateNodeTable_200_to_220 +( const RelationalTableRow& row ) +{ + unsigned int nodeId = + row[RelationalNodeTable::columnNames::nodeId].data<unsigned int>(); + + // 1. Update NODE_SCHEMA_VERSION + { + log() << coral::Info + << "Updating folder schema version " + << RelationalFolder::folderSchemaVersion() + << " in node table (200->220)..." << coral::MessageStream::endmsg; + std::string columnName = + RelationalNodeTable::columnNames::nodeSchemaVersion; + const StorageType::TypeId columnTypeId = + RelationalNodeTable::columnTypeIds::nodeSchemaVersion; + const cool::StorageType& columnType = + StorageType::storageType( columnTypeId ); + coral::AttributeList updateData; + updateData.extend + ( "nodeSchemaVersion", columnType.cppType() ); + updateData.extend + ( "nodeId", + StorageType::storageType + ( RelationalNodeTable::columnTypeIds::nodeId ).cppType() ); + updateData["nodeSchemaVersion"] + .setValue<RelationalNodeTable::columnTypes::folderChannelTableName> + ( RelationalFolder::folderSchemaVersion() ); + updateData["nodeId"]. + setValue<RelationalNodeTable::columnTypes::nodeId> + ( nodeId ); + std::string setClause = columnName + "=:nodeSchemaVersion"; + std::string whereClause = + RelationalNodeTable::columnNames::nodeId + "=:nodeId"; + unsigned int expectedRows = 1; + if ( ! db().queryMgr().updateTableRows + ( db().nodeTableName(), setClause, whereClause, + updateData, expectedRows ) ) + { + log() << coral::Error + << "Failed to set value to in column '" << columnName + << "' of table '" << db().nodeTableName() << "'" << coral::MessageStream::endmsg; + throw RelationalException + ( "Schema evolution failed", "RalSchemaEvolution" ); + } + log() << coral::Info + << "Updating folder schema version " + << RelationalFolder::folderSchemaVersion() + << " in node table (200->220)... DONE!" << coral::MessageStream::endmsg; + } +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/utilities/coolEvolveSchema/RalSchemaEvolution.h b/RelationalCool/utilities/coolEvolveSchema/RalSchemaEvolution.h new file mode 100644 index 000000000..e22c8e8f8 --- /dev/null +++ b/RelationalCool/utilities/coolEvolveSchema/RalSchemaEvolution.h @@ -0,0 +1,162 @@ +// $Id: RalSchemaEvolution.h,v 1.32 2008-04-10 15:31:15 avalassi Exp $ +#ifndef RELATIONALCOOL_RALSCHEMAEVOLUTION_H +#define RELATIONALCOOL_RALSCHEMAEVOLUTION_H 1 + +// Include files +#include <boost/shared_ptr.hpp> +#include "CoolKernel/DatabaseId.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoralBase/MessageStream.h" +#include "RelationalAccess/IConnectionService.h" + +// Local include files +#include "../../src/CoralConnectionServiceProxy.h" + +namespace cool +{ + + // Forward declarations + class RalDatabase; + class RelationalObjectTableRow; + class RelationalTableRow; + + /** @class RalSchemaEvolution RalSchemaEvolution.h + * + * Private utility class to implement COOL relational schema evolution. + * + * @author Andrea Valassi + * @date 2006-03-15 + */ + + class RalSchemaEvolution + { + + public: + + /// Constructor + RalSchemaEvolution( CoralConnectionServiceProxyPtr ppConnSvc, + const DatabaseId& dbId ); + + /// Destructor + virtual ~RalSchemaEvolution(); + + /// Evolve the schema of the full database to version 220. + /// Encapsulate schema evolution in a single transaction. + void evolveDatabase(); + + protected: + + /// Get a CORAL MessageStream + coral::MessageStream& log(); + + /// Get the RalDatabase reference + const RalDatabase& db() const { return *m_db; } + + /// --- SCHEMA EVOLUTION FROM COOL_1_3_0 TO COOL_2_0_0 + + /// Evolve the schema of the full database (130->200). + void evolveDatabase_130_to_200(); + + /// Evolve the schema of the node table (130->200). + void i_evolveNodeTable_130_200(); + + /// Evolve the schema of the global tag table (130->200). + void i_evolveGlobalTagTable_130_200(); + + /// Evolve the schema of the tag2tag table (130->200). + void i_evolveTag2TagTable_130_200(); + + /// Create the tag shared sequence (130->200). + void i_createTagSharedSequence_130_200(); + + /// Create the IOV shared sequence (130->200). + void i_createIovSharedSequence_130_200(); + + /// Evolve the IOV table schema for a given folder (130->200). + void i_evolveIovTable_130_to_200( const RelationalTableRow& row ); + + /// Create the channels table for a given folder (130->200). + void i_createChannelsTable_130_to_200( const RelationalTableRow& row ); + + /// Fill the channels tables for a given SV folder (130->200). + void i_fillChannelsTableSV_130_to_200( const RelationalTableRow& row ); + + /// Update node table with updated values for a given folder (130->200). + void i_updateNodeTable_130_to_200( const RelationalTableRow& row ); + + /// Evolve the schema and contents of the main table (130->200). + void i_evolveMainTable_130_to_200(); + + /// Alter selected SQL types in all tables (130->200, MySQL/sqlite only). + void i_alterSqlTypes_130_to_200(); + + /// Decode a 200 RecordSpecification from a 130 encoded 'extended' EALS + static const RecordSpecification + decodeRecordSpecification130( const std::string& encodedEALS ); + + /// Decode a 200 StorageType from a 130 encoded type specification + static const StorageType& + storageType130( const std::string& encodedType ); + + const std::vector<ChannelId> + listChannels( const std::string& objectTableName ) const; + + RelationalObjectTableRow + fetchLastRow( const std::string& objectTableName, + const ChannelId& channelId ); + + const RelationalObjectTableRow + fetchRowForId( const std::string& objectTableName, + const unsigned int objectId ) const; + + void insertChannelTableRow( const std::string& channelTableName, + const ChannelId& channelId, + const unsigned int lastObjectId, + const bool hasNewData, + const std::string& channelName, + const std::string& description ) const; + + /// --- SCHEMA EVOLUTION FROM COOL_2_0_0 TO COOL_2_2_0 + + /// Evolve SQL types and the schema of individual nodes (200->220). + void evolveDatabase_200_to_220(); + + /// Alter selected SQL types in all tables (200->220, MySQL only). + void i_alterSqlTypes_200_to_220(); + + /// Evolve the schema of individual nodes (200->220). + void i_evolveNodes_200_to_220(); + + /// Fill the channels tables for a given MV folder (200->220). + void i_fillChannelsTableMV_200_to_220( const RelationalTableRow& row ); + + /// Evolve the IOV table schema for a given folder (200->220). + void i_evolveIovTable_200_to_220( const RelationalTableRow& row ); + + /// Update node table with updated values for a given folder (200->220). + void i_updateNodeTable_200_to_220( const RelationalTableRow& row ); + + private: + + /// Standard constructor is private + RalSchemaEvolution(); + + /// Copy constructor is private + RalSchemaEvolution( const RalSchemaEvolution& rhs ); + + /// Assignment operator is private + RalSchemaEvolution& operator=( const RalSchemaEvolution& rhs ); + + private: + + /// RalDatabase pointer + RalDatabase* m_db; + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + }; + +} + +#endif // RELATIONALCOOL_RALSCHEMAEVOLUTION_H diff --git a/RelationalCool/utilities/coolEvolveSchema/coolEvolveSchema.cpp b/RelationalCool/utilities/coolEvolveSchema/coolEvolveSchema.cpp new file mode 100644 index 000000000..f26a8ed7a --- /dev/null +++ b/RelationalCool/utilities/coolEvolveSchema/coolEvolveSchema.cpp @@ -0,0 +1,96 @@ +// $Id: coolEvolveSchema.cpp,v 1.15 2008-04-10 15:31:15 avalassi Exp $ + +// Include files +#include <iostream> +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" + +// Local include files +#include "RalSchemaEvolution.h" +#include "../../src/CoralApplication.h" +#include "../../src/CoralConnectionServiceProxy.h" +#include "../../src/RalDatabase.h" +#include "../../src/VersionInfo.h" + +// Namespace +using namespace cool; + +// Message output +#define LOG std::cout + +//----------------------------------------------------------------------------- + +int main( int argc, char** argv ) +{ + + try { + + // Get the command line arguments + std::string dbId; + if ( argc != 2 ) { + LOG << "Usage: " << argv[0] << " dbId" << std:: endl; + std::string dbIdOra = + "oracle://SERVER;schema=USER1;dbname=DB;user=USER1"; + LOG << "Example: " << argv[0] << " '" << dbIdOra << "'\n" << std::endl; + return 1; + } + else { + dbId = argv[1]; + } + + // Instantiate a COOL Application + CoralApplication app; + + // If we can access a LFC and the user is not explicitely forbidding it, + // we try to use CORAL LFCReplicaService + if ( ::getenv("COOL_IGNORE_LFC") == NULL && + ::getenv("LFC_HOST") != NULL ) + { + // try to load CORAL LFCReplicaService + coral::IConnectionServiceConfiguration &connSvcConf = + app.connectionSvc().configuration(); + connSvcConf.setAuthenticationService("CORAL/Services/LFCReplicaService"); + connSvcConf.setLookupService("CORAL/Services/LFCReplicaService"); + } + + // Create a schema evolution manager + cool::CoralConnectionServiceProxyPtr ppConnSvc + ( new cool::CoralConnectionServiceProxy( &app.connectionSvc() ) ); + RalSchemaEvolution se( ppConnSvc, dbId ); + + // Evolve the schema of the whole database + se.evolveDatabase(); + + // Close the session manager access to the CORAL connection service + ppConnSvc->purgeConnectionPool(); + ppConnSvc->resetICS(); + + } + + catch( cool::Exception& e ) + { + LOG << "ERROR! Cool Exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( std::exception& e ) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( ... ) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + return 1; + } + + // Successful program termination + LOG << "Schema evolution successfully completed" << std::endl; + return 0; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/utilities/coolPrivileges/RalPrivilegeManager.cpp b/RelationalCool/utilities/coolPrivileges/RalPrivilegeManager.cpp new file mode 100644 index 000000000..85ed7f90e --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/RalPrivilegeManager.cpp @@ -0,0 +1,510 @@ +// $Id: RalPrivilegeManager.cpp,v 1.12 2009-01-06 11:52:12 avalassi Exp $ + +// Include files +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ITable.h" + +// Local include files +// [NB Weird: a transaction is needed to avoid OCI_INVALID_HANDLE...] +// [See http://dbforums.com/t394084.html] +#include "RalPrivilegeManager.h" +#include "../../src/RalDatabase.h" +#include "../../src/RelationalException.h" +#include "../../src/RelationalFolder.h" +#include "../../src/RelationalFolderSet.h" +#include "../../src/RelationalNodeTable.h" +#include "../../src/RelationalObjectTable.h" +#include "../../src/RelationalTagSequence.h" +#include "../../src/RelationalTagTable.h" +#include "../../src/RelationalTag2TagTable.h" +#include "../../src/RelationalTransaction.h" + +// Workaround for Windows (win32_vc9_dbg) +// DELETE seems to be defined in a Windows VC9 header +// See also CoolKernel/CoolKernel/MessageLevels.h +// See also RelationalCool/src/CoralApplication.cpp +#ifdef WIN32 +#ifdef DELETE +#undef DELETE +#pragma message ("WARN!NG: in coolPrivileges/RalPrivilegeManager.cpp") +#pragma message ("WARN!NG: 'DELETE' was defined and has been undefined") +#endif +#endif + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RalPrivilegeManager::RalPrivilegeManager( RalDatabase* db ) + : m_db( db ) + , m_log( new coral::MessageStream + ( "RalPrivilegeManager" ) ) +{ + log() << coral::Debug << "Instantiate a RalPrivilegeManager for '" + << m_db->databaseId() << "'" << coral::MessageStream::endmsg; + m_fourPrivs.push_back( SELECT ); + m_fourPrivs.push_back( INSERT ); + m_fourPrivs.push_back( UPDATE ); + m_fourPrivs.push_back( DELETE ); + // This class can only be used with "oracle" database technology + if ( m_db->sessionMgr()->databaseTechnology() != "Oracle" ) { + throw RelationalException + ( "Unsupported technology '" + m_db->sessionMgr()->databaseTechnology() + + "' for database privilege management ", "RalPrivilegeManager" ); + } +} + +//----------------------------------------------------------------------------- + +RalPrivilegeManager::~RalPrivilegeManager() +{ + log() << coral::Debug << "Delete the RalPrivilegeManager for '" + << m_db->databaseId() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RalPrivilegeManager::log() { + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +std::vector< std::string > +RalPrivilegeManager::i_listReaderTables( const Privilege& priv ) +{ + std::vector< std::string > tables; + + // Tables with SELECT privileges + if ( priv == SELECT ) { + + // Main table + tables.push_back + ( m_db->mainTableName() ); + + // Node table and sequence + tables.push_back + ( m_db->nodeTableName() ); + tables.push_back + ( RelationalNodeTable::sequenceName( m_db->nodeTableName() ) ); + + // Global tag table + tables.push_back + ( m_db->globalTagTableName() ); + + // Tag2tag table and sequence + tables.push_back + ( m_db->tag2TagTableName() ); + tables.push_back + ( RelationalTag2TagTable::sequenceName( m_db->tag2TagTableName() ) ); + + // Tag shared sequence + tables.push_back + ( m_db->tagSharedSequenceName() ); + + // Object shared sequence + tables.push_back + ( m_db->iovSharedSequenceName() ); + + // Loop over all nodes in the database + std::vector<std::string> nodes( m_db->listAllNodes( false ) ); + std::vector<std::string>::const_iterator node; + for ( node = nodes.begin(); node != nodes.end(); node++ ) { + // Process folders + try { + IFolderPtr folder = m_db->getFolder( *node ); + RelationalFolder* relFolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + // Object table and sequence + tables.push_back + ( relFolder->objectTableName() ); + tables.push_back + ( RelationalObjectTable::sequenceName + ( relFolder->objectTableName() ) ); + // Channel table + tables.push_back + ( relFolder->channelTableName() ); + // Tag table and sequence and object2tag table (MV only) + if ( relFolder->versioningMode() == FolderVersioning::MULTI_VERSION ) { + tables.push_back + ( relFolder->tagTableName() ); + tables.push_back + ( RelationalTagSequence::sequenceName + ( m_db->defaultTablePrefix(), relFolder->id() ) ); + tables.push_back + ( relFolder->object2TagTableName() ); + } + } + catch ( FolderNotFound& e ) { + if ( ! e.isFolderSet() ) throw; + } + // Process folder sets + try { + IFolderSetPtr folderSet = m_db->getFolderSet( *node ); + RelationalFolderSet* relFolderSet = + dynamic_cast<RelationalFolderSet*>( folderSet.get() ); + if ( priv == SELECT ) { + // Local tag sequence + tables.push_back + ( RelationalTagSequence::sequenceName + ( m_db->defaultTablePrefix(), relFolderSet->id() ) ); + } + } + catch ( FolderSetNotFound& e ) { + if ( ! e.isFolder() ) throw; + } + } + } + + // Tables with INSERT or UPDATE or DELETE privileges + else if ( priv == INSERT || priv == UPDATE || priv == DELETE ) { + // No tables! + } + + // Unknown privilege + else { + throw RelationalException + ( "PANIC! Unknown privilege", "RalPrivilegeManager" ); + } + + return tables; + +} + +//----------------------------------------------------------------------------- + +std::vector< std::string > +RalPrivilegeManager::i_listWriterTables( const Privilege& priv ) +{ + std::vector< std::string > tables; + + // Tables with SELECT privileges + if ( priv == SELECT ) { + // No tables! Reader privileges must be granted explcitly! + //tables = i_listReaderTables( SELECT ); + } + + // Tables with INSERT or UPDATE privileges + else if ( priv == INSERT || priv == UPDATE ) { + + if ( priv == UPDATE ) { + // UPDATE: object shared sequence + tables.push_back + ( m_db->iovSharedSequenceName() ); + } + + // Loop over all nodes in the database + std::vector<std::string> nodes( m_db->listAllNodes( false ) ); + std::vector<std::string>::const_iterator node; + for ( node = nodes.begin(); node != nodes.end(); node++ ) { + try { + IFolderPtr folder = m_db->getFolder( *node ); + RelationalFolder* relFolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + if ( priv == INSERT ) { + // INSERT: object table, channel table + tables.push_back + ( relFolder->objectTableName() ); + tables.push_back + ( relFolder->channelTableName() ); + } else { + // UPDATE: object table and sequence, channel table + tables.push_back + ( relFolder->objectTableName() ); + tables.push_back + ( RelationalObjectTable::sequenceName + ( relFolder->objectTableName() ) ); + tables.push_back + ( relFolder->channelTableName() ); + } + } + catch ( FolderNotFound& e ) { + if ( ! e.isFolderSet() ) throw; + } + } + } + + // Tables with DELETE privileges + else if ( priv == DELETE ) { + // No tables! + } + + // Unknown privilege + else { + throw RelationalException + ( "PANIC! Unknown privilege", "RalPrivilegeManager" ); + } + + return tables; + +} + +//----------------------------------------------------------------------------- + +std::vector< std::string > +RalPrivilegeManager::i_listTaggerTables( const Privilege& priv, + const bool retag ) +{ + std::vector< std::string > tables; + + // Tables with SELECT privileges + if ( priv == SELECT ) { + // No tables! Reader privileges must be granted explcitly! + //tables = i_listReaderTables( SELECT ); + } + + // Tables with INSERT or UPDATE or DELETE privileges + else if ( priv == INSERT || priv == UPDATE || priv == DELETE ) { + + if ( priv == INSERT ) { + // INSERT: global tag and tag2tag tables + tables.push_back + ( m_db->globalTagTableName() ); + tables.push_back + ( m_db->tag2TagTableName() ); + } else if ( priv == UPDATE ) { + // UPDATE: tag shared sequence and tag2tag sequence + tables.push_back + ( m_db->tagSharedSequenceName() ); + tables.push_back + ( RelationalTag2TagTable::sequenceName( m_db->tag2TagTableName() ) ); + } else { + // DELETE: global tag and tag2tag table (only for retagging) + if ( retag ) { + tables.push_back + ( m_db->globalTagTableName() ); + tables.push_back + ( m_db->tag2TagTableName() ); + } + } + + // Loop over all nodes in the database + std::vector<std::string> nodes( m_db->listAllNodes( false ) ); + std::vector<std::string>::const_iterator node; + for ( node = nodes.begin(); node != nodes.end(); node++ ) { + // Process folders + try { + IFolderPtr folder = m_db->getFolder( *node ); + RelationalFolder* relFolder = + dynamic_cast<RelationalFolder*>( folder.get() ); + // MV folders only + if ( relFolder->versioningMode() == FolderVersioning::MULTI_VERSION ) { + if ( priv == INSERT ) { + // INSERT: local tag and object2tag table + tables.push_back + ( relFolder->tagTableName() ); + tables.push_back + ( relFolder->object2TagTableName() ); + } else if ( priv == UPDATE ) { + // UPDATE: local tag sequence + tables.push_back + ( RelationalTagSequence::sequenceName + ( m_db->defaultTablePrefix(), relFolder->id() ) ); + } else { + // DELETE: local tag and object2tag table (only for retagging) + if ( retag ) { + tables.push_back + ( relFolder->tagTableName() ); + tables.push_back + ( relFolder->object2TagTableName() ); + } + } + } + } + catch ( FolderNotFound& e ) { + if ( ! e.isFolderSet() ) throw; + } + // Process folder sets + try { + IFolderSetPtr folderSet = m_db->getFolderSet( *node ); + RelationalFolderSet* relFolderSet = + dynamic_cast<RelationalFolderSet*>( folderSet.get() ); + if ( priv == UPDATE ) { + // UPDATE: local tag sequence + tables.push_back + ( RelationalTagSequence::sequenceName + ( m_db->defaultTablePrefix(), relFolderSet->id() ) ); + } + } + catch ( FolderSetNotFound& e ) { + if ( ! e.isFolder() ) throw; + } + } + } + + // Unknown privilege + else { + throw RelationalException + ( "PANIC! Unknown privilege", "RalPrivilegeManager" ); + } + + return tables; + +} + +//----------------------------------------------------------------------------- + +coral::ITablePrivilegeManager& +RalPrivilegeManager::i_tablePrivMgr( const std::string& tableName ) +{ + coral::ITable& tableHandle = + m_db->session().nominalSchema().tableHandle( tableName ); + return tableHandle.privilegeManager(); +} + +//----------------------------------------------------------------------------- + +void RalPrivilegeManager::i_grantPrivilege( const Privilege& priv, + const std::string& table, + const std::string& user ) +{ + coral::ITablePrivilegeManager::Privilege ralPriv; + if ( priv == SELECT ) + ralPriv = coral::ITablePrivilegeManager::Select; + else if ( priv == INSERT ) + ralPriv = coral::ITablePrivilegeManager::Insert; + else if ( priv == UPDATE ) + ralPriv = coral::ITablePrivilegeManager::Update; + else if ( priv == DELETE ) + ralPriv = coral::ITablePrivilegeManager::Delete; + else + throw RelationalException + ( "PANIC! Unknown privilege", "RalPrivilegeManager" ); + i_tablePrivMgr( table ).grantToUser( user, ralPriv ); +} + +//----------------------------------------------------------------------------- + +void RalPrivilegeManager::i_revokePrivilege( const Privilege& priv, + const std::string& table, + const std::string& user ) +{ + coral::ITablePrivilegeManager::Privilege ralPriv; + if ( priv == SELECT ) + ralPriv = coral::ITablePrivilegeManager::Select; + else if ( priv == INSERT ) + ralPriv = coral::ITablePrivilegeManager::Insert; + else if ( priv == UPDATE ) + ralPriv = coral::ITablePrivilegeManager::Update; + else if ( priv == DELETE ) + ralPriv = coral::ITablePrivilegeManager::Delete; + else + throw RelationalException + ( "PANIC! Unknown privilege", "RalPrivilegeManager" ); + i_tablePrivMgr( table ).revokeFromUser( user, ralPriv ); +} + +//----------------------------------------------------------------------------- + +void RalPrivilegeManager::grantReaderPrivileges( const std::string& user ) +{ + log() << "Grant reader role privileges to user '" << user << "'" + << coral::MessageStream::endmsg; + std::vector<Privilege>::const_iterator priv; + for ( priv = m_fourPrivs.begin(); priv != m_fourPrivs.end(); priv++ ) { + std::vector<std::string> tables( i_listReaderTables( *priv ) ); + std::vector<std::string>::const_iterator table; + RelationalTransaction transaction( m_db->transactionMgr() ); // read-write + for ( table = tables.begin(); table != tables.end(); table++ ) { + i_grantPrivilege( *priv, *table, user ); + } + transaction.commit(); + } +} + +//----------------------------------------------------------------------------- + +void RalPrivilegeManager::revokeReaderPrivileges( const std::string& user ) +{ + log() << "Revoke reader role privileges from user '" << user << "'" + << coral::MessageStream::endmsg; + std::vector<Privilege>::const_iterator priv; + for ( priv = m_fourPrivs.begin(); priv != m_fourPrivs.end(); priv++ ) { + std::vector<std::string> tables( i_listReaderTables( *priv ) ); + std::vector<std::string>::const_iterator table; + RelationalTransaction transaction( m_db->transactionMgr() ); // read-write + for ( table = tables.begin(); table != tables.end(); table++ ) { + i_revokePrivilege( *priv, *table, user ); + } + transaction.commit(); + } +} + +//----------------------------------------------------------------------------- + +void RalPrivilegeManager::grantWriterPrivileges( const std::string& user ) +{ + log() << "Grant writer role privileges to user '" << user << "'" + << coral::MessageStream::endmsg; + std::vector<Privilege>::const_iterator priv; + for ( priv = m_fourPrivs.begin(); priv != m_fourPrivs.end(); priv++ ) { + std::vector<std::string> tables( i_listWriterTables( *priv ) ); + std::vector<std::string>::const_iterator table; + RelationalTransaction transaction( m_db->transactionMgr() ); // read-write + for ( table = tables.begin(); table != tables.end(); table++ ) { + i_grantPrivilege( *priv, *table, user ); + } + transaction.commit(); + } +} + +//----------------------------------------------------------------------------- + +void RalPrivilegeManager::revokeWriterPrivileges( const std::string& user ) +{ + log() << "Revoke writer role privileges from user '" << user << "'" + << coral::MessageStream::endmsg; + std::vector<Privilege>::const_iterator priv; + for ( priv = m_fourPrivs.begin(); priv != m_fourPrivs.end(); priv++ ) { + std::vector<std::string> tables( i_listWriterTables( *priv ) ); + std::vector<std::string>::const_iterator table; + RelationalTransaction transaction( m_db->transactionMgr() ); // read-write + for ( table = tables.begin(); table != tables.end(); table++ ) { + i_revokePrivilege( *priv, *table, user ); + } + transaction.commit(); + } +} + +//----------------------------------------------------------------------------- + +void RalPrivilegeManager::grantTaggerPrivileges( const std::string& user, + const bool retag ) +{ + log() << "Grant tagger role privileges to user '" << user << "'" + << coral::MessageStream::endmsg; + std::vector<Privilege>::const_iterator priv; + for ( priv = m_fourPrivs.begin(); priv != m_fourPrivs.end(); priv++ ) { + std::vector<std::string> tables( i_listTaggerTables( *priv, retag ) ); + std::vector<std::string>::const_iterator table; + RelationalTransaction transaction( m_db->transactionMgr() ); // read-write + for ( table = tables.begin(); table != tables.end(); table++ ) { + i_grantPrivilege( *priv, *table, user ); + } + transaction.commit(); + } +} + +//----------------------------------------------------------------------------- + +void RalPrivilegeManager::revokeTaggerPrivileges( const std::string& user ) +{ + bool retag = true; // Revoke retag privileges + log() << "Revoke tagger role privileges from user '" << user << "'" + << coral::MessageStream::endmsg; + std::vector<Privilege>::const_iterator priv; + for ( priv = m_fourPrivs.begin(); priv != m_fourPrivs.end(); priv++ ) { + std::vector<std::string> tables( i_listTaggerTables( *priv, retag ) ); + std::vector<std::string>::const_iterator table; + RelationalTransaction transaction( m_db->transactionMgr() ); // read-write + for ( table = tables.begin(); table != tables.end(); table++ ) { + i_revokePrivilege( *priv, *table, user ); + } + transaction.commit(); + } +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/utilities/coolPrivileges/RalPrivilegeManager.h b/RelationalCool/utilities/coolPrivileges/RalPrivilegeManager.h new file mode 100644 index 000000000..00e2a3dc2 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/RalPrivilegeManager.h @@ -0,0 +1,121 @@ +// $Id: RalPrivilegeManager.h,v 1.3 2008-10-29 09:11:31 avalassi Exp $ +#ifndef RELATIONALCOOL_RALPRIVILEGEMANAGER_H +#define RELATIONALCOOL_RALPRIVILEGEMANAGER_H 1 + +// Include files +#include <memory> +#include "CoralBase/MessageStream.h" +#include "RelationalAccess/ITablePrivilegeManager.h" + +namespace cool +{ + + // Forward declarations + class RalDatabase; + + /** @class RalPrivilegeManager RalPrivilegeManager.h + * + * Private utility class to grant/revoke table-level object privileges + * on COOL schema objects to other users in the same server. + * + * For the moment, this does not implement any public API: the + * functionality is offered to users only via pre-built executables. + * + * This class can only be used with "oracle" database technology. + * + * @author Andrea Valassi and Sven A. Schmidt + * @date 2005-07-05 + */ + + class RalPrivilegeManager + { + + /// Adopt the same Privilege list as RAL (SELECT, UPDATE, INSERT, DELETE) + typedef enum { SELECT, INSERT, UPDATE, DELETE } Privilege; + + public: + + /// Constructor from a RalDatabase pointer + RalPrivilegeManager( RalDatabase* db ); + + /// Destructor + virtual ~RalPrivilegeManager(); + + /// Grant privileges to read all data in the COOL database + void grantReaderPrivileges( const std::string& user ); + + /// Revoke privileges to read all data in the COOL database + void revokeReaderPrivileges( const std::string& user ); + + /// Grant privileges to insert new IOVs into the COOL database + /// [NB: reader privileges are also needed and must be granted explicitly] + void grantWriterPrivileges( const std::string& user ); + + /// Revoke privileges to insert new IOVs into the COOL database + void revokeWriterPrivileges( const std::string& user ); + + /// Grant privileges to tag (optionally retag) IOVs in the COOL database + /// [NB: reader privileges are also needed and must be granted explicitly] + void grantTaggerPrivileges( const std::string& user, + const bool retag ); + + /// Revoke privileges to tag and/or retag IOVs in the COOL database + void revokeTaggerPrivileges( const std::string& user ); + + protected: + + /// Get a CORAL MessageStream + coral::MessageStream& log(); + + /// List all tables that a READER must be allowed to have privileges on + /// [For SELECT privileges these are ALL the tables in the COOL database] + std::vector< std::string > i_listReaderTables( const Privilege& priv ); + + /// List all tables that a WRITER must be allowed to have privileges on + std::vector< std::string > i_listWriterTables( const Privilege& priv ); + + /// List all tables that a TAGGER must be allowed to have privileges on + std::vector< std::string > i_listTaggerTables( const Privilege& priv, + const bool retag ); + + /// Get the coral::ITablePrivilegeManager for a given table + coral::ITablePrivilegeManager& + i_tablePrivMgr( const std::string& table ); + + /// Grant a given privilege on a given table to a given user + void i_grantPrivilege( const Privilege& priv, + const std::string& table, + const std::string& user ); + + /// Revoke a given privilege on a given table to a given user + void i_revokePrivilege( const Privilege& priv, + const std::string& table, + const std::string& user ); + + private: + + /// Standard constructor is private + RalPrivilegeManager(); + + /// Copy constructor is private + RalPrivilegeManager( const RalPrivilegeManager& rhs ); + + /// Assignment operator is private + RalPrivilegeManager& operator=( const RalPrivilegeManager& rhs ); + + private: + + /// RalDatabase pointer + RalDatabase* m_db; + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// Vector of four basic privileges + std::vector<Privilege> m_fourPrivs; + + }; + +} + +#endif // RELATIONALCOOL_RALPRIVILEGEMANAGER_H diff --git a/RelationalCool/utilities/coolPrivileges/coolPrivileges.cpp b/RelationalCool/utilities/coolPrivileges/coolPrivileges.cpp new file mode 100644 index 000000000..3047bbc78 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/coolPrivileges.cpp @@ -0,0 +1,156 @@ +// $Id: coolPrivileges.cpp,v 1.10 2008-04-10 08:32:53 avalassi Exp $ + +// Include files +#include <iostream> +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoralBase/Exception.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" + +// Local include files +#include "RalPrivilegeManager.h" +#include "../../src/CoralApplication.h" +#include "../../src/RalDatabase.h" + +// Namespace +using namespace cool; + +// Message output +#define LOG std::cout + +//----------------------------------------------------------------------------- + +int main( int argc, char** argv ) +{ + + try { + + // Get the command line arguments + bool ok = true; + std::string dbId; + std::string comm; + std::string role; + std::string user; + if ( argc != 5 ) + ok = false; + else { + dbId = argv[1]; + comm = argv[2]; + role = argv[3]; + user = argv[4]; + if ( comm != "GRANT" && + comm != "REVOKE" ) + ok = false; + if ( role != "READER" && + role != "WRITER" && + role != "TAGGER" && + role != "ALL" ) + ok = false; + } + if ( !ok ) { + LOG << "Usage: " << argv[0] + << " dbId {GRANT|REVOKE} {READER|WRITER|TAGGER|ALL} user" + << std:: endl; + std::string dbId = + "oracle://SERVER;schema=USER1;dbname=DB;user=USER1"; + std::string dbId2 = + "ServerAlias(owner)/DBNAME"; + LOG << "Example: " << argv[0] << " '" << dbId + << "' GRANT READER USER2" << std::endl; + LOG << "Example: " << argv[0] << " '" << dbId2 + << "' GRANT READER USER2" << std::endl; + return 1; + } + + // Instantiate a COOL Application + CoralApplication app; + + // If we can access a LFC and the user is not explicitely forbidding it, + // we try to use CORAL LFCReplicaService + if ( ::getenv("COOL_IGNORE_LFC") == NULL && + ::getenv("LFC_HOST") != NULL ) { + // try to load CORAL LFCReplicaService + coral::IConnectionServiceConfiguration &connSvcConf = + app.connectionSvc().configuration(); + connSvcConf.setAuthenticationService("CORAL/Services/LFCReplicaService"); + connSvcConf.setLookupService("CORAL/Services/LFCReplicaService"); + } + + // Open the database + IDatabaseSvc& dbSvc = app.databaseService(); + IDatabasePtr db = dbSvc.openDatabase( dbId, false ); // open for update + RalDatabase* ralDb = dynamic_cast<RalDatabase*>( db.get() ); + RalPrivilegeManager prMgr( ralDb ); + + // Grant/Revoke role to/from user + if ( comm == "GRANT" ) { + LOG << "GRANT '" << role + << "' privileges to user " << user << std::endl; + if ( role == "READER" ) { + prMgr.grantReaderPrivileges( user ); + } else if ( role == "WRITER" ) { + prMgr.grantReaderPrivileges( user ); + prMgr.grantWriterPrivileges( user ); + } else if ( role == "TAGGER" ) { + bool retag = true; + prMgr.grantReaderPrivileges( user ); + prMgr.grantTaggerPrivileges( user, retag ); + } else if ( role == "ALL" ) { + bool retag = true; + prMgr.grantReaderPrivileges( user ); + prMgr.grantWriterPrivileges( user ); + prMgr.grantTaggerPrivileges( user, retag ); + } else { + LOG << "Unknown privileges '" << role << "'" << std::endl; + } + } + else { + LOG << "REVOKE '" << role + << "' privileges from user " << user << std::endl; + if ( role == "READER" ) { + prMgr.revokeReaderPrivileges( user ); + } else if ( role == "WRITER" ) { + prMgr.revokeWriterPrivileges( user ); + } else if ( role == "TAGGER" ) { + prMgr.revokeTaggerPrivileges( user ); + } else if ( role == "ALL" ) { + prMgr.revokeTaggerPrivileges( user ); + prMgr.revokeWriterPrivileges( user ); + prMgr.revokeReaderPrivileges( user ); + } else { + LOG << "Unknown privileges '" << role << "'" << std::endl; + } + } + } + + catch( cool::Exception& e ) + { + LOG << "ERROR! Cool Exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( coral::Exception& e ) + { + LOG << "ERROR! Coral Exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( std::exception& e ) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( ... ) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + return 1; + } + + // Successful program termination + return 0; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/utilities/coolPrivileges/logs/grantAll-details.txt b/RelationalCool/utilities/coolPrivileges/logs/grantAll-details.txt new file mode 100644 index 000000000..a7880bbb4 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/grantAll-details.txt @@ -0,0 +1,91 @@ +* READER privileges + +GRANT SELECT ON LCG_COOL.COOLTEST_DB_ATTRIBUTES TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_NODES TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_NODES_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_TAGS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_TAG2TAG TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_TAG2TAG_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_TAGS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_IOVS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0010_IOVS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0010_IOVS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0010_CHANNELS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0005_TAGS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0007_IOVS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0007_IOVS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0007_CHANNELS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0003_TAGS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0009_IOVS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0009_IOVS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0009_CHANNELS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0009_TAGS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0009_TAGS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0009_IOV2TAG TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0008_IOVS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0008_IOVS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0008_CHANNELS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0008_TAGS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0008_TAGS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0008_IOV2TAG TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0004_TAGS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0002_TAGS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0006_IOVS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0006_IOVS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0006_CHANNELS TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0001_TAGS_SEQ TO PUBLIC +GRANT SELECT ON LCG_COOL.COOLTEST_F0000_TAGS_SEQ TO PUBLIC + +* WRITER privileges + +GRANT INSERT ON LCG_COOL.COOLTEST_F0010_IOVS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0010_CHANNELS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0007_IOVS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0007_CHANNELS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0009_IOVS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0009_CHANNELS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0008_IOVS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0008_CHANNELS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0006_IOVS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0006_CHANNELS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_IOVS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0010_IOVS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0010_IOVS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0010_CHANNELS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0007_IOVS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0007_IOVS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0007_CHANNELS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0009_IOVS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0009_IOVS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0009_CHANNELS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0008_IOVS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0008_IOVS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0008_CHANNELS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0006_IOVS TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0006_IOVS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0006_CHANNELS TO PUBLIC + +* TAGGER privileges + +GRANT INSERT ON LCG_COOL.COOLTEST_TAGS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_TAG2TAG TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0009_TAGS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0009_IOV2TAG TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0008_TAGS TO PUBLIC +GRANT INSERT ON LCG_COOL.COOLTEST_F0008_IOV2TAG TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_TAGS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_TAG2TAG_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0005_TAGS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0003_TAGS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0009_TAGS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0008_TAGS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0004_TAGS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0002_TAGS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0001_TAGS_SEQ TO PUBLIC +GRANT UPDATE ON LCG_COOL.COOLTEST_F0000_TAGS_SEQ TO PUBLIC +GRANT DELETE ON LCG_COOL.COOLTEST_TAGS TO PUBLIC +GRANT DELETE ON LCG_COOL.COOLTEST_TAG2TAG TO PUBLIC +GRANT DELETE ON LCG_COOL.COOLTEST_F0009_TAGS TO PUBLIC +GRANT DELETE ON LCG_COOL.COOLTEST_F0009_IOV2TAG TO PUBLIC +GRANT DELETE ON LCG_COOL.COOLTEST_F0008_TAGS TO PUBLIC +GRANT DELETE ON LCG_COOL.COOLTEST_F0008_IOV2TAG TO PUBLIC diff --git a/RelationalCool/utilities/coolPrivileges/logs/grantAll.txt b/RelationalCool/utilities/coolPrivileges/logs/grantAll.txt new file mode 100644 index 000000000..10946df27 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/grantAll.txt @@ -0,0 +1,616 @@ +CoralApplication Info Create a cool::CoralApplication... +CoralApplication Info Enable the COOL signal handler +CoralApplication Info Create a new own CORAL connection service +CoralApplication Info Create the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +CoralApplication Info Create a cool::CoralApplication... DONE +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Instantiate a R/W RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Connect to the database server +PluginManager Info PluginManager creating CORAL/Services/ConnectionService component +PluginManager Info PluginMaager needs to load CORAL/Services/ConnectionService component +PluginManager Info PluginManager loaded ConnectionService library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IRelationalService: CORAL/Services/RelationalService +PluginManager Info PluginManager creating CORAL/Services/RelationalService component +PluginManager Info PluginMaager needs to load CORAL/Services/RelationalService component +PluginManager Info PluginManager loaded RelationalService library +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "coral" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "frontier" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "coral" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "frontier" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +PluginManager Info PluginManager creating CORAL/RelationalPlugins/oracle component +PluginManager Info PluginMaager needs to load CORAL/RelationalPlugins/oracle component +PluginManager Info PluginManager loaded OracleAccess library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IAuthenticationService: CORAL/Services/XMLAuthenticationService +PluginManager Info PluginManager creating CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginMaager needs to load CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginManager loaded XMLAuthenticationService library +CORAL/Services/XMLAuthenticationS... Info Authentication using /afs/cern.ch/user/a/avalassi/private/authentication.xml file +CORAL/Services/ConnectionService Debug No valid connection for string "oracle://lcg_cool_nightly/lcg_cool" found in the pool. Creating a new connection. +CORAL/Services/ConnectionService Debug Trying to get a new update session on "oracle://lcg_cool_nightly/lcg_cool" +CORAL/Services/ConnectionService Debug Connection parameters are: Retry-Period=10sec, Retry-Timeout=60sec, Connection-Timeout=0sec. +CORAL/Services/ConnectionService Info Connection to service "lcg_cool_nightly" established. Id=c183a350-8418-11dd-870d-001617c3b642 +CORAL/Services/ConnectionService Info New session on connection to service "lcg_cool_nightly" started for user "lcg_cool". Connection Id=c183a350-8418-11dd-870d-001617c3b642 +CORAL/Services/ConnectionService Debug A New connection to service "lcg_cool_nightly" has been added in the active list. Id=c183a350-8418-11dd-870d-001617c3b642 +RelationalDatabase Info Instantiate a R/W RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalQueryMgr Debug Instantiate a RelationalQueryMgr +RelationalQueryMgr Debug Instantiate a RalQueryMgr +RelationalSequenceMgr Debug Instantiate a RelationalSequenceMgr +RelationalSequenceMgr Debug Instantiate a RalSequenceMgr +RelationalSchemaMgr Debug Instantiate a RelationalSchemaMgr +RelationalSchemaMgr Debug Instantiate a RalSchemaMgr +RelationalNodeMgr Debug Instantiate a RelationalNodeMgr +RelationalTagMgr Debug Instantiate a RelationalTagMgr +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM LCG_COOL."COOLTEST_DB_ATTRIBUTES" "COOLTEST_DB_ATTRIBUTES"" +RelationalQueryMgr Debug Successfully fetched 10 table rows +RelationalDatabase Debug Release number match: database with CURRENT release number 2.6.0 will be opened using CURRENT client release number 2.6.0 +RalPrivilegeManager Debug Instantiate a RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +GRANT 'ALL' privileges to user PUBLIC +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_DB_ATTRIBUTES" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_NODES" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_NODES_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAG2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAG2TAG_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0010_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0010_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0007_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0007_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0009_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0009_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0008_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0008_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0006_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0006_CHANNELS" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0010_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0010_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0007_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0007_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0009_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0009_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0008_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0008_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0006_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0006_CHANNELS" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_TAG2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0009_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0008_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_TAG2TAG_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_TAG2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_F0009_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_F0009_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_F0008_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_F0008_IOV2TAG" TO PUBLIC" +RalPrivilegeManager Debug Delete the RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Delete the RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalTagMgr Debug Delete the RelationalTagMgr +RelationalNodeMgr Debug Delete the RelationalNodeMgr +RelationalSchemaMgr Debug Delete the RalSchemaMgr +RelationalSchemaMgr Debug Delete the RelationalSchemaMgr +RelationalQueryMgr Debug Delete the RalQueryMgr +RelationalSequenceMgr Debug Delete the RalSequenceMgr +RelationalSequenceMgr Debug Delete the RelationalSequenceMgr +RalSessionMgr Info Delete the RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Disconnect from the database server +CORAL/Services/ConnectionService Debug Connection id=c183a350-8418-11dd-870d-001617c3b642 to service "lcg_cool_nightly" has 0 session(s) opended. +CORAL/Services/ConnectionService Debug The active connection id=c183a350-8418-11dd-870d-001617c3b642 to service "lcg_cool_nightly" has been removed from the active list. +RelationalQueryMgr Debug Delete the RelationalQueryMgr +CoralApplication Info Delete the COOL CoralApplication... +CoralApplication Info Delete the COOL database service +RalDatabaseSvc Info Delete the RalDatabaseSvc... +RalDatabaseSvc Info Purge the connection pool +RalDatabaseSvc Info Reset the ICS pointer +RalDatabaseSvc Info Delete the RalDatabaseSvc... DONE +CoralApplication Info Delete the CORAL connection service +CoralApplication Info Delete the COOL CoralApplication... DONE diff --git a/RelationalCool/utilities/coolPrivileges/logs/grantReader.txt b/RelationalCool/utilities/coolPrivileges/logs/grantReader.txt new file mode 100644 index 000000000..6b33cb6f2 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/grantReader.txt @@ -0,0 +1,203 @@ +CoralApplication Info Create a cool::CoralApplication... +CoralApplication Info Enable the COOL signal handler +CoralApplication Info Create a new own CORAL connection service +CoralApplication Info Create the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +CoralApplication Info Create a cool::CoralApplication... DONE +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Instantiate a R/W RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Connect to the database server +PluginManager Info PluginManager creating CORAL/Services/ConnectionService component +PluginManager Info PluginMaager needs to load CORAL/Services/ConnectionService component +PluginManager Info PluginManager loaded ConnectionService library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IRelationalService: CORAL/Services/RelationalService +PluginManager Info PluginManager creating CORAL/Services/RelationalService component +PluginManager Info PluginMaager needs to load CORAL/Services/RelationalService component +PluginManager Info PluginManager loaded RelationalService library +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "coral" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "frontier" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "coral" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "frontier" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +PluginManager Info PluginManager creating CORAL/RelationalPlugins/oracle component +PluginManager Info PluginMaager needs to load CORAL/RelationalPlugins/oracle component +PluginManager Info PluginManager loaded OracleAccess library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IAuthenticationService: CORAL/Services/XMLAuthenticationService +PluginManager Info PluginManager creating CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginMaager needs to load CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginManager loaded XMLAuthenticationService library +CORAL/Services/XMLAuthenticationS... Info Authentication using /afs/cern.ch/user/a/avalassi/private/authentication.xml file +CORAL/Services/ConnectionService Debug No valid connection for string "oracle://lcg_cool_nightly/lcg_cool" found in the pool. Creating a new connection. +CORAL/Services/ConnectionService Debug Trying to get a new update session on "oracle://lcg_cool_nightly/lcg_cool" +CORAL/Services/ConnectionService Debug Connection parameters are: Retry-Period=10sec, Retry-Timeout=60sec, Connection-Timeout=0sec. +CORAL/Services/ConnectionService Info Connection to service "lcg_cool_nightly" established. Id=b1e038fa-8418-11dd-a887-001617c3b642 +CORAL/Services/ConnectionService Info New session on connection to service "lcg_cool_nightly" started for user "lcg_cool". Connection Id=b1e038fa-8418-11dd-a887-001617c3b642 +CORAL/Services/ConnectionService Debug A New connection to service "lcg_cool_nightly" has been added in the active list. Id=b1e038fa-8418-11dd-a887-001617c3b642 +RelationalDatabase Info Instantiate a R/W RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalQueryMgr Debug Instantiate a RelationalQueryMgr +RelationalQueryMgr Debug Instantiate a RalQueryMgr +RelationalSequenceMgr Debug Instantiate a RelationalSequenceMgr +RelationalSequenceMgr Debug Instantiate a RalSequenceMgr +RelationalSchemaMgr Debug Instantiate a RelationalSchemaMgr +RelationalSchemaMgr Debug Instantiate a RalSchemaMgr +RelationalNodeMgr Debug Instantiate a RelationalNodeMgr +RelationalTagMgr Debug Instantiate a RelationalTagMgr +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM LCG_COOL."COOLTEST_DB_ATTRIBUTES" "COOLTEST_DB_ATTRIBUTES"" +RelationalQueryMgr Debug Successfully fetched 10 table rows +RelationalDatabase Debug Release number match: database with CURRENT release number 2.6.0 will be opened using CURRENT client release number 2.6.0 +RalPrivilegeManager Debug Instantiate a RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +GRANT 'READER' privileges to user PUBLIC +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_DB_ATTRIBUTES" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_NODES" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_NODES_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAG2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAG2TAG_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" TO PUBLIC" +RalPrivilegeManager Debug Delete the RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Delete the RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalTagMgr Debug Delete the RelationalTagMgr +RelationalNodeMgr Debug Delete the RelationalNodeMgr +RelationalSchemaMgr Debug Delete the RalSchemaMgr +RelationalSchemaMgr Debug Delete the RelationalSchemaMgr +RelationalQueryMgr Debug Delete the RalQueryMgr +RelationalSequenceMgr Debug Delete the RalSequenceMgr +RelationalSequenceMgr Debug Delete the RelationalSequenceMgr +RalSessionMgr Info Delete the RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Disconnect from the database server +CORAL/Services/ConnectionService Debug Connection id=b1e038fa-8418-11dd-a887-001617c3b642 to service "lcg_cool_nightly" has 0 session(s) opended. +CORAL/Services/ConnectionService Debug The active connection id=b1e038fa-8418-11dd-a887-001617c3b642 to service "lcg_cool_nightly" has been removed from the active list. +RelationalQueryMgr Debug Delete the RelationalQueryMgr +CoralApplication Info Delete the COOL CoralApplication... +CoralApplication Info Delete the COOL database service +RalDatabaseSvc Info Delete the RalDatabaseSvc... +RalDatabaseSvc Info Purge the connection pool +RalDatabaseSvc Info Reset the ICS pointer +RalDatabaseSvc Info Delete the RalDatabaseSvc... DONE +CoralApplication Info Delete the CORAL connection service +CoralApplication Info Delete the COOL CoralApplication... DONE diff --git a/RelationalCool/utilities/coolPrivileges/logs/grantTagger.txt b/RelationalCool/utilities/coolPrivileges/logs/grantTagger.txt new file mode 100644 index 000000000..fe58d0214 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/grantTagger.txt @@ -0,0 +1,498 @@ +CoralApplication Info Create a cool::CoralApplication... +CoralApplication Info Enable the COOL signal handler +CoralApplication Info Create a new own CORAL connection service +CoralApplication Info Create the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +CoralApplication Info Create a cool::CoralApplication... DONE +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Instantiate a R/W RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Connect to the database server +PluginManager Info PluginManager creating CORAL/Services/ConnectionService component +PluginManager Info PluginMaager needs to load CORAL/Services/ConnectionService component +PluginManager Info PluginManager loaded ConnectionService library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IRelationalService: CORAL/Services/RelationalService +PluginManager Info PluginManager creating CORAL/Services/RelationalService component +PluginManager Info PluginMaager needs to load CORAL/Services/RelationalService component +PluginManager Info PluginManager loaded RelationalService library +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "coral" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "frontier" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "coral" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "frontier" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +PluginManager Info PluginManager creating CORAL/RelationalPlugins/oracle component +PluginManager Info PluginMaager needs to load CORAL/RelationalPlugins/oracle component +PluginManager Info PluginManager loaded OracleAccess library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IAuthenticationService: CORAL/Services/XMLAuthenticationService +PluginManager Info PluginManager creating CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginMaager needs to load CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginManager loaded XMLAuthenticationService library +CORAL/Services/XMLAuthenticationS... Info Authentication using /afs/cern.ch/user/a/avalassi/private/authentication.xml file +CORAL/Services/ConnectionService Debug No valid connection for string "oracle://lcg_cool_nightly/lcg_cool" found in the pool. Creating a new connection. +CORAL/Services/ConnectionService Debug Trying to get a new update session on "oracle://lcg_cool_nightly/lcg_cool" +CORAL/Services/ConnectionService Debug Connection parameters are: Retry-Period=10sec, Retry-Timeout=60sec, Connection-Timeout=0sec. +CORAL/Services/ConnectionService Info Connection to service "lcg_cool_nightly" established. Id=b91266d4-8418-11dd-ba29-001617c3b642 +CORAL/Services/ConnectionService Info New session on connection to service "lcg_cool_nightly" started for user "lcg_cool". Connection Id=b91266d4-8418-11dd-ba29-001617c3b642 +CORAL/Services/ConnectionService Debug A New connection to service "lcg_cool_nightly" has been added in the active list. Id=b91266d4-8418-11dd-ba29-001617c3b642 +RelationalDatabase Info Instantiate a R/W RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalQueryMgr Debug Instantiate a RelationalQueryMgr +RelationalQueryMgr Debug Instantiate a RalQueryMgr +RelationalSequenceMgr Debug Instantiate a RelationalSequenceMgr +RelationalSequenceMgr Debug Instantiate a RalSequenceMgr +RelationalSchemaMgr Debug Instantiate a RelationalSchemaMgr +RelationalSchemaMgr Debug Instantiate a RalSchemaMgr +RelationalNodeMgr Debug Instantiate a RelationalNodeMgr +RelationalTagMgr Debug Instantiate a RelationalTagMgr +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM LCG_COOL."COOLTEST_DB_ATTRIBUTES" "COOLTEST_DB_ATTRIBUTES"" +RelationalQueryMgr Debug Successfully fetched 10 table rows +RelationalDatabase Debug Release number match: database with CURRENT release number 2.6.0 will be opened using CURRENT client release number 2.6.0 +RalPrivilegeManager Debug Instantiate a RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +GRANT 'TAGGER' privileges to user PUBLIC +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_DB_ATTRIBUTES" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_NODES" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_NODES_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAG2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAG2TAG_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_TAG2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0009_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0008_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_TAG2TAG_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_TAG2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_F0009_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_F0009_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_F0008_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT DELETE ON LCG_COOL."COOLTEST_F0008_IOV2TAG" TO PUBLIC" +RalPrivilegeManager Debug Delete the RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Delete the RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalTagMgr Debug Delete the RelationalTagMgr +RelationalNodeMgr Debug Delete the RelationalNodeMgr +RelationalSchemaMgr Debug Delete the RalSchemaMgr +RelationalSchemaMgr Debug Delete the RelationalSchemaMgr +RelationalQueryMgr Debug Delete the RalQueryMgr +RelationalSequenceMgr Debug Delete the RalSequenceMgr +RelationalSequenceMgr Debug Delete the RelationalSequenceMgr +RalSessionMgr Info Delete the RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Disconnect from the database server +CORAL/Services/ConnectionService Debug Connection id=b91266d4-8418-11dd-ba29-001617c3b642 to service "lcg_cool_nightly" has 0 session(s) opended. +CORAL/Services/ConnectionService Debug The active connection id=b91266d4-8418-11dd-ba29-001617c3b642 to service "lcg_cool_nightly" has been removed from the active list. +RelationalQueryMgr Debug Delete the RelationalQueryMgr +CoralApplication Info Delete the COOL CoralApplication... +CoralApplication Info Delete the COOL database service +RalDatabaseSvc Info Delete the RalDatabaseSvc... +RalDatabaseSvc Info Purge the connection pool +RalDatabaseSvc Info Reset the ICS pointer +RalDatabaseSvc Info Delete the RalDatabaseSvc... DONE +CoralApplication Info Delete the CORAL connection service +CoralApplication Info Delete the COOL CoralApplication... DONE diff --git a/RelationalCool/utilities/coolPrivileges/logs/grantWriter.txt b/RelationalCool/utilities/coolPrivileges/logs/grantWriter.txt new file mode 100644 index 000000000..8d7527b79 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/grantWriter.txt @@ -0,0 +1,321 @@ +CoralApplication Info Create a cool::CoralApplication... +CoralApplication Info Enable the COOL signal handler +CoralApplication Info Create a new own CORAL connection service +CoralApplication Info Create the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +CoralApplication Info Create a cool::CoralApplication... DONE +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Instantiate a R/W RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Connect to the database server +PluginManager Info PluginManager creating CORAL/Services/ConnectionService component +PluginManager Info PluginMaager needs to load CORAL/Services/ConnectionService component +PluginManager Info PluginManager loaded ConnectionService library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IRelationalService: CORAL/Services/RelationalService +PluginManager Info PluginManager creating CORAL/Services/RelationalService component +PluginManager Info PluginMaager needs to load CORAL/Services/RelationalService component +PluginManager Info PluginManager loaded RelationalService library +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "coral" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "frontier" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "coral" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "frontier" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +PluginManager Info PluginManager creating CORAL/RelationalPlugins/oracle component +PluginManager Info PluginMaager needs to load CORAL/RelationalPlugins/oracle component +PluginManager Info PluginManager loaded OracleAccess library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IAuthenticationService: CORAL/Services/XMLAuthenticationService +PluginManager Info PluginManager creating CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginMaager needs to load CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginManager loaded XMLAuthenticationService library +CORAL/Services/XMLAuthenticationS... Info Authentication using /afs/cern.ch/user/a/avalassi/private/authentication.xml file +CORAL/Services/ConnectionService Debug No valid connection for string "oracle://lcg_cool_nightly/lcg_cool" found in the pool. Creating a new connection. +CORAL/Services/ConnectionService Debug Trying to get a new update session on "oracle://lcg_cool_nightly/lcg_cool" +CORAL/Services/ConnectionService Debug Connection parameters are: Retry-Period=10sec, Retry-Timeout=60sec, Connection-Timeout=0sec. +CORAL/Services/ConnectionService Info Connection to service "lcg_cool_nightly" established. Id=b49e1daa-8418-11dd-b331-001617c3b642 +CORAL/Services/ConnectionService Info New session on connection to service "lcg_cool_nightly" started for user "lcg_cool". Connection Id=b49e1daa-8418-11dd-b331-001617c3b642 +CORAL/Services/ConnectionService Debug A New connection to service "lcg_cool_nightly" has been added in the active list. Id=b49e1daa-8418-11dd-b331-001617c3b642 +RelationalDatabase Info Instantiate a R/W RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalQueryMgr Debug Instantiate a RelationalQueryMgr +RelationalQueryMgr Debug Instantiate a RalQueryMgr +RelationalSequenceMgr Debug Instantiate a RelationalSequenceMgr +RelationalSequenceMgr Debug Instantiate a RalSequenceMgr +RelationalSchemaMgr Debug Instantiate a RelationalSchemaMgr +RelationalSchemaMgr Debug Instantiate a RalSchemaMgr +RelationalNodeMgr Debug Instantiate a RelationalNodeMgr +RelationalTagMgr Debug Instantiate a RelationalTagMgr +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM LCG_COOL."COOLTEST_DB_ATTRIBUTES" "COOLTEST_DB_ATTRIBUTES"" +RelationalQueryMgr Debug Successfully fetched 10 table rows +RelationalDatabase Debug Release number match: database with CURRENT release number 2.6.0 will be opened using CURRENT client release number 2.6.0 +RalPrivilegeManager Debug Instantiate a RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +GRANT 'WRITER' privileges to user PUBLIC +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_DB_ATTRIBUTES" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_NODES" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_NODES_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAG2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAG2TAG_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0010_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0007_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_TAGS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0006_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT SELECT ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0010_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0010_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0007_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0007_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0009_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0009_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0008_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0008_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0006_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT INSERT ON LCG_COOL."COOLTEST_F0006_CHANNELS" TO PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0010_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0010_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0007_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0007_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0009_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0009_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0008_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0008_CHANNELS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0006_IOVS" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" TO PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "GRANT UPDATE ON LCG_COOL."COOLTEST_F0006_CHANNELS" TO PUBLIC" +RalPrivilegeManager Debug Delete the RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Delete the RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalTagMgr Debug Delete the RelationalTagMgr +RelationalNodeMgr Debug Delete the RelationalNodeMgr +RelationalSchemaMgr Debug Delete the RalSchemaMgr +RelationalSchemaMgr Debug Delete the RelationalSchemaMgr +RelationalQueryMgr Debug Delete the RalQueryMgr +RelationalSequenceMgr Debug Delete the RalSequenceMgr +RelationalSequenceMgr Debug Delete the RelationalSequenceMgr +RalSessionMgr Info Delete the RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Disconnect from the database server +CORAL/Services/ConnectionService Debug Connection id=b49e1daa-8418-11dd-b331-001617c3b642 to service "lcg_cool_nightly" has 0 session(s) opended. +CORAL/Services/ConnectionService Debug The active connection id=b49e1daa-8418-11dd-b331-001617c3b642 to service "lcg_cool_nightly" has been removed from the active list. +RelationalQueryMgr Debug Delete the RelationalQueryMgr +CoralApplication Info Delete the COOL CoralApplication... +CoralApplication Info Delete the COOL database service +RalDatabaseSvc Info Delete the RalDatabaseSvc... +RalDatabaseSvc Info Purge the connection pool +RalDatabaseSvc Info Reset the ICS pointer +RalDatabaseSvc Info Delete the RalDatabaseSvc... DONE +CoralApplication Info Delete the CORAL connection service +CoralApplication Info Delete the COOL CoralApplication... DONE diff --git a/RelationalCool/utilities/coolPrivileges/logs/revokeAll.txt b/RelationalCool/utilities/coolPrivileges/logs/revokeAll.txt new file mode 100644 index 000000000..1373d4c06 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/revokeAll.txt @@ -0,0 +1,616 @@ +CoralApplication Info Create a cool::CoralApplication... +CoralApplication Info Enable the COOL signal handler +CoralApplication Info Create a new own CORAL connection service +CoralApplication Info Create the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +CoralApplication Info Create a cool::CoralApplication... DONE +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Instantiate a R/W RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Connect to the database server +PluginManager Info PluginManager creating CORAL/Services/ConnectionService component +PluginManager Info PluginMaager needs to load CORAL/Services/ConnectionService component +PluginManager Info PluginManager loaded ConnectionService library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IRelationalService: CORAL/Services/RelationalService +PluginManager Info PluginManager creating CORAL/Services/RelationalService component +PluginManager Info PluginMaager needs to load CORAL/Services/RelationalService component +PluginManager Info PluginManager loaded RelationalService library +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "coral" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "frontier" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "coral" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "frontier" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +PluginManager Info PluginManager creating CORAL/RelationalPlugins/oracle component +PluginManager Info PluginMaager needs to load CORAL/RelationalPlugins/oracle component +PluginManager Info PluginManager loaded OracleAccess library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IAuthenticationService: CORAL/Services/XMLAuthenticationService +PluginManager Info PluginManager creating CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginMaager needs to load CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginManager loaded XMLAuthenticationService library +CORAL/Services/XMLAuthenticationS... Info Authentication using /afs/cern.ch/user/a/avalassi/private/authentication.xml file +CORAL/Services/ConnectionService Debug No valid connection for string "oracle://lcg_cool_nightly/lcg_cool" found in the pool. Creating a new connection. +CORAL/Services/ConnectionService Debug Trying to get a new update session on "oracle://lcg_cool_nightly/lcg_cool" +CORAL/Services/ConnectionService Debug Connection parameters are: Retry-Period=10sec, Retry-Timeout=60sec, Connection-Timeout=0sec. +CORAL/Services/ConnectionService Info Connection to service "lcg_cool_nightly" established. Id=c6ce484c-8418-11dd-80c3-001617c3b642 +CORAL/Services/ConnectionService Info New session on connection to service "lcg_cool_nightly" started for user "lcg_cool". Connection Id=c6ce484c-8418-11dd-80c3-001617c3b642 +CORAL/Services/ConnectionService Debug A New connection to service "lcg_cool_nightly" has been added in the active list. Id=c6ce484c-8418-11dd-80c3-001617c3b642 +RelationalDatabase Info Instantiate a R/W RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalQueryMgr Debug Instantiate a RelationalQueryMgr +RelationalQueryMgr Debug Instantiate a RalQueryMgr +RelationalSequenceMgr Debug Instantiate a RelationalSequenceMgr +RelationalSequenceMgr Debug Instantiate a RalSequenceMgr +RelationalSchemaMgr Debug Instantiate a RelationalSchemaMgr +RelationalSchemaMgr Debug Instantiate a RalSchemaMgr +RelationalNodeMgr Debug Instantiate a RelationalNodeMgr +RelationalTagMgr Debug Instantiate a RelationalTagMgr +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM LCG_COOL."COOLTEST_DB_ATTRIBUTES" "COOLTEST_DB_ATTRIBUTES"" +RelationalQueryMgr Debug Successfully fetched 10 table rows +RelationalDatabase Debug Release number match: database with CURRENT release number 2.6.0 will be opened using CURRENT client release number 2.6.0 +RalPrivilegeManager Debug Instantiate a RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +REVOKE 'ALL' privileges from user PUBLIC +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_TAG2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0009_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0008_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" FROM PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_TAG2TAG_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" FROM PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_TAG2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_F0009_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_F0009_IOV2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_F0008_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_F0008_IOV2TAG" FROM PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0010_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0010_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0007_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0007_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0009_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0009_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0008_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0008_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0006_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0006_CHANNELS" FROM PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0010_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0010_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0007_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0007_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0009_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0009_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0008_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0008_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0006_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0006_CHANNELS" FROM PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_DB_ATTRIBUTES" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_NODES" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_NODES_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_TAG2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_TAG2TAG_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0010_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0010_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0007_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0007_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0006_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0006_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" FROM PUBLIC" +RalPrivilegeManager Debug Delete the RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Delete the RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalTagMgr Debug Delete the RelationalTagMgr +RelationalNodeMgr Debug Delete the RelationalNodeMgr +RelationalSchemaMgr Debug Delete the RalSchemaMgr +RelationalSchemaMgr Debug Delete the RelationalSchemaMgr +RelationalQueryMgr Debug Delete the RalQueryMgr +RelationalSequenceMgr Debug Delete the RalSequenceMgr +RelationalSequenceMgr Debug Delete the RelationalSequenceMgr +RalSessionMgr Info Delete the RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Disconnect from the database server +CORAL/Services/ConnectionService Debug Connection id=c6ce484c-8418-11dd-80c3-001617c3b642 to service "lcg_cool_nightly" has 0 session(s) opended. +CORAL/Services/ConnectionService Debug The active connection id=c6ce484c-8418-11dd-80c3-001617c3b642 to service "lcg_cool_nightly" has been removed from the active list. +RelationalQueryMgr Debug Delete the RelationalQueryMgr +CoralApplication Info Delete the COOL CoralApplication... +CoralApplication Info Delete the COOL database service +RalDatabaseSvc Info Delete the RalDatabaseSvc... +RalDatabaseSvc Info Purge the connection pool +RalDatabaseSvc Info Reset the ICS pointer +RalDatabaseSvc Info Delete the RalDatabaseSvc... DONE +CoralApplication Info Delete the CORAL connection service +CoralApplication Info Delete the COOL CoralApplication... DONE diff --git a/RelationalCool/utilities/coolPrivileges/logs/revokeReader.txt b/RelationalCool/utilities/coolPrivileges/logs/revokeReader.txt new file mode 100644 index 000000000..25655d9f0 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/revokeReader.txt @@ -0,0 +1,202 @@ +CoralApplication Info Create a cool::CoralApplication... +CoralApplication Info Enable the COOL signal handler +CoralApplication Info Create a new own CORAL connection service +CoralApplication Info Create the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +CoralApplication Info Create a cool::CoralApplication... DONE +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Instantiate a R/W RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Connect to the database server +PluginManager Info PluginManager creating CORAL/Services/ConnectionService component +PluginManager Info PluginMaager needs to load CORAL/Services/ConnectionService component +PluginManager Info PluginManager loaded ConnectionService library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IRelationalService: CORAL/Services/RelationalService +PluginManager Info PluginManager creating CORAL/Services/RelationalService component +PluginManager Info PluginMaager needs to load CORAL/Services/RelationalService component +PluginManager Info PluginManager loaded RelationalService library +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "coral" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "frontier" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "coral" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "frontier" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +PluginManager Info PluginManager creating CORAL/RelationalPlugins/oracle component +PluginManager Info PluginMaager needs to load CORAL/RelationalPlugins/oracle component +PluginManager Info PluginManager loaded OracleAccess library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IAuthenticationService: CORAL/Services/XMLAuthenticationService +PluginManager Info PluginManager creating CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginMaager needs to load CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginManager loaded XMLAuthenticationService library +CORAL/Services/XMLAuthenticationS... Info Authentication using /afs/cern.ch/user/a/avalassi/private/authentication.xml file +CORAL/Services/ConnectionService Debug No valid connection for string "oracle://lcg_cool_nightly/lcg_cool" found in the pool. Creating a new connection. +CORAL/Services/ConnectionService Debug Trying to get a new update session on "oracle://lcg_cool_nightly/lcg_cool" +CORAL/Services/ConnectionService Debug Connection parameters are: Retry-Period=10sec, Retry-Timeout=60sec, Connection-Timeout=0sec. +CORAL/Services/ConnectionService Info Connection to service "lcg_cool_nightly" established. Id=1a8d4df4-8417-11dd-ac95-001617c3b642 +CORAL/Services/ConnectionService Info New session on connection to service "lcg_cool_nightly" started for user "lcg_cool". Connection Id=1a8d4df4-8417-11dd-ac95-001617c3b642 +CORAL/Services/ConnectionService Debug A New connection to service "lcg_cool_nightly" has been added in the active list. Id=1a8d4df4-8417-11dd-ac95-001617c3b642 +RelationalDatabase Info Instantiate a R/W RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalQueryMgr Debug Instantiate a RelationalQueryMgr +RelationalQueryMgr Debug Instantiate a RalQueryMgr +RelationalSequenceMgr Debug Instantiate a RelationalSequenceMgr +RelationalSequenceMgr Debug Instantiate a RalSequenceMgr +RelationalSchemaMgr Debug Instantiate a RelationalSchemaMgr +RelationalSchemaMgr Debug Instantiate a RalSchemaMgr +RelationalNodeMgr Debug Instantiate a RelationalNodeMgr +RelationalTagMgr Debug Instantiate a RelationalTagMgr +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM LCG_COOL."COOLTEST_DB_ATTRIBUTES" "COOLTEST_DB_ATTRIBUTES"" +RelationalQueryMgr Debug Successfully fetched 10 table rows +RelationalDatabase Debug Release number match: database with CURRENT release number 2.6.0 will be opened using CURRENT client release number 2.6.0 +RalPrivilegeManager Debug Instantiate a RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +REVOKE 'READER' privileges from user PUBLIC +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_DB_ATTRIBUTES" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_NODES" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_NODES_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_TAG2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0010_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0010_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0007_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0007_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0006_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0006_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE SELECT ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" FROM PUBLIC" +RalPrivilegeManager Debug Delete the RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Delete the RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalTagMgr Debug Delete the RelationalTagMgr +RelationalNodeMgr Debug Delete the RelationalNodeMgr +RelationalSchemaMgr Debug Delete the RalSchemaMgr +RelationalSchemaMgr Debug Delete the RelationalSchemaMgr +RelationalQueryMgr Debug Delete the RalQueryMgr +RelationalSequenceMgr Debug Delete the RalSequenceMgr +RelationalSequenceMgr Debug Delete the RelationalSequenceMgr +RalSessionMgr Info Delete the RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Disconnect from the database server +CORAL/Services/ConnectionService Debug Connection id=1a8d4df4-8417-11dd-ac95-001617c3b642 to service "lcg_cool_nightly" has 0 session(s) opended. +CORAL/Services/ConnectionService Debug The active connection id=1a8d4df4-8417-11dd-ac95-001617c3b642 to service "lcg_cool_nightly" has been removed from the active list. +RelationalQueryMgr Debug Delete the RelationalQueryMgr +CoralApplication Info Delete the COOL CoralApplication... +CoralApplication Info Delete the COOL database service +RalDatabaseSvc Info Delete the RalDatabaseSvc... +RalDatabaseSvc Info Purge the connection pool +RalDatabaseSvc Info Reset the ICS pointer +RalDatabaseSvc Info Delete the RalDatabaseSvc... DONE +CoralApplication Info Delete the CORAL connection service +CoralApplication Info Delete the COOL CoralApplication... DONE diff --git a/RelationalCool/utilities/coolPrivileges/logs/revokeTagger.txt b/RelationalCool/utilities/coolPrivileges/logs/revokeTagger.txt new file mode 100644 index 000000000..f63948853 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/revokeTagger.txt @@ -0,0 +1,372 @@ +CoralApplication Info Create a cool::CoralApplication... +CoralApplication Info Enable the COOL signal handler +CoralApplication Info Create a new own CORAL connection service +CoralApplication Info Create the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +CoralApplication Info Create a cool::CoralApplication... DONE +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Instantiate a R/W RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Connect to the database server +PluginManager Info PluginManager creating CORAL/Services/ConnectionService component +PluginManager Info PluginMaager needs to load CORAL/Services/ConnectionService component +PluginManager Info PluginManager loaded ConnectionService library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IRelationalService: CORAL/Services/RelationalService +PluginManager Info PluginManager creating CORAL/Services/RelationalService component +PluginManager Info PluginMaager needs to load CORAL/Services/RelationalService component +PluginManager Info PluginManager loaded RelationalService library +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "coral" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "frontier" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "coral" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "frontier" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +PluginManager Info PluginManager creating CORAL/RelationalPlugins/oracle component +PluginManager Info PluginMaager needs to load CORAL/RelationalPlugins/oracle component +PluginManager Info PluginManager loaded OracleAccess library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IAuthenticationService: CORAL/Services/XMLAuthenticationService +PluginManager Info PluginManager creating CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginMaager needs to load CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginManager loaded XMLAuthenticationService library +CORAL/Services/XMLAuthenticationS... Info Authentication using /afs/cern.ch/user/a/avalassi/private/authentication.xml file +CORAL/Services/ConnectionService Debug No valid connection for string "oracle://lcg_cool_nightly/lcg_cool" found in the pool. Creating a new connection. +CORAL/Services/ConnectionService Debug Trying to get a new update session on "oracle://lcg_cool_nightly/lcg_cool" +CORAL/Services/ConnectionService Debug Connection parameters are: Retry-Period=10sec, Retry-Timeout=60sec, Connection-Timeout=0sec. +CORAL/Services/ConnectionService Info Connection to service "lcg_cool_nightly" established. Id=baab43e4-8418-11dd-8d94-001617c3b642 +CORAL/Services/ConnectionService Info New session on connection to service "lcg_cool_nightly" started for user "lcg_cool". Connection Id=baab43e4-8418-11dd-8d94-001617c3b642 +CORAL/Services/ConnectionService Debug A New connection to service "lcg_cool_nightly" has been added in the active list. Id=baab43e4-8418-11dd-8d94-001617c3b642 +RelationalDatabase Info Instantiate a R/W RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalQueryMgr Debug Instantiate a RelationalQueryMgr +RelationalQueryMgr Debug Instantiate a RalQueryMgr +RelationalSequenceMgr Debug Instantiate a RelationalSequenceMgr +RelationalSequenceMgr Debug Instantiate a RalSequenceMgr +RelationalSchemaMgr Debug Instantiate a RelationalSchemaMgr +RelationalSchemaMgr Debug Instantiate a RalSchemaMgr +RelationalNodeMgr Debug Instantiate a RelationalNodeMgr +RelationalTagMgr Debug Instantiate a RelationalTagMgr +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM LCG_COOL."COOLTEST_DB_ATTRIBUTES" "COOLTEST_DB_ATTRIBUTES"" +RelationalQueryMgr Debug Successfully fetched 10 table rows +RelationalDatabase Debug Release number match: database with CURRENT release number 2.6.0 will be opened using CURRENT client release number 2.6.0 +RalPrivilegeManager Debug Instantiate a RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +REVOKE 'TAGGER' privileges from user PUBLIC +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_TAG2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0009_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0009_IOV2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0008_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0008_IOV2TAG" FROM PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_TAG2TAG_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0005_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0003_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0009_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0008_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0004_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0002_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0001_TAGS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0000_TAGS_SEQ" FROM PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/UcharSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/UcharSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/SV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/SV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec/MV' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec/MV' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/SimpleSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/SimpleSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/ReferenceSpec' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/ReferenceSpec' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolderSet Debug Instantiate a RelationalFolderSet for '/' +RelationalFolderSet Debug Delete the RelationalFolderSet for '/' +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_TAG2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_F0009_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_F0009_IOV2TAG" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_F0008_TAGS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE DELETE ON LCG_COOL."COOLTEST_F0008_IOV2TAG" FROM PUBLIC" +RalPrivilegeManager Debug Delete the RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Delete the RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalTagMgr Debug Delete the RelationalTagMgr +RelationalNodeMgr Debug Delete the RelationalNodeMgr +RelationalSchemaMgr Debug Delete the RalSchemaMgr +RelationalSchemaMgr Debug Delete the RelationalSchemaMgr +RelationalQueryMgr Debug Delete the RalQueryMgr +RelationalSequenceMgr Debug Delete the RalSequenceMgr +RelationalSequenceMgr Debug Delete the RelationalSequenceMgr +RalSessionMgr Info Delete the RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Disconnect from the database server +CORAL/Services/ConnectionService Debug Connection id=baab43e4-8418-11dd-8d94-001617c3b642 to service "lcg_cool_nightly" has 0 session(s) opended. +CORAL/Services/ConnectionService Debug The active connection id=baab43e4-8418-11dd-8d94-001617c3b642 to service "lcg_cool_nightly" has been removed from the active list. +RelationalQueryMgr Debug Delete the RelationalQueryMgr +CoralApplication Info Delete the COOL CoralApplication... +CoralApplication Info Delete the COOL database service +RalDatabaseSvc Info Delete the RalDatabaseSvc... +RalDatabaseSvc Info Purge the connection pool +RalDatabaseSvc Info Reset the ICS pointer +RalDatabaseSvc Info Delete the RalDatabaseSvc... DONE +CoralApplication Info Delete the CORAL connection service +CoralApplication Info Delete the COOL CoralApplication... DONE diff --git a/RelationalCool/utilities/coolPrivileges/logs/revokeWriter.txt b/RelationalCool/utilities/coolPrivileges/logs/revokeWriter.txt new file mode 100644 index 000000000..8f8b66c0b --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/revokeWriter.txt @@ -0,0 +1,195 @@ +CoralApplication Info Create a cool::CoralApplication... +CoralApplication Info Enable the COOL signal handler +CoralApplication Info Create a new own CORAL connection service +CoralApplication Info Create the COOL database service +RalDatabaseSvc Info Instantiate the RalDatabaseSvc +CoralApplication Info Create a cool::CoralApplication... DONE +RelationalDatabase Debug Instantiate a RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Instantiate a R/W RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Connect to the database server +PluginManager Info PluginManager creating CORAL/Services/ConnectionService component +PluginManager Info PluginMaager needs to load CORAL/Services/ConnectionService component +PluginManager Info PluginManager loaded ConnectionService library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IRelationalService: CORAL/Services/RelationalService +PluginManager Info PluginManager creating CORAL/Services/RelationalService component +PluginManager Info PluginMaager needs to load CORAL/Services/RelationalService component +PluginManager Info PluginManager loaded RelationalService library +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "coral" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "frontier" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "mysql" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "oracle" with native implementation +CORAL/Services/RelationalService Info Found plugin for RDBMS technology "sqlite" with native implementation +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "coral" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "frontier" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "mysql" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "oracle" is native +CORAL/Services/RelationalService Info Default implementation for RDBMS technology "sqlite" is native +PluginManager Info PluginManager creating CORAL/RelationalPlugins/oracle component +PluginManager Info PluginMaager needs to load CORAL/RelationalPlugins/oracle component +PluginManager Info PluginManager loaded OracleAccess library +CORAL/Services/ConnectionService Info Loading default plugin for coral::IAuthenticationService: CORAL/Services/XMLAuthenticationService +PluginManager Info PluginManager creating CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginMaager needs to load CORAL/Services/XMLAuthenticationService component +PluginManager Info PluginManager loaded XMLAuthenticationService library +CORAL/Services/XMLAuthenticationS... Info Authentication using /afs/cern.ch/user/a/avalassi/private/authentication.xml file +CORAL/Services/ConnectionService Debug No valid connection for string "oracle://lcg_cool_nightly/lcg_cool" found in the pool. Creating a new connection. +CORAL/Services/ConnectionService Debug Trying to get a new update session on "oracle://lcg_cool_nightly/lcg_cool" +CORAL/Services/ConnectionService Debug Connection parameters are: Retry-Period=10sec, Retry-Timeout=60sec, Connection-Timeout=0sec. +CORAL/Services/ConnectionService Info Connection to service "lcg_cool_nightly" established. Id=bcec47ac-8418-11dd-8186-001617c3b642 +CORAL/Services/ConnectionService Info New session on connection to service "lcg_cool_nightly" started for user "lcg_cool". Connection Id=bcec47ac-8418-11dd-8186-001617c3b642 +CORAL/Services/ConnectionService Debug A New connection to service "lcg_cool_nightly" has been added in the active list. Id=bcec47ac-8418-11dd-8186-001617c3b642 +RelationalDatabase Info Instantiate a R/W RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalQueryMgr Debug Instantiate a RelationalQueryMgr +RelationalQueryMgr Debug Instantiate a RalQueryMgr +RelationalSequenceMgr Debug Instantiate a RelationalSequenceMgr +RelationalSequenceMgr Debug Instantiate a RalSequenceMgr +RelationalSchemaMgr Debug Instantiate a RelationalSchemaMgr +RelationalSchemaMgr Debug Instantiate a RalSchemaMgr +RelationalNodeMgr Debug Instantiate a RelationalNodeMgr +RelationalTagMgr Debug Instantiate a RelationalTagMgr +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "DB_ATTRIBUTE_NAME", "DB_ATTRIBUTE_VALUE" FROM LCG_COOL."COOLTEST_DB_ATTRIBUTES" "COOLTEST_DB_ATTRIBUTES"" +RelationalQueryMgr Debug Successfully fetched 10 table rows +RelationalDatabase Debug Release number match: database with CURRENT release number 2.6.0 will be opened using CURRENT client release number 2.6.0 +RalPrivilegeManager Debug Instantiate a RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +REVOKE 'WRITER' privileges from user PUBLIC +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0010_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0010_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0007_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0007_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0009_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0009_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0008_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0008_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0006_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE INSERT ON LCG_COOL."COOLTEST_F0006_CHANNELS" FROM PUBLIC" +RelationalNodeMgr Debug Fetch all nodes in the database +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" ORDER BY "NODE_FULLPATH" DESC" +RelationalQueryMgr Debug Successfully fetched 11 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec/uc +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/UcharSpec/uc' +RelationalFolder Debug Delete the RelationalFolder for '/UcharSpec/uc' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/UcharSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV/sv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/SV/sv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/SV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv2 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv2' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV/mv1 +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalFolder Debug Delete the RelationalFolder for '/SimpleSpec/MV/mv1' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec/MV +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/SimpleSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec/ref +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalFolder Debug Instantiate a RelationalFolder for '/ReferenceSpec/ref' +RelationalFolder Debug Delete the RelationalFolder for '/ReferenceSpec/ref' +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ReferenceSpec +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +RelationalNodeMgr Debug Fetch table row for folder[set] with fullPath=/ +CORAL/RelationalPlugins/oracle Debug Prepared statement : "SELECT "NODE_ID", "NODE_PARENTID", "NODE_NAME", "NODE_FULLPATH", "NODE_DESCRIPTION", "NODE_ISLEAF", "NODE_SCHEMA_VERSION", "NODE_INSTIME", "LASTMOD_DATE", "FOLDER_VERSIONING", "FOLDER_PAYLOADSPEC", "FOLDER_PAYLOAD_INLINE", "FOLDER_PAYLOAD_EXTREF", "FOLDER_CHANNELSPEC", "FOLDER_CHANNEL_EXTREF", "FOLDER_IOVTABLENAME", "FOLDER_TAGTABLENAME", "FOLDER_IOV2TAGTABLENAME", "FOLDER_CHANNELTABLENAME" FROM LCG_COOL."COOLTEST_NODES" "COOLTEST_NODES" WHERE "NODE_FULLPATH"= :"fullName"" +RelationalQueryMgr Debug Successfully fetched 1 table rows +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0010_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0010_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0010_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0007_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0007_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0007_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0009_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0009_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0009_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0008_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0008_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0008_CHANNELS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0006_IOVS" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0006_IOVS_SEQ" FROM PUBLIC" +CORAL/RelationalPlugins/oracle Debug Prepared statement : "REVOKE UPDATE ON LCG_COOL."COOLTEST_F0006_CHANNELS" FROM PUBLIC" +RalPrivilegeManager Debug Delete the RalPrivilegeManager for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Info Delete the RalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalDatabase Debug Delete the RelationalDatabase for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RelationalTagMgr Debug Delete the RelationalTagMgr +RelationalNodeMgr Debug Delete the RelationalNodeMgr +RelationalSchemaMgr Debug Delete the RalSchemaMgr +RelationalSchemaMgr Debug Delete the RelationalSchemaMgr +RelationalQueryMgr Debug Delete the RalQueryMgr +RelationalSequenceMgr Debug Delete the RalSequenceMgr +RelationalSequenceMgr Debug Delete the RelationalSequenceMgr +RalSessionMgr Info Delete the RalSessionMgr for 'oracle://lcg_cool_nightly;schema=lcg_cool;dbname=COOLTEST' +RalSessionMgr Info Disconnect from the database server +CORAL/Services/ConnectionService Debug Connection id=bcec47ac-8418-11dd-8186-001617c3b642 to service "lcg_cool_nightly" has 0 session(s) opended. +CORAL/Services/ConnectionService Debug The active connection id=bcec47ac-8418-11dd-8186-001617c3b642 to service "lcg_cool_nightly" has been removed from the active list. +RelationalQueryMgr Debug Delete the RelationalQueryMgr +CoralApplication Info Delete the COOL CoralApplication... +CoralApplication Info Delete the COOL database service +RalDatabaseSvc Info Delete the RalDatabaseSvc... +RalDatabaseSvc Info Purge the connection pool +RalDatabaseSvc Info Reset the ICS pointer +RalDatabaseSvc Info Delete the RalDatabaseSvc... DONE +CoralApplication Info Delete the CORAL connection service +CoralApplication Info Delete the COOL CoralApplication... DONE diff --git a/RelationalCool/utilities/coolPrivileges/logs/showTables.txt b/RelationalCool/utilities/coolPrivileges/logs/showTables.txt new file mode 100644 index 000000000..9ac1e0572 --- /dev/null +++ b/RelationalCool/utilities/coolPrivileges/logs/showTables.txt @@ -0,0 +1,35 @@ +COOLTEST_TAGS_SEQ +COOLTEST_TAGS +COOLTEST_TAG2TAG_SEQ +COOLTEST_TAG2TAG +COOLTEST_NODES_SEQ +COOLTEST_NODES +COOLTEST_IOVS_SEQ +COOLTEST_F0010_IOVS_SEQ +COOLTEST_F0010_IOVS +COOLTEST_F0010_CHANNELS +COOLTEST_F0009_TAGS_SEQ +COOLTEST_F0009_TAGS +COOLTEST_F0009_IOVS_SEQ +COOLTEST_F0009_IOVS +COOLTEST_F0009_IOV2TAG +COOLTEST_F0009_CHANNELS +COOLTEST_F0008_TAGS_SEQ +COOLTEST_F0008_TAGS +COOLTEST_F0008_IOVS_SEQ +COOLTEST_F0008_IOVS +COOLTEST_F0008_IOV2TAG +COOLTEST_F0008_CHANNELS +COOLTEST_F0007_IOVS_SEQ +COOLTEST_F0007_IOVS +COOLTEST_F0007_CHANNELS +COOLTEST_F0006_IOVS_SEQ +COOLTEST_F0006_IOVS +COOLTEST_F0006_CHANNELS +COOLTEST_F0005_TAGS_SEQ +COOLTEST_F0004_TAGS_SEQ +COOLTEST_F0003_TAGS_SEQ +COOLTEST_F0002_TAGS_SEQ +COOLTEST_F0001_TAGS_SEQ +COOLTEST_F0000_TAGS_SEQ +COOLTEST_DB_ATTRIBUTES diff --git a/RelationalCool/utilities/coolReplicateDB/Replication.cpp b/RelationalCool/utilities/coolReplicateDB/Replication.cpp new file mode 100644 index 000000000..767c10ec7 --- /dev/null +++ b/RelationalCool/utilities/coolReplicateDB/Replication.cpp @@ -0,0 +1,1038 @@ +// $Id: Replication.cpp,v 1.42 2008-09-01 16:38:12 avalassi Exp $ + +// Include files +#include <iostream> +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeList.h" +#include "CoralBase/AttributeListException.h" +#include "CoolKernel/Exception.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/Record.h" +#include "RelationalAccess/IBulkOperation.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" +#include "RelationalAccess/IColumn.h" +#include "RelationalAccess/IQuery.h" +#include "RelationalAccess/ISchema.h" +#include "RelationalAccess/ISessionProxy.h" +#include "RelationalAccess/ITable.h" +#include "RelationalAccess/ITableDataEditor.h" +#include "RelationalAccess/ITableDescription.h" +#include "RelationalAccess/TableDescription.h" +#include "RelationalAccess/ITransaction.h" + +// Local include files +#include "Replication.h" +#include "../../src/RalDatabase.h" +#include "../../src/RalQueryMgr.h" +#include "../../src/RelationalChannelTable.h" +#include "../../src/RelationalDatabaseTable.h" +#include "../../src/RelationalFolder.h" +#include "../../src/RelationalGlobalTagTable.h" +#include "../../src/RelationalNodeMgr.h" +#include "../../src/RelationalNodeTable.h" +#include "../../src/RelationalObject2TagTable.h" +#include "../../src/RelationalObjectMgr.h" +#include "../../src/RelationalObjectTable.h" +#include "../../src/RelationalObjectTableRow.h" +#include "../../src/RelationalQueryMgr.h" +#include "../../src/RelationalSequence.h" +#include "../../src/RelationalSequenceMgr.h" +#include "../../src/RelationalSchemaMgr.h" +#include "../../src/RelationalTag2TagTable.h" +#include "../../src/RelationalTagTable.h" +#include "../../src/RelationalTransaction.h" +#include "../../src/sleep.h" + +using namespace cool; + +// Message output +#define LOG std::cout + +// Local type definitions +typedef boost::shared_ptr<RelationalSequence> RelationalSequencePtr; + +//--------------------------------------------------------------------------- + +Replication::Replication() + : CoralApplication() +{ + + // Disable CORAL automatic pool clean up thread + coral::IConnectionServiceConfiguration &connSvcConf = + connectionSvc().configuration(); + + // If we can access a LFC and the user is not explicitely forbidding it, + // we try to use CORAL LFCReplicaService + if ( ::getenv("COOL_IGNORE_LFC") == NULL && + ::getenv("LFC_HOST") != NULL ) { + // use CORAL LFCReplicaService + connSvcConf.setAuthenticationService("CORAL/Services/LFCReplicaService"); + connSvcConf.setLookupService("CORAL/Services/LFCReplicaService"); + } + + connSvcConf.disablePoolAutomaticCleanUp(); + connSvcConf.setConnectionTimeOut( 0 ); + +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalTableRow> +Replication::newNodeTableRows( const RalDatabase& db, + const std::string& lastUpdate ) +{ + coral::AttributeList whereData; + whereData.extend + ( "lastUpdate", + typeIdToCoralType + ( RelationalNodeTable::columnTypeIds::nodeInsertionTime ) ); + whereData["lastUpdate"].setValue( lastUpdate ); + std::string whereClause = + RelationalNodeTable::columnNames::nodeInsertionTime + " > :lastUpdate"; + + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeId; + orderBy.push_back( orderClause ); + std::string desc = ""; + + std::vector<RelationalTableRow> rows = + db.queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db.nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + return rows; +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalTableRow> +Replication::modifiedNodeTableRows( const RalDatabase& db, + const std::string& lastUpdate ) +{ + coral::AttributeList whereData; + whereData.extend + ( "lastUpdate", + typeIdToCoralType + ( RelationalNodeTable::columnTypeIds::lastModDate ) ); + whereData["lastUpdate"].setValue( lastUpdate ); + std::string whereClause = + RelationalNodeTable::columnNames::lastModDate + " > :lastUpdate" + + " and " + + RelationalNodeTable::columnNames::lastModDate + " > " + + RelationalNodeTable::columnNames::nodeInsertionTime; + + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeId; + orderBy.push_back( orderClause ); + std::string desc = ""; + + std::vector<RelationalTableRow> rows = + db.queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db.nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + return rows; +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalTableRow> +Replication::fetchNodeTableRows( const RalDatabase& db, bool isLeaf ) +{ + coral::AttributeList whereData; + whereData.extend + ( "isLeaf", + typeIdToCoralType + ( RelationalNodeTable::columnTypeIds::nodeIsLeaf ) ); + whereData["isLeaf"].setValue( isLeaf ); + std::string whereClause = + RelationalNodeTable::columnNames::nodeIsLeaf + " = :isLeaf"; + + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeId; + orderBy.push_back( orderClause ); + std::string desc = ""; + + std::vector<RelationalTableRow> rows = + db.queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db.nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + return rows; +} + +//--------------------------------------------------------------------------- + +boost::shared_ptr<CursorHandle> +Replication::newObjectTableRows( const RalDatabase& db, + const RelationalFolder& folder, + const std::string& lastUpdate ) +{ + coral::AttributeList whereData; + whereData.extend + ( "lastUpdate", + typeIdToCoralType + ( RelationalObjectTable::columnTypeIds::sysInsTime ) ); + whereData["lastUpdate"].setValue( lastUpdate ); + std::string whereClause = + RelationalObjectTable::columnNames::sysInsTime() + " > :lastUpdate"; + + std::vector<std::string> orderBy; + std::string orderClause = RelationalObjectTable::columnNames::objectId(); + orderBy.push_back( orderClause ); + + std::auto_ptr<RalQueryMgr> queryMgr( new RalQueryMgr( db.sessionMgr() ) ); + boost::shared_ptr<coral::AttributeList> dataBuffer; + std::auto_ptr<coral::IQuery> query = + queryMgr->prepareQuery + ( RelationalQueryMgr::tableList( folder.objectTableName() ), + RelationalQueryMgr::columnList + ( RelationalObjectTable::tableSpecification + ( folder.payloadSpecification() ) ), + whereClause, whereData, orderBy, dataBuffer ); + return boost::shared_ptr<CursorHandle>( new CursorHandle( query, + dataBuffer ) ); +} + +//--------------------------------------------------------------------------- + +boost::shared_ptr<CursorHandle> +Replication::modifiedObjectTableRows( const RalDatabase& db, + const RelationalFolder& folder, + const std::string& lastUpdate ) +{ + coral::AttributeList whereData; + whereData.extend + ( "lastUpdate", + typeIdToCoralType + ( RelationalObjectTable::columnTypeIds::lastModDate ) ); + whereData["lastUpdate"].setValue( lastUpdate ); + std::string whereClause = + RelationalObjectTable::columnNames::lastModDate() + " > :lastUpdate" + + " and " + + RelationalObjectTable::columnNames::lastModDate() + " > " + + RelationalObjectTable::columnNames::sysInsTime(); + + std::vector<std::string> orderBy; + std::string orderClause = RelationalObjectTable::columnNames::objectId(); + orderBy.push_back( orderClause ); + + std::auto_ptr<RalQueryMgr> queryMgr( new RalQueryMgr( db.sessionMgr() ) ); + boost::shared_ptr<coral::AttributeList> dataBuffer; + std::auto_ptr<coral::IQuery> query = + queryMgr->prepareQuery + ( RelationalQueryMgr::tableList( folder.objectTableName() ), + RelationalQueryMgr::columnList + ( RelationalObjectTable::tableSpecification + ( folder.payloadSpecification() ) ), + whereClause, whereData, orderBy, dataBuffer ); + return boost::shared_ptr<CursorHandle>( new CursorHandle( query, + dataBuffer ) ); +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalTableRow> +Replication::localTagTableRows( const RalDatabase& db, + const RelationalFolder& folder ) +{ + coral::AttributeList whereData; + std::string whereClause = ""; + + std::vector<std::string> orderBy; + std::string orderClause = RelationalTagTable::columnNames::tagId; + orderBy.push_back( orderClause ); + std::string desc = ""; + + std::vector<RelationalTableRow> rows = + db.queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( folder.tagTableName() ), + RelationalQueryMgr::columnList + ( RelationalTagTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + return rows; +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalTableRow> +Replication::object2TagTableRows( const RalDatabase& db, + const RelationalFolder& folder ) +{ + coral::AttributeList whereData; + std::string whereClause = ""; + + std::vector<std::string> orderBy; + std::string desc = ""; + + std::vector<RelationalTableRow> rows = + db.queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( folder.object2TagTableName() ), + RelationalQueryMgr::columnList + ( RelationalObject2TagTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + return rows; +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalTableRow> +Replication::globalTagTableRows( const RalDatabase& db ) +{ + coral::AttributeList whereData; + std::string whereClause = ""; + + std::vector<std::string> orderBy; + std::string desc = ""; + + std::vector<RelationalTableRow> rows = + db.queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db.globalTagTableName() ), + RelationalQueryMgr::columnList + ( RelationalGlobalTagTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + return rows; +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalTableRow> +Replication::tag2TagTableRows( const RalDatabase& db ) +{ + coral::AttributeList whereData; + std::string whereClause = ""; + + std::vector<std::string> orderBy; + std::string desc = ""; + + std::vector<RelationalTableRow> rows = + db.queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db.tag2TagTableName() ), + RelationalQueryMgr::columnList + ( RelationalTag2TagTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + return rows; +} + +//--------------------------------------------------------------------------- + +std::vector<RelationalTableRow> +Replication::channelTableRows( const RalDatabase& db, + const RelationalFolder& folder ) +{ + coral::AttributeList whereData; + std::string whereClause = ""; + + std::vector<std::string> orderBy; + std::string desc = ""; + + std::vector<RelationalTableRow> rows = + db.queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( folder.channelTableName() ), + RelationalQueryMgr::columnList + ( RelationalChannelTable::tableSpecification() ), + whereClause, whereData, orderBy, desc ); + + return rows; +} + +//--------------------------------------------------------------------------- + +unsigned int +Replication::bulkInsert( const RalDatabase& db, + const std::string& tableName, + boost::shared_ptr<CursorHandle>& cursorHandle ) +{ + if ( ! cursorHandle->cursor().next() ) return 0; + + coral::ITable& + objectTable = db.session().nominalSchema().tableHandle( tableName ); + coral::AttributeList data( cursorHandle->cursor().currentRow() ); + //coral::AttributeList data( rows[0].data() ); + int rowCacheSize = 100; + std::auto_ptr<coral::IBulkOperation> + bulkInserter( objectTable.dataEditor().bulkInsert( data, rowCacheSize ) ); + + int rowCount = 0; + do { + data.fastCopyData( cursorHandle->cursor().currentRow() ); + bulkInserter->processNextIteration(); + ++rowCount; + } while ( cursorHandle->cursor().next() ); + + bulkInserter->flush(); + + return rowCount; +} + +//--------------------------------------------------------------------------- + +unsigned int +Replication::bulkInsert( const RalDatabase& db, + const std::string& tableName, + const std::vector<RelationalTableRow>& rows ) +{ + if ( rows.empty() ) return 0; + + coral::ITable& + objectTable = db.session().nominalSchema().tableHandle( tableName ); + coral::AttributeList data( rows[0].data() ); + int rowCacheSize = 100; + std::auto_ptr<coral::IBulkOperation> + bulkInserter( objectTable.dataEditor().bulkInsert( data, rowCacheSize ) ); + + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + data.fastCopyData( row->data() ); + bulkInserter->processNextIteration(); + } + + bulkInserter->flush(); + + return rows.size(); +} + +//--------------------------------------------------------------------------- + +void +Replication::bulkUpdateObjectTableRows +( const RalDatabase& db, + const std::string& tableName, + boost::shared_ptr<CursorHandle>& cursorHandle ) +{ + if ( ! cursorHandle->cursor().next() ) return; + + coral::AttributeList updateData( cursorHandle->cursor().currentRow() ); + + std::string setClause = ""; + bool first = true; + for ( coral::AttributeList::const_iterator + i = updateData.begin(); i != updateData.end(); ++i ) { + if ( first ) { + first = false; + } else { + setClause += ", "; + } + setClause += i->specification().name() + " = :" + + i->specification().name(); + } + + std::string whereClause = RelationalObjectTable::columnNames::objectId(); + whereClause += "= :" + RelationalObjectTable::columnNames::objectId(); + + coral::ITable& + objectTable = db.session().nominalSchema().tableHandle( tableName ); + + int dataCacheSize = 100; // rows + std::auto_ptr<coral::IBulkOperation> + query( objectTable.dataEditor().bulkUpdateRows( setClause, + whereClause, + updateData, + dataCacheSize ) ); + + do { + updateData.fastCopyData( cursorHandle->cursor().currentRow() ); + query->processNextIteration(); + } while ( cursorHandle->cursor().next() ); + + query->flush(); +} + +//--------------------------------------------------------------------------- + +void +Replication::bulkUpdateNodeTableDescriptions +( const RalDatabase& db, + const std::vector<RelationalTableRow>& rows ) +{ + if ( rows.empty() ) return; + + coral::AttributeList updateData; + updateData.extend + ( "description", + typeIdToCoralType + ( RelationalNodeTable::columnTypeIds::nodeDescription ) ); + updateData.extend + ( "nodeId", + typeIdToCoralType + ( RelationalNodeTable::columnTypeIds::nodeId ) ); + + std::string setClause = + RelationalNodeTable::columnNames::nodeDescription + " = :description"; + + std::string whereClause = + RelationalNodeTable::columnNames::nodeId + " = :nodeId"; + + coral::ITable& + table = db.session().nominalSchema().tableHandle( db.nodeTableName() ); + + int dataCacheSize = 100; // rows + std::auto_ptr<coral::IBulkOperation> + query( table.dataEditor().bulkUpdateRows( setClause, + whereClause, + updateData, + dataCacheSize ) ); + + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) { + updateData["description"].setValue + ( row->data()[RelationalNodeTable::columnNames::nodeDescription]. + data<std::string>() ); + updateData["nodeId"].setValue + ( row->data()[RelationalNodeTable::columnNames::nodeId]. + data<unsigned int>() ); + query->processNextIteration(); + } + + query->flush(); +} + +//--------------------------------------------------------------------------- + +std::string Replication::serverTime( const RalDatabase& db ) +{ + std::string serverTimeClause = db.queryMgr().serverTimeClause(); + coral::AttributeList data; + data.extend( serverTimeClause, + typeIdToCoralType( StorageType::String255 ) ); + + std::auto_ptr<coral::IQuery> + query( db.session().nominalSchema().newQuery() ); + query->addToTableList( db.mainTableName() ); + query->addToOutputList( serverTimeClause ); + query->defineOutput( data ); + + coral::ICursor& cursor = query->execute(); + cursor.next(); + return cursor.currentRow()[serverTimeClause].data<std::string>(); +} + +//--------------------------------------------------------------------------- + +void Replication::updateLastReplication( const RalDatabase& db, + const std::string& lastReplication ) +{ + LOG << "Setting time of replication in target" << std::endl; + + coral::AttributeList updateData; + updateData.extend + ( "lastReplication", + typeIdToCoralType + (RelationalDatabaseTable::columnTypeIds::attributeValue) ); + updateData["lastReplication"].setValue( lastReplication ); + std::string setClause = + RelationalDatabaseTable::columnNames::attributeValue; + setClause += "= :lastReplication"; + std::string whereClause = + RelationalDatabaseTable::columnNames::attributeName + + " = '" + RelationalDatabaseTable::attributeNames::lastReplication + "'"; + + // Execute the update + UInt32 updatedRows = db.queryMgr().updateTableRows + ( db.mainTableName(), setClause, whereClause, updateData ); + + if ( updatedRows == 0 ) { + // it's a new attribute + coral::AttributeList data = + Record( RelationalDatabaseTable::tableSpecification() ).attributeList(); + data[RelationalDatabaseTable::columnNames::attributeName].setValue + ( RelationalDatabaseTable::attributeNames::lastReplication ); + data[RelationalDatabaseTable::columnNames::attributeValue].setValue + ( lastReplication ); + db.queryMgr().insertTableRow( db.mainTableName(), data ); + } else if ( updatedRows != 1 ) { + throw Exception + ( "Could not update a row of the main table", "Replication" ); + } +} + +//--------------------------------------------------------------------------- + +void Replication::updateLastReplicationSource( const RalDatabase& db, + const std::string& sourceUrl ) +{ + LOG << "Setting replication source in target" << std::endl; + + coral::AttributeList updateData; + updateData.extend + ( "sourceUrl", + typeIdToCoralType + (RelationalDatabaseTable::columnTypeIds::attributeValue) ); + updateData["sourceUrl"].setValue( sourceUrl ); + std::string setClause = + RelationalDatabaseTable::columnNames::attributeValue; + setClause += "= :sourceUrl"; + std::string whereClause = + RelationalDatabaseTable::columnNames::attributeName + + " = '" + + RelationalDatabaseTable::attributeNames::lastReplicationSource + "'"; + + // Execute the update + UInt32 updatedRows = db.queryMgr().updateTableRows + ( db.mainTableName(), setClause, whereClause, updateData ); + + if ( updatedRows == 0 ) { + // it's a new attribute + coral::AttributeList data = + Record( RelationalDatabaseTable::tableSpecification() ).attributeList(); + data[RelationalDatabaseTable::columnNames::attributeName].setValue + ( RelationalDatabaseTable::attributeNames::lastReplicationSource ); + data[RelationalDatabaseTable::columnNames::attributeValue].setValue + ( sourceUrl ); + db.queryMgr().insertTableRow( db.mainTableName(), data ); + } else if ( updatedRows != 1 ) { + throw Exception + ( "Could not update a row of the main table", "Replication" ); + } +} + +//--------------------------------------------------------------------------- + +void Replication::setSourceDb( const std::string& url ) +{ + std::cout << "opening source: " << url << std::endl; + try { + bool readOnly = true; + m_sourceDb = databaseService().openDatabase( url, readOnly ); + } catch ( Exception& e ) { + std::cerr << "Exception: " << e.what() << std::endl; + std::cerr << "while opening " << url << std::endl; + throw e; + } + if ( m_sourceDb.get() == 0 ) throw Exception( "source db is null", + "Replication" ); + m_sourceRalDb = dynamic_cast<RalDatabase*>( m_sourceDb.get() ); + if ( m_sourceRalDb == 0 ) throw Exception( "source db is null", + "Replication" ); +} + +//--------------------------------------------------------------------------- + +void Replication::setTargetDb( const std::string& url ) +{ + std::cout << "opening target: " << url << std::endl; + try { + bool readOnly = false; + m_targetDb = databaseService().openDatabase( url, readOnly ); + } catch ( DatabaseDoesNotExist& ) { + m_targetDb = databaseService().createDatabase( url ); + } + if ( m_targetDb.get() == 0 ) throw Exception( "target db is null", + "Replication" ); + m_targetRalDb = dynamic_cast<RalDatabase*>( m_targetDb.get() ); + if ( m_targetRalDb == 0 ) throw Exception( "target db is null", + "Replication" ); +} + +//--------------------------------------------------------------------------- + +std::string Replication::getLastUpdate() +{ + std::string lastUpdate = "0000-00-00_00:00:00.000000000 GMT"; + coral::AttributeList targetDbAttributes = + targetDb().databaseAttributes().attributeList(); + try { + lastUpdate = targetDbAttributes + [RelationalDatabaseTable::attributeNames::lastReplication] + .data<std::string>(); + } + catch ( coral::AttributeListException& ) {} + return lastUpdate; +} + +//--------------------------------------------------------------------------- + +bool Replication::checkSchemaCompliance( const RalDatabase& source, + const RalDatabase& target ) +{ + coral::AttributeList sourceDbAttributes = + source.databaseAttributes().attributeList(); + coral::AttributeList targetDbAttributes = + target.databaseAttributes().attributeList(); + return + sourceDbAttributes[RelationalDatabaseTable::attributeNames::schemaVersion] + == + targetDbAttributes[RelationalDatabaseTable::attributeNames::schemaVersion]; +} + +//--------------------------------------------------------------------------- + +void Replication::replicateNodeTable( const std::string& lastUpdate ) +{ + LOG << "Replicating node table" << std::endl; + // check for dropped nodes + { + // Fetch nodes in reverse order so that dropping nodes will start with the + // deepest node. + bool ascending = false; + // Use node mgr directly to prevent opening of a new transaction. + std::vector<std::string> sourceNodes = + sourceDb().nodeMgr().listAllNodes( ascending ); + std::vector<std::string> targetNodes = + targetDb().nodeMgr().listAllNodes( ascending ); + // Find dropped nodes + for ( std::vector<std::string>::const_iterator + n = targetNodes.begin(); n != targetNodes.end(); ++n ) { + if ( find( sourceNodes.begin(), sourceNodes.end(), *n ) + == sourceNodes.end() ) { + // Node does not exist in source -- drop it + targetDb().__dropNode( *n ); + } + } + } + std::vector<RelationalTableRow> rows = newNodeTableRows( sourceDb(), + lastUpdate ); + + std::string nodeSeqName = + RelationalNodeTable::sequenceName( targetDb().nodeTableName() ); + RelationalSequencePtr nodeSeq + ( targetDb().queryMgr().sequenceMgr().getSequence( nodeSeqName ) ); + unsigned int previousNodeId = nodeSeq->currVal(); + + for ( std::vector<RelationalTableRow>::const_iterator + i = rows.begin(); i != rows.end(); ++i ) { + unsigned int nodeId = + i->data()[RelationalNodeTable::columnNames::nodeId] + .data<unsigned int>(); + bool nodeIsLeaf = + i->data()[RelationalNodeTable::columnNames::nodeIsLeaf] + .data<bool>(); + std::string nodeFullPath = + i->data()[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + std::string nodeDescription = + i->data()[RelationalNodeTable::columnNames::nodeDescription] + .data<std::string>(); + std::string folderPayloadSpecDesc = + i->data()[RelationalNodeTable::columnNames::folderPayloadSpecDesc] + .data<std::string>(); + FolderVersioning::Mode folderVersioningMode = + FolderVersioning::Mode + ( i->data()[RelationalNodeTable::columnNames::folderVersioningMode] + .data<int>() ); + + // Skip the root folder set if present, because even if it shows up + // in the selection (when a db has never been replicated) it will already + // exists on the target after database bootstrapping. In other words + // it then is already replicated through bootstrapping. + if ( nodeFullPath == "/" ) continue; + + // fix for bug #30578 + unsigned int gap = nodeId - previousNodeId; + // start counting from 1, because a gap of 1 is expected -- we only + // want to increment the node sequence for gaps larger than one + for ( unsigned int i = 1; i < gap; ++i ) { + nodeSeq->nextVal(); + } + previousNodeId = nodeId; + + // Check if the node exists on the target. If so, it was dropped and + // recreated in the meantime. Therefore we drop and recreate it as well. + if ( targetDb().nodeMgr().existsNode( nodeFullPath ) ) + targetDb().__dropNode( nodeFullPath ); + + bool createParents = false; + + LOG << "\tReplicating " << nodeFullPath << " ... "; + + if ( nodeIsLeaf ) { + RecordSpecification spec = + RelationalDatabase::decodeRecordSpecification + ( folderPayloadSpecDesc ); + targetDb().__createFolder( nodeFullPath, + spec, + nodeDescription, + folderVersioningMode, + createParents ); + } else { + targetDb().__createFolderSet( nodeFullPath, + nodeDescription, + createParents ); + } + LOG << "done" << std::endl; + } + // update modified node descriptions + { + std::vector<RelationalTableRow> rows = + modifiedNodeTableRows( sourceDb(), + lastUpdate ); + bulkUpdateNodeTableDescriptions( targetDb(), rows ); + } + // identify renamed/extended payload specifications + updatePayloadSpecifications(); +} + +//--------------------------------------------------------------------------- + +void Replication::updatePayloadSpecifications() { + bool isLeaf = true; + std::vector<RelationalTableRow> sourceNodes + = fetchNodeTableRows( sourceDb(), isLeaf ); + std::vector<RelationalTableRow> targetNodes + = fetchNodeTableRows( targetDb(), isLeaf ); + if ( ! sourceNodes.size() == targetNodes.size() ) { + throw Exception( "Unexpected size mismatch between source and target " + "node counts.", "Replication" ); + } + + std::vector<RelationalTableRow>::const_iterator s, t; + for ( s = sourceNodes.begin(), t = targetNodes.begin(); + s != sourceNodes.end(); + ++s, ++t ) { + std::string sourceFullPath = + s->data()[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + std::string targetFullPath = + t->data()[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + if ( sourceFullPath != targetFullPath ) { + throw Exception( "Unexpected node path mismatch between source " + "and target.", "Replication" ); + } + + // Get the folders and specs of source and target + IFolderPtr sourceFolder = sourceDb().__getFolder( sourceFullPath ); + IFolderPtr targetFolder = targetDb().__getFolder( targetFullPath ); + const IRecordSpecification& + sourceSpec = sourceFolder->payloadSpecification(); + const IRecordSpecification& + targetSpec = targetFolder->payloadSpecification(); + + if ( sourceSpec != targetSpec ) { + // Obtain a RelationalFolder pointer to call the interal API + RelationalFolder* relTargetFolder + = dynamic_cast<RelationalFolder*>(targetFolder.get()); + + // The source spec is at least as long as the target spec. We check the + // fields up to the target's size for name changes. Any extra fields in + // the source must be additional fields which we add. + UInt32 index = 0; + for ( ; index < targetSpec.size(); ++index ) { + if ( sourceSpec[index].name() != targetSpec[index].name() ) { + relTargetFolder->__renamePayload( targetSpec[index].name(), + sourceSpec[index].name() ); + } + } + + // We continue to use 'index' to loop over the potential extra fields + // in sourceSpec + for ( ; index < sourceSpec.size(); ++index ) { + // Prepare the new specification + // (we need to get the target spec from the folder each time, + // because it changes as we loop) + RecordSpecification newRecordSpecification; + newRecordSpecification.extend( sourceSpec[index] ); + Record newRecord( newRecordSpecification ); + relTargetFolder->__extendPayloadSpecification( newRecord ); + } + } + } +} + + +//--------------------------------------------------------------------------- + +void Replication::replicateNodes( const std::string& lastUpdate ) +{ + LOG << "Replicating nodes" << std::endl; + replicateFolderSets( lastUpdate ); + replicateFolders( lastUpdate ); +} + +//--------------------------------------------------------------------------- + +void Replication::replicateFolderSets( const std::string& /*lastUpdate*/ ) +{ + //LOG << "Replicating folder sets" << std::endl; + // only table is xxx_TAGS_SEQ which we don't replicate for the read-only + // target +} + +//--------------------------------------------------------------------------- + +void Replication::replicateFolders( const std::string& lastUpdate ) +{ + LOG << "Replicating folders" << std::endl; + bool isLeaf = true; + std::vector<RelationalTableRow> nodes = fetchNodeTableRows( sourceDb(), + isLeaf ); + + for ( std::vector<RelationalTableRow>::const_iterator + n = nodes.begin(); n != nodes.end(); ++n ) { + RelationalFolder sourceFolder( sourceDb().relationalDbPtr(), n->data() ); + RelationalTableRow targetNode = + targetDb().nodeMgr().fetchNodeTableRow( sourceFolder.fullPath() ); + RelationalFolder targetFolder( targetDb().relationalDbPtr(), + targetNode.data() ); + LOG << "\tReplicating " << sourceFolder.fullPath() << " ... "; + replicateFolder( sourceFolder, targetFolder, lastUpdate ); + LOG << " done" << std::endl; + } +} + +//--------------------------------------------------------------------------- + +void Replication::replicateFolder( const RelationalFolder& sourceFolder, + const RelationalFolder& targetFolder, + const std::string& lastUpdate ) +{ + // replicate channels (drop the FK to the channel table, + // delete all channels, recreate all channels, recreate the FK) + { + targetDb().schemaMgr().dropObjectChannelFK + ( targetFolder.objectTableName() ); + std::vector<RelationalTableRow> rows = + channelTableRows( sourceDb(), sourceFolder ); + std::string whereClause = ""; + coral::AttributeList whereData; + targetDb().queryMgr().deleteTableRows + ( targetFolder.channelTableName(), whereClause, whereData ); + bulkInsert( targetDb(), targetFolder.channelTableName(), rows ); + targetDb().schemaMgr().createObjectChannelFK + ( targetFolder.objectTableName(), + targetFolder.channelTableName() ); + } + // update modified iovs + { + boost::shared_ptr<CursorHandle> + cursorHandle = modifiedObjectTableRows( sourceDb(), + sourceFolder, + lastUpdate ); + bulkUpdateObjectTableRows( targetDb(), + targetFolder.objectTableName(), + cursorHandle ); + } + // replicate new iovs + { + boost::shared_ptr<CursorHandle> + cursorHandle = newObjectTableRows( sourceDb(), + sourceFolder, + lastUpdate ); + bulkInsert( targetDb(), targetFolder.objectTableName(), cursorHandle ); + } + if ( sourceFolder.versioningMode() == FolderVersioning::MULTI_VERSION ) { + // clear target's tag related tables + // (do object2tag first, because of integrity constraints) + std::string whereClause = ""; + coral::AttributeList whereData; + targetDb().queryMgr().deleteTableRows( targetFolder.object2TagTableName(), + whereClause, + whereData ); + targetDb().queryMgr().deleteTableRows( targetFolder.tagTableName(), + whereClause, + whereData ); + // replicate local tags + { + std::vector<RelationalTableRow> rows = localTagTableRows( sourceDb(), + sourceFolder ); + bulkInsert( targetDb(), targetFolder.tagTableName(), rows ); + } + // replicate tag to iov relations + { + std::vector<RelationalTableRow> rows = + object2TagTableRows( sourceDb(), sourceFolder ); + bulkInsert( targetDb(), targetFolder.object2TagTableName(), rows ); + } + } +} + +//--------------------------------------------------------------------------- + +void Replication::replicateTags() +{ + LOG << "Replicating tags" << std::endl; + // remove integrity constraint on target tag2tag table + targetDb().schemaMgr().dropTag2TagFKs( targetDb().tag2TagTableName() ); + // replicate global tag table + { + std::vector<RelationalTableRow> rows = globalTagTableRows( sourceDb() ); + std::string whereClause = ""; + coral::AttributeList whereData; + targetDb().queryMgr().deleteTableRows( targetDb().globalTagTableName(), + whereClause, + whereData ); + bulkInsert( targetDb(), targetDb().globalTagTableName(), rows ); + } + // reenable integrity constraint on target tag2tag table + targetDb().schemaMgr().createTag2TagFKs( targetDb().tag2TagTableName(), + targetDb().globalTagTableName() ); + // replicate tag to tag tabel + { + // delete all target rows + std::string whereClause = ""; + coral::AttributeList whereData; + targetDb().queryMgr().deleteTableRows( targetDb().tag2TagTableName(), + whereClause, + whereData ); + + // fetch and insert source rows into target table + std::vector<RelationalTableRow> rows = tag2TagTableRows( sourceDb() ); + bulkInsert( targetDb(), targetDb().tag2TagTableName(), rows ); + } +} + +//--------------------------------------------------------------------------- + +int Replication::replicate( const std::string& sourceUrl, + const std::string& targetUrl ) +{ + + setSourceDb( sourceUrl ); + setTargetDb( targetUrl ); + + if ( ! checkSchemaCompliance( sourceDb(), targetDb() ) ) { + throw Exception( "schemas are incompatible for replication", + "Replication" ); + } + + std::string lastUpdate = getLastUpdate(); + + { + bool readOnly = true; + RelationalTransaction sourceTransaction( sourceDb().transactionMgr(), + readOnly ); + readOnly = false; + RelationalTransaction targetTransaction( targetDb().transactionMgr(), + readOnly ); + + std::string timeOfReplication = serverTime( sourceDb() ); + LOG << "Time of last update: " << lastUpdate << std::endl; + LOG << "Time of replication: " << timeOfReplication << std::endl; + + // This timeout variable exists purely for concurrency testing purposes. + // The intention is to allow the replciation transaction to start + // and leave time for concurrent processes to access the database + // before the actual replication starts in order to investigate how + // the replication behaves under these circumstances. + if ( getenv( "COOLREPLICATION_TIMEOUT" ) ) { + int timeout = atoi( getenv( "COOLREPLICATION_TIMEOUT" ) ); + cool::sleep( timeout ); + } + + replicateNodeTable( lastUpdate ); + replicateNodes( lastUpdate ); + replicateTags(); + + updateLastReplication( targetDb(), timeOfReplication ); + updateLastReplicationSource( targetDb(), sourceUrl ); + + sourceTransaction.commit(); + targetTransaction.commit(); + } + + LOG << "Done." << std::endl; + + return 0; +} + +//--------------------------------------------------------------------------- diff --git a/RelationalCool/utilities/coolReplicateDB/Replication.h b/RelationalCool/utilities/coolReplicateDB/Replication.h new file mode 100644 index 000000000..5084baf62 --- /dev/null +++ b/RelationalCool/utilities/coolReplicateDB/Replication.h @@ -0,0 +1,190 @@ +// $Id: Replication.h,v 1.16 2008-10-30 16:10:26 avalassi Exp $ + +// Include files +#include "CoolKernel/pointers.h" +#include "RelationalAccess/ICursor.h" +#include "RelationalAccess/IQuery.h" + +// Local include files +#include "../../src/CoralApplication.h" +#include "../../src/RelationalTableRow.h" + +namespace cool { + + class IRecordSpecification; + class RalDatabase; + class RelationalFolder; + + class CursorHandle { + + public: + CursorHandle( std::auto_ptr<coral::IQuery>& query, + boost::shared_ptr<coral::AttributeList>& dataBuffer ) + : m_query( query ) + // AFAIK, execution order is not guaranteed, meaning + // m_query->execute() could be called before m_query is assigned. However, + // using query->execute() won't work either, because assigning query + // to m_query (which is highly likely to happen before in the current + // initialization order) invalidates query. + // The ternary operator is there to ensure we use the right IQuery pointer. + , m_cursor( m_query.get() != NULL ? m_query->execute() + : query->execute() ) + , m_dataBuffer( dataBuffer ) {} + coral::ICursor& cursor() { + return m_cursor; + } + private: + std::auto_ptr<coral::IQuery> m_query; + coral::ICursor& m_cursor; + boost::shared_ptr<coral::AttributeList> m_dataBuffer; + }; + + + class Replication : public CoralApplication { + + public: + + Replication(); + + /// Replicate the source to the target database as specified by the urls. + int replicate( const std::string& sourceUrl, + const std::string& targetUrl ); + + private: + + /// Replicates all new rows in the node table since 'lastUpdate'. + void replicateNodeTable( const std::string& lastUpdate ); + + /// Replicates data in all nodes since 'lastUpdate'. + void replicateNodes( const std::string& lastUpdate ); + + /// Replicates data in all folder sets since 'lastUpdate'. + void replicateFolderSets( const std::string& lastUpdate ); + + /// Replicates data in all folders since 'lastUpdate'. + void replicateFolders( const std::string& lastUpdate ); + + /// Replicates the 'source' to the 'target' folder. + void replicateFolder( const RelationalFolder& sourceFolder, + const RelationalFolder& targetFolder, + const std::string& lastUpdate ); + + /// Replicates the global tag table. + void replicateTags(); + + /// Inserts the given rows into 'tableName' in 'db' in bulk. + /// Returns the number of inserted rows. + unsigned int bulkInsert( const RalDatabase& db, + const std::string& tableName, + boost::shared_ptr<CursorHandle>& cursorHandle ); + + /// Inserts the given rows into 'tableName' in 'db' in bulk. + /// Returns the number of inserted rows. + unsigned int bulkInsert( const RalDatabase& db, + const std::string& tableName, + const std::vector<RelationalTableRow>& rows ); + + /// Updates the given rows of object table 'tableName' in 'db' in bulk. + void bulkUpdateObjectTableRows( const RalDatabase& db, + const std::string& tableName, + boost::shared_ptr<CursorHandle>& cursorHandle ); + + /// Updates the given descriptions of the node table in 'db' in bulk. + void bulkUpdateNodeTableDescriptions( const RalDatabase& db, + const std::vector<RelationalTableRow>& rows ); + + /// Returns the current server time. + std::string serverTime( const RalDatabase& db ); + + /// Updates the main LAST_REPLICATION field of db's main table. + void updateLastReplication( const RalDatabase& db, + const std::string& lastUpdate ); + + /// Updates the main LAST_REPLICATION_SOURCE field of db's main table. + void updateLastReplicationSource( const RalDatabase& db, + const std::string& sourceUrl ); + + /// Sets the source database member variables. This implies opening the + /// the database. + void setSourceDb( const std::string& url ); + + /// Returns the source database handle. + RalDatabase& sourceDb() { return *m_sourceRalDb; } + + /// Sets the target database member variables. This implies opening the + /// the database. + void setTargetDb( const std::string& url ); + + /// Returns the target database handle. + RalDatabase& targetDb() { return *m_targetRalDb; } + + /// Fetched the time of the target's last update for the database. + std::string getLastUpdate(); + + /// Checks if the two schemas are compatible for replication + bool checkSchemaCompliance( const RalDatabase& source, + const RalDatabase& target ); + + /// Fetch node table rows inserted after 'lastUpdate'. + std::vector<RelationalTableRow> + newNodeTableRows( const RalDatabase& db, + const std::string& lastUpdate ); + + /// Fetch node table rows modified after 'lastUpdate'. + std::vector<RelationalTableRow> + modifiedNodeTableRows( const RalDatabase& db, + const std::string& lastUpdate ); + + /// Fetch node table rows with the given 'isLeaf' flag. + std::vector<RelationalTableRow> + fetchNodeTableRows( const RalDatabase& db, bool isLeaf ); + + /// Fetch object table rows inserted after 'lastUpdate'. + boost::shared_ptr<CursorHandle> + newObjectTableRows( const RalDatabase& db, + const RelationalFolder& folder, + const std::string& lastUpdate ); + + /// Fetch object table rows modified after 'lastUpdate'. + boost::shared_ptr<CursorHandle> + modifiedObjectTableRows( const RalDatabase& db, + const RelationalFolder& folder, + const std::string& lastUpdate ); + + /// Fetch all local tag table rows + std::vector<RelationalTableRow> + localTagTableRows( const RalDatabase& db, + const RelationalFolder& folder ); + + /// Fetch all iov to tag table rows + std::vector<RelationalTableRow> + object2TagTableRows( const RalDatabase& db, + const RelationalFolder& folder ); + + /// Fetch all global tag table rows + std::vector<RelationalTableRow> + globalTagTableRows( const RalDatabase& db ); + + /// Fetch all tag to tag table rows + std::vector<RelationalTableRow> + tag2TagTableRows( const RalDatabase& db ); + + /// Fetch all channel table rows. + std::vector<RelationalTableRow> + channelTableRows( const RalDatabase& db, + const RelationalFolder& folder ); + + /// Update payload specifications (payload name changes, extensions) + /// on the target. + void updatePayloadSpecifications(); + + IDatabasePtr m_sourceDb; + IDatabasePtr m_targetDb; + RalDatabase* m_sourceRalDb; + RalDatabase* m_targetRalDb; + std::auto_ptr<CursorHandle> m_cursor; + + }; + +} // namespace + diff --git a/RelationalCool/utilities/coolReplicateDB/coolReplicateDb.cpp b/RelationalCool/utilities/coolReplicateDB/coolReplicateDb.cpp new file mode 100644 index 000000000..969f11515 --- /dev/null +++ b/RelationalCool/utilities/coolReplicateDB/coolReplicateDb.cpp @@ -0,0 +1,73 @@ +// $Id: coolReplicateDb.cpp,v 1.5 2007-06-18 09:28:58 sas Exp $ + +#include <iostream> +#include "Replication.h" +#include "CoolKernel/Exception.h" + +int main( int argc, char** argv ) { + + std::string sourceConnectString; + std::string targetConnectString; + + if ( argc == 3 ) { + sourceConnectString = argv[1]; + targetConnectString = argv[2]; + } else { + std::cout << "Usage: " << argv[0] << " <source> <target>" << std::endl; + return -1; + } + + try { + + cool::Replication replicator; + return replicator.replicate( sourceConnectString, targetConnectString ); + + } catch ( std::exception& e ) { + std::cout << "Exception: " << e.what() << std::endl; + return -2; + } catch ( ... ) { + std::cout << "failure" << std::endl; + return -2; + } + +} + +/*! \page replicatedb Dynamic Replication Tool + +The COOL Dynamic Replication Tool 'coolReplicateDB' allows replication of +COOL databases. It differs from the PyCoolCopy tool in the ability to +continuously update a replication target with the changes since the last +replication instead of requiring a completely new copy of all data. + +Calling the tool without parameters will give the following brief help: + +\code +%> coolReplicateDB +Usage: coolReplicateDB <source> <target> +\endcode + +The expected parameters are a source and a target URL provided with the normal +COOL database URL syntax. Replication between different technologies is +possible. + +\section replication_limitations Limitations + +There are two limitations regarding the replication tool: + +- The replica is a read-only database. It would be impossible for the tool +to merge replication changes with direct changes to the replica. Therefore, +the replica is flagged as read-only and cannot be used for writing by any +software based on the public COOL API. In order to make replication more +manageable and performant, some of the COOL 'infrastructure' information +(like the seqence tables) is not replicated, making updates through the public +API impossible. + +- Only the Oracle backend supports replication while clients are actively +writing on the source database. SQLite only supports single client access and +therefore prevents concurrent access by default. Tests with MySQL have exposed +problems that lead to the conclusion that the replication tool <em>must not</em> +be run while there are active clients (writers) on the source database. It is +advised to restart the database with restricted access to safely run the +replication on MySQL. + +*/ diff --git a/RelationalCool/utilities/coolStat/coolStat.cpp b/RelationalCool/utilities/coolStat/coolStat.cpp new file mode 100644 index 000000000..66d75d0b9 --- /dev/null +++ b/RelationalCool/utilities/coolStat/coolStat.cpp @@ -0,0 +1,57 @@ +// $Id: coolStat.cpp,v 1.1 2006-03-15 09:53:30 avalassi Exp $ + +// Include files +#include <iostream> +#include <sys/stat.h> +#include <cerrno> +//#include "SealBase/Filename.h" + +// Message output +#define LOG std::cout + +//----------------------------------------------------------------------------- + +int main( int argc, char** argv ) +{ + + try { + + if ( argc != 2 ) { + LOG << "Usage: " << argv[0] << " filename" << std:: endl; + return 1; + } + + std::string file = argv[1]; + struct stat statbuf; + //seal::Filename filename( file ); + //int status = stat( filename, &statbuf ); + int status = stat( file.c_str(), &statbuf ); + + if (status == -1) + { + LOG << "stat() failed with error " << errno << std::endl; + return 1; + } + + LOG << "File: " << file.c_str() << std::endl; + LOG << "Last modification time: " << statbuf.st_mtime << std::endl; + + } + + catch( std::exception& e ) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << std::endl; + return 1; + } + + catch( ... ) + { + LOG << "ERROR! Unknown exception caught" << std::endl; + return 1; + } + + return 0; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/utilities/coolStat/coolStat.py b/RelationalCool/utilities/coolStat/coolStat.py new file mode 100644 index 000000000..073bc36cb --- /dev/null +++ b/RelationalCool/utilities/coolStat/coolStat.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +import os, sys + +def coolStat( file, newTZ="ignore" ) : + + tz='TZ' + + if newTZ == "none" : + if tz in os.environ: + #del os.environ[tz] + print "ERROR! Cannot unset",tz,": please unset it and start again" + sys.exit(1) + elif newTZ != "ignore" : + os.environ[tz] = newTZ + + if tz in os.environ: + print 'TZ =', os.environ[tz] + else : + print 'TZ = [none]' + + cmd = 'coolStat ' + file + status = os.system(cmd) + if status>0 : print 'Status =', status + return status + +####################################################################### + +if __name__ == '__main__': + + if ( len(sys.argv) == 3 ) : + file = sys.argv[1] + newTZ = sys.argv[2] + elif ( len(sys.argv) == 2 ) : + file = sys.argv[1] + newTZ = "ignore" + else : + print 'Usage:', sys.argv[0], '<fileName> [<newTZ> | none]' + sys.exit(1) + + status = coolStat( file, newTZ ) + sys.exit(status>0) diff --git a/RelationalCool/utilities/coolStat/testBug30859.py b/RelationalCool/utilities/coolStat/testBug30859.py new file mode 100644 index 000000000..e8599f015 --- /dev/null +++ b/RelationalCool/utilities/coolStat/testBug30859.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +import os +from coolStat import coolStat +if __name__ == '__main__': + key='OSTYPE' + if key in os.environ and os.environ[key] == "linux" : + file="/afs/cern.ch/sw/lcg/app/releases/SEAL/SEAL_1_9_3/win32_vc71_dbg/lib/modules/lcg_SealServices.reg" + ###file="/afs/cern.ch/sw/lcg/app/releases/COOL/internal/avalassi/COOL_HEAD/win32_vc71_dbg/lib/modules/lcg_RelationalCool.reg" + else : + file="\\\\afs\\all\\cern.ch\\sw\\lcg\\app\\releases\\SEAL\\SEAL_1_9_3\\win32_vc71_dbg\\lib\\modules\\lcg_SealServices.reg" + ###file="\\\\afs\\all\\cern.ch\\sw\\lcg\\app\\releases\\COOL\\internal\\avalassi\\COOL_HEAD\\win32_vc71_dbg\\lib\\modules\\lcg_RelationalCool.reg" + print "File =", file + coolStat(file,"none") + coolStat(file,"CEST") + coolStat(file,"CET") + coolStat(file,"UTC") + + + diff --git a/RelationalCool/utilities/coolValidateSchema/RalSchemaValidation.cpp b/RelationalCool/utilities/coolValidateSchema/RalSchemaValidation.cpp new file mode 100644 index 000000000..0586d1d6e --- /dev/null +++ b/RelationalCool/utilities/coolValidateSchema/RalSchemaValidation.cpp @@ -0,0 +1,512 @@ +// $Id: RalSchemaValidation.cpp,v 1.11 2008-09-11 06:31:05 avalassi Exp $ + +// Include files +#include "CoolKernel/Record.h" +#include "CoolKernel/FolderVersioning.h" +#include "CoralBase/Attribute.h" + +// Local include files +#include "RalSchemaValidation.h" +#include "../../src/HvsPathHandler.h" +#include "../../src/HvsPathHandlerException.h" +#include "../../src/RalDatabase.h" +#include "../../src/RelationalChannelTable.h" +#include "../../src/RelationalDatabaseTable.h" +#include "../../src/RelationalException.h" +#include "../../src/RelationalFolder.h" +#include "../../src/RelationalNodeTable.h" +#include "../../src/RelationalObjectTable.h" +#include "../../src/RelationalQueryDefinition.h" +#include "../../src/RelationalQueryMgr.h" +#include "../../src/RelationalTableRow.h" +#include "../../src/RelationalTagSequence.h" +#include "../../src/RelationalTransaction.h" +#include "../../src/RelationalSequenceTable.h" + +// Namespace +using namespace cool; + +//----------------------------------------------------------------------------- + +RalSchemaValidation::RalSchemaValidation( RalDatabase* db ) + : m_db( db ) + , m_log( new coral::MessageStream + ( "RalSchemaValidation" ) ) + , m_fatal( false ) +{ + log() << coral::Info + << "Instantiate a RalSchemaValidation manager for '" + << m_db->databaseId() << "'" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +RalSchemaValidation::~RalSchemaValidation() +{ + log() << coral::Info + << "Delete the RalSchemaValidation manager for '" + << m_db->databaseId() << "'" << coral::MessageStream::endmsg; + if ( ! m_fatal ) + { + if ( m_errors.size() == 0 && m_warnings.size() == 0 ) + { + std::cout << "All seems ok - no errors and no warnings" << std::endl; + } + else + { + unsigned ierr = 0; + for ( std::vector<std::string>::const_iterator + err = m_errors.begin(); err != m_errors.end(); ++err ) + { + ierr++; + std::cout << "ERROR (" << ierr << "/" << m_errors.size() + << "): " << *err << std::endl; + } + unsigned iwarn = 0; + for ( std::vector<std::string>::const_iterator + warn = m_warnings.begin(); warn != m_warnings.end(); ++warn ) + { + iwarn++; + std::cout << "WARNING (" << iwarn << "/" << m_warnings.size() + << "): " << *warn << std::endl; + } + } + } +} + +//----------------------------------------------------------------------------- + +coral::MessageStream& RalSchemaValidation::log() +{ + *m_log << coral::Verbose; + return *m_log; +} + +//----------------------------------------------------------------------------- + +void RalSchemaValidation::validateDatabase() +{ + // WELCOME + log() << coral::Info + << "Validate database schema... START" << coral::MessageStream::endmsg; + RelationalTransaction transaction( db().transactionMgr(), true ); // r/o + + // Can the schema of this database be validated? + const Record& dbAttr = db().databaseAttributes(); + std::string releaseNumber = + dbAttr[RelationalDatabaseTable::attributeNames::release] + .data<std::string>(); + std::string schemaVersion = + dbAttr[RelationalDatabaseTable::attributeNames::schemaVersion]. + data<std::string>(); + log() << coral::Info + << "Database release number: " << releaseNumber + << coral::MessageStream::endmsg; + log() << coral::Info + << "Database schema version: " << schemaVersion + << coral::MessageStream::endmsg; + + // VALIDATE THE DATABASE SCHEMA + validateDatabase_22x(); + + // GOODBYE + transaction.commit(); + log() << coral::Info + << "Validate database schema... DONE!" << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaValidation::validateDatabase_22x() +{ + log() << coral::Info + << "Validate database schema (22x)..." << coral::MessageStream::endmsg; + + // ------------------------------------------------------------------- + // Check SQL types of columns in all existing tables (220): + // (..) ..to be implemented.. + // ------------------------------------------------------------------- + + //i_checkSqlTypes_220(); + + // ------------------------------------------------------------------- + // Check all nodes (220): + // ( 1) Check the existence of the tag sequence table of each node + // ( 2) Check the existence of the channels table of each folder + // ------------------------------------------------------------------- + + i_checkNodeTables_220(); + + // ------------------------------------------------------------------- + // Check all folders (220): + // ( 3) Check the schema of the channels table of each folder + // ------------------------------------------------------------------- + + i_checkFolders_220(); + + // ------------------------------------------------------------------- + // Check all nodes (222): + // ( 4) Check the name of each node + // ------------------------------------------------------------------- + + i_checkNodeNames_222(); + + // Success + log() << coral::Info + << "Validate database schema (22x)... DONE!" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +/* +void RalSchemaValidation::i_checkSqlTypes_220() +{ + log() << coral::Info + << "Check SQL types (220)... START" << coral::MessageStream::endmsg; + + // Success + log() << coral::Info + << "Check SQL types (220)... DONE" << coral::MessageStream::endmsg; +} +*/ + +//----------------------------------------------------------------------------- + +void RalSchemaValidation::i_checkFolders_220() +{ + log() << coral::Info + << "Check individual nodes (220)..." << coral::MessageStream::endmsg; + + { + // List all folders ordered by nodeId + coral::AttributeList whereData; + whereData.extend + ( "isLeaf", + typeIdToCoralType(RelationalNodeTable::columnTypeIds::nodeIsLeaf) ); + whereData["isLeaf"].setValue + ( true ); // select folders only + std::string whereClause = RelationalNodeTable::columnNames::nodeIsLeaf; + whereClause += "= :isLeaf"; + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeId; + orderClause += " ASC"; + orderBy.push_back( orderClause ); + std::vector<RelationalTableRow> rows = + db().queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db().nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification + ( VersionNumber( "2.0.0" ) ) ), + whereClause, whereData, orderBy, "" ); + // Check all folders one by one + bool evolveNone = true; + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + std::string fullPath = + (*row)[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + VersionNumber nodeSchemaVersion = + (*row)[RelationalNodeTable::columnNames::nodeSchemaVersion] + .data<std::string>(); + VersionNumber version201( "2.0.1" ); + if ( version201 != + std::string( RelationalFolder::folderSchemaVersion() ) ) + { + std::stringstream msg; + msg << "PANIC! Folder schema version for this software release is '" + << RelationalFolder::folderSchemaVersion() + << "' (expected: '" << version201 << "'):" + << " please update the schemaValidation tool" << std::endl; + log() << coral::Fatal << msg.str() << coral::MessageStream::endmsg; + m_fatal = true; + throw RelationalException( msg.str(), "RalSchemaValidation" ); + } + if ( nodeSchemaVersion < + std::string( RelationalFolder::folderSchemaVersion() ) ) + { + evolveNone = false; + std::stringstream msg; + msg << "Folder '" << fullPath << "' needs schema evolution" + << " from schema version '" << nodeSchemaVersion + << "' to '" << RelationalFolder::folderSchemaVersion() << "'"; + log() << coral::Warning << msg.str() << coral::MessageStream::endmsg; + // No need to fail: just warn that this folder must be updated. + // No need to check FKs either: they were not there before 2.0.1. + m_warnings.push_back( msg.str() ); + } + else if ( nodeSchemaVersion == + std::string( RelationalFolder::folderSchemaVersion() ) ) + { + log() << coral::Verbose + << "Folder '" << fullPath << "' is already schema version '" + << RelationalFolder::folderSchemaVersion() + << "' and needs no schema evolution" + << coral::MessageStream::endmsg; + i_checkChannelsTable_220( *row ); + } + else + { + std::stringstream msg; + msg << "PANIC! Folder " << fullPath + << " has schema version " << nodeSchemaVersion + << " that is newer than that supported by this release (" + << RelationalFolder::folderSchemaVersion() << ")"; + log() << coral::Fatal << msg.str() << coral::MessageStream::endmsg; + m_fatal = true; + throw RelationalException( msg.str(), "RalSchemaValidation" ); + } + } + if ( evolveNone ) + log() << coral::Info + << "All folders are already schema version '" + << RelationalFolder::folderSchemaVersion() + << "' and need no schema evolution" + << coral::MessageStream::endmsg; + } + + // Success + log() << coral::Info + << "Check individual nodes (220)... DONE!" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaValidation::i_checkChannelsTable_220 +( const RelationalTableRow& row ) +{ + int folderVersioningMode = + row[RelationalNodeTable::columnNames::folderVersioningMode].data<int>(); + std::string svOrMv = "SV"; + if ( folderVersioningMode == FolderVersioning::MULTI_VERSION ) svOrMv = "MV"; + std::string fullPath = + row[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + std::string channelTableName = + row[RelationalNodeTable::columnNames::folderChannelTableName] + .data<std::string>(); + std::string objectTableName = + row[RelationalNodeTable::columnNames::folderObjectTableName] + .data<std::string>(); + log() << coral::Info + << "Check the " << svOrMv << " channels table " << channelTableName + << " of folder " << fullPath << " (220)..." + << coral::MessageStream::endmsg; + + // List all channels in the IOV table + std::vector<RelationalTableRow> iovTableChannels; + try + { + RelationalQueryDefinition def; + def.addSelectItem + ( "DISTINCT " + RelationalObjectTable::columnNames::channelId() ); + def.addFromItem( objectTableName ); + def.addOrderItem + ( RelationalObjectTable::columnNames::channelId() + " ASC" ); + RecordSpecification spec; + spec.extend( RelationalObjectTable::columnNames::channelId(), + RelationalObjectTable::columnTypeIds::channelId ); + def.setResultSetSpecification( spec ); + iovTableChannels = db().queryMgr().fetchOrderedRows( def ); + } + catch( RelationalException& e ) + { + std::stringstream msg; + msg << "Error checking iov table of folder '" << fullPath + << "'. Caught exception: '" << e.what() << "'. Skipping this table."; + m_errors.push_back( msg.str() ); + return; + } + + // List all channels in the channels table + std::vector<RelationalTableRow> chTableChannels; + try + { + RelationalQueryDefinition def; + def.addSelectItem( RelationalChannelTable::columnNames::channelId() ); + def.addFromItem( channelTableName ); + def.addOrderItem + ( RelationalChannelTable::columnNames::channelId() + " ASC" ); + RecordSpecification spec; + spec.extend( RelationalChannelTable::columnNames::channelId(), + RelationalChannelTable::columnTypeIds::channelId ); + def.setResultSetSpecification( spec ); + chTableChannels = db().queryMgr().fetchOrderedRows( def ); + } + catch( RelationalException& e ) + { + std::stringstream msg; + msg << "Error checking channels table of folder '" << fullPath + << "'. Caught exception: '" << e.what() << "'. Skipping this table."; + m_errors.push_back(msg.str()); + return; + } + + // Check that all IOV table channels are present in the channels table + for ( std::vector<RelationalTableRow>::const_iterator ch = + iovTableChannels.begin(); ch != iovTableChannels.end(); ++ch ) + { + ChannelId chId = + (*ch)[RelationalObjectTable::columnNames::channelId()].data<ChannelId>(); + bool found = false; + //std::cout << "Channel in IOV table: " << chId << std::endl; + for ( std::vector<RelationalTableRow>::const_iterator ch2 = + chTableChannels.begin(); ch2 != chTableChannels.end(); ++ch2 ) + { + ChannelId chId2 = + (*ch2)[RelationalChannelTable::columnNames::channelId()] + .data<ChannelId>(); + //std::cout << "Channel in channels table: " << chId2 << std::endl; + if ( chId2 == chId ) + { + //std::cout << "Channel found in both tables: " << chId << std::endl; + found = true; + break; + } + } + if ( !found ) + { + std::stringstream msg; + msg << "Channel #" << chId << " in the IOV table " << objectTableName + << " does not reference an entry in the channels table " + << channelTableName << " of folder " << fullPath; + m_fatal = true; + throw RelationalException( msg.str(), "RalSchemaValidation" ); + } + } + log() << coral::Info + << "Check the " << svOrMv << " channels table " << channelTableName + << " of folder " << fullPath << " (220)... DONE!" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaValidation::i_checkNodeNames_222() +{ + log() << coral::Info + << "Check node names (222)..." << coral::MessageStream::endmsg; + + { + // List all nodes ordered by nodeId + coral::AttributeList whereData; + std::string whereClause; + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeId; + orderClause += " ASC"; + orderBy.push_back( orderClause ); + std::vector<RelationalTableRow> rows = + db().queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db().nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification + ( VersionNumber( "2.0.0" ) ) ), + whereClause, whereData, orderBy, "" ); + // Check all nodes one by one + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + std::string fullPath = + (*row)[RelationalNodeTable::columnNames::nodeFullPath] + .data<std::string>(); + HvsPathHandler pathHandler; + try + { + if ( fullPath != pathHandler.rootFullPath() ) + pathHandler.splitFullPath( fullPath ); + } + catch ( HvsPathHandlerException& e ) + { + log() << coral::Warning << e.what() << coral::MessageStream::endmsg; + m_warnings.push_back( e.what() ); + } + } + } + + // Success + log() << coral::Info + << "Check node names (222)... DONE!" + << coral::MessageStream::endmsg; +} + +//----------------------------------------------------------------------------- + +void RalSchemaValidation::i_checkNodeTables_220() +{ + + // List all nodes ordered by nodeId + std::vector<RelationalTableRow> rows; + { + coral::AttributeList whereData; + std::string whereClause = ""; + std::vector<std::string> orderBy; + std::string orderClause = RelationalNodeTable::columnNames::nodeId; + orderClause += " ASC"; + orderBy.push_back( orderClause ); + rows = db().queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( db().nodeTableName() ), + RelationalQueryMgr::columnList + ( RelationalNodeTable::tableSpecification + ( VersionNumber( "2.0.0" ) ) ), + whereClause, whereData, orderBy, "" ); + } + + // Check all nodes one by one + for ( std::vector<RelationalTableRow>::const_iterator + row = rows.begin(); row != rows.end(); ++row ) + { + UInt32 nodeId = + (*row)[RelationalNodeTable::columnNames::nodeId] + .data<UInt32>(); + std::string nodeFullPath = + (*row)[RelationalNodeTable::columnNames::nodeFullPath] + .data<cool::String255>(); + Int32 folderVersioningMode = + (*row)[RelationalNodeTable::columnNames::folderVersioningMode] + .data<Int32>(); + std::string tagSequenceName = + RelationalTagSequence::sequenceName + ( db().defaultTablePrefix(), nodeId ); + std::string channelTableName = + RelationalChannelTable::defaultTableName + ( db().defaultTablePrefix(), nodeId ); + try + { + coral::AttributeList whereData; + std::string whereClause = ""; + std::vector<std::string> orderBy; + if ( folderVersioningMode != FolderVersioning::SINGLE_VERSION ) + { + // single version folder don't have a tag sequence table + db().queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( tagSequenceName ), + RelationalQueryMgr::columnList + ( RelationalSequenceTable::tableSpecification() ), + whereClause, whereData, orderBy, "" ); + } + if ( folderVersioningMode != FolderVersioning::NONE ) + { + // check for channels table if the node is not a folder set + db().queryMgr().fetchOrderedRowsFromTables + ( RelationalQueryMgr::tableList( channelTableName ), + RelationalQueryMgr::columnList + ( RelationalChannelTable::tableSpecification() ), + whereClause, whereData, orderBy, ""); + } + } + catch ( RelationalException& e ) + { + std::stringstream msg; + msg << "Corrupt or missing table for "; + if ( folderVersioningMode != FolderVersioning::NONE ) msg << "folder "; + else msg << "folder set "; + msg << "'" << nodeFullPath << "'. Error Message: '"<< e.what() << "'"; + m_errors.push_back( msg.str() ); + } + } +} + +//----------------------------------------------------------------------------- + diff --git a/RelationalCool/utilities/coolValidateSchema/RalSchemaValidation.h b/RelationalCool/utilities/coolValidateSchema/RalSchemaValidation.h new file mode 100644 index 000000000..55975cef7 --- /dev/null +++ b/RelationalCool/utilities/coolValidateSchema/RalSchemaValidation.h @@ -0,0 +1,101 @@ +// $Id: RalSchemaValidation.h,v 1.8 2008-10-29 09:11:31 avalassi Exp $ +#ifndef RELATIONALCOOL_RALSCHEMAVALIDATION_H +#define RELATIONALCOOL_RALSCHEMAVALIDATION_H 1 + +// Include files +#include <memory> +#include "CoolKernel/DatabaseId.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoralBase/MessageStream.h" + +namespace cool +{ + + // Forward declarations + class RalDatabase; + class RelationalObjectTableRow; + class RelationalTableRow; + + /** @class RalSchemaValidation RalSchemaValidation.h + * + * Private utility class to implement COOL relational schema validation. + * + * @author Andrea Valassi + * @date 2007-10-22 + */ + + class RalSchemaValidation + { + + public: + + /// Constructor from a RalDatabase pointer (see RalPrivilegeManager) + RalSchemaValidation( RalDatabase* db ); + + /// Destructor + virtual ~RalSchemaValidation(); + + /// Validate the schema of the full database. + void validateDatabase(); + + protected: + + /// Get a CORAL MessageStream + coral::MessageStream& log(); + + /// Get the RalDatabase reference + const RalDatabase& db() const { return *m_db; } + + /// --- SCHEMA VALIDATION FOR COOL_2_2_0 + + /// Validate the schema of the full database (22x). + void validateDatabase_22x(); + + /// Check SQL types in all tables (220). + //void i_checkSqlTypes_220(); + + /// Check that channels and tag sequence tables exist for all nodes (220). + void i_checkNodeTables_220(); + + /// Check the schemas of all folders (220). + void i_checkFolders_220(); + + /// Check the schema of the channels table of a folder (220). + void i_checkChannelsTable_220( const RelationalTableRow& row ); + + /// Check the names of all nodes (222). + void i_checkNodeNames_222(); + + private: + + /// Standard constructor is private + RalSchemaValidation(); + + /// Copy constructor is private + RalSchemaValidation( const RalSchemaValidation& rhs ); + + /// Assignment operator is private + RalSchemaValidation& operator=( const RalSchemaValidation& rhs ); + + private: + + /// RalDatabase pointer + RalDatabase* m_db; + + /// CORAL MessageStream + std::auto_ptr<coral::MessageStream> m_log; + + /// Fatal errors received during schema validation + bool m_fatal; + + /// Errors received during schema validation + std::vector<std::string> m_errors; + + /// Warnings received during schema validation + std::vector<std::string> m_warnings; + + }; + +} + +#endif // RELATIONALCOOL_RALSCHEMAVALIDATION_H diff --git a/RelationalCool/utilities/coolValidateSchema/coolValidateSchema.cpp b/RelationalCool/utilities/coolValidateSchema/coolValidateSchema.cpp new file mode 100644 index 000000000..34399b251 --- /dev/null +++ b/RelationalCool/utilities/coolValidateSchema/coolValidateSchema.cpp @@ -0,0 +1,95 @@ +// $Id: coolValidateSchema.cpp,v 1.5 2008-04-10 08:32:54 avalassi Exp $ + +// Include files +#include <iostream> +#include "CoolKernel/IDatabase.h" +#include "CoolKernel/IDatabaseSvc.h" +#include "RelationalAccess/IConnectionService.h" +#include "RelationalAccess/IConnectionServiceConfiguration.h" + +// Local include files +#include "RalSchemaValidation.h" +#include "../../src/CoralApplication.h" +#include "../../src/RalDatabase.h" +#include "../../src/VersionInfo.h" + +// Namespace +using namespace cool; + +// Message output +#define LOG std::cout +#define ENDL std::endl + +//----------------------------------------------------------------------------- + +int main( int argc, char** argv ) +{ + + LOG << "Schema validation starting" << ENDL; + + try { + + // Get the command line arguments + std::string dbId; + if ( argc != 2 ) { + LOG << "Usage: " << argv[0] << " dbId" << ENDL; + std::string dbIdOra = + "oracle://SERVER;schema=USER1;dbname=DB;user=USER1"; + LOG << "Example: " << argv[0] << " '" << dbIdOra << "'\n" << ENDL; + return 1; + } + else { + dbId = argv[1]; + } + + // Instantiate a COOL Application + CoralApplication app; + + // If we can access a LFC and the user is not explicitely forbidding it, + // we try to use CORAL LFCReplicaService + if ( ::getenv("COOL_IGNORE_LFC") == NULL && + ::getenv("LFC_HOST") != NULL ) + { + // try to load CORAL LFCReplicaService + coral::IConnectionServiceConfiguration& connSvcConf = + app.connectionSvc().configuration(); + connSvcConf.setAuthenticationService("CORAL/Services/LFCReplicaService"); + connSvcConf.setLookupService("CORAL/Services/LFCReplicaService"); + } + + // Open the database and create a schema validation manager + IDatabaseSvc& dbSvc = app.databaseService(); + IDatabasePtr db = dbSvc.openDatabase( dbId ); // open in readOnly mode + RalDatabase* ralDb = dynamic_cast<RalDatabase*>( db.get() ); + RalSchemaValidation sv( ralDb ); + + // Validate the schema of the whole database + sv.validateDatabase(); + + } + + catch( cool::Exception& e ) + { + LOG << "ERROR! Cool Exception: '" << e.what() << "'" << ENDL; + return 1; + } + + catch( std::exception& e ) + { + LOG << "ERROR! Standard C++ exception: '" << e.what() << "'" << ENDL; + return 1; + } + + catch( ... ) + { + LOG << "ERROR! Unknown exception caught" << ENDL; + return 1; + } + + // Successful program termination + LOG << "Schema validation successfully completed" << ENDL; + return 0; + +} + +//----------------------------------------------------------------------------- diff --git a/RelationalCool/utilities/coolValidateSchema/test_missingTables.py b/RelationalCool/utilities/coolValidateSchema/test_missingTables.py new file mode 100644 index 000000000..579f69c87 --- /dev/null +++ b/RelationalCool/utilities/coolValidateSchema/test_missingTables.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +# +# Martin's test for missing tables in coolValidateSchema (task #7691) +# With Andrea's modifications - drop a table by brute force instead... +# + +from PyCool import cool +import os, sys, re + +# connect string for the schema owner +connectString = 'Oracle-avalassi/COOLTEST' + +app = cool.Application() +dbSvc = app.databaseService() +svcVersion = dbSvc.serviceVersion() + +spec = cool.RecordSpecification() +spec.extend( "I", cool.StorageType.Int32 ) + +def checkValidateOutput(line) : + p = re.compile('.*Corrupt or missing table for folder \'([^\']*)\'.*'); + m=p.match(line) + if ( m ) : + print "Found corrupt folder " , m.group(1) + return m.group(1) + return "" + +if (1): + # recreate the database and create folders + print "Drop the test database" + dbSvc.dropDatabase( connectString ) + print "Create the test database as the owner" + db = dbSvc.createDatabase( connectString ) + db.createFolderSet('/f1',"test folder set"); + db.createFolder( '/f2', spec, "MV folder", \ + cool.FolderVersioning.MULTI_VERSION ) + db.createFolder( '/f3', spec, "SV folder", \ + cool.FolderVersioning.SINGLE_VERSION ) + db.closeDatabase() + + # drop table in /f1 by brute force + err = os.system( "coolExecuteSql.csh %s -e 'DROP TABLE %s;'" % \ + ( connectString, "COOLTEST_F0001_TAGS_SEQ" ) ); + if ( err != 0 ) : + print "Error: could not drop table COOLTEST_F0001_TAGS_SEQ" + sys.exit(err); + + # drop table in /f2 by brute force + err = os.system( "coolExecuteSql.csh %s -e 'DROP TABLE %s;'" % \ + ( connectString, "COOLTEST_F0002_TAGS_SEQ" ) ); + if ( err != 0 ) : + print "Error: could not drop table COOLTEST_F0002_TAGS_SEQ" + sys.exit(err); + + # run coolValidateSchema on test database + print "Validate the schema using:\n",\ + "coolValidateSchema %s" % connectString; + f = os.popen("coolValidateSchema %s" % connectString); + corruptFolders=[]; + for line in f: + ret = checkValidateOutput(line); + if (ret != "") : + corruptFolders.append(ret); + + # check that coolValidateSchema reported the errors + expectedCorruptFolders =['/f1','/f2'] + if (corruptFolders != expectedCorruptFolders) : + print "Error: expected ", expectedCorruptFolders,\ + " but found: ", corruptFolders + sys.exit(255) + print "Test OK" + sys.exit(0); diff --git a/RelationalCool/utilities/coolValidateSchema/test_missingTables_roles.py b/RelationalCool/utilities/coolValidateSchema/test_missingTables_roles.py new file mode 100644 index 000000000..18444357e --- /dev/null +++ b/RelationalCool/utilities/coolValidateSchema/test_missingTables_roles.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +# +# Martin's test for missing tables in coolValidateSchema (task #7691) +# + +from PyCool import cool +import os, sys, re + +# connect string for the schema owner +connectString = 'Oracle-avalassi/COOLTEST' +# connect string for a writer +connectStringWriter = 'Oracle-avalassi(writer)/COOLTEST' + +# user name to whom writer privileges will be granted +# (should be the one used in connectStringWriter) +writerUser = 'lcg_cool_w' + +app = cool.Application() +dbSvc = app.databaseService() +svcVersion = dbSvc.serviceVersion() +outLvl = app.outputLevel() + +spec = cool.RecordSpecification() +spec.extend( "I", cool.StorageType.Int32 ) + +def checkValidateOutput(line) : + p = re.compile('.*Corrupt or missing table for folder \'([^\']*)\'.*'); + m=p.match(line) + if ( m ) : + print "Found corrupt folder " , m.group(1) + return m.group(1) + return "" + +if (1): + # recreate the database + print "Drop the test database" + dbSvc.dropDatabase( connectString ) + print "Create the test database as the owner" + db = dbSvc.createDatabase( connectString ) + db.closeDatabase() + + # grant writer privileges to writerUser + print "Grant WRITER privileges" + err = os.system( "coolPrivileges %s GRANT WRITER %s" % \ + ( connectString, writerUser ) ); + if ( err != 0 ) : + print "Error: could not grant writer privileges to '%s'" % \ + writerUser + sys.exit(err); + + # try to create folders with the writer user + # (this fails and is expected to corrupt the database) + print "Reopen the database as a writer\n" + ok=1; + db = dbSvc.openDatabase( connectStringWriter, False ) + app.setOutputLevel( 1 ) + + # try to create /f1 + print "Try to create /f1" + try: + db.createFolderSet('/f1',"test folder set"); + print "Error: 'createFolderSet()' did not throw... \n"; + ok=0; + except RuntimeError: + print "Failed as expected\n"; + + # try to create /f2 + print "Try to create /f2" + try: + db.createFolder( '/f2', spec, "MV folder", \ + cool.FolderVersioning.MULTI_VERSION ) + print "Error: creating multi version folder",\ + "with 'createFolder()' did not throw... \n"; + ok=0; + #except RuntimeError: + # print "Failed as expected\n"; + except TypeError: + print "Failed as expected\n"; + + # try to create /f3 + print "Try to create /f3" + try: + db.createFolder( '/f3', spec, "SV folder", \ + cool.FolderVersioning.SINGLE_VERSION ) + print "Error: creating single verstion folder",\ + "with 'createFolder()' did not throw... \n"; + ok=0; + #except RuntimeError: + # print "Failed as expected\n"; + except TypeError: + print "Failed as expected\n"; + + # check that all failed + app.setOutputLevel( outLvl ) + if ( ok == 0 ) : + print "Error: Some or all folder creation calls"\ + "did not fail as expected." + print "Error: Could not set up test database." + sys.exit(255); + + # run coolValidateSchema on test database + print "Validate the schema using:\n",\ + "coolValidateSchema %s" % connectString; + f = os.popen("coolValidateSchema %s" % connectString); + corruptFolders=[]; + for line in f: + ret = checkValidateOutput(line); + if (ret != "") : + corruptFolders.append(ret); + + # check that coolValidateSchema reported the errors + expectedCorruptFolders =['/f1','/f2','/f3'] + if (corruptFolders != expectedCorruptFolders) : + print "Error: expected ", expectedCorruptFolders,\ + " but found: ", corruptFolders + sys.exit(255) + print "Passed test." + sys.exit(0); -- GitLab