# HG changeset patch # User nrich@ii.net # Date 1227693663 0 # Node ID b61020ca475360e0168bd801c954a0207b711780 # Parent c4f02fc67e5ac2f07b82f051bcdcecad121c0a03 Cleanup and 'assert' error handling. diff -r c4f02fc67e5a -r b61020ca4753 DBI.lua --- a/DBI.lua Sun Nov 23 04:12:04 2008 +0000 +++ b/DBI.lua Wed Nov 26 10:01:03 2008 +0000 @@ -56,3 +56,12 @@ return connection_class.New(name, username, password, host, port) end +function Do(dbh, sql, ...) + local sth,err = dbh:prepare(sql) + + if not sth then + return false, err + end + + return sth:execute(...) +end diff -r c4f02fc67e5a -r b61020ca4753 dbd/mysql/connection.c --- a/dbd/mysql/connection.c Sun Nov 23 04:12:04 2008 +0000 +++ b/dbd/mysql/connection.c Wed Nov 26 10:01:03 2008 +0000 @@ -3,7 +3,7 @@ int dbd_mysql_statement_create(lua_State *L, connection_t *conn, const char *sql_query); /* - * connection = DBD.MySQl.New(dbname, user, password, host, port) + * connection,err = DBD.MySQl.New(dbname, user, password, host, port) */ static int connection_new(lua_State *L) { int n = lua_gettop(L); @@ -42,14 +42,15 @@ conn->mysql = mysql_init(NULL); - if (mysql_real_connect(conn->mysql, host, user, password, db, port, unix_socket, client_flag)) { - luaL_getmetatable(L, DBD_MYSQL_CONNECTION); - lua_setmetatable(L, -2); - } else { - luaL_error(L, "Failed to connect to database: %s", mysql_error(conn->mysql)); + if (!mysql_real_connect(conn->mysql, host, user, password, db, port, unix_socket, client_flag)) { lua_pushnil(L); + lua_pushfstring(L, "Failed to connect to database: %s", mysql_error(conn->mysql)); + return 2; } + luaL_getmetatable(L, DBD_MYSQL_CONNECTION); + lua_setmetatable(L, -2); + return 1; } @@ -63,6 +64,7 @@ if (conn->mysql) { mysql_close(conn->mysql); disconnect = 1; + conn->mysql = NULL; } lua_pushboolean(L, disconnect); @@ -85,7 +87,7 @@ } /* - * statement = connection:prepare(sql_string) + * statement,err = connection:prepare(sql_string) */ static int connection_prepare(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION); @@ -95,7 +97,9 @@ } lua_pushnil(L); - return 1; + lua_pushstring(L, "Database not available"); + + return 2; } /* diff -r c4f02fc67e5a -r b61020ca4753 dbd/mysql/statement.c --- a/dbd/mysql/statement.c Sun Nov 23 04:12:04 2008 +0000 +++ b/dbd/mysql/statement.c Wed Nov 26 10:01:03 2008 +0000 @@ -34,22 +34,26 @@ if (statement->metadata) { mysql_free_result(statement->metadata); + statement->metadata = NULL; } if (statement->stmt) { - mysql_stmt_close(statement->stmt); + mysql_stmt_close(statement->stmt); + statement->stmt = NULL; } + lua_pushboolean(L, 1); return 1; } /* - * success = statement:execute(...) + * success,err = statement:execute(...) */ static int statement_execute(lua_State *L) { int n = lua_gettop(L); statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT); int num_bind_params = n - 1; + int expected_params; MYSQL_BIND *bind = NULL; MYSQL_RES *metadata = NULL; @@ -58,6 +62,24 @@ int p; + if (!statement->stmt) { + lua_pushboolean(L, 0); + lua_pushstring(L, "execute called on a closed or invalid statement"); + return 2; + } + + expected_params = mysql_stmt_param_count(statement->stmt); + + if (expected_params != num_bind_params) { + /* + * mysql_stmt_bind_param does not handle this conndition, + * and the client library will segfault if these do no match + */ + lua_pushboolean(L, 0); + lua_pushfstring(L, "Statement expected %d paramaters but received %d", expected_params, num_bind_params); + return 2; + } + bind = malloc(sizeof(MYSQL_BIND) * num_bind_params); memset(bind, 0, sizeof(MYSQL_BIND) * num_bind_params); @@ -117,12 +139,14 @@ free(bind); if (error_message) { - luaL_error(L, error_message, mysql_stmt_error(statement->stmt)); - return 0; + lua_pushboolean(L, 0); + lua_pushfstring(L, error_message, mysql_stmt_error(statement->stmt)); + return 2; } statement->metadata = metadata; + lua_pushboolean(L, 1); return 1; } @@ -133,9 +157,13 @@ const char *error_message = NULL; if (!statement->stmt) { + luaL_error(L, "fetch called on a closed or invalid statement"); + return 0; + } + + if (!statement->metadata) { luaL_error(L, "fetch called before execute"); - lua_pushnil(L); - return 1; + return 0; } if (!statement->metadata) { @@ -268,13 +296,15 @@ MYSQL_STMT *stmt = mysql_stmt_init(conn->mysql); if (!stmt) { - luaL_error(L, "Error allocating statement handle: %s", mysql_error(conn->mysql)); - return 0; + lua_pushnil(L); + lua_pushfstring(L, "Error allocating statement handle: %s", mysql_error(conn->mysql)); + return 2; } if (mysql_stmt_prepare(stmt, sql_query, sql_len)) { - luaL_error(L, "Error preparing statement handle: %s", mysql_stmt_error(stmt)); - return 0; + lua_pushnil(L); + lua_pushfstring(L, "Error preparing statement handle: %s", mysql_stmt_error(stmt)); + return 2; } statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t)); diff -r c4f02fc67e5a -r b61020ca4753 dbd/postgresql/connection.c --- a/dbd/postgresql/connection.c Sun Nov 23 04:12:04 2008 +0000 +++ b/dbd/postgresql/connection.c Wed Nov 26 10:01:03 2008 +0000 @@ -53,14 +53,15 @@ conn->postgresql = PQsetdbLogin(host, port, options, tty, db, user, password); conn->statement_id = 0; - if (PQstatus(conn->postgresql) == CONNECTION_OK) { - luaL_getmetatable(L, DBD_POSTGRESQL_CONNECTION); - lua_setmetatable(L, -2); - } else { - luaL_error(L, "Failed to connect to database: %s", PQerrorMessage(conn->postgresql)); + if (PQstatus(conn->postgresql) != CONNECTION_OK) { lua_pushnil(L); + lua_pushfstring(L, "Failed to connect to database: %s", PQerrorMessage(conn->postgresql)); + return 2; } + luaL_getmetatable(L, DBD_POSTGRESQL_CONNECTION); + lua_setmetatable(L, -2); + return 1; } @@ -74,6 +75,7 @@ if (conn->postgresql) { PQfinish(conn->postgresql); disconnect = 1; + conn->postgresql = NULL; } lua_pushboolean(L, disconnect); @@ -109,7 +111,8 @@ } lua_pushnil(L); - return 1; + lua_pushstring(L, "Database not available"); + return 2; } /* diff -r c4f02fc67e5a -r b61020ca4753 dbd/postgresql/statement.c --- a/dbd/postgresql/statement.c Sun Nov 23 04:12:04 2008 +0000 +++ b/dbd/postgresql/statement.c Wed Nov 26 10:01:03 2008 +0000 @@ -180,21 +180,22 @@ free(params); if (!result) { - luaL_error(L, "Unable to allocate result handle"); lua_pushboolean(L, 0); - return 1; + lua_pushstring(L, "Unable to allocate result handle"); + return 2; } status = PQresultStatus(result); if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { - luaL_error(L, "Unable to execute statment: %s", PQresultErrorMessage(result)); lua_pushboolean(L, 0); - return 1; + lua_pushfstring(L, "Unable to execute statment: %s", PQresultErrorMessage(result)); + return 2; } statement->result = result; lua_pushboolean(L, 1); + lua_pushnil(L); return 1; } @@ -207,6 +208,11 @@ int i; int num_columns; + if (!statement->result) { + luaL_error(L, "fetch called on a closed or invalid statement"); + return 0; + } + if (PQresultStatus(statement->result) != PGRES_TUPLES_OK) { lua_pushnil(L); return 1; @@ -332,15 +338,19 @@ free(new_sql); if (!result) { - luaL_error(L, "Unable to allocate prepare result handle"); + lua_pushnil(L); + lua_pushstring(L, "Unable to allocate prepare result handle"); + return 2; } status = PQresultStatus(result); if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { const char *err_string = PQresultErrorMessage(result); PQclear(result); - luaL_error(L, "Unable to prepare statment: %s", err_string); - return 0; + + lua_pushnil(L); + lua_pushfstring(L, "Unable to prepare statment: %s", err_string); + return 2; } PQclear(result); diff -r c4f02fc67e5a -r b61020ca4753 dbd/sqlite3/connection.c --- a/dbd/sqlite3/connection.c Sun Nov 23 04:12:04 2008 +0000 +++ b/dbd/sqlite3/connection.c Wed Nov 26 10:01:03 2008 +0000 @@ -3,7 +3,7 @@ int dbd_sqlite3_statement_create(lua_State *L, connection_t *conn, const char *sql_query); /* - * connection = DBD.SQLite3.New(dbfile) + * connection,err = DBD.SQLite3.New(dbfile) */ static int connection_new(lua_State *L) { int n = lua_gettop(L); @@ -13,21 +13,22 @@ /* db */ switch (n) { - default: + case 1: if (lua_isnil(L, 1) == 0) db = luaL_checkstring(L, 1); } conn = (connection_t *)lua_newuserdata(L, sizeof(connection_t)); - if (sqlite3_open(db, &conn->sqlite) == SQLITE_OK) { - luaL_getmetatable(L, DBD_SQLITE_CONNECTION); - lua_setmetatable(L, -2); - } else { - luaL_error(L, "Failed to connect to database: %s", sqlite3_errmsg(conn->sqlite)); + if (sqlite3_open(db, &conn->sqlite) != SQLITE_OK) { lua_pushnil(L); + lua_pushfstring(L, "Failed to connect to database: %s", sqlite3_errmsg(conn->sqlite)); + return 2; } + luaL_getmetatable(L, DBD_SQLITE_CONNECTION); + lua_setmetatable(L, -2); + return 1; } @@ -39,15 +40,16 @@ int disconnect = 0; if (conn->sqlite) { - if (sqlite3_close(conn->sqlite) == SQLITE_OK) { - disconnect = 1; - } + sqlite3_close(conn->sqlite); + disconnect = 1; + conn->sqlite = NULL; } lua_pushboolean(L, disconnect); return 1; } + /* * ok = connection:ping() */ @@ -64,7 +66,7 @@ } /* - * statement = connection:prepare(sql_str) + * statement,err = connection:prepare(sql_str) */ static int connection_prepare(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION); @@ -74,7 +76,8 @@ } lua_pushnil(L); - return 1; + lua_pushstring(L, "Connection not available"); + return 2; } /* diff -r c4f02fc67e5a -r b61020ca4753 dbd/sqlite3/statement.c --- a/dbd/sqlite3/statement.c Sun Nov 23 04:12:04 2008 +0000 +++ b/dbd/sqlite3/statement.c Wed Nov 26 10:01:03 2008 +0000 @@ -46,7 +46,7 @@ /* * success = statement:close() */ -static int statement_close(lua_State *L) { +int statement_close(lua_State *L) { statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_SQLITE_STATEMENT); int ok = 0; @@ -54,20 +54,29 @@ if (sqlite3_finalize(statement->stmt) == SQLITE_OK) { ok = 1; } + + statement->stmt = NULL; } lua_pushboolean(L, ok); - return 1; } /* - * success = statement:execute(...) + * success,err = statement:execute(...) */ -static int statement_execute(lua_State *L) { +int statement_execute(lua_State *L) { int n = lua_gettop(L); statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_SQLITE_STATEMENT); int p; + int err = 0; + + + if (!statement->stmt) { + lua_pushboolean(L, 0); + lua_pushstring(L, "execute called on a closed or invalid handle"); + return 2; + } /* * reset the handle before binding params @@ -76,7 +85,8 @@ */ if (sqlite3_reset(statement->stmt) != SQLITE_OK) { lua_pushboolean(L, 0); - return 1; + lua_pushfstring(L, "Failed to execute statement: %s", sqlite3_errmsg(statement->sqlite)); + return 2; } for (p = 2; p <= n; p++) { @@ -84,20 +94,29 @@ if (lua_isnil(L, p)) { if (sqlite3_bind_null(statement->stmt, i) != SQLITE_OK) { - luaL_error(L, "Failed to execute statement: %s", sqlite3_errmsg(statement->sqlite)); + err = 1; } } else if (lua_isnumber(L, p)) { if (sqlite3_bind_double(statement->stmt, i, luaL_checknumber(L, p)) != SQLITE_OK) { - luaL_error(L, "Failed to execute statement: %s", sqlite3_errmsg(statement->sqlite)); + err = 1; } } else if (lua_isstring(L, p)) { if (sqlite3_bind_text(statement->stmt, i, luaL_checkstring(L, p), -1, SQLITE_STATIC) != SQLITE_OK) { - luaL_error(L, "Failed to execute statement: %s", sqlite3_errmsg(statement->sqlite)); + err = 1; } } + + if (err) + break; } - lua_pushboolean(L, step(statement)); + if (err || step(statement) == 0) { + lua_pushboolean(L, 0); + lua_pushfstring(L, "Failed to execute statement: %s", sqlite3_errmsg(statement->sqlite)); + return 2; + } + + lua_pushboolean(L, 1); return 1; } @@ -108,6 +127,11 @@ statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_SQLITE_STATEMENT); int num_columns; + if (!statement->stmt) { + luaL_error(L, "fetch called on a closed or invalid handle"); + return 0; + } + if (!statement->more_data) { /* * Result set is empty, or not result set returned @@ -223,14 +247,13 @@ statement->more_data = 0; if (sqlite3_prepare_v2(statement->sqlite, sql_query, strlen(sql_query), &statement->stmt, NULL) != SQLITE_OK) { - luaL_error(L, "Failed to prepare statement: %s", sqlite3_errmsg(statement->sqlite)); lua_pushnil(L); - return 1; + lua_pushfstring(L, "Failed to prepare statement: %s", sqlite3_errmsg(statement->sqlite)); + return 2; } luaL_getmetatable(L, DBD_SQLITE_STATEMENT); lua_setmetatable(L, -2); - return 1; }