Project

General

Profile

Feature #1747 ยป 0042-luasql-Update-to-version-2.7.0.patch

Marko Lindqvist, 11/17/2025 07:52 PM

View differences:

dependencies/luasql/Version.txt
Sources here are from luasql git tag 2.6.0
(https://github.com/lunarmodules/luasql/tree/2.6.0)
Some modifications have been done to them, but as of 08-Oct-22
all our modifications have been accepted to the upstream.
Sources here are from luasql git tag 2.7.0
(https://github.com/lunarmodules/luasql/tree/2.7.0)
Some modifications have been done to them:
- Commit 10ed75b36bf909f57b3c1a070dd87669c323cff0 backported
- Fixed compile error on ls_sqlite3.c raw_readparams_table()
Fix has been submitted to upstream.
Only the files needed by freeciv are included here, not entire luasql
source directory hierarchy.
dependencies/luasql/src/ls_mysql.c
luaL_argcheck (L, cur != NULL, 1, LUASQL_PREFIX"cursor expected");
if (cur->closed) {
lua_pushboolean (L, 0);
return 1;
lua_pushstring (L, "Cursor is already closed");
return 2;
}
cur_nullify (L, cur);
lua_pushboolean (L, 1);
......
** Create a new Cursor object and push it on top of the stack.
*/
static int create_cursor (lua_State *L, MYSQL *my_conn, int conn, MYSQL_RES *result, int cols) {
cur_data *cur = (cur_data *)lua_newuserdata(L, sizeof(cur_data));
cur_data *cur = (cur_data *)LUASQL_NEWUD(L, sizeof(cur_data));
luasql_setmeta (L, LUASQL_CURSOR_MYSQL);
/* fill in structure */
......
luaL_argcheck (L, conn != NULL, 1, LUASQL_PREFIX"connection expected");
if (conn->closed) {
lua_pushboolean (L, 0);
return 1;
lua_pushstring (L, "Connection is already closed");
return 2;
}
conn_gc (L);
/* Nullify structure fields. */
conn->closed = 1;
luaL_unref (L, LUA_REGISTRYINDEX, conn->env);
mysql_close (conn->my_conn);
lua_pushboolean (L, 1);
return 1;
}
......
** Create a new Connection object and push it on top of the stack.
*/
static int create_connection (lua_State *L, int env, MYSQL *const my_conn) {
conn_data *conn = (conn_data *)lua_newuserdata(L, sizeof(conn_data));
conn_data *conn = (conn_data *)LUASQL_NEWUD(L, sizeof(conn_data));
luasql_setmeta (L, LUASQL_CONNECTION_MYSQL);
/* fill in structure */
......
**
*/
static int env_gc (lua_State *L) {
env_data *env= (env_data *)luaL_checkudata (L, 1, LUASQL_ENVIRONMENT_MYSQL); if (env != NULL && !(env->closed))
env_data *env= (env_data *)luaL_checkudata (L, 1, LUASQL_ENVIRONMENT_MYSQL);
if (env != NULL && !(env->closed)) {
env->closed = 1;
mysql_library_end();
}
return 0;
}
......
luaL_argcheck (L, env != NULL, 1, LUASQL_PREFIX"environment expected");
if (env->closed) {
lua_pushboolean (L, 0);
return 1;
lua_pushstring(L, "Environment is already closed");
return 2;
}
mysql_library_end();
env->closed = 1;
mysql_library_end();
lua_pushboolean (L, 1);
return 1;
}
......
*/
static void create_metatables (lua_State *L) {
struct luaL_Reg environment_methods[] = {
{"__gc", env_gc},
{"close", env_close},
{"connect", env_connect},
{"__gc", env_gc},
{"__close", env_gc},
{"close", env_close},
{"connect", env_connect},
{NULL, NULL},
};
struct luaL_Reg connection_methods[] = {
{"__gc", conn_gc},
{"close", conn_close},
{"ping", conn_ping},
{"escape", escape_string},
{"execute", conn_execute},
{"commit", conn_commit},
{"rollback", conn_rollback},
{"setautocommit", conn_setautocommit},
{"__gc", conn_gc},
{"__close", conn_gc},
{"close", conn_close},
{"ping", conn_ping},
{"escape", escape_string},
{"execute", conn_execute},
{"commit", conn_commit},
{"rollback", conn_rollback},
{"setautocommit", conn_setautocommit},
{"getlastautoid", conn_getlastautoid},
{NULL, NULL},
};
struct luaL_Reg cursor_methods[] = {
{"__gc", cur_gc},
{"__close", cur_gc},
{"close", cur_close},
{"getcolnames", cur_getcolnames},
{"getcoltypes", cur_getcoltypes},
......
** Creates an Environment and returns it.
*/
static int create_environment (lua_State *L) {
env_data *env = (env_data *)lua_newuserdata(L, sizeof(env_data));
env_data *env = (env_data *)LUASQL_NEWUD(L, sizeof(env_data));
luasql_setmeta (L, LUASQL_ENVIRONMENT_MYSQL);
/* fill in structure */
dependencies/luasql/src/ls_odbc.c
SQLHSTMT hstmt; /* statement handle */
SQLSMALLINT numparams; /* number of input parameters */
int paramtypes; /* reference to param type table */
param_data *params; /* array of parater data */
param_data *params; /* array of parameter data */
} stmt_data;
typedef struct {
......
case SQL_DATE: case SQL_INTERVAL: case SQL_TIMESTAMP:
case SQL_LONGVARCHAR:
case SQL_WCHAR: case SQL_WVARCHAR: case SQL_WLONGVARCHAR:
#if (ODBCVER >= 0x0350)
case SQL_GUID:
#endif
return "string";
case SQL_BIGINT: case SQL_TINYINT:
case SQL_INTEGER: case SQL_SMALLINT:
......
** hstmt: statement handle
** i: column number
** Returns:
** 0 if successfull, non-zero otherwise;
** 0 if successful, non-zero otherwise;
*/
static int push_column(lua_State *L, int coltypes, const SQLHSTMT hstmt,
SQLUSMALLINT i) {
......
}
}
/*
** Cursor object collector function
*/
static int cur_gc (lua_State *L) {
cur_data *cur = (cur_data *) luaL_checkudata (L, 1, LUASQL_CURSOR_ODBC);
if (cur != NULL && !(cur->closed))
cur_shut(L, cur);
return 0;
}
/*
** Closes a cursor.
*/
......
if (cur->closed) {
lua_pushboolean (L, 0);
return 1;
lua_pushstring (L, "Cursor is already closed");
return 2;
}
if((res = cur_shut(L, cur)) != 0) {
......
lock_obj(L, stmt_i, stmt);
cur = (cur_data *) lua_newuserdata(L, sizeof(cur_data));
cur = (cur_data *) LUASQL_NEWUD(L, sizeof(cur_data));
luasql_setmeta (L, LUASQL_CURSOR_ODBC);
/* fill in structure */
......
luaL_argcheck (L, conn != NULL, 1, LUASQL_PREFIX"connection expected");
if (conn->closed) {
lua_pushboolean (L, 0);
return 1;
lua_pushstring (L, "Connection is already closed");
return 2;
}
if (conn->lock > 0) {
return luaL_error (L, LUASQL_PREFIX"there are open statements/cursors");
lua_pushboolean (L, 0);
lua_pushstring (L, "There are open cursors");
return 2;
}
/* Decrement connection counter on environment object */
......
return ret;
}
stmt = (stmt_data *)lua_newuserdata(L, sizeof(stmt_data));
stmt = (stmt_data *)LUASQL_NEWUD(L, sizeof(stmt_data));
memset(stmt, 0, sizeof(stmt_data));
stmt->closed = 0;
......
*/
static int create_connection (lua_State *L, int o, env_data *env, SQLHDBC hdbc)
{
conn_data *conn = (conn_data *)lua_newuserdata(L, sizeof(conn_data));
conn_data *conn = (conn_data *)LUASQL_NEWUD(L, sizeof(conn_data));
/* set auto commit mode */
SQLRETURN ret = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT,
......
** source: data source
** user, pass: data source authentication information
** Lua Returns:
** connection object if successfull
** connection object if successful
** nil and error message otherwise.
*/
static int env_connect (lua_State *L) {
......
return create_connection (L, 1, env, hdbc);
}
/*
** Environment object collector function
*/
static int env_gc (lua_State *L)
{
SQLRETURN ret;
env_data *env = (env_data *)luaL_checkudata(L, 1, LUASQL_ENVIRONMENT_ODBC);
if (env != NULL && !(env->closed)) {
env->closed = 1;
ret = SQLFreeHandle (hENV, env->henv);
if (error (ret)) {
int ret2 = fail (L, hENV, env->henv);
env->henv = NULL;
return ret2;
}
}
return 0;
}
/*
** Closes an environment object
*/
......
luaL_argcheck (L, env != NULL, 1, LUASQL_PREFIX"environment expected");
if (env->closed) {
lua_pushboolean (L, 0);
return 1;
lua_pushstring (L, "Environment is already closed");
return 2;
}
if (env->lock > 0) {
return luaL_error (L, LUASQL_PREFIX"there are open connections");
lua_pushboolean (L, 0);
lua_pushstring (L, "There are open connections");
return 2;
}
env->closed = 1;
......
*/
static void create_metatables (lua_State *L) {
struct luaL_Reg environment_methods[] = {
{"__gc", env_close}, /* Should this method be changed? */
{"__gc", env_gc},
{"__close", env_gc},
{"close", env_close},
{"connect", env_connect},
{NULL, NULL},
};
struct luaL_Reg connection_methods[] = {
{"__gc", conn_close}, /* Should this method be changed? */
{"__close", conn_close},
{"close", conn_close},
{"prepare", conn_prepare},
{"execute", conn_execute},
......
};
struct luaL_Reg statement_methods[] = {
{"__gc", stmt_close}, /* Should this method be changed? */
{"__close", stmt_close},
{"close", stmt_close},
{"execute", stmt_execute},
{"getparamtypes", stmt_paramtypes},
{NULL, NULL},
};
struct luaL_Reg cursor_methods[] = {
{"__gc", cur_close}, /* Should this method be changed? */
{"__gc", cur_gc}, /* Should this method be changed? */
{"__close", cur_gc},
{"close", cur_close},
{"fetch", cur_fetch},
{"getcoltypes", cur_coltypes},
......
return ret;
}
env = (env_data *)lua_newuserdata (L, sizeof (env_data));
env = (env_data *)LUASQL_NEWUD (L, sizeof (env_data));
luasql_setmeta (L, LUASQL_ENVIRONMENT_ODBC);
/* fill in structure */
env->closed = 0;
dependencies/luasql/src/ls_postgres.c
luaL_argcheck (L, cur != NULL, 1, LUASQL_PREFIX"cursor expected");
if (cur->closed) {
lua_pushboolean (L, 0);
return 1;
lua_pushstring (L, "cursor is already closed");
return 2;
}
cur_nullify (L, cur); /* == cur_gc (L); */
cur_nullify (L, cur);
lua_pushboolean (L, 1);
return 1;
}
......
** Create a new Cursor object and push it on top of the stack.
*/
static int create_cursor (lua_State *L, int conn, PGresult *result) {
cur_data *cur = (cur_data *)lua_newuserdata(L, sizeof(cur_data));
cur_data *cur = (cur_data *)LUASQL_NEWUD(L, sizeof(cur_data));
luasql_setmeta (L, LUASQL_CURSOR_PG);
/* fill in structure */
......
luaL_argcheck (L, conn != NULL, 1, LUASQL_PREFIX"connection expected");
if (conn->closed) {
lua_pushboolean (L, 0);
return 1;
lua_pushstring(L, "Connection is already closed");
return 2;
}
conn_gc (L);
conn->closed = 1;
luaL_unref (L, LUA_REGISTRYINDEX, conn->env);
PQfinish (conn->pg_conn);
lua_pushboolean (L, 1);
return 1;
}
......
** Create a new Connection object and push it on top of the stack.
*/
static int create_connection (lua_State *L, int env, PGconn *const pg_conn) {
conn_data *conn = (conn_data *)lua_newuserdata(L, sizeof(conn_data));
conn_data *conn = (conn_data *)LUASQL_NEWUD(L, sizeof(conn_data));
luasql_setmeta (L, LUASQL_CONNECTION_PG);
/* fill in structure */
......
luaL_argcheck (L, env != NULL, 1, LUASQL_PREFIX"environment expected");
if (env->closed) {
lua_pushboolean (L, 0);
return 1;
lua_pushstring (L, "Environment is already closed");
return 2;
}
env_gc (L);
env->closed = 1;
lua_pushboolean (L, 1);
return 1;
}
......
static void create_metatables (lua_State *L) {
struct luaL_Reg environment_methods[] = {
{"__gc", env_gc},
{"__close", env_gc},
{"close", env_close},
{"connect", env_connect},
{NULL, NULL},
};
struct luaL_Reg connection_methods[] = {
{"__gc", conn_gc},
{"__close", conn_gc},
{"close", conn_close},
{"escape", conn_escape},
{"execute", conn_execute},
......
};
struct luaL_Reg cursor_methods[] = {
{"__gc", cur_gc},
{"__close", cur_gc},
{"close", cur_close},
{"getcolnames", cur_getcolnames},
{"getcoltypes", cur_getcoltypes},
......
** Creates an Environment and returns it.
*/
static int create_environment (lua_State *L) {
env_data *env = (env_data *)lua_newuserdata(L, sizeof(env_data));
env_data *env = (env_data *)LUASQL_NEWUD(L, sizeof(env_data));
luasql_setmeta (L, LUASQL_ENVIRONMENT_PG);
/* fill in structure */
dependencies/luasql/src/ls_sqlite3.c
/*
** Finalizes the vm
** Return nil + errmsg or nil in case of sucess
** Return nil + errmsg or nil in case of success
*/
static int finalize(lua_State *L, cur_data *cur) {
const char *errmsg;
......
cur_data *cur = (cur_data *)luaL_checkudata(L, 1, LUASQL_CURSOR_SQLITE);
luaL_argcheck(L, cur != NULL, 1, LUASQL_PREFIX"cursor expected");
if (cur->closed) {
lua_pushboolean(L, 0);
return 1;
lua_pushboolean (L, 0);
lua_pushstring(L, "cursor is already closed");
return 2;
}
cur->closed = 1;
sqlite3_finalize(cur->sql_vm);
cur_nullify(L, cur);
lua_pushboolean(L, 1);
......
sqlite3_stmt *sql_vm, int numcols)
{
int i;
cur_data *cur = (cur_data*)lua_newuserdata(L, sizeof(cur_data));
cur_data *cur = (cur_data*)LUASQL_NEWUD(L, sizeof(cur_data));
luasql_setmeta (L, LUASQL_CURSOR_SQLITE);
/* increment cursor count for the connection creating this cursor */
......
conn_data *conn = (conn_data *)luaL_checkudata(L, 1, LUASQL_CONNECTION_SQLITE);
if (conn != NULL && !(conn->closed))
{
if (conn->cur_counter > 0)
return luaL_error (L, LUASQL_PREFIX"there are open cursors");
/* Nullify structure fields. */
conn->closed = 1;
luaL_unref(L, LUA_REGISTRYINDEX, conn->env);
......
conn_data *conn = (conn_data *)luaL_checkudata(L, 1, LUASQL_CONNECTION_SQLITE);
luaL_argcheck (L, conn != NULL, 1, LUASQL_PREFIX"connection expected");
if (conn->closed)
{
lua_pushboolean(L, 0);
return 1;
}
conn_gc(L);
{
lua_pushboolean(L, 0);
lua_pushstring(L, "Connection is already closed");
return 2;
}
if (conn->cur_counter > 0)
{
lua_pushboolean(L, 0);
lua_pushstring(L, "There are open cursors");
return 2;
}
conn->closed = 1;
lua_pushboolean(L, 1);
return 1;
}
......
return 1;
}
/*
** Bind one parameter.
** Supported are the data types nil, string, boolean, number.
*/
static int set_param(lua_State *L, sqlite3_stmt *vm, int param_nr, int arg)
{
int tt = lua_type(L, arg);
int rc = 0;
switch (tt) {
case LUA_TNIL:
rc = sqlite3_bind_null(vm, param_nr);
break;
case LUA_TSTRING: {
size_t s_len;
const char *s = lua_tolstring(L, arg, &s_len);
rc = sqlite3_bind_null(vm, param_nr);
rc = sqlite3_bind_text(vm, param_nr, s, s_len, SQLITE_TRANSIENT);
break;
}
case LUA_TBOOLEAN: {
int val = lua_tointeger(L, arg);
rc = sqlite3_bind_int(vm, param_nr, val);
break;
}
case LUA_TNUMBER: {
#if defined(lua_isinteger)
if (lua_isinteger(L, arg)) {
lua_Integer val = lua_tointeger(L, arg);
rc = sqlite3_bind_int64(vm, param_nr, val);
} else {
#endif
double val = lua_tonumber(L, arg);
rc = sqlite3_bind_double(vm, param_nr, val);
#if defined(lua_isinteger)
}
#endif
break;
}
default:
luaL_error(L, LUASQL_PREFIX"unhandled data type %s in parameter binding",
lua_typename(L, tt));
}
return rc;
}
static int raw_readparams_args(lua_State *L, sqlite3_stmt *vm, int arg, int ltop)
{
int param_count, param_nr, rc = 0;
param_count = sqlite3_bind_parameter_count(vm);
if (ltop - arg + 1 != param_count)
luaL_error(L, LUASQL_PREFIX"wrong number of parameters: expected=%d, given=%d",
param_count, ltop - arg + 1);
for (param_nr=1; param_nr <= param_count; param_nr ++, arg ++) {
rc = set_param(L, vm, param_nr, arg);
if (rc)
break;
}
return rc;
}
/*
** Bind all parameters from the given table.
** The table indices can be integers or strings.
** Unbound parameters, or duplicate bindings are not detected.
*/
static int raw_readparams_table(lua_State *L, sqlite3_stmt *vm, int arg)
{
int param_nr, rc = 0;
lua_pushnil(L);
while (lua_next(L, arg)) { // [arg]=table, [-2]=key, [-1]=val
#if defined(lua_isinteger)
int tt =
#endif
lua_type(L, -2);
#if defined(lua_isinteger)
if (tt == LUA_TNUMBER && lua_isinteger(L, -2)) {
param_nr = lua_tointeger(L, -2);
} else {
#endif
const char *param_name = lua_tostring(L, -2);
param_nr = sqlite3_bind_parameter_index(vm, param_name);
if (param_nr == 0)
luaL_error(L, LUASQL_PREFIX"binding to invalid parameter name %s\n",
param_name);
#if defined(lua_isinteger)
}
#endif
set_param(L, vm, param_nr, -1);
lua_pop(L, 1);
}
return rc;
}
/*
** Execute an SQL statement.
** Return a Cursor object if the statement is a query, otherwise
......
return luasql_faildirect(L, errmsg);
}
/* process first result to retrive query information and type */
/* Bind parameters (if any) */
int ltop = lua_gettop(L);
if (ltop > 2) {
if (ltop == 3 && lua_type(L, 3) == LUA_TTABLE) {
res = raw_readparams_table(L, vm, 3);
} else if (ltop >= 3) {
res = raw_readparams_args(L, vm, 3, ltop);
} else {
luaL_error(L, LUASQL_PREFIX"parameters are either one table or positional");
}
if (res)
return res;
}
/* process first result to retrieve query information and type */
res = sqlite3_step(vm);
numcols = sqlite3_column_count(vm);
......
*/
static int create_connection(lua_State *L, int env, sqlite3 *sql_conn)
{
conn_data *conn = (conn_data*)lua_newuserdata(L, sizeof(conn_data));
conn_data *conn = (conn_data*)LUASQL_NEWUD(L, sizeof(conn_data));
luasql_setmeta(L, LUASQL_CONNECTION_SQLITE);
/* fill in structure */
......
luaL_argcheck(L, env != NULL, 1, LUASQL_PREFIX"environment expected");
if (env->closed) {
lua_pushboolean(L, 0);
return 1;
lua_pushstring(L, "env is already closed");
return 2;
}
env_gc(L);
env->closed = 1;
lua_pushboolean(L, 1);
return 1;
}
......
{
struct luaL_Reg environment_methods[] = {
{"__gc", env_gc},
{"__close", env_gc},
{"close", env_close},
{"connect", env_connect},
{NULL, NULL},
};
struct luaL_Reg connection_methods[] = {
{"__gc", conn_gc},
{"__close", conn_gc},
{"close", conn_close},
{"escape", conn_escape},
// {"prepare", conn_prepare},
{"execute", conn_execute},
{"commit", conn_commit},
{"rollback", conn_rollback},
......
};
struct luaL_Reg cursor_methods[] = {
{"__gc", cur_gc},
{"__close", cur_gc},
{"close", cur_close},
{"getcolnames", cur_getcolnames},
{"getcoltypes", cur_getcoltypes},
......
*/
static int create_environment (lua_State *L)
{
env_data *env = (env_data *)lua_newuserdata(L, sizeof(env_data));
env_data *env = (env_data *)LUASQL_NEWUD(L, sizeof(env_data));
luasql_setmeta(L, LUASQL_ENVIRONMENT_SQLITE);
/* fill in structure */
dependencies/luasql/src/luasql.c
*/
LUASQL_API void luasql_set_info (lua_State *L) {
lua_pushliteral (L, "_COPYRIGHT");
lua_pushliteral (L, "Copyright (C) 2003-2020 Kepler Project");
lua_pushliteral (L, "Copyright (C) 2003-2025 Kepler Project");
lua_settable (L, -3);
lua_pushliteral (L, "_DESCRIPTION");
lua_pushliteral (L, "LuaSQL is a simple interface from Lua to a DBMS");
lua_settable (L, -3);
lua_pushliteral (L, "_VERSION");
lua_pushliteral (L, "LuaSQL 2.6.0 (for "LUA_VERSION")");
lua_pushliteral (L, "LuaSQL 2.7.0 (for "LUA_VERSION")");
lua_settable (L, -3);
}
dependencies/luasql/src/luasql.h
#define LUASQL_CONNECTION "Each driver must have a connection metatable"
#define LUASQL_CURSOR "Each driver must have a cursor metatable"
// Macro to handle userdata creation across Lua versions
#if LUA_VERSION_NUM >= 504
#define LUASQL_NEWUD(L, size) lua_newuserdatauv(L, size, 0)
#else
#define LUASQL_NEWUD(L, size) lua_newuserdata(L, size)
#endif
LUASQL_API int luasql_faildirect (lua_State *L, const char *err);
LUASQL_API int luasql_failmsg (lua_State *L, const char *err, const char *m);
LUASQL_API int luasql_createmeta (lua_State *L, const char *name, const luaL_Reg *methods);
    (1-1/1)