Blob Blame History Raw
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/common.c luadbi/dbd/common.c
--- lua-dbi-0.5/dbd/common.c	2009-06-13 04:50:59.000000000 -0400
+++ luadbi/dbd/common.c	2015-01-15 13:38:28.163032130 -0500
@@ -52,9 +52,12 @@
     /*
      * allocate a new string for the converted SQL statement
      */
-    newsql = malloc(sizeof(char) * (len+extra_space+1));
-    memset(newsql, 0, sizeof(char) * (len+extra_space+1));
-    
+    newsql = calloc(len+extra_space+1, sizeof(char));
+    if(!newsql) {
+    	lua_pushliteral(L, "out of memory");
+    	return lua_error(L);
+    }
+
     /* 
      * copy first char. In valid SQL this cannot be a placeholder
      */
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/common.h luadbi/dbd/common.h
--- lua-dbi-0.5/dbd/common.h	2010-05-01 00:25:11.000000000 -0400
+++ luadbi/dbd/common.h	2015-01-15 13:38:28.163032130 -0500
@@ -39,6 +39,11 @@
     lua_pushnumber(L, v); \
     lua_rawset(L, -3); 
 
+#define LUA_PUSH_ATTRIB_STRING_BY_LENGTH(n, v, len) \
+    lua_pushstring(L, n); \
+    lua_pushlstring(L, v, len); \
+    lua_rawset(L, -3); 
+
 #define LUA_PUSH_ATTRIB_STRING(n, v) \
     lua_pushstring(L, n); \
     lua_pushstring(L, v); \
@@ -71,6 +76,11 @@
     lua_rawseti(L, -2, n); \
     n++;
 
+#define LUA_PUSH_ARRAY_STRING_BY_LENGTH(n, v, len) \
+    lua_pushlstring(L, v, len); \
+    lua_rawseti(L, -2, n); \
+    n++;
+
 #define LUA_PUSH_ARRAY_BOOL(n, v) \
     lua_pushboolean(L, v); \
     lua_rawseti(L, -2, n); \
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/mysql/connection.c luadbi/dbd/mysql/connection.c
--- lua-dbi-0.5/dbd/mysql/connection.c	2010-05-01 00:25:12.000000000 -0400
+++ luadbi/dbd/mysql/connection.c	2015-01-15 13:38:28.171032087 -0500
@@ -16,7 +16,7 @@
     const char *db = NULL;
     int port = 0;
 
-    const char *unix_socket = NULL; /* TODO always NULL */
+    const char *unix_socket = NULL;
     int client_flag = 0; /* TODO always 0, set flags from options table */
 
     /* db, user, password, host, port */
@@ -27,6 +27,10 @@
     case 4: 
 	if (lua_isnil(L, 4) == 0) 
 	    host = luaL_checkstring(L, 4);
+	if (host[0] == '/') {
+		unix_socket = host;
+		host = NULL;
+	};
     case 3:
 	if (lua_isnil(L, 3) == 0) 
 	    password = luaL_checkstring(L, 3);
@@ -178,6 +182,16 @@
 }
 
 /*
+ * last_id = statement:last_id()
+ */
+static int connection_lastid(lua_State *L) {
+	connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION);
+
+	lua_pushinteger(L, mysql_insert_id( conn->mysql ));
+	return 1;
+}
+
+/*
  * __gc
  */
 static int connection_gc(lua_State *L) {
@@ -207,6 +221,7 @@
 	{"prepare", connection_prepare},
 	{"quote", connection_quote},
 	{"rollback", connection_rollback},
+	{"last_id", connection_lastid},
 	{NULL, NULL}
     };
 
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/mysql/dbd_mysql.h luadbi/dbd/mysql/dbd_mysql.h
--- lua-dbi-0.5/dbd/mysql/dbd_mysql.h	2010-05-01 00:25:12.000000000 -0400
+++ luadbi/dbd/mysql/dbd_mysql.h	2015-01-15 13:38:28.172032081 -0500
@@ -22,6 +22,10 @@
 typedef struct _statement {
     MYSQL *mysql;
     MYSQL_STMT *stmt;
-    MYSQL_RES *metadata; /* result dataset metadata */
+    MYSQL_RES *metadata;	/* result dataset metadata */
+    
+    unsigned long *lengths;	/* length of retrieved data 
+							we have to keep this from bind time to 
+							result retrival time */
 } statement_t;
 
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/mysql/statement.c luadbi/dbd/mysql/statement.c
--- lua-dbi-0.5/dbd/mysql/statement.c	2010-05-21 18:49:59.000000000 -0400
+++ luadbi/dbd/mysql/statement.c	2015-01-15 13:38:28.173032076 -0500
@@ -11,10 +11,12 @@
     case MYSQL_TYPE_TINY:
     case MYSQL_TYPE_YEAR:
     case MYSQL_TYPE_SHORT:
