# HG changeset patch # User nrich@ii.net # Date 1228293880 0 # Node ID 10c8c6f0da14bc22d7d8b166b1d551f9a3bb70bd # Parent 014ba3ab3903e2903a19a9d88c92b11fb2db85bc Added connection:autocommit(), connection:commit(), and connection:rollback() to control transactions. diff -r 014ba3ab3903 -r 10c8c6f0da14 dbd/mysql/connection.c --- a/dbd/mysql/connection.c Tue Dec 02 21:11:27 2008 +0000 +++ b/dbd/mysql/connection.c Wed Dec 03 08:44:40 2008 +0000 @@ -48,6 +48,11 @@ return 2; } + /* + * by default turn off autocommit + */ + mysql_autocommit(conn->mysql, 0); + luaL_getmetatable(L, DBD_MYSQL_CONNECTION); lua_setmetatable(L, -2); @@ -55,6 +60,22 @@ } /* + * success = connection:autocommit(on) + */ +static int connection_autocommit(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION); + int on = lua_toboolean(L, 2); + int err = 0; + + if (conn->mysql) { + err = mysql_autocommit(conn->mysql, on); + } + + lua_pushboolean(L, !err); + return 1; +} + +/* * success = connection:close() */ static int connection_close(lua_State *L) { @@ -71,6 +92,21 @@ return 1; } +/* + * success = connection:commit() + */ +static int connection_commit(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION); + int err = 0; + + if (conn->mysql) { + err = mysql_commit(conn->mysql); + } + + lua_pushboolean(L, !err); + return 1; +} + /* * ok = connection:ping() */ @@ -103,6 +139,21 @@ } /* + * success = connection:rollback() + */ +static int connection_rollback(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION); + int err = 0; + + if (conn->mysql) { + err = mysql_rollback(conn->mysql); + } + + lua_pushboolean(L, !err); + return 1; +} + +/* * __gc */ static int connection_gc(lua_State *L) { @@ -114,9 +165,12 @@ int dbd_mysql_connection(lua_State *L) { static const luaL_Reg connection_methods[] = { + {"autocommit", connection_autocommit}, {"close", connection_close}, + {"commit", connection_commit}, {"ping", connection_ping}, {"prepare", connection_prepare}, + {"rollback", connection_rollback}, {NULL, NULL} }; diff -r 014ba3ab3903 -r 10c8c6f0da14 dbd/postgresql/connection.c --- a/dbd/postgresql/connection.c Tue Dec 02 21:11:27 2008 +0000 +++ b/dbd/postgresql/connection.c Wed Dec 03 08:44:40 2008 +0000 @@ -2,6 +2,37 @@ int dbd_postgresql_statement_create(lua_State *L, connection_t *conn, const char *sql_query); +static int run(connection_t *conn, const char *command) { + PGresult *result = PQexec(conn->postgresql, command); + ExecStatusType status; + + if (!result) + return 1; + + status = PQresultStatus(result); + PQclear(result); + + if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) + return 1; + + return 0; +} + +static int commit(connection_t *conn) { + return run(conn, "COMMIT"); +} + + +static int begin(connection_t *conn) { + return run(conn, "BEGIN"); +} + + +static int rollback(connection_t *conn) { + return run(conn, "ROLLBACK"); +} + + /* * connection = DBD.PostgreSQL.New(dbname, user, password, host, port) */ @@ -52,6 +83,8 @@ conn->postgresql = PQsetdbLogin(host, port, options, tty, db, user, password); conn->statement_id = 0; + conn->autocommit = 0; + begin(conn); if (PQstatus(conn->postgresql) != CONNECTION_OK) { lua_pushnil(L); @@ -66,6 +99,27 @@ } /* + * success = connection:autocommit(on) + */ +static int connection_autocommit(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_CONNECTION); + int on = lua_toboolean(L, 2); + int err = 0; + + if (conn->postgresql) { + if (on) + err = rollback(conn); + else + err = begin(conn); + + conn->autocommit = on; + } + + lua_pushboolean(L, !err); + return 1; +} + +/* * success = connection:close() */ static int connection_close(lua_State *L) { @@ -73,6 +127,13 @@ int disconnect = 0; if (conn->postgresql) { + /* + * if autocommit is turned off, we probably + * want to rollback any outstanding transactions. + */ + if (!conn->autocommit) + rollback(conn); + PQfinish(conn->postgresql); disconnect = 1; conn->postgresql = NULL; @@ -83,6 +144,26 @@ } /* + * success = connection:commit() + */ +static int connection_commit(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_CONNECTION); + int err = 0; + + if (conn->postgresql) { + commit(conn); + + if (!conn->autocommit) + err = begin(conn); + else + err = 1; + } + + lua_pushboolean(L, !err); + return 1; +} + +/* * ok = connection:ping() */ static int connection_ping(lua_State *L) { @@ -116,6 +197,26 @@ } /* + * success = connection:rollback() + */ +static int connection_rollback(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_CONNECTION); + int err = 0; + + if (conn->postgresql) { + rollback(conn); + + if (!conn->autocommit) + err = begin(conn); + else + err = 1; + } + + lua_pushboolean(L, !err); + return 1; +} + +/* * __gc */ static int connection_gc(lua_State *L) { @@ -127,9 +228,12 @@ int dbd_postgresql_connection(lua_State *L) { static const luaL_Reg connection_methods[] = { + {"autocommit", connection_autocommit}, {"close", connection_close}, + {"commit", connection_commit}, {"ping", connection_ping}, {"prepare", connection_prepare}, + {"rollback", connection_rollback}, {NULL, NULL} }; diff -r 014ba3ab3903 -r 10c8c6f0da14 dbd/postgresql/dbd_postgresql.h --- a/dbd/postgresql/dbd_postgresql.h Tue Dec 02 21:11:27 2008 +0000 +++ b/dbd/postgresql/dbd_postgresql.h Wed Dec 03 08:44:40 2008 +0000 @@ -17,6 +17,7 @@ */ typedef struct _connection { PGconn *postgresql; + int autocommit; unsigned int statement_id; /* sequence for statement IDs */ } connection_t; diff -r 014ba3ab3903 -r 10c8c6f0da14 dbd/sqlite3/connection.c --- a/dbd/sqlite3/connection.c Tue Dec 02 21:11:27 2008 +0000 +++ b/dbd/sqlite3/connection.c Wed Dec 03 08:44:40 2008 +0000 @@ -2,6 +2,27 @@ int dbd_sqlite3_statement_create(lua_State *L, connection_t *conn, const char *sql_query); +static int run(connection_t *conn, const char *command) { + int res = sqlite3_exec(conn->sqlite, command, NULL, NULL, NULL); + + return res != SQLITE_OK; +} + +static int commit(connection_t *conn) { + return run(conn, "COMMIT"); +} + + +static int begin(connection_t *conn) { + return run(conn, "BEGIN"); +} + + +static int rollback(connection_t *conn) { + return run(conn, "ROLLBACK"); +} + + /* * connection,err = DBD.SQLite3.New(dbfile) */ @@ -26,6 +47,9 @@ return 2; } + conn->autocommit = 0; + begin(conn); + luaL_getmetatable(L, DBD_SQLITE_CONNECTION); lua_setmetatable(L, -2); @@ -33,6 +57,28 @@ } /* + * success = connection:autocommit(on) + */ +static int connection_autocommit(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION); + int on = lua_toboolean(L, 2); + int err = 1; + + if (conn->sqlite) { + if (on) + err = rollback(conn); + else + err = begin(conn); + + conn->autocommit = on; + } + + lua_pushboolean(L, !err); + return 1; +} + + +/* * success = connection:close() */ static int connection_close(lua_State *L) { @@ -49,6 +95,25 @@ return 1; } +/* + * success = connection:commit() + */ +static int connection_commit(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION); + int err = 1; + + if (conn->sqlite) { + commit(conn); + + if (!conn->autocommit) + err = begin(conn); + else + err = 1; + } + + lua_pushboolean(L, !err); + return 1; +} /* * ok = connection:ping() @@ -81,6 +146,26 @@ } /* + * success = connection:rollback() + */ +static int connection_rollback(lua_State *L) { + connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION); + int err = 1; + + if (conn->sqlite) { + rollback(conn); + + if (!conn->autocommit) + err = begin(conn); + else + err = 1; + } + + lua_pushboolean(L, !err); + return 1; +} + +/* * __gc */ static int connection_gc(lua_State *L) { @@ -95,9 +180,12 @@ * instance methods */ static const luaL_Reg connection_methods[] = { + {"autocommit", connection_autocommit}, {"close", connection_close}, + {"commit", connection_commit}, {"ping", connection_ping}, {"prepare", connection_prepare}, + {"rollback", connection_rollback}, {NULL, NULL} }; diff -r 014ba3ab3903 -r 10c8c6f0da14 dbd/sqlite3/dbd_sqlite3.h --- a/dbd/sqlite3/dbd_sqlite3.h Tue Dec 02 21:11:27 2008 +0000 +++ b/dbd/sqlite3/dbd_sqlite3.h Wed Dec 03 08:44:40 2008 +0000 @@ -9,6 +9,7 @@ */ typedef struct _connection { sqlite3 *sqlite; + int autocommit; } connection_t; /*