# HG changeset patch # User František Kučera # Date 1591221817 -7200 # Node ID 85e6dc1853ee3d0ec8c6a63a5ad6c42fed95f18d # Parent 225e294ad1dbf1d776f3dfeeae49688cf1806b96 transaction control: disable auto-commit, run all statements in a single transaction, do rollback on exception diff -r 225e294ad1db -r 85e6dc1853ee src/Connection.cpp --- a/src/Connection.cpp Wed Jun 03 17:22:22 2020 +0200 +++ b/src/Connection.cpp Thu Jun 04 00:03:37 2020 +0200 @@ -29,12 +29,16 @@ namespace sql { Connection::Connection(void* db) : connection(db) { - // TODO: transaction control + setAutoCommit(false); } Connection::~Connection() { + // If an exception was thrown somewhere, there might be a transaction in progress, so we will cancel this transaction. + // If there was no exception, commit() has already been called and this rollback() will not affect any (desired) transaction. + // Without this rollback(), SQLDisconnect() will fail and then will fail also freeHandle() which will throw exception. + // And throwing exception while throwing exception will lead to a catastrophic failure: SIGABRT, core dump. + rollback(); SQLRETURN result = SQLDisconnect(connection); - // TODO: log warning if disconnection failed? OdbcCommon::freeHandle(SQL_HANDLE_DBC, connection); } @@ -46,12 +50,18 @@ } bool Connection::getAutoCommit() { - // TODO: transaction control - return false; + SQLULEN autoCommit = SQL_AUTOCOMMIT_DEFAULT; + SQLRETURN result = SQLGetConnectOption(connection, SQL_AUTOCOMMIT, &autoCommit); + if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to get auto-commit status", result, SQL_HANDLE_DBC, connection); + + if (autoCommit == SQL_AUTOCOMMIT_ON) return true; + else if (autoCommit == SQL_AUTOCOMMIT_OFF) return false; + else throw SqlException(L"Unexpected value of auto-commit status"); } void Connection::setAutoCommit(bool autoCommit) { - // TODO: transaction control + SQLRETURN result = SQLSetConnectOption(connection, SQL_AUTOCOMMIT, autoCommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF); + if (OdbcCommon::isNotSuccessful(result)) throw SqlException(std::wstring(L"Unable to set auto-commit to ") + (autoCommit ? L"enabled" : L"disabled"), result, SQL_HANDLE_DBC, connection); } void Connection::commit() {