-    case MYSQL_TYPE_LONG:	
+    case MYSQL_TYPE_INT24:
+    case MYSQL_TYPE_LONG:
 	lua_type =  LUA_PUSH_INTEGER;
 	break;
 
+    case MYSQL_TYPE_FLOAT:
     case MYSQL_TYPE_DOUBLE:
     case MYSQL_TYPE_LONGLONG:
 	lua_type = LUA_PUSH_NUMBER;
@@ -89,13 +91,18 @@
     statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT);
 
     if (statement->metadata) {
-	mysql_free_result(statement->metadata);
-	statement->metadata = NULL;
+		mysql_free_result(statement->metadata);
+		statement->metadata = NULL;
     }
 
+	if (statement->lengths) {
+		free(statement->lengths);
+		statement->lengths = NULL;
+	}
+
     if (statement->stmt) {
-	mysql_stmt_close(statement->stmt);
-	statement->stmt = NULL;
+		mysql_stmt_close(statement->stmt);
+		statement->stmt = NULL;
     }
 
     lua_pushboolean(L, 1);
@@ -286,7 +293,7 @@
 }
 
 static int statement_fetch_impl(lua_State *L, statement_t *statement, int named_columns) {
-    int column_count;
+    int column_count, fetch_result_ok;
     MYSQL_BIND *bind = NULL;
     const char *error_message = NULL;
 
@@ -306,6 +313,13 @@
 	int i;
 	MYSQL_FIELD *fields;
 
+	if (statement->lengths) {
+			free(statement->lengths);
+			statement->lengths = NULL;
+	}
+	
+	statement->lengths = calloc(column_count, sizeof(unsigned long));
+
         bind = malloc(sizeof(MYSQL_BIND) * column_count);
         memset(bind, 0, sizeof(MYSQL_BIND) * column_count);
 
@@ -313,12 +327,19 @@
 
 	for (i = 0; i < column_count; i++) {
 	    unsigned int length = mysql_buffer_size(&fields[i]);
-	    char *buffer = (char *)malloc(length);
-	    memset(buffer, 0, length);
+	    if (length > sizeof(MYSQL_TIME)) {
+		bind[i].buffer = NULL;
+		bind[i].buffer_length = 0;
+	    } else {
+		char *buffer = (char *)malloc(length);
+		memset(buffer, 0, length);
+
+		bind[i].buffer = buffer;
+		bind[i].buffer_length = length;
+	    }
 
 	    bind[i].buffer_type = fields[i].type; 
-	    bind[i].buffer = buffer;
-	    bind[i].buffer_length = length;
+	    bind[i].length = &(statement->lengths[i]);
 	}
 
 	if (mysql_stmt_bind_result(statement->stmt, bind)) {
@@ -326,7 +347,8 @@
 	    goto cleanup;
 	}
 
-	if (!mysql_stmt_fetch(statement->stmt)) {
+	fetch_result_ok = mysql_stmt_fetch(statement->stmt);
+	if (fetch_result_ok == 0 || fetch_result_ok == MYSQL_DATA_TRUNCATED) {
 	    int d = 1;
 
 	    lua_newtable(L);
@@ -334,6 +356,13 @@
 		lua_push_type_t lua_push = mysql_to_lua_push(fields[i].type);
 		const char *name = fields[i].name;
 
+		if (bind[i].buffer == NULL) {
+		    char *buffer = (char *)calloc(statement->lengths[i]+1, sizeof(char));
+		    bind[i].buffer = buffer;
+		    bind[i].buffer_length = statement->lengths[i];
+		    mysql_stmt_fetch_column(statement->stmt, &bind[i], i, 0);
+		}
+
 		if (lua_push == LUA_PUSH_NIL) {
 		    if (named_columns) {
 			LUA_PUSH_ATTRIB_NIL(name);
@@ -361,11 +390,25 @@
 			}
 		    }
 		} else if (lua_push == LUA_PUSH_NUMBER) {
-		    if (named_columns) {
-			LUA_PUSH_ATTRIB_FLOAT(name, *(double *)(bind[i].buffer));
-		    } else {
-			LUA_PUSH_ARRAY_FLOAT(d, *(double *)(bind[i].buffer));
-		    }
+			if (fields[i].type == MYSQL_TYPE_FLOAT)	{
+				if (named_columns) {
+					LUA_PUSH_ATTRIB_FLOAT(name, *(float *)(bind[i].buffer));
+				} else {
+					LUA_PUSH_ARRAY_FLOAT(d, *(float *)(bind[i].buffer));
+				}
+			} else if (fields[i].type == MYSQL_TYPE_DOUBLE) {
+				if (named_columns) {
+					LUA_PUSH_ATTRIB_FLOAT(name, *(double *)(bind[i].buffer));
+				} else {
+					LUA_PUSH_ARRAY_FLOAT(d, *(double *)(bind[i].buffer));
+				}
+			} else {
+				if (named_columns) {
+					LUA_PUSH_ATTRIB_FLOAT(name, *(long long *)(bind[i].buffer));
+				} else {
+					LUA_PUSH_ARRAY_FLOAT(d, *(long long *)(bind[i].buffer));
+				}
+			}
 		} else if (lua_push == LUA_PUSH_STRING) {
 
 		    if (fields[i].type == MYSQL_TYPE_TIMESTAMP || fields[i].type == MYSQL_TYPE_DATETIME) {
@@ -404,9 +447,9 @@
 
 		    } else {
 			if (named_columns) {
-			    LUA_PUSH_ATTRIB_STRING(name, bind[i].buffer);
+			    LUA_PUSH_ATTRIB_STRING_BY_LENGTH(name, bind[i].buffer, *bind[i].length);
 			} else {
-			    LUA_PUSH_ARRAY_STRING(d, bind[i].buffer);
+			    LUA_PUSH_ARRAY_STRING_BY_LENGTH(d, bind[i].buffer, *bind[i].length);
 			}
 		    }
 		} else if (lua_push == LUA_PUSH_BOOLEAN) {
@@ -425,6 +468,7 @@
     }
 
 cleanup:
+
     if (bind) {
 	int i;
 
@@ -535,6 +579,7 @@
     statement->mysql = conn->mysql;
     statement->stmt = stmt;
     statement->metadata = NULL;
+    statement->lengths = NULL;
 
     /*
     mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (my_bool*)0);
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/postgresql/connection.c luadbi/dbd/postgresql/connection.c
--- lua-dbi-0.5/dbd/postgresql/connection.c	2010-05-01 00:25:12.000000000 -0400
+++ luadbi/dbd/postgresql/connection.c	2015-01-15 13:38:28.176032059 -0500
@@ -109,10 +109,12 @@
     int err = 0;
 
     if (conn->postgresql) {
-	if (on)
-	    err = rollback(conn);
-	else
-	    err = begin(conn);
+	if (on != conn->autocommit) {
+	    if (on)
+		err = rollback(conn);
+	    else
+		err = begin(conn);
+	}
 
 	conn->autocommit = on;	
     }
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/postgresql/dbd_postgresql.h luadbi/dbd/postgresql/dbd_postgresql.h
--- lua-dbi-0.5/dbd/postgresql/dbd_postgresql.h	2010-05-01 00:25:12.000000000 -0400
+++ luadbi/dbd/postgresql/dbd_postgresql.h	2015-01-15 13:38:28.176032059 -0500
@@ -1,5 +1,4 @@
 #include <libpq-fe.h>
-#include <postgres_fe.h>
 #include <dbd/common.h>
 
 /* 
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/sqlite3/connection.c luadbi/dbd/sqlite3/connection.c
--- lua-dbi-0.5/dbd/sqlite3/connection.c	2010-05-01 00:25:12.000000000 -0400
+++ luadbi/dbd/sqlite3/connection.c	2015-01-15 13:38:28.178032048 -0500
@@ -9,19 +9,33 @@
 }
 
 static int commit(connection_t *conn) {
-    return run(conn, "COMMIT");
+    return run(conn, "COMMIT TRANSACTION");
 }
 
 
 static int begin(connection_t *conn) {
-    return run(conn, "BEGIN");
-}
+    int err = 0;
 
+    if (sqlite3_get_autocommit(conn->sqlite)) {
+        err = run(conn, "BEGIN TRANSACTION");
+    } else {
+        err = 0;
+    }
+
+    return err;
+}
 
 static int rollback(connection_t *conn) {
-    return run(conn, "ROLLBACK");
+    return run(conn, "ROLLBACK TRANSACTION");
 }
 
+int try_begin_transaction(connection_t *conn) {
+    if (conn->autocommit) {
+        return 1;
+    }
+
+    return begin(conn) == 0;
+}
 
 /* 
  * connection,err = DBD.SQLite3.New(dbfile)
@@ -50,7 +64,6 @@
     }
 
     conn->autocommit = 0;
-    begin(conn);
 
     luaL_getmetatable(L, DBD_SQLITE_CONNECTION);
     lua_setmetatable(L, -2);
@@ -67,10 +80,9 @@
     int err = 1;
 
     if (conn->sqlite) {
-	if (on)
+	if (on) {
 	    err = rollback(conn);
-	else
-	    err = begin(conn);
+        }
 
 	conn->autocommit = on;	
     }
@@ -88,6 +100,7 @@
     int disconnect = 0;   
 
     if (conn->sqlite) {
+        rollback(conn);
 	sqlite3_close(conn->sqlite);
 	disconnect = 1;
 	conn->sqlite = NULL;
@@ -105,12 +118,7 @@
     int err = 1;
 
     if (conn->sqlite) {
-	commit(conn);
-
-	if (!conn->autocommit)
-	    err = begin(conn);
-	else
-	    err = 1;
+	err = commit(conn);
     }
 
     lua_pushboolean(L, !err);
@@ -176,12 +184,7 @@
     int err = 1;
 
     if (conn->sqlite) {
-	rollback(conn);
-
-	if (!conn->autocommit)
-	    err = begin(conn);
-	else
-	    err = 1;
+	err =rollback(conn);
     }
 
     lua_pushboolean(L, !err);
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/sqlite3/dbd_sqlite3.h luadbi/dbd/sqlite3/dbd_sqlite3.h
--- lua-dbi-0.5/dbd/sqlite3/dbd_sqlite3.h	2008-12-19 01:33:32.000000000 -0500
+++ luadbi/dbd/sqlite3/dbd_sqlite3.h	2015-01-15 13:38:28.178032048 -0500
@@ -10,14 +10,15 @@
 typedef struct _connection {
     sqlite3 *sqlite;
     int autocommit;
+//    int txn_in_progress;
 } connection_t;
 
 /*
  * statement object
  */
 typedef struct _statement {
+    connection_t *conn;
     sqlite3_stmt *stmt;
-    sqlite3 *sqlite;
     int more_data;
     int affected;
 } statement_t;
diff -urP '--exclude=.hg' lua-dbi-0.5/dbd/sqlite3/statement.c luadbi/dbd/sqlite3/statement.c
--- lua-dbi-0.5/dbd/sqlite3/statement.c	2010-05-01 00:25:12.000000000 -0400
+++ luadbi/dbd/sqlite3/statement.c	2015-01-15 13:38:28.179032043 -0500
@@ -1,5 +1,8 @@
 #include "dbd_sqlite3.h"
 
+extern int try_begin_transaction(connection_t *conn);
+extern int try_end_transaction(connection_t *conn);
+
 /*
  * Converts SQLite types to Lua types
  */
@@ -128,10 +131,12 @@
      */
     if (sqlite3_reset(statement->stmt) != SQLITE_OK) {
 	lua_pushboolean(L, 0);
-	lua_pushfstring(L, DBI_ERR_EXECUTE_FAILED, sqlite3_errmsg(statement->sqlite));
+	lua_pushfstring(L, DBI_ERR_EXECUTE_FAILED, sqlite3_errmsg(statement->conn->sqlite));
 	return 2;
     }
 
+    sqlite3_clear_bindings(statement->stmt);
+
     expected_params = sqlite3_bind_parameter_count(statement->stmt);
     if (expected_params != num_bind_params) {
 	/*
@@ -156,10 +161,13 @@
 	case LUA_TNUMBER:
 	    errflag = sqlite3_bind_double(statement->stmt, i, lua_tonumber(L, p)) != SQLITE_OK;
 	    break;
-	case LUA_TSTRING:
-	    errflag = sqlite3_bind_text(statement->stmt, i, lua_tostring(L, p), -1, SQLITE_STATIC) != SQLITE_OK;
+	case LUA_TSTRING: {
+	    size_t len = -1;
+	    const char *str = lua_tolstring(L, p, &len);
+	    errflag = sqlite3_bind_text(statement->stmt, i, str, len, SQLITE_STATIC) != SQLITE_OK;
 	    break;
-	case LUA_TBOOLEAN:
+	}
+    case LUA_TBOOLEAN:
 	    errflag = sqlite3_bind_int(statement->stmt, i, lua_toboolean(L, p)) != SQLITE_OK;
 	    break;
 	default:
@@ -180,18 +188,20 @@
 	if (errstr)
 	    lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errstr);
 	else
-	    lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, sqlite3_errmsg(statement->sqlite));
+	    lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, sqlite3_errmsg(statement->conn->sqlite));
     
 	return 2;
     }
+    
+    try_begin_transaction(statement->conn);
 
     if (!step(statement)) {
 	lua_pushboolean(L, 0);
-	lua_pushfstring(L, DBI_ERR_EXECUTE_FAILED, sqlite3_errmsg(statement->sqlite));
+	lua_pushfstring(L, DBI_ERR_EXECUTE_FAILED, sqlite3_errmsg(statement->conn->sqlite));
 	return 2;
     }
 
-    statement->affected = sqlite3_changes(statement->sqlite);
+    statement->affected = sqlite3_changes(statement->conn->sqlite);
 
     lua_pushboolean(L, 1);
     return 1;
@@ -283,7 +293,7 @@
 	    /* 
 	     * reset needs to be called to retrieve the 'real' error message
 	     */
-	    luaL_error(L, DBI_ERR_FETCH_FAILED, sqlite3_errmsg(statement->sqlite));
+	    luaL_error(L, DBI_ERR_FETCH_FAILED, sqlite3_errmsg(statement->conn->sqlite));
 	}
     }
 
@@ -327,9 +337,9 @@
  * num_rows = statement:rowcount()
  */
 static int statement_rowcount(lua_State *L) {
-    luaL_error(L, DBI_ERR_NOT_IMPLEMENTED, DBD_SQLITE_STATEMENT, "rowcount");
-
-    return 0;
+	statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_SQLITE_STATEMENT);
+	lua_pushinteger(L, sqlite3_data_count(statement->stmt));
+	return 1;
 }
 
 /*
@@ -357,14 +367,14 @@
     statement_t *statement = NULL;
 
     statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t));
-    statement->sqlite = conn->sqlite;
+    statement->conn = conn;
     statement->stmt = NULL;
     statement->more_data = 0;
     statement->affected = 0;
 
-    if (sqlite3_prepare_v2(statement->sqlite, sql_query, strlen(sql_query), &statement->stmt, NULL) != SQLITE_OK) {
+    if (sqlite3_prepare_v2(statement->conn->sqlite, sql_query, strlen(sql_query), &statement->stmt, NULL) != SQLITE_OK) {
 	lua_pushnil(L);
-	lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, sqlite3_errmsg(statement->sqlite));	
+	lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, sqlite3_errmsg(statement->conn->sqlite));	
 	return 2;
     }