Data/SQLite: Exception messages contain duplicate text #2012

This commit is contained in:
Alex Fabijanic 2017-11-29 19:40:21 -06:00
parent 21704830f1
commit 52cc7e669d
6 changed files with 85 additions and 57 deletions

View File

@ -30,6 +30,7 @@ extern "C"
{
typedef struct sqlite3 sqlite3;
typedef struct sqlite3_stmt sqlite3_stmt;
typedef struct sqlite3_mutex* _pMutex;
}
@ -57,13 +58,13 @@ public:
static sqlite3* dbHandle(const Session& session);
/// Returns native DB handle.
static std::string lastError(sqlite3* pDb);
static std::string lastError(sqlite3* pDB);
/// Retreives the last error code from sqlite and converts it to a string.
static std::string lastError(const Session& session);
/// Retreives the last error code from sqlite and converts it to a string.
static void throwException(int rc, const std::string& addErrMsg = std::string());
static void throwException(sqlite3* pDB, int rc, const std::string& addErrMsg = std::string());
/// Throws for an error code the appropriate exception
static MetaColumn::ColumnDataType getColumnType(sqlite3_stmt* pStmt, std::size_t pos);
@ -174,6 +175,17 @@ public:
return registerUpdateHandler(dbHandle(session), callbackFn, pParam);
}
class SQLiteMutex
{
public:
SQLiteMutex(sqlite3* pDB);
~SQLiteMutex();
private:
SQLiteMutex();
sqlite3_mutex* _pMutex;
};
private:
Utility();
/// Maps SQLite column declared types to Poco::Data types through

View File

@ -113,14 +113,14 @@ void Binder::bind(std::size_t pos, const DateTime& val, Direction dir)
void Binder::bind(std::size_t pos, const NullData&, Direction)
{
sqlite3_bind_null(_pStmt, pos);
sqlite3_bind_null(_pStmt, static_cast<int>(pos));
}
void Binder::checkReturn(int rc)
{
if (rc != SQLITE_OK)
Utility::throwException(rc);
Utility::throwException(sqlite3_db_handle(_pStmt), rc);
}

View File

@ -228,7 +228,7 @@ bool Extractor::isNull(std::size_t pos, std::size_t)
if (!_nulls[pos].first)
{
_nulls[pos].first = true;
_nulls[pos].second = (SQLITE_NULL == sqlite3_column_type(_pStmt, pos));
_nulls[pos].second = (SQLITE_NULL == sqlite3_column_type(_pStmt, static_cast<int>(pos)));
}
return _nulls[pos].second;

View File

