Commit 1251850f authored by Steven Murray's avatar Steven Murray
Browse files

SqliteRset::next() now throws DatabaseConstraintViolation

parent 49190c08
......@@ -79,6 +79,7 @@ set (COMMON_LIB_SRC_FILES
exception/Backtrace.cpp
exception/BadAlloc.cpp
exception/CommandLineNotParsed.cpp
exception/DatabaseConstraintViolation.cpp
exception/DismountFailed.cpp
exception/Errnum.cpp
exception/Exception.cpp
......
/*
* 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/DatabaseConstraintViolation.hpp"
namespace cta {
namespace exception {
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
DatabaseConstraintViolation::DatabaseConstraintViolation(const std::string &context, const bool embedBacktrace):
Exception(context, embedBacktrace) {
}
//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
DatabaseConstraintViolation::~DatabaseConstraintViolation() noexcept {
}
} // namespace exception
} // namespace cta
/*
* 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/exception/Exception.hpp"
#include <string>
namespace cta {
namespace exception {
/**
* A database constraint has been violated.
*/
class DatabaseConstraintViolation : public cta::exception::Exception {
public:
/**
* Constructor.
*
* @param context optional context string added to the message
* at initialisation time.
* @param embedBacktrace whether to embed a backtrace of where the
* exception was throw in the message
*/
DatabaseConstraintViolation(const std::string &context = "", const bool embedBacktrace = true);
/**
* Empty Destructor, explicitely non-throwing (needed for std::exception
* inheritance)
*/
~DatabaseConstraintViolation() noexcept override;
}; // class DatabaseConstraintViolation
} // namespace exception
} // namespace cta
......@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/exception/DatabaseConstraintViolation.hpp"
#include "common/exception/Exception.hpp"
#include "common/exception/Errnum.hpp"
#include "rdbms/NullDbValue.hpp"
......@@ -151,7 +152,13 @@ bool SqliteRset::next() {
// Throw an exception if the call to sqlite3_step() failed
if(SQLITE_DONE != stepRc && SQLITE_ROW != stepRc) {
throw exception::Exception(Sqlite::rcToStr(stepRc));
const std::string msg = Sqlite::rcToStr(stepRc);
if(SQLITE_CONSTRAINT == stepRc) {
throw exception::DatabaseConstraintViolation(msg);
} else {
throw exception::Exception(msg);
}
}
if(SQLITE_ROW == stepRc) {
......
......@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/exception/DatabaseConstraintViolation.hpp"
#include "rdbms/wrapper/SqliteConn.hpp"
#include "rdbms/wrapper/SqliteRset.hpp"
#include "rdbms/wrapper/SqliteStmt.hpp"
......@@ -358,4 +359,50 @@ TEST_F(cta_rdbms_wrapper_SqliteStmtTest, isolated_transaction) {
}
}
TEST_F(cta_rdbms_wrapper_SqliteStmtTest, insert_violating_primary_key) {
using namespace cta;
using namespace cta::rdbms::wrapper;
// Create a connection a memory resident database
SqliteConn conn(":memory:");
ASSERT_TRUE(conn.getTableNames().empty());
// Create a test table
{
const char *const sql =
"CREATE TABLE TEST("
"COL1 INTEGER,"
"CONSTRAINT TEST_COL1_PK PRIMARY KEY(COL1));";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
stmt->executeNonQuery();
ASSERT_EQ(1, conn.getTableNames().size());
ASSERT_EQ("TEST", conn.getTableNames().front());
}
// Insert a row into the test table
{
const char *const sql =
"INSERT INTO TEST("
"COL1)"
"VALUES("
":COL1);";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
stmt->bindUint64(":COL1", 1);
stmt->executeNonQuery();
}
// Try to insert an identical row into the test table
{
const char *const sql =
"INSERT INTO TEST("
"COL1)"
"VALUES("
":COL1);";
auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
stmt->bindUint64(":COL1", 1);
ASSERT_THROW(stmt->executeNonQuery(), exception::DatabaseConstraintViolation);
}
}
} // namespace unitTests
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment