forked from qt-creator/qt-creator
Sqlite: Improve exception handling
Introducing different exceptions for different error cases. Change-Id: I4371d1e64d9dca2a9f68dcbaa4a891c55879c1f5 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io> Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -95,19 +95,26 @@ private:
|
||||
void Statement::waitForUnlockNotify() const
|
||||
{
|
||||
UnlockNotification unlockNotification;
|
||||
int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(), UnlockNotification::unlockNotifyCallBack, &unlockNotification);
|
||||
int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(),
|
||||
UnlockNotification::unlockNotifyCallBack,
|
||||
&unlockNotification);
|
||||
|
||||
if (resultCode == SQLITE_OK)
|
||||
unlockNotification.wait();
|
||||
else
|
||||
throwException("SqliteStatement::waitForUnlockNotify: database is in a dead lock!");
|
||||
if (resultCode == SQLITE_LOCKED)
|
||||
throw DeadLock("SqliteStatement::waitForUnlockNotify: database is in a dead lock!");
|
||||
|
||||
unlockNotification.wait();
|
||||
}
|
||||
|
||||
void Statement::reset() const
|
||||
{
|
||||
int resultCode = sqlite3_reset(m_compiledStatement.get());
|
||||
if (resultCode != SQLITE_OK)
|
||||
throwException("SqliteStatement::reset: can't reset statement!");
|
||||
switch (resultCode) {
|
||||
case SQLITE_OK: return;
|
||||
case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!");
|
||||
case SQLITE_ERROR : throwStatementHasError("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!");
|
||||
case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::stepStatement: was called inappropriately!");
|
||||
case SQLITE_CONSTRAINT: throwConstraintPreventsModification("SqliteStatement::stepStatement: contraint prevent insert or update!");
|
||||
}
|
||||
|
||||
m_isReadyToFetchValues = false;
|
||||
}
|
||||
@@ -159,30 +166,30 @@ Utils::SmallStringVector Statement::columnNames() const
|
||||
|
||||
void Statement::bind(int index, int value)
|
||||
{
|
||||
int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
|
||||
if (resultCode != SQLITE_OK)
|
||||
throwException("SqliteStatement::bind: cant' bind 32 bit integer!");
|
||||
int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
|
||||
checkForBindingError(resultCode);
|
||||
}
|
||||
|
||||
void Statement::bind(int index, long long value)
|
||||
{
|
||||
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
|
||||
if (resultCode != SQLITE_OK)
|
||||
throwException("SqliteStatement::bind: cant' bind 64 bit integer!");
|
||||
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
|
||||
checkForBindingError(resultCode);
|
||||
}
|
||||
|
||||
void Statement::bind(int index, double value)
|
||||
{
|
||||
int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
|
||||
if (resultCode != SQLITE_OK)
|
||||
throwException("SqliteStatement::bind: cant' bind double!");
|
||||
checkForBindingError(resultCode);
|
||||
}
|
||||
|
||||
void Statement::bind(int index, Utils::SmallStringView text)
|
||||
{
|
||||
int resultCode = sqlite3_bind_text(m_compiledStatement.get(), index, text.data(), int(text.size()), SQLITE_TRANSIENT);
|
||||
if (resultCode != SQLITE_OK)
|
||||
throwException("SqliteStatement::bind: cant' bind double!");
|
||||
int resultCode = sqlite3_bind_text(m_compiledStatement.get(),
|
||||
index,
|
||||
text.data(),
|
||||
int(text.size()),
|
||||
SQLITE_TRANSIENT);
|
||||
checkForBindingError(resultCode);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
@@ -250,13 +257,13 @@ bool Statement::checkForStepError(int resultCode) const
|
||||
switch (resultCode) {
|
||||
case SQLITE_ROW: return true;
|
||||
case SQLITE_DONE: return false;
|
||||
case SQLITE_BUSY: throwException("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!");
|
||||
case SQLITE_ERROR : throwException("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!");
|
||||
case SQLITE_MISUSE: throwException("SqliteStatement::stepStatement: was called inappropriately!");
|
||||
case SQLITE_CONSTRAINT: throwException("SqliteStatement::stepStatement: contraint prevent insert or update!");
|
||||
case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!");
|
||||
case SQLITE_ERROR : throwStatementHasError("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!");
|
||||
case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::stepStatement: was called inappropriately!");
|
||||
case SQLITE_CONSTRAINT: throwConstraintPreventsModification("SqliteStatement::stepStatement: contraint prevent insert or update!");
|
||||
}
|
||||
|
||||
throwException("SqliteStatement::stepStatement: unknown error has happened");
|
||||
throwUnknowError("SqliteStatement::stepStatement: unknown error has happened");
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
@@ -265,12 +272,24 @@ void Statement::checkForPrepareError(int resultCode) const
|
||||
{
|
||||
switch (resultCode) {
|
||||
case SQLITE_OK: return;
|
||||
case SQLITE_BUSY: throwException("SqliteStatement::prepareStatement: database engine was unable to acquire the database locks!");
|
||||
case SQLITE_ERROR : throwException("SqliteStatement::prepareStatement: run-time error (such as a constraint violation) has occurred!");
|
||||
case SQLITE_MISUSE: throwException("SqliteStatement::prepareStatement: was called inappropriately!");
|
||||
case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::prepareStatement: database engine was unable to acquire the database locks!");
|
||||
case SQLITE_ERROR : throwStatementHasError("SqliteStatement::prepareStatement: run-time error (such as a constraint violation) has occurred!");
|
||||
case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::prepareStatement: was called inappropriately!");
|
||||
}
|
||||
|
||||
throwException("SqliteStatement::prepareStatement: unknown error has happened");
|
||||
throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened");
|
||||
}
|
||||
|
||||
void Statement::checkForBindingError(int resultCode) const
|
||||
{
|
||||
switch (resultCode) {
|
||||
case SQLITE_OK: return;
|
||||
case SQLITE_TOOBIG: throwBingingTooBig("SqliteStatement::bind: string or blob are over size limits(SQLITE_LIMIT_LENGTH)!");
|
||||
case SQLITE_RANGE : throwBindingIndexIsOutOfRange("SqliteStatement::bind: binding index is out of range!");
|
||||
case SQLITE_NOMEM: throw std::bad_alloc();
|
||||
}
|
||||
|
||||
throwUnknowError("SqliteStatement::bind: unknown error has happened");
|
||||
}
|
||||
|
||||
void Statement::setIfIsReadyToFetchValues(int resultCode) const
|
||||
@@ -285,33 +304,27 @@ void Statement::setIfIsReadyToFetchValues(int resultCode) const
|
||||
void Statement::checkIfIsReadyToFetchValues() const
|
||||
{
|
||||
if (!m_isReadyToFetchValues)
|
||||
throwException("SqliteStatement::value: there are no values to fetch!");
|
||||
throwNoValuesToFetch("SqliteStatement::value: there are no values to fetch!");
|
||||
}
|
||||
|
||||
void Statement::checkColumnsAreValid(const std::vector<int> &columns) const
|
||||
{
|
||||
for (int column : columns) {
|
||||
if (column < 0 || column >= m_columnCount)
|
||||
throwException("SqliteStatement::values: column index out of bound!");
|
||||
throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
|
||||
}
|
||||
}
|
||||
|
||||
void Statement::checkColumnIsValid(int column) const
|
||||
{
|
||||
if (column < 0 || column >= m_columnCount)
|
||||
throwException("SqliteStatement::values: column index out of bound!");
|
||||
}
|
||||
|
||||
void Statement::checkBindingIndex(int index) const
|
||||
{
|
||||
if (index <= 0 || index > m_bindingParameterCount)
|
||||
throwException("SqliteStatement::bind: binding index is out of bound!");
|
||||
throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
|
||||
}
|
||||
|
||||
void Statement::checkBindingName(int index) const
|
||||
{
|
||||
if (index <= 0 || index > m_bindingParameterCount)
|
||||
throwException("SqliteStatement::bind: binding name are not exists in this statement!");
|
||||
throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!");
|
||||
}
|
||||
|
||||
void Statement::setBindingParameterCount()
|
||||
@@ -345,9 +358,57 @@ bool Statement::isReadOnlyStatement() const
|
||||
return sqlite3_stmt_readonly(m_compiledStatement.get());
|
||||
}
|
||||
|
||||
void Statement::throwException(const char *whatHasHappened) const
|
||||
void Statement::throwStatementIsBusy(const char *whatHasHappened) const
|
||||
{
|
||||
throw Exception(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
throw StatementIsBusy(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
}
|
||||
|
||||
void Statement::throwStatementHasError(const char *whatHasHappened) const
|
||||
{
|
||||
throw StatementHasError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
}
|
||||
|
||||
void Statement::throwStatementIsMisused(const char *whatHasHappened) const
|
||||
{
|
||||
throw StatementIsMisused(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
}
|
||||
|
||||
void Statement::throwConstraintPreventsModification(const char *whatHasHappened) const
|
||||
{
|
||||
throw ContraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
}
|
||||
|
||||
void Statement::throwNoValuesToFetch(const char *whatHasHappened) const
|
||||
{
|
||||
throw NoValuesToFetch(whatHasHappened);
|
||||
}
|
||||
|
||||
void Statement::throwInvalidColumnFetched(const char *whatHasHappened) const
|
||||
{
|
||||
throw InvalidColumnFetched(whatHasHappened);
|
||||
}
|
||||
|
||||
void Statement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
|
||||
{
|
||||
throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
}
|
||||
|
||||
void Statement::throwWrongBingingName(const char *whatHasHappened) const
|
||||
{
|
||||
throw WrongBingingName(whatHasHappened);
|
||||
}
|
||||
|
||||
void Statement::throwUnknowError(const char *whatHasHappened) const
|
||||
{
|
||||
if (sqliteDatabaseHandle())
|
||||
throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
else
|
||||
throw UnknowError(whatHasHappened);
|
||||
}
|
||||
|
||||
void Statement::throwBingingTooBig(const char *whatHasHappened) const
|
||||
{
|
||||
throw BindingTooBig(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
|
||||
}
|
||||
|
||||
QString Statement::columnName(int column) const
|
||||
|
||||
Reference in New Issue
Block a user