database: Add support for serializable transactions
This commit is contained in:
@@ -115,6 +115,10 @@ struct database_t {
|
||||
/**
|
||||
* Start a transaction.
|
||||
*
|
||||
* A serializable transaction forces a strict separation between other
|
||||
* transactions. Due to the performance overhead they should only be used
|
||||
* in certain situations (e.g. SELECT->INSERT|UPDATE).
|
||||
*
|
||||
* @note Either commit() or rollback() has to be called to end the
|
||||
* transaction.
|
||||
* @note Transactions are thread-specific. So commit()/rollbak() has to be
|
||||
@@ -124,9 +128,10 @@ struct database_t {
|
||||
* not supported. So if any if the "inner" transactions are rolled back
|
||||
* the outer most transaction is rolled back.
|
||||
*
|
||||
* @return TRUE on success
|
||||
* @param serializable TRUE to create a serializable transaction
|
||||
* @return TRUE on success
|
||||
*/
|
||||
bool (*transaction)(database_t *this);
|
||||
bool (*transaction)(database_t *this, bool serializable);
|
||||
|
||||
/**
|
||||
* Commit all changes made during the current transaction.
|
||||
|
||||
@@ -652,7 +652,7 @@ METHOD(database_t, execute, int,
|
||||
}
|
||||
|
||||
METHOD(database_t, transaction, bool,
|
||||
private_mysql_database_t *this)
|
||||
private_mysql_database_t *this, bool serializable)
|
||||
{
|
||||
transaction_t *trans = NULL;
|
||||
conn_t *conn;
|
||||
@@ -669,6 +669,17 @@ METHOD(database_t, transaction, bool,
|
||||
}
|
||||
/* these statements are not supported in prepared statements that are used
|
||||
* by the execute() method */
|
||||
if (serializable)
|
||||
{
|
||||
if (mysql_query(conn->mysql,
|
||||
"SET TRANSACTION ISOLATION LEVEL SERIALIZABLE") != 0)
|
||||
{
|
||||
DBG1(DBG_LIB, "starting transaction failed: %s",
|
||||
mysql_error(conn->mysql));
|
||||
conn_release(this, conn);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (mysql_query(conn->mysql, "START TRANSACTION") != 0)
|
||||
{
|
||||
DBG1(DBG_LIB, "starting transaction failed: %s",
|
||||
|
||||
@@ -305,9 +305,11 @@ METHOD(database_t, execute, int,
|
||||
}
|
||||
|
||||
METHOD(database_t, transaction, bool,
|
||||
private_sqlite_database_t *this)
|
||||
private_sqlite_database_t *this, bool serializable)
|
||||
{
|
||||
transaction_t *trans;
|
||||
char *cmd = serializable ? "BEGIN EXCLUSIVE TRANSACTION"
|
||||
: "BEGIN TRANSACTION";
|
||||
|
||||
trans = this->transaction->get(this->transaction);
|
||||
if (trans)
|
||||
@@ -315,7 +317,7 @@ METHOD(database_t, transaction, bool,
|
||||
ref_get(&trans->refs);
|
||||
return TRUE;
|
||||
}
|
||||
if (execute(this, NULL, "BEGIN EXCLUSIVE TRANSACTION") == -1)
|
||||
if (execute(this, NULL, cmd) == -1)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user