Added connection:autocommit(), connection:commit(), and connection:rollback() to control transactions.

Wed, 03 Dec 2008 08:44:40 +0000

author
nrich@ii.net
date
Wed, 03 Dec 2008 08:44:40 +0000
changeset 13
10c8c6f0da14
parent 12
014ba3ab3903
child 14
98192b7d4e89

Added connection:autocommit(), connection:commit(), and connection:rollback() to control transactions.

dbd/mysql/connection.c file | annotate | diff | comparison | revisions
dbd/postgresql/connection.c file | annotate | diff | comparison | revisions
dbd/postgresql/dbd_postgresql.h file | annotate | diff | comparison | revisions
dbd/sqlite3/connection.c file | annotate | diff | comparison | revisions
dbd/sqlite3/dbd_sqlite3.h file | annotate | diff | comparison | revisions
--- 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}
     };
 
--- 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}
     };
 
--- 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;
 
--- 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}
     };
 
--- 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;
 
 /*

mercurial