From 909d4325fd72185c3dbab76da956b4fd6e667d77 Mon Sep 17 00:00:00 2001 From: Steven Murray <Steven.Murray@cern.ch> Date: Wed, 16 Mar 2016 11:32:56 +0100 Subject: [PATCH] Added SqliteCatalogue::createTape --- catalogue/SqliteCatalogue.cpp | 549 ++++++++++++++++++++++-------- catalogue/SqliteCatalogue.hpp | 2 +- catalogue/SqliteCatalogueTest.cpp | 183 +++++++--- catalogue/SqliteConn.cpp | 25 ++ catalogue/SqliteConn.hpp | 21 ++ catalogue/SqliteStmt.cpp | 27 +- catalogue/SqliteStmt.hpp | 20 +- catalogue/SqliteStmtTest.cpp | 62 ++-- doxygen/.gitignore | 3 +- 9 files changed, 641 insertions(+), 251 deletions(-) diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp index 1063ecfe26..cd8734ff5c 100644 --- a/catalogue/SqliteCatalogue.cpp +++ b/catalogue/SqliteCatalogue.cpp @@ -20,6 +20,7 @@ #include "catalogue/SqliteStmt.hpp" #include "common/exception/Exception.hpp" +#include <memory> #include <sqlite3.h> #include <time.h> @@ -152,6 +153,48 @@ void cta::catalogue::SqliteCatalogue::createDbSchema() { "LAST_MOD_TIME INTEGER," "PRIMARY KEY(LOGICAL_LIBRARY_NAME)" + ");" + + "CREATE TABLE TAPE(" + "VID TEXT," + "LOGICAL_LIBRARY_NAME TEXT," + "TAPE_POOL_NAME TEXT," + "ENCRYPTION_KEY TEXT," + "CAPACITY_IN_BYTES INTEGER," + "DATA_IN_BYTES INTEGER," + "LAST_FSEQ INTEGER," + "IS_BUSY INTEGER," + "IS_DISABLED INTEGER," + "IS_FULL INTEGER," + "LBP_IS_ON INTEGER," + + "LABEL_DRIVE TEXT," + "LABEL_TIME INTEGER," + + "LAST_READ_DRIVE TEXT," + "LAST_READ_TIME INTEGER," + + "LAST_WRITE_DRIVE TEXT," + "LAST_WRITE_TIME INTEGER," + + "COMMENT TEXT," + + "CREATION_LOG_USER_NAME TEXT," + "CREATION_LOG_GROUP_NAME TEXT," + "CREATION_LOG_HOST_NAME TEXT," + "CREATION_LOG_TIME INTEGER," + + "LAST_MOD_USER_NAME TEXT," + "LAST_MOD_GROUP_NAME TEXT," + "LAST_MOD_HOST_NAME TEXT," + "LAST_MOD_TIME INTEGER," + + "PRIMARY KEY(VID)," + + "FOREIGN KEY(LOGICAL_LIBRARY_NAME) REFERENCES " + "LOGICAL_LIBRARY(LOGICAL_LIBRARY_NAME)," + "FOREIGN KEY(TAPE_POOL_NAME) REFERENCES " + "TAPE_POOL(TAPE_POOL_NAME)" ");"; m_conn.enableForeignKeys(); m_conn.execNonQuery(sql); @@ -213,18 +256,18 @@ void cta::catalogue::SqliteCatalogue::createAdminUser( ":CREATION_LOG_GROUP_NAME," ":CREATION_LOG_HOST_NAME," ":CREATION_LOG_TIME);"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); - stmt.bind(":USER_NAME", user.name); - stmt.bind(":GROUP_NAME", user.group); - stmt.bind(":COMMENT", comment); + stmt->bind(":USER_NAME", user.name); + stmt->bind(":GROUP_NAME", user.group); + stmt->bind(":COMMENT", comment); - stmt.bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); - stmt.bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); - stmt.bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); - stmt.bind(":CREATION_LOG_TIME", now); + stmt->bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); + stmt->bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); + stmt->bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); + stmt->bind(":CREATION_LOG_TIME", now); - stmt.step(); + stmt->step(); } //------------------------------------------------------------------------------ @@ -255,41 +298,41 @@ std::list<cta::common::dataStructures::AdminUser> "LAST_MOD_HOST_NAME AS LAST_MOD_HOST_NAME," "LAST_MOD_TIME AS LAST_MOD_TIME " "FROM ADMIN_USER"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); ColumnNameToIdx nameToIdx; - while(SQLITE_ROW == stmt.step()) { + while(SQLITE_ROW == stmt->step()) { if(nameToIdx.empty()) { - nameToIdx = stmt.getColumnNameToIdx(); + nameToIdx = stmt->getColumnNameToIdx(); } common::dataStructures::AdminUser admin; common::dataStructures::UserIdentity adminUI; - adminUI.name = stmt.columnText(nameToIdx["USER_NAME"]); - adminUI.group = stmt.columnText(nameToIdx["GROUP_NAME"]); + adminUI.name = stmt->columnText(nameToIdx["USER_NAME"]); + adminUI.group = stmt->columnText(nameToIdx["GROUP_NAME"]); admin.user = adminUI; - admin.comment = stmt.columnText(nameToIdx["COMMENT"]); + admin.comment = stmt->columnText(nameToIdx["COMMENT"]); common::dataStructures::UserIdentity creatorUI; - creatorUI.name = stmt.columnText(nameToIdx["CREATION_LOG_USER_NAME"]); - creatorUI.group = stmt.columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); + creatorUI.name = stmt->columnText(nameToIdx["CREATION_LOG_USER_NAME"]); + creatorUI.group = stmt->columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); common::dataStructures::EntryLog creationLog; creationLog.user = creatorUI; - creationLog.host = stmt.columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); - creationLog.time = stmt.columnUint64(nameToIdx["CREATION_LOG_TIME"]); + creationLog.host = stmt->columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); + creationLog.time = stmt->columnUint64(nameToIdx["CREATION_LOG_TIME"]); admin.creationLog = creationLog; common::dataStructures::UserIdentity updaterUI; - updaterUI.name = stmt.columnText(nameToIdx["LAST_MOD_USER_NAME"]); - updaterUI.group = stmt.columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); + updaterUI.name = stmt->columnText(nameToIdx["LAST_MOD_USER_NAME"]); + updaterUI.group = stmt->columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); common::dataStructures::EntryLog updateLog; updateLog.user = updaterUI; - updateLog.host = stmt.columnText(nameToIdx["LAST_MOD_HOST_NAME"]); - updateLog.time = stmt.columnUint64(nameToIdx["LAST_MOD_TIME"]); + updateLog.host = stmt->columnText(nameToIdx["LAST_MOD_HOST_NAME"]); + updateLog.time = stmt->columnUint64(nameToIdx["LAST_MOD_TIME"]); admin.lastModificationLog = updateLog; @@ -341,17 +384,17 @@ void cta::catalogue::SqliteCatalogue::createAdminHost( ":CREATION_LOG_GROUP_NAME," ":CREATION_LOG_HOST_NAME," ":CREATION_LOG_TIME);"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); - stmt.bind(":HOST_NAME", hostName); - stmt.bind(":COMMENT", comment); + stmt->bind(":HOST_NAME", hostName); + stmt->bind(":COMMENT", comment); - stmt.bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); - stmt.bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); - stmt.bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); - stmt.bind(":CREATION_LOG_TIME", now); + stmt->bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); + stmt->bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); + stmt->bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); + stmt->bind(":CREATION_LOG_TIME", now); - stmt.step(); + stmt->step(); } //------------------------------------------------------------------------------ @@ -380,36 +423,36 @@ std::list<cta::common::dataStructures::AdminHost> cta::catalogue::SqliteCatalogu "LAST_MOD_HOST_NAME AS LAST_MOD_HOST_NAME," "LAST_MOD_TIME AS LAST_MOD_TIME " "FROM ADMIN_HOST"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); ColumnNameToIdx nameToIdx; - while(SQLITE_ROW == stmt.step()) { + while(SQLITE_ROW == stmt->step()) { if(nameToIdx.empty()) { - nameToIdx = stmt.getColumnNameToIdx(); + nameToIdx = stmt->getColumnNameToIdx(); } common::dataStructures::AdminHost host; - host.name = stmt.columnText(nameToIdx["HOST_NAME"]); - host.comment = stmt.columnText(nameToIdx["COMMENT"]); + host.name = stmt->columnText(nameToIdx["HOST_NAME"]); + host.comment = stmt->columnText(nameToIdx["COMMENT"]); common::dataStructures::UserIdentity creatorUI; - creatorUI.name = stmt.columnText(nameToIdx["CREATION_LOG_USER_NAME"]); - creatorUI.group = stmt.columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); + creatorUI.name = stmt->columnText(nameToIdx["CREATION_LOG_USER_NAME"]); + creatorUI.group = stmt->columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); common::dataStructures::EntryLog creationLog; creationLog.user = creatorUI; - creationLog.host = stmt.columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); - creationLog.time = stmt.columnUint64(nameToIdx["CREATION_LOG_TIME"]); + creationLog.host = stmt->columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); + creationLog.time = stmt->columnUint64(nameToIdx["CREATION_LOG_TIME"]); host.creationLog = creationLog; common::dataStructures::UserIdentity updaterUI; - updaterUI.name = stmt.columnText(nameToIdx["LAST_MOD_USER_NAME"]); - updaterUI.group = stmt.columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); + updaterUI.name = stmt->columnText(nameToIdx["LAST_MOD_USER_NAME"]); + updaterUI.group = stmt->columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); common::dataStructures::EntryLog updateLog; updateLog.user = updaterUI; - updateLog.host = stmt.columnText(nameToIdx["LAST_MOD_HOST_NAME"]); - updateLog.time = stmt.columnUint64(nameToIdx["LAST_MOD_TIME"]); + updateLog.host = stmt->columnText(nameToIdx["LAST_MOD_HOST_NAME"]); + updateLog.time = stmt->columnUint64(nameToIdx["LAST_MOD_TIME"]); host.lastModificationLog = updateLog; @@ -464,19 +507,19 @@ void cta::catalogue::SqliteCatalogue::createStorageClass( ":CREATION_LOG_GROUP_NAME," ":CREATION_LOG_HOST_NAME," ":CREATION_LOG_TIME);"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); - stmt.bind(":STORAGE_CLASS_NAME", name); - stmt.bind(":NB_COPIES", nbCopies); + stmt->bind(":STORAGE_CLASS_NAME", name); + stmt->bind(":NB_COPIES", nbCopies); - stmt.bind(":COMMENT", comment); + stmt->bind(":COMMENT", comment); - stmt.bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); - stmt.bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); - stmt.bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); - stmt.bind(":CREATION_LOG_TIME", now); + stmt->bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); + stmt->bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); + stmt->bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); + stmt->bind(":CREATION_LOG_TIME", now); - stmt.step(); + stmt->step(); } //------------------------------------------------------------------------------ @@ -507,37 +550,37 @@ std::list<cta::common::dataStructures::StorageClass> "LAST_MOD_HOST_NAME AS LAST_MOD_HOST_NAME," "LAST_MOD_TIME AS LAST_MOD_TIME " "FROM STORAGE_CLASS"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); ColumnNameToIdx nameToIdx; - while(SQLITE_ROW == stmt.step()) { + while(SQLITE_ROW == stmt->step()) { if(nameToIdx.empty()) { - nameToIdx = stmt.getColumnNameToIdx(); + nameToIdx = stmt->getColumnNameToIdx(); } common::dataStructures::StorageClass storageClass; - storageClass.name = stmt.columnText(nameToIdx["STORAGE_CLASS_NAME"]); - storageClass.nbCopies = stmt.columnUint64(nameToIdx["NB_COPIES"]); - storageClass.comment = stmt.columnText(nameToIdx["COMMENT"]); + storageClass.name = stmt->columnText(nameToIdx["STORAGE_CLASS_NAME"]); + storageClass.nbCopies = stmt->columnUint64(nameToIdx["NB_COPIES"]); + storageClass.comment = stmt->columnText(nameToIdx["COMMENT"]); common::dataStructures::UserIdentity creatorUI; - creatorUI.name = stmt.columnText(nameToIdx["CREATION_LOG_USER_NAME"]); - creatorUI.group = stmt.columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); + creatorUI.name = stmt->columnText(nameToIdx["CREATION_LOG_USER_NAME"]); + creatorUI.group = stmt->columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); common::dataStructures::EntryLog creationLog; creationLog.user = creatorUI; - creationLog.host = stmt.columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); - creationLog.time = stmt.columnUint64(nameToIdx["CREATION_LOG_TIME"]); + creationLog.host = stmt->columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); + creationLog.time = stmt->columnUint64(nameToIdx["CREATION_LOG_TIME"]); storageClass.creationLog = creationLog; common::dataStructures::UserIdentity updaterUI; - updaterUI.name = stmt.columnText(nameToIdx["LAST_MOD_USER_NAME"]); - updaterUI.group = stmt.columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); + updaterUI.name = stmt->columnText(nameToIdx["LAST_MOD_USER_NAME"]); + updaterUI.group = stmt->columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); common::dataStructures::EntryLog updateLog; updateLog.user = updaterUI; - updateLog.host = stmt.columnText(nameToIdx["LAST_MOD_HOST_NAME"]); - updateLog.time = stmt.columnUint64(nameToIdx["LAST_MOD_TIME"]); + updateLog.host = stmt->columnText(nameToIdx["LAST_MOD_HOST_NAME"]); + updateLog.time = stmt->columnUint64(nameToIdx["LAST_MOD_TIME"]); storageClass.lastModificationLog = updateLog; @@ -600,20 +643,20 @@ void cta::catalogue::SqliteCatalogue::createTapePool( ":CREATION_LOG_GROUP_NAME," ":CREATION_LOG_HOST_NAME," ":CREATION_LOG_TIME);"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); - stmt.bind(":TAPE_POOL_NAME", name); - stmt.bind(":NB_PARTIAL_TAPES", nbPartialTapes); - stmt.bind(":IS_ENCRYPTED", encryptionValue); + stmt->bind(":TAPE_POOL_NAME", name); + stmt->bind(":NB_PARTIAL_TAPES", nbPartialTapes); + stmt->bind(":IS_ENCRYPTED", encryptionValue); - stmt.bind(":COMMENT", comment); + stmt->bind(":COMMENT", comment); - stmt.bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); - stmt.bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); - stmt.bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); - stmt.bind(":CREATION_LOG_TIME", now); + stmt->bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); + stmt->bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); + stmt->bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); + stmt->bind(":CREATION_LOG_TIME", now); - stmt.step(); + stmt->step(); } //------------------------------------------------------------------------------ @@ -645,39 +688,39 @@ std::list<cta::common::dataStructures::TapePool> "LAST_MOD_HOST_NAME AS LAST_MOD_HOST_NAME," "LAST_MOD_TIME AS LAST_MOD_TIME " "FROM TAPE_POOL"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); ColumnNameToIdx nameToIdx; - while(SQLITE_ROW == stmt.step()) { + while(SQLITE_ROW == stmt->step()) { if(nameToIdx.empty()) { - nameToIdx = stmt.getColumnNameToIdx(); + nameToIdx = stmt->getColumnNameToIdx(); } common::dataStructures::TapePool pool; - pool.name = stmt.columnText(nameToIdx["TAPE_POOL_NAME"]); - pool.nbPartialTapes = stmt.columnUint64(nameToIdx["NB_PARTIAL_TAPES"]); - pool.encryption = stmt.columnUint64(nameToIdx["IS_ENCRYPTED"]); + pool.name = stmt->columnText(nameToIdx["TAPE_POOL_NAME"]); + pool.nbPartialTapes = stmt->columnUint64(nameToIdx["NB_PARTIAL_TAPES"]); + pool.encryption = stmt->columnUint64(nameToIdx["IS_ENCRYPTED"]); - pool.comment = stmt.columnText(nameToIdx["COMMENT"]); + pool.comment = stmt->columnText(nameToIdx["COMMENT"]); common::dataStructures::UserIdentity creatorUI; - creatorUI.name = stmt.columnText(nameToIdx["CREATION_LOG_USER_NAME"]); - creatorUI.group = stmt.columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); + creatorUI.name = stmt->columnText(nameToIdx["CREATION_LOG_USER_NAME"]); + creatorUI.group = stmt->columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); common::dataStructures::EntryLog creationLog; creationLog.user = creatorUI; - creationLog.host = stmt.columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); - creationLog.time = stmt.columnUint64(nameToIdx["CREATION_LOG_TIME"]); + creationLog.host = stmt->columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); + creationLog.time = stmt->columnUint64(nameToIdx["CREATION_LOG_TIME"]); pool.creationLog = creationLog; common::dataStructures::UserIdentity updaterUI; - updaterUI.name = stmt.columnText(nameToIdx["LAST_MOD_USER_NAME"]); - updaterUI.group = stmt.columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); + updaterUI.name = stmt->columnText(nameToIdx["LAST_MOD_USER_NAME"]); + updaterUI.group = stmt->columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); common::dataStructures::EntryLog updateLog; updateLog.user = updaterUI; - updateLog.host = stmt.columnText(nameToIdx["LAST_MOD_HOST_NAME"]); - updateLog.time = stmt.columnUint64(nameToIdx["LAST_MOD_TIME"]); + updateLog.host = stmt->columnText(nameToIdx["LAST_MOD_HOST_NAME"]); + updateLog.time = stmt->columnUint64(nameToIdx["LAST_MOD_TIME"]); pool.lastModificationLog = updateLog; @@ -745,20 +788,20 @@ void cta::catalogue::SqliteCatalogue::createArchiveRoute( ":CREATION_LOG_GROUP_NAME," ":CREATION_LOG_HOST_NAME," ":CREATION_LOG_TIME);"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); - stmt.bind(":STORAGE_CLASS_NAME", storageClassName); - stmt.bind(":COPY_NB", copyNb); - stmt.bind(":TAPE_POOL_NAME", tapePoolName); + stmt->bind(":STORAGE_CLASS_NAME", storageClassName); + stmt->bind(":COPY_NB", copyNb); + stmt->bind(":TAPE_POOL_NAME", tapePoolName); - stmt.bind(":COMMENT", comment); + stmt->bind(":COMMENT", comment); - stmt.bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); - stmt.bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); - stmt.bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); - stmt.bind(":CREATION_LOG_TIME", now); + stmt->bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); + stmt->bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); + stmt->bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); + stmt->bind(":CREATION_LOG_TIME", now); - stmt.step(); + stmt->step(); } //------------------------------------------------------------------------------ @@ -790,39 +833,39 @@ std::list<cta::common::dataStructures::ArchiveRoute> "LAST_MOD_HOST_NAME AS LAST_MOD_HOST_NAME," "LAST_MOD_TIME AS LAST_MOD_TIME " "FROM ARCHIVE_ROUTE"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); ColumnNameToIdx nameToIdx; - while(SQLITE_ROW == stmt.step()) { + while(SQLITE_ROW == stmt->step()) { if(nameToIdx.empty()) { - nameToIdx = stmt.getColumnNameToIdx(); + nameToIdx = stmt->getColumnNameToIdx(); } common::dataStructures::ArchiveRoute route; - route.storageClassName = stmt.columnText(nameToIdx["STORAGE_CLASS_NAME"]); - route.copyNb = stmt.columnUint64(nameToIdx["COPY_NB"]); - route.tapePoolName = stmt.columnText(nameToIdx["TAPE_POOL_NAME"]); + route.storageClassName = stmt->columnText(nameToIdx["STORAGE_CLASS_NAME"]); + route.copyNb = stmt->columnUint64(nameToIdx["COPY_NB"]); + route.tapePoolName = stmt->columnText(nameToIdx["TAPE_POOL_NAME"]); - route.comment = stmt.columnText(nameToIdx["COMMENT"]); + route.comment = stmt->columnText(nameToIdx["COMMENT"]); common::dataStructures::UserIdentity creatorUI; - creatorUI.name = stmt.columnText(nameToIdx["CREATION_LOG_USER_NAME"]); - creatorUI.group = stmt.columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); + creatorUI.name = stmt->columnText(nameToIdx["CREATION_LOG_USER_NAME"]); + creatorUI.group = stmt->columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); common::dataStructures::EntryLog creationLog; creationLog.user = creatorUI; - creationLog.host = stmt.columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); - creationLog.time = stmt.columnUint64(nameToIdx["CREATION_LOG_TIME"]); + creationLog.host = stmt->columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); + creationLog.time = stmt->columnUint64(nameToIdx["CREATION_LOG_TIME"]); route.creationLog = creationLog; common::dataStructures::UserIdentity updaterUI; - updaterUI.name = stmt.columnText(nameToIdx["LAST_MOD_USER_NAME"]); - updaterUI.group = stmt.columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); + updaterUI.name = stmt->columnText(nameToIdx["LAST_MOD_USER_NAME"]); + updaterUI.group = stmt->columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); common::dataStructures::EntryLog updateLog; updateLog.user = updaterUI; - updateLog.host = stmt.columnText(nameToIdx["LAST_MOD_HOST_NAME"]); - updateLog.time = stmt.columnUint64(nameToIdx["LAST_MOD_TIME"]); + updateLog.host = stmt->columnText(nameToIdx["LAST_MOD_HOST_NAME"]); + updateLog.time = stmt->columnUint64(nameToIdx["LAST_MOD_TIME"]); route.lastModificationLog = updateLog; @@ -879,18 +922,18 @@ void cta::catalogue::SqliteCatalogue::createLogicalLibrary( ":CREATION_LOG_GROUP_NAME," ":CREATION_LOG_HOST_NAME," ":CREATION_LOG_TIME);"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); - stmt.bind(":LOGICAL_LIBRARY_NAME", name); + stmt->bind(":LOGICAL_LIBRARY_NAME", name); - stmt.bind(":COMMENT", comment); + stmt->bind(":COMMENT", comment); - stmt.bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); - stmt.bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); - stmt.bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); - stmt.bind(":CREATION_LOG_TIME", now); + stmt->bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); + stmt->bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); + stmt->bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); + stmt->bind(":CREATION_LOG_TIME", now); - stmt.step(); + stmt->step(); } //------------------------------------------------------------------------------ @@ -920,37 +963,37 @@ std::list<cta::common::dataStructures::LogicalLibrary> "LAST_MOD_HOST_NAME AS LAST_MOD_HOST_NAME," "LAST_MOD_TIME AS LAST_MOD_TIME " "FROM LOGICAL_LIBRARY"; - SqliteStmt stmt(m_conn, sql); + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); ColumnNameToIdx nameToIdx; - while(SQLITE_ROW == stmt.step()) { + while(SQLITE_ROW == stmt->step()) { if(nameToIdx.empty()) { - nameToIdx = stmt.getColumnNameToIdx(); + nameToIdx = stmt->getColumnNameToIdx(); } common::dataStructures::LogicalLibrary lib; - lib.name = stmt.columnText(nameToIdx["LOGICAL_LIBRARY_NAME"]); + lib.name = stmt->columnText(nameToIdx["LOGICAL_LIBRARY_NAME"]); - lib.comment = stmt.columnText(nameToIdx["COMMENT"]); + lib.comment = stmt->columnText(nameToIdx["COMMENT"]); common::dataStructures::UserIdentity creatorUI; - creatorUI.name = stmt.columnText(nameToIdx["CREATION_LOG_USER_NAME"]); - creatorUI.group = stmt.columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); + creatorUI.name = stmt->columnText(nameToIdx["CREATION_LOG_USER_NAME"]); + creatorUI.group = stmt->columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); common::dataStructures::EntryLog creationLog; creationLog.user = creatorUI; - creationLog.host = stmt.columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); - creationLog.time = stmt.columnUint64(nameToIdx["CREATION_LOG_TIME"]); + creationLog.host = stmt->columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); + creationLog.time = stmt->columnUint64(nameToIdx["CREATION_LOG_TIME"]); lib.creationLog = creationLog; common::dataStructures::UserIdentity updaterUI; - updaterUI.name = stmt.columnText(nameToIdx["LAST_MOD_USER_NAME"]); - updaterUI.group = stmt.columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); + updaterUI.name = stmt->columnText(nameToIdx["LAST_MOD_USER_NAME"]); + updaterUI.group = stmt->columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); common::dataStructures::EntryLog updateLog; updateLog.user = updaterUI; - updateLog.host = stmt.columnText(nameToIdx["LAST_MOD_HOST_NAME"]); - updateLog.time = stmt.columnUint64(nameToIdx["LAST_MOD_TIME"]); + updateLog.host = stmt->columnText(nameToIdx["LAST_MOD_HOST_NAME"]); + updateLog.time = stmt->columnUint64(nameToIdx["LAST_MOD_TIME"]); lib.lastModificationLog = updateLog; @@ -968,8 +1011,116 @@ void cta::catalogue::SqliteCatalogue::modifyLogicalLibraryComment(const common:: //------------------------------------------------------------------------------ // createTape //------------------------------------------------------------------------------ -void cta::catalogue::SqliteCatalogue::createTape(const cta::common::dataStructures::SecurityIdentity &cliIdentity, const std::string &vid, const std::string &logicalLibraryName, const std::string &tapePoolName, - const std::string &encryptionKey, const uint64_t capacityInBytes, const bool disabledValue, const bool fullValue, const std::string &comment) {} +void cta::catalogue::SqliteCatalogue::createTape( + const cta::common::dataStructures::SecurityIdentity &cliIdentity, + const std::string &vid, + const std::string &logicalLibraryName, + const std::string &tapePoolName, + const std::string &encryptionKey, + const uint64_t capacityInBytes, + const bool disabledValue, + const bool fullValue, + const std::string &comment) { + const time_t now = time(NULL); + const char *const sql = + "INSERT INTO TAPE(" + "VID," + "LOGICAL_LIBRARY_NAME," + "TAPE_POOL_NAME," + "ENCRYPTION_KEY," + "CAPACITY_IN_BYTES," + "DATA_IN_BYTES," + "LAST_FSEQ," + "IS_BUSY," + "IS_DISABLED," + "IS_FULL," + "LBP_IS_ON," + + "LABEL_DRIVE," + "LABEL_TIME," + + "LAST_READ_DRIVE," + "LAST_READ_TIME," + + "LAST_WRITE_DRIVE," + "LAST_WRITE_TIME," + + "COMMENT," + + "CREATION_LOG_USER_NAME," + "CREATION_LOG_GROUP_NAME," + "CREATION_LOG_HOST_NAME," + "CREATION_LOG_TIME," + + "LAST_MOD_USER_NAME," + "LAST_MOD_GROUP_NAME," + "LAST_MOD_HOST_NAME," + "LAST_MOD_TIME)" + "VALUES(" + ":VID," + ":LOGICAL_LIBRARY_NAME," + ":TAPE_POOL_NAME," + ":ENCRYPTION_KEY," + ":CAPACITY_IN_BYTES," + ":DATA_IN_BYTES," + ":LAST_FSEQ," + ":IS_BUSY," + ":IS_DISABLED," + ":IS_FULL," + ":LBP_IS_ON," + + ":LABEL_DRIVE," + ":LABEL_TIME," + + ":LAST_READ_DRIVE," + ":LAST_READ_TIME," + + ":LAST_WRITE_DRIVE," + ":LAST_WRITE_TIME," + + ":COMMENT," + + ":CREATION_LOG_USER_NAME," + ":CREATION_LOG_GROUP_NAME," + ":CREATION_LOG_HOST_NAME," + ":CREATION_LOG_TIME," + + ":CREATION_LOG_USER_NAME," + ":CREATION_LOG_GROUP_NAME," + ":CREATION_LOG_HOST_NAME," + ":CREATION_LOG_TIME);"; + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); + + stmt->bind(":VID", vid); + stmt->bind(":LOGICAL_LIBRARY_NAME", logicalLibraryName); + stmt->bind(":TAPE_POOL_NAME", tapePoolName); + stmt->bind(":ENCRYPTION_KEY", encryptionKey); + stmt->bind(":CAPACITY_IN_BYTES", capacityInBytes); + stmt->bind(":DATA_IN_BYTES", 0); + stmt->bind(":LAST_FSEQ", 0); + stmt->bind(":IS_BUSY", 0); + stmt->bind(":IS_DISABLED", disabledValue); + stmt->bind(":IS_FULL", fullValue); + stmt->bind(":LBP_IS_ON", 1); + + stmt->bind(":LABEL_DRIVE", ""); + stmt->bind(":LABEL_TIME", 0); + + stmt->bind(":LAST_READ_DRIVE", ""); + stmt->bind(":LAST_READ_TIME", 0); + + stmt->bind(":LAST_WRITE_DRIVE", ""); + stmt->bind(":LAST_WRITE_TIME", 0); + + stmt->bind(":COMMENT", comment); + + stmt->bind(":CREATION_LOG_USER_NAME", cliIdentity.user.name); + stmt->bind(":CREATION_LOG_GROUP_NAME", cliIdentity.user.group); + stmt->bind(":CREATION_LOG_HOST_NAME", cliIdentity.host); + stmt->bind(":CREATION_LOG_TIME", now); + + stmt->step(); +} //------------------------------------------------------------------------------ // deleteTape @@ -979,8 +1130,110 @@ void cta::catalogue::SqliteCatalogue::deleteTape(const std::string &vid) {} //------------------------------------------------------------------------------ // getTapes //------------------------------------------------------------------------------ -std::list<cta::common::dataStructures::Tape> cta::catalogue::SqliteCatalogue::getTapes(const std::string &vid, const std::string &logicalLibraryName, const std::string &tapePoolName, - const std::string &capacityInBytes, const std::string &disabledValue, const std::string &fullValue, const std::string &busyValue, const std::string &lbpValue) { return std::list<cta::common::dataStructures::Tape>();} +std::list<cta::common::dataStructures::Tape> + cta::catalogue::SqliteCatalogue::getTapes( + const std::string &vid, + const std::string &logicalLibraryName, + const std::string &tapePoolName, + const std::string &capacityInBytes, + const std::string &disabledValue, + const std::string &fullValue, + const std::string &busyValue, + const std::string &lbpValue) { + std::list<cta::common::dataStructures::Tape> tapes; + const char *const sql = + "SELECT " + "VID AS VID," + "LOGICAL_LIBRARY_NAME AS LOGICAL_LIBRARY_NAME," + "TAPE_POOL_NAME AS TAPE_POOL_NAME," + "ENCRYPTION_KEY AS ENCRYPTION_KEY," + "CAPACITY_IN_BYTES AS CAPACITY_IN_BYTES," + "DATA_IN_BYTES AS DATA_IN_BYTES," + "LAST_FSEQ AS LAST_FSEQ," + "IS_BUSY AS IS_BUSY," + "IS_DISABLED AS IS_DISABLED," + "IS_FULL AS IS_FULL," + "LBP_IS_ON AS LBP_IS_ON," + + "LABEL_DRIVE AS LABEL_DRIVE," + "LABEL_TIME AS LABEL_TIME," + + "LAST_READ_DRIVE AS LAST_READ_DRIVE," + "LAST_READ_TIME AS LAST_READ_TIME," + + "LAST_WRITE_DRIVE AS LAST_WRITE_DRIVE," + "LAST_WRITE_TIME AS LAST_WRITE_TIME," + + "COMMENT AS COMMENT," + + "CREATION_LOG_USER_NAME AS CREATION_LOG_USER_NAME," + "CREATION_LOG_GROUP_NAME AS CREATION_LOG_GROUP_NAME," + "CREATION_LOG_HOST_NAME AS CREATION_LOG_HOST_NAME," + "CREATION_LOG_TIME AS CREATION_LOG_TIME," + + "LAST_MOD_USER_NAME AS LAST_MOD_USER_NAME," + "LAST_MOD_GROUP_NAME AS LAST_MOD_GROUP_NAME," + "LAST_MOD_HOST_NAME AS LAST_MOD_HOST_NAME," + "LAST_MOD_TIME AS LAST_MOD_TIME " + "FROM TAPE"; + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); + ColumnNameToIdx nameToIdx; + while(SQLITE_ROW == stmt->step()) { + if(nameToIdx.empty()) { + nameToIdx = stmt->getColumnNameToIdx(); + } + common::dataStructures::Tape tape; + + tape.vid = stmt->columnText(nameToIdx["VID"]); + tape.logicalLibraryName = stmt->columnText(nameToIdx["LOGICAL_LIBRARY_NAME"]); + tape.tapePoolName = stmt->columnText(nameToIdx["TAPE_POOL_NAME"]); + tape.encryptionKey = stmt->columnText(nameToIdx["ENCRYPTION_KEY"]); + tape.capacityInBytes = stmt->columnUint64(nameToIdx["CAPACITY_IN_BYTES"]); + tape.dataOnTapeInBytes = stmt->columnUint64(nameToIdx["DATA_IN_BYTES"]); + tape.lastFSeq = stmt->columnUint64(nameToIdx["LAST_FSEQ"]); + tape.busy = stmt->columnUint64(nameToIdx["IS_BUSY"]); + tape.disabled = stmt->columnUint64(nameToIdx["IS_DISABLED"]); + tape.full = stmt->columnUint64(nameToIdx["IS_FULL"]); + tape.lbp = stmt->columnUint64(nameToIdx["LBP_IS_ON"]); + + tape.labelLog.drive = stmt->columnText(nameToIdx["LABEL_DRIVE"]); + tape.labelLog.time = stmt->columnUint64(nameToIdx["LABEL_TIME"]); + + tape.lastReadLog.drive = stmt->columnText(nameToIdx["LAST_READ_DRIVE"]); + tape.lastReadLog.time = stmt->columnUint64(nameToIdx["LAST_READ_TIME"]); + + tape.lastWriteLog.drive = stmt->columnText(nameToIdx["LAST_WRITE_DRIVE"]); + tape.lastWriteLog.time = stmt->columnUint64(nameToIdx["LAST_WRITE_TIME"]); + + tape.comment = stmt->columnText(nameToIdx["COMMENT"]); + + common::dataStructures::UserIdentity creatorUI; + creatorUI.name = stmt->columnText(nameToIdx["CREATION_LOG_USER_NAME"]); + creatorUI.group = stmt->columnText(nameToIdx["CREATION_LOG_GROUP_NAME"]); + + common::dataStructures::EntryLog creationLog; + creationLog.user = creatorUI; + creationLog.host = stmt->columnText(nameToIdx["CREATION_LOG_HOST_NAME"]); + creationLog.time = stmt->columnUint64(nameToIdx["CREATION_LOG_TIME"]); + + tape.creationLog = creationLog; + + common::dataStructures::UserIdentity updaterUI; + updaterUI.name = stmt->columnText(nameToIdx["LAST_MOD_USER_NAME"]); + updaterUI.group = stmt->columnText(nameToIdx["LAST_MOD_GROUP_NAME"]); + + common::dataStructures::EntryLog updateLog; + updateLog.user = updaterUI; + updateLog.host = stmt->columnText(nameToIdx["LAST_MOD_HOST_NAME"]); + updateLog.time = stmt->columnUint64(nameToIdx["LAST_MOD_TIME"]); + + tape.lastModificationLog = updateLog; + + tapes.push_back(tape); + } + + return tapes; +} //------------------------------------------------------------------------------ // reclaimTape @@ -1277,9 +1530,9 @@ bool cta::catalogue::SqliteCatalogue::userIsAdmin(const std::string &userName) "USER_NAME AS USER_NAME " "FROM ADMIN_USER WHERE " "USER_NAME = :USER_NAME;"; - SqliteStmt stmt(m_conn, sql); - stmt.bind(":USER_NAME", userName); - if(SQLITE_ROW == stmt.step()) { + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); + stmt->bind(":USER_NAME", userName); + if(SQLITE_ROW == stmt->step()) { return true; } else { return false; @@ -1296,9 +1549,9 @@ bool cta::catalogue::SqliteCatalogue::hostIsAdmin(const std::string &hostName) "HOST_NAME AS HOST_NAME " "FROM ADMIN_HOST WHERE " "HOST_NAME = :HOST_NAME;"; - SqliteStmt stmt(m_conn, sql); - stmt.bind(":HOST_NAME", hostName); - if(SQLITE_ROW == stmt.step()) { + std::unique_ptr<SqliteStmt> stmt(m_conn.createStmt(sql)); + stmt->bind(":HOST_NAME", hostName); + if(SQLITE_ROW == stmt->step()) { return true; } else { return false; diff --git a/catalogue/SqliteCatalogue.hpp b/catalogue/SqliteCatalogue.hpp index bd158729d4..e2eca83f09 100644 --- a/catalogue/SqliteCatalogue.hpp +++ b/catalogue/SqliteCatalogue.hpp @@ -164,7 +164,7 @@ private: /** * The connection to the underlying relational database. */ - SqliteConn m_conn; + mutable SqliteConn m_conn; /** * Creates the database schema. diff --git a/catalogue/SqliteCatalogueTest.cpp b/catalogue/SqliteCatalogueTest.cpp index 55d2e47412..914b7db20e 100644 --- a/catalogue/SqliteCatalogueTest.cpp +++ b/catalogue/SqliteCatalogueTest.cpp @@ -68,12 +68,15 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createBootstrapAdminAndHostNoAuth) { catalogue::SqliteCatalogue catalogue; + ASSERT_TRUE(catalogue.getAdminUsers().empty()); + ASSERT_TRUE(catalogue.getAdminHosts().empty()); + catalogue.createBootstrapAdminAndHostNoAuth( m_cliSI, m_bootstrapAdminUI, m_bootstrapAdminSI.host, m_bootstrapComment); { std::list<common::dataStructures::AdminUser> admins; - ASSERT_NO_THROW(admins = catalogue.getAdminUsers()); + admins = catalogue.getAdminUsers(); ASSERT_EQ(1, admins.size()); const common::dataStructures::AdminUser admin = admins.front(); @@ -91,7 +94,7 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createBootstrapAdminAndHostNoAuth) { { std::list<common::dataStructures::AdminHost> hosts; - ASSERT_NO_THROW(hosts = catalogue.getAdminHosts()); + hosts = catalogue.getAdminHosts(); ASSERT_EQ(1, hosts.size()); const common::dataStructures::AdminHost host = hosts.front(); @@ -113,12 +116,14 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminUser) { catalogue::SqliteCatalogue catalogue; - ASSERT_NO_THROW(catalogue.createBootstrapAdminAndHostNoAuth( - m_cliSI, m_bootstrapAdminUI, m_bootstrapAdminSI.host, m_bootstrapComment)); + ASSERT_TRUE(catalogue.getAdminUsers().empty()); + + catalogue.createBootstrapAdminAndHostNoAuth( + m_cliSI, m_bootstrapAdminUI, m_bootstrapAdminSI.host, m_bootstrapComment); { std::list<common::dataStructures::AdminUser> admins; - ASSERT_NO_THROW(admins = catalogue.getAdminUsers()); + admins = catalogue.getAdminUsers(); ASSERT_EQ(1, admins.size()); const common::dataStructures::AdminUser admin = admins.front(); @@ -135,8 +140,8 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminUser) { } const std::string createAdminUserComment = "create admin user"; - ASSERT_NO_THROW(catalogue.createAdminUser(m_bootstrapAdminSI, m_adminUI, - createAdminUserComment)); + catalogue.createAdminUser(m_bootstrapAdminSI, m_adminUI, + createAdminUserComment); { std::list<common::dataStructures::AdminUser> admins; @@ -183,17 +188,17 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminUser) { } } -TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminUser_same_admin_twice) { +TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminUser_same_twice) { using namespace cta; catalogue::SqliteCatalogue catalogue; - ASSERT_NO_THROW(catalogue.createBootstrapAdminAndHostNoAuth( - m_cliSI, m_bootstrapAdminUI, m_bootstrapAdminSI.host, m_bootstrapComment)); + catalogue.createBootstrapAdminAndHostNoAuth( + m_cliSI, m_bootstrapAdminUI, m_bootstrapAdminSI.host, m_bootstrapComment); { std::list<common::dataStructures::AdminUser> admins; - ASSERT_NO_THROW(admins = catalogue.getAdminUsers()); + admins = catalogue.getAdminUsers(); ASSERT_EQ(1, admins.size()); const common::dataStructures::AdminUser admin = admins.front(); @@ -209,8 +214,7 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminUser_same_admin_twice) { ASSERT_EQ(creationLog, lastModificationLog); } - ASSERT_NO_THROW(catalogue.createAdminUser(m_bootstrapAdminSI, m_adminUI, - "comment 1")); + catalogue.createAdminUser(m_bootstrapAdminSI, m_adminUI, "comment 1"); ASSERT_THROW(catalogue.createAdminUser(m_bootstrapAdminSI, m_adminUI, "comment 2"), exception::Exception); @@ -221,12 +225,14 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminHost) { catalogue::SqliteCatalogue catalogue; - ASSERT_NO_THROW(catalogue.createBootstrapAdminAndHostNoAuth( - m_cliSI, m_bootstrapAdminUI, m_bootstrapAdminSI.host, m_bootstrapComment)); + ASSERT_TRUE(catalogue.getAdminHosts().empty()); + + catalogue.createBootstrapAdminAndHostNoAuth( + m_cliSI, m_bootstrapAdminUI, m_bootstrapAdminSI.host, m_bootstrapComment); { std::list<common::dataStructures::AdminUser> admins; - ASSERT_NO_THROW(admins = catalogue.getAdminUsers()); + admins = catalogue.getAdminUsers(); ASSERT_EQ(1, admins.size()); const common::dataStructures::AdminUser admin = admins.front(); @@ -244,8 +250,8 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminHost) { const std::string createAdminHostComment = "create host user"; const std::string anotherAdminHost = "another_admin_host"; - ASSERT_NO_THROW(catalogue.createAdminHost(m_bootstrapAdminSI, - anotherAdminHost, createAdminHostComment)); + catalogue.createAdminHost(m_bootstrapAdminSI, + anotherAdminHost, createAdminHostComment); { std::list<common::dataStructures::AdminHost> hosts; @@ -295,17 +301,17 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminHost) { } } -TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminHost_same_host_twice) { +TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminHost_same_twice) { using namespace cta; catalogue::SqliteCatalogue catalogue; - ASSERT_NO_THROW(catalogue.createBootstrapAdminAndHostNoAuth( - m_cliSI, m_bootstrapAdminUI, m_bootstrapAdminSI.host, m_bootstrapComment)); + catalogue.createBootstrapAdminAndHostNoAuth( + m_cliSI, m_bootstrapAdminUI, m_bootstrapAdminSI.host, m_bootstrapComment); { std::list<common::dataStructures::AdminUser> admins; - ASSERT_NO_THROW(admins = catalogue.getAdminUsers()); + admins = catalogue.getAdminUsers(); ASSERT_EQ(1, admins.size()); const common::dataStructures::AdminUser admin = admins.front(); @@ -323,8 +329,7 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createAdminHost_same_host_twice) { const std::string anotherAdminHost = "another_admin_host"; - ASSERT_NO_THROW(catalogue.createAdminHost(m_bootstrapAdminSI, - anotherAdminHost, "comment 1")); + catalogue.createAdminHost(m_bootstrapAdminSI, anotherAdminHost, "comment 1"); ASSERT_THROW(catalogue.createAdminHost(m_bootstrapAdminSI, anotherAdminHost, "coment 2"), exception::Exception); @@ -354,11 +359,12 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createStorageClass) { catalogue::SqliteCatalogue catalogue; + ASSERT_TRUE(catalogue.getStorageClasses().empty()); + const std::string storageClassName = "storage_class"; const uint64_t nbCopies = 2; const std::string comment = "create storage class"; - ASSERT_NO_THROW(catalogue.createStorageClass(m_cliSI, - storageClassName, nbCopies, comment)); + catalogue.createStorageClass(m_cliSI, storageClassName, nbCopies, comment); const std::list<common::dataStructures::StorageClass> storageClasses = catalogue.getStorageClasses(); @@ -381,7 +387,7 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createStorageClass) { ASSERT_EQ(creationLog, lastModificationLog); } -TEST_F(cta_catalogue_SqliteCatalogueTest, createStorageClass_same_name_twice) { +TEST_F(cta_catalogue_SqliteCatalogueTest, createStorageClass_same_twice) { using namespace cta; catalogue::SqliteCatalogue catalogue; @@ -389,8 +395,7 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createStorageClass_same_name_twice) { const std::string storageClassName = "storage_class"; const uint64_t nbCopies = 2; const std::string comment = "create storage class"; - ASSERT_NO_THROW(catalogue.createStorageClass(m_cliSI, - storageClassName, nbCopies, comment)); + catalogue.createStorageClass(m_cliSI, storageClassName, nbCopies, comment); ASSERT_THROW(catalogue.createStorageClass(m_cliSI, storageClassName, nbCopies, comment), exception::Exception); } @@ -399,13 +404,15 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createTapePool) { using namespace cta; catalogue::SqliteCatalogue catalogue; + + ASSERT_TRUE(catalogue.getTapePools().empty()); const std::string tapePoolName = "tape_pool"; const uint64_t nbPartialTapes = 2; const bool is_encrypted = true; const std::string comment = "create tape pool"; - ASSERT_NO_THROW(catalogue.createTapePool(m_cliSI, - tapePoolName, nbPartialTapes, is_encrypted, comment)); + catalogue.createTapePool(m_cliSI, tapePoolName, nbPartialTapes, is_encrypted, + comment); const std::list<common::dataStructures::TapePool> pools = catalogue.getTapePools(); @@ -428,7 +435,7 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createTapePool) { ASSERT_EQ(creationLog, lastModificationLog); } -TEST_F(cta_catalogue_SqliteCatalogueTest, createTapePool_same_name_twice) { +TEST_F(cta_catalogue_SqliteCatalogueTest, createTapePool_same_twice) { using namespace cta; catalogue::SqliteCatalogue catalogue; @@ -437,8 +444,8 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createTapePool_same_name_twice) { const uint64_t nbPartialTapes = 2; const bool is_encrypted = true; const std::string comment = "create tape pool"; - ASSERT_NO_THROW(catalogue.createTapePool(m_cliSI, - tapePoolName, nbPartialTapes, is_encrypted, comment)); + catalogue.createTapePool(m_cliSI, tapePoolName, nbPartialTapes, is_encrypted, + comment); ASSERT_THROW(catalogue.createTapePool(m_cliSI, tapePoolName, nbPartialTapes, is_encrypted, comment), exception::Exception); @@ -449,21 +456,23 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createArchiveRoute) { catalogue::SqliteCatalogue catalogue; + ASSERT_TRUE(catalogue.getArchiveRoutes().empty()); + const std::string storageClassName = "storage_class"; const uint64_t nbCopies = 2; - ASSERT_NO_THROW(catalogue.createStorageClass(m_cliSI, - storageClassName, nbCopies, "create storage class")); + catalogue.createStorageClass(m_cliSI, storageClassName, nbCopies, + "create storage class"); const std::string tapePoolName = "tape_pool"; const uint64_t nbPartialTapes = 2; const bool is_encrypted = true; - ASSERT_NO_THROW(catalogue.createTapePool(m_cliSI, - tapePoolName, nbPartialTapes, is_encrypted, "create tape pool")); + catalogue.createTapePool(m_cliSI, tapePoolName, nbPartialTapes, is_encrypted, + "create tape pool"); const uint64_t copyNb = 1; const std::string comment = "create archive route"; - ASSERT_NO_THROW(catalogue.createArchiveRoute(m_cliSI, - storageClassName, copyNb, tapePoolName, comment)); + catalogue.createArchiveRoute(m_cliSI, storageClassName, copyNb, tapePoolName, + comment); const std::list<common::dataStructures::ArchiveRoute> routes = catalogue.getArchiveRoutes(); @@ -493,19 +502,19 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createArchiveRouteTapePool_same_twice) const std::string storageClassName = "storage_class"; const uint64_t nbCopies = 2; - ASSERT_NO_THROW(catalogue.createStorageClass(m_cliSI, - storageClassName, nbCopies, "create storage class")); + catalogue.createStorageClass(m_cliSI, storageClassName, nbCopies, + "create storage class"); const std::string tapePoolName = "tape_pool"; const uint64_t nbPartialTapes = 2; const bool is_encrypted = true; - ASSERT_NO_THROW(catalogue.createTapePool(m_cliSI, - tapePoolName, nbPartialTapes, is_encrypted, "create tape pool")); + catalogue.createTapePool(m_cliSI, tapePoolName, nbPartialTapes, is_encrypted, + "create tape pool"); const uint64_t copyNb = 1; const std::string comment = "create archive route"; - ASSERT_NO_THROW(catalogue.createArchiveRoute(m_cliSI, - storageClassName, copyNb, tapePoolName, comment)); + catalogue.createArchiveRoute(m_cliSI, storageClassName, copyNb, tapePoolName, + comment); ASSERT_THROW(catalogue.createArchiveRoute(m_cliSI, storageClassName, copyNb, tapePoolName, comment), exception::Exception); @@ -515,11 +524,12 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createLogicalLibrary) { using namespace cta; catalogue::SqliteCatalogue catalogue; + + ASSERT_TRUE(catalogue.getLogicalLibraries().empty()); const std::string logicalLibraryName = "logical_library"; const std::string comment = "create logical library"; - ASSERT_NO_THROW(catalogue.createLogicalLibrary(m_cliSI, - logicalLibraryName, comment)); + catalogue.createLogicalLibrary(m_cliSI, logicalLibraryName, comment); const std::list<common::dataStructures::LogicalLibrary> libs = catalogue.getLogicalLibraries(); @@ -540,18 +550,89 @@ TEST_F(cta_catalogue_SqliteCatalogueTest, createLogicalLibrary) { ASSERT_EQ(creationLog, lastModificationLog); } -TEST_F(cta_catalogue_SqliteCatalogueTest, createLogicalLibrary_same_name_twice) { +TEST_F(cta_catalogue_SqliteCatalogueTest, createLogicalLibrary_same_twice) { using namespace cta; catalogue::SqliteCatalogue catalogue; const std::string logicalLibraryName = "logical_library"; const std::string comment = "create logical library"; - ASSERT_NO_THROW(catalogue.createLogicalLibrary(m_cliSI, - logicalLibraryName, comment)); + catalogue.createLogicalLibrary(m_cliSI, logicalLibraryName, comment); ASSERT_THROW(catalogue.createLogicalLibrary(m_cliSI, logicalLibraryName, comment), exception::Exception); } +TEST_F(cta_catalogue_SqliteCatalogueTest, createTape) { + using namespace cta; + + catalogue::SqliteCatalogue catalogue; + + ASSERT_TRUE(catalogue.getTapes("", "", "", "", "", "", "", "").empty()); + + const std::string vid = "vid"; + const std::string logicalLibraryName = "logical_library_name"; + const std::string tapePoolName = "tape_pool_name"; + const std::string encryptionKey = "encryption_key"; + const uint64_t capacityInBytes = (uint64_t)10 * 1000 * 1000 * 1000 * 1000; + const bool disabledValue = true; + const bool fullValue = false; + const std::string comment = "create tape"; + + catalogue.createLogicalLibrary(m_cliSI, logicalLibraryName, + "create logical library"); + catalogue.createTapePool(m_cliSI, tapePoolName, 2, true, "create tape pool"); + catalogue.createTape(m_cliSI, vid, logicalLibraryName, tapePoolName, + encryptionKey, capacityInBytes, disabledValue, fullValue, + comment); + + const std::list<common::dataStructures::Tape> tapes = + catalogue.getTapes("", "", "", "", "", "", "", ""); + + ASSERT_EQ(1, tapes.size()); + + const common::dataStructures::Tape tape = tapes.front(); + ASSERT_EQ(vid, tape.vid); + ASSERT_EQ(logicalLibraryName, tape.logicalLibraryName); + ASSERT_EQ(tapePoolName, tape.tapePoolName); + ASSERT_EQ(encryptionKey, tape.encryptionKey); + ASSERT_EQ(capacityInBytes, tape.capacityInBytes); + ASSERT_TRUE(disabledValue == tape.disabled); + ASSERT_TRUE(fullValue == tape.full); + ASSERT_EQ(comment, tape.comment); + + const common::dataStructures::EntryLog creationLog = tape.creationLog; + ASSERT_EQ(m_cliSI.user.name, creationLog.user.name); + ASSERT_EQ(m_cliSI.user.group, creationLog.user.group); + ASSERT_EQ(m_cliSI.host, creationLog.host); + + const common::dataStructures::EntryLog lastModificationLog = + tape.lastModificationLog; + ASSERT_EQ(creationLog, lastModificationLog); +} + +TEST_F(cta_catalogue_SqliteCatalogueTest, createTape_same_twice) { + using namespace cta; + + catalogue::SqliteCatalogue catalogue; + + const std::string vid = "vid"; + const std::string logicalLibraryName = "logical_library_name"; + const std::string tapePoolName = "tape_pool_name"; + const std::string encryptionKey = "encryption_key"; + const uint64_t capacityInBytes = (uint64_t)10 * 1000 * 1000 * 1000 * 1000; + const bool disabledValue = true; + const bool fullValue = false; + const std::string comment = "create tape"; + + catalogue.createLogicalLibrary(m_cliSI, logicalLibraryName, + "create logical library"); + catalogue.createTapePool(m_cliSI, tapePoolName, 2, true, "create tape pool"); + catalogue.createTape(m_cliSI, vid, logicalLibraryName, tapePoolName, + encryptionKey, capacityInBytes, disabledValue, fullValue, comment); + ASSERT_THROW(catalogue.createTape(m_cliSI, vid, logicalLibraryName, + tapePoolName, encryptionKey, capacityInBytes, disabledValue, fullValue, + comment), exception::Exception); +} + } // namespace unitTests diff --git a/catalogue/SqliteConn.cpp b/catalogue/SqliteConn.cpp index 073d4bd76c..73704a03e2 100644 --- a/catalogue/SqliteConn.cpp +++ b/catalogue/SqliteConn.cpp @@ -16,7 +16,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "catalogue/Sqlite.hpp" #include "catalogue/SqliteConn.hpp" +#include "catalogue/SqliteStmt.hpp" #include "common/exception/Exception.hpp" //------------------------------------------------------------------------------ @@ -80,3 +82,26 @@ void cta::catalogue::SqliteConn::execNonQuery(const std::string &sql) { throw ex; } } + +//------------------------------------------------------------------------------ +// createStmt +//------------------------------------------------------------------------------ +cta::catalogue::SqliteStmt *cta::catalogue::SqliteConn::createStmt( + const std::string &sql) { + std::lock_guard<std::mutex> lock(m_mutex); + + sqlite3_stmt *stmt = NULL; + const int nByte = -1; // Read SQL up to first null terminator + const int prepareRc = sqlite3_prepare_v2(m_conn, sql.c_str(), nByte, &stmt, + NULL); + if(SQLITE_OK != prepareRc) { + sqlite3_finalize(stmt); + exception::Exception ex; + ex.getMessage() << __FUNCTION__ << " failed" + ": Failed to prepare SQL statement " << sql << ": " << + sqlite3_errmsg(m_conn); + throw ex; + } + + return new SqliteStmt(sql, stmt); +} diff --git a/catalogue/SqliteConn.hpp b/catalogue/SqliteConn.hpp index 147c357e37..66dfbd91b4 100644 --- a/catalogue/SqliteConn.hpp +++ b/catalogue/SqliteConn.hpp @@ -18,12 +18,19 @@ #pragma once +#include <mutex> #include <sqlite3.h> #include <string> namespace cta { namespace catalogue { +/** + * Forward declaraion to avoid a circular dependency beween SqliteConn and + * SqliteStmt. + */ +class SqliteStmt; + /** * A C++ wrapper around a connectioin an SQLite database. */ @@ -61,8 +68,22 @@ public: */ void execNonQuery(const std::string &sql); + /** + * Creates a prepared statement. + * + * @sql The SQL statement. + * @return The prepared statement. + */ + SqliteStmt *createStmt(const std::string &sql); + private: + /** + * Mutex to be used to create a critical section around the database + * connection. + */ + std::mutex m_mutex; + /** * The database connection. */ diff --git a/catalogue/SqliteStmt.cpp b/catalogue/SqliteStmt.cpp index 25b3317ac8..662e6eca72 100644 --- a/catalogue/SqliteStmt.cpp +++ b/catalogue/SqliteStmt.cpp @@ -17,26 +17,18 @@ */ #include "catalogue/Sqlite.hpp" +#include "catalogue/SqliteConn.hpp" #include "catalogue/SqliteStmt.hpp" #include "common/exception/Exception.hpp" //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -cta::catalogue::SqliteStmt::SqliteStmt(const SqliteConn &conn, - const std::string &sql): m_sql(sql) { - m_stmt = NULL; - const int nByte = -1; // Read SQL up to first null terminator - const int prepareRc = sqlite3_prepare_v2(conn.get(), sql.c_str(), nByte, - &m_stmt, NULL); - if(SQLITE_OK != prepareRc) { - sqlite3_finalize(m_stmt); - exception::Exception ex; - ex.getMessage() << __FUNCTION__ << " failed" - ": Failed to prepare SQL statement " << sql; - throw ex; - } -} +cta::catalogue::SqliteStmt::SqliteStmt(const std::string &sql, + sqlite3_stmt *const stmt): + m_sql(sql), + m_stmt(stmt) { +} //------------------------------------------------------------------------------ // destructor @@ -45,6 +37,13 @@ cta::catalogue::SqliteStmt::~SqliteStmt() throw() { sqlite3_finalize(m_stmt); } +//------------------------------------------------------------------------------ +// getSql +//------------------------------------------------------------------------------ +const std::string &cta::catalogue::SqliteStmt::getSql() const { + return m_sql; +} + //------------------------------------------------------------------------------ // get //------------------------------------------------------------------------------ diff --git a/catalogue/SqliteStmt.hpp b/catalogue/SqliteStmt.hpp index 550ae49399..edaa78ce25 100644 --- a/catalogue/SqliteStmt.hpp +++ b/catalogue/SqliteStmt.hpp @@ -18,7 +18,6 @@ #pragma once -#include "catalogue/SqliteConn.hpp" #include "catalogue/ColumnNameToIdx.hpp" #include <map> @@ -29,6 +28,12 @@ namespace cta { namespace catalogue { +/** + * Forward decalaration to avoid a circular depedency between SqliteConn and + * SqliteStmt. + */ +class SqliteConn; + /** * A C++ wrapper around an SQLite prepared statement. */ @@ -38,16 +43,23 @@ public: /** * Constructor. * - * @param conn The SQLite database connection. * @param sql The SQL statement. + * @param stmt The SQLite prepared statement. */ - SqliteStmt(const SqliteConn &conn, const std::string &sql); + SqliteStmt(const std::string &sql, sqlite3_stmt *const stmt); /** * Destructor. */ ~SqliteStmt() throw(); + /** + * Returns the SQL statement. + * + * @return The SQL statement. + */ + const std::string &getSql() const; + /** * Returns the underlying prepared statement. * @@ -76,7 +88,7 @@ public: * * This method throws a exception if sqlite3_step() returns an error. * - * @return See sqlite3_step() documenetation. + * @return See sqlite3_step() documentation. */ int step(); diff --git a/catalogue/SqliteStmtTest.cpp b/catalogue/SqliteStmtTest.cpp index ae7a83f179..1810aa9823 100644 --- a/catalogue/SqliteStmtTest.cpp +++ b/catalogue/SqliteStmtTest.cpp @@ -46,8 +46,8 @@ TEST_F(cta_catalogue_SqliteStmtTest, create_table) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - SqliteStmt stmt(conn, sql); - ASSERT_EQ(SQLITE_DONE, stmt.step()); + std::unique_ptr<SqliteStmt> stmt(conn.createStmt(sql)); + ASSERT_EQ(SQLITE_DONE, stmt->step()); } } @@ -63,8 +63,8 @@ TEST_F(cta_catalogue_SqliteStmtTest, select_from_empty_table) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - SqliteStmt stmt(conn, sql); - ASSERT_EQ(SQLITE_DONE, stmt.step()); + std::unique_ptr<SqliteStmt> stmt(conn.createStmt(sql)); + ASSERT_EQ(SQLITE_DONE, stmt->step()); } // Select from the empty table @@ -75,8 +75,8 @@ TEST_F(cta_catalogue_SqliteStmtTest, select_from_empty_table) { "COL2," "COL3 " "FROM TEST;"; - SqliteStmt stmt(conn, sql); - ASSERT_EQ(SQLITE_DONE, stmt.step()); + std::unique_ptr<SqliteStmt> stmt(conn.createStmt(sql)); + ASSERT_EQ(SQLITE_DONE, stmt->step()); } } @@ -92,8 +92,8 @@ TEST_F(cta_catalogue_SqliteStmtTest, insert_without_bind) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - SqliteStmt stmt(conn, sql); - ASSERT_EQ(SQLITE_DONE, stmt.step()); + std::unique_ptr<SqliteStmt> stmt(conn.createStmt(sql)); + ASSERT_EQ(SQLITE_DONE, stmt->step()); } // Insert a row into the test table @@ -107,8 +107,8 @@ TEST_F(cta_catalogue_SqliteStmtTest, insert_without_bind) { "'one'," "'two'," "3);"; - SqliteStmt stmt(conn, sql); - ASSERT_EQ(SQLITE_DONE, stmt.step()); + std::unique_ptr<SqliteStmt> stmt(conn.createStmt(sql)); + ASSERT_EQ(SQLITE_DONE, stmt->step()); } // Select the row back from the table @@ -119,25 +119,25 @@ TEST_F(cta_catalogue_SqliteStmtTest, insert_without_bind) { "COL2 AS COL2," "COL3 AS COL3 " "FROM TEST;"; - SqliteStmt stmt(conn, sql); - ASSERT_EQ(SQLITE_ROW, stmt.step()); + std::unique_ptr<SqliteStmt> stmt(conn.createStmt(sql)); + ASSERT_EQ(SQLITE_ROW, stmt->step()); ColumnNameToIdx nameToIdx; - ASSERT_NO_THROW(nameToIdx = stmt.getColumnNameToIdx()); + ASSERT_NO_THROW(nameToIdx = stmt->getColumnNameToIdx()); std::string col1; std::string col2; uint64_t col3 = 0; - ASSERT_NO_THROW(col1 = stmt.columnText(nameToIdx["COL1"])); - ASSERT_NO_THROW(col2 = stmt.columnText(nameToIdx["COL2"])); - ASSERT_NO_THROW(col3 = stmt.columnUint64(nameToIdx["COL3"])); + ASSERT_NO_THROW(col1 = stmt->columnText(nameToIdx["COL1"])); + ASSERT_NO_THROW(col2 = stmt->columnText(nameToIdx["COL2"])); + ASSERT_NO_THROW(col3 = stmt->columnUint64(nameToIdx["COL3"])); ASSERT_EQ("one", col1); ASSERT_EQ("two", col2); ASSERT_EQ((uint64_t)3, col3); - ASSERT_EQ(SQLITE_DONE, stmt.step()); + ASSERT_EQ(SQLITE_DONE, stmt->step()); } } @@ -153,8 +153,8 @@ TEST_F(cta_catalogue_SqliteStmtTest, insert_with_bind) { "COL1 TEXT," "COL2 TEXT," "COL3 INTEGER);"; - SqliteStmt stmt(conn, sql); - ASSERT_EQ(SQLITE_DONE, stmt.step()); + std::unique_ptr<SqliteStmt> stmt(conn.createStmt(sql)); + ASSERT_EQ(SQLITE_DONE, stmt->step()); } // Insert a row into the test table @@ -168,11 +168,11 @@ TEST_F(cta_catalogue_SqliteStmtTest, insert_with_bind) { ":COL1," ":COL2," ":COL3);"; - SqliteStmt stmt(conn, sql); - ASSERT_NO_THROW(stmt.bind(":COL1", "one")); - ASSERT_NO_THROW(stmt.bind(":COL2", "two")); - ASSERT_NO_THROW(stmt.bind(":COL3", 3)); - ASSERT_EQ(SQLITE_DONE, stmt.step()); + std::unique_ptr<SqliteStmt> stmt(conn.createStmt(sql)); + ASSERT_NO_THROW(stmt->bind(":COL1", "one")); + ASSERT_NO_THROW(stmt->bind(":COL2", "two")); + ASSERT_NO_THROW(stmt->bind(":COL3", 3)); + ASSERT_EQ(SQLITE_DONE, stmt->step()); } // Select the row back from the table @@ -183,25 +183,25 @@ TEST_F(cta_catalogue_SqliteStmtTest, insert_with_bind) { "COL2 AS COL2," "COL3 AS COL3 " "FROM TEST;"; - SqliteStmt stmt(conn, sql); - ASSERT_EQ(SQLITE_ROW, stmt.step()); + std::unique_ptr<SqliteStmt> stmt(conn.createStmt(sql)); + ASSERT_EQ(SQLITE_ROW, stmt->step()); ColumnNameToIdx nameToIdx; - ASSERT_NO_THROW(nameToIdx = stmt.getColumnNameToIdx()); + ASSERT_NO_THROW(nameToIdx = stmt->getColumnNameToIdx()); std::string col1; std::string col2; uint64_t col3 = 0; - ASSERT_NO_THROW(col1 = stmt.columnText(nameToIdx["COL1"])); - ASSERT_NO_THROW(col2 = stmt.columnText(nameToIdx["COL2"])); - ASSERT_NO_THROW(col3 = stmt.columnUint64(nameToIdx["COL3"])); + ASSERT_NO_THROW(col1 = stmt->columnText(nameToIdx["COL1"])); + ASSERT_NO_THROW(col2 = stmt->columnText(nameToIdx["COL2"])); + ASSERT_NO_THROW(col3 = stmt->columnUint64(nameToIdx["COL3"])); ASSERT_EQ("one", col1); ASSERT_EQ("two", col2); ASSERT_EQ((uint64_t)3, col3); - ASSERT_EQ(SQLITE_DONE, stmt.step()); + ASSERT_EQ(SQLITE_DONE, stmt->step()); } } diff --git a/doxygen/.gitignore b/doxygen/.gitignore index d092772385..1936cc1d44 100644 --- a/doxygen/.gitignore +++ b/doxygen/.gitignore @@ -1,2 +1 @@ -# Ignore everything in this directory except this file -!.gitignore +html -- GitLab