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

Added unit-test insert_same_primary_twice

parent b22d8865
...@@ -84,6 +84,7 @@ set (COMMON_LIB_SRC_FILES ...@@ -84,6 +84,7 @@ set (COMMON_LIB_SRC_FILES
exception/DatabaseCheckConstraintError.cpp exception/DatabaseCheckConstraintError.cpp
exception/DatabaseConstraintError.cpp exception/DatabaseConstraintError.cpp
exception/DatabasePrimaryKeyError.cpp exception/DatabasePrimaryKeyError.cpp
exception/DatabaseUniqueError.cpp
exception/DismountFailed.cpp exception/DismountFailed.cpp
exception/ForceDismountFailed.cpp exception/ForceDismountFailed.cpp
exception/Errnum.cpp exception/Errnum.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/DatabaseUniqueError.hpp"
namespace cta {
namespace exception {
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
DatabaseUniqueError::DatabaseUniqueError(const std::string &context, const bool embedBacktrace):
DatabaseConstraintError(context, embedBacktrace) {
}
//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
DatabaseUniqueError::~DatabaseUniqueError() 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/DatabaseConstraintError.hpp"
#include <string>
namespace cta {
namespace exception {
/**
* A database constraint has been violated.
*/
class DatabaseUniqueError : public DatabaseConstraintError {
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
*/
DatabaseUniqueError(const std::string &context = "", const bool embedBacktrace = true);
/**
* Empty Destructor, explicitely non-throwing (needed for std::exception
* inheritance)
*/
~DatabaseUniqueError() noexcept override;
}; // class DatabaseUniqueError
} // namespace exception
} // namespace cta
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "common/exception/DatabaseCheckConstraintError.hpp" #include "common/exception/DatabaseCheckConstraintError.hpp"
#include "common/exception/DatabasePrimaryKeyError.hpp" #include "common/exception/DatabasePrimaryKeyError.hpp"
#include "common/exception/DatabaseUniqueError.hpp"
#include "common/exception/Exception.hpp" #include "common/exception/Exception.hpp"
#include "common/make_unique.hpp" #include "common/make_unique.hpp"
#include "common/utils/utils.hpp" #include "common/utils/utils.hpp"
...@@ -62,12 +63,14 @@ std::string cta_rdbms_StmtTest::getCreateStmtTestTableSql() { ...@@ -62,12 +63,14 @@ std::string cta_rdbms_StmtTest::getCreateStmtTestTableSql() {
try { try {
std::string sql = std::string sql =
"CREATE TABLE STMT_TEST(" "\n" "CREATE TABLE STMT_TEST(" "\n"
" DOUBLE_COL FLOAT," "\n" " ID UINT64TYPE CONSTRAINT STMT_TEST_ID_NN NOT NULL," "\n"
" UINT64_COL UINT64TYPE," "\n" " DOUBLE_COL FLOAT," "\n"
" STRING_COL VARCHAR(100)," "\n" " UINT64_COL UINT64TYPE," "\n"
" BOOL_COL CHAR(1) DEFAULT '0'," "\n" " STRING_COL VARCHAR(100)," "\n"
" CONSTRAINT BOOL_COL_BOOL_CK CHECK(BOOL_COL IN ('0', '1'))" "\n" " BOOL_COL CHAR(1) DEFAULT '0'," "\n"
" CONSTRAINT STMT_TEST_PK PRIMARY KEY(ID)," "\n"
" CONSTRAINT BOOL_COL_BOOL_CK CHECK(BOOL_COL IN ('0', '1'))" "\n"
")"; ")";
switch(m_login.dbType) { switch(m_login.dbType) {
...@@ -127,10 +130,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindDouble) { ...@@ -127,10 +130,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindDouble) {
// Insert a row into the test table // Insert a row into the test table
{ {
const char *const sql = const char *const sql =
"INSERT INTO STMT_TEST(" "INSERT INTO STMT_TEST(" "\n"
"DOUBLE_COL) " " ID," "\n"
"VALUES(" " DOUBLE_COL)" "\n"
":DOUBLE_COL)"; "VALUES(" "\n"
" 1," "\n"
" :DOUBLE_COL)";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
stmt.bindDouble(":DOUBLE_COL", insertValue); stmt.bindDouble(":DOUBLE_COL", insertValue);
stmt.executeNonQuery(); stmt.executeNonQuery();
...@@ -139,10 +144,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindDouble) { ...@@ -139,10 +144,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindDouble) {
// Select the row back from the table // Select the row back from the table
{ {
const char *const sql = const char *const sql =
"SELECT " "SELECT" "\n"
"DOUBLE_COL AS DOUBLE_COL " " DOUBLE_COL AS DOUBLE_COL" "\n"
"FROM " "FROM" "\n"
"STMT_TEST"; " STMT_TEST";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
auto rset = stmt.executeQuery(); auto rset = stmt.executeQuery();
ASSERT_TRUE(rset.next()); ASSERT_TRUE(rset.next());
...@@ -166,10 +171,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64) { ...@@ -166,10 +171,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64) {
// Insert a row into the test table // Insert a row into the test table
{ {
const char *const sql = const char *const sql =
"INSERT INTO STMT_TEST(" "INSERT INTO STMT_TEST(" "\n"
"UINT64_COL) " " ID," "\n"
"VALUES(" " UINT64_COL) " "\n"
":UINT64_COL)"; "VALUES(" "\n"
" 1," "\n"
" :UINT64_COL)";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
stmt.bindDouble(":UINT64_COL", insertValue); stmt.bindDouble(":UINT64_COL", insertValue);
stmt.executeNonQuery(); stmt.executeNonQuery();
...@@ -178,10 +185,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64) { ...@@ -178,10 +185,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64) {
// Select the row back from the table // Select the row back from the table
{ {
const char *const sql = const char *const sql =
"SELECT " "SELECT" "\n"
"UINT64_COL AS UINT64_COL " " UINT64_COL AS UINT64_COL" "\n"
"FROM " "FROM" "\n"
"STMT_TEST"; " STMT_TEST";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
auto rset = stmt.executeQuery(); auto rset = stmt.executeQuery();
ASSERT_TRUE(rset.next()); ASSERT_TRUE(rset.next());
...@@ -204,10 +211,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_1) { ...@@ -204,10 +211,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_1) {
// Insert a row into the test table // Insert a row into the test table
{ {
const char *const sql = const char *const sql =
"INSERT INTO STMT_TEST(" "INSERT INTO STMT_TEST(" "\n"
"UINT64_COL) " " ID," "\n"
"VALUES(" " UINT64_COL)" "\n"
":UINT64_COL)"; "VALUES(" "\n"
" 1," "\n"
" :UINT64_COL)";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
stmt.bindUint64(":UINT64_COL", insertValue); stmt.bindUint64(":UINT64_COL", insertValue);
stmt.executeNonQuery(); stmt.executeNonQuery();
...@@ -216,10 +225,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_1) { ...@@ -216,10 +225,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_1) {
// Select the row back from the table // Select the row back from the table
{ {
const char *const sql = const char *const sql =
"SELECT " "SELECT" "\n"
"UINT64_COL AS UINT64_COL " " UINT64_COL AS UINT64_COL" "\n"
"FROM " "FROM" "\n"
"STMT_TEST"; " STMT_TEST";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
auto rset = stmt.executeQuery(); auto rset = stmt.executeQuery();
ASSERT_TRUE(rset.next()); ASSERT_TRUE(rset.next());
...@@ -242,10 +251,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_2) { ...@@ -242,10 +251,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_2) {
// Insert a row into the test table // Insert a row into the test table
{ {
const char *const sql = const char *const sql =
"INSERT INTO STMT_TEST(" "INSERT INTO STMT_TEST(" "\n"
"UINT64_COL) " " ID," "\n"
"VALUES(" " UINT64_COL)" "\n"
":UINT64_COL)"; "VALUES(" "\n"
" 1," "\n"
" :UINT64_COL)";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
stmt.bindUint64(":UINT64_COL", insertValue); stmt.bindUint64(":UINT64_COL", insertValue);
stmt.executeNonQuery(); stmt.executeNonQuery();
...@@ -254,10 +265,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_2) { ...@@ -254,10 +265,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindUint64_2_pow_64_minus_2) {
// Select the row back from the table // Select the row back from the table
{ {
const char *const sql = const char *const sql =
"SELECT " "SELECT" "\n"
"UINT64_COL AS UINT64_COL " " UINT64_COL AS UINT64_COL" "\n"
"FROM " "FROM" "\n"
"STMT_TEST"; " STMT_TEST";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
auto rset = stmt.executeQuery(); auto rset = stmt.executeQuery();
ASSERT_TRUE(rset.next()); ASSERT_TRUE(rset.next());
...@@ -280,10 +291,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindString) { ...@@ -280,10 +291,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindString) {
// Insert a row into the test table // Insert a row into the test table
{ {
const char *const sql = const char *const sql =
"INSERT INTO STMT_TEST(" "INSERT INTO STMT_TEST(" "\n"
"STRING_COL) " " ID," "\n"
"VALUES(" " STRING_COL)" "\n"
":STRING_COL)"; "VALUES(" "\n"
" 1," "\n"
" :STRING_COL)";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
stmt.bindString(":STRING_COL", insertValue); stmt.bindString(":STRING_COL", insertValue);
stmt.executeNonQuery(); stmt.executeNonQuery();
...@@ -292,10 +305,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindString) { ...@@ -292,10 +305,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindString) {
// Select the row back from the table // Select the row back from the table
{ {
const char *const sql = const char *const sql =
"SELECT " "SELECT" "\n"
"STRING_COL AS STRING_COL " " STRING_COL AS STRING_COL" "\n"
"FROM " "FROM" "\n"
"STMT_TEST"; " STMT_TEST";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
auto rset = stmt.executeQuery(); auto rset = stmt.executeQuery();
ASSERT_TRUE(rset.next()); ASSERT_TRUE(rset.next());
...@@ -318,10 +331,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindBool_true) { ...@@ -318,10 +331,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindBool_true) {
// Insert a row into the test table // Insert a row into the test table
{ {
const char *const sql = const char *const sql =
"INSERT INTO STMT_TEST(" "INSERT INTO STMT_TEST(" "\n"
"BOOL_COL) " " ID," "\n"
"VALUES(" " BOOL_COL)" "\n"
":BOOL_COL)"; "VALUES(" "\n"
" 1," "\n"
" :BOOL_COL)";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
stmt.bindBool(":BOOL_COL", insertValue); stmt.bindBool(":BOOL_COL", insertValue);
stmt.executeNonQuery(); stmt.executeNonQuery();
...@@ -330,10 +345,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindBool_true) { ...@@ -330,10 +345,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindBool_true) {
// Select the row back from the table // Select the row back from the table
{ {
const char *const sql = const char *const sql =
"SELECT " "SELECT" "\n"
"BOOL_COL AS BOOL_COL " " BOOL_COL AS BOOL_COL" "\n"
"FROM " "FROM" "\n"
"STMT_TEST"; " STMT_TEST";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
auto rset = stmt.executeQuery(); auto rset = stmt.executeQuery();
ASSERT_TRUE(rset.next()); ASSERT_TRUE(rset.next());
...@@ -356,10 +371,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindBool_false) { ...@@ -356,10 +371,12 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindBool_false) {
// Insert a row into the test table // Insert a row into the test table
{ {
const char *const sql = const char *const sql =
"INSERT INTO STMT_TEST(" "INSERT INTO STMT_TEST(" "\n"
"BOOL_COL) " " ID," "\n"
"VALUES(" " BOOL_COL)" "\n"
":BOOL_COL)"; "VALUES(" "\n"
" 1," "\n"
" :BOOL_COL)";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
stmt.bindBool(":BOOL_COL", insertValue); stmt.bindBool(":BOOL_COL", insertValue);
stmt.executeNonQuery(); stmt.executeNonQuery();
...@@ -368,10 +385,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindBool_false) { ...@@ -368,10 +385,10 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindBool_false) {
// Select the row back from the table // Select the row back from the table
{ {
const char *const sql = const char *const sql =
"SELECT " "SELECT" "\n"
"BOOL_COL AS BOOL_COL " " BOOL_COL AS BOOL_COL" "\n"
"FROM " "FROM" "\n"
"STMT_TEST"; " STMT_TEST";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
auto rset = stmt.executeQuery(); auto rset = stmt.executeQuery();
ASSERT_TRUE(rset.next()); ASSERT_TRUE(rset.next());
...@@ -394,9 +411,11 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindString_invalid_bool_value) { ...@@ -394,9 +411,11 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindString_invalid_bool_value) {
// Insert a row into the test table // Insert a row into the test table
{ {
const char *const sql = const char *const sql =
"INSERT INTO STMT_TEST(" "INSERT INTO STMT_TEST(" "\n"
"BOOL_COL) " " ID," "\n"
"VALUES(" "BOOL_COL)" "\n"
"VALUES(" "\n"
" 1," "\n"
":BOOL_COL)"; ":BOOL_COL)";
auto stmt = m_conn.createStmt(sql); auto stmt = m_conn.createStmt(sql);
stmt.bindString(":BOOL_COL", insertValue); stmt.bindString(":BOOL_COL", insertValue);
...@@ -405,4 +424,62 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindString_invalid_bool_value) { ...@@ -405,4 +424,62 @@ TEST_P(cta_rdbms_StmtTest, insert_with_bindString_invalid_bool_value) {
} }
} }
TEST_P(cta_rdbms_StmtTest, insert_same_primary_twice) {
using namespace cta::rdbms;
const uint64_t insertValue = 1234;
// Insert an ID into the test table
{
const char *const sql =
"INSERT INTO STMT_TEST(" "\n"
" ID)" "\n"
"VALUES(" "\n"
" :ID)";
auto stmt = m_conn.createStmt(sql);
stmt.bindUint64(":ID", insertValue);
stmt.executeNonQuery();
}
// Select the ID back from the table
{
const char *const sql =
"SELECT" "\n"
" ID AS ID" "\n"
"FROM" "\n"
" STMT_TEST";
auto stmt = m_conn.createStmt(sql);
auto rset = stmt.executeQuery();
ASSERT_TRUE(rset.next());
const auto selectValue = rset.columnOptionalDouble("ID");
ASSERT_TRUE((bool)selectValue);
ASSERT_EQ(insertValue,selectValue.value());
ASSERT_FALSE(rset.next());
}
// Attempt to insert the same ID again
{
const char *const sql =
"INSERT INTO STMT_TEST(" "\n"
" ID) " "\n"
"VALUES(" "\n"
" :ID)";
auto stmt = m_conn.createStmt(sql);
stmt.bindUint64(":ID", insertValue);
switch(m_login.dbType) {
case Login::DBTYPE_IN_MEMORY:
case Login::DBTYPE_ORACLE:
case Login::DBTYPE_POSTGRESQL:
ASSERT_THROW(stmt.executeNonQuery(), cta::exception::DatabaseUniqueError);
break;
default:
ASSERT_THROW(stmt.executeNonQuery(), cta::exception::DatabasePrimaryKeyError);
}
}
}
} // namespace unitTests } // namespace unitTests
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
*/ */
#include "common/exception/DatabaseCheckConstraintError.hpp" #include "common/exception/DatabaseCheckConstraintError.hpp"
#include "common/exception/DatabasePrimaryKeyError.hpp"
#include "common/exception/DatabaseUniqueError.hpp"
#include "common/exception/Exception.hpp" #include "common/exception/Exception.hpp"
#include "common/exception/LostDatabaseConnection.hpp" #include "common/exception/LostDatabaseConnection.hpp"
#include "common/make_unique.hpp" #include "common/make_unique.hpp"
...@@ -27,6 +29,7 @@ ...@@ -27,6 +29,7 @@
#include "rdbms/wrapper/OcciStmt.hpp" #include "rdbms/wrapper/OcciStmt.hpp"
#include <cstring> #include <cstring>
#include <iostream>
#include <map> #include <map>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
...@@ -268,9 +271,13 @@ void OcciStmt::executeNonQuery() { ...@@ -268,9 +271,13 @@ void OcciStmt::executeNonQuery() {
} }
throw exception::LostDatabaseConnection(msg.str()); throw exception::LostDatabaseConnection(msg.str());
} }
if(2290 == ex.getErrorCode()) {
switch(ex.getErrorCode()) {
case 1:
throw exception::DatabaseUniqueError(msg.str());
case 2290:
throw exception::DatabaseCheckConstraintError(msg.str()); throw exception::DatabaseCheckConstraintError(msg.str());
} else { default:
throw exception::Exception(msg.str()); throw exception::Exception(msg.str());
} }
} }
......
...@@ -19,11 +19,13 @@ ...@@ -19,11 +19,13 @@
#pragma once #pragma once
#include "common/exception/DatabaseCheckConstraintError.hpp" #include "common/exception/DatabaseCheckConstraintError.hpp"
#include "common/exception/DatabaseUniqueError.hpp"
#include "common/exception/Exception.hpp" #include "common/exception/Exception.hpp"
#include "common/exception/LostDatabaseConnection.hpp" #include "common/exception/LostDatabaseConnection.hpp"
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <iostream>
#include <libpq-fe.h> #include <libpq-fe.h>
#include <string> #include <string>
...@@ -50,11 +52,13 @@ public: ...@@ -50,11 +52,13 @@ public:
pgstr.erase(std::remove(pgstr.begin(), pgstr.end(), '\n'), pgstr.end()); pgstr.erase(std::remove(pgstr.begin(), pgstr.end(), '\n'), pgstr.end());
} }
std::string resstr; std::string resstr;
bool uniqueViolation = false;
bool checkViolation = false; bool checkViolation = false;
if (nullptr != res) { if (nullptr != res) {
resstr = "DB Result Status:" + std::to_string(PQresultStatus(res)); resstr = "DB Result Status:" + std::to_string(PQresultStatus(res));
const char *const e = PQresultErrorField(res, PG_DIAG_SQLSTATE); const char *const e = PQresultErrorField(res, PG_DIAG_SQLSTATE);
if (nullptr != e && '\0' != *e) { if (nullptr != e && '\0' != *e) {
uniqueViolation = 0 == std::strcmp("23505", e);
checkViolation = 0 == std::strcmp("23514", e); checkViolation = 0 == std::strcmp("23514", e);
resstr += " SQLState:" + std::string(e); resstr += " SQLState:" + std::string(e);
} }
...@@ -90,6 +94,9 @@ public: ...@@ -90,6 +94,9 @@ public:
if (badconn) { if (badconn) {
throw exception::LostDatabaseConnection(dbmsg); throw exception::LostDatabaseConnection(dbmsg);
} }
if (uniqueViolation) {
throw exception::DatabaseUniqueError(dbmsg);
}
if (checkViolation) { if (checkViolation) {
throw exception::DatabaseCheckConstraintError(dbmsg); throw exception::DatabaseCheckConstraintError(dbmsg);
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "common/exception/DatabaseCheckConstraintError.hpp" #include "common/exception/DatabaseCheckConstraintError.hpp"
#include "common/exception/DatabaseConstraintError.hpp" #include "common/exception/DatabaseConstraintError.hpp"
#include "common/exception/DatabasePrimaryKeyError.hpp" #include "common/exception/DatabasePrimaryKeyError.hpp"
#include "common/exception/DatabaseUniqueError.hpp"
#include "common/exception/Exception.hpp" #include "common/exception/Exception.hpp"
#include "common/make_unique.hpp" #include "common/make_unique.hpp"
#include "common/threading/MutexLocker.hpp" #include "common/threading/MutexLocker.hpp"
...@@ -286,12 +287,14 @@ void SqliteStmt::executeNonQuery() { ...@@ -286,12 +287,14 @@ void SqliteStmt::executeNonQuery() {
msg << __FUNCTION__ << " failed for SQL statement " << getSqlForException() + ": " << Sqlite::rcToStr(stepRc);