diff --git a/catalogue/CMakeLists.txt b/catalogue/CMakeLists.txt index 3cde8545579f9834b2d4527943609d1e5b760664..1e3f20791e90d677d07028b7c736c8ded21786a7 100644 --- a/catalogue/CMakeLists.txt +++ b/catalogue/CMakeLists.txt @@ -15,9 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. cmake_minimum_required (VERSION 2.6) -if (OCCI_SUPPORT) - include_directories (${ORACLE-INSTANTCLIENT_INCLUDE_DIRS}) -endif (OCCI_SUPPORT) +include_directories (${ORACLE-INSTANTCLIENT_INCLUDE_DIRS}) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") @@ -37,25 +35,17 @@ set (CATALOGUE_LIB_SRC_FILES SqliteCatalogue.cpp TapeForWriting.cpp) -if (OCCI_SUPPORT) - set (CATALOGUE_LIB_SRC_FILES - ${CATALOGUE_LIB_SRC_FILES} - CatalogueFactory.cpp - OracleCatalogue.cpp) -else (OCCI_SUPPORT) - set (CATALOGUE_LIB_SRC_FILES - ${CATALOGUE_LIB_SRC_FILES} - CatalogueFactory_OCCI_SUPPORT_OFF.cpp) -endif (OCCI_SUPPORT) +set (CATALOGUE_LIB_SRC_FILES + ${CATALOGUE_LIB_SRC_FILES} + CatalogueFactory.cpp + OracleCatalogue.cpp) add_library (ctacatalogue SHARED ${CATALOGUE_LIB_SRC_FILES}) set_property(TARGET ctacatalogue PROPERTY SOVERSION "${CTA_SOVERSION}") set_property(TARGET ctacatalogue PROPERTY VERSION "${CTA_LIBVERSION}") -if (OCCI_SUPPORT) - set_property (TARGET ctacatalogue APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) -endif (OCCI_SUPPORT) +set_property (TARGET ctacatalogue APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) install (TARGETS ctacatalogue DESTINATION usr/${CMAKE_INSTALL_LIBDIR}) @@ -133,9 +123,7 @@ add_executable(cta-catalogue-schema-create target_link_libraries (cta-catalogue-schema-create ctacatalogue) -if (OCCI_SUPPORT) - set_property (TARGET cta-catalogue-schema-create APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) -endif (OCCI_SUPPORT) +set_property (TARGET cta-catalogue-schema-create APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) install (TARGETS cta-catalogue-schema-create DESTINATION /usr/bin) install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/cta-catalogue-schema-create.1cta DESTINATION /usr/share/man/man1) @@ -148,9 +136,7 @@ add_executable(cta-catalogue-schema-drop target_link_libraries (cta-catalogue-schema-drop ctacatalogue) -if (OCCI_SUPPORT) - set_property (TARGET cta-catalogue-schema-drop APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) -endif (OCCI_SUPPORT) +set_property (TARGET cta-catalogue-schema-drop APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) install (TARGETS cta-catalogue-schema-drop DESTINATION /usr/bin) install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/cta-catalogue-schema-drop.1cta DESTINATION /usr/share/man/man1) @@ -163,9 +149,7 @@ add_executable(cta-database-poll target_link_libraries (cta-database-poll ctacatalogue) -if (OCCI_SUPPORT) - set_property (TARGET cta-database-poll APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) -endif (OCCI_SUPPORT) +set_property (TARGET cta-database-poll APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) install (TARGETS cta-database-poll DESTINATION /usr/bin) install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/cta-database-poll.1cta DESTINATION /usr/share/man/man1) @@ -178,9 +162,7 @@ add_executable(cta-catalogue-admin-user-create target_link_libraries (cta-catalogue-admin-user-create ctacatalogue) -if (OCCI_SUPPORT) - set_property (TARGET cta-catalogue-admin-user-create APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) -endif (OCCI_SUPPORT) +set_property (TARGET cta-catalogue-admin-user-create APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) install (TARGETS cta-catalogue-admin-user-create DESTINATION /usr/bin) install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/cta-catalogue-admin-user-create.1cta DESTINATION /usr/share/man/man1) @@ -193,9 +175,7 @@ add_executable(cta-catalogue-admin-host-create target_link_libraries (cta-catalogue-admin-host-create ctacatalogue) -if (OCCI_SUPPORT) - set_property (TARGET cta-catalogue-admin-host-create APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) -endif (OCCI_SUPPORT) +set_property (TARGET cta-catalogue-admin-host-create APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) install (TARGETS cta-catalogue-admin-host-create DESTINATION /usr/bin) install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/cta-catalogue-admin-host-create.1cta DESTINATION /usr/share/man/man1) diff --git a/catalogue/CatalogueFactory_OCCI_SUPPORT_OFF.cpp b/catalogue/CatalogueFactory_OCCI_SUPPORT_OFF.cpp deleted file mode 100644 index 6c0c2895752343e9898f4b960da24ea44730930e..0000000000000000000000000000000000000000 --- a/catalogue/CatalogueFactory_OCCI_SUPPORT_OFF.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * The CERN Tape Archive (CTA) project - * Copyright (C) 2015 CERN - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "catalogue/CatalogueFactory.hpp" -#include "catalogue/InMemoryCatalogue.hpp" -#include "catalogue/SqliteCatalogue.hpp" -#include "common/exception/Exception.hpp" -#include "common/make_unique.hpp" - -namespace cta { -namespace catalogue { - -//------------------------------------------------------------------------------ -// create -//------------------------------------------------------------------------------ -std::unique_ptr<Catalogue> CatalogueFactory::create(const rdbms::Login &login, const uint64_t nbConns) { - try { - switch(login.dbType) { - case rdbms::Login::DBTYPE_IN_MEMORY: - return cta::make_unique<InMemoryCatalogue>(nbConns); - case rdbms::Login::DBTYPE_ORACLE: - throw exception::Exception("OCCI support disabled at compile time"); - case rdbms::Login::DBTYPE_SQLITE: - return cta::make_unique<SqliteCatalogue>(login.database, nbConns); - case rdbms::Login::DBTYPE_NONE: - throw exception::Exception("Cannot create a catalogue without a database type"); - default: - { - exception::Exception ex; - ex.getMessage() << "Unknown database type: value=" << login.dbType; - throw ex; - } - } - } catch(exception::Exception &ex) { - throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); - } -} - -} // namespace catalogue -} // namespace cta diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp index fcf5cfcfbe04f4f381d837c988643338cdeeaa7d..3a01724ce89f560b98d3d9c35e4de1e5d924717f 100644 --- a/catalogue/CatalogueTest.cpp +++ b/catalogue/CatalogueTest.cpp @@ -21,7 +21,7 @@ #include "catalogue/CatalogueTest.hpp" #include "common/exception/Exception.hpp" #include "common/exception/UserError.hpp" -#include "rdbms/ConnFactoryFactory.hpp" +#include "rdbms/wrapper/ConnFactoryFactory.hpp" #include <algorithm> #include <gtest/gtest.h> @@ -53,7 +53,7 @@ void cta_catalogue_CatalogueTest::SetUp() { try { const rdbms::Login &login = GetParam()->create(); - auto connFactory = rdbms::ConnFactoryFactory::create(login); + auto connFactory = rdbms::wrapper::ConnFactoryFactory::create(login); const uint64_t nbConns = 2; const uint64_t nbArchiveFileListingConns = 2; @@ -4528,6 +4528,64 @@ TEST_P(cta_catalogue_CatalogueTest, deleteRequesterGroupMountRule_non_existant) exception::UserError); } +TEST_P(cta_catalogue_CatalogueTest, prepareForNewFile_no_archive_routes) { + using namespace cta; + + ASSERT_TRUE(m_catalogue->getRequesterMountRules().empty()); + + const std::string mountPolicyName = "mount_policy"; + const uint64_t archivePriority = 1; + const uint64_t minArchiveRequestAge = 2; + const uint64_t retrievePriority = 3; + const uint64_t minRetrieveRequestAge = 4; + const uint64_t maxDrivesAllowed = 5; + + m_catalogue->createMountPolicy( + m_admin, + mountPolicyName, + archivePriority, + minArchiveRequestAge, + retrievePriority, + minRetrieveRequestAge, + maxDrivesAllowed, + "Create mount policy"); + + const std::string comment = "Create mount rule for requester"; + const std::string diskInstanceName = "disk_instance_name"; + const std::string requesterName = "requester_name"; + m_catalogue->createRequesterMountRule(m_admin, mountPolicyName, diskInstanceName, requesterName, comment); + + const std::list<common::dataStructures::RequesterMountRule> rules = m_catalogue->getRequesterMountRules(); + ASSERT_EQ(1, rules.size()); + + const common::dataStructures::RequesterMountRule rule = rules.front(); + + ASSERT_EQ(diskInstanceName, rule.diskInstance); + ASSERT_EQ(requesterName, rule.name); + ASSERT_EQ(mountPolicyName, rule.mountPolicy); + ASSERT_EQ(comment, rule.comment); + ASSERT_EQ(m_admin.username, rule.creationLog.username); + ASSERT_EQ(m_admin.host, rule.creationLog.host); + ASSERT_EQ(rule.creationLog, rule.lastModificationLog); + + // Do not create any archive routes + ASSERT_TRUE(m_catalogue->getArchiveRoutes().empty()); + + common::dataStructures::StorageClass storageClass; + storageClass.diskInstance = diskInstanceName; + storageClass.name = "storage_class"; + storageClass.nbCopies = 2; + storageClass.comment = "Create storage class"; + m_catalogue->createStorageClass(m_admin, storageClass); + + common::dataStructures::UserIdentity userIdentity; + userIdentity.name = requesterName; + userIdentity.group = "group"; + + ASSERT_THROW(m_catalogue->prepareForNewFile(storageClass.diskInstance, storageClass.name, userIdentity), + exception::UserError); +} + TEST_P(cta_catalogue_CatalogueTest, prepareForNewFile_requester_mount_rule) { using namespace cta; diff --git a/catalogue/CatalogueTest.hpp b/catalogue/CatalogueTest.hpp index a421ae0a6972a02a05ac9f56353fbe175cd36087..b190b8712082431a119f3938a0947dcc48ca6506 100644 --- a/catalogue/CatalogueTest.hpp +++ b/catalogue/CatalogueTest.hpp @@ -22,7 +22,7 @@ #include "catalogue/CatalogueFactory.hpp" #include "common/exception/Exception.hpp" #include "common/log/DummyLogger.hpp" -#include "rdbms/Conn.hpp" +#include "rdbms/wrapper/Conn.hpp" #include "rdbms/LoginFactory.hpp" #include <gtest/gtest.h> @@ -48,7 +48,7 @@ protected: * A general purpose database connection outside of the m_catalogue object to * be used to run tests directly on the underlying "raw" catalogue database. */ - std::unique_ptr<cta::rdbms::Conn> m_conn; + std::unique_ptr<cta::rdbms::wrapper::Conn> m_conn; virtual void SetUp(); diff --git a/catalogue/CreateAdminHostCmd.cpp b/catalogue/CreateAdminHostCmd.cpp index aad0551c81ce48b221577d4598ddebd673bfe19d..e7540c591ded5adba15c028d155953e15d81acb0 100644 --- a/catalogue/CreateAdminHostCmd.cpp +++ b/catalogue/CreateAdminHostCmd.cpp @@ -21,7 +21,7 @@ #include "catalogue/CreateAdminHostCmdLineArgs.hpp" #include "common/exception/Exception.hpp" #include "common/log/DummyLogger.hpp" -#include "rdbms/ConnFactoryFactory.hpp" +#include "rdbms/wrapper/ConnFactoryFactory.hpp" namespace cta { namespace catalogue { diff --git a/catalogue/CreateAdminUserCmd.cpp b/catalogue/CreateAdminUserCmd.cpp index 8bc5d1c98920520207b21956a48d9644b5baceb1..a0af942d14f2f0a0d2005f758c7e3f900dcaa505 100644 --- a/catalogue/CreateAdminUserCmd.cpp +++ b/catalogue/CreateAdminUserCmd.cpp @@ -21,7 +21,7 @@ #include "catalogue/CreateAdminUserCmdLineArgs.hpp" #include "common/exception/Exception.hpp" #include "common/log/DummyLogger.hpp" -#include "rdbms/ConnFactoryFactory.hpp" +#include "rdbms/wrapper/ConnFactoryFactory.hpp" namespace cta { namespace catalogue { diff --git a/catalogue/CreateSchemaCmd.cpp b/catalogue/CreateSchemaCmd.cpp index 2e03dab2afdf4a38094eec3d569303c9a7b6adc5..cdd9e046160ba71f79b6b72524568f27e9899361 100644 --- a/catalogue/CreateSchemaCmd.cpp +++ b/catalogue/CreateSchemaCmd.cpp @@ -16,14 +16,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "rdbms/ConnFactoryFactory.hpp" #include "catalogue/CreateSchemaCmd.hpp" #include "catalogue/CreateSchemaCmdLineArgs.hpp" #include "catalogue/OracleCatalogueSchema.hpp" #include "catalogue/SqliteCatalogueSchema.hpp" #include "common/exception/Exception.hpp" - -#include <iostream> +#include "rdbms/ConnPool.hpp" +#include "rdbms/Login.hpp" namespace cta { namespace catalogue { @@ -53,10 +52,11 @@ int CreateSchemaCmd::exceptionThrowingMain(const int argc, char *const *const ar } const auto login = rdbms::Login::parseFile(cmdLineArgs.dbConfigPath); - auto factory = rdbms::ConnFactoryFactory::create(login); - auto conn = factory->create(); + const uint64_t maxNbConns = 1; + rdbms::ConnPool connPool(login, maxNbConns); + auto conn = connPool.getConn();; - const bool ctaCatalogueTableExists = tableExists("CTA_CATALOGUE", *conn); + const bool ctaCatalogueTableExists = tableExists("CTA_CATALOGUE", conn); if(ctaCatalogueTableExists) { std::cerr << "Cannot create the database schema because the CTA_CATALOGUE table already exists" << std::endl; @@ -68,13 +68,13 @@ int CreateSchemaCmd::exceptionThrowingMain(const int argc, char *const *const ar case rdbms::Login::DBTYPE_SQLITE: { SqliteCatalogueSchema schema; - conn->executeNonQueries(schema.sql); + conn.executeNonQueries(schema.sql); } break; case rdbms::Login::DBTYPE_ORACLE: { OracleCatalogueSchema schema; - conn->executeNonQueries(schema.sql); + conn.executeNonQueries(schema.sql); } break; case rdbms::Login::DBTYPE_NONE: diff --git a/catalogue/DropSchemaCmd.cpp b/catalogue/DropSchemaCmd.cpp index 1380c7b816e453f82cdc5c3dcfe1962d96833b7d..c698c8bbe8ed028dc580a2fa4f6ae2bb6ad8f78c 100644 --- a/catalogue/DropSchemaCmd.cpp +++ b/catalogue/DropSchemaCmd.cpp @@ -22,11 +22,9 @@ #include "catalogue/DropSchemaCmdLineArgs.hpp" #include "catalogue/DropSqliteCatalogueSchema.hpp" #include "common/exception/Exception.hpp" -#include "rdbms/ConnFactoryFactory.hpp" -#include "rdbms/OcciConn.hpp" +#include "rdbms/ConnPool.hpp" #include <algorithm> -#include <rdbms/OcciConn.hpp> namespace cta { namespace catalogue { @@ -59,45 +57,20 @@ int DropSchemaCmd::exceptionThrowingMain(const int argc, char *const *const argv } const rdbms::Login dbLogin = rdbms::Login::parseFile(cmdLineArgs.dbConfigPath); - auto factory = rdbms::ConnFactoryFactory::create(dbLogin); - auto conn = factory->create(); + const uint64_t maxNbConns = 1; + rdbms::ConnPool connPool(dbLogin, maxNbConns); + auto conn = connPool.getConn(); // Abort if the schema is already dropped - switch(dbLogin.dbType) { - case rdbms::Login::DBTYPE_IN_MEMORY: - case rdbms::Login::DBTYPE_SQLITE: - if (conn->getTableNames().empty()) { - m_out << "Database contains no tables." << std::endl << - "Assuming the schema has already been dropped." << std::endl; - return 0; - } - break; - case rdbms::Login::DBTYPE_ORACLE: - { - rdbms::OcciConn *const occiConn = dynamic_cast<rdbms::OcciConn *>(conn.get()); - if(nullptr == occiConn) { - throw exception::Exception("Failed to down cast rdbms::conn to rdbms::OcciConn"); - } - if(occiConn->getTableNames().empty() && occiConn->getSequenceNames().empty()) { - m_out << "Database contains no tables and no sequences." << std::endl << - "Assuming the schema has already been dropped." << std::endl; - return 0; - } - } - break; - case rdbms::Login::DBTYPE_NONE: - throw exception::Exception("Cannot delete the schema of catalogue database without a database type"); - default: - { - exception::Exception ex; - ex.getMessage() << "Unknown database type: value=" << dbLogin.dbType; - throw ex; - } + if(conn.getTableNames().empty() && conn.getSequenceNames().empty()) { + m_out << "Database contains no tables and no sequences." << std::endl << + "Assuming the schema has already been dropped." << std::endl; + return 0; } if(userConfirmsDropOfSchema(dbLogin)) { m_out << "DROPPING the schema of the CTA calalogue database" << std::endl; - dropCatalogueSchema(dbLogin.dbType, *conn); + dropCatalogueSchema(dbLogin.dbType, conn); } else { m_out << "Aborting" << std::endl; } @@ -186,7 +159,7 @@ void DropSchemaCmd::dropDatabaseTables(rdbms::Conn &conn, const std::list<std::s for(auto tableToDrop : tablesToDrop) { const bool tableToDropIsInDb = tablesInDb.end() != std::find(tablesInDb.begin(), tablesInDb.end(), tableToDrop); if(tableToDropIsInDb) { - conn.executeNonQuery(std::string("DROP TABLE ") + tableToDrop, rdbms::Stmt::AutocommitMode::ON); + conn.executeNonQuery(std::string("DROP TABLE ") + tableToDrop, rdbms::AutocommitMode::ON); m_out << "Dropped table " << tableToDrop << std::endl; } } @@ -220,8 +193,7 @@ void DropSchemaCmd::dropOracleCatalogueSchema(rdbms::Conn &conn) { dropDatabaseTables(conn, tablesToDrop); std::list<std::string> sequencesToDrop = {"ARCHIVE_FILE_ID_SEQ"}; - rdbms::OcciConn &occiConn = dynamic_cast<rdbms::OcciConn &>(conn); - dropDatabaseSequences(occiConn, sequencesToDrop); + dropDatabaseSequences(conn, sequencesToDrop); } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); } @@ -230,14 +202,14 @@ void DropSchemaCmd::dropOracleCatalogueSchema(rdbms::Conn &conn) { //------------------------------------------------------------------------------ // dropDatabaseSequences //------------------------------------------------------------------------------ -void DropSchemaCmd::dropDatabaseSequences(rdbms::OcciConn &conn, const std::list<std::string> &sequencesToDrop) { +void DropSchemaCmd::dropDatabaseSequences(rdbms::Conn &conn, const std::list<std::string> &sequencesToDrop) { try { std::list<std::string> sequencesInDb = conn.getSequenceNames(); for(auto sequenceToDrop : sequencesToDrop) { const bool sequenceToDropIsInDb = sequencesInDb.end() != std::find(sequencesInDb.begin(), sequencesInDb.end(), sequenceToDrop); if(sequenceToDropIsInDb) { - conn.executeNonQuery(std::string("DROP SEQUENCE ") + sequenceToDrop, rdbms::Stmt::AutocommitMode::ON); + conn.executeNonQuery(std::string("DROP SEQUENCE ") + sequenceToDrop, rdbms::AutocommitMode::ON); m_out << "Dropped sequence " << sequenceToDrop << std::endl; } } diff --git a/catalogue/DropSchemaCmd.hpp b/catalogue/DropSchemaCmd.hpp index 760aa3b3dc0fca5383eee65c9b70bef056e22d15..a2e1c669279ce6729f5d4d676659cca792eefb72 100644 --- a/catalogue/DropSchemaCmd.hpp +++ b/catalogue/DropSchemaCmd.hpp @@ -22,7 +22,6 @@ #include "catalogue/CmdLineTool.hpp" #include "rdbms/Conn.hpp" #include "rdbms/Login.hpp" -#include "rdbms/OcciConn.hpp" namespace cta { namespace catalogue { @@ -109,9 +108,10 @@ private: /** * Drops the database sequences with the specified names. * + * @param conn The database connection. * @param seqeuncesToDrop The names of the database sequences to be dropped. */ - void dropDatabaseSequences(rdbms::OcciConn &conn, const std::list<std::string> &sequencesToDrop); + void dropDatabaseSequences(rdbms::Conn &conn, const std::list<std::string> &sequencesToDrop); }; // class DropSchemaCmd diff --git a/catalogue/InMemoryCatalogue.cpp b/catalogue/InMemoryCatalogue.cpp index a88201c16d9fd366da2037168523da84126072df..69eeb195103a9fff734d880278768a63f91c97d6 100644 --- a/catalogue/InMemoryCatalogue.cpp +++ b/catalogue/InMemoryCatalogue.cpp @@ -17,9 +17,6 @@ */ #include "catalogue/InMemoryCatalogue.hpp" -#include "catalogue/SqliteCatalogueSchema.hpp" -#include "rdbms/SqliteConn.hpp" -#include "rdbms/SqliteConnFactory.hpp" namespace cta { namespace catalogue { diff --git a/catalogue/OracleCatalogue.cpp b/catalogue/OracleCatalogue.cpp index 8f6627776b27caca7f1ca8b5e1dc12379bd0d273..308baaea692a8ca488bdffec41bd9d66736218c1 100644 --- a/catalogue/OracleCatalogue.cpp +++ b/catalogue/OracleCatalogue.cpp @@ -25,14 +25,90 @@ #include "common/Timer.hpp" #include "common/utils/utils.hpp" #include "rdbms/AutoRollback.hpp" -#include "rdbms/ConnFactoryFactory.hpp" -#include "rdbms/OcciStmt.hpp" +#include "rdbms/wrapper/OcciColumn.hpp" +#include "rdbms/wrapper/OcciStmt.hpp" #include <string.h> namespace cta { namespace catalogue { +namespace { + /** + * Structure used to assemble a batch of rows to insert into the TAPE_FILE + * table. + */ + struct TapeFileBatch { + size_t nbRows; + rdbms::wrapper::OcciColumn vid; + rdbms::wrapper::OcciColumn fSeq; + rdbms::wrapper::OcciColumn blockId; + rdbms::wrapper::OcciColumn compressedSize; + rdbms::wrapper::OcciColumn copyNb; + rdbms::wrapper::OcciColumn creationTime; + rdbms::wrapper::OcciColumn archiveFileId; + + /** + * Constructor. + * + * @param nbRowsValue The Number of rows to be inserted. + */ + TapeFileBatch(const size_t nbRowsValue): + nbRows(nbRowsValue), + vid("VID", nbRows), + fSeq("FSEQ", nbRows), + blockId("BLOCK_ID", nbRows), + compressedSize("COMPRESSED_SIZE_IN_BYTES", nbRows), + copyNb("COPY_NB", nbRows), + creationTime("CREATION_TIME", nbRows), + archiveFileId("ARCHIVE_FILE_ID", nbRows) { + } + }; // struct TapeFileBatch + + /** + * Structure used to assemble a batch of rows to insert into the ARCHIVE_FILE + * table. + */ + struct ArchiveFileBatch { + size_t nbRows; + rdbms::wrapper::OcciColumn archiveFileId; + rdbms::wrapper::OcciColumn diskInstance; + rdbms::wrapper::OcciColumn diskFileId; + rdbms::wrapper::OcciColumn diskFilePath; + rdbms::wrapper::OcciColumn diskFileUser; + rdbms::wrapper::OcciColumn diskFileGroup; + rdbms::wrapper::OcciColumn diskFileRecoveryBlob; + rdbms::wrapper::OcciColumn size; + rdbms::wrapper::OcciColumn checksumType; + rdbms::wrapper::OcciColumn checksumValue; + rdbms::wrapper::OcciColumn storageClassName; + rdbms::wrapper::OcciColumn creationTime; + rdbms::wrapper::OcciColumn reconciliationTime; + + /** + * Constructor. + * + * @param nbRowsValue The Number of rows to be inserted. + */ + ArchiveFileBatch(const size_t nbRowsValue): + nbRows(nbRowsValue), + archiveFileId("ARCHIVE_FILE_ID", nbRows), + diskInstance("DISK_INSTANCE_NAME", nbRows), + diskFileId("DISK_FILE_ID", nbRows), + diskFilePath("DISK_FILE_PATH", nbRows), + diskFileUser("DISK_FILE_USER", nbRows), + diskFileGroup("DISK_FILE_GROUP", nbRows), + diskFileRecoveryBlob("DISK_FILE_RECOVERY_BLOB", nbRows), + size("SIZE_IN_BYTES", nbRows), + checksumType("CHECKSUM_TYPE", nbRows), + checksumValue("CHECKSUM_VALUE", nbRows), + storageClassName("STORAGE_CLASS_NAME", nbRows), + creationTime("CREATION_TIME", nbRows), + reconciliationTime("RECONCILIATION_TIME", nbRows) { + } + }; // struct ArchiveFileBatch +} // anonymous namespace + //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ @@ -45,7 +121,7 @@ OracleCatalogue::OracleCatalogue( const uint64_t nbArchiveFileListingConns): RdbmsCatalogue( log, - rdbms::ConnFactoryFactory::create(rdbms::Login(rdbms::Login::DBTYPE_ORACLE, username, password, database)), + rdbms::Login(rdbms::Login::DBTYPE_ORACLE, username, password, database), nbConns, nbArchiveFileListingConns) { @@ -94,11 +170,11 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con utils::Timer t; auto conn = m_connPool.getConn(); const auto getConnTime = t.secs(utils::Timer::resetCounter); - auto selectStmt = conn.createStmt(selectSql, rdbms::Stmt::AutocommitMode::OFF); + auto selectStmt = conn.createStmt(selectSql, rdbms::AutocommitMode::OFF); const auto createStmtTime = t.secs(); - selectStmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId); + selectStmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); t.reset(); - rdbms::Rset selectRset = selectStmt->executeQuery(); + rdbms::Rset selectRset = selectStmt.executeQuery(); const auto selectFromArchiveFileTime = t.secs(); std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile; while(selectRset.next()) { @@ -189,17 +265,17 @@ void OracleCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con t.reset(); { const char *const sql = "DELETE FROM TAPE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); + stmt.executeNonQuery(); } const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter); { const char *const sql = "DELETE FROM ARCHIVE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); + stmt.executeNonQuery(); } const auto deleteFromArchiveFileTime = t.secs(utils::Timer::resetCounter); @@ -284,12 +360,12 @@ void OracleCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInsta utils::Timer t; auto conn = m_connPool.getConn(); const auto getConnTime = t.secs(utils::Timer::resetCounter); - auto selectStmt = conn.createStmt(selectSql, rdbms::Stmt::AutocommitMode::OFF); + auto selectStmt = conn.createStmt(selectSql, rdbms::AutocommitMode::OFF); const auto createStmtTime = t.secs(); - selectStmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - selectStmt->bindString(":DISK_FILE_ID", diskFileId); + selectStmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + selectStmt.bindString(":DISK_FILE_ID", diskFileId); t.reset(); - rdbms::Rset selectRset = selectStmt->executeQuery(); + rdbms::Rset selectRset = selectStmt.executeQuery(); const auto selectFromArchiveFileTime = t.secs(); std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile; while(selectRset.next()) { @@ -339,17 +415,17 @@ void OracleCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInsta t.reset(); { const char *const sql = "DELETE FROM TAPE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFile->archiveFileID); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFile->archiveFileID); + stmt.executeNonQuery(); } const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter); { const char *const sql = "DELETE FROM ARCHIVE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFile->archiveFileID); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFile->archiveFileID); + stmt.executeNonQuery(); } const auto deleteFromArchiveFileTime = t.secs(utils::Timer::resetCounter); @@ -399,15 +475,15 @@ void OracleCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInsta //------------------------------------------------------------------------------ // getNextArchiveFileId //------------------------------------------------------------------------------ -uint64_t OracleCatalogue::getNextArchiveFileId(rdbms::PooledConn &conn) { +uint64_t OracleCatalogue::getNextArchiveFileId(rdbms::Conn &conn) { try { const char *const sql = "SELECT " "ARCHIVE_FILE_ID_SEQ.NEXTVAL AS ARCHIVE_FILE_ID " "FROM " "DUAL"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); if (!rset.next()) { throw exception::Exception(std::string("Result set is unexpectedly empty")); } @@ -421,7 +497,7 @@ uint64_t OracleCatalogue::getNextArchiveFileId(rdbms::PooledConn &conn) { //------------------------------------------------------------------------------ // selectTapeForUpdate //------------------------------------------------------------------------------ -common::dataStructures::Tape OracleCatalogue::selectTapeForUpdate(rdbms::PooledConn &conn, const std::string &vid) { +common::dataStructures::Tape OracleCatalogue::selectTapeForUpdate(rdbms::Conn &conn, const std::string &vid) { try { const char *const sql = "SELECT " @@ -459,9 +535,9 @@ common::dataStructures::Tape OracleCatalogue::selectTapeForUpdate(rdbms::PooledC "WHERE " "VID = :VID " "FOR UPDATE"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":VID", vid); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":VID", vid); + auto rset = stmt.executeQuery(); if (!rset.next()) { throw exception::Exception(std::string("The tape with VID " + vid + " does not exist")); } @@ -568,10 +644,10 @@ void OracleCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events auto lastEventItor = events.cend(); lastEventItor--; const TapeFileWritten &lastEvent = *lastEventItor; - updateTape(conn, rdbms::Stmt::AutocommitMode::OFF, lastEvent.vid, lastEvent.fSeq, totalCompressedBytesWritten, + updateTape(conn, rdbms::AutocommitMode::OFF, lastEvent.vid, lastEvent.fSeq, totalCompressedBytesWritten, lastEvent.tapeDrive); - idempotentBatchInsertArchiveFiles(conn, rdbms::Stmt::AutocommitMode::OFF, events); + idempotentBatchInsertArchiveFiles(conn, rdbms::AutocommitMode::OFF, events); // Store the value of each field i = 0; @@ -603,8 +679,8 @@ void OracleCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events ":COPY_NB," ":CREATION_TIME," ":ARCHIVE_FILE_ID)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - rdbms::OcciStmt &occiStmt = dynamic_cast<rdbms::OcciStmt &>(*stmt); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + rdbms::wrapper::OcciStmt &occiStmt = dynamic_cast<rdbms::wrapper::OcciStmt &>(stmt.getStmt()); occiStmt.setColumn(tapeFileBatch.vid); occiStmt.setColumn(tapeFileBatch.fSeq); occiStmt.setColumn(tapeFileBatch.blockId); @@ -626,8 +702,8 @@ void OracleCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events //------------------------------------------------------------------------------ // idempotentBatchInsertArchiveFiles //------------------------------------------------------------------------------ -void OracleCatalogue::idempotentBatchInsertArchiveFiles(rdbms::PooledConn &conn, - const rdbms::Stmt::AutocommitMode autocommitMode, const std::set<TapeFileWritten> &events) { +void OracleCatalogue::idempotentBatchInsertArchiveFiles(rdbms::Conn &conn, + const rdbms::AutocommitMode autocommitMode, const std::set<TapeFileWritten> &events) { try { ArchiveFileBatch archiveFileBatch(events.size()); const time_t now = time(nullptr); @@ -701,7 +777,7 @@ void OracleCatalogue::idempotentBatchInsertArchiveFiles(rdbms::PooledConn &conn, ":CREATION_TIME," ":RECONCILIATION_TIME)"; auto stmt = conn.createStmt(sql, autocommitMode); - rdbms::OcciStmt &occiStmt = dynamic_cast<rdbms::OcciStmt &>(*stmt); + rdbms::wrapper::OcciStmt &occiStmt = dynamic_cast<rdbms::wrapper::OcciStmt &>(stmt.getStmt()); occiStmt->setBatchErrorMode(true); occiStmt.setColumn(archiveFileBatch.archiveFileId); diff --git a/catalogue/OracleCatalogue.hpp b/catalogue/OracleCatalogue.hpp index b9587cd54b8b5dc436047483f8065ee373985190..99a404752a8cb398e46e9fb007840298676dc9ce 100644 --- a/catalogue/OracleCatalogue.hpp +++ b/catalogue/OracleCatalogue.hpp @@ -19,8 +19,7 @@ #pragma once #include "catalogue/RdbmsCatalogue.hpp" -#include "rdbms/OcciColumn.hpp" -#include "rdbms/PooledConn.hpp" +#include "rdbms/Conn.hpp" #include <occi.h> #include <string.h> @@ -117,7 +116,7 @@ public: * @return A unique archive ID that can be used by a new archive file within * the catalogue. */ - uint64_t getNextArchiveFileId(rdbms::PooledConn &conn) override; + uint64_t getNextArchiveFileId(rdbms::Conn &conn) override; /** * Notifies the catalogue that the specified files have been written to tape. @@ -134,81 +133,7 @@ private: * @param conn The database connection. * @param vid The volume identifier of the tape. */ - common::dataStructures::Tape selectTapeForUpdate(rdbms::PooledConn &conn, const std::string &vid); - - /** - * Structure used to assemble a batch of rows to insert into the TAPE_FILE - * table. - */ - struct TapeFileBatch { - size_t nbRows; - rdbms::OcciColumn vid; - rdbms::OcciColumn fSeq; - rdbms::OcciColumn blockId; - rdbms::OcciColumn compressedSize; - rdbms::OcciColumn copyNb; - rdbms::OcciColumn creationTime; - rdbms::OcciColumn archiveFileId; - - /** - * Constructor. - * - * @param nbRowsValue The Number of rows to be inserted. - */ - TapeFileBatch(const size_t nbRowsValue): - nbRows(nbRowsValue), - vid("VID", nbRows), - fSeq("FSEQ", nbRows), - blockId("BLOCK_ID", nbRows), - compressedSize("COMPRESSED_SIZE_IN_BYTES", nbRows), - copyNb("COPY_NB", nbRows), - creationTime("CREATION_TIME", nbRows), - archiveFileId("ARCHIVE_FILE_ID", nbRows) { - } - }; // struct TapeFileBatch - - /** - * Structure used to assemble a batch of rows to insert into the ARCHIVE_FILE - * table. - */ - struct ArchiveFileBatch { - size_t nbRows; - rdbms::OcciColumn archiveFileId; - rdbms::OcciColumn diskInstance; - rdbms::OcciColumn diskFileId; - rdbms::OcciColumn diskFilePath; - rdbms::OcciColumn diskFileUser; - rdbms::OcciColumn diskFileGroup; - rdbms::OcciColumn diskFileRecoveryBlob; - rdbms::OcciColumn size; - rdbms::OcciColumn checksumType; - rdbms::OcciColumn checksumValue; - rdbms::OcciColumn storageClassName; - rdbms::OcciColumn creationTime; - rdbms::OcciColumn reconciliationTime; - - /** - * Constructor. - * - * @param nbRowsValue The Number of rows to be inserted. - */ - ArchiveFileBatch(const size_t nbRowsValue): - nbRows(nbRowsValue), - archiveFileId("ARCHIVE_FILE_ID", nbRows), - diskInstance("DISK_INSTANCE_NAME", nbRows), - diskFileId("DISK_FILE_ID", nbRows), - diskFilePath("DISK_FILE_PATH", nbRows), - diskFileUser("DISK_FILE_USER", nbRows), - diskFileGroup("DISK_FILE_GROUP", nbRows), - diskFileRecoveryBlob("DISK_FILE_RECOVERY_BLOB", nbRows), - size("SIZE_IN_BYTES", nbRows), - checksumType("CHECKSUM_TYPE", nbRows), - checksumValue("CHECKSUM_VALUE", nbRows), - storageClassName("STORAGE_CLASS_NAME", nbRows), - creationTime("CREATION_TIME", nbRows), - reconciliationTime("RECONCILIATION_TIME", nbRows) { - } - }; // struct ArchiveFileBatch + common::dataStructures::Tape selectTapeForUpdate(rdbms::Conn &conn, const std::string &vid); /** * Batch inserts rows into the ARCHIVE_FILE table that correspond to the @@ -227,7 +152,7 @@ private: * @param autocommitMode The autocommit mode of the SQL insert statement. * @param events The tape file written events. */ - void idempotentBatchInsertArchiveFiles(rdbms::PooledConn &conn, const rdbms::Stmt::AutocommitMode autocommitMode, + void idempotentBatchInsertArchiveFiles(rdbms::Conn &conn, const rdbms::AutocommitMode autocommitMode, const std::set<TapeFileWritten> &events); }; // class OracleCatalogue diff --git a/catalogue/PollDatabaseCmd.cpp b/catalogue/PollDatabaseCmd.cpp index bd680a770cfe6dbed7ee3950c004c5ec183ce573..5f796a6f404fdfd54adeb542b09058116c4f34f8 100644 --- a/catalogue/PollDatabaseCmd.cpp +++ b/catalogue/PollDatabaseCmd.cpp @@ -19,7 +19,6 @@ #include "catalogue/CatalogueFactory.hpp" #include "catalogue/PollDatabaseCmd.hpp" #include "catalogue/PollDatabaseCmdLineArgs.hpp" -#include "rdbms/ConnFactoryFactory.hpp" #include "rdbms/ConnPool.hpp" #include <unistd.h> @@ -52,9 +51,8 @@ int PollDatabaseCmd::exceptionThrowingMain(const int argc, char *const *const ar } const auto dbLogin = rdbms::Login::parseFile(cmdLineArgs.dbConfigPath); - auto factory = rdbms::ConnFactoryFactory::create(dbLogin); const uint64_t nbConns = 2; - rdbms::ConnPool connPool(*factory, nbConns); + rdbms::ConnPool connPool(dbLogin, nbConns); uint32_t elapsedSeconds = 0; for(uint32_t i = 0; i < cmdLineArgs.numberOfSecondsToKeepPolling; i++) { diff --git a/catalogue/RdbmsArchiveFileItorImpl.cpp b/catalogue/RdbmsArchiveFileItorImpl.cpp index 61cec15416ffe9cb4c46b2c16d903da6b48bcb8f..03516f2c0ba97fed59fb0a2b4a8d45ea6e0462e9 100644 --- a/catalogue/RdbmsArchiveFileItorImpl.cpp +++ b/catalogue/RdbmsArchiveFileItorImpl.cpp @@ -198,38 +198,38 @@ RdbmsArchiveFileItorImpl::RdbmsArchiveFileItorImpl( } auto conn = connPool.getConn(); - m_stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); + m_stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); if(searchCriteria.archiveFileId) { - m_stmt->bindUint64(":ARCHIVE_FILE_ID", searchCriteria.archiveFileId.value()); + m_stmt.bindUint64(":ARCHIVE_FILE_ID", searchCriteria.archiveFileId.value()); } if(searchCriteria.diskInstance) { - m_stmt->bindString(":DISK_INSTANCE_NAME", searchCriteria.diskInstance.value()); + m_stmt.bindString(":DISK_INSTANCE_NAME", searchCriteria.diskInstance.value()); } if(searchCriteria.diskFileId) { - m_stmt->bindString(":DISK_FILE_ID", searchCriteria.diskFileId.value()); + m_stmt.bindString(":DISK_FILE_ID", searchCriteria.diskFileId.value()); } if(searchCriteria.diskFilePath) { - m_stmt->bindString(":DISK_FILE_PATH", searchCriteria.diskFilePath.value()); + m_stmt.bindString(":DISK_FILE_PATH", searchCriteria.diskFilePath.value()); } if(searchCriteria.diskFileUser) { - m_stmt->bindString(":DISK_FILE_USER", searchCriteria.diskFileUser.value()); + m_stmt.bindString(":DISK_FILE_USER", searchCriteria.diskFileUser.value()); } if(searchCriteria.diskFileGroup) { - m_stmt->bindString(":DISK_FILE_GROUP", searchCriteria.diskFileGroup.value()); + m_stmt.bindString(":DISK_FILE_GROUP", searchCriteria.diskFileGroup.value()); } if(searchCriteria.storageClass) { - m_stmt->bindString(":STORAGE_CLASS_NAME", searchCriteria.storageClass.value()); + m_stmt.bindString(":STORAGE_CLASS_NAME", searchCriteria.storageClass.value()); } if(searchCriteria.vid) { - m_stmt->bindString(":VID", searchCriteria.vid.value()); + m_stmt.bindString(":VID", searchCriteria.vid.value()); } if(searchCriteria.tapeFileCopyNb) { - m_stmt->bindUint64(":TAPE_FILE_COPY_NB", searchCriteria.tapeFileCopyNb.value()); + m_stmt.bindUint64(":TAPE_FILE_COPY_NB", searchCriteria.tapeFileCopyNb.value()); } if(searchCriteria.tapePool) { - m_stmt->bindString(":TAPE_POOL_NAME", searchCriteria.tapePool.value()); + m_stmt.bindString(":TAPE_POOL_NAME", searchCriteria.tapePool.value()); } - m_rset = m_stmt->executeQuery(); + m_rset = m_stmt.executeQuery(); m_rsetIsEmpty = !m_rset.next(); } catch(exception::Exception &ex) { diff --git a/catalogue/RdbmsArchiveFileItorImpl.hpp b/catalogue/RdbmsArchiveFileItorImpl.hpp index 059dbc038fc26fd80ed5d146e6ed99f4d53e85e4..decca68918438ec6c40ad8ca3184bc50e7f3af9f 100644 --- a/catalogue/RdbmsArchiveFileItorImpl.hpp +++ b/catalogue/RdbmsArchiveFileItorImpl.hpp @@ -23,8 +23,8 @@ #include "catalogue/TapeFileSearchCriteria.hpp" #include "common/log/Logger.hpp" #include "rdbms/ConnPool.hpp" -#include "rdbms/Rset.hpp" #include "rdbms/Stmt.hpp" +#include "rdbms/Rset.hpp" namespace cta { namespace catalogue { @@ -97,7 +97,7 @@ private: /** * The database statement. */ - std::unique_ptr<rdbms::Stmt> m_stmt; + rdbms::Stmt m_stmt; /** * The result set of archive files that is to be iterated over. diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp index 23e34822911ee2198a626dc66b8c18ff9c1c56eb..39415e5cc38048cadfcd2f4df3b861df856d6901 100644 --- a/catalogue/RdbmsCatalogue.cpp +++ b/catalogue/RdbmsCatalogue.cpp @@ -41,13 +41,12 @@ namespace catalogue { //------------------------------------------------------------------------------ RdbmsCatalogue::RdbmsCatalogue( log::Logger &log, - std::unique_ptr<rdbms::ConnFactory> connFactory, + const rdbms::Login &login, const uint64_t nbConns, const uint64_t nbArchiveFileListingConns): Catalogue(log), - m_connFactory(std::move(connFactory)), - m_connPool(*m_connFactory, nbConns), - m_archiveFileListingConnPool(*m_connFactory, nbArchiveFileListingConns) { + m_connPool(login, nbConns), + m_archiveFileListingConnPool(login, nbArchiveFileListingConns) { } //------------------------------------------------------------------------------ @@ -95,21 +94,21 @@ void RdbmsCatalogue::createAdminUser( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":ADMIN_USER_NAME", username); + stmt.bindString(":ADMIN_USER_NAME", username); - stmt->bindString(":USER_COMMENT", comment); + stmt.bindString(":USER_COMMENT", comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch (exception::Exception &ex) { @@ -120,7 +119,7 @@ void RdbmsCatalogue::createAdminUser( //------------------------------------------------------------------------------ // adminUserExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::adminUserExists(rdbms::PooledConn &conn, const std::string adminUsername) const { +bool RdbmsCatalogue::adminUserExists(rdbms::Conn &conn, const std::string adminUsername) const { try { const char *const sql = "SELECT " @@ -129,9 +128,9 @@ bool RdbmsCatalogue::adminUserExists(rdbms::PooledConn &conn, const std::string "ADMIN_USER " "WHERE " "ADMIN_USER_NAME = :ADMIN_USER_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":ADMIN_USER_NAME", adminUsername); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":ADMIN_USER_NAME", adminUsername); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -145,11 +144,11 @@ void RdbmsCatalogue::deleteAdminUser(const std::string &username) { try { const char *const sql = "DELETE FROM ADMIN_USER WHERE ADMIN_USER_NAME = :ADMIN_USER_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":ADMIN_USER_NAME", username); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":ADMIN_USER_NAME", username); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot delete admin-user ") + username + " because they do not exist"); } } catch(exception::UserError &) { @@ -183,8 +182,8 @@ std::list<common::dataStructures::AdminUser> RdbmsCatalogue::getAdminUsers() con "ORDER BY " "ADMIN_USER_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); while (rset.next()) { common::dataStructures::AdminUser admin; @@ -222,15 +221,15 @@ void RdbmsCatalogue::modifyAdminUserComment(const common::dataStructures::Securi "WHERE " "ADMIN_USER_NAME = :ADMIN_USER_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":ADMIN_USER_NAME", username); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":ADMIN_USER_NAME", username); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify admin user ") + username + " because they do not exist"); } } catch(exception::UserError &) { @@ -279,21 +278,21 @@ void RdbmsCatalogue::createAdminHost( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":ADMIN_HOST_NAME", hostName); + stmt.bindString(":ADMIN_HOST_NAME", hostName); - stmt->bindString(":USER_COMMENT", comment); + stmt.bindString(":USER_COMMENT", comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch (exception::Exception &ex) { @@ -304,7 +303,7 @@ void RdbmsCatalogue::createAdminHost( //------------------------------------------------------------------------------ // adminHostExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::adminHostExists(rdbms::PooledConn &conn, const std::string adminHost) const { +bool RdbmsCatalogue::adminHostExists(rdbms::Conn &conn, const std::string adminHost) const { try { const char *const sql = "SELECT " @@ -313,9 +312,9 @@ bool RdbmsCatalogue::adminHostExists(rdbms::PooledConn &conn, const std::string "ADMIN_HOST " "WHERE " "ADMIN_HOST_NAME = :ADMIN_HOST_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":ADMIN_HOST_NAME", adminHost); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":ADMIN_HOST_NAME", adminHost); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -329,11 +328,11 @@ void RdbmsCatalogue::deleteAdminHost(const std::string &hostName) { try { const char *const sql = "DELETE FROM ADMIN_HOST WHERE ADMIN_HOST_NAME = :ADMIN_HOST_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":ADMIN_HOST_NAME", hostName); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":ADMIN_HOST_NAME", hostName); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot delete admin-host ") + hostName + " because it does not exist"); } } catch(exception::UserError &) { @@ -367,8 +366,8 @@ std::list<common::dataStructures::AdminHost> RdbmsCatalogue::getAdminHosts() con "ORDER BY " "ADMIN_HOST_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); while (rset.next()) { common::dataStructures::AdminHost host; @@ -406,15 +405,15 @@ void RdbmsCatalogue::modifyAdminHostComment(const common::dataStructures::Securi "WHERE " "ADMIN_HOST_NAME = :ADMIN_HOST_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":ADMIN_HOST_NAME", hostName); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":ADMIN_HOST_NAME", hostName); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify admin host ") + hostName + " because it does not exist"); } } catch(exception::UserError &) { @@ -466,23 +465,23 @@ void RdbmsCatalogue::createStorageClass( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":DISK_INSTANCE_NAME", storageClass.diskInstance); - stmt->bindString(":STORAGE_CLASS_NAME", storageClass.name); - stmt->bindUint64(":NB_COPIES", storageClass.nbCopies); + stmt.bindString(":DISK_INSTANCE_NAME", storageClass.diskInstance); + stmt.bindString(":STORAGE_CLASS_NAME", storageClass.name); + stmt.bindUint64(":NB_COPIES", storageClass.nbCopies); - stmt->bindString(":USER_COMMENT", storageClass.comment); + stmt.bindString(":USER_COMMENT", storageClass.comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch (exception::Exception &ex) { @@ -493,7 +492,7 @@ void RdbmsCatalogue::createStorageClass( //------------------------------------------------------------------------------ // storageClassExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::storageClassExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, +bool RdbmsCatalogue::storageClassExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName) const { try { const char *const sql = @@ -505,10 +504,10 @@ bool RdbmsCatalogue::storageClassExists(rdbms::PooledConn &conn, const std::stri "WHERE " "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":STORAGE_CLASS_NAME", storageClassName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":STORAGE_CLASS_NAME", storageClassName); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -527,13 +526,13 @@ void RdbmsCatalogue::deleteStorageClass(const std::string &diskInstanceName, con "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql,rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql,rdbms::AutocommitMode::ON); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":STORAGE_CLASS_NAME", storageClassName); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":STORAGE_CLASS_NAME", storageClassName); - stmt->executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + stmt.executeNonQuery(); + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot delete storage-class ") + diskInstanceName + ":" + storageClassName + " because it does not exist"); } @@ -571,8 +570,8 @@ std::list<common::dataStructures::StorageClass> "ORDER BY " "DISK_INSTANCE_NAME, STORAGE_CLASS_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); while (rset.next()) { common::dataStructures::StorageClass storageClass; @@ -613,16 +612,16 @@ void RdbmsCatalogue::modifyStorageClassNbCopies(const common::dataStructures::Se "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindUint64(":NB_COPIES", nbCopies); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":DISK_INSTANCE_NAME", instanceName); - stmt->bindString(":STORAGE_CLASS_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindUint64(":NB_COPIES", nbCopies); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":DISK_INSTANCE_NAME", instanceName); + stmt.bindString(":STORAGE_CLASS_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify storage class ") + instanceName + ":" + name + " because it does not exist"); } @@ -650,16 +649,16 @@ void RdbmsCatalogue::modifyStorageClassComment(const common::dataStructures::Sec "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":DISK_INSTANCE_NAME", instanceName); - stmt->bindString(":STORAGE_CLASS_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":DISK_INSTANCE_NAME", instanceName); + stmt.bindString(":STORAGE_CLASS_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify storage class ") + instanceName + ":" + name + " because it does not exist"); } @@ -716,23 +715,23 @@ void RdbmsCatalogue::createTapePool( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":TAPE_POOL_NAME", name); - stmt->bindUint64(":NB_PARTIAL_TAPES", nbPartialTapes); - stmt->bindBool(":IS_ENCRYPTED", encryptionValue); + stmt.bindString(":TAPE_POOL_NAME", name); + stmt.bindUint64(":NB_PARTIAL_TAPES", nbPartialTapes); + stmt.bindBool(":IS_ENCRYPTED", encryptionValue); - stmt->bindString(":USER_COMMENT", comment); + stmt.bindString(":USER_COMMENT", comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -755,7 +754,7 @@ bool RdbmsCatalogue::tapePoolExists(const std::string &tapePoolName) const { //------------------------------------------------------------------------------ // tapePoolExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::tapePoolExists(rdbms::PooledConn &conn, const std::string &tapePoolName) const { +bool RdbmsCatalogue::tapePoolExists(rdbms::Conn &conn, const std::string &tapePoolName) const { try { const char *const sql = "SELECT " @@ -764,9 +763,9 @@ bool RdbmsCatalogue::tapePoolExists(rdbms::PooledConn &conn, const std::string & "TAPE_POOL " "WHERE " "TAPE_POOL_NAME = :TAPE_POOL_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":TAPE_POOL_NAME", tapePoolName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":TAPE_POOL_NAME", tapePoolName); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -776,7 +775,7 @@ bool RdbmsCatalogue::tapePoolExists(rdbms::PooledConn &conn, const std::string & //------------------------------------------------------------------------------ // archiveFileExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::archiveFileIdExists(rdbms::PooledConn &conn, const uint64_t archiveFileId) const { +bool RdbmsCatalogue::archiveFileIdExists(rdbms::Conn &conn, const uint64_t archiveFileId) const { try { const char *const sql = "SELECT " @@ -785,9 +784,9 @@ bool RdbmsCatalogue::archiveFileIdExists(rdbms::PooledConn &conn, const uint64_t "ARCHIVE_FILE " "WHERE " "ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -797,7 +796,7 @@ bool RdbmsCatalogue::archiveFileIdExists(rdbms::PooledConn &conn, const uint64_t //------------------------------------------------------------------------------ // diskFileIdExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::diskFileIdExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, +bool RdbmsCatalogue::diskFileIdExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &diskFileId) const { try { const char *const sql = @@ -809,10 +808,10 @@ bool RdbmsCatalogue::diskFileIdExists(rdbms::PooledConn &conn, const std::string "WHERE " "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "DISK_FILE_ID = :DISK_FILE_ID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":DISK_FILE_ID", diskFileId); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":DISK_FILE_ID", diskFileId); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -822,7 +821,7 @@ bool RdbmsCatalogue::diskFileIdExists(rdbms::PooledConn &conn, const std::string //------------------------------------------------------------------------------ // diskFilePathExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::diskFilePathExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, +bool RdbmsCatalogue::diskFilePathExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &diskFilePath) const { try { const char *const sql = @@ -834,10 +833,10 @@ bool RdbmsCatalogue::diskFilePathExists(rdbms::PooledConn &conn, const std::stri "WHERE " "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "DISK_FILE_PATH = :DISK_FILE_PATH"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":DISK_FILE_PATH", diskFilePath); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":DISK_FILE_PATH", diskFilePath); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -847,7 +846,7 @@ bool RdbmsCatalogue::diskFilePathExists(rdbms::PooledConn &conn, const std::stri //------------------------------------------------------------------------------ // diskFileUserExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::diskFileUserExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, +bool RdbmsCatalogue::diskFileUserExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &diskFileUser) const { try { const char *const sql = @@ -859,10 +858,10 @@ bool RdbmsCatalogue::diskFileUserExists(rdbms::PooledConn &conn, const std::stri "WHERE " "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "DISK_FILE_USER = :DISK_FILE_USER"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":DISK_FILE_USER", diskFileUser); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":DISK_FILE_USER", diskFileUser); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -872,7 +871,7 @@ bool RdbmsCatalogue::diskFileUserExists(rdbms::PooledConn &conn, const std::stri //------------------------------------------------------------------------------ // diskFileGroupExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::diskFileGroupExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, +bool RdbmsCatalogue::diskFileGroupExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &diskFileGroup) const { try { const char *const sql = @@ -884,10 +883,10 @@ bool RdbmsCatalogue::diskFileGroupExists(rdbms::PooledConn &conn, const std::str "WHERE " "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "DISK_FILE_GROUP = :DISK_FILE_GROUP"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":DISK_FILE_GROUP", diskFileGroup); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":DISK_FILE_GROUP", diskFileGroup); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -897,7 +896,7 @@ bool RdbmsCatalogue::diskFileGroupExists(rdbms::PooledConn &conn, const std::str //------------------------------------------------------------------------------ // archiveRouteExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::archiveRouteExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, +bool RdbmsCatalogue::archiveRouteExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName, const uint64_t copyNb) const { try { const char *const sql = @@ -911,11 +910,11 @@ bool RdbmsCatalogue::archiveRouteExists(rdbms::PooledConn &conn, const std::stri "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME AND " "COPY_NB = :COPY_NB"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":STORAGE_CLASS_NAME", storageClassName); - stmt->bindUint64(":COPY_NB", copyNb); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":STORAGE_CLASS_NAME", storageClassName); + stmt.bindUint64(":COPY_NB", copyNb); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -929,11 +928,11 @@ void RdbmsCatalogue::deleteTapePool(const std::string &name) { try { const char *const sql = "DELETE FROM TAPE_POOL WHERE TAPE_POOL_NAME = :TAPE_POOL_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":TAPE_POOL_NAME", name); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":TAPE_POOL_NAME", name); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot delete tape-pool ") + name + " because it does not exist"); } } catch(exception::UserError &) { @@ -987,8 +986,8 @@ std::list<TapePool> RdbmsCatalogue::getTapePools() const { "TAPE_POOL_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); while (rset.next()) { TapePool pool; @@ -1031,15 +1030,15 @@ void RdbmsCatalogue::modifyTapePoolNbPartialTapes(const common::dataStructures:: "WHERE " "TAPE_POOL_NAME = :TAPE_POOL_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindUint64(":NB_PARTIAL_TAPES", nbPartialTapes); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":TAPE_POOL_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindUint64(":NB_PARTIAL_TAPES", nbPartialTapes); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":TAPE_POOL_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape pool ") + name + " because it does not exist"); } } catch(exception::UserError &) { @@ -1064,15 +1063,15 @@ void RdbmsCatalogue::modifyTapePoolComment(const common::dataStructures::Securit "WHERE " "TAPE_POOL_NAME = :TAPE_POOL_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":TAPE_POOL_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":TAPE_POOL_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape pool ") + name + " because it does not exist"); } } catch(exception::UserError &) { @@ -1098,15 +1097,15 @@ void RdbmsCatalogue::setTapePoolEncryption(const common::dataStructures::Securit "WHERE " "TAPE_POOL_NAME = :TAPE_POOL_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindBool(":IS_ENCRYPTED", encryptionValue); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":TAPE_POOL_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindBool(":IS_ENCRYPTED", encryptionValue); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":TAPE_POOL_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape pool ") + name + " because it does not exist"); } } catch(exception::UserError &) { @@ -1180,24 +1179,24 @@ void RdbmsCatalogue::createArchiveRoute( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":STORAGE_CLASS_NAME", storageClassName); - stmt->bindUint64(":COPY_NB", copyNb); - stmt->bindString(":TAPE_POOL_NAME", tapePoolName); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":STORAGE_CLASS_NAME", storageClassName); + stmt.bindUint64(":COPY_NB", copyNb); + stmt.bindString(":TAPE_POOL_NAME", tapePoolName); - stmt->bindString(":USER_COMMENT", comment); + stmt.bindString(":USER_COMMENT", comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -1219,13 +1218,13 @@ void RdbmsCatalogue::deleteArchiveRoute(const std::string &diskInstanceName, con "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME AND " "COPY_NB = :COPY_NB"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":STORAGE_CLASS_NAME", storageClassName); - stmt->bindUint64(":COPY_NB", copyNb); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":STORAGE_CLASS_NAME", storageClassName); + stmt.bindUint64(":COPY_NB", copyNb); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { exception::UserError ue; ue.getMessage() << "Cannot delete archive route for storage-class " << diskInstanceName + ":" + storageClassName + " and copy number " << copyNb << " because it does not exist"; @@ -1265,8 +1264,8 @@ std::list<common::dataStructures::ArchiveRoute> RdbmsCatalogue::getArchiveRoutes "ORDER BY " "DISK_INSTANCE_NAME, STORAGE_CLASS_NAME, COPY_NB"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); while (rset.next()) { common::dataStructures::ArchiveRoute route; @@ -1310,17 +1309,17 @@ void RdbmsCatalogue::modifyArchiveRouteTapePoolName(const common::dataStructures "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME AND " "COPY_NB = :COPY_NB"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":TAPE_POOL_NAME", tapePoolName); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":DISK_INSTANCE_NAME", instanceName); - stmt->bindString(":STORAGE_CLASS_NAME", storageClassName); - stmt->bindUint64(":COPY_NB", copyNb); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":TAPE_POOL_NAME", tapePoolName); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":DISK_INSTANCE_NAME", instanceName); + stmt.bindString(":STORAGE_CLASS_NAME", storageClassName); + stmt.bindUint64(":COPY_NB", copyNb); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { exception::UserError ue; ue.getMessage() << "Cannot modify archive route for storage-class " << instanceName + ":" + storageClassName + " and copy number " << copyNb << " because it does not exist"; @@ -1352,17 +1351,17 @@ void RdbmsCatalogue::modifyArchiveRouteComment(const common::dataStructures::Sec "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME AND " "COPY_NB = :COPY_NB"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":DISK_INSTANCE_NAME", instanceName); - stmt->bindString(":STORAGE_CLASS_NAME", storageClassName); - stmt->bindUint64(":COPY_NB", copyNb); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":DISK_INSTANCE_NAME", instanceName); + stmt.bindString(":STORAGE_CLASS_NAME", storageClassName); + stmt.bindUint64(":COPY_NB", copyNb); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { exception::UserError ue; ue.getMessage() << "Cannot modify archive route for storage-class " << instanceName + ":" + storageClassName + " and copy number " << copyNb << " because it does not exist"; @@ -1414,21 +1413,21 @@ void RdbmsCatalogue::createLogicalLibrary( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":LOGICAL_LIBRARY_NAME", name); + stmt.bindString(":LOGICAL_LIBRARY_NAME", name); - stmt->bindString(":USER_COMMENT", comment); + stmt.bindString(":USER_COMMENT", comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch(std::exception &ex) { @@ -1439,7 +1438,7 @@ void RdbmsCatalogue::createLogicalLibrary( //------------------------------------------------------------------------------ // logicalLibraryExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::logicalLibraryExists(rdbms::PooledConn &conn, const std::string &logicalLibraryName) const { +bool RdbmsCatalogue::logicalLibraryExists(rdbms::Conn &conn, const std::string &logicalLibraryName) const { try { const char *const sql = "SELECT " @@ -1448,9 +1447,9 @@ bool RdbmsCatalogue::logicalLibraryExists(rdbms::PooledConn &conn, const std::st "LOGICAL_LIBRARY " "WHERE " "LOGICAL_LIBRARY_NAME = :LOGICAL_LIBRARY_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -1464,11 +1463,11 @@ void RdbmsCatalogue::deleteLogicalLibrary(const std::string &name) { try { const char *const sql = "DELETE FROM LOGICAL_LIBRARY WHERE LOGICAL_LIBRARY_NAME = :LOGICAL_LIBRARY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":LOGICAL_LIBRARY_NAME", name); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":LOGICAL_LIBRARY_NAME", name); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot delete logical-library ") + name + " because it does not exist"); } } catch(exception::UserError &) { @@ -1503,8 +1502,8 @@ std::list<common::dataStructures::LogicalLibrary> "ORDER BY " "LOGICAL_LIBRARY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); while (rset.next()) { common::dataStructures::LogicalLibrary lib; @@ -1542,15 +1541,15 @@ void RdbmsCatalogue::modifyLogicalLibraryComment(const common::dataStructures::S "WHERE " "LOGICAL_LIBRARY_NAME = :LOGICAL_LIBRARY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":LOGICAL_LIBRARY_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LOGICAL_LIBRARY_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify logical library ") + name + " because it does not exist"); } } catch(exception::UserError &) { @@ -1626,28 +1625,28 @@ void RdbmsCatalogue::createTape( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":VID", vid); - stmt->bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName); - stmt->bindString(":TAPE_POOL_NAME", tapePoolName); - stmt->bindUint64(":CAPACITY_IN_BYTES", capacityInBytes); - stmt->bindUint64(":DATA_IN_BYTES", 0); - stmt->bindUint64(":LAST_FSEQ", 0); - stmt->bindBool(":IS_DISABLED", disabled); - stmt->bindBool(":IS_FULL", full); + stmt.bindString(":VID", vid); + stmt.bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName); + stmt.bindString(":TAPE_POOL_NAME", tapePoolName); + stmt.bindUint64(":CAPACITY_IN_BYTES", capacityInBytes); + stmt.bindUint64(":DATA_IN_BYTES", 0); + stmt.bindUint64(":LAST_FSEQ", 0); + stmt.bindBool(":IS_DISABLED", disabled); + stmt.bindBool(":IS_FULL", full); - stmt->bindString(":USER_COMMENT", comment); + stmt.bindString(":USER_COMMENT", comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -1670,7 +1669,7 @@ bool RdbmsCatalogue::tapeExists(const std::string &vid) const { //------------------------------------------------------------------------------ // tapeExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::tapeExists(rdbms::PooledConn &conn, const std::string &vid) const { +bool RdbmsCatalogue::tapeExists(rdbms::Conn &conn, const std::string &vid) const { try { const char *const sql = "SELECT " @@ -1679,9 +1678,9 @@ bool RdbmsCatalogue::tapeExists(rdbms::PooledConn &conn, const std::string &vid) "TAPE " "WHERE " "VID = :VID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":VID", vid); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":VID", vid); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -1695,11 +1694,11 @@ void RdbmsCatalogue::deleteTape(const std::string &vid) { try { const char *const sql = "DELETE FROM TAPE WHERE VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot delete tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -1724,7 +1723,7 @@ std::list<common::dataStructures::Tape> RdbmsCatalogue::getTapes(const TapeSearc //------------------------------------------------------------------------------ // getTapes //------------------------------------------------------------------------------ -std::list<common::dataStructures::Tape> RdbmsCatalogue::getTapes(rdbms::PooledConn &conn, +std::list<common::dataStructures::Tape> RdbmsCatalogue::getTapes(rdbms::Conn &conn, const TapeSearchCriteria &searchCriteria) const { try { std::list<common::dataStructures::Tape> tapes; @@ -1810,17 +1809,17 @@ std::list<common::dataStructures::Tape> RdbmsCatalogue::getTapes(rdbms::PooledCo sql += " ORDER BY VID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); - if(searchCriteria.vid) stmt->bindString(":VID", searchCriteria.vid.value()); - if(searchCriteria.logicalLibrary) stmt->bindString(":LOGICAL_LIBRARY_NAME", searchCriteria.logicalLibrary.value()); - if(searchCriteria.tapePool) stmt->bindString(":TAPE_POOL_NAME", searchCriteria.tapePool.value()); - if(searchCriteria.capacityInBytes) stmt->bindUint64(":CAPACITY_IN_BYTES", searchCriteria.capacityInBytes.value()); - if(searchCriteria.disabled) stmt->bindBool(":IS_DISABLED", searchCriteria.disabled.value()); - if(searchCriteria.full) stmt->bindBool(":IS_FULL", searchCriteria.full.value()); - if(searchCriteria.lbp) stmt->bindBool(":LBP_IS_ON", searchCriteria.lbp.value()); + if(searchCriteria.vid) stmt.bindString(":VID", searchCriteria.vid.value()); + if(searchCriteria.logicalLibrary) stmt.bindString(":LOGICAL_LIBRARY_NAME", searchCriteria.logicalLibrary.value()); + if(searchCriteria.tapePool) stmt.bindString(":TAPE_POOL_NAME", searchCriteria.tapePool.value()); + if(searchCriteria.capacityInBytes) stmt.bindUint64(":CAPACITY_IN_BYTES", searchCriteria.capacityInBytes.value()); + if(searchCriteria.disabled) stmt.bindBool(":IS_DISABLED", searchCriteria.disabled.value()); + if(searchCriteria.full) stmt.bindBool(":IS_FULL", searchCriteria.full.value()); + if(searchCriteria.lbp) stmt.bindBool(":LBP_IS_ON", searchCriteria.lbp.value()); - auto rset = stmt->executeQuery(); + auto rset = stmt.executeQuery(); while (rset.next()) { common::dataStructures::Tape tape; @@ -1910,17 +1909,17 @@ common::dataStructures::VidToTapeMap RdbmsCatalogue::getTapesByVid(const std::se } auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); { uint64_t vidNb = 1; for(auto &vid : vids) { - stmt->bindString(":VID" + std::to_string(vidNb), vid); + stmt.bindString(":VID" + std::to_string(vidNb), vid); vidNb++; } } - auto rset = stmt->executeQuery(); + auto rset = stmt.executeQuery(); while (rset.next()) { common::dataStructures::Tape tape; @@ -1979,16 +1978,16 @@ void RdbmsCatalogue::reclaimTape(const common::dataStructures::SecurityIdentity "IS_FULL != 0 AND " "NOT EXISTS (SELECT VID FROM TAPE_FILE WHERE VID = :SELECT_VID)"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":UPDATE_VID", vid); - stmt->bindString(":SELECT_VID", vid); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":UPDATE_VID", vid); + stmt.bindString(":SELECT_VID", vid); + stmt.executeNonQuery(); // If the update failed due to a user error - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { // Try to determine the user error // // Please note that this is a best effort diagnosis because there is no @@ -2067,15 +2066,15 @@ void RdbmsCatalogue::modifyTapeLogicalLibraryName(const common::dataStructures:: "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -2101,15 +2100,15 @@ void RdbmsCatalogue::modifyTapeTapePoolName(const common::dataStructures::Securi "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":TAPE_POOL_NAME", tapePoolName); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":TAPE_POOL_NAME", tapePoolName); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -2135,15 +2134,15 @@ void RdbmsCatalogue::modifyTapeCapacityInBytes(const common::dataStructures::Sec "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindUint64(":CAPACITY_IN_BYTES", capacityInBytes); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindUint64(":CAPACITY_IN_BYTES", capacityInBytes); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -2169,15 +2168,15 @@ void RdbmsCatalogue::modifyTapeEncryptionKey(const common::dataStructures::Secur "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":ENCRYPTION_KEY", encryptionKey); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":ENCRYPTION_KEY", encryptionKey); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -2200,13 +2199,13 @@ void RdbmsCatalogue::tapeMountedForArchive(const std::string &vid, const std::st "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":LAST_WRITE_DRIVE", drive); - stmt->bindUint64(":LAST_WRITE_TIME", now); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":LAST_WRITE_DRIVE", drive); + stmt.bindUint64(":LAST_WRITE_TIME", now); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -2229,13 +2228,13 @@ void RdbmsCatalogue::tapeMountedForRetrieve(const std::string &vid, const std::s "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":LAST_READ_DRIVE", drive); - stmt->bindUint64(":LAST_READ_TIME", now); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":LAST_READ_DRIVE", drive); + stmt.bindUint64(":LAST_READ_TIME", now); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -2261,15 +2260,15 @@ void RdbmsCatalogue::setTapeFull(const common::dataStructures::SecurityIdentity "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindBool(":IS_FULL", fullValue); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindBool(":IS_FULL", fullValue); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -2290,11 +2289,11 @@ void RdbmsCatalogue::noSpaceLeftOnTape(const std::string &vid) { "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::Exception(std::string("Tape ") + vid + " does not exist"); } } catch (exception::Exception &ex) { @@ -2318,15 +2317,15 @@ void RdbmsCatalogue::setTapeDisabled(const common::dataStructures::SecurityIdent "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindBool(":IS_DISABLED", disabledValue); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindBool(":IS_DISABLED", disabledValue); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -2352,15 +2351,15 @@ void RdbmsCatalogue::modifyTapeComment(const common::dataStructures::SecurityIde "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -2387,16 +2386,16 @@ void RdbmsCatalogue::modifyRequesterMountRulePolicy(const common::dataStructures "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_NAME = :REQUESTER_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":MOUNT_POLICY_NAME", mountPolicy); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":DISK_INSTANCE_NAME", instanceName); - stmt->bindString(":REQUESTER_NAME", requesterName); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":MOUNT_POLICY_NAME", mountPolicy); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":DISK_INSTANCE_NAME", instanceName); + stmt.bindString(":REQUESTER_NAME", requesterName); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify requester mount rule ") + instanceName + ":" + requesterName + " because it does not exist"); } @@ -2424,16 +2423,16 @@ void RdbmsCatalogue::modifyRequesteMountRuleComment(const common::dataStructures "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_NAME = :REQUESTER_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":DISK_INSTANCE_NAME", instanceName); - stmt->bindString(":REQUESTER_NAME", requesterName); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":DISK_INSTANCE_NAME", instanceName); + stmt.bindString(":REQUESTER_NAME", requesterName); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify requester mount rule ") + instanceName + ":" + requesterName + " because it does not exist"); } @@ -2461,16 +2460,16 @@ void RdbmsCatalogue::modifyRequesterGroupMountRulePolicy(const common::dataStruc "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_GROUP_NAME = :REQUESTER_GROUP_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":MOUNT_POLICY_NAME", mountPolicy); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":DISK_INSTANCE_NAME", instanceName); - stmt->bindString(":REQUESTER_GROUP_NAME", requesterGroupName); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":MOUNT_POLICY_NAME", mountPolicy); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":DISK_INSTANCE_NAME", instanceName); + stmt.bindString(":REQUESTER_GROUP_NAME", requesterGroupName); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify requester group mount rule ") + instanceName + ":" + requesterGroupName + " because it does not exist"); } @@ -2498,16 +2497,16 @@ void RdbmsCatalogue::modifyRequesterGroupMountRuleComment(const common::dataStru "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_GROUP_NAME = :REQUESTER_GROUP_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":DISK_INSTANCE_NAME", instanceName); - stmt->bindString(":REQUESTER_GROUP_NAME", requesterGroupName); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":DISK_INSTANCE_NAME", instanceName); + stmt.bindString(":REQUESTER_GROUP_NAME", requesterGroupName); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify requester group mount rule ") + instanceName + ":" + requesterGroupName + " because it does not exist"); } @@ -2578,29 +2577,29 @@ void RdbmsCatalogue::createMountPolicy( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":MOUNT_POLICY_NAME", name); + stmt.bindString(":MOUNT_POLICY_NAME", name); - stmt->bindUint64(":ARCHIVE_PRIORITY", archivePriority); - stmt->bindUint64(":ARCHIVE_MIN_REQUEST_AGE", minArchiveRequestAge); + stmt.bindUint64(":ARCHIVE_PRIORITY", archivePriority); + stmt.bindUint64(":ARCHIVE_MIN_REQUEST_AGE", minArchiveRequestAge); - stmt->bindUint64(":RETRIEVE_PRIORITY", retrievePriority); - stmt->bindUint64(":RETRIEVE_MIN_REQUEST_AGE", minRetrieveRequestAge); + stmt.bindUint64(":RETRIEVE_PRIORITY", retrievePriority); + stmt.bindUint64(":RETRIEVE_MIN_REQUEST_AGE", minRetrieveRequestAge); - stmt->bindUint64(":MAX_DRIVES_ALLOWED", maxDrivesAllowed); + stmt.bindUint64(":MAX_DRIVES_ALLOWED", maxDrivesAllowed); - stmt->bindString(":USER_COMMENT", comment); + stmt.bindString(":USER_COMMENT", comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -2661,23 +2660,23 @@ void RdbmsCatalogue::createRequesterMountRule( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":REQUESTER_NAME", requesterName); - stmt->bindString(":MOUNT_POLICY_NAME", mountPolicyName); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":REQUESTER_NAME", requesterName); + stmt.bindString(":MOUNT_POLICY_NAME", mountPolicyName); - stmt->bindString(":USER_COMMENT", comment); + stmt.bindString(":USER_COMMENT", comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -2711,8 +2710,8 @@ std::list<common::dataStructures::RequesterMountRule> RdbmsCatalogue::getRequest "ORDER BY " "DISK_INSTANCE_NAME, REQUESTER_NAME, MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); while(rset.next()) { common::dataStructures::RequesterMountRule rule; @@ -2748,12 +2747,12 @@ void RdbmsCatalogue::deleteRequesterMountRule(const std::string &diskInstanceNam "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_NAME = :REQUESTER_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":REQUESTER_NAME", requesterName); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":REQUESTER_NAME", requesterName); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot delete mount rule for requester ") + diskInstanceName + ":" + requesterName + " because the rule does not exist"); } @@ -2816,23 +2815,23 @@ void RdbmsCatalogue::createRequesterGroupMountRule( ":LAST_UPDATE_USER_NAME," ":LAST_UPDATE_HOST_NAME," ":LAST_UPDATE_TIME)"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":REQUESTER_GROUP_NAME", requesterGroupName); - stmt->bindString(":MOUNT_POLICY_NAME", mountPolicyName); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":REQUESTER_GROUP_NAME", requesterGroupName); + stmt.bindString(":MOUNT_POLICY_NAME", mountPolicyName); - stmt->bindString(":USER_COMMENT", comment); + stmt.bindString(":USER_COMMENT", comment); - stmt->bindString(":CREATION_LOG_USER_NAME", admin.username); - stmt->bindString(":CREATION_LOG_HOST_NAME", admin.host); - stmt->bindUint64(":CREATION_LOG_TIME", now); + stmt.bindString(":CREATION_LOG_USER_NAME", admin.username); + stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host); + stmt.bindUint64(":CREATION_LOG_TIME", now); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::UserError &) { throw; } catch(exception::Exception &ex) { @@ -2844,7 +2843,7 @@ void RdbmsCatalogue::createRequesterGroupMountRule( // getRequesterGroupMountPolicy //------------------------------------------------------------------------------ common::dataStructures::MountPolicy *RdbmsCatalogue::getRequesterGroupMountPolicy( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterGroupName) const { try { @@ -2878,10 +2877,10 @@ common::dataStructures::MountPolicy *RdbmsCatalogue::getRequesterGroupMountPolic "WHERE " "REQUESTER_GROUP_MOUNT_RULE.DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_GROUP_MOUNT_RULE.REQUESTER_GROUP_NAME = :REQUESTER_GROUP_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":REQUESTER_GROUP_NAME", requesterGroupName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":REQUESTER_GROUP_NAME", requesterGroupName); + auto rset = stmt.executeQuery(); if(rset.next()) { auto policy = cta::make_unique<common::dataStructures::MountPolicy>(); @@ -2938,8 +2937,8 @@ std::list<common::dataStructures::RequesterGroupMountRule> RdbmsCatalogue::getRe "ORDER BY " "DISK_INSTANCE_NAME, REQUESTER_GROUP_NAME, MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); while(rset.next()) { common::dataStructures::RequesterGroupMountRule rule; @@ -2977,12 +2976,12 @@ void RdbmsCatalogue::deleteRequesterGroupMountRule(const std::string &diskInstan "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_GROUP_NAME = :REQUESTER_GROUP_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":REQUESTER_GROUP_NAME", requesterGroupName); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":REQUESTER_GROUP_NAME", requesterGroupName); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot delete the mount rule for requester group ") + diskInstanceName + ":" + requesterGroupName + " because it does not exist"); } @@ -2996,7 +2995,7 @@ void RdbmsCatalogue::deleteRequesterGroupMountRule(const std::string &diskInstan //------------------------------------------------------------------------------ // mountPolicyExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::mountPolicyExists(rdbms::PooledConn &conn, const std::string &mountPolicyName) const { +bool RdbmsCatalogue::mountPolicyExists(rdbms::Conn &conn, const std::string &mountPolicyName) const { try { const char *const sql = "SELECT " @@ -3005,9 +3004,9 @@ bool RdbmsCatalogue::mountPolicyExists(rdbms::PooledConn &conn, const std::strin "MOUNT_POLICY " "WHERE " "MOUNT_POLICY_NAME = :MOUNT_POLICY_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":MOUNT_POLICY_NAME", mountPolicyName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":MOUNT_POLICY_NAME", mountPolicyName); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -3017,7 +3016,7 @@ bool RdbmsCatalogue::mountPolicyExists(rdbms::PooledConn &conn, const std::strin //------------------------------------------------------------------------------ // requesterMountRuleExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::requesterMountRuleExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, +bool RdbmsCatalogue::requesterMountRuleExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterName) const { try { const char *const sql = @@ -3028,10 +3027,10 @@ bool RdbmsCatalogue::requesterMountRuleExists(rdbms::PooledConn &conn, const std "WHERE " "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_NAME = :REQUESTER_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":REQUESTER_NAME", requesterName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":REQUESTER_NAME", requesterName); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -3042,7 +3041,7 @@ bool RdbmsCatalogue::requesterMountRuleExists(rdbms::PooledConn &conn, const std // getRequesterMountPolicy //------------------------------------------------------------------------------ common::dataStructures::MountPolicy *RdbmsCatalogue::getRequesterMountPolicy( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterName) const { try { @@ -3076,10 +3075,10 @@ common::dataStructures::MountPolicy *RdbmsCatalogue::getRequesterMountPolicy( "WHERE " "REQUESTER_MOUNT_RULE.DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_MOUNT_RULE.REQUESTER_NAME = :REQUESTER_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":REQUESTER_NAME", requesterName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":REQUESTER_NAME", requesterName); + auto rset = stmt.executeQuery(); if(rset.next()) { auto policy = cta::make_unique<common::dataStructures::MountPolicy>(); @@ -3116,7 +3115,7 @@ common::dataStructures::MountPolicy *RdbmsCatalogue::getRequesterMountPolicy( //------------------------------------------------------------------------------ // requesterGroupMountRuleExists //------------------------------------------------------------------------------ -bool RdbmsCatalogue::requesterGroupMountRuleExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, +bool RdbmsCatalogue::requesterGroupMountRuleExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterGroupName) const { try { const char *const sql = @@ -3128,10 +3127,10 @@ bool RdbmsCatalogue::requesterGroupMountRuleExists(rdbms::PooledConn &conn, cons "WHERE " "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "REQUESTER_GROUP_NAME = :REQUESTER_GROUP_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":REQUESTER_GROUP_NAME", requesterGroupName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":REQUESTER_GROUP_NAME", requesterGroupName); + auto rset = stmt.executeQuery(); return rset.next(); } catch (exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -3145,11 +3144,11 @@ void RdbmsCatalogue::deleteMountPolicy(const std::string &name) { try { const char *const sql = "DELETE FROM MOUNT_POLICY WHERE MOUNT_POLICY_NAME = :MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":MOUNT_POLICY_NAME", name); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":MOUNT_POLICY_NAME", name); + stmt.executeNonQuery(); - if(0 == stmt->getNbAffectedRows()) { + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot delete mount policy ") + name + " because it does not exist"); } } catch(exception::UserError &) { @@ -3191,8 +3190,8 @@ std::list<common::dataStructures::MountPolicy> RdbmsCatalogue::getMountPolicies( "ORDER BY " "MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); while (rset.next()) { common::dataStructures::MountPolicy policy; @@ -3241,15 +3240,15 @@ void RdbmsCatalogue::modifyMountPolicyArchivePriority(const common::dataStructur "WHERE " "MOUNT_POLICY_NAME = :MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindUint64(":ARCHIVE_PRIORITY", archivePriority); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":MOUNT_POLICY_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindUint64(":ARCHIVE_PRIORITY", archivePriority); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":MOUNT_POLICY_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify mount policy ") + name + " because they do not exist"); } } catch(exception::UserError &) { @@ -3275,15 +3274,15 @@ void RdbmsCatalogue::modifyMountPolicyArchiveMinRequestAge(const common::dataStr "WHERE " "MOUNT_POLICY_NAME = :MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindUint64(":ARCHIVE_MIN_REQUEST_AGE", minArchiveRequestAge); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":MOUNT_POLICY_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindUint64(":ARCHIVE_MIN_REQUEST_AGE", minArchiveRequestAge); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":MOUNT_POLICY_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify mount policy ") + name + " because they do not exist"); } } catch(exception::UserError &) { @@ -3309,15 +3308,15 @@ void RdbmsCatalogue::modifyMountPolicyRetrievePriority(const common::dataStructu "WHERE " "MOUNT_POLICY_NAME = :MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindUint64(":RETRIEVE_PRIORITY", retrievePriority); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":MOUNT_POLICY_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindUint64(":RETRIEVE_PRIORITY", retrievePriority); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":MOUNT_POLICY_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify mount policy ") + name + " because they do not exist"); } } catch(exception::UserError &) { @@ -3343,15 +3342,15 @@ void RdbmsCatalogue::modifyMountPolicyRetrieveMinRequestAge(const common::dataSt "WHERE " "MOUNT_POLICY_NAME = :MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindUint64(":RETRIEVE_MIN_REQUEST_AGE", minRetrieveRequestAge); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":MOUNT_POLICY_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindUint64(":RETRIEVE_MIN_REQUEST_AGE", minRetrieveRequestAge); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":MOUNT_POLICY_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify mount policy ") + name + " because they do not exist"); } } catch(exception::UserError &) { @@ -3377,15 +3376,15 @@ void RdbmsCatalogue::modifyMountPolicyMaxDrivesAllowed(const common::dataStructu "WHERE " "MOUNT_POLICY_NAME = :MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindUint64(":MAX_DRIVES_ALLOWED", maxDrivesAllowed); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":MOUNT_POLICY_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindUint64(":MAX_DRIVES_ALLOWED", maxDrivesAllowed); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":MOUNT_POLICY_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify mount policy ") + name + " because they do not exist"); } } catch(exception::UserError &) { @@ -3411,15 +3410,15 @@ void RdbmsCatalogue::modifyMountPolicyComment(const common::dataStructures::Secu "WHERE " "MOUNT_POLICY_NAME = :MOUNT_POLICY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":USER_COMMENT", comment); - stmt->bindString(":LAST_UPDATE_USER_NAME", admin.username); - stmt->bindString(":LAST_UPDATE_HOST_NAME", admin.host); - stmt->bindUint64(":LAST_UPDATE_TIME", now); - stmt->bindString(":MOUNT_POLICY_NAME", name); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":USER_COMMENT", comment); + stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username); + stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host); + stmt.bindUint64(":LAST_UPDATE_TIME", now); + stmt.bindString(":MOUNT_POLICY_NAME", name); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify mount policy ") + name + " because they do not exist"); } } catch(exception::UserError &) { @@ -3432,7 +3431,7 @@ void RdbmsCatalogue::modifyMountPolicyComment(const common::dataStructures::Secu //------------------------------------------------------------------------------ // insertArchiveFile //------------------------------------------------------------------------------ -void RdbmsCatalogue::insertArchiveFile(rdbms::PooledConn &conn, const rdbms::Stmt::AutocommitMode autocommitMode, +void RdbmsCatalogue::insertArchiveFile(rdbms::Conn &conn, const rdbms::AutocommitMode autocommitMode, const ArchiveFileRow &row) { try { if(!storageClassExists(conn, row.diskInstance, row.storageClassName)) { @@ -3472,21 +3471,21 @@ void RdbmsCatalogue::insertArchiveFile(rdbms::PooledConn &conn, const rdbms::Stm ":RECONCILIATION_TIME)"; auto stmt = conn.createStmt(sql, autocommitMode); - stmt->bindUint64(":ARCHIVE_FILE_ID", row.archiveFileId); - stmt->bindString(":DISK_INSTANCE_NAME", row.diskInstance); - stmt->bindString(":DISK_FILE_ID", row.diskFileId); - stmt->bindString(":DISK_FILE_PATH", row.diskFilePath); - stmt->bindString(":DISK_FILE_USER", row.diskFileUser); - stmt->bindString(":DISK_FILE_GROUP", row.diskFileGroup); - stmt->bindString(":DISK_FILE_RECOVERY_BLOB", row.diskFileRecoveryBlob); - stmt->bindUint64(":SIZE_IN_BYTES", row.size); - stmt->bindString(":CHECKSUM_TYPE", row.checksumType); - stmt->bindString(":CHECKSUM_VALUE", row.checksumValue); - stmt->bindString(":STORAGE_CLASS_NAME", row.storageClassName); - stmt->bindUint64(":CREATION_TIME", now); - stmt->bindUint64(":RECONCILIATION_TIME", now); - - stmt->executeNonQuery(); + stmt.bindUint64(":ARCHIVE_FILE_ID", row.archiveFileId); + stmt.bindString(":DISK_INSTANCE_NAME", row.diskInstance); + stmt.bindString(":DISK_FILE_ID", row.diskFileId); + stmt.bindString(":DISK_FILE_PATH", row.diskFilePath); + stmt.bindString(":DISK_FILE_USER", row.diskFileUser); + stmt.bindString(":DISK_FILE_GROUP", row.diskFileGroup); + stmt.bindString(":DISK_FILE_RECOVERY_BLOB", row.diskFileRecoveryBlob); + stmt.bindUint64(":SIZE_IN_BYTES", row.size); + stmt.bindString(":CHECKSUM_TYPE", row.checksumType); + stmt.bindString(":CHECKSUM_VALUE", row.checksumValue); + stmt.bindString(":STORAGE_CLASS_NAME", row.storageClassName); + stmt.bindUint64(":CREATION_TIME", now); + stmt.bindUint64(":RECONCILIATION_TIME", now); + + stmt.executeNonQuery(); } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); } @@ -3677,38 +3676,38 @@ common::dataStructures::ArchiveFileSummary RdbmsCatalogue::getTapeFileSummary( } auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); if(searchCriteria.archiveFileId) { - stmt->bindUint64(":ARCHIVE_FILE_ID", searchCriteria.archiveFileId.value()); + stmt.bindUint64(":ARCHIVE_FILE_ID", searchCriteria.archiveFileId.value()); } if(searchCriteria.diskInstance) { - stmt->bindString(":DISK_INSTANCE_NAME", searchCriteria.diskInstance.value()); + stmt.bindString(":DISK_INSTANCE_NAME", searchCriteria.diskInstance.value()); } if(searchCriteria.diskFileId) { - stmt->bindString(":DISK_FILE_ID", searchCriteria.diskFileId.value()); + stmt.bindString(":DISK_FILE_ID", searchCriteria.diskFileId.value()); } if(searchCriteria.diskFilePath) { - stmt->bindString(":DISK_FILE_PATH", searchCriteria.diskFilePath.value()); + stmt.bindString(":DISK_FILE_PATH", searchCriteria.diskFilePath.value()); } if(searchCriteria.diskFileUser) { - stmt->bindString(":DISK_FILE_USER", searchCriteria.diskFileUser.value()); + stmt.bindString(":DISK_FILE_USER", searchCriteria.diskFileUser.value()); } if(searchCriteria.diskFileGroup) { - stmt->bindString(":DISK_FILE_GROUP", searchCriteria.diskFileGroup.value()); + stmt.bindString(":DISK_FILE_GROUP", searchCriteria.diskFileGroup.value()); } if(searchCriteria.storageClass) { - stmt->bindString(":STORAGE_CLASS_NAME", searchCriteria.storageClass.value()); + stmt.bindString(":STORAGE_CLASS_NAME", searchCriteria.storageClass.value()); } if(searchCriteria.vid) { - stmt->bindString(":VID", searchCriteria.vid.value()); + stmt.bindString(":VID", searchCriteria.vid.value()); } if(searchCriteria.tapeFileCopyNb) { - stmt->bindUint64(":TAPE_FILE_COPY_NB", searchCriteria.tapeFileCopyNb.value()); + stmt.bindUint64(":TAPE_FILE_COPY_NB", searchCriteria.tapeFileCopyNb.value()); } if(searchCriteria.tapePool) { - stmt->bindString(":TAPE_POOL_NAME", searchCriteria.tapePool.value()); + stmt.bindString(":TAPE_POOL_NAME", searchCriteria.tapePool.value()); } - auto rset = stmt->executeQuery(); + auto rset = stmt.executeQuery(); if(!rset.next()) { throw exception::Exception("SELECT COUNT statement did not returned a row"); } @@ -3758,14 +3757,14 @@ void RdbmsCatalogue::tapeLabelled(const std::string &vid, const std::string &dri "WHERE " "VID = :VID"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":LABEL_DRIVE", drive); - stmt->bindUint64(":LABEL_TIME", now); - stmt->bindBool(":LBP_IS_ON", lbpIsOn); - stmt->bindString(":VID", vid); - stmt->executeNonQuery(); - - if(0 == stmt->getNbAffectedRows()) { + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":LABEL_DRIVE", drive); + stmt.bindUint64(":LABEL_TIME", now); + stmt.bindBool(":LBP_IS_ON", lbpIsOn); + stmt.bindString(":VID", vid); + stmt.executeNonQuery(); + + if(0 == stmt.getNbAffectedRows()) { throw exception::UserError(std::string("Cannot modify tape ") + vid + " because it does not exist"); } } catch(exception::UserError &) { @@ -3788,16 +3787,16 @@ common::dataStructures::ArchiveFileQueueCriteria RdbmsCatalogue::prepareForNewFi // Check that the number of archive routes is correct if(copyToPoolMap.empty()) { - exception::Exception ex; - ex.getMessage() << "Storage class " << diskInstanceName << ":" << storageClassName << " has no archive routes"; - throw ex; + exception::UserError ue; + ue.getMessage() << "Storage class " << diskInstanceName << ":" << storageClassName << " has no archive routes"; + throw ue; } if(copyToPoolMap.size() != expectedNbRoutes) { - exception::Exception ex; - ex.getMessage() << "Storage class " << diskInstanceName << ":" << storageClassName << " does not have the" + exception::UserError ue; + ue.getMessage() << "Storage class " << diskInstanceName << ":" << storageClassName << " does not have the" " expected number of archive routes routes: expected=" << expectedNbRoutes << ", actual=" << copyToPoolMap.size(); - throw ex; + throw ue; } const RequesterAndGroupMountPolicies mountPolicies = getMountPolicies(conn, diskInstanceName, user.name, @@ -3831,7 +3830,7 @@ common::dataStructures::ArchiveFileQueueCriteria RdbmsCatalogue::prepareForNewFi //------------------------------------------------------------------------------ // getTapeCopyToPoolMap //------------------------------------------------------------------------------ -common::dataStructures::TapeCopyToPoolMap RdbmsCatalogue::getTapeCopyToPoolMap(rdbms::PooledConn &conn, +common::dataStructures::TapeCopyToPoolMap RdbmsCatalogue::getTapeCopyToPoolMap(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName) const { try { common::dataStructures::TapeCopyToPoolMap copyToPoolMap; @@ -3844,10 +3843,10 @@ common::dataStructures::TapeCopyToPoolMap RdbmsCatalogue::getTapeCopyToPoolMap(r "WHERE " "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":STORAGE_CLASS_NAME", storageClassName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":STORAGE_CLASS_NAME", storageClassName); + auto rset = stmt.executeQuery(); while (rset.next()) { const uint64_t copyNb = rset.columnUint64("COPY_NB"); const std::string tapePoolName = rset.columnString("TAPE_POOL_NAME"); @@ -3863,7 +3862,7 @@ common::dataStructures::TapeCopyToPoolMap RdbmsCatalogue::getTapeCopyToPoolMap(r //------------------------------------------------------------------------------ // getExpectedNbArchiveRoutes //------------------------------------------------------------------------------ -uint64_t RdbmsCatalogue::getExpectedNbArchiveRoutes(rdbms::PooledConn &conn, const std::string &diskInstanceName, +uint64_t RdbmsCatalogue::getExpectedNbArchiveRoutes(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName) const { try { const char *const sql = @@ -3874,10 +3873,10 @@ uint64_t RdbmsCatalogue::getExpectedNbArchiveRoutes(rdbms::PooledConn &conn, con "WHERE " "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":STORAGE_CLASS_NAME", storageClassName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":STORAGE_CLASS_NAME", storageClassName); + auto rset = stmt.executeQuery(); if(!rset.next()) { throw exception::Exception("Result set of SELECT COUNT(*) is empty"); } @@ -3891,8 +3890,8 @@ uint64_t RdbmsCatalogue::getExpectedNbArchiveRoutes(rdbms::PooledConn &conn, con // updateTape //------------------------------------------------------------------------------ void RdbmsCatalogue::updateTape( - rdbms::PooledConn &conn, - const rdbms::Stmt::AutocommitMode autocommitMode, + rdbms::Conn &conn, + const rdbms::AutocommitMode autocommitMode, const std::string &vid, const uint64_t lastFSeq, const uint64_t compressedBytesWritten, @@ -3908,12 +3907,12 @@ void RdbmsCatalogue::updateTape( "WHERE " "VID = :VID"; auto stmt = conn.createStmt(sql, autocommitMode); - stmt->bindString(":VID", vid); - stmt->bindUint64(":LAST_FSEQ", lastFSeq); - stmt->bindUint64(":DATA_IN_BYTES", compressedBytesWritten); - stmt->bindString(":LAST_WRITE_DRIVE", tapeDrive); - stmt->bindUint64(":LAST_WRITE_TIME", now); - stmt->executeNonQuery(); + stmt.bindString(":VID", vid); + stmt.bindUint64(":LAST_FSEQ", lastFSeq); + stmt.bindUint64(":DATA_IN_BYTES", compressedBytesWritten); + stmt.bindString(":LAST_WRITE_DRIVE", tapeDrive); + stmt.bindUint64(":LAST_WRITE_TIME", now); + stmt.executeNonQuery(); } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); } @@ -4045,7 +4044,7 @@ common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetri // getMountPolicies //------------------------------------------------------------------------------ RequesterAndGroupMountPolicies RdbmsCatalogue::getMountPolicies( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterName, const std::string &requesterGroupName) const { @@ -4105,12 +4104,12 @@ RequesterAndGroupMountPolicies RdbmsCatalogue::getMountPolicies( "REQUESTER_GROUP_MOUNT_RULE.DISK_INSTANCE_NAME = :GROUP_DISK_INSTANCE_NAME AND " "REQUESTER_GROUP_MOUNT_RULE.REQUESTER_GROUP_NAME = :REQUESTER_GROUP_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":REQUESTER_DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":GROUP_DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":REQUESTER_NAME", requesterName); - stmt->bindString(":REQUESTER_GROUP_NAME", requesterGroupName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":REQUESTER_DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":GROUP_DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":REQUESTER_NAME", requesterName); + stmt.bindString(":REQUESTER_GROUP_NAME", requesterGroupName); + auto rset = stmt.executeQuery(); RequesterAndGroupMountPolicies policies; while(rset.next()) { @@ -4154,7 +4153,7 @@ bool RdbmsCatalogue::isAdmin(const common::dataStructures::SecurityIdentity &adm //------------------------------------------------------------------------------ // userIsAdmin //------------------------------------------------------------------------------ -bool RdbmsCatalogue::userIsAdmin(rdbms::PooledConn &conn, const std::string &userName) const { +bool RdbmsCatalogue::userIsAdmin(rdbms::Conn &conn, const std::string &userName) const { const char *const sql = "SELECT " "ADMIN_USER_NAME AS ADMIN_USER_NAME " @@ -4162,16 +4161,16 @@ bool RdbmsCatalogue::userIsAdmin(rdbms::PooledConn &conn, const std::string &use "ADMIN_USER " "WHERE " "ADMIN_USER_NAME = :ADMIN_USER_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":ADMIN_USER_NAME", userName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":ADMIN_USER_NAME", userName); + auto rset = stmt.executeQuery(); return rset.next(); } //------------------------------------------------------------------------------ // hostIsAdmin //------------------------------------------------------------------------------ -bool RdbmsCatalogue::hostIsAdmin(rdbms::PooledConn &conn, const std::string &hostName) const { +bool RdbmsCatalogue::hostIsAdmin(rdbms::Conn &conn, const std::string &hostName) const { const char *const sql = "SELECT " "ADMIN_HOST_NAME AS ADMIN_HOST_NAME " @@ -4179,9 +4178,9 @@ bool RdbmsCatalogue::hostIsAdmin(rdbms::PooledConn &conn, const std::string &hos "ADMIN_HOST " "WHERE " "ADMIN_HOST_NAME = :ADMIN_HOST_NAME"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":ADMIN_HOST_NAME", hostName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":ADMIN_HOST_NAME", hostName); + auto rset = stmt.executeQuery(); return rset.next(); } @@ -4208,9 +4207,9 @@ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string & "IS_FULL = 0 AND " "LOGICAL_LIBRARY_NAME = :LOGICAL_LIBRARY_NAME"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":LOGICAL_LIBRARY_NAME", logicalLibraryName); + auto rset = stmt.executeQuery(); while (rset.next()) { TapeForWriting tape; tape.vid = rset.columnString("VID"); @@ -4232,8 +4231,8 @@ std::list<TapeForWriting> RdbmsCatalogue::getTapesForWriting(const std::string & // insertTapeFile //------------------------------------------------------------------------------ void RdbmsCatalogue::insertTapeFile( - rdbms::PooledConn &conn, - const rdbms::Stmt::AutocommitMode autocommitMode, + rdbms::Conn &conn, + const rdbms::AutocommitMode autocommitMode, const common::dataStructures::TapeFile &tapeFile, const uint64_t archiveFileId) { try { @@ -4257,15 +4256,15 @@ void RdbmsCatalogue::insertTapeFile( ":ARCHIVE_FILE_ID)"; auto stmt = conn.createStmt(sql, autocommitMode); - stmt->bindString(":VID", tapeFile.vid); - stmt->bindUint64(":FSEQ", tapeFile.fSeq); - stmt->bindUint64(":BLOCK_ID", tapeFile.blockId); - stmt->bindUint64(":COMPRESSED_SIZE_IN_BYTES", tapeFile.compressedSize); - stmt->bindUint64(":COPY_NB", tapeFile.copyNb); - stmt->bindUint64(":CREATION_TIME", now); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId); + stmt.bindString(":VID", tapeFile.vid); + stmt.bindUint64(":FSEQ", tapeFile.fSeq); + stmt.bindUint64(":BLOCK_ID", tapeFile.blockId); + stmt.bindUint64(":COMPRESSED_SIZE_IN_BYTES", tapeFile.compressedSize); + stmt.bindUint64(":COPY_NB", tapeFile.copyNb); + stmt.bindUint64(":CREATION_TIME", now); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); } @@ -4274,7 +4273,7 @@ void RdbmsCatalogue::insertTapeFile( //------------------------------------------------------------------------------ // setTapeLastFseq //------------------------------------------------------------------------------ -void RdbmsCatalogue::setTapeLastFSeq(rdbms::PooledConn &conn, const std::string &vid, const uint64_t lastFSeq) { +void RdbmsCatalogue::setTapeLastFSeq(rdbms::Conn &conn, const std::string &vid, const uint64_t lastFSeq) { try { threading::MutexLocker locker(m_mutex); @@ -4290,10 +4289,10 @@ void RdbmsCatalogue::setTapeLastFSeq(rdbms::PooledConn &conn, const std::string "LAST_FSEQ = :LAST_FSEQ " "WHERE " "VID=:VID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::ON); - stmt->bindString(":VID", vid); - stmt->bindUint64(":LAST_FSEQ", lastFSeq); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); + stmt.bindString(":VID", vid); + stmt.bindUint64(":LAST_FSEQ", lastFSeq); + stmt.executeNonQuery(); } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); } @@ -4302,7 +4301,7 @@ void RdbmsCatalogue::setTapeLastFSeq(rdbms::PooledConn &conn, const std::string //------------------------------------------------------------------------------ // getTapeLastFSeq //------------------------------------------------------------------------------ -uint64_t RdbmsCatalogue::getTapeLastFSeq(rdbms::PooledConn &conn, const std::string &vid) const { +uint64_t RdbmsCatalogue::getTapeLastFSeq(rdbms::Conn &conn, const std::string &vid) const { try { const char *const sql = "SELECT " @@ -4311,9 +4310,9 @@ uint64_t RdbmsCatalogue::getTapeLastFSeq(rdbms::PooledConn &conn, const std::str "TAPE " "WHERE " "VID = :VID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":VID", vid); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":VID", vid); + auto rset = stmt.executeQuery(); if(rset.next()) { return rset.columnUint64("LAST_FSEQ"); } else { @@ -4328,7 +4327,7 @@ uint64_t RdbmsCatalogue::getTapeLastFSeq(rdbms::PooledConn &conn, const std::str // getArchiveFileByArchiveId //------------------------------------------------------------------------------ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveFileByArchiveFileId( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const uint64_t archiveFileId) const { try { const char *const sql = @@ -4358,9 +4357,9 @@ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveF "ARCHIVE_FILE.ARCHIVE_FILE_ID = TAPE_FILE.ARCHIVE_FILE_ID " "WHERE " "ARCHIVE_FILE.ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); + auto rset = stmt.executeQuery(); std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile; while (rset.next()) { if(nullptr == archiveFile.get()) { @@ -4408,7 +4407,7 @@ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveF // getArchiveFileByDiskFileId //------------------------------------------------------------------------------ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveFileByDiskFileId( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &diskFileId) const { try { @@ -4440,10 +4439,10 @@ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveF "WHERE " "ARCHIVE_FILE.DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND " "ARCHIVE_FILE.DISK_FILE_ID = :DISK_FILE_ID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindString(":DISK_INSTANCE_NAME", diskInstanceName); - stmt->bindString(":DISK_FILE_ID", diskFileId); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName); + stmt.bindString(":DISK_FILE_ID", diskFileId); + auto rset = stmt.executeQuery(); std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile; while (rset.next()) { if(nullptr == archiveFile.get()) { @@ -4493,8 +4492,8 @@ std::unique_ptr<common::dataStructures::ArchiveFile> RdbmsCatalogue::getArchiveF void RdbmsCatalogue::ping() { const char *const sql = "SELECT COUNT(*) FROM CTA_CATALOGUE"; auto conn = m_connPool.getConn(); - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); } //------------------------------------------------------------------------------ diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp index c2318545d96d3c20d090006cec5525241161f905..738b78b4b8cc7060ec8b37226dd2e5ca1f2835b1 100644 --- a/catalogue/RdbmsCatalogue.hpp +++ b/catalogue/RdbmsCatalogue.hpp @@ -21,8 +21,8 @@ #include "catalogue/Catalogue.hpp" #include "catalogue/RequesterAndGroupMountPolicies.hpp" #include "common/threading/Mutex.hpp" -#include "rdbms/Conn.hpp" #include "rdbms/ConnPool.hpp" +#include "rdbms/Login.hpp" #include <memory> @@ -62,7 +62,8 @@ protected: * Protected constructor only to be called by sub-classes. * * @param log Object representing the API to the CTA logging system. - * @param connFactory The factory for creating new database connections. + * @param login The database login details to be used to create new + * connections. * @param nbConns The maximum number of concurrent connections to the * underlying relational database for all operations accept listing archive * files which can be relatively long operations. @@ -72,7 +73,7 @@ protected: */ RdbmsCatalogue( log::Logger &log, - std::unique_ptr<rdbms::ConnFactory> connFactory, + const rdbms::Login &login, const uint64_t nbConns, const uint64_t nbArchiveFileListingConns); @@ -533,11 +534,6 @@ protected: */ threading::Mutex m_mutex; - /** - * The database connection factory. - */ - std::unique_ptr<rdbms::ConnFactory> m_connFactory; - /** * The pool of connections to the underlying relational database to be used * for all operations accept listing archive files which can be relatively @@ -558,7 +554,7 @@ protected: * @param adminUsername The name of the admin user. * @return True if the admin user exists. */ - bool adminUserExists(rdbms::PooledConn &conn, const std::string adminUsername) const; + bool adminUserExists(rdbms::Conn &conn, const std::string adminUsername) const; /** * Returns true if the specified admin host exists. @@ -567,7 +563,7 @@ protected: * @param adminHost The name of the admin host. * @return True if the admin host exists. */ - bool adminHostExists(rdbms::PooledConn &conn, const std::string adminHost) const; + bool adminHostExists(rdbms::Conn &conn, const std::string adminHost) const; /** * Returns true if the specified storage class exists. @@ -578,7 +574,7 @@ protected: * @param storageClassName The name of the storage class. * @return True if the storage class exists. */ - bool storageClassExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, const std::string &storageClassName) + bool storageClassExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName) const; /** @@ -596,7 +592,7 @@ protected: * @param tapePoolName The name of the tape pool. * @return True if the tape pool exists. */ - bool tapePoolExists(rdbms::PooledConn &conn, const std::string &tapePoolName) const; + bool tapePoolExists(rdbms::Conn &conn, const std::string &tapePoolName) const; /** * Returns true if the specified archive file identifier exists. @@ -605,7 +601,7 @@ protected: * @param archiveFileId The archive file identifier. * @return True if the archive file identifier exists. */ - bool archiveFileIdExists(rdbms::PooledConn &conn, const uint64_t archiveFileId) const; + bool archiveFileIdExists(rdbms::Conn &conn, const uint64_t archiveFileId) const; /** * Returns true if the specified disk file identifier exists. @@ -616,7 +612,7 @@ protected: * @param diskFileId The disk file identifier. * @return True if the disk file identifier exists. */ - bool diskFileIdExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, const std::string &diskFileId) const; + bool diskFileIdExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &diskFileId) const; /** * Returns true if the specified disk file path exists. @@ -627,7 +623,7 @@ protected: * @param diskFilePath The disk file path. * @return True if the disk file path exists. */ - bool diskFilePathExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, const std::string &diskFilePath) + bool diskFilePathExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &diskFilePath) const; /** @@ -639,7 +635,7 @@ protected: * @param diskFileUSer The name of the disk file user. * @return True if the disk file user exists. */ - bool diskFileUserExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, const std::string &diskFileUser) + bool diskFileUserExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &diskFileUser) const; /** @@ -651,7 +647,7 @@ protected: * @param diskFileGroup The name of the disk file group. * @return True if the disk file group exists. */ - bool diskFileGroupExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, const std::string &diskFileGroup) + bool diskFileGroupExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &diskFileGroup) const; /** @@ -665,7 +661,7 @@ protected: * @param copyNb The copy number of the tape file. * @return True if the archive route exists. */ - bool archiveRouteExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, const std::string &storageClassName, + bool archiveRouteExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName, const uint64_t copyNb) const; /** @@ -683,7 +679,7 @@ protected: * @param vid The volume identifier of the tape. * @return True if the tape exists. */ - bool tapeExists(rdbms::PooledConn &conn, const std::string &vid) const; + bool tapeExists(rdbms::Conn &conn, const std::string &vid) const; /** * Returns the list of tapes that meet the specified search criteria. @@ -692,7 +688,7 @@ protected: * @param searchCriteria The search criteria. * @return The list of tapes. */ - std::list<common::dataStructures::Tape> getTapes(rdbms::PooledConn &conn, const TapeSearchCriteria &searchCriteria) const; + std::list<common::dataStructures::Tape> getTapes(rdbms::Conn &conn, const TapeSearchCriteria &searchCriteria) const; /** * Returns true if the specified logical library exists. @@ -701,7 +697,7 @@ protected: * @param logicalLibraryName The name of the logical library. * @return True if the logical library exists. */ - bool logicalLibraryExists(rdbms::PooledConn &conn, const std::string &logicalLibraryName) const; + bool logicalLibraryExists(rdbms::Conn &conn, const std::string &logicalLibraryName) const; /** * Returns true if the specified mount policy exists. @@ -710,7 +706,7 @@ protected: * @param mountPolicyName The name of the mount policy * @return True if the mount policy exists. */ - bool mountPolicyExists(rdbms::PooledConn &conn, const std::string &mountPolicyName) const; + bool mountPolicyExists(rdbms::Conn &conn, const std::string &mountPolicyName) const; /** * Returns true if the specified requester mount-rule exists. @@ -721,7 +717,7 @@ protected: * to be unique within its disk instance. * @return True if the requester mount-rule exists. */ - bool requesterMountRuleExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, + bool requesterMountRuleExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterName) const; /** @@ -735,7 +731,7 @@ protected: * @return The mount policy or nullptr if one does not exists. */ common::dataStructures::MountPolicy *getRequesterMountPolicy( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterName) const; @@ -749,7 +745,7 @@ protected: * guaranteed to be unique within its disk instance. * @return True if the requester-group mount-rule exists. */ - bool requesterGroupMountRuleExists(rdbms::PooledConn &conn, const std::string &diskInstanceName, + bool requesterGroupMountRuleExists(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterGroupName) const; /** @@ -763,7 +759,7 @@ protected: * guaranteed to be unique within its disk instance. * @return The mount policy or nullptr if one does not exists. */ - common::dataStructures::MountPolicy *getRequesterGroupMountPolicy(rdbms::PooledConn &conn, + common::dataStructures::MountPolicy *getRequesterGroupMountPolicy(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterGroupName) const; /** @@ -787,7 +783,7 @@ protected: * @param autocommitMode The autocommit mode of the SQL insert statement. * @param row The row to be inserted. */ - void insertArchiveFile(rdbms::PooledConn &conn, const rdbms::Stmt::AutocommitMode autocommitMode, + void insertArchiveFile(rdbms::Conn &conn, const rdbms::AutocommitMode autocommitMode, const ArchiveFileRow &row); /** @@ -803,7 +799,7 @@ protected: * table. * @return true if the specified user name is listed in the ADMIN_USER table. */ - bool userIsAdmin(rdbms::PooledConn &conn, const std::string &userName) const; + bool userIsAdmin(rdbms::Conn &conn, const std::string &userName) const; /** * Returns true if the specified host name is listed in the ADMIN_HOST table. @@ -813,7 +809,7 @@ protected: * table. * @return true if the specified host name is listed in the ADMIN_HOST table. */ - bool hostIsAdmin(rdbms::PooledConn &conn, const std::string &userName) const; + bool hostIsAdmin(rdbms::Conn &conn, const std::string &userName) const; /** * Returns the expected number of archive routes for the specified storage @@ -828,7 +824,7 @@ protected: * guaranteed to be unique within its disk instance. * @return The expected number of archive routes. */ - uint64_t getExpectedNbArchiveRoutes(rdbms::PooledConn &conn, const std::string &diskInstanceName, + uint64_t getExpectedNbArchiveRoutes(rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassNAme) const; /** @@ -841,8 +837,8 @@ protected: * file is a copy. */ void insertTapeFile( - rdbms::PooledConn &conn, - const rdbms::Stmt::AutocommitMode autocommitMode, + rdbms::Conn &conn, + const rdbms::AutocommitMode autocommitMode, const common::dataStructures::TapeFile &tapeFile, const uint64_t archiveFileId); @@ -853,7 +849,7 @@ protected: * @param vid The volume identifier of the tape. * @param lastFseq The new value of the last FSeq. */ - void setTapeLastFSeq(rdbms::PooledConn &conn, const std::string &vid, const uint64_t lastFSeq); + void setTapeLastFSeq(rdbms::Conn &conn, const std::string &vid, const uint64_t lastFSeq); /** * Returns the last FSeq of the specified tape. @@ -862,7 +858,7 @@ protected: * @param vid The volume identifier of the tape. * @return The last FSeq. */ - uint64_t getTapeLastFSeq(rdbms::PooledConn &conn, const std::string &vid) const; + uint64_t getTapeLastFSeq(rdbms::Conn &conn, const std::string &vid) const; /** * Updates the specified tape with the specified information. @@ -877,8 +873,8 @@ protected: * @param tapeDrive The name of the tape drive that last wrote to the tape. */ void updateTape( - rdbms::PooledConn &conn, - const rdbms::Stmt::AutocommitMode autocommitMode, + rdbms::Conn &conn, + const rdbms::AutocommitMode autocommitMode, const std::string &vid, const uint64_t lastFSeq, const uint64_t compressedBytesWritten, @@ -894,7 +890,7 @@ protected: * an empty list. */ std::unique_ptr<common::dataStructures::ArchiveFile> getArchiveFileByArchiveFileId( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const uint64_t archiveFileId) const; /** @@ -912,7 +908,7 @@ protected: * an empty list. */ std::unique_ptr<common::dataStructures::ArchiveFile> getArchiveFileByDiskFileId( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const std::string &diskInstance, const std::string &diskFileId) const; @@ -929,7 +925,7 @@ protected: * @return The mount policies. */ RequesterAndGroupMountPolicies getMountPolicies( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &requesterName, const std::string &requesterGroupName) const; @@ -946,7 +942,7 @@ protected: * @return A unique archive ID that can be used by a new archive file within * the catalogue. */ - virtual uint64_t getNextArchiveFileId(rdbms::PooledConn &conn) = 0; + virtual uint64_t getNextArchiveFileId(rdbms::Conn &conn) = 0; /** * Returns the mapping from tape copy to tape pool for the specified storage @@ -961,7 +957,7 @@ protected: * class. */ common::dataStructures::TapeCopyToPoolMap getTapeCopyToPoolMap( - rdbms::PooledConn &conn, + rdbms::Conn &conn, const std::string &diskInstanceName, const std::string &storageClassName) const; diff --git a/catalogue/SchemaCreatingSqliteCatalogue.cpp b/catalogue/SchemaCreatingSqliteCatalogue.cpp index 1f3d9ef0aa9334a46f682050b2766c0bbe4ba90e..e492e78fb9e7146f972d76535482cdc3e4c7d8d0 100644 --- a/catalogue/SchemaCreatingSqliteCatalogue.cpp +++ b/catalogue/SchemaCreatingSqliteCatalogue.cpp @@ -18,8 +18,6 @@ #include "catalogue/SqliteCatalogueSchema.hpp" #include "catalogue/SchemaCreatingSqliteCatalogue.hpp" -#include "rdbms/SqliteConn.hpp" -#include "rdbms/SqliteConnFactory.hpp" namespace cta { namespace catalogue { diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp index e8b1241c2c09e978f1aeffe23958d25879000d9b..b923e49f71facba47e5d335dcf51427718d1487e 100644 --- a/catalogue/SqliteCatalogue.cpp +++ b/catalogue/SqliteCatalogue.cpp @@ -26,7 +26,6 @@ #include "common/Timer.hpp" #include "common/utils/utils.hpp" #include "rdbms/AutoRollback.hpp" -#include "rdbms/ConnFactoryFactory.hpp" namespace cta { namespace catalogue { @@ -41,7 +40,7 @@ SqliteCatalogue::SqliteCatalogue( const uint64_t nbArchiveFileListingConns): RdbmsCatalogue( log, - rdbms::ConnFactoryFactory::create(rdbms::Login(rdbms::Login::DBTYPE_SQLITE, "", "", filename)), + rdbms::Login(rdbms::Login::DBTYPE_SQLITE, "", "", filename), nbConns, nbArchiveFileListingConns) { } @@ -117,17 +116,17 @@ void SqliteCatalogue::deleteArchiveFile(const std::string &diskInstanceName, con t.reset(); { const char *const sql = "DELETE FROM TAPE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID;"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); + stmt.executeNonQuery(); } const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter); { const char *const sql = "DELETE FROM ARCHIVE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID;"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId); + stmt.executeNonQuery(); } const auto deleteFromArchiveFileTime = t.secs(utils::Timer::resetCounter); @@ -198,17 +197,17 @@ void SqliteCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInsta t.reset(); { const char *const sql = "DELETE FROM TAPE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID;"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFile->archiveFileID); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFile->archiveFileID); + stmt.executeNonQuery(); } const auto deleteFromTapeFileTime = t.secs(utils::Timer::resetCounter); { const char *const sql = "DELETE FROM ARCHIVE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID;"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFile->archiveFileID); - stmt->executeNonQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFile->archiveFileID); + stmt.executeNonQuery(); } const auto deleteFromArchiveFileTime = t.secs(utils::Timer::resetCounter); @@ -257,7 +256,7 @@ void SqliteCatalogue::deleteArchiveFileByDiskFileId(const std::string &diskInsta //------------------------------------------------------------------------------ // getNextArchiveFileId //------------------------------------------------------------------------------ -uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::PooledConn &conn) { +uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::Conn &conn) { try { // The SQLite implemenation of getNextArchiveFileId() serializes access to // the SQLite database in order to avoid busy errors @@ -265,7 +264,7 @@ uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::PooledConn &conn) { rdbms::AutoRollback autoRollback(conn); - conn.executeNonQuery("UPDATE ARCHIVE_FILE_ID SET ID = ID + 1", rdbms::Stmt::AutocommitMode::OFF); + conn.executeNonQuery("UPDATE ARCHIVE_FILE_ID SET ID = ID + 1", rdbms::AutocommitMode::OFF); uint64_t archiveFileId = 0; { const char *const sql = @@ -273,8 +272,8 @@ uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::PooledConn &conn) { "ID AS ID " "FROM " "ARCHIVE_FILE_ID"; - auto stmt = conn.createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); - auto rset = stmt->executeQuery(); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF); + auto rset = stmt.executeQuery(); if(!rset.next()) { throw exception::Exception("ARCHIVE_FILE_ID table is empty"); } @@ -294,8 +293,8 @@ uint64_t SqliteCatalogue::getNextArchiveFileId(rdbms::PooledConn &conn) { //------------------------------------------------------------------------------ // selectTapeForUpdate //------------------------------------------------------------------------------ -common::dataStructures::Tape SqliteCatalogue::selectTape(const rdbms::Stmt::AutocommitMode autocommitMode, - rdbms::PooledConn &conn, const std::string &vid) { +common::dataStructures::Tape SqliteCatalogue::selectTape(const rdbms::AutocommitMode autocommitMode, + rdbms::Conn &conn, const std::string &vid) { try { const char *const sql = "SELECT " @@ -334,8 +333,8 @@ common::dataStructures::Tape SqliteCatalogue::selectTape(const rdbms::Stmt::Auto "VID = :VID;"; auto stmt = conn.createStmt(sql, autocommitMode); - stmt->bindString(":VID", vid); - auto rset = stmt->executeQuery(); + stmt.bindString(":VID", vid); + auto rset = stmt.executeQuery(); if (!rset.next()) { throw exception::Exception(std::string("The tape with VID " + vid + " does not exist")); } @@ -407,7 +406,7 @@ void SqliteCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events threading::MutexLocker locker(m_mutex); auto conn = m_connPool.getConn(); - const auto tape = selectTape(rdbms::Stmt::AutocommitMode::ON, conn, firstEvent.vid); + const auto tape = selectTape(rdbms::AutocommitMode::ON, conn, firstEvent.vid); uint64_t expectedFSeq = tape.lastFSeq + 1; uint64_t totalCompressedBytesWritten = 0; @@ -432,11 +431,11 @@ void SqliteCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events auto lastEventItor = events.cend(); lastEventItor--; const TapeFileWritten &lastEvent = *lastEventItor; - updateTape(conn, rdbms::Stmt::AutocommitMode::ON, lastEvent.vid, lastEvent.fSeq, totalCompressedBytesWritten, + updateTape(conn, rdbms::AutocommitMode::ON, lastEvent.vid, lastEvent.fSeq, totalCompressedBytesWritten, lastEvent.tapeDrive); for(const auto &event : events) { - fileWrittenToTape(rdbms::Stmt::AutocommitMode::ON, conn, event); + fileWrittenToTape(rdbms::AutocommitMode::ON, conn, event); } } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -446,7 +445,7 @@ void SqliteCatalogue::filesWrittenToTape(const std::set<TapeFileWritten> &events //------------------------------------------------------------------------------ // fileWrittenToTape //------------------------------------------------------------------------------ -void SqliteCatalogue::fileWrittenToTape(const rdbms::Stmt::AutocommitMode autocommitMode, rdbms::PooledConn &conn, +void SqliteCatalogue::fileWrittenToTape(const rdbms::AutocommitMode autocommitMode, rdbms::Conn &conn, const TapeFileWritten &event) { try { checkTapeFileWrittenFieldsAreSet(event); diff --git a/catalogue/SqliteCatalogue.hpp b/catalogue/SqliteCatalogue.hpp index 86a6f49c970c7507a62dd6dc42a9d601109f6e70..a1d8d966d7f856f39ab7fb123f1deb3026e976ee 100644 --- a/catalogue/SqliteCatalogue.hpp +++ b/catalogue/SqliteCatalogue.hpp @@ -116,7 +116,7 @@ protected: * @return A unique archive ID that can be used by a new archive file within * the catalogue. */ - uint64_t getNextArchiveFileId(rdbms::PooledConn &conn) override; + uint64_t getNextArchiveFileId(rdbms::Conn &conn) override; /** * Notifies the catalogue that the specified files have been written to tape. @@ -134,7 +134,7 @@ private: * @param conn The database connection. * @param event The tape file written event. */ - void fileWrittenToTape(const rdbms::Stmt::AutocommitMode autocommitMode, rdbms::PooledConn &conn, + void fileWrittenToTape(const rdbms::AutocommitMode autocommitMode, rdbms::Conn &conn, const TapeFileWritten &event); /** @@ -144,7 +144,7 @@ private: * @param conn The database connection. * @param vid The volume identifier of the tape. */ - common::dataStructures::Tape selectTape(const rdbms::Stmt::AutocommitMode autocommitMode, rdbms::PooledConn &conn, + common::dataStructures::Tape selectTape(const rdbms::AutocommitMode autocommitMode, rdbms::Conn &conn, const std::string &vid); }; // class SqliteCatalogue diff --git a/cta.spec.in b/cta.spec.in index 647cc3d133616bb6e775b142cb13c5020e2f88a6..ad1893c7d993461cd0f085ba641ee911ea33ae57 100644 --- a/cta.spec.in +++ b/cta.spec.in @@ -202,6 +202,7 @@ The shared libraries %{_libdir}/libctamessages.so* %{_libdir}/libctamessagesutils.so* %{_libdir}/libctardbms.so* +%{_libdir}/libctardbmswrapper.so* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/cta/cta-catalogue.conf.example #CTA-lib installs libraries so we need ldconfig. @@ -232,6 +233,7 @@ Unit tests and system tests with virtual tape drives %{_libdir}/libctainmemorycatalogueunittests.so* %{_libdir}/libctaobjectstoreunittests.so* %{_libdir}/libctardbmsunittests.so* +%{_libdir}/libctardbmswrapperunittests.so* %{_libdir}/libctaschedulerunittests.so* %{_libdir}/libctatapeserverdaemonunittests.so* %{_libdir}/libctatapeserverdriveunittests.so* diff --git a/rdbms/AutoRollback.cpp b/rdbms/AutoRollback.cpp index d205f54dd0f4238fa09ab28087782628a0b59ad3..9cfb642497c9169ae27cf176f4bdf7e8586636aa 100644 --- a/rdbms/AutoRollback.cpp +++ b/rdbms/AutoRollback.cpp @@ -18,7 +18,7 @@ #include "common/exception/Exception.hpp" #include "rdbms/AutoRollback.hpp" -#include "rdbms/PooledConn.hpp" +#include "rdbms/Conn.hpp" namespace cta { namespace rdbms { @@ -26,7 +26,7 @@ namespace rdbms { //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -AutoRollback::AutoRollback(PooledConn &conn): +AutoRollback::AutoRollback(Conn &conn): m_cancelled(false), m_conn(conn) { } diff --git a/rdbms/AutoRollback.hpp b/rdbms/AutoRollback.hpp index 155aa4da5efa7a6f6e5347fe924a451fa831ab57..5d7af16d867e4193688143fff9a832914129adf1 100644 --- a/rdbms/AutoRollback.hpp +++ b/rdbms/AutoRollback.hpp @@ -24,7 +24,7 @@ namespace rdbms { /** * Forward declaration. */ -class PooledConn; +class Conn; /** * A class to automatically rollback a database connection when an instance of @@ -38,7 +38,7 @@ public: * * @param conn The database connection. */ - AutoRollback(PooledConn &conn); + AutoRollback(Conn &conn); /** * Prevent copying. @@ -72,7 +72,7 @@ private: /** * The database connection or nullptr if no rollback should take place. */ - PooledConn &m_conn; + Conn &m_conn; }; // class Login diff --git a/rdbms/AutocommitMode.hpp b/rdbms/AutocommitMode.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6d392f1a86d7d5de09e7a5ac385c8227cc61a369 --- /dev/null +++ b/rdbms/AutocommitMode.hpp @@ -0,0 +1,33 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +namespace cta { +namespace rdbms { + +/** + * A database statement can either have auto commiting mode turned on or off. + */ +enum class AutocommitMode { + ON, + OFF +}; + +} // namespace rdbms +} // namespace cta diff --git a/rdbms/CMakeLists.txt b/rdbms/CMakeLists.txt index 3a4143140df1961acd071a2c90e94bfc10c096da..70dea64e10858cfc58ea0711a2194838e10fec42 100644 --- a/rdbms/CMakeLists.txt +++ b/rdbms/CMakeLists.txt @@ -15,70 +15,33 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. cmake_minimum_required (VERSION 2.6) +add_subdirectory (wrapper) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") find_package (sqlite REQUIRED) +find_package (oracle-instantclient REQUIRED) -if(OCCI_SUPPORT) - find_package (oracle-instantclient REQUIRED) - include_directories (${ORACLE-INSTANTCLIENT_INCLUDE_DIRS}) -endif(OCCI_SUPPORT) +include_directories (${ORACLE-INSTANTCLIENT_INCLUDE_DIRS}) set (RDBMS_LIB_SRC_FILES AutoRollback.cpp - ColumnNameToIdx.cpp - ColumnNameToIdxAndType.cpp Conn.cpp - ConnFactory.cpp ConnPool.cpp Login.cpp LoginFactory.cpp + NullDbValue.cpp Rset.cpp - RsetImpl.cpp Stmt.cpp - NullDbValue.cpp - ParamNameToIdx.cpp - PooledConn.cpp - Sqlite.cpp - SqliteConn.cpp - SqliteConnFactory.cpp - SqliteRsetImpl.cpp - SqliteStmt.cpp) - -if (OCCI_SUPPORT) - set (RDBMS_LIB_SRC_FILES - ${RDBMS_LIB_SRC_FILES} - ConnFactoryFactory.cpp - OcciColumn.cpp - OcciConn.cpp - OcciConnFactory.cpp - OcciEnv.cpp - OcciEnvSingleton.cpp - OcciRsetImpl.cpp - OcciStmt.cpp) -else (OCCI_SUPPORT) - set (RDBMS_LIB_SRC_FILES - ${RDBMS_LIB_SRC_FILES} - ConnFactoryFactory_OCCI_SUPPORT_OFF.cpp) -endif (OCCI_SUPPORT) + StmtPool.cpp) add_library (ctardbms SHARED ${RDBMS_LIB_SRC_FILES}) set_property(TARGET ctardbms PROPERTY SOVERSION "${CTA_SOVERSION}") set_property(TARGET ctardbms PROPERTY VERSION "${CTA_LIBVERSION}") -set (CTARDBMS_LINK_LIBRARIES - ctacommon - ${SQLITE_LIBRARIES}) - -if (OCCI_SUPPORT) - set (CTARDBMS_LINK_LIBRARIES - ${CTARDBMS_LINK_LIBRARIES} - ${ORACLE-INSTANTCLIENT_LIBRARIES}) -endif (OCCI_SUPPORT) - target_link_libraries (ctardbms - ${CTARDBMS_LINK_LIBRARIES}) + ctardbmswrapper) install (TARGETS ctardbms DESTINATION usr/${CMAKE_INSTALL_LIBDIR}) @@ -86,12 +49,7 @@ set(RDBMS_UNIT_TESTS_LIB_SRC_FILES ConnPoolTest.cpp ConnTest.cpp LoginTest.cpp - ParamNameToIdxTest.cpp - SqliteStmtTest.cpp) - -if (OCCI_SUPPORT) - list (APPEND RDBMS_UNIT_TESTS_LIB_SRC_FILES OcciColumnTest.cpp) -endif (OCCI_SUPPORT) + StmtPoolTest.cpp) add_library (ctardbmsunittests SHARED ${RDBMS_UNIT_TESTS_LIB_SRC_FILES}) diff --git a/rdbms/Conn.cpp b/rdbms/Conn.cpp index f70c14b855d45147253aa655e85826fc8f7cd47e..9e92793189701796c1f536c039f6c666dd2da311 100644 --- a/rdbms/Conn.cpp +++ b/rdbms/Conn.cpp @@ -17,18 +17,72 @@ */ #include "common/exception/Exception.hpp" -#include "common/utils/utils.hpp" +#include "common/utils/utils.cpp" +#include "rdbms/ConnPool.hpp" #include "rdbms/Conn.hpp" -#include <string> - namespace cta { namespace rdbms { +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +Conn::Conn(std::unique_ptr<ConnAndStmts> connAndStmts, ConnPool *pool): + m_connAndStmts(std::move(connAndStmts)), + m_pool(pool) { +} + +//------------------------------------------------------------------------------ +// move constructor +//------------------------------------------------------------------------------ +Conn::Conn(Conn &&other): + m_connAndStmts(std::move(other.m_connAndStmts)), + m_pool(other.m_pool) { + other.m_pool = nullptr; +} + //------------------------------------------------------------------------------ // destructor //------------------------------------------------------------------------------ -Conn::~Conn() throw() { +Conn::~Conn() noexcept { + try { + // If this smart database connection currently points to a database connection then return it back to its pool + if(nullptr != m_pool && nullptr != m_connAndStmts) { + m_pool->returnConn(std::move(m_connAndStmts)); + } + } catch(...) { + } +} + +//------------------------------------------------------------------------------ +// operator= +//------------------------------------------------------------------------------ +Conn &Conn::operator=(Conn &&rhs) { + // If the database connection is not the one already owned + if(rhs.m_connAndStmts != m_connAndStmts) { + // If this smart database connection currently points to a database connection then return it back to its pool + if(nullptr != m_pool && nullptr != m_connAndStmts && nullptr != m_connAndStmts->conn) { + m_pool->returnConn(std::move(m_connAndStmts)); + } + + // Take ownership of the new database connection + m_connAndStmts = std::move(rhs.m_connAndStmts); + m_pool = rhs.m_pool; + + rhs.m_pool = nullptr; + } + return *this; +} + +//------------------------------------------------------------------------------ +// createStmt +//------------------------------------------------------------------------------ +Stmt Conn::createStmt(const std::string &sql, const AutocommitMode autocommitMode) { + if(nullptr != m_connAndStmts && nullptr != m_connAndStmts->conn) { + return m_connAndStmts->stmtPool->getStmt(*m_connAndStmts->conn, sql, autocommitMode); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Conn does not contain a connection"); + } } //------------------------------------------------------------------------------ @@ -46,7 +100,7 @@ void Conn::executeNonQueries(const std::string &sqlStmts) { searchPos = findResult + 1; if(0 < sqlStmt.size()) { // Ignore empty statements - executeNonQuery(sqlStmt, rdbms::Stmt::AutocommitMode::ON); + executeNonQuery(sqlStmt, AutocommitMode::ON); } } @@ -58,14 +112,69 @@ void Conn::executeNonQueries(const std::string &sqlStmts) { //------------------------------------------------------------------------------ // executeNonQuery //------------------------------------------------------------------------------ -void Conn::executeNonQuery(const std::string &sql, const Stmt::AutocommitMode autocommitMode) { +void Conn::executeNonQuery(const std::string &sql, const AutocommitMode autocommitMode) { try { auto stmt = createStmt(sql, autocommitMode); - stmt->executeNonQuery(); + stmt.executeNonQuery(); } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.what()); } } +//------------------------------------------------------------------------------ +// commit +//------------------------------------------------------------------------------ +void Conn::commit() { + if(nullptr != m_connAndStmts && nullptr != m_connAndStmts->conn) { + m_connAndStmts->conn->commit(); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Conn does not contain a connection"); + } +} + +//------------------------------------------------------------------------------ +// commit +//------------------------------------------------------------------------------ +void Conn::rollback() { + if(nullptr != m_connAndStmts && nullptr != m_connAndStmts->conn) { + m_connAndStmts->conn->rollback(); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Conn does not contain a connection"); + } +} + +//------------------------------------------------------------------------------ +// getTableNames +//------------------------------------------------------------------------------ +std::list<std::string> Conn::getTableNames() { + if(nullptr != m_connAndStmts && nullptr != m_connAndStmts->conn) { + return m_connAndStmts->conn->getTableNames(); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Conn does not contain a connection"); + } +} + +//------------------------------------------------------------------------------ +// isOpen +//------------------------------------------------------------------------------ +bool Conn::isOpen() const { + if(nullptr != m_connAndStmts && nullptr != m_connAndStmts->conn) { + return m_connAndStmts->conn->isOpen(); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Conn does not contain a connection"); + } +} + +//------------------------------------------------------------------------------ +// getSequenceNames +//------------------------------------------------------------------------------ +std::list<std::string> Conn::getSequenceNames() { + if(nullptr != m_connAndStmts && nullptr != m_connAndStmts->conn) { + return m_connAndStmts->conn->getSequenceNames(); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Conn does not contain a connection"); + } +} + } // namespace rdbms } // namespace cta diff --git a/rdbms/Conn.hpp b/rdbms/Conn.hpp index ac2740b90956e986c5efae66ac0031d32867b290..3d66a4fcc49832aec54d6c985db9adb183c89840 100644 --- a/rdbms/Conn.hpp +++ b/rdbms/Conn.hpp @@ -18,31 +18,65 @@ #pragma once -#include "Stmt.hpp" +#include "rdbms/ConnAndStmts.hpp" +#include "rdbms/Stmt.hpp" -#include <atomic> #include <list> #include <memory> -#include <string> namespace cta { namespace rdbms { +class ConnPool; + /** - * Abstract class that specifies the interface to a database connection. + * A smart database connection that will automatically return the underlying + * database connection to its parent connection pool when it goes out of scope. */ class Conn { public: + /** + * Constructor. + * + * @param connAndStmts The database connection and its pool of prepared + * statements. + * @param pool The database connection pool to which the connection + * should be returned. + */ + Conn(std::unique_ptr<ConnAndStmts> connAndStmts, ConnPool *const pool); + + /** + * Deletion of the copy constructor. + */ + Conn(Conn &) = delete; + + /** + * Move constructor. + * + * @param other The other object. + */ + Conn(Conn &&other); + /** * Destructor. + * + * Returns the database connection back to its pool. */ - virtual ~Conn() throw() = 0; + ~Conn() noexcept; /** - * Idempotent close() method. The destructor calls this method. + * Deletion of the copy assignment operator. */ - virtual void close() = 0; + Conn &operator=(const Conn &) = delete; + + /** + * Move assignment operator. + * + * @param rhs The object on the right-hand side of the operator. + * @return This object. + */ + Conn &operator=(Conn &&rhs); /** * Creates a prepared statement. @@ -51,7 +85,7 @@ public: * @param autocommitMode The autocommit mode of the statement. * @return The prepared statement. */ - virtual std::unique_ptr<Stmt> createStmt(const std::string &sql, const Stmt::AutocommitMode autocommitMode) = 0; + Stmt createStmt(const std::string &sql, const AutocommitMode autocommitMode); /** * Convenience method that parses the specified string of multiple SQL @@ -73,17 +107,17 @@ public: * @param sql The SQL statement. * @param autocommitMode The autocommit mode of the statement. */ - void executeNonQuery(const std::string &sql, const Stmt::AutocommitMode autocommitMode); + void executeNonQuery(const std::string &sql, const AutocommitMode autocommitMode); /** * Commits the current transaction. */ - virtual void commit() = 0; + void commit(); /** * Rolls back the current transaction. */ - virtual void rollback() = 0; + void rollback(); /** * Returns the names of all the tables in the database schema in alphabetical @@ -92,12 +126,36 @@ public: * @return The names of all the tables in the database schema in alphabetical * order. */ - virtual std::list<std::string> getTableNames() = 0; + std::list<std::string> getTableNames(); /** * Returns true if this connection is open. */ - virtual bool isOpen() const = 0; + bool isOpen() const; + + /** + * Returns the names of all the sequences in the database schema in + * alphabetical order. + * + * If the underlying database technologies does not supported sequences then + * this method simply returns an empty list. + * + * @return The names of all the sequences in the database schema in + * alphabetical order. + */ + std::list<std::string> getSequenceNames(); + +private: + + /** + * The database connection and its pool of prepared statements. + */ + std::unique_ptr<ConnAndStmts> m_connAndStmts; + + /** + * The database connection pool to which the m_conn should be returned. + */ + ConnPool *m_pool; }; // class Conn diff --git a/rdbms/ConnAndStmts.hpp b/rdbms/ConnAndStmts.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b5aa5d20dd84043fb70e86493a0be1b38b99cbdd --- /dev/null +++ b/rdbms/ConnAndStmts.hpp @@ -0,0 +1,98 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "rdbms/StmtPool.hpp" +#include "rdbms/wrapper/Conn.hpp" + +#include <iostream> +#include <memory> + +namespace cta { +namespace rdbms { + +/** + * Class to enforce prepared statements are destroyed before their corresponding + * database connection. + */ +struct ConnAndStmts { + + /** + * Constructor. + */ + ConnAndStmts() { + } + + /** + * Deletion of the copy constructor. + */ + ConnAndStmts(ConnAndStmts &) = delete; + + /** + * Move constructor. + * + * @param other The other object. + */ + ConnAndStmts(ConnAndStmts &&other): + conn(std::move(other.conn)), + stmtPool(std::move(other.stmtPool)) { + } + + /** + * Equality operator. + * + * @param rhs The object on the right hand side of the operator. + * @return True if equal. + */ + bool operator==(const ConnAndStmts &rhs) { + return conn.get() == rhs.conn.get(); + } + + /** + * Inequality operator. + * + * @param rhs The object on the right hand side of the operator. + * @return True if not equal. + */ + bool operator!=(const ConnAndStmts &rhs) { + return !operator==(rhs); + } + + /** + * The database connection. + * + * The database connection must be destroyed after all of its corresponding + * prepared statements. This means the conn member-variable must be declared + * before the stmtPool member-variable. + */ + std::unique_ptr<wrapper::Conn> conn; + + /** + * Pool of prepared statements. + * + * The prepared statements must be destroyed before their corresponding + * database connection. This means the stmtPool member-variable must be + * declared after the conn member-variable. + */ + std::unique_ptr<StmtPool> stmtPool; + +}; // class ConnAndStmts + +} // namespace rdbms +} // namespace cta diff --git a/rdbms/ConnPool.cpp b/rdbms/ConnPool.cpp index 0be866bc728dcbbd7a2f72c103516a07bce4bc48..f8f80d56acdbf61434bc1a25f90043bb8c28eea5 100644 --- a/rdbms/ConnPool.cpp +++ b/rdbms/ConnPool.cpp @@ -17,8 +17,10 @@ */ #include "common/exception/Exception.hpp" +#include "common/make_unique.hpp" #include "common/threading/MutexLocker.hpp" #include "rdbms/ConnPool.hpp" +#include "rdbms/wrapper/ConnFactoryFactory.hpp" #include <memory> @@ -28,15 +30,10 @@ namespace rdbms { //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -ConnPool::ConnPool(ConnFactory &connFactory, const uint64_t maxNbConns): - m_connFactory(connFactory), +ConnPool::ConnPool(const Login &login, const uint64_t maxNbConns): + m_connFactory(wrapper::ConnFactoryFactory::create(login)), m_maxNbConns(maxNbConns), - m_nbConnsOnLoan(0) { - try { - createConns(m_maxNbConns); - } catch(exception::Exception &ex) { - throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); - } + m_nbConnsOnLoan(0){ } //------------------------------------------------------------------------------ @@ -45,7 +42,10 @@ ConnPool::ConnPool(ConnFactory &connFactory, const uint64_t maxNbConns): void ConnPool::createConns(const uint64_t nbConns) { try { for(uint64_t i = 0; i < nbConns; i++) { - m_conns.push_back(m_connFactory.create()); + auto connAndStmts = cta::make_unique<ConnAndStmts>(); + connAndStmts->conn = m_connFactory->create(); + connAndStmts->stmtPool = cta::make_unique<StmtPool>(); + m_connsAndStmts.push_back(std::move(connAndStmts)); } } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -55,42 +55,50 @@ void ConnPool::createConns(const uint64_t nbConns) { //------------------------------------------------------------------------------ // getConn //------------------------------------------------------------------------------ -PooledConn ConnPool::getConn() { - threading::MutexLocker locker(m_connsMutex); +Conn ConnPool::getConn() { + threading::MutexLocker locker(m_connsAndStmtsMutex); - while(m_conns.size() == 0 && m_nbConnsOnLoan == m_maxNbConns) { - m_connsCv.wait(locker); + while(m_connsAndStmts.size() == 0 && m_nbConnsOnLoan == m_maxNbConns) { + m_connsAndStmtsCv.wait(locker); } - if(m_conns.size() == 0) { - m_conns.push_back(m_connFactory.create()); + if(m_connsAndStmts.size() == 0) { + auto connAndStmts = cta::make_unique<ConnAndStmts>(); + connAndStmts->conn = m_connFactory->create(); + connAndStmts->stmtPool = cta::make_unique<StmtPool>(); + m_connsAndStmts.push_back(std::move(connAndStmts)); } - std::unique_ptr<Conn> conn = std::move(m_conns.front()); - m_conns.pop_front(); + std::unique_ptr<ConnAndStmts> connAndStmts = std::move(m_connsAndStmts.front()); + m_connsAndStmts.pop_front(); m_nbConnsOnLoan++; - if(conn->isOpen()) { - return PooledConn(std::move(conn), this); + if(connAndStmts->conn->isOpen()) { + return Conn(std::move(connAndStmts), this); } else { - return PooledConn(m_connFactory.create(), this); + auto newConnAndStmts = cta::make_unique<ConnAndStmts>(); + newConnAndStmts->conn = m_connFactory->create(); + newConnAndStmts->stmtPool = cta::make_unique<StmtPool>(); + return Conn(std::move(newConnAndStmts), this); } } //------------------------------------------------------------------------------ // returnConn //------------------------------------------------------------------------------ -void ConnPool::returnConn(std::unique_ptr<Conn> conn) { +void ConnPool::returnConn(std::unique_ptr<ConnAndStmts> connAndStmts) { try { // If the connection is open - if(conn->isOpen()) { + if(connAndStmts->conn->isOpen()) { // Try to commit the connection and put it back in the pool try { - conn->commit(); + connAndStmts->conn->commit(); } catch(...) { - // If the commit failed then close the connection + // If the commit failed then destroy any prepare statements and then + // close the connection try { - conn->close(); + connAndStmts->stmtPool->clear(); + connAndStmts->conn->close(); } catch(...) { // Ignore any exceptions } @@ -99,25 +107,25 @@ void ConnPool::returnConn(std::unique_ptr<Conn> conn) { // connection, if there is one, has been lost. Delete all the connections // currently in the pool because their underlying TCP/IP connections may // also have been lost. - threading::MutexLocker locker(m_connsMutex); - while(!m_conns.empty()) { - m_conns.pop_front(); + threading::MutexLocker locker(m_connsAndStmtsMutex); + while(!m_connsAndStmts.empty()) { + m_connsAndStmts.pop_front(); } if(0 == m_nbConnsOnLoan) { throw exception::Exception("Would have reached -1 connections on loan"); } m_nbConnsOnLoan--; - m_connsCv.signal(); + m_connsAndStmtsCv.signal(); return; } - threading::MutexLocker locker(m_connsMutex); + threading::MutexLocker locker(m_connsAndStmtsMutex); if(0 == m_nbConnsOnLoan) { throw exception::Exception("Would have reached -1 connections on loan"); } m_nbConnsOnLoan--; - m_conns.push_back(std::move(conn)); - m_connsCv.signal(); + m_connsAndStmts.push_back(std::move(connAndStmts)); + m_connsAndStmtsCv.signal(); // Else the connection is closed } else { @@ -126,15 +134,15 @@ void ConnPool::returnConn(std::unique_ptr<Conn> conn) { // connection, if there is one, has been lost. Delete all the connections // currently in the pool because their underlying TCP/IP connections may // also have been lost. - threading::MutexLocker locker(m_connsMutex); - while(!m_conns.empty()) { - m_conns.pop_front(); + threading::MutexLocker locker(m_connsAndStmtsMutex); + while(!m_connsAndStmts.empty()) { + m_connsAndStmts.pop_front(); } if(0 == m_nbConnsOnLoan) { throw exception::Exception("Would have reached -1 connections on loan"); } m_nbConnsOnLoan--; - m_connsCv.signal(); + m_connsAndStmtsCv.signal(); } } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); diff --git a/rdbms/ConnPool.hpp b/rdbms/ConnPool.hpp index 98917197e54506ab671f18b06b04c6876ad879d2..76344d0238f1b5ff99e9d2f65239691010723587 100644 --- a/rdbms/ConnPool.hpp +++ b/rdbms/ConnPool.hpp @@ -20,9 +20,10 @@ #include "common/threading/CondVar.hpp" #include "common/threading/Mutex.hpp" +#include "rdbms/ConnAndStmts.hpp" #include "rdbms/Conn.hpp" -#include "rdbms/ConnFactory.hpp" -#include "rdbms/PooledConn.hpp" +#include "rdbms/wrapper/Conn.hpp" +#include "rdbms/wrapper/ConnFactory.hpp" #include <list> #include <memory> @@ -30,6 +31,8 @@ namespace cta { namespace rdbms { +class Login; + /** * A pool of database connections. */ @@ -39,11 +42,12 @@ public: /** * Constructor. * - * @param connFactory The database connection factory. + * @param login The database login details to be used to create new + * connections. * @param maxNbConns The maximum number of database connections within the * pool. */ - ConnPool(ConnFactory &connFactory, const uint64_t maxNbConns); + ConnPool(const Login &login, const uint64_t maxNbConns); /** * Takes a connection from the pool. @@ -54,11 +58,11 @@ public: * * @return A connection from the pool. */ - PooledConn getConn(); + Conn getConn(); private: - friend PooledConn; + friend Conn; /** * If the specified database connection is open, then this method calls @@ -69,14 +73,14 @@ private: * * A closed connection is reopened when it is pulled from the pool. * - * @param conn The connection to be commited and returned to the pool. + * @param connAndStmts The connection to be commited and returned to the pool. */ - void returnConn(std::unique_ptr<Conn> conn); + void returnConn(std::unique_ptr<ConnAndStmts> connAndStmts); /** * The database connection factory. */ - ConnFactory &m_connFactory; + std::unique_ptr<wrapper::ConnFactory> m_connFactory; /** * The maximum number of database connections within the pool. @@ -91,18 +95,18 @@ private: /** * Mutex used to serialize access to the database connections within the pool. */ - threading::Mutex m_connsMutex; + threading::Mutex m_connsAndStmtsMutex; /** * Condition variable used by threads returning connections to the pool to * notify threads waiting for connections. */ - threading::CondVar m_connsCv; + threading::CondVar m_connsAndStmtsCv; /** * The database connections within the pool. */ - std::list< std::unique_ptr<Conn> > m_conns; + std::list<std::unique_ptr<ConnAndStmts> > m_connsAndStmts; /** * Creates the specified number of database connections with the pool. diff --git a/rdbms/ConnPoolTest.cpp b/rdbms/ConnPoolTest.cpp index e3a4b9d7c0870525a4f457e76d825a2c2eb35ccd..93d2d617abb1aee6edac2c8095db7e4a447202af 100644 --- a/rdbms/ConnPoolTest.cpp +++ b/rdbms/ConnPoolTest.cpp @@ -17,11 +17,10 @@ */ #include "common/exception/Exception.hpp" -#include "rdbms/ConnFactoryFactory.hpp" #include "rdbms/ConnPool.hpp" +#include "rdbms/Login.hpp" #include <gtest/gtest.h> -#include <sstream> namespace unitTests { @@ -39,24 +38,22 @@ TEST_F(cta_rdbms_ConnPoolTest, getPooledConn) { using namespace cta::rdbms; const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); - auto connFactory = ConnFactoryFactory::create(login); const uint64_t nbConns = 2; - ConnPool pool(*connFactory, nbConns); + ConnPool pool(login, nbConns); - PooledConn conn = pool.getConn(); + Conn conn = pool.getConn(); } TEST_F(cta_rdbms_ConnPoolTest, assignment) { using namespace cta::rdbms; const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); - auto connFactory = ConnFactoryFactory::create(login); const uint64_t nbConns = 2; - ConnPool pool(*connFactory, nbConns); + ConnPool pool(login, nbConns); - PooledConn conn = pool.getConn(); + Conn conn = pool.getConn(); - PooledConn conn2(nullptr, nullptr); + Conn conn2(nullptr, nullptr); conn2 = pool.getConn(); } @@ -65,13 +62,12 @@ TEST_F(cta_rdbms_ConnPoolTest, moveConstructor) { using namespace cta::rdbms; const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); - auto connFactory = ConnFactoryFactory::create(login); const uint64_t nbConns = 2; - ConnPool pool(*connFactory, nbConns); + ConnPool pool(login, nbConns); - PooledConn conn = pool.getConn(); + Conn conn = pool.getConn(); - PooledConn conn2(std::move(conn)); + Conn conn2(std::move(conn)); } } // namespace unitTests diff --git a/rdbms/ConnTest.cpp b/rdbms/ConnTest.cpp index 0d0a953b915884c09493bf3fba165df61c0d7cef..322e893ee37c7d1c8f60d8985fc7777db804fea7 100644 --- a/rdbms/ConnTest.cpp +++ b/rdbms/ConnTest.cpp @@ -17,11 +17,10 @@ */ #include "common/exception/Exception.hpp" -#include "rdbms/ConnFactoryFactory.hpp" #include "rdbms/ConnPool.hpp" +#include "rdbms/Login.hpp" #include <gtest/gtest.h> -#include <sstream> namespace unitTests { @@ -35,6 +34,45 @@ protected: } }; +TEST_F(cta_rdbms_ConnTest, createTableInMemoryDatabase_executeNonQuery) { + using namespace cta::rdbms; + + const std::string sql = "CREATE TABLE POOLED_STMT_TEST(ID INTEGER)"; + + { + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + const uint64_t maxNbConns = 1; + ConnPool connPool(login, maxNbConns); + auto conn = connPool.getConn(); + + ASSERT_TRUE(conn.getTableNames().empty()); + + conn.executeNonQuery(sql, AutocommitMode::ON); + + ASSERT_EQ(1, conn.getTableNames().size()); + } +} + +TEST_F(cta_rdbms_ConnTest, createTableInMemoryDatabase_executeNonQueries) { + using namespace cta::rdbms; + + const std::string sql = "CREATE TABLE POOLED_STMT_TEST(ID INTEGER);"; + + // First in-memory database + { + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + const uint64_t maxNbConns = 1; + ConnPool connPool(login, maxNbConns); + auto conn = connPool.getConn(); + + ASSERT_TRUE(conn.getTableNames().empty()); + + conn.executeNonQueries(sql); + + ASSERT_EQ(1, conn.getTableNames().size()); + } +} + TEST_F(cta_rdbms_ConnTest, createSameTableInTwoSeparateInMemoryDatabases_executeNonQuery) { using namespace cta::rdbms; @@ -43,27 +81,29 @@ TEST_F(cta_rdbms_ConnTest, createSameTableInTwoSeparateInMemoryDatabases_execute // First in-memory database { const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); - auto connFactory = ConnFactoryFactory::create(login); - auto conn = connFactory->create(); + const uint64_t maxNbConns = 1; + ConnPool connPool(login, maxNbConns); + auto conn = connPool.getConn(); - ASSERT_TRUE(conn->getTableNames().empty()); + ASSERT_TRUE(conn.getTableNames().empty()); - conn->executeNonQuery(sql, Stmt::AutocommitMode::ON); + conn.executeNonQuery(sql, AutocommitMode::ON); - ASSERT_EQ(1, conn->getTableNames().size()); + ASSERT_EQ(1, conn.getTableNames().size()); } // Second in-memory database { const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); - auto connFactory = ConnFactoryFactory::create(login); - auto conn = connFactory->create(); + const uint64_t maxNbConns = 1; + ConnPool connPool(login, maxNbConns); + auto conn = connPool.getConn(); - ASSERT_TRUE(conn->getTableNames().empty()); + ASSERT_TRUE(conn.getTableNames().empty()); - conn->executeNonQuery(sql, Stmt::AutocommitMode::ON); + conn.executeNonQuery(sql, AutocommitMode::ON); - ASSERT_EQ(1, conn->getTableNames().size()); + ASSERT_EQ(1, conn.getTableNames().size()); } } @@ -75,27 +115,29 @@ TEST_F(cta_rdbms_ConnTest, createSameTableInTwoSeparateInMemoryDatabases_execute // First in-memory database { const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); - auto connFactory = ConnFactoryFactory::create(login); - auto conn = connFactory->create(); + const uint64_t maxNbConns = 1; + ConnPool connPool(login, maxNbConns); + auto conn = connPool.getConn(); - ASSERT_TRUE(conn->getTableNames().empty()); + ASSERT_TRUE(conn.getTableNames().empty()); - conn->executeNonQueries(sql); + conn.executeNonQueries(sql); - ASSERT_EQ(1, conn->getTableNames().size()); + ASSERT_EQ(1, conn.getTableNames().size()); } // Second in-memory database { const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); - auto connFactory = ConnFactoryFactory::create(login); - auto conn = connFactory->create(); + const uint64_t maxNbConns = 1; + ConnPool connPool(login, maxNbConns); + auto conn = connPool.getConn(); - ASSERT_TRUE(conn->getTableNames().empty()); + ASSERT_TRUE(conn.getTableNames().empty()); - conn->executeNonQueries(sql); + conn.executeNonQueries(sql); - ASSERT_EQ(1, conn->getTableNames().size()); + ASSERT_EQ(1, conn.getTableNames().size()); } } diff --git a/rdbms/Login.cpp b/rdbms/Login.cpp index 25faa7389a7caac4c8eb750b1b7798757b5346d7..ee024f732e95b35f9d3eac1ef8d37cc08dfd53c2 100644 --- a/rdbms/Login.cpp +++ b/rdbms/Login.cpp @@ -16,9 +16,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Login.hpp" #include "common/exception/Exception.hpp" #include "common/utils/utils.hpp" +#include "Login.hpp" #include <fstream> @@ -153,5 +153,5 @@ Login Login::parseOracleUserPassAndDb(const std::string &userPassAndDb) { return Login(DBTYPE_ORACLE, user, pass, db); } -} // namesapce catalogue +} // namespace catalogue } // namespace cta diff --git a/rdbms/LoginFactory.cpp b/rdbms/LoginFactory.cpp index d1acb5436bae67310aa4e78344ddfd5d3dda91db..b5eeb17b990a2d390736f43c766716c5c48ca7d4 100644 --- a/rdbms/LoginFactory.cpp +++ b/rdbms/LoginFactory.cpp @@ -16,7 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "LoginFactory.hpp" +#include "rdbms/LoginFactory.hpp" namespace cta { namespace rdbms { diff --git a/rdbms/LoginFactory.hpp b/rdbms/LoginFactory.hpp index 1959a134907aab0fde556784c5b5dc6897b4796c..7795d803301937f89dce0487a84065418a5ac791 100644 --- a/rdbms/LoginFactory.hpp +++ b/rdbms/LoginFactory.hpp @@ -18,7 +18,7 @@ #pragma once -#include "Login.hpp" +#include "rdbms/Login.hpp" namespace cta { namespace rdbms { diff --git a/rdbms/LoginTest.cpp b/rdbms/LoginTest.cpp index a7a9a3460320dd072a9de8a260726e7b57a0ee64..e4a5430195afa74a2a1ba00ca2cb3e700147b27a 100644 --- a/rdbms/LoginTest.cpp +++ b/rdbms/LoginTest.cpp @@ -16,8 +16,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Login.hpp" #include "common/exception/Exception.hpp" +#include "rdbms/Login.hpp" #include <gtest/gtest.h> #include <sstream> diff --git a/rdbms/PooledConn.cpp b/rdbms/PooledConn.cpp deleted file mode 100644 index dec6e9d9d2a9a5c01427dd9749ff896f0e8cc0cc..0000000000000000000000000000000000000000 --- a/rdbms/PooledConn.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * The CERN Tape Archive (CTA) project - * Copyright (C) 2015 CERN - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "common/exception/Exception.hpp" -#include "rdbms/ConnPool.hpp" -#include "rdbms/PooledConn.hpp" - -namespace cta { -namespace rdbms { - -//------------------------------------------------------------------------------ -// constructor -//------------------------------------------------------------------------------ -PooledConn::PooledConn(std::unique_ptr<Conn> conn, ConnPool *pool): - m_conn(conn.release()), - m_pool(pool) { -} - -//------------------------------------------------------------------------------ -// move constructor -//------------------------------------------------------------------------------ -PooledConn::PooledConn(PooledConn &&other): - m_conn(std::move(other.m_conn)), - m_pool(other.m_pool) { - other.m_pool = nullptr; -} - -//------------------------------------------------------------------------------ -// destructor -//------------------------------------------------------------------------------ -PooledConn::~PooledConn() noexcept { - try { - // If this smart database connection currently points to a database connection then return it back to its pool - if(nullptr != m_pool && nullptr != m_conn) { - m_pool->returnConn(std::move(m_conn)); - } - } catch(...) { - } -} - -//------------------------------------------------------------------------------ -// operator= -//------------------------------------------------------------------------------ -PooledConn &PooledConn::operator=(PooledConn &&rhs) { - // If the database connection is not the one already owned - if(rhs.m_conn != m_conn) { - // If this smart database connection currently points to a database connection then return it back to its pool - if(nullptr != m_pool && nullptr != m_conn) { - m_pool->returnConn(std::move(m_conn)); - } - - // Take ownership of the new database connection - m_conn = std::move(rhs.m_conn); - m_pool = rhs.m_pool; - - rhs.m_pool = nullptr; - } - return *this; -} - -//------------------------------------------------------------------------------ -// createStmt -//------------------------------------------------------------------------------ -std::unique_ptr<Stmt> PooledConn::createStmt(const std::string &sql, - const Stmt::AutocommitMode autocommitMode) { - if(nullptr != m_conn) { - return m_conn->createStmt(sql, autocommitMode); - } else { - throw exception::Exception(std::string(__FUNCTION__) + " failed: PooledConn does not contain a connection"); - } -} - -//------------------------------------------------------------------------------ -// executeNonQueries -//------------------------------------------------------------------------------ -void PooledConn::executeNonQueries(const std::string &sqlStmts) { - if(nullptr != m_conn) { - return m_conn->executeNonQueries(sqlStmts); - } else { - throw exception::Exception(std::string(__FUNCTION__) + " failed: PooledConn does not contain a connection"); - } -} - -//------------------------------------------------------------------------------ -// executeNonQuery -//------------------------------------------------------------------------------ -void PooledConn::executeNonQuery(const std::string &sql, const Stmt::AutocommitMode autocommitMode) { - if(nullptr != m_conn) { - return m_conn->executeNonQuery(sql, autocommitMode); - } else { - throw exception::Exception(std::string(__FUNCTION__) + " failed: PooledConn does not contain a connection"); - } -} - -//------------------------------------------------------------------------------ -// commit -//------------------------------------------------------------------------------ -void PooledConn::commit() { - if(nullptr != m_conn) { - m_conn->commit(); - } else { - throw exception::Exception(std::string(__FUNCTION__) + " failed: PooledConn does not contain a connection"); - } -} - -//------------------------------------------------------------------------------ -// commit -//------------------------------------------------------------------------------ -void PooledConn::rollback() { - if(nullptr != m_conn) { - m_conn->rollback(); - } else { - throw exception::Exception(std::string(__FUNCTION__) + " failed: PooledConn does not contain a connection"); - } -} - -//------------------------------------------------------------------------------ -// getTableNames -//------------------------------------------------------------------------------ -std::list<std::string> PooledConn::getTableNames() { - if(nullptr != m_conn) { - return m_conn->getTableNames(); - } else { - throw exception::Exception(std::string(__FUNCTION__) + " failed: PooledConn does not contain a connection"); - } -} - -//------------------------------------------------------------------------------ -// isOpen -//------------------------------------------------------------------------------ -bool PooledConn::isOpen() const { - if(nullptr != m_conn) { - return m_conn->isOpen(); - } else { - throw exception::Exception(std::string(__FUNCTION__) + " failed: PooledConn does not contain a connection"); - } -} - -} // namespace rdbms -} // namespace cta diff --git a/rdbms/PooledConn.hpp b/rdbms/PooledConn.hpp deleted file mode 100644 index 94c26c0d06a038fb8945e4f2be378ebd10f7bfd4..0000000000000000000000000000000000000000 --- a/rdbms/PooledConn.hpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * The CERN Tape Archive (CTA) project - * Copyright (C) 2015 CERN - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include "rdbms/Stmt.hpp" - -#include <list> -#include <memory> - -namespace cta { -namespace rdbms { - -class Conn; - -class ConnPool; - -/** - * A smart database connection that will automatically return the underlying - * database connection to its parent connection pool when it goes out of scope. - */ -class PooledConn { -public: - - /** - * Constructor. - * - * @param conn The database connection. - * @param pool The database connection pool to which the connection - * should be returned. - */ - PooledConn(std::unique_ptr<Conn> conn, ConnPool *const pool); - - /** - * Deletion of the copy constructor. - */ - PooledConn(PooledConn &) = delete; - - /** - * Move constructor. - * - * @param other The other object. - */ - PooledConn(PooledConn &&other); - - /** - * Destructor. - * - * Returns the database connection back to its pool. - */ - ~PooledConn() noexcept; - - /** - * Deletion of the copy assignment operator. - */ - PooledConn &operator=(const PooledConn &) = delete; - - /** - * Move assignment operator. - * - * @param rhs The object on the right-hand side of the operator. - * @return This object. - */ - PooledConn &operator=(PooledConn &&rhs); - - /** - * Creates a prepared statement. - * - * @param sql The SQL statement. - * @param autocommitMode The autocommit mode of the statement. - * @return The prepared statement. - */ - std::unique_ptr<Stmt> createStmt(const std::string &sql, const Stmt::AutocommitMode autocommitMode); - - /** - * Convenience method that parses the specified string of multiple SQL - * statements and calls executeNonQuery() for each individual statement found. - * - * Please note that each statement should be a non-query terminated by a - * semicolon and that each individual statement will be executed with - * autocommit ON. - * - * @param sqlStmts The SQL statements to be executed. - * @param autocommitMode The autocommit mode of the statement. - */ - void executeNonQueries(const std::string &sqlStmts); - - /** - * Convenience method that wraps Conn::createStmt() followed by - * Stmt::executeNonQuery(). - * - * @param sql The SQL statement. - * @param autocommitMode The autocommit mode of the statement. - */ - void executeNonQuery(const std::string &sql, const Stmt::AutocommitMode autocommitMode); - - /** - * Commits the current transaction. - */ - void commit(); - - /** - * Rolls back the current transaction. - */ - void rollback(); - - /** - * Returns the names of all the tables in the database schema in alphabetical - * order. - * - * @return The names of all the tables in the database schema in alphabetical - * order. - */ - std::list<std::string> getTableNames(); - - /** - * Returns true if this connection is open. - */ - bool isOpen() const; - -private: - - /** - * The database connection. - */ - std::unique_ptr<Conn> m_conn; - - /** - * The database connection pool to which the m_conn should be returned. - */ - ConnPool *m_pool; - -}; // class PooledConn - -} // namespace rdbms -} // namespace cta diff --git a/rdbms/Rset.cpp b/rdbms/Rset.cpp index 4b18232f1c03f788e089288eb393ec3fdd6b46f0..df390212897e5ed0f2e7aa5f4f647764bb9f76ac 100644 --- a/rdbms/Rset.cpp +++ b/rdbms/Rset.cpp @@ -16,10 +16,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Rset.hpp" -#include "RsetImpl.hpp" -#include "NullDbValue.hpp" - +#include "rdbms/NullDbValue.hpp" +#include "rdbms/Rset.hpp" +#include "rdbms/wrapper/Rset.hpp" namespace cta { namespace rdbms { @@ -34,9 +33,9 @@ Rset::Rset(): //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -Rset::Rset(RsetImpl *const impl): - m_impl(impl) { - if(nullptr == impl) { +Rset::Rset(std::unique_ptr<wrapper::Rset> impl): + m_impl(std::move(impl)) { + if(nullptr == m_impl.get()) { throw exception::Exception(std::string(__FUNCTION__) + " failed: Pointer to implementation object is null"); } } @@ -45,23 +44,16 @@ Rset::Rset(RsetImpl *const impl): // constructor //------------------------------------------------------------------------------ Rset::Rset(Rset &&other): - m_impl(other.m_impl) { - other.m_impl = nullptr; -} - -//------------------------------------------------------------------------------ -// destructor -//------------------------------------------------------------------------------ -Rset::~Rset() { - delete m_impl; + m_impl(std::move(other.m_impl)) { } //------------------------------------------------------------------------------ // operator= //------------------------------------------------------------------------------ Rset &Rset::operator=(Rset &&rhs) { - m_impl = rhs.m_impl; - rhs.m_impl = nullptr; + if(m_impl != rhs.m_impl) { + m_impl = std::move(rhs.m_impl); + } return *this; } diff --git a/rdbms/Rset.hpp b/rdbms/Rset.hpp index caa23d5443e3eb6424da58381df32093b1daf5b0..b8c9d1c4e9b1dd14e39bd0d2e06dec8997beff35 100644 --- a/rdbms/Rset.hpp +++ b/rdbms/Rset.hpp @@ -20,16 +20,16 @@ #include "common/optional.hpp" +#include <memory> #include <stdint.h> #include <string> namespace cta { namespace rdbms { -/** - * Forward declarartion. - */ -class RsetImpl; +namespace wrapper { + class Rset; +} /** * A wrapper around an object that iterators over a result set from the @@ -50,7 +50,7 @@ public: * * @param impl The object actually implementing this result set. */ - Rset(RsetImpl *const impl); + Rset(std::unique_ptr<wrapper::Rset> impl); /** * Deletion of copy constructor. @@ -64,11 +64,6 @@ public: */ Rset(Rset &&other); - /** - * Destructor. - */ - ~Rset() throw(); - /** * Deletion of copy assignment. */ @@ -176,7 +171,7 @@ private: /** * The object actually implementing this result set. */ - RsetImpl *m_impl; + std::unique_ptr<wrapper::Rset> m_impl; }; // class Rset diff --git a/rdbms/Stmt.cpp b/rdbms/Stmt.cpp index 00a4e4f17b2a98befb262422b31fe99db4694d7e..34eac226fb333327990dc6024344896c9c576410 100644 --- a/rdbms/Stmt.cpp +++ b/rdbms/Stmt.cpp @@ -16,70 +16,203 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Stmt.hpp" +#include "common/exception/Exception.hpp" +#include "rdbms/Stmt.hpp" +#include "rdbms/StmtPool.hpp" +#include "rdbms/wrapper/Stmt.hpp" namespace cta { namespace rdbms { -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- // constructor -//------------------------------------------------------------------------------ -Stmt::Stmt(const std::string &sql, const AutocommitMode autocommitMode): - m_sql(sql), - m_autoCommitMode(autocommitMode), - m_paramNameToIdx(sql) { +//----------------------------------------------------------------------------- +Stmt::Stmt(): + m_stmtPool(nullptr) { } -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------- +Stmt::Stmt(std::unique_ptr<wrapper::Stmt> stmt, StmtPool &stmtPool): + m_stmt(std::move(stmt)), + m_stmtPool(&stmtPool) { +} + +//----------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------- +Stmt::Stmt(Stmt &&other): + m_stmt(std::move(other.m_stmt)), + m_stmtPool(other.m_stmtPool){ +} + +//----------------------------------------------------------------------------- // destructor -//------------------------------------------------------------------------------ -Stmt::~Stmt() throw() { +//----------------------------------------------------------------------------- +Stmt::~Stmt() noexcept { + try { + // If this smart prepared statement currently points to a prepared + // statement then return it back to its pool + if(nullptr != m_stmtPool && nullptr != m_stmt) { + m_stmtPool->returnStmt(std::move(m_stmt)); + } + } catch(...) { + // Ignore any exceptions + } } -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- +// operator= +//----------------------------------------------------------------------------- +Stmt &Stmt::operator=(Stmt &&rhs) { + // If the cached statement is not already owned + if(rhs.m_stmt != m_stmt) { + // If this smart cached statement already points to cached statement, then + // return it back to its pool + if(nullptr != m_stmt && nullptr != m_stmtPool) { + m_stmtPool->returnStmt(std::move(m_stmt)); + } + + // Take ownership of the new cached statement + m_stmt = std::move(rhs.m_stmt); + m_stmtPool = rhs.m_stmtPool; + + rhs.m_stmtPool = nullptr; + } + + return *this; +} + +//----------------------------------------------------------------------------- // getSql -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- const std::string &Stmt::getSql() const { - return m_sql; + if(nullptr != m_stmt) { + return m_stmt->getSql(); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } } -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- // getParamIdx -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- uint32_t Stmt::getParamIdx(const std::string ¶mName) const { - return m_paramNameToIdx.getIdx(paramName); + if(nullptr != m_stmt) { + return m_stmt->getParamIdx(paramName); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } } -//------------------------------------------------------------------------------ -// getSqlForException -//------------------------------------------------------------------------------ -std::string Stmt::getSqlForException() const { - if(m_sql.length() <= c_maxSqlLenInExceptions) { - return m_sql; +//----------------------------------------------------------------------------- +// bindUint64 +//----------------------------------------------------------------------------- +void Stmt::bindUint64(const std::string ¶mName, const uint64_t paramValue) { + if(nullptr != m_stmt) { + return m_stmt->bindUint64(paramName, paramValue); } else { - if(c_maxSqlLenInExceptions >= 3) { - return m_sql.substr(0, c_maxSqlLenInExceptions - 3) + "..."; - } else { - return std::string("..."). substr(0, c_maxSqlLenInExceptions); - } + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } +} + +//----------------------------------------------------------------------------- +// bindOptionalUint64 +//----------------------------------------------------------------------------- +void Stmt::bindOptionalUint64(const std::string ¶mName, const optional<uint64_t> ¶mValue) { + if(nullptr != m_stmt) { + return m_stmt->bindOptionalUint64(paramName, paramValue); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); } } -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- // bindBool -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- void Stmt::bindBool(const std::string ¶mName, const bool paramValue) { - bindOptionalBool(paramName, paramValue); + if(nullptr != m_stmt) { + return m_stmt->bindBool(paramName, paramValue); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } } -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- // bindOptionalBool -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- void Stmt::bindOptionalBool(const std::string ¶mName, const optional<bool> ¶mValue) { - if(paramValue) { - bindOptionalUint64(paramName, paramValue.value() ? 1 : 0); + if(nullptr != m_stmt) { + return m_stmt->bindOptionalBool(paramName, paramValue); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } +} + +//----------------------------------------------------------------------------- +// bindString +//----------------------------------------------------------------------------- +void Stmt::bindString(const std::string ¶mName, const std::string ¶mValue) { + if(nullptr != m_stmt) { + return m_stmt->bindString(paramName, paramValue); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } +} + +//----------------------------------------------------------------------------- +// bindOptionalString +//----------------------------------------------------------------------------- +void Stmt::bindOptionalString(const std::string ¶mName, const optional<std::string> ¶mValue) { + if(nullptr != m_stmt) { + return m_stmt->bindOptionalString(paramName, paramValue); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } +} + +//----------------------------------------------------------------------------- +// executeQuery +//----------------------------------------------------------------------------- +Rset Stmt::executeQuery() { + if(nullptr != m_stmt) { + return Rset(m_stmt->executeQuery()); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } +} + +//----------------------------------------------------------------------------- +// executeNonQuery +//----------------------------------------------------------------------------- +void Stmt::executeNonQuery() { + if(nullptr != m_stmt) { + return m_stmt->executeNonQuery(); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } +} + +//----------------------------------------------------------------------------- +// getNbAffectedRows +//----------------------------------------------------------------------------- +uint64_t Stmt::getNbAffectedRows() const { + if(nullptr != m_stmt) { + return m_stmt->getNbAffectedRows(); + } else { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); + } +} + +//----------------------------------------------------------------------------- +// getStmt +//----------------------------------------------------------------------------- +wrapper::Stmt &Stmt::getStmt() { + if(nullptr != m_stmt) { + return *m_stmt; } else { - bindOptionalUint64(paramName, nullopt); + throw exception::Exception(std::string(__FUNCTION__) + " failed: Stmt does not contain a cached statement"); } } diff --git a/rdbms/Stmt.hpp b/rdbms/Stmt.hpp index 8aa49c5c4dea4626b31ef547a8e6a201f2b55e51..899e2f83e6b88ec0df9ca9ec1435a02f73e188c6 100644 --- a/rdbms/Stmt.hpp +++ b/rdbms/Stmt.hpp @@ -18,50 +18,42 @@ #pragma once -#include "common/optional.hpp" -#include "rdbms/ParamNameToIdx.hpp" #include "rdbms/Rset.hpp" +#include "common/optional.hpp" +#include <list> #include <memory> -#include <stdint.h> -#include <string> +#include <mutex> namespace cta { namespace rdbms { +namespace wrapper { + class Stmt; +} + +class StmtPool; + /** - * Abstract class specifying the interface to a database statement. + * A smart database statement that will automatically return the underlying + * database statement to its parent database connection when it goes out of + * scope. */ class Stmt { public: - /** - * A statement can either have auto commiting mode turned on or off. - */ - enum class AutocommitMode { - ON, - OFF - }; - /** * Constructor. - * - * @param sql The SQL statement. - * @param autocommitMode The autocommit mode of the statement. */ - Stmt(const std::string &sql, const AutocommitMode autocommitMode); + Stmt(); /** - * Returns the autocommit mode of teh statement. + * Constructor. * - * @return The autocommit mode of teh statement. + * @param stmt The database statement. + * @param stmtPool The database statement pool to which the m_stmt should be returned. */ - AutocommitMode getAutoCommitMode() const noexcept; - - /** - * Destructor. - */ - virtual ~Stmt() throw() = 0; + Stmt(std::unique_ptr<wrapper::Stmt> stmt, StmtPool &stmtPool); /** * Deletion of the copy constructor. @@ -69,24 +61,31 @@ public: Stmt(Stmt &) = delete; /** - * Deletion of the move constructor. + * Move constructor. + * + * @param other The other object. */ - Stmt(Stmt &&) = delete; + Stmt(Stmt &&other); /** - * Deletion of the copy assignment operator. + * Destructor. + * + * Returns the database statement back to its connection. */ - Stmt &operator=(const Stmt &) = delete; + ~Stmt() noexcept; /** - * Deletion of the move assignment operator. + * Deletion of the copy assignment operator. */ - Stmt &operator=(Stmt &&) = delete; + Stmt &operator=(const Stmt &) = delete; /** - * Idempotent close() method. The destructor calls this method. + * Move assignment operator. + * + * @param rhs The object on the right-hand side of the operator. + * @return This object. */ - virtual void close() = 0; + Stmt &operator=(Stmt &&rhs); /** * Returns the SQL statement. @@ -109,7 +108,7 @@ public: * @param paramName The name of the parameter. * @param paramValue The value to be bound. */ - virtual void bindUint64(const std::string ¶mName, const uint64_t paramValue) = 0; + void bindUint64(const std::string ¶mName, const uint64_t paramValue); /** * Binds an SQL parameter. @@ -117,7 +116,7 @@ public: * @param paramName The name of the parameter. * @param paramValue The value to be bound. */ - virtual void bindOptionalUint64(const std::string ¶mName, const optional<uint64_t> ¶mValue) = 0; + void bindOptionalUint64(const std::string ¶mName, const optional<uint64_t> ¶mValue); /** * Binds an SQL parameter. @@ -145,7 +144,7 @@ public: * @param paramName The name of the parameter. * @param paramValue The value to be bound. */ - virtual void bindString(const std::string ¶mName, const std::string ¶mValue) = 0; + void bindString(const std::string ¶mName, const std::string ¶mValue); /** * Binds an SQL parameter of type optional-string. @@ -157,19 +156,19 @@ public: * @param paramName The name of the parameter. * @param paramValue The value to be bound. */ - virtual void bindOptionalString(const std::string ¶mName, const optional<std::string> ¶mValue) = 0; + void bindOptionalString(const std::string ¶mName, const optional<std::string> ¶mValue); /** * Executes the statement and returns the result set. * * @return The result set. */ - virtual Rset executeQuery() = 0; + Rset executeQuery(); /** * Executes the statement. */ - virtual void executeNonQuery() = 0; + void executeNonQuery(); /** * Returns the number of rows affected by the last execution of this @@ -177,43 +176,25 @@ public: * * @return The number of affected rows. */ - virtual uint64_t getNbAffectedRows() const = 0; - -protected: - - /** - * The maximum length an SQL statement can have in exception error message. - */ - const uint32_t c_maxSqlLenInExceptions = 80; + uint64_t getNbAffectedRows() const; /** - * Returns the SQL string to be used in an exception message. The string - * will be clipped at a maxmum of c_maxSqlLenInExceptions characters. If the - * string is actually clipped then the three last characters will be an - * replaced by an ellipsis of three dots, in other word "...". These 3 - * characters will indicate to the reader of the exception message that the - * SQL statement has been clipped. - * - * @return The SQL string to be used in an exception message. + * Returns a reference to the underlying statement object that is not pool + * aware. */ - std::string getSqlForException() const; + wrapper::Stmt &getStmt(); private: /** - * The SQL statement. - */ - std::string m_sql; - - /** - * The autocommit mode of the statement. + * The database statement. */ - AutocommitMode m_autoCommitMode; + std::unique_ptr<wrapper::Stmt> m_stmt; /** - * Map from SQL parameter name to parameter index. + * The database statement pool to which the m_stmt should be returned. */ - ParamNameToIdx m_paramNameToIdx; + StmtPool *m_stmtPool; }; // class Stmt diff --git a/rdbms/StmtPool.cpp b/rdbms/StmtPool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..537efae8d32cadf20ec58c7f8fd24fc640306c6c --- /dev/null +++ b/rdbms/StmtPool.cpp @@ -0,0 +1,93 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "common/exception/Exception.hpp" +#include "common/threading/MutexLocker.hpp" +#include "rdbms/wrapper/Conn.hpp" +#include "rdbms/StmtPool.hpp" + +namespace cta { +namespace rdbms { + +//------------------------------------------------------------------------------ +// getStmt +//------------------------------------------------------------------------------ +Stmt StmtPool::getStmt(wrapper::Conn &conn, const std::string &sql, const AutocommitMode autocommitMode) { + const CachedStmtKey key(sql, autocommitMode); + + threading::MutexLocker locker(m_stmtsMutex); + + auto itor = m_stmts.find(key); + + // If there is no prepared statement in the cache + if(itor == m_stmts.end()) { + auto stmt = conn.createStmt(sql, autocommitMode); + return Stmt(std::move(stmt), *this); + } else { + auto &stmtList = itor->second; + if(stmtList.empty()) { + throw exception::Exception(std::string(__FUNCTION__) + " failed: Unexpected empty list of cached statements"); + } + auto stmt = std::move(stmtList.front()); + stmtList.pop_front(); + + // If there are no more cached prepared statements then remove the empty list from the cache + if(stmtList.empty()) { + m_stmts.erase(itor); + } + + return Stmt(std::move(stmt), *this); + } +} + +//------------------------------------------------------------------------------ +// getNbStmts +//------------------------------------------------------------------------------ +uint64_t StmtPool::getNbStmts() const { + threading::MutexLocker locker(m_stmtsMutex); + + uint64_t nbStmts = 0; + for(const auto &maplet: m_stmts) { + auto &stmtList = maplet.second; + nbStmts += stmtList.size(); + } + return nbStmts; +} + +//------------------------------------------------------------------------------ +// returnStmt +//------------------------------------------------------------------------------ +void StmtPool::returnStmt(std::unique_ptr<wrapper::Stmt> stmt) { + threading::MutexLocker locker(m_stmtsMutex); + + const CachedStmtKey key(stmt->getSql(), stmt->getAutocommitMode()); + + stmt->clear(); + + m_stmts[key].push_back(std::move(stmt)); +} + +//------------------------------------------------------------------------------ +// clear +//------------------------------------------------------------------------------ +void StmtPool::clear() { + m_stmts.clear(); +} + +} // namespace rdbms +} // namespace cta diff --git a/rdbms/StmtPool.hpp b/rdbms/StmtPool.hpp new file mode 100644 index 0000000000000000000000000000000000000000..04c8ce6cd53a1226df5f8077e764dc5f96a87d7f --- /dev/null +++ b/rdbms/StmtPool.hpp @@ -0,0 +1,132 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "common/threading/CondVar.hpp" +#include "common/threading/Mutex.hpp" +#include "rdbms/AutocommitMode.hpp" +#include "rdbms/Stmt.hpp" + +#include <iostream> +#include <list> +#include <map> +#include <memory> +#include <stdint.h> + +namespace cta { +namespace rdbms { + +namespace wrapper { + class Conn; + class Stmt; +} + +/** + * A pool of prepared database statements. + */ +class StmtPool { +public: + + /** + * Takes a database statement from the pool if one is present else a new + * statement will be prepared. + * + * @param conn The database connection to which the database statements + * @param sql The SQL statement. + * @param autocommitMode The autocommit mode of the statement. + * @return The prepared statement. + */ + Stmt getStmt(wrapper::Conn &conn, const std::string &sql, const AutocommitMode autocommitMode); + + /** + * Returns the number of cached statements currently in the pool. + * + * @return The number of cached statements currently in the pool. + */ + uint64_t getNbStmts() const; + + /** + * Clears the pooll of prepared statements which includes destroying those + * statements. + */ + void clear(); + +private: + + friend Stmt; + + /** + * Returns the specified statement to the pool. + * + * @param stmt The database statement to be returned to the pool. + */ + void returnStmt(std::unique_ptr<wrapper::Stmt> stmt); + + /** + * Mutex used to serialize access to the database statements within the pool. + */ + mutable threading::Mutex m_stmtsMutex; + + /** + * Key used to lookup prepares statements within the cache. + */ + struct CachedStmtKey { + /** + * The SQL of the cached statement. + */ + std::string sql; + + /** + * The autocommit mode of the cached statement. + */ + const AutocommitMode autocommitMode; + + /** + * Constructor. + * + * @param s The SQL of the cached statement. + * @param a The autocommit mode of the cached statement. + */ + CachedStmtKey(const std::string &s, const AutocommitMode a): sql(s), autocommitMode(a) { + } + + /** + * Less than operator. + */ + bool operator<(const CachedStmtKey &rhs) const { + if(sql != rhs.sql) { + return sql < rhs.sql; + } else { + return autocommitMode < rhs.autocommitMode; + } + } + }; + + /** + * The cached database statements. + * + * Please note that for a single key there maybe more than one cached + * statement, hence the map to list of statements. + */ + std::map<CachedStmtKey, std::list< std::unique_ptr<wrapper::Stmt> > > m_stmts; + +}; // class StmtPool + +} // namespace rdbms +} // namespace cta diff --git a/rdbms/StmtPoolTest.cpp b/rdbms/StmtPoolTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00bbc303804729772cf44d924776e09588de4800 --- /dev/null +++ b/rdbms/StmtPoolTest.cpp @@ -0,0 +1,234 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "common/exception/Exception.hpp" +#include "rdbms/ConnPool.hpp" +#include "rdbms/wrapper/ConnFactoryFactory.hpp" + +#include <gtest/gtest.h> +#include <sstream> + +namespace unitTests { + +class cta_rdbms_StmtPoolTest : public ::testing::Test { +protected: + + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + +TEST_F(cta_rdbms_StmtPoolTest, getStmt) { + using namespace cta::rdbms; + + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = wrapper::ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + const std::string sql = "CREATE TABLE POOLED_STMT_TEST(ID INTEGER)"; + StmtPool pool; + ASSERT_EQ(0, pool.getNbStmts()); + { + auto stmt = pool.getStmt(*conn, sql, AutocommitMode::ON); + ASSERT_EQ(0, pool.getNbStmts()); + } + ASSERT_EQ(1, pool.getNbStmts()); +} + +TEST_F(cta_rdbms_StmtPoolTest, moveAssignment) { + using namespace cta::rdbms; + + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = wrapper::ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + const std::string sql = "CREATE TABLE POOLED_STMT_TEST(ID INTEGER)"; + StmtPool pool; + ASSERT_EQ(0, pool.getNbStmts()); + { + Stmt stmt1 = pool.getStmt(*conn, sql, AutocommitMode::ON); + Stmt stmt2; + stmt2 = std::move(stmt1); + ASSERT_EQ(0, pool.getNbStmts()); + } + ASSERT_EQ(1, pool.getNbStmts()); +} + +TEST_F(cta_rdbms_StmtPoolTest, moveConstructor) { + using namespace cta::rdbms; + + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = wrapper::ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + const std::string sql = "CREATE TABLE POOLED_STMT_TEST(ID INTEGER)"; + StmtPool pool; + ASSERT_EQ(0, pool.getNbStmts()); + { + Stmt stmt1 = pool.getStmt(*conn, sql, AutocommitMode::ON); + Stmt stmt2(std::move(stmt1)); + ASSERT_EQ(0, pool.getNbStmts()); + } + ASSERT_EQ(1, pool.getNbStmts()); +} + +TEST_F(cta_rdbms_StmtPoolTest, createSameTableInTwoSeparateInMemoryDatabases) { + using namespace cta::rdbms; + + const std::string createTableSql = "CREATE TABLE POOLED_STMT_TEST(ID INTEGER)"; + const std::string selectTableNamesSql = + "SELECT " + "NAME AS NAME " + "FROM " + "SQLITE_MASTER " + "WHERE " + "TYPE = 'table' " + "ORDER BY " + "NAME;"; + + // First in-memory database + { + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = wrapper::ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + + StmtPool pool; + + { + Stmt stmt = pool.getStmt(*conn, selectTableNamesSql, AutocommitMode::ON); + auto rset = stmt.executeQuery(); + std::list<std::string> names; + while(rset.next()) { + names.push_back(rset.columnString("NAME")); + } + ASSERT_EQ(0, names.size()); + } + + { + Stmt stmt = pool.getStmt(*conn, createTableSql, AutocommitMode::ON); + stmt.executeNonQuery(); + } + + { + Stmt stmt = pool.getStmt(*conn, selectTableNamesSql, AutocommitMode::ON); + auto rset = stmt.executeQuery(); + std::list<std::string> names; + while(rset.next()) { + names.push_back(rset.columnString("NAME")); + } + ASSERT_EQ(1, names.size()); + ASSERT_EQ("POOLED_STMT_TEST", names.front()); + } + } + + // Second in-memory database + { + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = wrapper::ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + + StmtPool pool; + { + Stmt stmt = pool.getStmt(*conn, selectTableNamesSql, AutocommitMode::ON); + auto rset = stmt.executeQuery(); + std::list<std::string> names; + while(rset.next()) { + names.push_back(rset.columnString("NAME")); + } + ASSERT_EQ(0, names.size()); + } + + { + Stmt stmt = pool.getStmt(*conn, createTableSql, AutocommitMode::ON); + stmt.executeNonQuery(); + } + + { + Stmt stmt = pool.getStmt(*conn, selectTableNamesSql, AutocommitMode::ON); + auto rset = stmt.executeQuery(); + std::list<std::string> names; + while(rset.next()) { + names.push_back(rset.columnString("NAME")); + } + ASSERT_EQ(1, names.size()); + ASSERT_EQ("POOLED_STMT_TEST", names.front()); + } + } +} + +TEST_F(cta_rdbms_StmtPoolTest, createSameTableInTwoSeparateInMemoryDatabases_getTableNames) { + using namespace cta::rdbms; + + const std::string createTableSql = "CREATE TABLE POOLED_STMT_TEST(ID INTEGER)"; + + // First in-memory database + { + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = wrapper::ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + + StmtPool pool; + + ASSERT_TRUE(conn->getTableNames().empty()); + + { + Stmt stmt = pool.getStmt(*conn, createTableSql, AutocommitMode::ON); + stmt.executeNonQuery(); + } + + ASSERT_EQ(1, conn->getTableNames().size()); + } + + // Second in-memory database + { + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = wrapper::ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + + StmtPool pool; + + ASSERT_TRUE(conn->getTableNames().empty()); + + { + Stmt stmt = pool.getStmt(*conn, createTableSql, AutocommitMode::ON); + stmt.executeNonQuery(); + } + + ASSERT_EQ(1, conn->getTableNames().size()); + } +} + +TEST_F(cta_rdbms_StmtPoolTest, sameSqlTwoCachedStmts) { + using namespace cta::rdbms; + + const Login login(Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = wrapper::ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + const std::string sql = "CREATE TABLE POOLED_STMT_TEST(ID INTEGER)"; + StmtPool pool; + ASSERT_EQ(0, pool.getNbStmts()); + { + Stmt stmt1 = pool.getStmt(*conn, sql, AutocommitMode::ON); + Stmt stmt2 = pool.getStmt(*conn, sql, AutocommitMode::ON); + ASSERT_EQ(0, pool.getNbStmts()); + } + ASSERT_EQ(2, pool.getNbStmts()); +} + + + +} // namespace unitTests diff --git a/rdbms/wrapper/CMakeLists.txt b/rdbms/wrapper/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3777fa7068df4f6c9d899be92a2f5032285217ad --- /dev/null +++ b/rdbms/wrapper/CMakeLists.txt @@ -0,0 +1,76 @@ +# The CERN Tape Archive (CTA) project +# Copyright (C) 2015 CERN +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +cmake_minimum_required (VERSION 2.6) + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") + +find_package (sqlite REQUIRED) + +find_package (oracle-instantclient REQUIRED) +include_directories (${ORACLE-INSTANTCLIENT_INCLUDE_DIRS}) + +set (RDBMS_WRAPPER_LIB_SRC_FILES + ColumnNameToIdx.cpp + ColumnNameToIdxAndType.cpp + Conn.cpp + ConnFactory.cpp + Rset.cpp + Stmt.cpp + ParamNameToIdx.cpp + Sqlite.cpp + SqliteConn.cpp + SqliteConnFactory.cpp + SqliteRset.cpp + SqliteStmt.cpp) + +set (RDBMS_WRAPPER_LIB_SRC_FILES + ${RDBMS_WRAPPER_LIB_SRC_FILES} + ConnFactoryFactory.cpp + OcciColumn.cpp + OcciConn.cpp + OcciConnFactory.cpp + OcciEnv.cpp + OcciEnvSingleton.cpp + OcciRset.cpp + OcciStmt.cpp) + +add_library (ctardbmswrapper SHARED + ${RDBMS_WRAPPER_LIB_SRC_FILES}) +set_property(TARGET ctardbmswrapper PROPERTY SOVERSION "${CTA_SOVERSION}") +set_property(TARGET ctardbmswrapper PROPERTY VERSION "${CTA_LIBVERSION}") + +target_link_libraries (ctardbmswrapper + ctacommon + ${SQLITE_LIBRARIES} + ${ORACLE-INSTANTCLIENT_LIBRARIES}) + +install (TARGETS ctardbmswrapper DESTINATION usr/${CMAKE_INSTALL_LIBDIR}) + +set(RDBMS_UNIT_TESTS_LIB_SRC_FILES + ConnTest.cpp + OcciColumnTest.cpp + ParamNameToIdxTest.cpp + SqliteStmtTest.cpp) + +add_library (ctardbmswrapperunittests SHARED + ${RDBMS_UNIT_TESTS_LIB_SRC_FILES}) +set_property(TARGET ctardbmswrapperunittests PROPERTY SOVERSION "${CTA_SOVERSION}") +set_property(TARGET ctardbmswrapperunittests PROPERTY VERSION "${CTA_LIBVERSION}") + +target_link_libraries (ctardbmswrapperunittests + ctacatalogue) + +install(TARGETS ctardbmswrapperunittests DESTINATION usr/${CMAKE_INSTALL_LIBDIR}) diff --git a/rdbms/ColumnNameToIdx.cpp b/rdbms/wrapper/ColumnNameToIdx.cpp similarity index 95% rename from rdbms/ColumnNameToIdx.cpp rename to rdbms/wrapper/ColumnNameToIdx.cpp index c0f7fb5c685a0307aa4ec5a1d53849cdf0edde8c..bae20d1512f4a1507d94b663930fd470ca7ca7e0 100644 --- a/rdbms/ColumnNameToIdx.cpp +++ b/rdbms/wrapper/ColumnNameToIdx.cpp @@ -16,11 +16,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ColumnNameToIdx.hpp" #include "common/exception/Exception.hpp" +#include "rdbms/wrapper/ColumnNameToIdx.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // add @@ -50,5 +51,6 @@ bool ColumnNameToIdx::empty() const { return m_nameToIdx.empty(); } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ColumnNameToIdx.hpp b/rdbms/wrapper/ColumnNameToIdx.hpp similarity index 97% rename from rdbms/ColumnNameToIdx.hpp rename to rdbms/wrapper/ColumnNameToIdx.hpp index 511beb6bec235100ec3fe789ce90ecc9a53a7d42..698964a14ef7be3a40ca0ed78da421a7b22f6361 100644 --- a/rdbms/ColumnNameToIdx.hpp +++ b/rdbms/wrapper/ColumnNameToIdx.hpp @@ -23,6 +23,7 @@ namespace cta { namespace rdbms { +namespace wrapper { /** * A map from column name to column index. @@ -67,5 +68,6 @@ private: }; // class ColumnNameToIdx +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ColumnNameToIdxAndType.cpp b/rdbms/wrapper/ColumnNameToIdxAndType.cpp similarity index 96% rename from rdbms/ColumnNameToIdxAndType.cpp rename to rdbms/wrapper/ColumnNameToIdxAndType.cpp index 09f4842e1dface3674df5cb6913576f49f6f9124..5f02829aeac4d8082fe225f8a5c86ecf3a832527 100644 --- a/rdbms/ColumnNameToIdxAndType.cpp +++ b/rdbms/wrapper/ColumnNameToIdxAndType.cpp @@ -16,11 +16,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ColumnNameToIdxAndType.hpp" #include "common/exception/Exception.hpp" +#include "rdbms/wrapper/ColumnNameToIdxAndType.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // add @@ -57,5 +58,6 @@ void ColumnNameToIdxAndType::clear() { m_nameToIdxAndType.clear(); } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ColumnNameToIdxAndType.hpp b/rdbms/wrapper/ColumnNameToIdxAndType.hpp similarity index 98% rename from rdbms/ColumnNameToIdxAndType.hpp rename to rdbms/wrapper/ColumnNameToIdxAndType.hpp index d65f29a6c2d9a8b4ddce9a3a025ddb3ebae5c623..8c9478ef0f9f8fc1352d69c5a6b38dba6fe3af25 100644 --- a/rdbms/ColumnNameToIdxAndType.hpp +++ b/rdbms/wrapper/ColumnNameToIdxAndType.hpp @@ -21,6 +21,7 @@ namespace cta { namespace rdbms { +namespace wrapper { /** * A map from column name to column index and type. @@ -96,5 +97,6 @@ private: }; // class ColumnNameToIdxAndType +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ConnFactoryFactory_OCCI_SUPPORT_OFF.cpp b/rdbms/wrapper/Conn.cpp similarity index 50% rename from rdbms/ConnFactoryFactory_OCCI_SUPPORT_OFF.cpp rename to rdbms/wrapper/Conn.cpp index 99c5c9acec0e5501dc4263278f43a8e16b39a627..f3af845a966ffbaaa0fea242a96f2216ee7e7802 100644 --- a/rdbms/ConnFactoryFactory_OCCI_SUPPORT_OFF.cpp +++ b/rdbms/wrapper/Conn.cpp @@ -17,38 +17,19 @@ */ #include "common/exception/Exception.hpp" -#include "common/make_unique.hpp" -#include "rdbms/ConnFactoryFactory.hpp" -#include "rdbms/SqliteConnFactory.hpp" +#include "common/utils/utils.hpp" +#include "rdbms/wrapper/Conn.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ -// create +// destructor //------------------------------------------------------------------------------ -std::unique_ptr<ConnFactory> ConnFactoryFactory::create(const Login &login) { - try { - switch(login.dbType) { - case rdbms::Login::DBTYPE_IN_MEMORY: - return cta::make_unique<SqliteConnFactory>(":memory:"); - case rdbms::Login::DBTYPE_ORACLE: - throw exception::Exception("OCCI support disabled at compile time"); - case rdbms::Login::DBTYPE_SQLITE: - return cta::make_unique<SqliteConnFactory>(login.database); - case rdbms::Login::DBTYPE_NONE: - throw exception::Exception("Cannot create a catalogue without a database type"); - default: - { - exception::Exception ex; - ex.getMessage() << "Unknown database type: value=" << login.dbType; - throw ex; - } - } - } catch(exception::Exception &ex) { - throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); - } +Conn::~Conn() throw() { } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/wrapper/Conn.hpp b/rdbms/wrapper/Conn.hpp new file mode 100644 index 0000000000000000000000000000000000000000..708a25e076bc89ef6688ff31909b468c224ed753 --- /dev/null +++ b/rdbms/wrapper/Conn.hpp @@ -0,0 +1,97 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "rdbms/wrapper/Stmt.hpp" + +#include <atomic> +#include <list> +#include <memory> +#include <string> + +namespace cta { +namespace rdbms { +namespace wrapper { + +/** + * Abstract class that specifies the interface to a database connection. + */ +class Conn { +public: + + /** + * Destructor. + */ + virtual ~Conn() throw() = 0; + + /** + * Idempotent close() method. The destructor calls this method. + */ + virtual void close() = 0; + + /** + * Creates a prepared statement. + * + * @param sql The SQL statement. + * @param autocommitMode The autocommit mode of the statement. + * @return The prepared statement. + */ + virtual std::unique_ptr<Stmt> createStmt(const std::string &sql, const AutocommitMode autocommitMode) = 0; + + /** + * Commits the current transaction. + */ + virtual void commit() = 0; + + /** + * Rolls back the current transaction. + */ + virtual void rollback() = 0; + + /** + * Returns the names of all the tables in the database schema in alphabetical + * order. + * + * @return The names of all the tables in the database schema in alphabetical + * order. + */ + virtual std::list<std::string> getTableNames() = 0; + + /** + * Returns true if this connection is open. + */ + virtual bool isOpen() const = 0; + + /** + * Returns the names of all the sequences in the database schema in + * alphabetical order. + * + * If the underlying database technologies does not supported sequences then + * this method simply returns an empty list. + * + * @return The names of all the sequences in the database schema in + * alphabetical order. + */ + virtual std::list<std::string> getSequenceNames() = 0; + +}; // class Conn + +} // namespace wrapper +} // namespace rdbms +} // namespace cta diff --git a/rdbms/ConnFactory.cpp b/rdbms/wrapper/ConnFactory.cpp similarity index 92% rename from rdbms/ConnFactory.cpp rename to rdbms/wrapper/ConnFactory.cpp index 69e15806a3b292fff99a109425e94ea9819b41b1..45f70c30ff9e07875fd6c22bcf689e899c83f4ea 100644 --- a/rdbms/ConnFactory.cpp +++ b/rdbms/wrapper/ConnFactory.cpp @@ -16,10 +16,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ConnFactory.hpp" +#include "rdbms/wrapper/ConnFactory.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // destructor @@ -27,5 +28,6 @@ namespace rdbms { ConnFactory::~ConnFactory() throw() { } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ConnFactory.hpp b/rdbms/wrapper/ConnFactory.hpp similarity index 93% rename from rdbms/ConnFactory.hpp rename to rdbms/wrapper/ConnFactory.hpp index 79efb5b587a1c3aaad7d59223e3f9ee18c8feec9..a980b7e4f2c8614d885c11c1f62f44c9688894a8 100644 --- a/rdbms/ConnFactory.hpp +++ b/rdbms/wrapper/ConnFactory.hpp @@ -18,12 +18,13 @@ #pragma once -#include "Conn.hpp" +#include "rdbms/wrapper/Conn.hpp" #include <memory> namespace cta { namespace rdbms { +namespace wrapper { /** * Abstract class that specifies the interface of a factory of Conn objects. @@ -45,5 +46,6 @@ public: }; // class ConnFactory +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ConnFactoryFactory.cpp b/rdbms/wrapper/ConnFactoryFactory.cpp similarity index 85% rename from rdbms/ConnFactoryFactory.cpp rename to rdbms/wrapper/ConnFactoryFactory.cpp index a63d6a8e92bda2fc1c6daca04945ea8c92a67929..95e2e10047ae27b71e9b8c8023287fdf8bca3af8 100644 --- a/rdbms/ConnFactoryFactory.cpp +++ b/rdbms/wrapper/ConnFactoryFactory.cpp @@ -18,12 +18,13 @@ #include "common/exception/Exception.hpp" #include "common/make_unique.hpp" -#include "rdbms/ConnFactoryFactory.hpp" -#include "rdbms/OcciConnFactory.hpp" -#include "rdbms/SqliteConnFactory.hpp" +#include "rdbms/wrapper/ConnFactoryFactory.hpp" +#include "rdbms/wrapper/OcciConnFactory.hpp" +#include "rdbms/wrapper/SqliteConnFactory.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // create @@ -31,13 +32,13 @@ namespace rdbms { std::unique_ptr<ConnFactory> ConnFactoryFactory::create(const Login &login) { try { switch(login.dbType) { - case rdbms::Login::DBTYPE_IN_MEMORY: + case Login::DBTYPE_IN_MEMORY: return cta::make_unique<SqliteConnFactory>("file::memory:?cache=shared"); - case rdbms::Login::DBTYPE_ORACLE: + case Login::DBTYPE_ORACLE: return cta::make_unique<OcciConnFactory>(login.username, login.password, login.database); - case rdbms::Login::DBTYPE_SQLITE: + case Login::DBTYPE_SQLITE: return cta::make_unique<SqliteConnFactory>(login.database); - case rdbms::Login::DBTYPE_NONE: + case Login::DBTYPE_NONE: throw exception::Exception("Cannot create a catalogue without a database type"); default: { @@ -51,5 +52,6 @@ std::unique_ptr<ConnFactory> ConnFactoryFactory::create(const Login &login) { } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ConnFactoryFactory.hpp b/rdbms/wrapper/ConnFactoryFactory.hpp similarity index 93% rename from rdbms/ConnFactoryFactory.hpp rename to rdbms/wrapper/ConnFactoryFactory.hpp index cdacc5dafc9ecad608f54ccafb5a4f1823aab8df..49f96acc75ee2a36ba288c1a3568dbed6e011318 100644 --- a/rdbms/ConnFactoryFactory.hpp +++ b/rdbms/wrapper/ConnFactoryFactory.hpp @@ -18,13 +18,14 @@ #pragma once -#include "rdbms/ConnFactory.hpp" +#include "rdbms/wrapper/ConnFactory.hpp" #include "rdbms/Login.hpp" #include <memory> namespace cta { namespace rdbms { +namespace wrapper { /** * Abstract class that specifies the interface to a factory of ConnFactory objects. @@ -43,5 +44,6 @@ public: }; // class ConnFactoryFactory +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/wrapper/ConnTest.cpp b/rdbms/wrapper/ConnTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b5c46c501b483459fffadea169d98bb567b32de --- /dev/null +++ b/rdbms/wrapper/ConnTest.cpp @@ -0,0 +1,72 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "common/exception/Exception.hpp" +#include "rdbms/wrapper/ConnFactoryFactory.hpp" + +#include <gtest/gtest.h> +#include <sstream> + +namespace unitTests { + +class cta_rdbms_wrapper_ConnTest : public ::testing::Test { +protected: + + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + +TEST_F(cta_rdbms_wrapper_ConnTest, createSameTableInTwoSeparateInMemoryDatabases) { + using namespace cta; + using namespace cta::rdbms::wrapper; + + const std::string sql = "CREATE TABLE POOLED_STMT_TEST(ID INTEGER)"; + + // First in-memory database + { + const rdbms::Login login(rdbms::Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + + ASSERT_TRUE(conn->getTableNames().empty()); + + auto stmt = conn->createStmt(sql, rdbms::AutocommitMode::ON); + stmt->executeNonQuery(); + + ASSERT_EQ(1, conn->getTableNames().size()); + } + + // Second in-memory database + { + const rdbms::Login login(rdbms::Login::DBTYPE_SQLITE, "", "", "file::memory:?cache=shared"); + auto connFactory = ConnFactoryFactory::create(login); + auto conn = connFactory->create(); + + ASSERT_TRUE(conn->getTableNames().empty()); + + auto stmt = conn->createStmt(sql, rdbms::AutocommitMode::ON); + stmt->executeNonQuery(); + + ASSERT_EQ(1, conn->getTableNames().size()); + } +} + +} // namespace unitTests diff --git a/rdbms/OcciColumn.cpp b/rdbms/wrapper/OcciColumn.cpp similarity index 98% rename from rdbms/OcciColumn.cpp rename to rdbms/wrapper/OcciColumn.cpp index 7e29e1193857497356916e7ee28d6a7dd9bbf649..86c7f11902ae8eaffb3a6e94c32707dde38c5813 100644 --- a/rdbms/OcciColumn.cpp +++ b/rdbms/wrapper/OcciColumn.cpp @@ -17,10 +17,11 @@ */ #include "common/exception/Exception.hpp" -#include "rdbms/OcciColumn.hpp" +#include "rdbms/wrapper/OcciColumn.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor @@ -149,5 +150,6 @@ void OcciColumn::copyStrIntoField(const size_t index, const std::string &str) { } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciColumn.hpp b/rdbms/wrapper/OcciColumn.hpp similarity index 98% rename from rdbms/OcciColumn.hpp rename to rdbms/wrapper/OcciColumn.hpp index 4fa8f2059591172e3497c8c22b41d71ccdd7e478..af926721f4155beaf03b6d7ecd00d0d4dbb5f911 100644 --- a/rdbms/OcciColumn.hpp +++ b/rdbms/wrapper/OcciColumn.hpp @@ -18,14 +18,14 @@ #pragma once -#include "catalogue/RdbmsCatalogue.hpp" - +#include <memory> #include <occi.h> #include <string.h> #include <typeinfo> namespace cta { namespace rdbms { +namespace wrapper { /** * A class to help with preparing batch inserts and updatesi with the OCCI @@ -210,5 +210,6 @@ private: }; // OcciColumn +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciColumnTest.cpp b/rdbms/wrapper/OcciColumnTest.cpp similarity index 77% rename from rdbms/OcciColumnTest.cpp rename to rdbms/wrapper/OcciColumnTest.cpp index af834309fb1103148db4d73d3ddc8274d3a53fe2..29d5b870c15ee78a377dddce9380b3881a1c9d42 100644 --- a/rdbms/OcciColumnTest.cpp +++ b/rdbms/wrapper/OcciColumnTest.cpp @@ -16,13 +16,14 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "OcciColumn.hpp" +#include "common/exception/Exception.hpp" +#include "rdbms/wrapper/OcciColumn.hpp" #include <gtest/gtest.h> namespace unitTests { -class cta_rdbms_OcciColumnTest : public ::testing::Test { +class cta_rdbms_wrapper_OcciColumnTest : public ::testing::Test { protected: virtual void SetUp() { @@ -32,9 +33,9 @@ protected: } }; -TEST_F(cta_rdbms_OcciColumnTest, getColName) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, getColName) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; @@ -43,9 +44,9 @@ TEST_F(cta_rdbms_OcciColumnTest, getColName) { ASSERT_EQ(colName, col.getColName()); } -TEST_F(cta_rdbms_OcciColumnTest, getNbRows) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, getNbRows) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; @@ -54,9 +55,9 @@ TEST_F(cta_rdbms_OcciColumnTest, getNbRows) { ASSERT_EQ(nbRows, col.getNbRows()); } -TEST_F(cta_rdbms_OcciColumnTest, setFieldLen) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, setFieldLen) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; @@ -69,9 +70,9 @@ TEST_F(cta_rdbms_OcciColumnTest, setFieldLen) { ASSERT_EQ(5, col.getMaxFieldLength()); } -TEST_F(cta_rdbms_OcciColumnTest, setFieldLenToValueLen_stringValue) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, setFieldLenToValueLen_stringValue) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; @@ -84,9 +85,9 @@ TEST_F(cta_rdbms_OcciColumnTest, setFieldLenToValueLen_stringValue) { ASSERT_EQ(field0Value.length() + 1, col.getMaxFieldLength()); } -TEST_F(cta_rdbms_OcciColumnTest, setFieldLenToValueLen_uint64_tValue) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, setFieldLenToValueLen_uint64_tValue) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; @@ -99,9 +100,9 @@ TEST_F(cta_rdbms_OcciColumnTest, setFieldLenToValueLen_uint64_tValue) { ASSERT_EQ(5, col.getMaxFieldLength()); } -TEST_F(cta_rdbms_OcciColumnTest, setFieldLen_tooLate) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, setFieldLen_tooLate) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 2; @@ -116,9 +117,9 @@ TEST_F(cta_rdbms_OcciColumnTest, setFieldLen_tooLate) { ASSERT_THROW(col.setFieldLenToValueLen(1, field1Value), exception::Exception); } -TEST_F(cta_rdbms_OcciColumnTest, setFieldLen_invalidIndex) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, setFieldLen_invalidIndex) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; @@ -128,9 +129,9 @@ TEST_F(cta_rdbms_OcciColumnTest, setFieldLen_invalidIndex) { ASSERT_THROW(col.setFieldLenToValueLen(1, field1Value), exception::Exception); } -TEST_F(cta_rdbms_OcciColumnTest, getFieldLengths) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, getFieldLengths) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 3; @@ -150,9 +151,9 @@ TEST_F(cta_rdbms_OcciColumnTest, getFieldLengths) { ASSERT_EQ(4, fieldLens[2]); } -TEST_F(cta_rdbms_OcciColumnTest, getBuffer) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, getBuffer) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; @@ -165,9 +166,9 @@ TEST_F(cta_rdbms_OcciColumnTest, getBuffer) { ASSERT_NE(nullptr, buf); } -TEST_F(cta_rdbms_OcciColumnTest, getBuffer_tooEarly) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, getBuffer_tooEarly) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; @@ -176,9 +177,9 @@ TEST_F(cta_rdbms_OcciColumnTest, getBuffer_tooEarly) { ASSERT_THROW(col.getBuffer(), exception::Exception); } -TEST_F(cta_rdbms_OcciColumnTest, getMaxFieldLength) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, getMaxFieldLength) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 4; @@ -196,9 +197,9 @@ TEST_F(cta_rdbms_OcciColumnTest, getMaxFieldLength) { ASSERT_EQ(4, col.getMaxFieldLength()); } -TEST_F(cta_rdbms_OcciColumnTest, copyStrIntoField_1_oneField) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, copyStrIntoField_1_oneField) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; @@ -212,9 +213,9 @@ TEST_F(cta_rdbms_OcciColumnTest, copyStrIntoField_1_oneField) { ASSERT_EQ(field0Value, std::string(buf)); } -TEST_F(cta_rdbms_OcciColumnTest, setFieldValue_twoFields) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, setFieldValue_twoFields) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 2; @@ -234,9 +235,9 @@ TEST_F(cta_rdbms_OcciColumnTest, setFieldValue_twoFields) { ASSERT_EQ(field1Value, std::string(bufField1)); } -TEST_F(cta_rdbms_OcciColumnTest, setFieldValue_tooLong) { +TEST_F(cta_rdbms_wrapper_OcciColumnTest, setFieldValue_tooLong) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const std::string colName = "TEST_COLUMN"; const size_t nbRows = 1; diff --git a/rdbms/OcciConn.cpp b/rdbms/wrapper/OcciConn.cpp similarity index 91% rename from rdbms/OcciConn.cpp rename to rdbms/wrapper/OcciConn.cpp index 36702ed5ccedad612c8ee5f9a2423d3b91ac5150..d042314fede06d04f334ef8f8ce6201c0f4294be 100644 --- a/rdbms/OcciConn.cpp +++ b/rdbms/wrapper/OcciConn.cpp @@ -19,15 +19,16 @@ #include "common/exception/Exception.hpp" #include "common/make_unique.hpp" #include "common/threading/MutexLocker.hpp" -#include "rdbms/OcciConn.hpp" -#include "rdbms/OcciEnv.hpp" -#include "rdbms/OcciStmt.hpp" +#include "rdbms/wrapper/OcciConn.hpp" +#include "rdbms/wrapper/OcciEnv.hpp" +#include "rdbms/wrapper/OcciStmt.hpp" #include <stdexcept> #include <string> namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor @@ -46,7 +47,7 @@ OcciConn::OcciConn(oracle::occi::Environment *const env, oracle::occi::Connectio //------------------------------------------------------------------------------ OcciConn::~OcciConn() throw() { try { - close(); // Idempotent close() mthod + close(); // Idempotent close() method } catch(...) { // Destructor should not throw any exceptions } @@ -67,7 +68,7 @@ void OcciConn::close() { //------------------------------------------------------------------------------ // createStmt //------------------------------------------------------------------------------ -std::unique_ptr<Stmt> OcciConn::createStmt(const std::string &sql, Stmt::AutocommitMode autocommitMode) { +std::unique_ptr<Stmt> OcciConn::createStmt(const std::string &sql, AutocommitMode autocommitMode) { try { threading::MutexLocker locker(m_mutex); @@ -139,10 +140,13 @@ std::list<std::string> OcciConn::getTableNames() { "USER_TABLES " "ORDER BY " "TABLE_NAME"; - auto stmt = createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); + auto stmt = createStmt(sql, AutocommitMode::OFF); auto rset = stmt->executeQuery(); - while (rset.next()) { - names.push_back(rset.columnString("TABLE_NAME")); + while (rset->next()) { + auto name = rset->columnOptionalString("TABLE_NAME"); + if(name) { + names.push_back(name.value()); + } } return names; @@ -164,10 +168,11 @@ std::list<std::string> OcciConn::getSequenceNames() { "USER_SEQUENCES " "ORDER BY " "SEQUENCE_NAME"; - auto stmt = createStmt(sql, rdbms::Stmt::AutocommitMode::OFF); + auto stmt = createStmt(sql, AutocommitMode::OFF); auto rset = stmt->executeQuery(); - while (rset.next()) { - names.push_back(rset.columnString("SEQUENCE_NAME")); + while (rset->next()) { + auto name = rset->columnOptionalString("SEQUENCE_NAME"); + names.push_back(name.value()); } return names; @@ -206,5 +211,6 @@ void OcciConn::closeStmt(oracle::occi::Statement *const stmt) { } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciConn.hpp b/rdbms/wrapper/OcciConn.hpp similarity index 90% rename from rdbms/OcciConn.hpp rename to rdbms/wrapper/OcciConn.hpp index 7e18d703a8224ebf1208a63e8470354f882e1e80..614a778fe2d34792f860ec56ea24834137d8c11c 100644 --- a/rdbms/OcciConn.hpp +++ b/rdbms/wrapper/OcciConn.hpp @@ -19,12 +19,13 @@ #pragma once #include "common/threading/MutexLocker.hpp" -#include "rdbms/Conn.hpp" +#include "rdbms/wrapper/Conn.hpp" #include <occi.h> namespace cta { namespace rdbms { +namespace wrapper { /** * Forward declaraion to avoid a circular dependency beween OcciConn and @@ -66,7 +67,7 @@ public: * @param autocommitMode The autocommit mode of the statement. * @return The prepared statement. */ - virtual std::unique_ptr<Stmt> createStmt(const std::string &sql, const Stmt::AutocommitMode autocommitMode) override; + virtual std::unique_ptr<Stmt> createStmt(const std::string &sql, const AutocommitMode autocommitMode) override; /** * Commits the current transaction. @@ -96,10 +97,13 @@ public: * Returns the names of all the sequences in the database schema in * alphabetical order. * + * If the underlying database technologies does not supported sequences then + * this method simply returns an empty list. + * * @return The names of all the sequences in the database schema in * alphabetical order. */ - std::list<std::string> getSequenceNames(); + virtual std::list<std::string> getSequenceNames() override; private: @@ -129,5 +133,6 @@ private: }; // class OcciConn +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciConnFactory.cpp b/rdbms/wrapper/OcciConnFactory.cpp similarity index 93% rename from rdbms/OcciConnFactory.cpp rename to rdbms/wrapper/OcciConnFactory.cpp index f1f7695261ef0541143d3326b8f4879a6bb96dd5..16f52edfa91197e88eb17a2c03a840671a525222 100644 --- a/rdbms/OcciConnFactory.cpp +++ b/rdbms/wrapper/OcciConnFactory.cpp @@ -18,11 +18,12 @@ #include "common/exception/Exception.hpp" #include "common/make_unique.hpp" -#include "OcciConnFactory.hpp" -#include "OcciEnvSingleton.hpp" +#include "rdbms/wrapper/OcciConnFactory.hpp" +#include "rdbms/wrapper/OcciEnvSingleton.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor @@ -53,5 +54,6 @@ std::unique_ptr<Conn> OcciConnFactory::create() { } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciConnFactory.hpp b/rdbms/wrapper/OcciConnFactory.hpp similarity index 95% rename from rdbms/OcciConnFactory.hpp rename to rdbms/wrapper/OcciConnFactory.hpp index cb3e42a877e22994a0560f5a63456d3c9cc78f3a..9e7cab5a2543a9a35e35dd92d63340dbeaa8cd5d 100644 --- a/rdbms/OcciConnFactory.hpp +++ b/rdbms/wrapper/OcciConnFactory.hpp @@ -18,10 +18,11 @@ #pragma once -#include "ConnFactory.hpp" +#include "rdbms/wrapper/ConnFactory.hpp" namespace cta { namespace rdbms { +namespace wrapper { /** * A concrete factory of Conn objects. @@ -72,5 +73,6 @@ private: }; // class OcciConnFactory +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciEnv.cpp b/rdbms/wrapper/OcciEnv.cpp similarity index 95% rename from rdbms/OcciEnv.cpp rename to rdbms/wrapper/OcciEnv.cpp index e290c6f13edacb01cc16466c2c020a2100aa6617..b322079fbbcdc75ec3e9f3c3ed97b28c61ee61d3 100644 --- a/rdbms/OcciEnv.cpp +++ b/rdbms/wrapper/OcciEnv.cpp @@ -16,13 +16,14 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "OcciConn.hpp" -#include "OcciEnv.hpp" #include "common/exception/Exception.hpp" #include "common/make_unique.hpp" +#include "rdbms/wrapper/OcciConn.hpp" +#include "rdbms/wrapper/OcciEnv.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor @@ -66,5 +67,6 @@ std::unique_ptr<Conn> OcciEnv::createConn( } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciEnv.hpp b/rdbms/wrapper/OcciEnv.hpp similarity index 95% rename from rdbms/OcciEnv.hpp rename to rdbms/wrapper/OcciEnv.hpp index 659e0862450141940ac2b68fe8a9d460876c3795..ae922ebc4f528d87ef4c4fb681cd762ede61af17 100644 --- a/rdbms/OcciEnv.hpp +++ b/rdbms/wrapper/OcciEnv.hpp @@ -18,13 +18,14 @@ #pragma once -#include "rdbms/Conn.hpp" +#include "rdbms/wrapper/Conn.hpp" #include <memory> #include <occi.h> namespace cta { namespace rdbms { +namespace wrapper { /** * A convenience wrapper around an OCCI environment. @@ -71,5 +72,6 @@ private: }; // class OcciEnv +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciEnvSingleton.cpp b/rdbms/wrapper/OcciEnvSingleton.cpp similarity index 96% rename from rdbms/OcciEnvSingleton.cpp rename to rdbms/wrapper/OcciEnvSingleton.cpp index 84844fff7900ae3812c1c137b51a713dea336743..551ad0dd8df9929edcfc4ebfa4e061723fde7bd3 100644 --- a/rdbms/OcciEnvSingleton.cpp +++ b/rdbms/wrapper/OcciEnvSingleton.cpp @@ -16,12 +16,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "rdbms/OcciEnvSingleton.hpp" #include "common/exception/Exception.hpp" #include "common/threading/MutexLocker.hpp" +#include "rdbms/wrapper/OcciEnvSingleton.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // s_mutex @@ -57,5 +58,6 @@ OcciEnvSingleton &OcciEnvSingleton::instance() { OcciEnvSingleton::OcciEnvSingleton() { } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciEnvSingleton.hpp b/rdbms/wrapper/OcciEnvSingleton.hpp similarity index 95% rename from rdbms/OcciEnvSingleton.hpp rename to rdbms/wrapper/OcciEnvSingleton.hpp index c6c36b2faa91edf2367955e3285a47b4fa16f5ab..a2afe8454a9c6c1071c838c162a43a314af097c9 100644 --- a/rdbms/OcciEnvSingleton.hpp +++ b/rdbms/wrapper/OcciEnvSingleton.hpp @@ -19,12 +19,13 @@ #pragma once #include "common/threading/Mutex.hpp" -#include "rdbms/OcciEnv.hpp" +#include "rdbms/wrapper/OcciEnv.hpp" #include <memory> namespace cta { namespace rdbms { +namespace wrapper { /** * A singleton version of OcciEnv. @@ -67,5 +68,6 @@ private: }; // class OcciEnvSingleton +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciRsetImpl.cpp b/rdbms/wrapper/OcciRset.cpp similarity index 90% rename from rdbms/OcciRsetImpl.cpp rename to rdbms/wrapper/OcciRset.cpp index 12b11d90573976df1cd05e37cc602ae2814dfa17..788d1f5d0ec31dd5d7a337a87118fe128dbf33f8 100644 --- a/rdbms/OcciRsetImpl.cpp +++ b/rdbms/wrapper/OcciRset.cpp @@ -16,11 +16,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "NullDbValue.hpp" -#include "OcciRsetImpl.hpp" -#include "OcciStmt.hpp" #include "common/exception/Exception.hpp" #include "common/utils/utils.hpp" +#include "rdbms/NullDbValue.hpp" +#include "rdbms/wrapper/OcciRset.hpp" +#include "rdbms/wrapper/OcciStmt.hpp" #include <cstring> #include <map> @@ -28,11 +28,12 @@ namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -OcciRsetImpl::OcciRsetImpl(OcciStmt &stmt, oracle::occi::ResultSet *const rset): +OcciRset::OcciRset(OcciStmt &stmt, oracle::occi::ResultSet *const rset): m_stmt(stmt), m_rset(rset) { try { @@ -49,7 +50,7 @@ OcciRsetImpl::OcciRsetImpl(OcciStmt &stmt, oracle::occi::ResultSet *const rset): //------------------------------------------------------------------------------ // populateColNameToIdx //------------------------------------------------------------------------------ -void OcciRsetImpl::populateColNameToIdxMap() { +void OcciRset::populateColNameToIdxMap() { using namespace oracle; try { @@ -69,7 +70,7 @@ void OcciRsetImpl::populateColNameToIdxMap() { //------------------------------------------------------------------------------ // destructor //------------------------------------------------------------------------------ -OcciRsetImpl::~OcciRsetImpl() throw() { +OcciRset::~OcciRset() throw() { try { close(); // Idempotent close() } catch(...) { @@ -80,14 +81,14 @@ OcciRsetImpl::~OcciRsetImpl() throw() { //------------------------------------------------------------------------------ // getSql //------------------------------------------------------------------------------ -const std::string &OcciRsetImpl::getSql() const { +const std::string &OcciRset::getSql() const { return m_stmt.getSql(); } //------------------------------------------------------------------------------ // next //------------------------------------------------------------------------------ -bool OcciRsetImpl::next() { +bool OcciRset::next() { using namespace oracle; try { @@ -102,7 +103,7 @@ bool OcciRsetImpl::next() { //------------------------------------------------------------------------------ // columnIsNull //------------------------------------------------------------------------------ -bool OcciRsetImpl::columnIsNull(const std::string &colName) const { +bool OcciRset::columnIsNull(const std::string &colName) const { try { const int colIdx = m_colNameToIdx.getIdx(colName); return m_rset->isNull(colIdx); @@ -116,7 +117,7 @@ bool OcciRsetImpl::columnIsNull(const std::string &colName) const { //------------------------------------------------------------------------------ // close //------------------------------------------------------------------------------ -void OcciRsetImpl::close() { +void OcciRset::close() { threading::Mutex locker(m_mutex); if(nullptr != m_rset) { @@ -128,7 +129,7 @@ void OcciRsetImpl::close() { //------------------------------------------------------------------------------ // columnOptionalString //------------------------------------------------------------------------------ -optional<std::string> OcciRsetImpl::columnOptionalString(const std::string &colName) const { +optional<std::string> OcciRset::columnOptionalString(const std::string &colName) const { try { const int colIdx = m_colNameToIdx.getIdx(colName); const std::string stringValue = m_rset->getString(colIdx); @@ -148,7 +149,7 @@ optional<std::string> OcciRsetImpl::columnOptionalString(const std::string &colN //------------------------------------------------------------------------------ // columnOptionalUint64 //------------------------------------------------------------------------------ -optional<uint64_t> OcciRsetImpl::columnOptionalUint64(const std::string &colName) const { +optional<uint64_t> OcciRset::columnOptionalUint64(const std::string &colName) const { try { threading::Mutex locker(m_mutex); @@ -171,5 +172,6 @@ optional<uint64_t> OcciRsetImpl::columnOptionalUint64(const std::string &colName } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciRsetImpl.hpp b/rdbms/wrapper/OcciRset.hpp similarity index 91% rename from rdbms/OcciRsetImpl.hpp rename to rdbms/wrapper/OcciRset.hpp index d6cc3ca54827c2a849398b88f2473209ead03213..bad427edb7d5b0dfa3dfbc615b425920aeea4942 100644 --- a/rdbms/OcciRsetImpl.hpp +++ b/rdbms/wrapper/OcciRset.hpp @@ -19,14 +19,15 @@ #pragma once #include "common/threading/Mutex.hpp" -#include "rdbms/ColumnNameToIdx.hpp" -#include "rdbms/RsetImpl.hpp" +#include "rdbms/wrapper/ColumnNameToIdx.hpp" +#include "rdbms/wrapper/Rset.hpp" #include <memory> #include <occi.h> namespace cta { namespace rdbms { +namespace wrapper { /** * Forward declaration to avoid a circular dependency between OcciRset and @@ -37,7 +38,7 @@ class OcciStmt; /** * A convenience wrapper around an OCCI result set. */ -class OcciRsetImpl: public RsetImpl { +class OcciRset: public Rset { public: /** @@ -49,12 +50,12 @@ public: * @param stmt The OCCI statement. * @param rset The OCCI result set. */ - OcciRsetImpl(OcciStmt &stmt, oracle::occi::ResultSet *const rset); + OcciRset(OcciStmt &stmt, oracle::occi::ResultSet *const rset); /** * Destructor. */ - virtual ~OcciRsetImpl() throw() override; + virtual ~OcciRset() throw() override; /** * Returns the SQL statement. @@ -131,7 +132,8 @@ private: */ void populateColNameToIdxMap(); -}; // class OcciRsetImpl +}; // class OcciRset +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciStmt.cpp b/rdbms/wrapper/OcciStmt.cpp similarity index 94% rename from rdbms/OcciStmt.cpp rename to rdbms/wrapper/OcciStmt.cpp index 320be053b6f8e77b2d2ddf80b3e85bfd8e01a78d..3337affdf298bc5ee02a4acfa01caf4d740bf939 100644 --- a/rdbms/OcciStmt.cpp +++ b/rdbms/wrapper/OcciStmt.cpp @@ -19,10 +19,10 @@ #include "common/exception/Exception.hpp" #include "common/make_unique.hpp" #include "common/threading/MutexLocker.hpp" -#include "rdbms/OcciColumn.hpp" -#include "rdbms/OcciConn.hpp" -#include "rdbms/OcciRsetImpl.hpp" -#include "rdbms/OcciStmt.hpp" +#include "rdbms/wrapper/OcciColumn.hpp" +#include "rdbms/wrapper/OcciConn.hpp" +#include "rdbms/wrapper/OcciRset.hpp" +#include "rdbms/wrapper/OcciStmt.hpp" #include <cstring> #include <map> @@ -31,6 +31,7 @@ namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor @@ -79,6 +80,12 @@ OcciStmt::~OcciStmt() throw() { } } +//------------------------------------------------------------------------------ +// clear +//------------------------------------------------------------------------------ +void OcciStmt::clear() { +} + //------------------------------------------------------------------------------ // close //------------------------------------------------------------------------------ @@ -170,11 +177,11 @@ void OcciStmt::bindOptionalString(const std::string ¶mName, const optional<s //------------------------------------------------------------------------------ // executeQuery //------------------------------------------------------------------------------ -Rset OcciStmt::executeQuery() { +std::unique_ptr<Rset> OcciStmt::executeQuery() { using namespace oracle; try { - return Rset(new OcciRsetImpl(*this, m_stmt->executeQuery())); + return cta::make_unique<OcciRset>(*this, m_stmt->executeQuery()); } catch(occi::SQLException &ex) { if(connShouldBeClosed(ex)) { // Close the statement first and then the connection @@ -283,5 +290,6 @@ bool OcciStmt::connShouldBeClosed(const oracle::occi::SQLException &ex) { }; } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/OcciStmt.hpp b/rdbms/wrapper/OcciStmt.hpp similarity index 94% rename from rdbms/OcciStmt.hpp rename to rdbms/wrapper/OcciStmt.hpp index a180db9f3d877c0bec3f85af5415e75c5c45cd33..5b58998eed81a81ddb78ee77d939471bb992ce7b 100644 --- a/rdbms/OcciStmt.hpp +++ b/rdbms/wrapper/OcciStmt.hpp @@ -19,7 +19,7 @@ #pragma once #include "common/threading/Mutex.hpp" -#include "rdbms/Stmt.hpp" +#include "rdbms/wrapper/Stmt.hpp" #include <memory> #include <occi.h> @@ -27,6 +27,7 @@ namespace cta { namespace rdbms { +namespace wrapper { /** * Forward declaration to avoid a circular dependency between OcciStmt and @@ -38,7 +39,7 @@ class OcciConn; * Forward declaration to avoid a circular dependency between OcciStmt and * OcciRset. */ -class OcciRsetImpl; +class OcciRset; class OcciColumn; @@ -72,6 +73,11 @@ public: */ OcciStmt(const OcciStmt &) = delete; + /** + * Clears the prepared statement so that it is ready to be reused. + */ + void clear() override; + /** * Idempotent close() method. The destructor calls this method. */ @@ -122,7 +128,7 @@ public: * * @return The result set. */ - Rset executeQuery() override; + std::unique_ptr<Rset> executeQuery() override; /** * Executes the statement. @@ -186,5 +192,6 @@ private: }; // class OcciStmt +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ParamNameToIdx.cpp b/rdbms/wrapper/ParamNameToIdx.cpp similarity index 97% rename from rdbms/ParamNameToIdx.cpp rename to rdbms/wrapper/ParamNameToIdx.cpp index 8173850517892b63508bd352093c2da16c3ce16a..00aeadafa6f2095678813aac9788f6ba4ad1a488 100644 --- a/rdbms/ParamNameToIdx.cpp +++ b/rdbms/wrapper/ParamNameToIdx.cpp @@ -16,13 +16,14 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ParamNameToIdx.hpp" #include "common/exception/Exception.hpp" +#include "rdbms/wrapper/ParamNameToIdx.hpp" #include <sstream> namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor @@ -90,5 +91,6 @@ uint32_t ParamNameToIdx::getIdx(const std::string ¶mName) const { return itor->second; } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ParamNameToIdx.hpp b/rdbms/wrapper/ParamNameToIdx.hpp similarity index 97% rename from rdbms/ParamNameToIdx.hpp rename to rdbms/wrapper/ParamNameToIdx.hpp index 3ab4d175da2f1a2650f20702d14c2962c3184883..79c79eb6c910a5484998bf267a335a1005a635bc 100644 --- a/rdbms/ParamNameToIdx.hpp +++ b/rdbms/wrapper/ParamNameToIdx.hpp @@ -22,6 +22,7 @@ namespace cta { namespace rdbms { +namespace wrapper { /** * Map from SQL parameter name to parameter index. @@ -65,5 +66,6 @@ private: }; // class ParamNameToIdx +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/ParamNameToIdxTest.cpp b/rdbms/wrapper/ParamNameToIdxTest.cpp similarity index 88% rename from rdbms/ParamNameToIdxTest.cpp rename to rdbms/wrapper/ParamNameToIdxTest.cpp index 7ded28ade1a364948f6f0e2cb76dec084ac4f9e8..380ab4a2bffb280df8440d5d31adb93cc037d787 100644 --- a/rdbms/ParamNameToIdxTest.cpp +++ b/rdbms/wrapper/ParamNameToIdxTest.cpp @@ -16,15 +16,15 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ParamNameToIdx.hpp" #include "common/exception/Exception.hpp" +#include "rdbms/wrapper/ParamNameToIdx.hpp" #include <gtest/gtest.h> #include <sstream> namespace unitTests { -class cta_rdbms_ParamNameToIdxTest : public ::testing::Test { +class cta_rdbms_wrapper_ParamNameToIdxTest : public ::testing::Test { protected: virtual void SetUp() { @@ -34,8 +34,8 @@ protected: } }; -TEST_F(cta_rdbms_ParamNameToIdxTest, getIdx_existing_params) { - using namespace cta::rdbms; +TEST_F(cta_rdbms_wrapper_ParamNameToIdxTest, getIdx_existing_params) { + using namespace cta::rdbms::wrapper; const char *const sql = "INSERT INTO ADMIN_USER(" @@ -80,9 +80,9 @@ TEST_F(cta_rdbms_ParamNameToIdxTest, getIdx_existing_params) { ASSERT_EQ(10, paramNameToIdx.getIdx(":LAST_UPDATE_TIME")); } -TEST_F(cta_rdbms_ParamNameToIdxTest, getIdx_non_existing_param) { +TEST_F(cta_rdbms_wrapper_ParamNameToIdxTest, getIdx_non_existing_param) { using namespace cta; - using namespace cta::rdbms; + using namespace cta::rdbms::wrapper; const char *const sql = "String containing no bind parameters"; diff --git a/rdbms/RsetImpl.cpp b/rdbms/wrapper/Rset.cpp similarity index 90% rename from rdbms/RsetImpl.cpp rename to rdbms/wrapper/Rset.cpp index 6eb67a189cb3c47d91b1fa85adef93a08470ba82..9448304a56cda20a241676166549e19803924c96 100644 --- a/rdbms/RsetImpl.cpp +++ b/rdbms/wrapper/Rset.cpp @@ -16,16 +16,18 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "rdbms/RsetImpl.hpp" +#include "rdbms/wrapper/Rset.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // destructor //------------------------------------------------------------------------------ -RsetImpl::~RsetImpl() throw() { +Rset::~Rset() throw() { } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/RsetImpl.hpp b/rdbms/wrapper/Rset.hpp similarity index 95% rename from rdbms/RsetImpl.hpp rename to rdbms/wrapper/Rset.hpp index 72db6ed246e8dbd6eb9a4a9bbb3d763c0dcaa8d0..bcc98870d73496dc43e156732aaa3d3cb843d0bb 100644 --- a/rdbms/RsetImpl.hpp +++ b/rdbms/wrapper/Rset.hpp @@ -25,18 +25,19 @@ namespace cta { namespace rdbms { +namespace wrapper { /** * Abstract class specifying the interface to an implementation of the result * set of an sql query. */ -class RsetImpl { +class Rset { public: /** * Destructor. */ - virtual ~RsetImpl() throw() = 0; + virtual ~Rset() throw() = 0; /** * Returns the SQL statement. @@ -81,7 +82,8 @@ public: */ virtual optional<uint64_t> columnOptionalUint64(const std::string &colName) const = 0; -}; // class RsetImpl +}; // class Rset +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/Sqlite.cpp b/rdbms/wrapper/Sqlite.cpp similarity index 96% rename from rdbms/Sqlite.cpp rename to rdbms/wrapper/Sqlite.cpp index 52ae52af15b6636c047478c0d894c77da0ccb16c..287aeab85b9933707c2759b735ec925bd47d9a72 100644 --- a/rdbms/Sqlite.cpp +++ b/rdbms/wrapper/Sqlite.cpp @@ -16,12 +16,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Sqlite.hpp" +#include "rdbms/wrapper/Sqlite.hpp" #include <sstream> namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // rcToStr @@ -33,7 +34,7 @@ std::string Sqlite::rcToStr(const int rc) { case SQLITE_AUTH: return "Authorization denied"; case SQLITE_BUSY: - return "Failed to take locks"; + return "Busy"; case SQLITE_CANTOPEN: return "Cannot open database file"; case SQLITE_CONSTRAINT: @@ -90,5 +91,6 @@ std::string Sqlite::rcToStr(const int rc) { } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/Sqlite.hpp b/rdbms/wrapper/Sqlite.hpp similarity index 96% rename from rdbms/Sqlite.hpp rename to rdbms/wrapper/Sqlite.hpp index b69abf7991a649efac86a2ae712109c611eb7da2..93c46f975c9d20e7368a3290bd3fe61e23e02bff 100644 --- a/rdbms/Sqlite.hpp +++ b/rdbms/wrapper/Sqlite.hpp @@ -23,6 +23,7 @@ namespace cta { namespace rdbms { +namespace wrapper { /** * A helper class for working with SQLite. @@ -40,5 +41,6 @@ public: }; // class SqlLiteStmt +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/SqliteConn.cpp b/rdbms/wrapper/SqliteConn.cpp similarity index 81% rename from rdbms/SqliteConn.cpp rename to rdbms/wrapper/SqliteConn.cpp index 3b08df7341d0cdb16c54a427f0f3907ed93be97f..98ad9a79c277754bb44d5f36bc47256708709aed 100644 --- a/rdbms/SqliteConn.cpp +++ b/rdbms/wrapper/SqliteConn.cpp @@ -19,14 +19,17 @@ #include "common/exception/Exception.hpp" #include "common/make_unique.hpp" #include "common/threading/MutexLocker.hpp" -#include "rdbms/SqliteConn.hpp" -#include "rdbms/SqliteStmt.hpp" +#include "rdbms/wrapper/Sqlite.hpp" +#include "rdbms/wrapper/SqliteConn.hpp" +#include "rdbms/wrapper/SqliteStmt.hpp" +#include <iostream> #include <stdexcept> #include <string> namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor @@ -66,7 +69,11 @@ SqliteConn::SqliteConn(const std::string &filename): // destructor //------------------------------------------------------------------------------ SqliteConn::~SqliteConn() throw() { - close(); + try { + close(); // Idempotent close() method + } catch(...) { + // Destructor should not throw any exceptions + } } //------------------------------------------------------------------------------ @@ -76,7 +83,12 @@ void SqliteConn::close() { threading::MutexLocker locker(m_mutex); if(nullptr != m_sqliteConn) { - sqlite3_close(m_sqliteConn); + const int closeRc = sqlite3_close(m_sqliteConn); + if(SQLITE_OK != closeRc) { + exception::Exception ex; + ex.getMessage() << "Failed to close SQLite connection: " << Sqlite::rcToStr(closeRc); + throw ex; + } m_sqliteConn = nullptr; } } @@ -84,7 +96,7 @@ void SqliteConn::close() { //------------------------------------------------------------------------------ // createStmt //------------------------------------------------------------------------------ -std::unique_ptr<Stmt> SqliteConn::createStmt(const std::string &sql, const Stmt::AutocommitMode autocommitMode) { +std::unique_ptr<Stmt> SqliteConn::createStmt(const std::string &sql, const AutocommitMode autocommitMode) { try { threading::MutexLocker locker(m_mutex); @@ -170,14 +182,14 @@ void SqliteConn::printSchema(std::ostream &os) { "ORDER BY " "TYPE, " "NAME;"; - auto stmt = createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = createStmt(sql, AutocommitMode::ON); auto rset = stmt->executeQuery(); os << "NAME, TYPE" << std::endl; os << "==========" << std::endl; - while (rset.next()) { - const std::string name = rset.columnString("NAME"); - const std::string type = rset.columnString("TYPE"); - os << name << ", " << type << std::endl; + while (rset->next()) { + const auto name = rset->columnOptionalString("NAME"); + const auto type = rset->columnOptionalString("TYPE"); + os << (name ? name.value() : "NULL") << ", " << (type ? type.value() : "NULL") << std::endl; } } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); @@ -198,11 +210,14 @@ std::list<std::string> SqliteConn::getTableNames() { "TYPE = 'table' " "ORDER BY " "NAME;"; - auto stmt = createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = createStmt(sql, AutocommitMode::ON); auto rset = stmt->executeQuery(); std::list<std::string> names; - while (rset.next()) { - names.push_back(rset.columnString("NAME")); + while (rset->next()) { + auto name = rset->columnOptionalString("NAME"); + if(name) { + names.push_back(name.value()); + } } return names; } catch(exception::Exception &ex) { @@ -217,5 +232,17 @@ bool SqliteConn::isOpen() const { return nullptr != m_sqliteConn; } +//------------------------------------------------------------------------------ +// getSequenceNames +//------------------------------------------------------------------------------ +std::list<std::string> SqliteConn::getSequenceNames() { + try { + return std::list<std::string>(); + } catch(exception::Exception &ex) { + throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); + } +} + +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/SqliteConn.hpp b/rdbms/wrapper/SqliteConn.hpp similarity index 85% rename from rdbms/SqliteConn.hpp rename to rdbms/wrapper/SqliteConn.hpp index d8f3df7bd997ec5a91e68d8eec42adb95b86996c..ee66e6749c80186e375446a710aa89e931c9748c 100644 --- a/rdbms/SqliteConn.hpp +++ b/rdbms/wrapper/SqliteConn.hpp @@ -19,12 +19,13 @@ #pragma once #include "common/threading/Mutex.hpp" -#include "rdbms/Conn.hpp" +#include "rdbms/wrapper/Conn.hpp" #include <sqlite3.h> namespace cta { namespace rdbms { +namespace wrapper { /** * Forward declaration to avoid a circular dependency between SqliteConn and @@ -68,7 +69,7 @@ public: * @param autocommitMode The autocommit mode of the statement. * @return The prepared statement. */ - std::unique_ptr<Stmt> createStmt(const std::string &sql, const Stmt::AutocommitMode autocommitMode) override; + std::unique_ptr<Stmt> createStmt(const std::string &sql, const AutocommitMode autocommitMode) override; /** * Commits the current transaction. @@ -94,6 +95,18 @@ public: */ bool isOpen() const override; + /** + * Returns the names of all the sequences in the database schema in + * alphabetical order. + * + * If the underlying database technologies does not supported sequences then + * this method simply returns an empty list. + * + * @return The names of all the sequences in the database schema in + * alphabetical order. + */ + std::list<std::string> getSequenceNames() override; + /** * This ia an SqliteConn specific method that prints the database schema to * the specified output stream. @@ -124,5 +137,6 @@ private: }; // class SqliteConn +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/SqliteConnFactory.cpp b/rdbms/wrapper/SqliteConnFactory.cpp similarity index 93% rename from rdbms/SqliteConnFactory.cpp rename to rdbms/wrapper/SqliteConnFactory.cpp index f7898e1087af491730f384d7905b510269a1fca9..72bdecd387f5f9aa66117c301330f1df0e634b72 100644 --- a/rdbms/SqliteConnFactory.cpp +++ b/rdbms/wrapper/SqliteConnFactory.cpp @@ -18,11 +18,12 @@ #include "common/exception/Exception.hpp" #include "common/make_unique.hpp" -#include "SqliteConn.hpp" -#include "SqliteConnFactory.hpp" +#include "rdbms/wrapper/SqliteConn.hpp" +#include "rdbms/wrapper/SqliteConnFactory.hpp" namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor @@ -48,5 +49,6 @@ std::unique_ptr<Conn> SqliteConnFactory::create() { } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/SqliteConnFactory.hpp b/rdbms/wrapper/SqliteConnFactory.hpp similarity index 94% rename from rdbms/SqliteConnFactory.hpp rename to rdbms/wrapper/SqliteConnFactory.hpp index a1838c9921cfc7a016d8e3b58a710dc6e0dfcc1d..b04c5e98a6fa856025c667b0f3e054658ce913b4 100644 --- a/rdbms/SqliteConnFactory.hpp +++ b/rdbms/wrapper/SqliteConnFactory.hpp @@ -18,10 +18,11 @@ #pragma once -#include "ConnFactory.hpp" +#include "rdbms/wrapper/ConnFactory.hpp" namespace cta { namespace rdbms { +namespace wrapper { /** * A concrete factory of Conn objects. @@ -57,5 +58,6 @@ private: }; // class SqliteConnFactory +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/SqliteRsetImpl.cpp b/rdbms/wrapper/SqliteRset.cpp similarity index 91% rename from rdbms/SqliteRsetImpl.cpp rename to rdbms/wrapper/SqliteRset.cpp index f16144e65dc01c403e2a1468d92b965b53176260..1a45e1ffb63dd7ef297afc3311d3a01755d17ae1 100644 --- a/rdbms/SqliteRsetImpl.cpp +++ b/rdbms/wrapper/SqliteRset.cpp @@ -16,12 +16,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "NullDbValue.hpp" -#include "Sqlite.hpp" -#include "SqliteRsetImpl.hpp" -#include "SqliteStmt.hpp" #include "common/exception/Exception.hpp" #include "common/exception/Errnum.hpp" +#include "rdbms/NullDbValue.hpp" +#include "rdbms/wrapper/Sqlite.hpp" +#include "rdbms/wrapper/SqliteRset.hpp" +#include "rdbms/wrapper/SqliteStmt.hpp" #include <cstring> #include <sstream> @@ -30,6 +30,7 @@ namespace cta { namespace rdbms { +namespace wrapper { /** * A map from column name to column index and type. @@ -120,31 +121,31 @@ private: */ std::map<std::string, IdxAndType> m_nameToIdxAndType; -}; // class SqliteRsetImpl::ColNameToIdx +}; // class SqliteRset::ColNameToIdx //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -SqliteRsetImpl::SqliteRsetImpl(SqliteStmt &stmt): m_stmt(stmt) { +SqliteRset::SqliteRset(SqliteStmt &stmt): m_stmt(stmt) { } //------------------------------------------------------------------------------ // destructor. //------------------------------------------------------------------------------ -SqliteRsetImpl::~SqliteRsetImpl() throw() { +SqliteRset::~SqliteRset() throw() { } //------------------------------------------------------------------------------ // getSql //------------------------------------------------------------------------------ -const std::string &SqliteRsetImpl::getSql() const { +const std::string &SqliteRset::getSql() const { return m_stmt.getSql(); } //------------------------------------------------------------------------------ // next //------------------------------------------------------------------------------ -bool SqliteRsetImpl::next() { +bool SqliteRset::next() { try { const int stepRc = sqlite3_step(m_stmt.get()); @@ -159,7 +160,7 @@ bool SqliteRsetImpl::next() { return SQLITE_ROW == stepRc; } catch(exception::Exception &ex) { - throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + m_stmt.getSql() + + throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + m_stmt.getSqlForException() + ": " + ex.getMessage().str()); } } @@ -167,7 +168,7 @@ bool SqliteRsetImpl::next() { //------------------------------------------------------------------------------ // clearAndPopulateColNameToIdxMap //------------------------------------------------------------------------------ -void SqliteRsetImpl::clearAndPopulateColNameToIdxAndTypeMap() { +void SqliteRset::clearAndPopulateColNameToIdxAndTypeMap() { try { m_colNameToIdxAndType.clear(); @@ -197,7 +198,7 @@ void SqliteRsetImpl::clearAndPopulateColNameToIdxAndTypeMap() { //------------------------------------------------------------------------------ // columnIsNull //------------------------------------------------------------------------------ -bool SqliteRsetImpl::columnIsNull(const std::string &colName) const { +bool SqliteRset::columnIsNull(const std::string &colName) const { try { const ColumnNameToIdxAndType::IdxAndType idxAndType = m_colNameToIdxAndType.getIdxAndType(colName); return SQLITE_NULL == idxAndType.colType; @@ -209,7 +210,7 @@ bool SqliteRsetImpl::columnIsNull(const std::string &colName) const { //------------------------------------------------------------------------------ // columnOptionalString //------------------------------------------------------------------------------ -optional<std::string> SqliteRsetImpl::columnOptionalString(const std::string &colName) const { +optional<std::string> SqliteRset::columnOptionalString(const std::string &colName) const { try { const ColumnNameToIdxAndType::IdxAndType idxAndType = m_colNameToIdxAndType.getIdxAndType(colName); if(SQLITE_NULL == idxAndType.colType) { @@ -232,7 +233,7 @@ optional<std::string> SqliteRsetImpl::columnOptionalString(const std::string &co //------------------------------------------------------------------------------ // columnOptionalUint64 //------------------------------------------------------------------------------ -optional<uint64_t> SqliteRsetImpl::columnOptionalUint64(const std::string &colName) const { +optional<uint64_t> SqliteRset::columnOptionalUint64(const std::string &colName) const { try { const ColumnNameToIdxAndType::IdxAndType idxAndType = m_colNameToIdxAndType.getIdxAndType(colName); if(SQLITE_NULL == idxAndType.colType) { @@ -245,5 +246,6 @@ optional<uint64_t> SqliteRsetImpl::columnOptionalUint64(const std::string &colNa } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/SqliteRsetImpl.hpp b/rdbms/wrapper/SqliteRset.hpp similarity index 92% rename from rdbms/SqliteRsetImpl.hpp rename to rdbms/wrapper/SqliteRset.hpp index 8aaee093ec3fe6b053184b488e1e027fb9cb834b..0bda5b1e29543c6308096290212e46bdc2895d3e 100644 --- a/rdbms/SqliteRsetImpl.hpp +++ b/rdbms/wrapper/SqliteRset.hpp @@ -18,8 +18,8 @@ #pragma once -#include "rdbms/ColumnNameToIdxAndType.hpp" -#include "rdbms/RsetImpl.hpp" +#include "rdbms/wrapper/ColumnNameToIdxAndType.hpp" +#include "rdbms/wrapper/Rset.hpp" #include <memory> #include <stdint.h> @@ -27,6 +27,7 @@ namespace cta { namespace rdbms { +namespace wrapper { /** * Forward declaration. @@ -36,7 +37,7 @@ class SqliteStmt; /** * The result set of an sql query. */ -class SqliteRsetImpl: public RsetImpl { +class SqliteRset: public Rset { public: /** @@ -44,12 +45,12 @@ public: * * @param stmt The prepared statement. */ - SqliteRsetImpl(SqliteStmt &stmt); + SqliteRset(SqliteStmt &stmt); /** * Destructor. */ - ~SqliteRsetImpl() throw() override; + ~SqliteRset() throw() override; /** * Returns the SQL statement. @@ -113,5 +114,6 @@ private: }; // class SqlLiteRset +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/SqliteStmt.cpp b/rdbms/wrapper/SqliteStmt.cpp similarity index 82% rename from rdbms/SqliteStmt.cpp rename to rdbms/wrapper/SqliteStmt.cpp index 76b61a37945e315e273b180a4b93e1a5d49447f0..68886b2b4c32bc14fa4fe043ab524572eac6a104 100644 --- a/rdbms/SqliteStmt.cpp +++ b/rdbms/wrapper/SqliteStmt.cpp @@ -19,12 +19,13 @@ #include "common/exception/Exception.hpp" #include "common/make_unique.hpp" #include "common/threading/MutexLocker.hpp" -#include "rdbms/Sqlite.hpp" -#include "rdbms/SqliteConn.hpp" -#include "rdbms/SqliteRsetImpl.hpp" -#include "rdbms/SqliteStmt.hpp" +#include "rdbms/wrapper/Sqlite.hpp" +#include "rdbms/wrapper/SqliteConn.hpp" +#include "rdbms/wrapper/SqliteRset.hpp" +#include "rdbms/wrapper/SqliteStmt.hpp" #include <cstring> +#include <iostream> #include <stdexcept> #include <stdlib.h> #include <string> @@ -32,6 +33,7 @@ namespace cta { namespace rdbms { +namespace wrapper { //------------------------------------------------------------------------------ // constructor @@ -114,15 +116,47 @@ SqliteStmt::~SqliteStmt() throw() { } } +//------------------------------------------------------------------------------ +// clear +//------------------------------------------------------------------------------ +void SqliteStmt::clear() { + try { + threading::MutexLocker locker(m_mutex); + + if(nullptr != m_stmt) { + const int resetRc = sqlite3_reset(m_stmt); + if(SQLITE_OK != resetRc) { + exception::Exception ex; + ex.getMessage() <<"sqlite3_reset failed: " << Sqlite::rcToStr(resetRc); + } + const int clearBindingsRc = sqlite3_clear_bindings(m_stmt); + if(SQLITE_OK != clearBindingsRc) { + exception::Exception ex; + ex.getMessage() <<"sqlite3_clear_bindings failed: " << Sqlite::rcToStr(clearBindingsRc); + } + } + } catch(exception::Exception &ex) { + throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); + } +} + //------------------------------------------------------------------------------ // close //------------------------------------------------------------------------------ void SqliteStmt::close() { - threading::MutexLocker locker(m_mutex); + try { + threading::MutexLocker locker(m_mutex); - if(nullptr != m_stmt) { - sqlite3_finalize(m_stmt); - m_stmt = nullptr; + if (nullptr != m_stmt) { + const int finalizeRc = sqlite3_finalize(m_stmt); + if (SQLITE_OK != finalizeRc) { + exception::Exception ex; + ex.getMessage() <<"sqlite3_finalize failed: " << Sqlite::rcToStr(finalizeRc); + } + m_stmt = nullptr; + } + } catch(exception::Exception &ex) { + throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str()); } } @@ -161,7 +195,9 @@ void SqliteStmt::bindOptionalUint64(const std::string ¶mName, const optional bindRc = sqlite3_bind_null(m_stmt, paramIdx); } if(SQLITE_OK != bindRc) { - throw exception::Exception("sqlite3_bind_int64() failed"); + exception::Exception ex; + ex.getMessage() << "sqlite3_bind_int64() failed: " << Sqlite::rcToStr(bindRc); + throw ex; } } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + @@ -197,7 +233,10 @@ void SqliteStmt::bindOptionalString(const std::string ¶mName, const optional bindRc = sqlite3_bind_null(m_stmt, paramIdx); } if(SQLITE_OK != bindRc) { - throw exception::Exception("sqlite3_bind_text() failed"); + exception::Exception ex; + + ex.getMessage() << "sqlite3_bind_text() failed: " << Sqlite::rcToStr(bindRc); + throw ex; } } catch(exception::Exception &ex) { throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + @@ -208,8 +247,8 @@ void SqliteStmt::bindOptionalString(const std::string ¶mName, const optional //------------------------------------------------------------------------------ // executeQuery //------------------------------------------------------------------------------ -Rset SqliteStmt::executeQuery() { - return Rset(new SqliteRsetImpl(*this)); +std::unique_ptr<Rset> SqliteStmt::executeQuery() { + return cta::make_unique<SqliteRset>(*this); } //------------------------------------------------------------------------------ @@ -262,5 +301,6 @@ void SqliteStmt::beginDeferredTransaction() { } } +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/SqliteStmt.hpp b/rdbms/wrapper/SqliteStmt.hpp similarity index 94% rename from rdbms/SqliteStmt.hpp rename to rdbms/wrapper/SqliteStmt.hpp index 3d0cee5ad7a5b209191612883703bedba070efcd..bf0bdb9b9965cb9ee8abb0cadb70ee9d6146f9ae 100644 --- a/rdbms/SqliteStmt.hpp +++ b/rdbms/wrapper/SqliteStmt.hpp @@ -19,7 +19,7 @@ #pragma once #include "common/threading/Mutex.hpp" -#include "rdbms/Stmt.hpp" +#include "rdbms/wrapper/Stmt.hpp" #include <map> #include <memory> @@ -28,9 +28,10 @@ namespace cta { namespace rdbms { +namespace wrapper { class SqliteConn; -class SqliteRsetImpl; +class SqliteRset; /** * A convenience wrapper around an SQLite prepared statement. @@ -55,6 +56,11 @@ public: */ ~SqliteStmt() throw() override; + /** + * Clears the prepared statement so that it is ready to be reused. + */ + void clear() override; + /** * Idempotent close() method. The destructor calls this method. */ @@ -115,7 +121,7 @@ public: * * @return The result set. */ - Rset executeQuery() override; + std::unique_ptr<Rset> executeQuery() override; /** * Executes the statement. @@ -163,5 +169,6 @@ private: }; // class SqlLiteStmt +} // namespace wrapper } // namespace rdbms } // namespace cta diff --git a/rdbms/SqliteStmtTest.cpp b/rdbms/wrapper/SqliteStmtTest.cpp similarity index 63% rename from rdbms/SqliteStmtTest.cpp rename to rdbms/wrapper/SqliteStmtTest.cpp index 9aaadca885731648adaf24faded12dc3479d12bf..0d7b7d32df283b5c8fe90d3771017f1c0e6a1c09 100644 --- a/rdbms/SqliteStmtTest.cpp +++ b/rdbms/wrapper/SqliteStmtTest.cpp @@ -16,16 +16,16 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "SqliteConn.hpp" -#include "SqliteRsetImpl.hpp" -#include "SqliteStmt.hpp" +#include "rdbms/wrapper/SqliteConn.hpp" +#include "rdbms/wrapper/SqliteRset.hpp" +#include "rdbms/wrapper/SqliteStmt.hpp" #include <gtest/gtest.h> #include <memory> namespace unitTests { -class cta_rdbms_SqliteStmtTest : public ::testing::Test { +class cta_rdbms_wrapper_SqliteStmtTest : public ::testing::Test { protected: virtual void SetUp() { @@ -35,8 +35,9 @@ protected: } }; -TEST_F(cta_rdbms_SqliteStmtTest, create_table) { - using namespace cta::rdbms; +TEST_F(cta_rdbms_wrapper_SqliteStmtTest, create_table) { + using namespace cta; + using namespace cta::rdbms::wrapper; // Create a connection a memory resident database SqliteConn conn(":memory:"); @@ -49,12 +50,13 @@ TEST_F(cta_rdbms_SqliteStmtTest, create_table) { "SQLITE_MASTER " "WHERE " "TYPE = 'table';"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); auto rset = stmt->executeQuery(); - ASSERT_TRUE(rset.next()); - const uint64_t nbTables = rset.columnUint64("NB_TABLES"); - ASSERT_EQ(0, nbTables); - ASSERT_FALSE(rset.next()); + ASSERT_TRUE(rset->next()); + const auto nbTables = rset->columnOptionalUint64("NB_TABLES"); + ASSERT_TRUE((bool)nbTables); + ASSERT_EQ(0, nbTables.value()); + ASSERT_FALSE(rset->next()); ASSERT_TRUE(conn.getTableNames().empty()); } @@ -65,7 +67,7 @@ TEST_F(cta_rdbms_SqliteStmtTest, create_table) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); stmt->executeNonQuery(); } @@ -78,12 +80,13 @@ TEST_F(cta_rdbms_SqliteStmtTest, create_table) { "WHERE " "NAME = 'TEST1' AND " "TYPE = 'table';"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); auto rset = stmt->executeQuery(); - ASSERT_TRUE(rset.next()); - const uint64_t nbTables = rset.columnUint64("NB_TABLES"); - ASSERT_EQ(1, nbTables); - ASSERT_FALSE(rset.next()); + ASSERT_TRUE(rset->next()); + const auto nbTables = rset->columnOptionalUint64("NB_TABLES"); + ASSERT_TRUE((bool)nbTables); + ASSERT_EQ(1, nbTables.value()); + ASSERT_FALSE(rset->next()); ASSERT_EQ(1, conn.getTableNames().size()); ASSERT_EQ("TEST1", conn.getTableNames().front()); } @@ -95,7 +98,7 @@ TEST_F(cta_rdbms_SqliteStmtTest, create_table) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); stmt->executeNonQuery(); } @@ -108,12 +111,13 @@ TEST_F(cta_rdbms_SqliteStmtTest, create_table) { "WHERE " "NAME = 'TEST2' AND " "TYPE = 'table';"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); auto rset = stmt->executeQuery(); - ASSERT_TRUE(rset.next()); - const uint64_t nbTables = rset.columnUint64("NB_TABLES"); - ASSERT_EQ(1, nbTables); - ASSERT_FALSE(rset.next()); + ASSERT_TRUE(rset->next()); + const auto nbTables = rset->columnOptionalUint64("NB_TABLES"); + ASSERT_TRUE((bool)nbTables); + ASSERT_EQ(1, nbTables.value()); + ASSERT_FALSE(rset->next()); const auto tableNames = conn.getTableNames(); ASSERT_EQ(2, tableNames.size()); auto nameItor = tableNames.begin(); @@ -125,8 +129,9 @@ TEST_F(cta_rdbms_SqliteStmtTest, create_table) { } } -TEST_F(cta_rdbms_SqliteStmtTest, select_from_empty_table) { - using namespace cta::rdbms; +TEST_F(cta_rdbms_wrapper_SqliteStmtTest, select_from_empty_table) { + using namespace cta; + using namespace cta::rdbms::wrapper; // Create a connection a memory resident database SqliteConn conn(":memory:"); @@ -139,7 +144,7 @@ TEST_F(cta_rdbms_SqliteStmtTest, select_from_empty_table) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); stmt->executeNonQuery(); ASSERT_EQ(1, conn.getTableNames().size()); ASSERT_EQ("TEST", conn.getTableNames().front()); @@ -154,14 +159,15 @@ TEST_F(cta_rdbms_SqliteStmtTest, select_from_empty_table) { "COL3 " "FROM " "TEST;"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); auto rset = stmt->executeQuery(); - ASSERT_FALSE(rset.next()); + ASSERT_FALSE(rset->next()); } } -TEST_F(cta_rdbms_SqliteStmtTest, insert_without_bind) { - using namespace cta::rdbms; +TEST_F(cta_rdbms_wrapper_SqliteStmtTest, insert_without_bind) { + using namespace cta; + using namespace cta::rdbms::wrapper; // Create a connection a memory resident database SqliteConn conn(":memory:"); @@ -174,7 +180,7 @@ TEST_F(cta_rdbms_SqliteStmtTest, insert_without_bind) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); stmt->executeNonQuery(); ASSERT_EQ(1, conn.getTableNames().size()); ASSERT_EQ("TEST", conn.getTableNames().front()); @@ -191,7 +197,7 @@ TEST_F(cta_rdbms_SqliteStmtTest, insert_without_bind) { "'one'," "'two'," "3);"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); stmt->executeNonQuery(); } @@ -204,24 +210,29 @@ TEST_F(cta_rdbms_SqliteStmtTest, insert_without_bind) { "COL3 AS COL3 " "FROM " "TEST;"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); auto rset = stmt->executeQuery(); - ASSERT_TRUE(rset.next()); + ASSERT_TRUE(rset->next()); - const std::string col1 = rset.columnString("COL1"); - const std::string col2 = rset.columnString("COL2"); - const uint64_t col3 = rset.columnUint64("COL3"); + const auto col1 = rset->columnOptionalString("COL1"); + const auto col2 = rset->columnOptionalString("COL2"); + const auto col3 = rset->columnOptionalUint64("COL3"); - ASSERT_EQ("one", col1); - ASSERT_EQ("two", col2); - ASSERT_EQ((uint64_t)3, col3); + ASSERT_TRUE((bool)col1); + ASSERT_TRUE((bool)col2); + ASSERT_TRUE((bool)col3); - ASSERT_FALSE(rset.next()); + ASSERT_EQ("one", col1.value()); + ASSERT_EQ("two", col2.value()); + ASSERT_EQ(3, col3.value()); + + ASSERT_FALSE(rset->next()); } } -TEST_F(cta_rdbms_SqliteStmtTest, insert_with_bind) { - using namespace cta::rdbms; +TEST_F(cta_rdbms_wrapper_SqliteStmtTest, insert_with_bind) { + using namespace cta; + using namespace cta::rdbms::wrapper; // Create a connection a memory resident database SqliteConn conn(":memory:"); @@ -235,7 +246,7 @@ TEST_F(cta_rdbms_SqliteStmtTest, insert_with_bind) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); stmt->executeNonQuery(); ASSERT_EQ(1, conn.getTableNames().size()); ASSERT_EQ("TEST", conn.getTableNames().front()); @@ -252,7 +263,7 @@ TEST_F(cta_rdbms_SqliteStmtTest, insert_with_bind) { ":COL1," ":COL2," ":COL3);"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); stmt->bindString(":COL1", "one"); stmt->bindString(":COL2", "two"); stmt->bindUint64(":COL3", 3); @@ -268,24 +279,29 @@ TEST_F(cta_rdbms_SqliteStmtTest, insert_with_bind) { "COL3 AS COL3 " "FROM " "TEST;"; - auto stmt = conn.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON); auto rset = stmt->executeQuery(); - ASSERT_TRUE(rset.next()); + ASSERT_TRUE(rset->next()); + + const auto col1 = rset->columnOptionalString("COL1"); + const auto col2 = rset->columnOptionalString("COL2"); + const auto col3 = rset->columnOptionalUint64("COL3"); - const std::string col1 = rset.columnString("COL1"); - const std::string col2 = rset.columnString("COL2"); - const uint64_t col3 = rset.columnUint64("COL3"); + ASSERT_TRUE((bool)col1); + ASSERT_TRUE((bool)col2); + ASSERT_TRUE((bool)col3); - ASSERT_EQ("one", col1); - ASSERT_EQ("two", col2); - ASSERT_EQ((uint64_t)3, col3); + ASSERT_EQ("one", col1.value()); + ASSERT_EQ("two", col2.value()); + ASSERT_EQ(3, col3.value()); - ASSERT_FALSE(rset.next()); + ASSERT_FALSE(rset->next()); } } -TEST_F(cta_rdbms_SqliteStmtTest, isolated_transaction) { - using namespace cta::rdbms; +TEST_F(cta_rdbms_wrapper_SqliteStmtTest, isolated_transaction) { + using namespace cta; + using namespace cta::rdbms::wrapper; const std::string dbFilename = "file::memory:?cache=shared"; @@ -298,7 +314,7 @@ TEST_F(cta_rdbms_SqliteStmtTest, isolated_transaction) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - auto stmt = connForCreate.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = connForCreate.createStmt(sql, rdbms::AutocommitMode::ON); stmt->executeNonQuery(); ASSERT_EQ(1, connForCreate.getTableNames().size()); ASSERT_EQ("TEST", connForCreate.getTableNames().front()); @@ -316,7 +332,7 @@ TEST_F(cta_rdbms_SqliteStmtTest, isolated_transaction) { "'one'," "'two'," "3);"; - auto stmt = connForInsert.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = connForInsert.createStmt(sql, rdbms::AutocommitMode::ON); stmt->executeNonQuery(); } @@ -330,15 +346,15 @@ TEST_F(cta_rdbms_SqliteStmtTest, isolated_transaction) { "COUNT(*) AS NB_ROWS " "FROM " "TEST;"; - auto stmt = connForSelect.createStmt(sql, Stmt::AutocommitMode::ON); + auto stmt = connForSelect.createStmt(sql, rdbms::AutocommitMode::ON); auto rset = stmt->executeQuery(); - ASSERT_TRUE(rset.next()); - - const uint64_t nbRows = rset.columnUint64("NB_ROWS"); + ASSERT_TRUE(rset->next()); - ASSERT_EQ((uint64_t)1, nbRows); + const auto nbRows = rset->columnOptionalUint64("NB_ROWS"); + ASSERT_TRUE((bool)nbRows); + ASSERT_EQ((uint64_t)1, nbRows.value()); - ASSERT_FALSE(rset.next()); + ASSERT_FALSE(rset->next()); } } diff --git a/rdbms/wrapper/Stmt.cpp b/rdbms/wrapper/Stmt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be47b1bf5dd63d7b0a47cae8b2a3f15661020270 --- /dev/null +++ b/rdbms/wrapper/Stmt.cpp @@ -0,0 +1,96 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "rdbms/wrapper/Stmt.hpp" + +namespace cta { +namespace rdbms { +namespace wrapper { + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +Stmt::Stmt(const std::string &sql, const AutocommitMode autocommitMode): + m_sql(sql), + m_autocommitMode(autocommitMode), + m_paramNameToIdx(sql) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +Stmt::~Stmt() throw() { +} + +//------------------------------------------------------------------------------ +// getSql +//------------------------------------------------------------------------------ +const std::string &Stmt::getSql() const { + return m_sql; +} + +//------------------------------------------------------------------------------ +// getAutocommitMode +//------------------------------------------------------------------------------ +AutocommitMode Stmt::getAutocommitMode() const noexcept { + return m_autocommitMode; +} + +//------------------------------------------------------------------------------ +// getParamIdx +//------------------------------------------------------------------------------ +uint32_t Stmt::getParamIdx(const std::string ¶mName) const { + return m_paramNameToIdx.getIdx(paramName); +} + +//------------------------------------------------------------------------------ +// getSqlForException +//------------------------------------------------------------------------------ +std::string Stmt::getSqlForException() const { + if(m_sql.length() <= c_maxSqlLenInExceptions) { + return m_sql; + } else { + if(c_maxSqlLenInExceptions >= 3) { + return m_sql.substr(0, c_maxSqlLenInExceptions - 3) + "..."; + } else { + return std::string("..."). substr(0, c_maxSqlLenInExceptions); + } + } +} + +//------------------------------------------------------------------------------ +// bindBool +//------------------------------------------------------------------------------ +void Stmt::bindBool(const std::string ¶mName, const bool paramValue) { + bindOptionalBool(paramName, paramValue); +} + +//------------------------------------------------------------------------------ +// bindOptionalBool +//------------------------------------------------------------------------------ +void Stmt::bindOptionalBool(const std::string ¶mName, const optional<bool> ¶mValue) { + if(paramValue) { + bindOptionalUint64(paramName, paramValue.value() ? 1 : 0); + } else { + bindOptionalUint64(paramName, nullopt); + } +} + +} // namespace wrapper +} // namespace rdbms +} // namespace cta diff --git a/rdbms/wrapper/Stmt.hpp b/rdbms/wrapper/Stmt.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3ee0a3a6dcafe8de91a61baef0ded6a97953c39f --- /dev/null +++ b/rdbms/wrapper/Stmt.hpp @@ -0,0 +1,221 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "common/optional.hpp" +#include "rdbms/AutocommitMode.hpp" +#include "rdbms/wrapper/ParamNameToIdx.hpp" +#include "rdbms/wrapper/Rset.hpp" + +#include <memory> +#include <stdint.h> +#include <string> + +namespace cta { +namespace rdbms { +namespace wrapper { + +/** + * Abstract class specifying the interface to a database statement. + */ +class Stmt { +public: + + /** + * Constructor. + * + * @param sql The SQL statement. + * @param autocommitMode The autocommit mode of the statement. + */ + Stmt(const std::string &sql, const AutocommitMode autocommitMode); + + /** + * Returns the autocommit mode of teh statement. + * + * @return The autocommit mode of teh statement. + */ + AutocommitMode getAutocommitMode() const noexcept; + + /** + * Destructor. + */ + virtual ~Stmt() throw() = 0; + + /** + * Deletion of the copy constructor. + */ + Stmt(Stmt &) = delete; + + /** + * Deletion of the move constructor. + */ + Stmt(Stmt &&) = delete; + + /** + * Deletion of the copy assignment operator. + */ + Stmt &operator=(const Stmt &) = delete; + + /** + * Deletion of the move assignment operator. + */ + Stmt &operator=(Stmt &&) = delete; + + /** + * Clears the prepared statement so that it is ready to be reused. + */ + virtual void clear() = 0; + + /** + * Idempotent close() method. The destructor calls this method. + */ + virtual void close() = 0; + + /** + * Returns the SQL statement. + * + * @return The SQL statement. + */ + const std::string &getSql() const; + + /** + * Returns the index of the specified SQL parameter. + * + * @param paramName The name of the SQL parameter. + * @return The index of the SQL parameter. + */ + uint32_t getParamIdx(const std::string ¶mName) const; + + /** + * Binds an SQL parameter. + * + * @param paramName The name of the parameter. + * @param paramValue The value to be bound. + */ + virtual void bindUint64(const std::string ¶mName, const uint64_t paramValue) = 0; + + /** + * Binds an SQL parameter. + * + * @param paramName The name of the parameter. + * @param paramValue The value to be bound. + */ + virtual void bindOptionalUint64(const std::string ¶mName, const optional<uint64_t> ¶mValue) = 0; + + /** + * Binds an SQL parameter. + * + * @param paramName The name of the parameter. + * @param paramValue The value to be bound. + */ + void bindBool(const std::string ¶mName, const bool paramValue); + + /** + * Binds an SQL parameter. + * + * @param paramName The name of the parameter. + * @param paramValue The value to be bound. + */ + void bindOptionalBool(const std::string ¶mName, const optional<bool> ¶mValue); + + /** + * Binds an SQL parameter of type string. + * + * Please note that this method will throw an exception if the string + * parameter is empty. If a null value is to be bound then the + * bindOptionalString() method should be used. + * + * @param paramName The name of the parameter. + * @param paramValue The value to be bound. + */ + virtual void bindString(const std::string ¶mName, const std::string ¶mValue) = 0; + + /** + * Binds an SQL parameter of type optional-string. + * + * Please note that this method will throw an exception if the optional string + * parameter has the empty string as its value. An optional string parameter + * should either have a non-empty string value or no value at all. + * + * @param paramName The name of the parameter. + * @param paramValue The value to be bound. + */ + virtual void bindOptionalString(const std::string ¶mName, const optional<std::string> ¶mValue) = 0; + + /** + * Executes the statement and returns the result set. + * + * @return The result set. + */ + virtual std::unique_ptr<Rset> executeQuery() = 0; + + /** + * Executes the statement. + */ + virtual void executeNonQuery() = 0; + + /** + * Returns the number of rows affected by the last execution of this + * statement. + * + * @return The number of affected rows. + */ + virtual uint64_t getNbAffectedRows() const = 0; + + /** + * Returns the SQL string to be used in an exception message. The string + * will be clipped at a maxmum of c_maxSqlLenInExceptions characters. If the + * string is actually clipped then the three last characters will be an + * replaced by an ellipsis of three dots, in other word "...". These 3 + * characters will indicate to the reader of the exception message that the + * SQL statement has been clipped. + * + * @return The SQL string to be used in an exception message. + */ + std::string getSqlForException() const; + +protected: + + /** + * The maximum length an SQL statement can have in exception error message. + */ + const uint32_t c_maxSqlLenInExceptions = 80; + +private: + + /** + * The SQL statement. + */ + std::string m_sql; + + /** + * The autocommit mode of the statement. + */ + AutocommitMode m_autocommitMode; + + /** + * Map from SQL parameter name to parameter index. + */ + ParamNameToIdx m_paramNameToIdx; + +}; // class Stmt + +} // namespace wrapper +} // namespace rdbms +} // namespace cta