Project

Profile

Help

HostedRedmine.com has moved to the Planio platform. All logins and passwords remained the same. All users will be able to login and use Redmine just as before. *Read more...*

Feature #824990 ยป 0053-Update-included-luasql-files-to-luasql-2.5.0-level.patch

Marko Lindqvist, 2019-07-04 02:58 PM

View differences:

dependencies/luasql/Version
Sources here are fron luasql git tag v2.4.0
(https://github.com/keplerproject/luasql/tree/v2.4.0)
Sources here are fron luasql git tag 2.5.0
(https://github.com/keplerproject/luasql/tree/2.5.0)
Only the files needed by freeciv are included here, not entire luasql
source directory hierarchy.
dependencies/luasql/src/ls_mysql.c
}
/*
** Seeks to an arbitrary row in a query result set.
*/
static int cur_seek (lua_State *L) {
cur_data *cur = getcursor (L);
lua_Integer rownum = luaL_checkinteger (L, 2);
mysql_data_seek (cur->my_res, rownum);
return 0;
}
/*
** Create a new Cursor object and push it on top of the stack.
*/
......
{"getcoltypes", cur_getcoltypes},
{"fetch", cur_fetch},
{"numrows", cur_numrows},
{"seek", cur_seek},
{NULL, NULL},
};
luasql_createmeta (L, LUASQL_ENVIRONMENT_MYSQL, environment_methods);
......
#else
lua_pushliteral (L, MYSQL_SERVER_VERSION);
#endif
/*lua_pushliteral (L, MYSQL_SERVER_VERSION);*/
lua_settable (L, -3);
return 1;
}
dependencies/luasql/src/ls_odbc.c
#include <string.h>
#include <time.h>
#if defined(_WIN32)
#include <windows.h>
#include <sqlext.h>
#elif defined(INFORMIX)
#include "infxcli.h"
#elif defined(UNIXODBC)
#include "sql.h"
#include "sqltypes.h"
#include "sqlext.h"
#endif
#include "lua.h"
#include "lauxlib.h"
......
#define LUASQL_ENVIRONMENT_ODBC "ODBC environment"
#define LUASQL_CONNECTION_ODBC "ODBC connection"
#define LUASQL_STATEMENT_ODBC "ODBC statement"
#define LUASQL_CURSOR_ODBC "ODBC cursor"
/* holds data for paramter binding */
typedef struct {
SQLPOINTER buf;
SQLINTEGER len;
SQLINTEGER type;
} param_data;
/* general form of the driver objects */
typedef struct {
short closed;
int conn_counter;
SQLHENV henv; /* environment handle */
} env_data;
short closed;
int lock;
} obj_data;
typedef struct {
short closed;
int lock; /* lock count for open connections */
SQLHENV henv; /* environment handle */
} env_data;
typedef struct {
short closed;
int cur_counter;
int env; /* reference to environment */
SQLHDBC hdbc; /* database connection handle */
short closed;
int lock; /* lock count for open statements */
env_data *env; /* the connection's environment */
SQLHDBC hdbc; /* database connection handle */
} conn_data;
typedef struct {
short closed;
int lock; /* lock count for open cursors */
unsigned char hidden; /* these statement was created indirectly */
conn_data *conn; /* the statement's connection */
SQLHSTMT hstmt; /* statement handle */
SQLSMALLINT numparams; /* number of input parameters */
int paramtypes; /* reference to param type table */
param_data *params; /* array of parater data */
} stmt_data;
typedef struct {
short closed;
int conn; /* reference to connection */
int numcols; /* number of columns */
int coltypes, colnames; /* reference to column information tables */
SQLHSTMT hstmt; /* statement handle */
short closed;
stmt_data *stmt; /* the cursor's statement */
int numcols; /* number of columns */
int coltypes, colnames; /* reference to column information tables */
} cur_data;
......
#define hENV SQL_HANDLE_ENV
#define hSTMT SQL_HANDLE_STMT
#define hDBC SQL_HANDLE_DBC
#define error(a) ((a) != SQL_SUCCESS && (a) != SQL_SUCCESS_WITH_INFO)
static int error(SQLRETURN a)
{
return (a != SQL_SUCCESS) && (a != SQL_SUCCESS_WITH_INFO) && (a != SQL_NO_DATA);
}
LUASQL_API int luaopen_luasql_odbc (lua_State *L);
/*
** Registers a given C object in the registry to avoid GC
*/
static void luasql_registerobj(lua_State *L, int index, void *obj)
{
lua_pushvalue(L, index);
lua_pushlightuserdata(L, obj);
lua_pushvalue(L, -2);
lua_settable(L, LUA_REGISTRYINDEX);
lua_pop(L, 1);
}
/*
** Unregisters a given C object from the registry
*/
static void luasql_unregisterobj(lua_State *L, void *obj)
{
lua_pushlightuserdata(L, obj);
lua_pushnil(L);
lua_settable(L, LUA_REGISTRYINDEX);
}
static int lock_obj(lua_State *L, int indx, void *ptr)
{
obj_data *obj = (obj_data *)ptr;
luasql_registerobj(L, indx, obj);
return ++obj->lock;
}
static int unlock_obj(lua_State *L, void *ptr)
{
obj_data *obj = (obj_data *)ptr;
if(--obj->lock == 0) {
luasql_unregisterobj(L, obj);
}
return obj->lock;
}
/*
** Check for valid environment.
*/
static env_data *getenvironment (lua_State *L) {
env_data *env = (env_data *)luaL_checkudata (L, 1, LUASQL_ENVIRONMENT_ODBC);
luaL_argcheck (L, env != NULL, 1, LUASQL_PREFIX"environment expected");
luaL_argcheck (L, !env->closed, 1, LUASQL_PREFIX"environment is closed");
static env_data *getenvironment (lua_State *L, int i)
{
env_data *env = (env_data *)luaL_checkudata (L, i, LUASQL_ENVIRONMENT_ODBC);
luaL_argcheck (L, env != NULL, i, LUASQL_PREFIX"environment expected");
luaL_argcheck (L, !env->closed, i, LUASQL_PREFIX"environment is closed");
return env;
}
......
/*
** Check for valid connection.
*/
static conn_data *getconnection (lua_State *L) {
conn_data *conn = (conn_data *)luaL_checkudata (L, 1, LUASQL_CONNECTION_ODBC);
luaL_argcheck (L, conn != NULL, 1, LUASQL_PREFIX"connection expected");
luaL_argcheck (L, !conn->closed, 1, LUASQL_PREFIX"connection is closed");
static conn_data *getconnection (lua_State *L, int i)
{
conn_data *conn = (conn_data *)luaL_checkudata (L, i, LUASQL_CONNECTION_ODBC);
luaL_argcheck (L, conn != NULL, i, LUASQL_PREFIX"connection expected");
luaL_argcheck (L, !conn->closed, i, LUASQL_PREFIX"connection is closed");
return conn;
}
/*
** Check for valid connection.
*/
static stmt_data *getstatement (lua_State *L, int i)
{
stmt_data *stmt = (stmt_data *)luaL_checkudata (L, i, LUASQL_STATEMENT_ODBC);
luaL_argcheck (L, stmt != NULL, i, LUASQL_PREFIX"statement expected");
luaL_argcheck (L, !stmt->closed, i, LUASQL_PREFIX"statement is closed");
return stmt;
}
/*
** Check for valid cursor.
*/
static cur_data *getcursor (lua_State *L) {
cur_data *cursor = (cur_data *)luaL_checkudata (L, 1, LUASQL_CURSOR_ODBC);
luaL_argcheck (L, cursor != NULL, 1, LUASQL_PREFIX"cursor expected");
luaL_argcheck (L, !cursor->closed, 1, LUASQL_PREFIX"cursor is closed");
static cur_data *getcursor (lua_State *L, int i)
{
cur_data *cursor = (cur_data *)luaL_checkudata (L, i, LUASQL_CURSOR_ODBC);
luaL_argcheck (L, cursor != NULL, i, LUASQL_PREFIX"cursor expected");
luaL_argcheck (L, !cursor->closed, i, LUASQL_PREFIX"cursor is closed");
return cursor;
}
......
/*
** Fails with error message from ODBC
** Inputs:
** Inputs:
** type: type of handle used in operation
** handle: handle used in operation
*/
......
luaL_buffinit(L, &b);
i = 1;
while (1) {
ret = SQLGetDiagRec(type, handle, i, State, &NativeError, Msg,
ret = SQLGetDiagRec(type, handle, i, State, &NativeError, Msg,
sizeof(Msg), &MsgSize);
if (ret == SQL_NO_DATA) break;
luaL_addlstring(&b, (char*)Msg, MsgSize);
luaL_addchar(&b, '\n');
i++;
}
}
luaL_pushresult(&b);
return 2;
}
static param_data *malloc_stmt_params(SQLSMALLINT c)
{
param_data *p = (param_data *)malloc(sizeof(param_data)*c);
memset(p, 0, sizeof(param_data)*c);
return p;
}
static param_data *free_stmt_params(param_data *data, SQLSMALLINT c)
{
if(data != NULL) {
param_data *p = data;
for(; c>0; ++p, --c) {
free(p->buf);
}
free(data);
}
return NULL;
}
/*
** Shuts a statement
** Returns non-zero on error
*/
static int stmt_shut(lua_State *L, stmt_data *stmt)
{
SQLRETURN ret;
unlock_obj(L, stmt->conn);
stmt->closed = 1;
luaL_unref (L, LUA_REGISTRYINDEX, stmt->paramtypes);
stmt->paramtypes = LUA_NOREF;
stmt->params = free_stmt_params(stmt->params, stmt->numparams);
ret = SQLFreeHandle(hSTMT, stmt->hstmt);
if (error(ret)) {
return 1;
}
return 0;
}
/*
** Closes a cursor directly
** Returns non-zero on error
*/
static int cur_shut(lua_State *L, cur_data *cur)
{
/* Nullify structure fields. */
cur->closed = 1;
if (error(SQLCloseCursor(cur->stmt->hstmt))) {
return fail(L, hSTMT, cur->stmt->hstmt);
}
/* release col tables */
luaL_unref (L, LUA_REGISTRYINDEX, cur->colnames);
luaL_unref (L, LUA_REGISTRYINDEX, cur->coltypes);
/* release statement and, if hidden, shut it */
if(unlock_obj(L, cur->stmt) == 0) {
if(cur->stmt->hidden) {
return stmt_shut(L, cur->stmt);
}
}
return 0;
}
/*
** Returns the name of an equivalent lua type for a SQL type.
*/
static const char *sqltypetolua (const SQLSMALLINT type) {
switch (type) {
case SQL_UNKNOWN_TYPE: case SQL_CHAR: case SQL_VARCHAR:
case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP:
case SQL_DATE: case SQL_INTERVAL: case SQL_TIMESTAMP:
case SQL_UNKNOWN_TYPE: case SQL_CHAR: case SQL_VARCHAR:
case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP:
case SQL_DATE: case SQL_INTERVAL: case SQL_TIMESTAMP:
case SQL_LONGVARCHAR:
case SQL_WCHAR: case SQL_WVARCHAR: case SQL_WLONGVARCHAR:
return "string";
case SQL_BIGINT: case SQL_TINYINT:
case SQL_INTEGER: case SQL_SMALLINT:
case SQL_BIGINT: case SQL_TINYINT:
case SQL_INTEGER: case SQL_SMALLINT:
#if LUA_VERSION_NUM>=503
return "integer";
#endif
case SQL_NUMERIC: case SQL_DECIMAL:
case SQL_NUMERIC: case SQL_DECIMAL:
case SQL_FLOAT: case SQL_REAL: case SQL_DOUBLE:
return "number";
case SQL_BINARY: case SQL_VARBINARY: case SQL_LONGVARBINARY:
......
** Returns:
** 0 if successfull, non-zero otherwise;
*/
static int push_column(lua_State *L, int coltypes, const SQLHSTMT hstmt,
static int push_column(lua_State *L, int coltypes, const SQLHSTMT hstmt,
SQLUSMALLINT i) {
const char *tname;
char type;
......
/* deal with data according to type */
switch (type) {
/* nUmber */
case 'u': {
double num;
case 'u': {
SQLDOUBLE num;
SQLLEN got;
SQLRETURN rc = SQLGetData(hstmt, i, SQL_C_DOUBLE, &num, 0, &got);
if (error(rc))
......
#if LUA_VERSION_NUM>=503
/* iNteger */
case 'n': {
long int num;
SQLINTEGER num;
SQLLEN got;
SQLRETURN rc = SQLGetData(hstmt, i, SQL_C_SLONG, &num, 0, &got);
if (error(rc))
......
}
#endif
/* bOol */
case 'o': {
char b;
case 'o': {
SQLCHAR b;
SQLLEN got;
SQLRETURN rc = SQLGetData(hstmt, i, SQL_C_BIT, &b, 0, &got);
if (error(rc))
......
return 0;
}
/* sTring */
case 't':
case 't':
/* bInary */
case 'i': {
case 'i': {
SQLSMALLINT stype = (type == 't') ? SQL_C_CHAR : SQL_C_BINARY;
SQLLEN got;
char *buffer;
......
}
luaL_addsize(&b, got);
buffer = luaL_prepbuffer(&b);
rc = SQLGetData(hstmt, i, stype, buffer,
rc = SQLGetData(hstmt, i, stype, buffer,
LUAL_BUFFERSIZE, &got);
}
/* concat last chunk */
......
/*
** Get another row of the given cursor.
*/
static int cur_fetch (lua_State *L) {
cur_data *cur = (cur_data *) getcursor (L);
SQLHSTMT hstmt = cur->hstmt;
int ret;
SQLRETURN rc = SQLFetch(cur->hstmt);
if (rc == SQL_NO_DATA) {
lua_pushnil(L);
return 1;
} else if (error(rc)) return fail(L, hSTMT, hstmt);
static int cur_fetch (lua_State *L)
{
cur_data *cur = getcursor (L, 1);
SQLHSTMT hstmt = cur->stmt->hstmt;
int ret;
SQLRETURN rc = SQLFetch(hstmt);
if (rc == SQL_NO_DATA) {
/* automatically close cursor when end of resultset is reached */
if((ret = cur_shut(L, cur)) != 0) {
return ret;
}
lua_pushnil(L);
return 1;
} else {
if (error(rc)) {
return fail(L, hSTMT, hstmt);
}
}
if (lua_istable (L, 2)) {
SQLUSMALLINT i;
......
int alpha = strchr (opts, 'a') != NULL;
for (i = 1; i <= cur->numcols; i++) {
ret = push_column (L, cur->coltypes, hstmt, i);
if (ret)
if (ret) {
return ret;
}
if (alpha) {
lua_rawgeti (L, LUA_REGISTRYINDEX, cur->colnames);
lua_rawgeti (L, -1, i); /* gets column name */
......
lua_rawset (L, 2); /* table[name] = value */
lua_pop (L, 1); /* pops colnames table */
}
if (num)
if (num) {
lua_rawseti (L, 2, i);
else
} else {
lua_pop (L, 1); /* pops value */
}
}
lua_pushvalue (L, 2);
return 1; /* return table */
}
else {
} else {
SQLUSMALLINT i;
luaL_checkstack (L, cur->numcols, LUASQL_PREFIX"too many columns");
for (i = 1; i <= cur->numcols; i++) {
ret = push_column (L, cur->coltypes, hstmt, i);
if (ret)
if (ret) {
return ret;
}
}
return cur->numcols;
}
......
/*
** Closes a cursor.
*/
static int cur_close (lua_State *L) {
conn_data *conn;
static int cur_close (lua_State *L)
{
int res;
cur_data *cur = (cur_data *) luaL_checkudata (L, 1, LUASQL_CURSOR_ODBC);
SQLRETURN ret;
luaL_argcheck (L, cur != NULL, 1, LUASQL_PREFIX"cursor expected");
if (cur->closed) {
lua_pushboolean (L, 0);
return 1;
}
/* Nullify structure fields. */
cur->closed = 1;
ret = SQLCloseCursor(cur->hstmt);
if (error(ret))
return fail(L, hSTMT, cur->hstmt);
ret = SQLFreeHandle(hSTMT, cur->hstmt);
if (error(ret))
return fail(L, hSTMT, cur->hstmt);
/* Decrement cursor counter on connection object */
lua_rawgeti (L, LUA_REGISTRYINDEX, cur->conn);
conn = lua_touserdata (L, -1);
conn->cur_counter--;
luaL_unref (L, LUA_REGISTRYINDEX, cur->conn);
luaL_unref (L, LUA_REGISTRYINDEX, cur->colnames);
luaL_unref (L, LUA_REGISTRYINDEX, cur->coltypes);
return pass(L);
}
if((res = cur_shut(L, cur)) != 0) {
return res;
}
return pass(L);
}
/*
** Returns the table with column names.
*/
static int cur_colnames (lua_State *L) {
cur_data *cur = (cur_data *) getcursor (L);
cur_data *cur = (cur_data *) getcursor (L, 1);
lua_rawgeti (L, LUA_REGISTRYINDEX, cur->colnames);
return 1;
}
......
** Returns the table with column types.
*/
static int cur_coltypes (lua_State *L) {
cur_data *cur = (cur_data *) getcursor (L);
cur_data *cur = (cur_data *) getcursor (L, 1);
lua_rawgeti (L, LUA_REGISTRYINDEX, cur->coltypes);
return 1;
}
......
/*
** Creates two tables with the names and the types of the columns.
*/
static int create_colinfo (lua_State *L, cur_data *cur) {
static int create_colinfo (lua_State *L, cur_data *cur)
{
SQLCHAR buffer[256];
SQLSMALLINT namelen, datatype, i;
SQLRETURN ret;
......
lua_newtable(L);
names = lua_gettop (L);
for (i = 1; i <= cur->numcols; i++) {
ret = SQLDescribeCol(cur->hstmt, i, buffer, sizeof(buffer),
&namelen, &datatype, NULL, NULL, NULL);
ret = SQLDescribeCol(cur->stmt->hstmt, i, buffer, sizeof(buffer),
&namelen, &datatype, NULL, NULL, NULL);
if (ret == SQL_ERROR) {
lua_pop(L, 2);
return -1;
}
lua_pushstring (L, (char*)buffer);
lua_pushstring (L, (char *)buffer);
lua_rawseti (L, names, i);
lua_pushstring(L, sqltypetolua(datatype));
lua_rawseti (L, types, i);
......
/*
** Creates a cursor table and leave it on the top of the stack.
*/
static int create_cursor (lua_State *L, int o, conn_data *conn,
const SQLHSTMT hstmt, const SQLSMALLINT numcols)
static int create_cursor (lua_State *L, int stmt_i, stmt_data *stmt,
const SQLSMALLINT numcols)
{
cur_data *cur = (cur_data *) lua_newuserdata(L, sizeof(cur_data));
luasql_setmeta (L, LUASQL_CURSOR_ODBC);
cur_data *cur;
conn->cur_counter++;
lock_obj(L, stmt_i, stmt);
cur = (cur_data *) lua_newuserdata(L, sizeof(cur_data));
luasql_setmeta (L, LUASQL_CURSOR_ODBC);
/* fill in structure */
cur->closed = 0;
cur->conn = LUA_NOREF;
cur->stmt = stmt;
cur->numcols = numcols;
cur->colnames = LUA_NOREF;
cur->coltypes = LUA_NOREF;
cur->hstmt = hstmt;
lua_pushvalue (L, o);
cur->conn = luaL_ref (L, LUA_REGISTRYINDEX);
/* make and store column information table */
if(create_colinfo (L, cur) < 0) {
lua_pop(L, 1);
return fail(L, hSTMT, cur->hstmt);
return fail(L, hSTMT, cur->stmt->hstmt);
}
return 1;
}
/*
** Returns the table with statement params.
*/
static int stmt_paramtypes (lua_State *L)
{
stmt_data *stmt = getstatement(L, 1);
lua_rawgeti (L, LUA_REGISTRYINDEX, stmt->paramtypes);
return 1;
}
static int stmt_close(lua_State *L)
{
stmt_data *stmt = (stmt_data *) luaL_checkudata (L, 1, LUASQL_STATEMENT_ODBC);
luaL_argcheck (L, stmt != NULL, 1, LUASQL_PREFIX"statement expected");
luaL_argcheck (L, stmt->lock == 0, 1,
LUASQL_PREFIX"there are still open cursors");
if (stmt->closed) {
lua_pushboolean (L, 0);
return 1;
}
if(stmt_shut(L, stmt)) {
return fail(L, hSTMT, stmt->hstmt);
}
lua_pushboolean(L, 1);
return 1;
}
......
/*
** Closes a connection.
*/
static int conn_close (lua_State *L) {
static int conn_close (lua_State *L)
{
SQLRETURN ret;
env_data *env;
conn_data *conn = (conn_data *)luaL_checkudata(L,1,LUASQL_CONNECTION_ODBC);
conn_data *conn = (conn_data *)luaL_checkudata(L,1,LUASQL_CONNECTION_ODBC);
luaL_argcheck (L, conn != NULL, 1, LUASQL_PREFIX"connection expected");
if (conn->closed) {
lua_pushboolean (L, 0);
return 1;
}
if (conn->cur_counter > 0)
return luaL_error (L, LUASQL_PREFIX"there are open cursors");
if (conn->lock > 0) {
return luaL_error (L, LUASQL_PREFIX"there are open statements/cursors");
}
/* Decrement connection counter on environment object */
lua_rawgeti (L, LUA_REGISTRYINDEX, conn->env);
env = lua_touserdata (L, -1);
env->conn_counter--;
unlock_obj(L, conn->env);
/* Nullify structure fields. */
conn->closed = 1;
luaL_unref (L, LUA_REGISTRYINDEX, conn->env);
ret = SQLDisconnect(conn->hdbc);
if (error(ret))
if (error(ret)) {
return fail(L, hDBC, conn->hdbc);
}
ret = SQLFreeHandle(hDBC, conn->hdbc);
if (error(ret))
if (error(ret)) {
return fail(L, hDBC, conn->hdbc);
return pass(L);
}
return pass(L);
}
/*
** Executes the given statement
** Takes:
** * istmt : location of the statement object on the stack
*/
static int raw_execute(lua_State *L, int istmt)
{
SQLSMALLINT numcols;
stmt_data *stmt = getstatement(L, istmt);
/* execute the statement */
if (error(SQLExecute(stmt->hstmt))) {
return fail(L, hSTMT, stmt->hstmt);
}
/* determine the number of result columns */
if (error(SQLNumResultCols(stmt->hstmt, &numcols))) {
return fail(L, hSTMT, stmt->hstmt);
}
if (numcols > 0) {
/* if there is a results table (e.g., SELECT) */
return create_cursor(L, -1, stmt, numcols);
} else {
/* if action has no results (e.g., UPDATE) */
SQLINTEGER numrows;
if(error(SQLRowCount(stmt->hstmt, &numrows))) {
return fail(L, hSTMT, stmt->hstmt);
}
lua_pushnumber(L, numrows);
return 1;
}
}
static int set_param(lua_State *L, stmt_data *stmt, int i, param_data *data)
{
static SQLINTEGER cbNull = SQL_NULL_DATA;
switch(lua_type(L, -1)) {
case LUA_TNIL: {
lua_pop(L, 1);
if(error(SQLBindParameter(stmt->hstmt, i, SQL_PARAM_INPUT, SQL_C_DEFAULT,
SQL_DOUBLE, 0, 0, NULL, 0, &cbNull))) {
return fail(L, hSTMT, stmt->hstmt);
}
}
break;
case LUA_TNUMBER: {
data->buf = malloc(sizeof(double));
*(double *)data->buf = (double)lua_tonumber(L, -1);
data->len = sizeof(double);
data->type = 0;
lua_pop(L, 1);
if(error(SQLBindParameter(stmt->hstmt, i, SQL_PARAM_INPUT, SQL_C_DOUBLE,
SQL_DOUBLE, 0, 0, data->buf, data->len,
&data->type))) {
return fail(L, hSTMT, stmt->hstmt);
}
}
break;
case LUA_TSTRING: {
const char *str = lua_tostring(L, -1);
size_t len = strlen(str);
data->buf = malloc(len+1);
memcpy((char *)data->buf, str, len+1);
data->len = len;
data->type = SQL_NTS;
lua_pop(L, 1);
if(error(SQLBindParameter(stmt->hstmt, i, SQL_PARAM_INPUT, SQL_C_CHAR,
SQL_CHAR, len, 0, data->buf, data->len,
&data->type))) {
return fail(L, hSTMT, stmt->hstmt);
}
}
break;
case LUA_TBOOLEAN: {
data->buf = malloc(sizeof(SQLCHAR));
*(SQLCHAR *)data->buf = (SQLCHAR)lua_toboolean(L, -1);
data->len = 0;
data->type = 0;
lua_pop(L, 1);
if(error(SQLBindParameter(stmt->hstmt, i, SQL_PARAM_INPUT, SQL_C_BIT,
SQL_BIT, 0, 0, data->buf, data->len,
&data->type))) {
return fail(L, hSTMT, stmt->hstmt);
}
}
break;
default:
lua_pop(L, 1);
return luasql_faildirect(L, "unsupported parameter type");
}
return 0;
}
/*
** Reads a param table into a statement
*/
static int raw_readparams_table(lua_State *L, stmt_data *stmt, int iparams)
{
static SQLINTEGER cbNull = SQL_NULL_DATA;
SQLSMALLINT i;
param_data *data;
int res = 0;
free_stmt_params(stmt->params, stmt->numparams);
stmt->params = malloc_stmt_params(stmt->numparams);
data = stmt->params;
for(i=1; i<=stmt->numparams; ++i, ++data) {
/* not using lua_geti for backwards compat with Lua 5.1/LuaJIT */
lua_pushnumber(L, i);
lua_gettable(L, iparams);
res = set_param(L, stmt, i, data);
if(res != 0) {
return res;
}
}
return 0;
}
/*
** Reads a param table into a statement
*/
static int raw_readparams_args(lua_State *L, stmt_data *stmt, int arg, int ltop)
{
static SQLINTEGER cbNull = SQL_NULL_DATA;
SQLSMALLINT i;
param_data *data;
int res = 0;
free_stmt_params(stmt->params, stmt->numparams);
stmt->params = malloc_stmt_params(stmt->numparams);
data = stmt->params;
for(i=1; i<=stmt->numparams; ++i, ++data, ++arg) {
if(arg > ltop) {
lua_pushnil(L);
} else {
lua_pushvalue(L, arg);
}
res = set_param(L, stmt, i, data);
if(res != 0) {
return res;
}
}
return 0;
}
/*
** Executes a SQL statement.
** Returns
** Executes the prepared statement
** Lua Input: [params]
** params: A table of parameters to use in the statement
** Lua Returns
** cursor object: if there are results or
** row count: number of rows affected by statement if no results
*/
static int conn_execute (lua_State *L) {
conn_data *conn = (conn_data *) getconnection (L);
SQLCHAR *statement = (SQLCHAR*)luaL_checkstring(L, 2);
static int stmt_execute(lua_State *L)
{
int ltop = lua_gettop(L);
int res;
/* any parameters to use */
if(ltop > 1) {
stmt_data *stmt = getstatement(L, 1);
if(lua_type(L, 2) == LUA_TTABLE) {
res = raw_readparams_table(L, stmt, 2);
} else {
res = raw_readparams_args(L, stmt, 2, ltop);
}
if(res != 0) {
return res;
}
}
return raw_execute(L, 1);
}
/*
** creates a table of parameter types (maybe)
** Returns: the reference key of the table (noref if unable to build the table)
*/
static int desc_params(lua_State *L, stmt_data *stmt)
{
SQLSMALLINT i;
lua_newtable(L);
for(i=1; i <= stmt->numparams; ++i) {
SQLSMALLINT type, digits, nullable;
SQLULEN len;
/* fun fact: most ODBC drivers don't support this function (MS Access for
example), so we can't get a param type table */
if(error(SQLDescribeParam(stmt->hstmt, i, &type, &len, &digits, &nullable))) {
lua_pop(L,1);
return LUA_NOREF;
}
lua_pushstring(L, sqltypetolua(type));
lua_rawseti(L, -2, i);
}
return luaL_ref(L, LUA_REGISTRYINDEX);
}
/*
** Prepares a statement
** Lua Input: sql
** sql: The SQL statement to prepare
** Lua Returns:
** Statement object
*/
static int conn_prepare(lua_State *L)
{
conn_data *conn = getconnection(L, 1);
SQLCHAR *statement = (SQLCHAR *)luaL_checkstring(L, 2);
SQLHDBC hdbc = conn->hdbc;
SQLHSTMT hstmt;
SQLSMALLINT numcols;
SQLRETURN ret;
stmt_data *stmt;
ret = SQLAllocHandle(hSTMT, hdbc, &hstmt);
if (error(ret))
if (error(ret)) {
return fail(L, hDBC, hdbc);
}
ret = SQLPrepare(hstmt, statement, SQL_NTS);
if (error(ret)) {
......
return ret;
}
/* execute the statement */
ret = SQLExecute (hstmt);
if (error(ret)) {
ret = fail(L, hSTMT, hstmt);
SQLFreeHandle(hSTMT, hstmt);
return ret;
}
stmt = (stmt_data *)lua_newuserdata(L, sizeof(stmt_data));
memset(stmt, 0, sizeof(stmt_data));
/* determine the number of results */
ret = SQLNumResultCols (hstmt, &numcols);
if (error(ret)) {
ret = fail(L, hSTMT, hstmt);
stmt->closed = 0;
stmt->lock = 0;
stmt->hidden = 0;
stmt->conn = conn;
stmt->hstmt = hstmt;
if(error(SQLNumParams(hstmt, &stmt->numparams))) {
int res;
lua_pop(L, 1);
res = fail(L, hSTMT, hstmt);
SQLFreeHandle(hSTMT, hstmt);
return ret;
return res;
}
stmt->paramtypes = desc_params(L, stmt);
stmt->params = NULL;
if (numcols > 0)
/* if there is a results table (e.g., SELECT) */
return create_cursor (L, 1, conn, hstmt, numcols);
else {
/* if action has no results (e.g., UPDATE) */
SQLLEN numrows;
ret = SQLRowCount(hstmt, &numrows);
if (error(ret)) {
ret = fail(L, hSTMT, hstmt);
SQLFreeHandle(hSTMT, hstmt);
return ret;
/* activate statement object */
luasql_setmeta(L, LUASQL_STATEMENT_ODBC);
lock_obj(L, 1, conn);
return 1;
}
/*
** Executes a SQL statement directly
** Lua Input: sql, [params]
** sql: The SQL statement to execute
** params: A table of parameters to use in the SQL
** Lua Returns
** cursor object: if there are results or
** row count: number of rows affected by statement if no results
*/
static int conn_execute (lua_State *L)
{
stmt_data *stmt;
int res, istmt;
int ltop = lua_gettop(L);
/* prepare statement */
if((res = conn_prepare(L)) != 1) {
return res;
}
istmt = lua_gettop(L);
stmt = getstatement(L, istmt);
/* because this is a direct execute, statement is hidden from user */
stmt->hidden = 1;
/* do we have any parameters */
if(ltop > 2) {
if(lua_type(L, 3) == LUA_TTABLE) {
res = raw_readparams_table(L, stmt, 3);
} else {
res = raw_readparams_args(L, stmt, 3, ltop);
}
if(res != 0) {
return res;
}
lua_pushnumber(L, numrows);
SQLFreeHandle(hSTMT, hstmt);
return 1;
}
/* do it */
res = raw_execute(L, istmt);
/* anything but a cursor, close the statement directly */
if(!lua_isuserdata(L, -res)) {
stmt_shut(L, stmt);
}
/* tidy up */
lua_remove(L, istmt);
return res;
}
/*
** Rolls back a transaction.
** Rolls back a transaction.
*/
static int conn_commit (lua_State *L) {
conn_data *conn = (conn_data *) getconnection (L);
conn_data *conn = (conn_data *) getconnection (L, 1);
SQLRETURN ret = SQLEndTran(hDBC, conn->hdbc, SQL_COMMIT);
if (error(ret))
return fail(L, hSTMT, conn->hdbc);
......
}
/*
** Rollback the current transaction.
** Rollback the current transaction.
*/
static int conn_rollback (lua_State *L) {
conn_data *conn = (conn_data *) getconnection (L);
conn_data *conn = (conn_data *) getconnection (L, 1);
SQLRETURN ret = SQLEndTran(hDBC, conn->hdbc, SQL_ROLLBACK);
if (error(ret))
return fail(L, hSTMT, conn->hdbc);
......
** Sets the auto commit mode
*/
static int conn_setautocommit (lua_State *L) {
conn_data *conn = (conn_data *) getconnection (L);
conn_data *conn = (conn_data *) getconnection (L, 1);
SQLRETURN ret;
if (lua_toboolean (L, 2)) {
ret = SQLSetConnectAttr(conn->hdbc, SQL_ATTR_AUTOCOMMIT,
......
/*
** Create a new Connection object and push it on top of the stack.
*/
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));
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));
/* set auto commit mode */
SQLRETURN ret = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT,
(SQLPOINTER) SQL_AUTOCOMMIT_ON, 0);
if (error(ret))
(SQLPOINTER) SQL_AUTOCOMMIT_ON, 0);
if (error(ret)) {
return fail(L, hDBC, hdbc);
}
luasql_setmeta (L, LUASQL_CONNECTION_ODBC);
/* fill in structure */
conn->closed = 0;
conn->cur_counter = 0;
conn->env = LUA_NOREF;
conn->lock = 0;
conn->env = env;
conn->hdbc = hdbc;
lua_pushvalue (L, o);
conn->env = luaL_ref (L, LUA_REGISTRYINDEX);
env->conn_counter++;
lock_obj(L, 1, env);
return 1;
}
......
** nil and error message otherwise.
*/
static int env_connect (lua_State *L) {
env_data *env = (env_data *) getenvironment (L);
env_data *env = (env_data *) getenvironment (L, 1);
SQLCHAR *sourcename = (SQLCHAR*)luaL_checkstring (L, 2);
SQLCHAR *username = (SQLCHAR*)luaL_optstring (L, 3, NULL);
SQLCHAR *password = (SQLCHAR*)luaL_optstring (L, 4, NULL);
......
return luasql_faildirect (L, "connection allocation error.");
/* tries to connect handle */
ret = SQLConnect (hdbc, sourcename, SQL_NTS,
ret = SQLConnect (hdbc, sourcename, SQL_NTS,
username, SQL_NTS, password, SQL_NTS);
if (error(ret)) {
ret = fail(L, hDBC, hdbc);
......
/*
** Closes an environment object
*/
static int env_close (lua_State *L) {
static int env_close (lua_State *L)
{
SQLRETURN ret;
env_data *env = (env_data *)luaL_checkudata(L, 1, LUASQL_ENVIRONMENT_ODBC);
luaL_argcheck (L, env != NULL, 1, LUASQL_PREFIX"environment expected");
......
lua_pushboolean (L, 0);
return 1;
}
if (env->conn_counter > 0)
if (env->lock > 0) {
return luaL_error (L, LUASQL_PREFIX"there are open connections");
}
env->closed = 1;
ret = SQLFreeHandle (hENV, env->henv);
......
return pass(L);
}
/*
** Create metatables for each class of object.
*/
......
struct luaL_Reg connection_methods[] = {
{"__gc", conn_close}, /* Should this method be changed? */
{"close", conn_close},
{"prepare", conn_prepare},
{"execute", conn_execute},
{"commit", conn_commit},
{"rollback", conn_rollback},
{"setautocommit", conn_setautocommit},
{NULL, NULL},
};
struct luaL_Reg statement_methods[] = {
{"__gc", stmt_close}, /* Should this method be changed? */
{"close", stmt_close},
{"execute", stmt_execute},
{"getparamtypes", stmt_paramtypes},
{NULL, NULL},
};
struct luaL_Reg cursor_methods[] = {
{"__gc", cur_close}, /* Should this method be changed? */
{"close", cur_close},
......
};
luasql_createmeta (L, LUASQL_ENVIRONMENT_ODBC, environment_methods);
luasql_createmeta (L, LUASQL_CONNECTION_ODBC, connection_methods);
luasql_createmeta (L, LUASQL_STATEMENT_ODBC, statement_methods);
luasql_createmeta (L, LUASQL_CURSOR_ODBC, cursor_methods);
lua_pop (L, 3);
lua_pop (L, 4);
}
/*
** Creates an Environment and returns it.
*/
static int create_environment (lua_State *L) {
static int create_environment (lua_State *L)
{
env_data *env;
SQLHENV henv;
SQLRETURN ret = SQLAllocHandle(hENV, SQL_NULL_HANDLE, &henv);
if (error(ret))
if (error(ret)) {
return luasql_faildirect(L, "error creating environment.");
}
ret = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION,
(void*)SQL_OV_ODBC3, 0);
ret = SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
if (error(ret)) {
ret = luasql_faildirect (L, "error setting SQL version.");
SQLFreeHandle (hENV, henv);
return ret;
}
}
env = (env_data *)lua_newuserdata (L, sizeof (env_data));
luasql_setmeta (L, LUASQL_ENVIRONMENT_ODBC);
/* fill in structure */
env->closed = 0;
env->conn_counter = 0;
env->lock = 0;
env->henv = henv;
return 1;
}
......
luaL_setfuncs (L, driver, 0);
luasql_set_info (L);
return 1;
}
}
dependencies/luasql/src/luasql.c
*/
LUASQL_API void luasql_set_info (lua_State *L) {
lua_pushliteral (L, "_COPYRIGHT");
lua_pushliteral (L, "Copyright (C) 2003-2017 Kepler Project");
lua_pushliteral (L, "Copyright (C) 2003-2019 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.3.5 (for "LUA_VERSION")");
lua_pushliteral (L, "LuaSQL 2.5.0 (for "LUA_VERSION")");
lua_settable (L, -3);
}
    (1-1/1)