@ -21,29 +21,29 @@ namespace Data {
namespace SQLite {
POCO_IMPLEMENT_EXCEPTION(SQLiteException, Poco::Data::DataException, "Generic SQLite error")
POCO_IMPLEMENT_EXCEPTION(InvalidSQLStatementException, SQLiteException, "SQL Statement invalid")
POCO_IMPLEMENT_EXCEPTION(InternalDBErrorException, SQLiteException, "Internal error")
POCO_IMPLEMENT_EXCEPTION(DBAccessDeniedException, SQLiteException, "Access permission denied")
POCO_IMPLEMENT_EXCEPTION(ExecutionAbortedException, SQLiteException, "Execution of SQL statement aborted")
POCO_IMPLEMENT_EXCEPTION(DBLockedException, SQLiteException, "The database is locked")
POCO_IMPLEMENT_EXCEPTION(TableLockedException, SQLiteException, "A table in the database is locked")
POCO_IMPLEMENT_EXCEPTION(SQLiteException, Poco::Data::DataException, "SQLite exception")
POCO_IMPLEMENT_EXCEPTION(InvalidSQLStatementException, SQLiteException, "Invalid SQL statement")
POCO_IMPLEMENT_EXCEPTION(InternalDBErrorException, SQLiteException, "Internal DB error")
POCO_IMPLEMENT_EXCEPTION(DBAccessDeniedException, SQLiteException, "DB access denied")
POCO_IMPLEMENT_EXCEPTION(ExecutionAbortedException, SQLiteException, "Execution aborted")
POCO_IMPLEMENT_EXCEPTION(DBLockedException, SQLiteException, "DB locked")
POCO_IMPLEMENT_EXCEPTION(TableLockedException, SQLiteException, "Table locked")
POCO_IMPLEMENT_EXCEPTION(NoMemoryException, SQLiteException, "Out of Memory")
POCO_IMPLEMENT_EXCEPTION(ReadOnlyException, SQLiteException, "Attempt to write a readonly database")
POCO_IMPLEMENT_EXCEPTION(InterruptException, SQLiteException, "Operation terminated by an interrupt")
POCO_IMPLEMENT_EXCEPTION(IOErrorException, SQLiteException, "Some kind of disk I/O error occurred")
POCO_IMPLEMENT_EXCEPTION(CorruptImageException, SQLiteException, "The database disk image is malformed")
POCO_IMPLEMENT_EXCEPTION(ReadOnlyException, SQLiteException, "Read only")
POCO_IMPLEMENT_EXCEPTION(InterruptException, SQLiteException, "Interrupt")
POCO_IMPLEMENT_EXCEPTION(IOErrorException, SQLiteException, "I/O error")
POCO_IMPLEMENT_EXCEPTION(CorruptImageException, SQLiteException, "Corrupt image")
POCO_IMPLEMENT_EXCEPTION(TableNotFoundException, SQLiteException, "Table not found")
POCO_IMPLEMENT_EXCEPTION(DatabaseFullException, SQLiteException, "Insertion failed because database is full")
POCO_IMPLEMENT_EXCEPTION(CantOpenDBFileException, SQLiteException, "Unable to open the database file")
POCO_IMPLEMENT_EXCEPTION(LockProtocolException, SQLiteException, "Database lock protocol error")
POCO_IMPLEMENT_EXCEPTION(SchemaDiffersException, SQLiteException, "The database schema changed")
POCO_IMPLEMENT_EXCEPTION(RowTooBigException, SQLiteException, "Too much data for one row of a table")
POCO_IMPLEMENT_EXCEPTION(ConstraintViolationException, SQLiteException, "Abort due to constraint violation")
POCO_IMPLEMENT_EXCEPTION(DatabaseFullException, SQLiteException, "Database full")
POCO_IMPLEMENT_EXCEPTION(CantOpenDBFileException, SQLiteException, "Can't open DB file")
POCO_IMPLEMENT_EXCEPTION(LockProtocolException, SQLiteException, "Lock protocol")
POCO_IMPLEMENT_EXCEPTION(SchemaDiffersException, SQLiteException, "Schema differs")
POCO_IMPLEMENT_EXCEPTION(RowTooBigException, SQLiteException, "Row too big")
POCO_IMPLEMENT_EXCEPTION(ConstraintViolationException, SQLiteException, "Constraint violation")
POCO_IMPLEMENT_EXCEPTION(DataTypeMismatchException, SQLiteException, "Data type mismatch")
POCO_IMPLEMENT_EXCEPTION(ParameterCountMismatchException, SQLiteException, "Parameter count mismatch")
POCO_IMPLEMENT_EXCEPTION(InvalidLibraryUseException, SQLiteException, "Library used incorrectly")
POCO_IMPLEMENT_EXCEPTION(OSFeaturesMissingException, SQLiteException, "Uses OS features not supported on host")
POCO_IMPLEMENT_EXCEPTION(InvalidLibraryUseException, SQLiteException, "Invalid library use")
POCO_IMPLEMENT_EXCEPTION(OSFeaturesMissingException, SQLiteException, "OS features missing")
POCO_IMPLEMENT_EXCEPTION(AuthorizationDeniedException, SQLiteException, "Authorization denied")
POCO_IMPLEMENT_EXCEPTION(TransactionException, SQLiteException, "Transaction exception")

View File

@ -182,14 +182,14 @@ void SessionImpl::open(const std::string& connect)
{
ActiveConnector connector(connectionString(), &_pDB);
ActiveResult<int> result = connector.connect();
if (!result.tryWait(getLoginTimeout() * 1000))
if (!result.tryWait(static_cast<long>(getLoginTimeout() * 1000)))
throw ConnectionFailedException("Timed out.");
int rc = result.data();
if (rc != 0)
{
close();
Utility::throwException(rc);
Utility::throwException(_pDB, rc);
}
}
catch (SQLiteException& ex)
@ -221,9 +221,9 @@ bool SessionImpl::isConnected()
void SessionImpl::setConnectionTimeout(std::size_t timeout)
{
int tout = 1000 * timeout;
int tout = static_cast<int>(1000 * timeout);
int rc = sqlite3_busy_timeout(_pDB, tout);
if (rc != 0) Utility::throwException(rc);
if (rc != 0) Utility::throwException(_pDB, rc);
_timeout = tout;
}

View File

@ -59,6 +59,18 @@ Utility::TypeMap Utility::_types;
Poco::Mutex Utility::_mutex;
Utility::SQLiteMutex::SQLiteMutex(sqlite3* pDB): _pMutex(sqlite3_db_mutex(pDB))
{
sqlite3_mutex_enter(_pMutex);
}
Utility::SQLiteMutex::~SQLiteMutex()
{
sqlite3_mutex_leave(_pMutex);
}
Utility::Utility()
{
if (_types.empty())
@ -125,7 +137,11 @@ Utility::Utility()
std::string Utility::lastError(sqlite3* pDB)
{
return std::string(sqlite3_errmsg(pDB));
std::string errStr;
SQLiteMutex m(pDB);
const char* pErr = sqlite3_errmsg(pDB);
if (pErr) errStr = pErr;
return errStr;
}
@ -151,74 +167,74 @@ MetaColumn::ColumnDataType Utility::getColumnType(sqlite3_stmt* pStmt, std::size
}
void Utility::throwException(int rc, const std::string& addErrMsg)
void Utility::throwException(sqlite3* pDB, int rc, const std::string& addErrMsg)
{
switch (rc)
{
case SQLITE_OK:
break;
case SQLITE_ERROR:
throw InvalidSQLStatementException(std::string("SQL error or missing database"), addErrMsg);
throw InvalidSQLStatementException(lastError(pDB), addErrMsg);
case SQLITE_INTERNAL:
throw InternalDBErrorException(std::string("An internal logic error in SQLite"), addErrMsg);
throw InternalDBErrorException(lastError(pDB), addErrMsg);
case SQLITE_PERM:
throw DBAccessDeniedException(std::string("Access permission denied"), addErrMsg);
throw DBAccessDeniedException(lastError(pDB), addErrMsg);
case SQLITE_ABORT:
throw ExecutionAbortedException(std::string("Callback routine requested an abort"), addErrMsg);
throw ExecutionAbortedException(lastError(pDB), addErrMsg);
case SQLITE_BUSY:
case SQLITE_BUSY_RECOVERY:
#if defined(SQLITE_BUSY_SNAPSHOT)
case SQLITE_BUSY_SNAPSHOT:
#endif
throw DBLockedException(std::string("The database file is locked"), addErrMsg);
throw DBLockedException(lastError(pDB), addErrMsg);
case SQLITE_LOCKED:
throw TableLockedException(std::string("A table in the database is locked"), addErrMsg);
throw TableLockedException(lastError(pDB), addErrMsg);
case SQLITE_NOMEM:
throw NoMemoryException(std::string("A malloc() failed"), addErrMsg);
throw NoMemoryException(lastError(pDB), addErrMsg);
case SQLITE_READONLY:
throw ReadOnlyException(std::string("Attempt to write a readonly database"), addErrMsg);
throw ReadOnlyException(lastError(pDB), addErrMsg);
case SQLITE_INTERRUPT:
throw InterruptException(std::string("Operation terminated by sqlite_interrupt()"), addErrMsg);
throw InterruptException(lastError(pDB), addErrMsg);
case SQLITE_IOERR:
throw IOErrorException(std::string("Some kind of disk I/O error occurred"), addErrMsg);
throw IOErrorException(lastError(pDB), addErrMsg);
case SQLITE_CORRUPT:
throw CorruptImageException(std::string("The database disk image is malformed"), addErrMsg);
throw CorruptImageException(lastError(pDB), addErrMsg);
case SQLITE_NOTFOUND:
throw TableNotFoundException(std::string("Table or record not found"), addErrMsg);
throw TableNotFoundException(lastError(pDB), addErrMsg);
case SQLITE_FULL:
throw DatabaseFullException(std::string("Insertion failed because database is full"), addErrMsg);
throw DatabaseFullException(lastError(pDB), addErrMsg);
case SQLITE_CANTOPEN:
throw CantOpenDBFileException(std::string("Unable to open the database file"), addErrMsg);
throw CantOpenDBFileException(lastError(pDB), addErrMsg);
case SQLITE_PROTOCOL:
throw LockProtocolException(std::string("Database lock protocol error"), addErrMsg);
throw LockProtocolException(lastError(pDB), addErrMsg);
case SQLITE_EMPTY:
throw InternalDBErrorException(std::string("(Internal Only) Database table is empty"), addErrMsg);
throw InternalDBErrorException(lastError(pDB), addErrMsg);
case SQLITE_SCHEMA:
throw SchemaDiffersException(std::string("The database schema changed"), addErrMsg);
throw SchemaDiffersException(lastError(pDB), addErrMsg);
case SQLITE_TOOBIG:
throw RowTooBigException(std::string("Too much data for one row of a table"), addErrMsg);
throw RowTooBigException(lastError(pDB), addErrMsg);
case SQLITE_CONSTRAINT:
throw ConstraintViolationException(std::string("Abort due to constraint violation"), addErrMsg);
throw ConstraintViolationException(lastError(pDB), addErrMsg);
case SQLITE_MISMATCH:
throw DataTypeMismatchException(std::string("Data type mismatch"), addErrMsg);
throw DataTypeMismatchException(lastError(pDB), addErrMsg);
case SQLITE_MISUSE:
throw InvalidLibraryUseException(std::string("Library used incorrectly"), addErrMsg);
throw InvalidLibraryUseException(lastError(pDB), addErrMsg);
case SQLITE_NOLFS:
throw OSFeaturesMissingException(std::string("Uses OS features not supported on host"), addErrMsg);
throw OSFeaturesMissingException(lastError(pDB), addErrMsg);
case SQLITE_AUTH:
throw AuthorizationDeniedException(std::string("Authorization denied"), addErrMsg);
throw AuthorizationDeniedException(lastError(pDB), addErrMsg);
case SQLITE_FORMAT:
throw CorruptImageException(std::string("Auxiliary database format error"), addErrMsg);
throw CorruptImageException(lastError(pDB), addErrMsg);
case SQLITE_NOTADB:
throw CorruptImageException(std::string("File opened that is not a database file"), addErrMsg);
throw CorruptImageException(lastError(pDB), addErrMsg);
case SQLITE_RANGE:
throw InvalidSQLStatementException(std::string("Bind Parameter out of range (Access of invalid position 0? bind starts with 1!)"), addErrMsg);
throw InvalidSQLStatementException(lastError(pDB), addErrMsg);
case SQLITE_ROW:
break; // sqlite_step() has another row ready
case SQLITE_DONE:
break; // sqlite_step() has finished executing
default:
throw SQLiteException(std::string("Unknown error code: ") + Poco::NumberFormatter::format(rc), addErrMsg);
throw SQLiteException(Poco::format("Unknown error code: %d", rc), addErrMsg);
}
}