Commit ee923af1 authored by Steven Murray's avatar Steven Murray
Browse files

Added delete functionality to the Catalogue

parent 3a620793
......@@ -61,9 +61,9 @@ target_link_libraries (ctacatalogue
${SQLITE_LIBRARIES})
add_custom_command(OUTPUT sqlite_catalogue_schema.sql oracle_catalogue_schema.sql
COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/sqlite_catalogue_schema_header.sql ${CMAKE_CURRENT_SOURCE_DIR}/catalogue_common_schema.sql > sqlite_catalogue_schema.sql
COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/sqlite_catalogue_schema_header.sql ${CMAKE_CURRENT_SOURCE_DIR}/catalogue_common_schema.sql ${CMAKE_CURRENT_SOURCE_DIR}/sqlite_catalogue_schema_trailer.sql > sqlite_catalogue_schema.sql
COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/catalogue_common_schema.sql > oracle_catalogue_schema.sql
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/sqlite_catalogue_schema_header.sql catalogue_common_schema.sql)
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/sqlite_catalogue_schema_header.sql catalogue_common_schema.sql ${CMAKE_CURRENT_SOURCE_DIR}/sqlite_catalogue_schema_trailer.sql)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/sqlite_catalogue_schema.sql
DESTINATION usr/share/cta-${CTA_VERSION}/sql
......@@ -74,7 +74,7 @@ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/oracle_catalogue_schema.sql
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
add_custom_command(OUTPUT in_memory_catalogue_schema.cpp
COMMAND sed 's/^/\ \ \ \ \"/' sqlite_catalogue_schema.sql | sed 's/$$/\"/' > in_memory_catalogue_schema.cpp
COMMAND sed 's/^/\ \ \"/' sqlite_catalogue_schema.sql | sed 's/$$/\"/' > in_memory_catalogue_schema.cpp
DEPENDS sqlite_catalogue_schema.sql)
add_custom_command(OUTPUT InMemoryCatalogueSchema.cpp
......
......@@ -138,11 +138,11 @@ public:
virtual void createRequester(
const common::dataStructures::SecurityIdentity &cliIdentity,
const common::dataStructures::UserIdentity &user,
const std::string &requesterName,
const std::string &mountPolicy,
const std::string &comment) = 0;
virtual void deleteRequester(const common::dataStructures::UserIdentity &user) = 0;
virtual void deleteRequester(const std::string &requesterName) = 0;
virtual std::list<common::dataStructures::Requester> getRequesters() const = 0;
virtual void modifyRequesterMountPolicy(const common::dataStructures::SecurityIdentity &cliIdentity, const common::dataStructures::UserIdentity &user, const std::string &mountPolicy) = 0;
virtual void modifyRequesterComment(const common::dataStructures::SecurityIdentity &cliIdentity, const common::dataStructures::UserIdentity &user, const std::string &comment) = 0;
......@@ -157,6 +157,35 @@ public:
const uint64_t maxDrivesAllowed,
const std::string &comment) = 0;
/**
* Assigns the specified mount policy to the specified requester.
*
* Please note that requester mount-policies overrule requester-group
* mount-policies.
*
* @param cliIdentity The user of the command-line tool.
* @param mountPolicyName The name of the mount policy.
* @param requesterName The name of the requester.
* @param comment Comment.
*/
virtual void assignMountPolicyToRequester(
const common::dataStructures::SecurityIdentity &cliIdentity,
const std::string &mountPolicyName,
const std::string &requesterName,
const std::string &comment) = 0;
/**
* Assigns the specified mount policy to the specified requester group.
*
* Please note that requester mount-policies overrule requester-group
* mount-policies.
*
* @param mountPolicyName The name of the mount policy.
* @param requesterGrouprName The name of the requester group.
*/
virtual void assignMountPolicyToRequesterGroup(const std::string &mountPolicyName,
const std::string &requesterGroupName) = 0;
virtual void deleteMountPolicy(const std::string &name) = 0;
virtual std::list<common::dataStructures::MountPolicy> getMountPolicies() const = 0;
virtual void modifyMountPolicyArchivePriority(const common::dataStructures::SecurityIdentity &cliIdentity, const std::string &name, const uint64_t archivePriority) = 0;
......@@ -222,6 +251,16 @@ public:
*/
virtual void fileWrittenToTape(const TapeFileWritten &event) = 0;
/**
* Deletes the specified archive file and its associated tape copies from the
* catalogue.
*
* @param archiveFileId The unique identifier of the archive file.
* @return The metadata of the deleted archive file including the metadata of
* the associated and also deleted tape copies.
*/
virtual common::dataStructures::ArchiveFile deleteArchiveFile(const uint64_t archiveFileId) = 0;
/**
* Prepares for a file retrieval by returning the information required to
* queue the associated retrieve request(s).
......@@ -243,10 +282,10 @@ public:
/**
* Returns the mount policy for the specified end user.
*
* @param user The name of the end user.
* @param username The name of the end user.
* @return The mount policy.
*/
virtual common::dataStructures::MountPolicy getMountPolicyForAUser(const common::dataStructures::UserIdentity &user) const = 0;
virtual common::dataStructures::MountPolicy getMountPolicyForAUser(const std::string &username) const = 0;
virtual bool isAdmin(const common::dataStructures::SecurityIdentity &cliIdentity) const = 0;
......
......@@ -78,6 +78,14 @@ public:
*/
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;
}; // class DbStmt
} // namespace catalogue
......
This diff is collapsed.
......@@ -143,6 +143,13 @@ void OcciStmt::executeNonQuery() {
}
}
//------------------------------------------------------------------------------
// getNbAffectedRows
//------------------------------------------------------------------------------
uint64_t OcciStmt::getNbAffectedRows() const {
throw exception::Exception(std::string(__FUNCTION__) + " not implemented");
}
//------------------------------------------------------------------------------
// get
//------------------------------------------------------------------------------
......
......@@ -107,6 +107,14 @@ public:
*/
virtual void executeNonQuery();
/**
* Returns the number of rows affected by the last execution of this
* statement.
*
* @return The number of affected rows.
*/
virtual uint64_t getNbAffectedRows() const;
/**
* Returns the underlying OCCI result set.
*
......
......@@ -40,6 +40,13 @@ OracleCatalogue::OracleCatalogue(
OracleCatalogue::~OracleCatalogue() {
}
//------------------------------------------------------------------------------
// deleteArchiveFile
//------------------------------------------------------------------------------
common::dataStructures::ArchiveFile OracleCatalogue::deleteArchiveFile(const uint64_t archiveFileId) {
throw exception::Exception(std::string(__FUNCTION__) + " not implemented");
}
//------------------------------------------------------------------------------
// getNextArchiveFileId
//------------------------------------------------------------------------------
......
......@@ -58,6 +58,16 @@ public:
*/
virtual ~OracleCatalogue();
/**
* Deletes the specified archive file and its associated tape copies from the
* catalogue.
*
* @param archiveFileId The unique identifier of the archive file.
* @return The metadata of the deleted archive file including the metadata of
* the associated and also deleted tape copies.
*/
virtual common::dataStructures::ArchiveFile deleteArchiveFile(const uint64_t archiveFileId);
/**
* Returns a unique archive ID that can be used by a new archive file within
* the catalogue.
......
This diff is collapsed.
......@@ -20,6 +20,7 @@
#include "catalogue/Catalogue.hpp"
#include "catalogue/DbConn.hpp"
#include "catalogue/RequesterAndGroupMountPolicies.hpp"
#include <memory>
#include <mutex>
......@@ -118,8 +119,13 @@ public:
virtual void setTapeLbp(const common::dataStructures::SecurityIdentity &cliIdentity, const std::string &vid, const bool lbpValue); // internal function (noCLI)
virtual void modifyTapeComment(const common::dataStructures::SecurityIdentity &cliIdentity, const std::string &vid, const std::string &comment);
virtual void createRequester(const common::dataStructures::SecurityIdentity &cliIdentity, const common::dataStructures::UserIdentity &user, const std::string &mountPolicy, const std::string &comment);
virtual void deleteRequester(const common::dataStructures::UserIdentity &user);
virtual void createRequester(
const common::dataStructures::SecurityIdentity &cliIdentity,
const std::string &requesterName,
const std::string &mountPolicy,
const std::string &comment);
virtual void deleteRequester(const std::string &requesterName);
virtual std::list<common::dataStructures::Requester> getRequesters() const;
virtual void modifyRequesterMountPolicy(const common::dataStructures::SecurityIdentity &cliIdentity, const common::dataStructures::UserIdentity &user, const std::string &mountPolicy);
virtual void modifyRequesterComment(const common::dataStructures::SecurityIdentity &cliIdentity, const common::dataStructures::UserIdentity &user, const std::string &comment);
......@@ -134,6 +140,35 @@ public:
const uint64_t maxDrivesAllowed,
const std::string &comment);
/**
* Assigns the specified mount policy to the specified requester.
*
* Please note that requester mount-policies overrule requester-group
* mount-policies.
*
* @param cliIdentity The user of the command-line tool.
* @param mountPolicyName The name of the mount policy.
* @param requesterName The name of the requester.
* @param comment Comment.
*/
virtual void assignMountPolicyToRequester(
const common::dataStructures::SecurityIdentity &cliIdentity,
const std::string &mountPolicyName,
const std::string &requesterName,
const std::string &comment);
/**
* Assigns the specified mount policy to the specified requester group.
*
* Please note that requester mount-policies overrule requester-group
* mount-policies.
*
* @param mountPolicyName The name of the mount policy.
* @param requesterGrouprName The name of the requester group.
*/
virtual void assignMountPolicyToRequesterGroup(const std::string &mountPolicyName,
const std::string &requesterGroupName);
virtual void deleteMountPolicy(const std::string &name);
virtual std::list<common::dataStructures::MountPolicy> getMountPolicies() const;
virtual void modifyMountPolicyArchivePriority(const common::dataStructures::SecurityIdentity &cliIdentity, const std::string &name, const uint64_t archivePriority);
......@@ -219,15 +254,15 @@ public:
/**
* Returns the mount policy for the specified end user.
*
* @param user The name of the end user.
* @return The archive mount policy.
* @param username The name of the end user.
* @return The mount policy.
*/
virtual common::dataStructures::MountPolicy getMountPolicyForAUser(const common::dataStructures::UserIdentity &user) const;
virtual common::dataStructures::MountPolicy getMountPolicyForAUser(const std::string &username) const;
/**
* Returns true if the specified user has admin privileges.
*
* @param cliIdentity The user.
* @param cliIdentity The user of the command-line tool.
* @return True if the specified user has admin privileges.:w
*/
virtual bool isAdmin(const common::dataStructures::SecurityIdentity &cliIdentity) const;
......@@ -298,6 +333,30 @@ protected:
*/
bool mountPolicyExists(const std::string &mountPolicyName) const;
/**
* Returns true if the specified requester exists.
*
* @param requesterName The username of the requester.
* @return True if the requester exists.
*/
bool requesterExists(const std::string &requesterName) const;
/**
* Returns the specified requester mount-policy or NULL if one does not exist.
*
* @param requesterName The name of the requester.
* @return The mount policy.
*/
common::dataStructures::MountPolicy *getRequesterMountPolicy(const std::string &requesterName) const;
/**
* Returns true if the specified requester group exists.
*
* @param requesterGroupName The name of the requester group.
* @return True if the requester group exists.
*/
bool requesterGroupExists(const std::string &requesterGroupName) const;
/**
* An RdbmsCatalogue specific method that inserts the specified row into the
* ArchiveFile table.
......@@ -409,6 +468,16 @@ protected:
*/
std::map<uint64_t, common::dataStructures::TapeFile>getTapeFiles(const uint64_t archiveFileId) const;
/**
* Returns the mount policies for the specified requester and requester group.
*
* @param requesterName The name of the requester.
* @param requesterGroupName The name of the requester group.
* @return The mount policies.
*/
RequesterAndGroupMountPolicies getMountPolicies(const std::string &requesterName,
const std::string &requesterGroupName);
/**
* Returns a unique archive ID that can be used by a new archive file within
* the catalogue.
......
/*
* 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/dataStructures/MountPolicy.hpp"
#include <list>
namespace cta {
namespace catalogue {
/**
* Structure containing a list of requester mount-polices and a list of
* requester-group mount-policies.
*/
struct RequesterAndGroupMountPolicies {
/**
* List of requester mount-policies.
*/
std::list<common::dataStructures::MountPolicy> requesterMountPolicies;
/**
* List of requester-group mount-policies.
*/
std::list<common::dataStructures::MountPolicy> requesterGroupMountPolicies;
}; // struct RequesterAndGroupMountPolicies
} // namespace catalogue
} // namespace cta
......@@ -16,9 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "catalogue/SqliteCatalogue.hpp"
#include "catalogue/AutoRollback.hpp"
#include "catalogue/RdbmsCatalogueSchema.hpp"
#include "catalogue/SqliteCatalogue.hpp"
#include "catalogue/SqliteConn.hpp"
#include "catalogue/UserError.hpp"
#include "common/exception/Exception.hpp"
namespace cta {
......@@ -44,12 +46,115 @@ SqliteCatalogue::SqliteCatalogue() {
SqliteCatalogue::~SqliteCatalogue() {
}
//------------------------------------------------------------------------------
// deleteArchiveFile
//------------------------------------------------------------------------------
common::dataStructures::ArchiveFile SqliteCatalogue::deleteArchiveFile(const uint64_t archiveFileId) {
try {
std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile;
m_conn->executeNonQuery("BEGIN EXCLUSIVE;");
const char *selectSql =
"SELECT "
"ARCHIVE_FILE.ARCHIVE_FILE_ID AS ARCHIVE_FILE_ID,"
"ARCHIVE_FILE.DISK_INSTANCE AS DISK_INSTANCE,"
"ARCHIVE_FILE.DISK_FILE_ID AS DISK_FILE_ID,"
"ARCHIVE_FILE.DISK_FILE_PATH AS DISK_FILE_PATH,"
"ARCHIVE_FILE.DISK_FILE_USER AS DISK_FILE_USER,"
"ARCHIVE_FILE.DISK_FILE_GROUP AS DISK_FILE_GROUP,"
"ARCHIVE_FILE.DISK_FILE_RECOVERY_BLOB AS DISK_FILE_RECOVERY_BLOB,"
"ARCHIVE_FILE.FILE_SIZE AS FILE_SIZE,"
"ARCHIVE_FILE.CHECKSUM_TYPE AS CHECKSUM_TYPE,"
"ARCHIVE_FILE.CHECKSUM_VALUE AS CHECKSUM_VALUE,"
"ARCHIVE_FILE.STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
"ARCHIVE_FILE.CREATION_TIME AS ARCHIVE_FILE_CREATION_TIME,"
"ARCHIVE_FILE.RECONCILIATION_TIME AS RECONCILIATION_TIME,"
"TAPE_FILE.VID AS VID,"
"TAPE_FILE.FSEQ AS FSEQ,"
"TAPE_FILE.BLOCK_ID AS BLOCK_ID,"
"TAPE_FILE.COMPRESSED_SIZE AS COMPRESSED_SIZE,"
"TAPE_FILE.COPY_NB AS COPY_NB,"
"TAPE_FILE.CREATION_TIME AS TAPE_FILE_CREATION_TIME "
"FROM "
"ARCHIVE_FILE "
"LEFT OUTER JOIN TAPE_FILE ON "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = TAPE_FILE.ARCHIVE_FILE_ID "
"WHERE "
"ARCHIVE_FILE.ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID";
std::unique_ptr<DbStmt> selectStmt(m_conn->createStmt(selectSql));
selectStmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
std::unique_ptr<DbRset> selectRset(selectStmt->executeQuery());
while(selectRset->next()) {
if(NULL == archiveFile.get()) {
archiveFile.reset(new common::dataStructures::ArchiveFile);
archiveFile->archiveFileID = selectRset->columnUint64("ARCHIVE_FILE_ID");
archiveFile->diskInstance = selectRset->columnText("DISK_INSTANCE");
archiveFile->diskFileID = selectRset->columnText("DISK_FILE_ID");
archiveFile->drData.drPath = selectRset->columnText("DISK_FILE_PATH");
archiveFile->drData.drOwner = selectRset->columnText("DISK_FILE_USER");
archiveFile->drData.drGroup = selectRset->columnText("DISK_FILE_GROUP");
archiveFile->drData.drBlob = selectRset->columnText("DISK_FILE_RECOVERY_BLOB");
archiveFile->fileSize = selectRset->columnUint64("FILE_SIZE");
archiveFile->checksumType = selectRset->columnText("CHECKSUM_TYPE");
archiveFile->checksumValue = selectRset->columnText("CHECKSUM_VALUE");
archiveFile->storageClass = selectRset->columnText("STORAGE_CLASS_NAME");
archiveFile->creationTime = selectRset->columnUint64("ARCHIVE_FILE_CREATION_TIME");
archiveFile->reconciliationTime = selectRset->columnUint64("RECONCILIATION_TIME");
}
// If there is a tape file
if(!selectRset->columnIsNull("VID")) {
// Add the tape file to the archive file's in-memory structure
common::dataStructures::TapeFile tapeFile;
tapeFile.vid = selectRset->columnText("VID");
tapeFile.fSeq = selectRset->columnUint64("FSEQ");
tapeFile.blockId = selectRset->columnUint64("BLOCK_ID");
tapeFile.compressedSize = selectRset->columnUint64("COMPRESSED_SIZE");
tapeFile.copyNb = selectRset->columnUint64("COPY_NB");
tapeFile.creationTime = selectRset->columnUint64("TAPE_FILE_CREATION_TIME");
archiveFile->tapeFiles[selectRset->columnUint64("COPY_NB")] = tapeFile;
}
}
if(NULL == archiveFile.get()) {
UserError ue;
ue.getMessage() << "Failed to delete archive file with ID " << archiveFileId << " because it does not exist";
throw ue;
}
{
const char *const sql = "DELETE FROM TAPE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID;";
std::unique_ptr<DbStmt> stmt(m_conn->createStmt(sql));
stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
stmt->executeNonQuery();
}
{
const char *const sql = "DELETE FROM ARCHIVE_FILE WHERE ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID;";
std::unique_ptr<DbStmt> stmt(m_conn->createStmt(sql));
stmt->bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
stmt->executeNonQuery();
}
m_conn->commit();
return *archiveFile;
} catch(UserError &) {
throw;
} catch(exception::Exception &ex) {
throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
}
}
//------------------------------------------------------------------------------
// getNextArchiveFileId
//------------------------------------------------------------------------------
uint64_t SqliteCatalogue::getNextArchiveFileId() {
try {
m_conn->executeNonQuery("BEGIN EXCLUSIVE;");
AutoRollback autoRollback(m_conn.get());
m_conn->executeNonQuery("UPDATE ARCHIVE_FILE_ID SET ID = ID + 1;");
uint64_t archiveFileId = 0;
{
......
......@@ -63,6 +63,16 @@ public:
*/
virtual ~SqliteCatalogue();
/**
* Deletes the specified archive file and its associated tape copies from the
* catalogue.
*
* @param archiveFileId The unique identifier of the archive file.
* @return The metadata of the deleted archive file including the metadata of
* the associated and also deleted tape copies.
*/
virtual common::dataStructures::ArchiveFile deleteArchiveFile(const uint64_t archiveFileId);
protected:
/**
......
......@@ -33,11 +33,24 @@ namespace catalogue {
SqliteConn::SqliteConn(const std::string &filename) {
try {
m_conn = NULL;
if (sqlite3_open_v2(filename.c_str(), &m_conn, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL)) {
if(sqlite3_open_v2(filename.c_str(), &m_conn, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI, NULL)) {
std::string msg = sqlite3_errmsg(m_conn);
sqlite3_close(m_conn);
throw exception::Exception(msg);
}
{
char *errMsg = NULL;
if(SQLITE_OK != sqlite3_exec(m_conn, "PRAGMA foreign_keys = ON;", NULL, NULL, &errMsg)) {
exception::Exception ex;
ex.getMessage() << "Failed to to set PRAGMA foreign_keys = ON";
if(NULL != errMsg) {
ex.getMessage() << ": " << errMsg;
sqlite3_free(errMsg);
}
sqlite3_close(m_conn);
throw ex;
}
}
} catch(exception::Exception &ex) {
throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
}
......@@ -78,7 +91,7 @@ DbStmt *SqliteConn::createStmt(const std::string &sql) {
throw exception::Exception(msg);
}
return new SqliteStmt(sql, stmt);
return new SqliteStmt(*this, sql, stmt);
} catch(exception::Exception &ex) {
throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + sql + ": " +
ex.getMessage().str());
......
......@@ -38,6 +38,12 @@ class SqliteStmt;
class SqliteConn: public DbConn {
public:
/**
* The SqliteStmt class can lock the m_mutex member of the SqliteConn class
* and it can read the pointer to the SQLite connection.
*/
friend SqliteStmt;
/**
* Constructor.
*
......
......@@ -32,10 +32,12 @@ namespace catalogue {
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
SqliteStmt::SqliteStmt(const std::string &sql, sqlite3_stmt *const stmt):
SqliteStmt::SqliteStmt(SqliteConn &conn, const std::string &sql, sqlite3_stmt *const stmt):
m_conn(conn),
m_sql(sql),
m_paramNameToIdx(sql),
m_stmt(stmt) {
m_stmt(stmt),
m_nbAffectedRows(0) {
if (NULL == stmt) {
throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + sql + ": stmt is NULL");
......@@ -116,6 +118,8 @@ DbRset *SqliteStmt::executeQuery() {
// executeNonQuery
//------------------------------------------------------------------------------
void SqliteStmt::executeNonQuery() {
std::lock_guard<std::mutex> connLock(m_conn.m_mutex);
const int stepRc = sqlite3_step(m_stmt);
// Throw an exception if the call to sqlite3_step() failed
......@@ -124,6 +128,8 @@ void SqliteStmt::executeNonQuery() {
Sqlite::rcToStr(stepRc));
}
m_nbAffectedRows = sqlite3_changes(m_conn.m_conn);
// Throw an exception if the SQL statement returned a result set
if(SQLITE_ROW == stepRc) {
throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + getSql() +
......@@ -131,5 +137,12 @@ void SqliteStmt::executeNonQuery() {
}
}
//------------------------------------------------------------------------------
// getNbAffectedRows
//------------------------------------------------------------------------------
uint64_t SqliteStmt::getNbAffectedRows() const {
return m_nbAffectedRows;
}
} // namespace catalogue
} // namespace cta
......@@ -41,11 +41,12 @@ public:
/**
* Constructor.
*
*
* @param conn The database connection.
* @param sql The SQL statement.
* @param stmt The prepared statement.
*/
SqliteStmt(const std::string &sql, sqlite3_stmt *const stmt);