# HG changeset patch # User nrich@ii.net # Date 1227413524 0 # Node ID c4f02fc67e5ac2f07b82f051bcdcecad121c0a03 # Parent 408291a6eb3ea6816710ccd708d86fac09434772 Cleanup and commenting diff -r 408291a6eb3e -r c4f02fc67e5a DBI.lua --- a/DBI.lua Sun Nov 23 01:29:09 2008 +0000 +++ b/DBI.lua Sun Nov 23 04:12:04 2008 +0000 @@ -2,6 +2,7 @@ module('DBI', package.seeall) +-- Driver to module mapping local name_to_module = { MySQL = 'dbdmysql', PostgreSQL = 'dbdpostgresql', @@ -10,6 +11,8 @@ local string = require('string') +-- Returns a list of available drivers +-- based on run time loading local function available_drivers() local available = {} @@ -21,6 +24,7 @@ end end + -- no drivers available if table.maxn(available) < 1 then return '(None)' end @@ -28,6 +32,8 @@ return table.concat(available, ',') end + -- High level DB connection function + -- This should be used rather than DBD.{Driver}.New function Connect(driver, name, username, password, host, port) local modulefile = name_to_module[driver] @@ -38,6 +44,7 @@ local m, err = pcall(require, modulefile) if not m then + -- cannot load the module, we cannot continue error(string.format('Cannot load driver %s. Available drivers are: %s', driver, available_drivers())) end @@ -45,6 +52,7 @@ local connection_class = package.loaded[class_str] + -- Calls DBD.{Driver}.New(...) return connection_class.New(name, username, password, host, port) end diff -r 408291a6eb3e -r c4f02fc67e5a dbd/common.h --- a/dbd/common.h Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/common.h Sun Nov 23 04:12:04 2008 +0000 @@ -10,7 +10,14 @@ #include #endif - +/* + * + * Table construction helper functions + * + * LUA_PUSH_ATTRIB_* creates string indexed (hashmap) + * LUA_PUSH_ATTRIB_* creates integer indexed (array) + * + */ #define LUA_PUSH_ATTRIB_INT(n, v) \ lua_pushstring(L, n); \ @@ -64,7 +71,11 @@ lua_rawseti(L, -2, n); \ n++; - +/* + * + * Describes SQL to Lua API conversions + * + */ typedef enum lua_push_type { LUA_PUSH_NIL = 0, diff -r 408291a6eb3e -r c4f02fc67e5a dbd/mysql/connection.c --- a/dbd/mysql/connection.c Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/mysql/connection.c Sun Nov 23 04:12:04 2008 +0000 @@ -2,6 +2,9 @@ int dbd_mysql_statement_create(lua_State *L, connection_t *conn, const char *sql_query); +/* + * connection = DBD.MySQl.New(dbname, user, password, host, port) + */ static int connection_new(lua_State *L) { int n = lua_gettop(L); @@ -50,6 +53,9 @@ return 1; } +/* + * success = connection:close() + */ static int connection_close(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION); int disconnect = 0; @@ -63,6 +69,9 @@ return 1; } +/* + * ok = connection:ping() + */ static int connection_ping(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION); int err = 1; @@ -75,6 +84,9 @@ return 1; } +/* + * statement = connection:prepare(sql_string) + */ static int connection_prepare(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_MYSQL_CONNECTION); @@ -86,7 +98,9 @@ return 1; } - +/* + * __gc + */ static int connection_gc(lua_State *L) { /* always close the connection */ connection_close(L); @@ -94,19 +108,19 @@ return 0; } -static const luaL_Reg connection_methods[] = { - {"close", connection_close}, - {"ping", connection_ping}, - {"prepare", connection_prepare}, - {NULL, NULL} -}; +int dbd_mysql_connection(lua_State *L) { + static const luaL_Reg connection_methods[] = { + {"close", connection_close}, + {"ping", connection_ping}, + {"prepare", connection_prepare}, + {NULL, NULL} + }; -static const luaL_Reg connection_class_methods[] = { - {"New", connection_new}, - {NULL, NULL} -}; + static const luaL_Reg connection_class_methods[] = { + {"New", connection_new}, + {NULL, NULL} + }; -int dbd_mysql_connection(lua_State *L) { luaL_newmetatable(L, DBD_MYSQL_CONNECTION); luaL_register(L, 0, connection_methods); lua_pushvalue(L,-1); diff -r 408291a6eb3e -r c4f02fc67e5a dbd/mysql/dbd_mysql.h --- a/dbd/mysql/dbd_mysql.h Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/mysql/dbd_mysql.h Sun Nov 23 04:12:04 2008 +0000 @@ -4,13 +4,19 @@ #define DBD_MYSQL_CONNECTION "DBD.MySQL.Connection" #define DBD_MYSQL_STATEMENT "DBD.MySQL.Statement" +/* + * connection object implementation + */ typedef struct _connection { MYSQL *mysql; } connection_t; +/* + * statement object implementation + */ typedef struct _statement { MYSQL *mysql; MYSQL_STMT *stmt; - MYSQL_RES *metadata; + MYSQL_RES *metadata; /* result dataset metadata */ } statement_t; diff -r 408291a6eb3e -r c4f02fc67e5a dbd/mysql/main.c --- a/dbd/mysql/main.c Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/mysql/main.c Sun Nov 23 04:12:04 2008 +0000 @@ -3,6 +3,9 @@ int dbd_mysql_connection(lua_State *L); int dbd_mysql_statement(lua_State *L); +/* + * libabry entry point + */ int luaopen_dbdmysql(lua_State *L) { dbd_mysql_connection(L); dbd_mysql_statement(L); diff -r 408291a6eb3e -r c4f02fc67e5a dbd/mysql/statement.c --- a/dbd/mysql/statement.c Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/mysql/statement.c Sun Nov 23 04:12:04 2008 +0000 @@ -26,6 +26,9 @@ return lua_type; } +/* + * success = statement:close() + */ static int statement_close(lua_State *L) { statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT); @@ -40,6 +43,9 @@ return 1; } +/* + * success = 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); @@ -230,15 +236,23 @@ return 1; } - +/* + * array = statement:fetch() + */ static int statement_fetch(lua_State *L) { return statement_fetch_impl(L, 0); } +/* + * hashmap = statement:fetchtable() + */ static int statement_fetchtable(lua_State *L) { return statement_fetch_impl(L, 1); } +/* + * __gc + */ static int statement_gc(lua_State *L) { /* always free the handle */ statement_close(L); @@ -246,19 +260,6 @@ return 0; } - -static const luaL_Reg statement_methods[] = { - {"close", statement_close}, - {"execute", statement_execute}, - {"fetch", statement_fetch}, - {"fetchtable", statement_fetchtable}, - {NULL, NULL} -}; - -static const luaL_Reg statement_class_methods[] = { - {NULL, NULL} -}; - int dbd_mysql_statement_create(lua_State *L, connection_t *conn, const char *sql_query) { unsigned long sql_len = strlen(sql_query); @@ -288,6 +289,18 @@ } int dbd_mysql_statement(lua_State *L) { + static const luaL_Reg statement_methods[] = { + {"close", statement_close}, + {"execute", statement_execute}, + {"fetch", statement_fetch}, + {"fetchtable", statement_fetchtable}, + {NULL, NULL} + }; + + static const luaL_Reg statement_class_methods[] = { + {NULL, NULL} + }; + luaL_newmetatable(L, DBD_MYSQL_STATEMENT); luaL_register(L, 0, statement_methods); lua_pushvalue(L,-1); diff -r 408291a6eb3e -r c4f02fc67e5a dbd/postgresql/connection.c --- a/dbd/postgresql/connection.c Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/postgresql/connection.c Sun Nov 23 04:12:04 2008 +0000 @@ -2,6 +2,9 @@ int dbd_postgresql_statement_create(lua_State *L, connection_t *conn, const char *sql_query); +/* + * connection = DBD.PostgreSQL.New(dbname, user, password, host, port) + */ static int connection_new(lua_State *L) { int n = lua_gettop(L); connection_t *conn = NULL; @@ -61,6 +64,9 @@ return 1; } +/* + * success = connection:close() + */ static int connection_close(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_CONNECTION); int disconnect = 0; @@ -74,6 +80,9 @@ return 1; } +/* + * ok = connection:ping() + */ static int connection_ping(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_CONNECTION); int ok = 0; @@ -89,6 +98,9 @@ return 1; } +/* + * statement = connection:prepare(sql_string) + */ static int connection_prepare(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_CONNECTION); @@ -100,7 +112,9 @@ return 1; } - +/* + * __gc + */ static int connection_gc(lua_State *L) { /* always close the connection */ connection_close(L); @@ -108,19 +122,19 @@ return 0; } -static const luaL_Reg connection_methods[] = { - {"close", connection_close}, - {"ping", connection_ping}, - {"prepare", connection_prepare}, - {NULL, NULL} -}; +int dbd_postgresql_connection(lua_State *L) { + static const luaL_Reg connection_methods[] = { + {"close", connection_close}, + {"ping", connection_ping}, + {"prepare", connection_prepare}, + {NULL, NULL} + }; -static const luaL_Reg connection_class_methods[] = { - {"New", connection_new}, - {NULL, NULL} -}; + static const luaL_Reg connection_class_methods[] = { + {"New", connection_new}, + {NULL, NULL} + }; -int dbd_postgresql_connection(lua_State *L) { luaL_newmetatable(L, DBD_POSTGRESQL_CONNECTION); luaL_register(L, 0, connection_methods); lua_pushvalue(L,-1); diff -r 408291a6eb3e -r c4f02fc67e5a dbd/postgresql/dbd_postgresql.h --- a/dbd/postgresql/dbd_postgresql.h Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/postgresql/dbd_postgresql.h Sun Nov 23 04:12:04 2008 +0000 @@ -3,20 +3,30 @@ #include #include +/* + * length of a prepared statement ID + * \d{17}\0 + */ #define IDLEN 18 #define DBD_POSTGRESQL_CONNECTION "DBD.PostgreSQL.Connection" #define DBD_POSTGRESQL_STATEMENT "DBD.PostgreSQL.Statement" +/* + * connection object implentation + */ typedef struct _connection { PGconn *postgresql; - unsigned int statement_id; + unsigned int statement_id; /* sequence for statement IDs */ } connection_t; +/* + * statement object implementation + */ typedef struct _statement { PGconn *postgresql; PGresult *result; - char name[IDLEN]; - int tuple; + char name[IDLEN]; /* statement ID */ + int tuple; /* number of rows returned */ } statement_t; diff -r 408291a6eb3e -r c4f02fc67e5a dbd/postgresql/main.c --- a/dbd/postgresql/main.c Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/postgresql/main.c Sun Nov 23 04:12:04 2008 +0000 @@ -3,6 +3,9 @@ int dbd_postgresql_connection(lua_State *L); int dbd_postgresql_statement(lua_State *L); +/* + * library entry point + */ int luaopen_dbdpostgresql(lua_State *L) { dbd_postgresql_connection(L); dbd_postgresql_statement(L); diff -r 408291a6eb3e -r c4f02fc67e5a dbd/postgresql/statement.c --- a/dbd/postgresql/statement.c Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/postgresql/statement.c Sun Nov 23 04:12:04 2008 +0000 @@ -1,6 +1,6 @@ #include "dbd_postgresql.h" -#define MAX_PLACEHOLDERS 9999 +#define MAX_PLACEHOLDERS 9999 #define MAX_PLACEHOLDER_SIZE (1+4) /* $\d{4} */ static lua_push_type_t postgresql_to_lua_push(unsigned int postgresql_type) { @@ -28,6 +28,10 @@ return lua_type; } +/* + * replace '?' placeholders with $\d+ placeholders + * to be compatible with PSQL API + */ static char *replace_placeholders(lua_State *L, const char *sql) { size_t len = strlen(sql); int num_placeholders = 0; @@ -38,20 +42,43 @@ int ph_num = 1; int in_quote = 0; + /* + * dumb count of all '?' + * this will match more placeholders than necessesary + * but it's safer to allocate more placeholders at the + * cost of a few bytes than risk a buffer overflow + */ for (i = 1; i < len; i++) { if (sql[i] == '?') { num_placeholders++; } } + /* + * this is MAX_PLACEHOLDER_SIZE-1 because the '?' is + * replaced with '$' + */ extra_space = num_placeholders * (MAX_PLACEHOLDER_SIZE-1); + /* + * 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)); - /* copy first char */ + /* + * copy first char. In valid SQL this cannot be a placeholder + */ newsql[0] = sql[0]; + + /* + * only replace '?' not in a single quoted string + */ for (i = 1; i < len; i++) { + /* + * don't change the quote flag if the ''' is preceded + * bt a '\' to account for escaping + */ if (sql[i] == '\'' && sql[i-1] != '\\') { in_quote = !in_quote; } @@ -72,13 +99,18 @@ } } - /* terminate string on the last position */ + /* + * terminate string on the last position + */ newsql[newpos] = '\0'; /* fprintf(stderr, "[%s]\n", newsql); */ return newsql; } +/* + * success = statement:close() + */ static int statement_close(lua_State *L) { statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); @@ -90,6 +122,9 @@ return 0; } +/* + * success = statement:execute(...) + */ static int statement_execute(lua_State *L) { int n = lua_gettop(L); statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); @@ -104,6 +139,9 @@ params = malloc(num_bind_params * sizeof(params)); + /* + * convert and copy parameters into a string array + */ for (p = 2; p <= n; p++) { int i = p - 2; @@ -131,6 +169,9 @@ 0 ); + /* + * free string array + */ for (p = 0; p < num_bind_params; p++) { if (params[p]) { free(params[p]); @@ -157,6 +198,9 @@ return 1; } +/* + * must be called after an execute + */ static int statement_fetch_impl(lua_State *L, int named_columns) { statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); int tuple = statement->tuple++; @@ -189,6 +233,10 @@ const char *value = PQgetvalue(statement->result, tuple, i); lua_push_type_t lua_push = postgresql_to_lua_push(PQftype(statement->result, i)); + /* + * data is returned as strings from PSQL + */ + if (lua_push == LUA_PUSH_NIL) { if (named_columns) { LUA_PUSH_ATTRIB_NIL(name); @@ -218,6 +266,10 @@ LUA_PUSH_ARRAY_STRING(d, value); } } else if (lua_push == LUA_PUSH_BOOLEAN) { + /* + * booleans are returned as a string + * either 't' or 'f' + */ int val = value[0] == 't' ? 1 : 0; if (named_columns) { @@ -234,15 +286,23 @@ return 1; } - +/* + * array = statement:fetch() + */ static int statement_fetch(lua_State *L) { return statement_fetch_impl(L, 0); } +/* + * hashmap = statement:fetchtable() + */ static int statement_fetchtable(lua_State *L) { return statement_fetch_impl(L, 1); } +/* + * __gc + */ static int statement_gc(lua_State *L) { /* always free the handle */ statement_close(L); @@ -250,19 +310,6 @@ return 0; } - -static const luaL_Reg statement_methods[] = { - {"close", statement_close}, - {"execute", statement_execute}, - {"fetch", statement_fetch}, - {"fetchtable", statement_fetchtable}, - {NULL, NULL} -}; - -static const luaL_Reg statement_class_methods[] = { - {NULL, NULL} -}; - int dbd_postgresql_statement_create(lua_State *L, connection_t *conn, const char *sql_query) { statement_t *statement = NULL; ExecStatusType status; @@ -270,11 +317,18 @@ char *new_sql; char name[IDLEN]; + /* + * convert SQL string into a PSQL API compatible SQL statement + */ new_sql = replace_placeholders(L, sql_query); snprintf(name, IDLEN, "%017u", ++conn->statement_id); result = PQprepare(conn->postgresql, name, new_sql, 0, NULL); + + /* + * free converted statement after use + */ free(new_sql); if (!result) { @@ -305,6 +359,18 @@ } int dbd_postgresql_statement(lua_State *L) { + static const luaL_Reg statement_methods[] = { + {"close", statement_close}, + {"execute", statement_execute}, + {"fetch", statement_fetch}, + {"fetchtable", statement_fetchtable}, + {NULL, NULL} + }; + + static const luaL_Reg statement_class_methods[] = { + {NULL, NULL} + }; + luaL_newmetatable(L, DBD_POSTGRESQL_STATEMENT); luaL_register(L, 0, statement_methods); lua_pushvalue(L,-1); diff -r 408291a6eb3e -r c4f02fc67e5a dbd/sqlite3/connection.c --- a/dbd/sqlite3/connection.c Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/sqlite3/connection.c Sun Nov 23 04:12:04 2008 +0000 @@ -2,6 +2,9 @@ int dbd_sqlite3_statement_create(lua_State *L, connection_t *conn, const char *sql_query); +/* + * connection = DBD.SQLite3.New(dbfile) + */ static int connection_new(lua_State *L) { int n = lua_gettop(L); @@ -28,18 +31,14 @@ return 1; } +/* + * success = connection:close() + */ static int connection_close(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION); int disconnect = 0; if (conn->sqlite) { -#if 0 - sqlite3_stmt *stmt; - - while((stmt = sqlite3_next_stmt(conn->sqlite, NULL)) != 0){ - sqlite3_finalize(stmt); - } -#endif if (sqlite3_close(conn->sqlite) == SQLITE_OK) { disconnect = 1; } @@ -49,6 +48,9 @@ return 1; } +/* + * ok = connection:ping() + */ static int connection_ping(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION); int ok = 0; @@ -61,6 +63,9 @@ return 1; } +/* + * statement = connection:prepare(sql_str) + */ static int connection_prepare(lua_State *L) { connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION); @@ -72,7 +77,9 @@ return 1; } - +/* + * __gc + */ static int connection_gc(lua_State *L) { /* always close the connection */ connection_close(L); @@ -80,19 +87,25 @@ return 0; } -static const luaL_Reg connection_methods[] = { - {"close", connection_close}, - {"ping", connection_ping}, - {"prepare", connection_prepare}, - {NULL, NULL} -}; +int dbd_sqlite3_connection(lua_State *L) { + /* + * instance methods + */ + static const luaL_Reg connection_methods[] = { + {"close", connection_close}, + {"ping", connection_ping}, + {"prepare", connection_prepare}, + {NULL, NULL} + }; -static const luaL_Reg connection_class_methods[] = { - {"New", connection_new}, - {NULL, NULL} -}; + /* + * class methods + */ + static const luaL_Reg connection_class_methods[] = { + {"New", connection_new}, + {NULL, NULL} + }; -int dbd_sqlite3_connection(lua_State *L) { luaL_newmetatable(L, DBD_SQLITE_CONNECTION); luaL_register(L, 0, connection_methods); lua_pushvalue(L,-1); diff -r 408291a6eb3e -r c4f02fc67e5a dbd/sqlite3/dbd_sqlite3.h --- a/dbd/sqlite3/dbd_sqlite3.h Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/sqlite3/dbd_sqlite3.h Sun Nov 23 04:12:04 2008 +0000 @@ -4,10 +4,16 @@ #define DBD_SQLITE_CONNECTION "DBD.SQLite3.Connection" #define DBD_SQLITE_STATEMENT "DBD.SQLite3.Statement" +/* + * connection object + */ typedef struct _connection { sqlite3 *sqlite; } connection_t; +/* + * statement object + */ typedef struct _statement { sqlite3_stmt *stmt; sqlite3 *sqlite; diff -r 408291a6eb3e -r c4f02fc67e5a dbd/sqlite3/main.c --- a/dbd/sqlite3/main.c Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/sqlite3/main.c Sun Nov 23 04:12:04 2008 +0000 @@ -3,6 +3,9 @@ int dbd_sqlite3_connection(lua_State *L); int dbd_sqlite3_statement(lua_State *L); +/* + * library entry point + */ int luaopen_dbdsqlite3(lua_State *L) { dbd_sqlite3_connection(L); dbd_sqlite3_statement(L); diff -r 408291a6eb3e -r c4f02fc67e5a dbd/sqlite3/statement.c --- a/dbd/sqlite3/statement.c Sun Nov 23 01:29:09 2008 +0000 +++ b/dbd/sqlite3/statement.c Sun Nov 23 04:12:04 2008 +0000 @@ -1,5 +1,8 @@ #include "dbd_sqlite3.h" +/* + * Converts SQLite types to Lua types + */ static lua_push_type_t sqlite_to_lua_push(unsigned int sqlite_type) { lua_push_type_t lua_type; @@ -23,6 +26,9 @@ return lua_type; } +/* + * runs sqlite3_step on a statement handle + */ static int step(statement_t *statement) { int res = sqlite3_step(statement->stmt); @@ -37,6 +43,9 @@ return 0; } +/* + * success = statement:close() + */ static int statement_close(lua_State *L) { statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_SQLITE_STATEMENT); int ok = 0; @@ -52,11 +61,19 @@ return 1; } +/* + * success = statement:execute(...) + */ static 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; + /* + * reset the handle before binding params + * this wil be a NOP if the handle has not + * been executed + */ if (sqlite3_reset(statement->stmt) != SQLITE_OK) { lua_pushboolean(L, 0); return 1; @@ -84,11 +101,18 @@ return 1; } +/* + * must be called after an execute + */ static int statement_fetch_impl(lua_State *L, int named_columns) { statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_SQLITE_STATEMENT); int num_columns; if (!statement->more_data) { + /* + * Result set is empty, or not result set returned + */ + lua_pushnil(L); return 1; } @@ -147,10 +171,18 @@ luaL_error(L, "Unknown push type in result set"); } } + } else { + /* + * no columns returned by statement? + */ + lua_pushnil(L); } if (step(statement) == 0) { if (sqlite3_reset(statement->stmt) != SQLITE_OK) { + /* + * reset needs to be called to retrieve the 'real' error message + */ luaL_error(L, "Failed to fetch statement: %s", sqlite3_errmsg(statement->sqlite)); } } @@ -158,15 +190,23 @@ return 1; } - +/* + * array = statement:fetch() + */ static int statement_fetch(lua_State *L) { return statement_fetch_impl(L, 0); } +/* + * hashmap = statement:fetchtable() + */ static int statement_fetchtable(lua_State *L) { return statement_fetch_impl(L, 1); } +/* + * __gc + */ static int statement_gc(lua_State *L) { /* always free the handle */ statement_close(L); @@ -174,19 +214,6 @@ return 0; } - -static const luaL_Reg statement_methods[] = { - {"close", statement_close}, - {"execute", statement_execute}, - {"fetch", statement_fetch}, - {"fetchtable", statement_fetchtable}, - {NULL, NULL} -}; - -static const luaL_Reg statement_class_methods[] = { - {NULL, NULL} -}; - int dbd_sqlite3_statement_create(lua_State *L, connection_t *conn, const char *sql_query) { statement_t *statement = NULL; @@ -208,6 +235,18 @@ } int dbd_sqlite3_statement(lua_State *L) { + static const luaL_Reg statement_methods[] = { + {"close", statement_close}, + {"execute", statement_execute}, + {"fetch", statement_fetch}, + {"fetchtable", statement_fetchtable}, + {NULL, NULL} + }; + + static const luaL_Reg statement_class_methods[] = { + {NULL, NULL} + }; + luaL_newmetatable(L, DBD_SQLITE_STATEMENT); luaL_register(L, 0, statement_methods); lua_pushvalue(L,-1);