|
@@ -1,6 +1,6 @@
|
|
/************************************************************************
|
|
/************************************************************************
|
|
* lsqlite3 *
|
|
* lsqlite3 *
|
|
-* Copyright (C) 2002-2013 Tiago Dionizio, Doug Currie *
|
|
|
|
|
|
+* Copyright (C) 2002-2015 Tiago Dionizio, Doug Currie *
|
|
* All rights reserved. *
|
|
* All rights reserved. *
|
|
* Author : Tiago Dionizio <tiago.dionizio@ist.utl.pt> *
|
|
* Author : Tiago Dionizio <tiago.dionizio@ist.utl.pt> *
|
|
* Author : Doug Currie <doug.currie@alum.mit.edu> *
|
|
* Author : Doug Currie <doug.currie@alum.mit.edu> *
|
|
@@ -35,16 +35,23 @@
|
|
#include "lauxlib.h"
|
|
#include "lauxlib.h"
|
|
|
|
|
|
#if LUA_VERSION_NUM > 501
|
|
#if LUA_VERSION_NUM > 501
|
|
-//
|
|
|
|
-// Lua 5.2
|
|
|
|
-//
|
|
|
|
|
|
+/*
|
|
|
|
+** Lua 5.2
|
|
|
|
+*/
|
|
#define lua_strlen lua_rawlen
|
|
#define lua_strlen lua_rawlen
|
|
-// luaL_typerror always used with arg at ndx == NULL
|
|
|
|
|
|
+/* luaL_typerror always used with arg at ndx == NULL */
|
|
#define luaL_typerror(L,ndx,str) luaL_error(L,"bad argument %d (%s expected, got nil)",ndx,str)
|
|
#define luaL_typerror(L,ndx,str) luaL_error(L,"bad argument %d (%s expected, got nil)",ndx,str)
|
|
-// luaL_register used once, so below expansion is OK for this case
|
|
|
|
|
|
+/* luaL_register used once, so below expansion is OK for this case */
|
|
#define luaL_register(L,name,reg) lua_newtable(L);luaL_setfuncs(L,reg,0)
|
|
#define luaL_register(L,name,reg) lua_newtable(L);luaL_setfuncs(L,reg,0)
|
|
-// luaL_openlib always used with name == NULL
|
|
|
|
|
|
+/* luaL_openlib always used with name == NULL */
|
|
#define luaL_openlib(L,name,reg,nup) luaL_setfuncs(L,reg,nup)
|
|
#define luaL_openlib(L,name,reg,nup) luaL_setfuncs(L,reg,nup)
|
|
|
|
+
|
|
|
|
+#if LUA_VERSION_NUM > 502
|
|
|
|
+/*
|
|
|
|
+** Lua 5.3
|
|
|
|
+*/
|
|
|
|
+#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
|
|
|
+#endif
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#include "sqlite3.h"
|
|
#include "sqlite3.h"
|
|
@@ -57,6 +64,7 @@
|
|
#define LSQLITE_OMIT_UPDATE_HOOK 0
|
|
#define LSQLITE_OMIT_UPDATE_HOOK 0
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+
|
|
typedef struct sdb sdb;
|
|
typedef struct sdb sdb;
|
|
typedef struct sdb_vm sdb_vm;
|
|
typedef struct sdb_vm sdb_vm;
|
|
typedef struct sdb_func sdb_func;
|
|
typedef struct sdb_func sdb_func;
|
|
@@ -113,6 +121,32 @@ static const char *sqlite_vm_meta = ":sqlite3:vm";
|
|
static const char *sqlite_ctx_meta = ":sqlite3:ctx";
|
|
static const char *sqlite_ctx_meta = ":sqlite3:ctx";
|
|
static int sqlite_ctx_meta_ref;
|
|
static int sqlite_ctx_meta_ref;
|
|
|
|
|
|
|
|
+/* Lua 5.3 introduced an integer type, but depending on the implementation, it could be 32
|
|
|
|
+** or 64 bits (or something else?). This helper macro tries to do "the right thing."
|
|
|
|
+*/
|
|
|
|
+
|
|
|
|
+#if LUA_VERSION_NUM > 502
|
|
|
|
+#define PUSH_INT64(L,i64in,fallback) \
|
|
|
|
+ do { \
|
|
|
|
+ sqlite_int64 i64 = i64in; \
|
|
|
|
+ lua_Integer i = (lua_Integer )i64; \
|
|
|
|
+ if (i == i64) lua_pushinteger(L, i);\
|
|
|
|
+ else { \
|
|
|
|
+ lua_Number n = (lua_Number)i64; \
|
|
|
|
+ if (n == i64) lua_pushnumber(L, n); \
|
|
|
|
+ else fallback; \
|
|
|
|
+ } \
|
|
|
|
+ } while (0)
|
|
|
|
+#else
|
|
|
|
+#define PUSH_INT64(L,i64in,fallback) \
|
|
|
|
+ do { \
|
|
|
|
+ sqlite_int64 i64 = i64in; \
|
|
|
|
+ lua_Number n = (lua_Number)i64; \
|
|
|
|
+ if (n == i64) lua_pushnumber(L, n); \
|
|
|
|
+ else fallback; \
|
|
|
|
+ } while (0)
|
|
|
|
+#endif
|
|
|
|
+
|
|
/*
|
|
/*
|
|
** =======================================================
|
|
** =======================================================
|
|
** Database Virtual Machine Operations
|
|
** Database Virtual Machine Operations
|
|
@@ -122,14 +156,9 @@ static int sqlite_ctx_meta_ref;
|
|
static void vm_push_column(lua_State *L, sqlite3_stmt *vm, int idx) {
|
|
static void vm_push_column(lua_State *L, sqlite3_stmt *vm, int idx) {
|
|
switch (sqlite3_column_type(vm, idx)) {
|
|
switch (sqlite3_column_type(vm, idx)) {
|
|
case SQLITE_INTEGER:
|
|
case SQLITE_INTEGER:
|
|
- {
|
|
|
|
- sqlite_int64 i64 = sqlite3_column_int64(vm, idx);
|
|
|
|
- lua_Number n = (lua_Number)i64;
|
|
|
|
- if (n == i64)
|
|
|
|
- lua_pushnumber(L, n);
|
|
|
|
- else
|
|
|
|
- lua_pushlstring(L, (const char*)sqlite3_column_text(vm, idx), sqlite3_column_bytes(vm, idx));
|
|
|
|
- }
|
|
|
|
|
|
+ PUSH_INT64(L, sqlite3_column_int64(vm, idx)
|
|
|
|
+ , lua_pushlstring(L, (const char*)sqlite3_column_text(vm, idx)
|
|
|
|
+ , sqlite3_column_bytes(vm, idx)));
|
|
break;
|
|
break;
|
|
case SQLITE_FLOAT:
|
|
case SQLITE_FLOAT:
|
|
lua_pushnumber(L, sqlite3_column_double(vm, idx));
|
|
lua_pushnumber(L, sqlite3_column_double(vm, idx));
|
|
@@ -161,7 +190,7 @@ struct sdb_vm {
|
|
char temp; /* temporary vm used in db:rows */
|
|
char temp; /* temporary vm used in db:rows */
|
|
};
|
|
};
|
|
|
|
|
|
-/* called with sql text on the lua stack */
|
|
|
|
|
|
+/* called with db,sql text on the lua stack */
|
|
static sdb_vm *newvm(lua_State *L, sdb *db) {
|
|
static sdb_vm *newvm(lua_State *L, sdb *db) {
|
|
sdb_vm *svm = (sdb_vm*)lua_newuserdata(L, sizeof(sdb_vm));
|
|
sdb_vm *svm = (sdb_vm*)lua_newuserdata(L, sizeof(sdb_vm));
|
|
|
|
|
|
@@ -174,11 +203,11 @@ static sdb_vm *newvm(lua_State *L, sdb *db) {
|
|
svm->vm = NULL;
|
|
svm->vm = NULL;
|
|
svm->temp = 0;
|
|
svm->temp = 0;
|
|
|
|
|
|
- /* add an entry on the database table: svm -> sql text */
|
|
|
|
|
|
+ /* add an entry on the database table: svm -> db to keep db live while svm is live */
|
|
lua_pushlightuserdata(L, db);
|
|
lua_pushlightuserdata(L, db);
|
|
lua_rawget(L, LUA_REGISTRYINDEX);
|
|
lua_rawget(L, LUA_REGISTRYINDEX);
|
|
lua_pushlightuserdata(L, svm);
|
|
lua_pushlightuserdata(L, svm);
|
|
- lua_pushvalue(L, -4); /* the sql text */
|
|
|
|
|
|
+ lua_pushvalue(L, -5); /* the db for this vm */
|
|
lua_rawset(L, -3);
|
|
lua_rawset(L, -3);
|
|
lua_pop(L, 1);
|
|
lua_pop(L, 1);
|
|
|
|
|
|
@@ -186,6 +215,7 @@ static sdb_vm *newvm(lua_State *L, sdb *db) {
|
|
}
|
|
}
|
|
|
|
|
|
static int cleanupvm(lua_State *L, sdb_vm *svm) {
|
|
static int cleanupvm(lua_State *L, sdb_vm *svm) {
|
|
|
|
+
|
|
/* remove entry in database table - no harm if not present in the table */
|
|
/* remove entry in database table - no harm if not present in the table */
|
|
lua_pushlightuserdata(L, svm->db);
|
|
lua_pushlightuserdata(L, svm->db);
|
|
lua_rawget(L, LUA_REGISTRYINDEX);
|
|
lua_rawget(L, LUA_REGISTRYINDEX);
|
|
@@ -199,40 +229,13 @@ static int cleanupvm(lua_State *L, sdb_vm *svm) {
|
|
|
|
|
|
if (!svm->vm) return 0;
|
|
if (!svm->vm) return 0;
|
|
|
|
|
|
- lua_pushnumber(L, sqlite3_finalize(svm->vm));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_finalize(svm->vm));
|
|
svm->vm = NULL;
|
|
svm->vm = NULL;
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
static int stepvm(lua_State *L, sdb_vm *svm) {
|
|
static int stepvm(lua_State *L, sdb_vm *svm) {
|
|
- int result;
|
|
|
|
- int loop_limit = 3;
|
|
|
|
- while ( loop_limit-- ) {
|
|
|
|
- result = sqlite3_step(svm->vm);
|
|
|
|
- if ( result==SQLITE_ERROR ) {
|
|
|
|
- result = sqlite3_reset (svm->vm);
|
|
|
|
- }
|
|
|
|
- if ( result==SQLITE_SCHEMA ) {
|
|
|
|
- sqlite3_stmt *vn;
|
|
|
|
- const char *sql;
|
|
|
|
- /* recover sql text */
|
|
|
|
- lua_pushlightuserdata(L, svm->db);
|
|
|
|
- lua_rawget(L, LUA_REGISTRYINDEX);
|
|
|
|
- lua_pushlightuserdata(L, svm);
|
|
|
|
- lua_rawget(L, -2); /* sql text */
|
|
|
|
- sql = luaL_checkstring(L, -1);
|
|
|
|
- /* re-prepare */
|
|
|
|
- result = sqlite3_prepare(svm->db->db, sql, -1, &vn, NULL);
|
|
|
|
- if (result != SQLITE_OK) break;
|
|
|
|
- sqlite3_transfer_bindings(svm->vm, vn);
|
|
|
|
- sqlite3_finalize(svm->vm);
|
|
|
|
- svm->vm = vn;
|
|
|
|
- lua_pop(L,2);
|
|
|
|
- } else {
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return result;
|
|
|
|
|
|
+ return sqlite3_step(svm->vm);
|
|
}
|
|
}
|
|
|
|
|
|
static sdb_vm *lsqlite_getvm(lua_State *L, int index) {
|
|
static sdb_vm *lsqlite_getvm(lua_State *L, int index) {
|
|
@@ -279,7 +282,7 @@ static int dbvm_step(lua_State *L) {
|
|
svm->has_values = result == SQLITE_ROW ? 1 : 0;
|
|
svm->has_values = result == SQLITE_ROW ? 1 : 0;
|
|
svm->columns = sqlite3_data_count(svm->vm);
|
|
svm->columns = sqlite3_data_count(svm->vm);
|
|
|
|
|
|
- lua_pushnumber(L, result);
|
|
|
|
|
|
+ lua_pushinteger(L, result);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -291,7 +294,7 @@ static int dbvm_finalize(lua_State *L) {
|
|
static int dbvm_reset(lua_State *L) {
|
|
static int dbvm_reset(lua_State *L) {
|
|
sdb_vm *svm = lsqlite_checkvm(L, 1);
|
|
sdb_vm *svm = lsqlite_checkvm(L, 1);
|
|
sqlite3_reset(svm->vm);
|
|
sqlite3_reset(svm->vm);
|
|
- lua_pushnumber(L, sqlite3_errcode(svm->db->db));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_errcode(svm->db->db));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -313,6 +316,14 @@ static void dbvm_check_bind_index(lua_State *L, sdb_vm *svm, int index) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int dbvm_last_insert_rowid(lua_State *L) {
|
|
|
|
+ sdb_vm *svm = lsqlite_checkvm(L, 1);
|
|
|
|
+ /* conversion warning: int64 -> luaNumber */
|
|
|
|
+ sqlite_int64 rowid = sqlite3_last_insert_rowid(svm->db->db);
|
|
|
|
+ PUSH_INT64(L, rowid, lua_pushfstring(L, "%ll", rowid));
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
** =======================================================
|
|
** =======================================================
|
|
** Virtual Machine - generic info
|
|
** Virtual Machine - generic info
|
|
@@ -320,7 +331,7 @@ static void dbvm_check_bind_index(lua_State *L, sdb_vm *svm, int index) {
|
|
*/
|
|
*/
|
|
static int dbvm_columns(lua_State *L) {
|
|
static int dbvm_columns(lua_State *L) {
|
|
sdb_vm *svm = lsqlite_checkvm(L, 1);
|
|
sdb_vm *svm = lsqlite_checkvm(L, 1);
|
|
- lua_pushnumber(L, sqlite3_column_count(svm->vm));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_column_count(svm->vm));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -477,6 +488,10 @@ static int dbvm_bind_index(lua_State *L, sqlite3_stmt *vm, int index, int lindex
|
|
case LUA_TSTRING:
|
|
case LUA_TSTRING:
|
|
return sqlite3_bind_text(vm, index, lua_tostring(L, lindex), lua_strlen(L, lindex), SQLITE_TRANSIENT);
|
|
return sqlite3_bind_text(vm, index, lua_tostring(L, lindex), lua_strlen(L, lindex), SQLITE_TRANSIENT);
|
|
case LUA_TNUMBER:
|
|
case LUA_TNUMBER:
|
|
|
|
+#if LUA_VERSION_NUM > 502
|
|
|
|
+ if (lua_isinteger(L, lindex))
|
|
|
|
+ return sqlite3_bind_int64(vm, index, lua_tointeger(L, lindex));
|
|
|
|
+#endif
|
|
return sqlite3_bind_double(vm, index, lua_tonumber(L, lindex));
|
|
return sqlite3_bind_double(vm, index, lua_tonumber(L, lindex));
|
|
case LUA_TBOOLEAN:
|
|
case LUA_TBOOLEAN:
|
|
return sqlite3_bind_int(vm, index, lua_toboolean(L, lindex) ? 1 : 0);
|
|
return sqlite3_bind_int(vm, index, lua_toboolean(L, lindex) ? 1 : 0);
|
|
@@ -492,7 +507,7 @@ static int dbvm_bind_index(lua_State *L, sqlite3_stmt *vm, int index, int lindex
|
|
|
|
|
|
static int dbvm_bind_parameter_count(lua_State *L) {
|
|
static int dbvm_bind_parameter_count(lua_State *L) {
|
|
sdb_vm *svm = lsqlite_checkvm(L, 1);
|
|
sdb_vm *svm = lsqlite_checkvm(L, 1);
|
|
- lua_pushnumber(L, sqlite3_bind_parameter_count(svm->vm));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_bind_parameter_count(svm->vm));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -513,7 +528,7 @@ static int dbvm_bind(lua_State *L) {
|
|
dbvm_check_bind_index(L, svm, index);
|
|
dbvm_check_bind_index(L, svm, index);
|
|
result = dbvm_bind_index(L, vm, index, 3);
|
|
result = dbvm_bind_index(L, vm, index, 3);
|
|
|
|
|
|
- lua_pushnumber(L, result);
|
|
|
|
|
|
+ lua_pushinteger(L, result);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -523,7 +538,7 @@ static int dbvm_bind_blob(lua_State *L) {
|
|
const char *value = luaL_checkstring(L, 3);
|
|
const char *value = luaL_checkstring(L, 3);
|
|
int len = lua_strlen(L, 3);
|
|
int len = lua_strlen(L, 3);
|
|
|
|
|
|
- lua_pushnumber(L, sqlite3_bind_blob(svm->vm, index, value, len, SQLITE_TRANSIENT));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_bind_blob(svm->vm, index, value, len, SQLITE_TRANSIENT));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -542,12 +557,12 @@ static int dbvm_bind_values(lua_State *L) {
|
|
|
|
|
|
for (n = 2; n <= top; ++n) {
|
|
for (n = 2; n <= top; ++n) {
|
|
if ((result = dbvm_bind_index(L, vm, n - 1, n)) != SQLITE_OK) {
|
|
if ((result = dbvm_bind_index(L, vm, n - 1, n)) != SQLITE_OK) {
|
|
- lua_pushnumber(L, result);
|
|
|
|
|
|
+ lua_pushinteger(L, result);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- lua_pushnumber(L, SQLITE_OK);
|
|
|
|
|
|
+ lua_pushinteger(L, SQLITE_OK);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -568,19 +583,19 @@ static int dbvm_bind_names(lua_State *L) {
|
|
lua_pop(L, 1);
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- lua_pushnumber(L, n);
|
|
|
|
|
|
+ lua_pushinteger(L, n);
|
|
lua_gettable(L, 2);
|
|
lua_gettable(L, 2);
|
|
result = dbvm_bind_index(L, vm, n, -1);
|
|
result = dbvm_bind_index(L, vm, n, -1);
|
|
lua_pop(L, 1);
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
|
|
|
|
if (result != SQLITE_OK) {
|
|
if (result != SQLITE_OK) {
|
|
- lua_pushnumber(L, result);
|
|
|
|
|
|
+ lua_pushinteger(L, result);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- lua_pushnumber(L, SQLITE_OK);
|
|
|
|
|
|
+ lua_pushinteger(L, SQLITE_OK);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -780,7 +795,7 @@ static int lcontext_set_aggregate_context(lua_State *L) {
|
|
static int lcontext_aggregate_count(lua_State *L) {
|
|
static int lcontext_aggregate_count(lua_State *L) {
|
|
lcontext *ctx = lsqlite_checkcontext(L, 1);
|
|
lcontext *ctx = lsqlite_checkcontext(L, 1);
|
|
lcontext_check_aggregate(L, ctx);
|
|
lcontext_check_aggregate(L, ctx);
|
|
- lua_pushnumber(L, sqlite3_aggregate_count(ctx->ctx));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_aggregate_count(ctx->ctx));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -793,6 +808,11 @@ static int lcontext_result(lua_State *L) {
|
|
lcontext *ctx = lsqlite_checkcontext(L, 1);
|
|
lcontext *ctx = lsqlite_checkcontext(L, 1);
|
|
switch (lua_type(L, 2)) {
|
|
switch (lua_type(L, 2)) {
|
|
case LUA_TNUMBER:
|
|
case LUA_TNUMBER:
|
|
|
|
+#if LUA_VERSION_NUM > 502
|
|
|
|
+ if (lua_isinteger(L, 2))
|
|
|
|
+ sqlite3_result_int64(ctx->ctx, luaL_checkinteger(L, 2));
|
|
|
|
+ else
|
|
|
|
+#endif
|
|
sqlite3_result_double(ctx->ctx, luaL_checknumber(L, 2));
|
|
sqlite3_result_double(ctx->ctx, luaL_checknumber(L, 2));
|
|
break;
|
|
break;
|
|
case LUA_TSTRING:
|
|
case LUA_TSTRING:
|
|
@@ -870,29 +890,25 @@ static int db_last_insert_rowid(lua_State *L) {
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
/* conversion warning: int64 -> luaNumber */
|
|
/* conversion warning: int64 -> luaNumber */
|
|
sqlite_int64 rowid = sqlite3_last_insert_rowid(db->db);
|
|
sqlite_int64 rowid = sqlite3_last_insert_rowid(db->db);
|
|
- lua_Number n = (lua_Number)rowid;
|
|
|
|
- if (n == rowid)
|
|
|
|
- lua_pushnumber(L, n);
|
|
|
|
- else
|
|
|
|
- lua_pushfstring(L, "%ll", rowid);
|
|
|
|
|
|
+ PUSH_INT64(L, rowid, lua_pushfstring(L, "%ll", rowid));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
static int db_changes(lua_State *L) {
|
|
static int db_changes(lua_State *L) {
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
- lua_pushnumber(L, sqlite3_changes(db->db));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_changes(db->db));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
static int db_total_changes(lua_State *L) {
|
|
static int db_total_changes(lua_State *L) {
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
- lua_pushnumber(L, sqlite3_total_changes(db->db));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_total_changes(db->db));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
static int db_errcode(lua_State *L) {
|
|
static int db_errcode(lua_State *L) {
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
- lua_pushnumber(L, sqlite3_errcode(db->db));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_errcode(db->db));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -919,14 +935,9 @@ static void db_push_value(lua_State *L, sqlite3_value *value) {
|
|
break;
|
|
break;
|
|
|
|
|
|
case SQLITE_INTEGER:
|
|
case SQLITE_INTEGER:
|
|
- {
|
|
|
|
- sqlite_int64 i64 = sqlite3_value_int64(value);
|
|
|
|
- lua_Number n = (lua_Number)i64;
|
|
|
|
- if (n == i64)
|
|
|
|
- lua_pushnumber(L, n);
|
|
|
|
- else
|
|
|
|
- lua_pushlstring(L, (const char*)sqlite3_value_text(value), sqlite3_value_bytes(value));
|
|
|
|
- }
|
|
|
|
|
|
+ PUSH_INT64(L, sqlite3_value_int64(value)
|
|
|
|
+ , lua_pushlstring(L, (const char*)sqlite3_value_text(value)
|
|
|
|
+ , sqlite3_value_bytes(value)));
|
|
break;
|
|
break;
|
|
|
|
|
|
case SQLITE_FLOAT:
|
|
case SQLITE_FLOAT:
|
|
@@ -1192,6 +1203,34 @@ static int db_create_collation(lua_State *L) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Thanks to Wolfgang Oertl...
|
|
|
|
+*/
|
|
|
|
+static int db_load_extension(lua_State *L) {
|
|
|
|
+ sdb *db=lsqlite_checkdb(L,1);
|
|
|
|
+ const char *extname=luaL_optstring(L,2,NULL);
|
|
|
|
+ const char *entrypoint=luaL_optstring(L,3,NULL);
|
|
|
|
+ int result;
|
|
|
|
+ char *errmsg = NULL;
|
|
|
|
+
|
|
|
|
+ if (extname == NULL) {
|
|
|
|
+ result = sqlite3_enable_load_extension(db->db,0); /* disable extension loading */
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ sqlite3_enable_load_extension(db->db,1); /* enable extension loading */
|
|
|
|
+ result = sqlite3_load_extension(db->db,extname,entrypoint,&errmsg);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (result == SQLITE_OK) {
|
|
|
|
+ lua_pushboolean(L,1);
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lua_pushboolean(L,0); /* so, assert(load_extension(...)) works */
|
|
|
|
+ lua_pushstring(L,errmsg);
|
|
|
|
+ sqlite3_free(errmsg);
|
|
|
|
+ return 2;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
** trace callback:
|
|
** trace callback:
|
|
** Params: database, callback function, userdata
|
|
** Params: database, callback function, userdata
|
|
@@ -1267,14 +1306,11 @@ static void db_update_hook_callback(void *user, int op, char const *dbname, char
|
|
/* setup lua callback call */
|
|
/* setup lua callback call */
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, db->update_hook_cb); /* get callback */
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, db->update_hook_cb); /* get callback */
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, db->update_hook_udata); /* get callback user data */
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, db->update_hook_udata); /* get callback user data */
|
|
- lua_pushnumber(L, (lua_Number )op);
|
|
|
|
|
|
+ lua_pushinteger(L, op);
|
|
lua_pushstring(L, dbname); /* update_hook database name */
|
|
lua_pushstring(L, dbname); /* update_hook database name */
|
|
lua_pushstring(L, tblname); /* update_hook database name */
|
|
lua_pushstring(L, tblname); /* update_hook database name */
|
|
- n = (lua_Number)rowid;
|
|
|
|
- if (n == rowid)
|
|
|
|
- lua_pushnumber(L, n);
|
|
|
|
- else
|
|
|
|
- lua_pushfstring(L, "%ll", rowid);
|
|
|
|
|
|
+
|
|
|
|
+ PUSH_INT64(L, rowid, lua_pushfstring(L, "%ll", rowid));
|
|
|
|
|
|
/* call lua function */
|
|
/* call lua function */
|
|
lua_pcall(L, 5, 0, 0);
|
|
lua_pcall(L, 5, 0, 0);
|
|
@@ -1517,7 +1553,7 @@ static int db_busy_callback(void *user, int tries) {
|
|
|
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, db->busy_cb);
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, db->busy_cb);
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, db->busy_udata);
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, db->busy_udata);
|
|
- lua_pushnumber(L, tries);
|
|
|
|
|
|
+ lua_pushinteger(L, tries);
|
|
|
|
|
|
/* call lua function */
|
|
/* call lua function */
|
|
if (!lua_pcall(L, 2, 1, 0))
|
|
if (!lua_pcall(L, 2, 1, 0))
|
|
@@ -1590,7 +1626,7 @@ static int db_exec_callback(void* user, int columns, char **data, char **names)
|
|
|
|
|
|
lua_pushvalue(L, 3); /* function to call */
|
|
lua_pushvalue(L, 3); /* function to call */
|
|
lua_pushvalue(L, 4); /* user data */
|
|
lua_pushvalue(L, 4); /* user data */
|
|
- lua_pushnumber(L, columns); /* total number of rows in result */
|
|
|
|
|
|
+ lua_pushinteger(L, columns); /* total number of rows in result */
|
|
|
|
|
|
/* column values */
|
|
/* column values */
|
|
lua_pushvalue(L, 6);
|
|
lua_pushvalue(L, 6);
|
|
@@ -1614,6 +1650,12 @@ static int db_exec_callback(void* user, int columns, char **data, char **names)
|
|
|
|
|
|
/* call lua function */
|
|
/* call lua function */
|
|
if (!lua_pcall(L, 4, 1, 0)) {
|
|
if (!lua_pcall(L, 4, 1, 0)) {
|
|
|
|
+
|
|
|
|
+#if LUA_VERSION_NUM > 502
|
|
|
|
+ if (lua_isinteger(L, -1))
|
|
|
|
+ result = lua_tointeger(L, -1);
|
|
|
|
+ else
|
|
|
|
+#endif
|
|
if (lua_isnumber(L, -1))
|
|
if (lua_isnumber(L, -1))
|
|
result = lua_tonumber(L, -1);
|
|
result = lua_tonumber(L, -1);
|
|
}
|
|
}
|
|
@@ -1646,7 +1688,7 @@ static int db_exec(lua_State *L) {
|
|
result = sqlite3_exec(db->db, sql, NULL, NULL, NULL);
|
|
result = sqlite3_exec(db->db, sql, NULL, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
- lua_pushnumber(L, result);
|
|
|
|
|
|
+ lua_pushinteger(L, result);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1660,14 +1702,14 @@ static int db_prepare(lua_State *L) {
|
|
int sql_len = lua_strlen(L, 2);
|
|
int sql_len = lua_strlen(L, 2);
|
|
const char *sqltail;
|
|
const char *sqltail;
|
|
sdb_vm *svm;
|
|
sdb_vm *svm;
|
|
- lua_settop(L,2); /* sql is on top of stack for call to newvm */
|
|
|
|
|
|
+ lua_settop(L,2); /* db,sql is on top of stack for call to newvm */
|
|
svm = newvm(L, db);
|
|
svm = newvm(L, db);
|
|
|
|
|
|
- if (sqlite3_prepare(db->db, sql, sql_len, &svm->vm, &sqltail) != SQLITE_OK) {
|
|
|
|
- cleanupvm(L, svm);
|
|
|
|
-
|
|
|
|
|
|
+ if (sqlite3_prepare_v2(db->db, sql, sql_len, &svm->vm, &sqltail) != SQLITE_OK) {
|
|
lua_pushnil(L);
|
|
lua_pushnil(L);
|
|
- lua_pushnumber(L, sqlite3_errcode(db->db));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_errcode(db->db));
|
|
|
|
+ if (cleanupvm(L, svm) == 1)
|
|
|
|
+ lua_pop(L, 1); /* this should not happen since sqlite3_prepare_v2 will not set ->vm on error */
|
|
return 2;
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1768,14 +1810,14 @@ static int db_do_rows(lua_State *L, int(*f)(lua_State *)) {
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
const char *sql = luaL_checkstring(L, 2);
|
|
const char *sql = luaL_checkstring(L, 2);
|
|
sdb_vm *svm;
|
|
sdb_vm *svm;
|
|
- lua_settop(L,2); /* sql is on top of stack for call to newvm */
|
|
|
|
|
|
+ lua_settop(L,2); /* db,sql is on top of stack for call to newvm */
|
|
svm = newvm(L, db);
|
|
svm = newvm(L, db);
|
|
svm->temp = 1;
|
|
svm->temp = 1;
|
|
|
|
|
|
- if (sqlite3_prepare(db->db, sql, -1, &svm->vm, NULL) != SQLITE_OK) {
|
|
|
|
- cleanupvm(L, svm);
|
|
|
|
-
|
|
|
|
|
|
+ if (sqlite3_prepare_v2(db->db, sql, -1, &svm->vm, NULL) != SQLITE_OK) {
|
|
lua_pushstring(L, sqlite3_errmsg(svm->db->db));
|
|
lua_pushstring(L, sqlite3_errmsg(svm->db->db));
|
|
|
|
+ if (cleanupvm(L, svm) == 1)
|
|
|
|
+ lua_pop(L, 1); /* this should not happen since sqlite3_prepare_v2 will not set ->vm on error */
|
|
lua_error(L);
|
|
lua_error(L);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1810,7 +1852,7 @@ static int db_tostring(lua_State *L) {
|
|
|
|
|
|
static int db_close(lua_State *L) {
|
|
static int db_close(lua_State *L) {
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
sdb *db = lsqlite_checkdb(L, 1);
|
|
- lua_pushnumber(L, cleanupdb(L, db));
|
|
|
|
|
|
+ lua_pushinteger(L, cleanupdb(L, db));
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1895,7 +1937,7 @@ static int lsqlite_do_open(lua_State *L, const char *filename) {
|
|
|
|
|
|
/* failed to open database */
|
|
/* failed to open database */
|
|
lua_pushnil(L); /* push nil */
|
|
lua_pushnil(L); /* push nil */
|
|
- lua_pushnumber(L, sqlite3_errcode(db->db));
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite3_errcode(db->db));
|
|
lua_pushstring(L, sqlite3_errmsg(db->db)); /* push error message */
|
|
lua_pushstring(L, sqlite3_errmsg(db->db)); /* push error message */
|
|
|
|
|
|
/* clean things up */
|
|
/* clean things up */
|
|
@@ -1920,6 +1962,18 @@ static int lsqlite_newindex(lua_State *L) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifndef LSQLITE_VERSION
|
|
|
|
+/* should be defined in rockspec, but just in case... */
|
|
|
|
+#define LSQLITE_VERSION "unknown"
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/* Version number of this library
|
|
|
|
+*/
|
|
|
|
+static int lsqlite_lversion(lua_State *L) {
|
|
|
|
+ lua_pushstring(L, LSQLITE_VERSION);
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
** =======================================================
|
|
** =======================================================
|
|
** Register functions
|
|
** Register functions
|
|
@@ -2003,6 +2057,7 @@ static const luaL_Reg dblib[] = {
|
|
{"create_function", db_create_function },
|
|
{"create_function", db_create_function },
|
|
{"create_aggregate", db_create_aggregate },
|
|
{"create_aggregate", db_create_aggregate },
|
|
{"create_collation", db_create_collation },
|
|
{"create_collation", db_create_collation },
|
|
|
|
+ {"load_extension", db_load_extension },
|
|
|
|
|
|
{"trace", db_trace },
|
|
{"trace", db_trace },
|
|
{"progress_handler", db_progress_handler },
|
|
{"progress_handler", db_progress_handler },
|
|
@@ -2063,6 +2118,8 @@ static const luaL_Reg vmlib[] = {
|
|
{"urows", dbvm_urows },
|
|
{"urows", dbvm_urows },
|
|
{"nrows", dbvm_nrows },
|
|
{"nrows", dbvm_nrows },
|
|
|
|
|
|
|
|
+ {"last_insert_rowid", dbvm_last_insert_rowid },
|
|
|
|
+
|
|
/* compatibility names (added by request) */
|
|
/* compatibility names (added by request) */
|
|
{"idata", dbvm_get_values },
|
|
{"idata", dbvm_get_values },
|
|
{"inames", dbvm_get_names },
|
|
{"inames", dbvm_get_names },
|
|
@@ -2097,6 +2154,7 @@ static const luaL_Reg ctxlib[] = {
|
|
};
|
|
};
|
|
|
|
|
|
static const luaL_Reg sqlitelib[] = {
|
|
static const luaL_Reg sqlitelib[] = {
|
|
|
|
+ {"lversion", lsqlite_lversion },
|
|
{"version", lsqlite_version },
|
|
{"version", lsqlite_version },
|
|
{"complete", lsqlite_complete },
|
|
{"complete", lsqlite_complete },
|
|
#ifndef WIN32
|
|
#ifndef WIN32
|
|
@@ -2122,14 +2180,12 @@ static void create_meta(lua_State *L, const char *name, const luaL_Reg *lib) {
|
|
lua_pop(L, 1);
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-static int luaopen_sqlitelib (lua_State *L) {
|
|
|
|
- luaL_newlibtable(L, sqlitelib);
|
|
|
|
- luaL_setfuncs(L, sqlitelib, 0);
|
|
|
|
- return 1;
|
|
|
|
|
|
+static int luaopen_sqlitelib (lua_State *L) {
|
|
|
|
+ luaL_newlibtable(L, sqlitelib);
|
|
|
|
+ luaL_setfuncs(L, sqlitelib, 0);
|
|
|
|
+ return 1;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
LUALIB_API int luaopen_lsqlite3(lua_State *L) {
|
|
LUALIB_API int luaopen_lsqlite3(lua_State *L) {
|
|
create_meta(L, sqlite_meta, dblib);
|
|
create_meta(L, sqlite_meta, dblib);
|
|
create_meta(L, sqlite_vm_meta, vmlib);
|
|
create_meta(L, sqlite_vm_meta, vmlib);
|
|
@@ -2138,7 +2194,7 @@ LUALIB_API int luaopen_lsqlite3(lua_State *L) {
|
|
luaL_getmetatable(L, sqlite_ctx_meta);
|
|
luaL_getmetatable(L, sqlite_ctx_meta);
|
|
sqlite_ctx_meta_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
sqlite_ctx_meta_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
|
|
|
|
- /* register (local) sqlite metatable */
|
|
|
|
|
|
+ /* register global sqlite3 library */
|
|
luaL_requiref(L, "sqlite3", luaopen_sqlitelib, 1);
|
|
luaL_requiref(L, "sqlite3", luaopen_sqlitelib, 1);
|
|
|
|
|
|
{
|
|
{
|
|
@@ -2146,7 +2202,7 @@ LUALIB_API int luaopen_lsqlite3(lua_State *L) {
|
|
/* add constants to global table */
|
|
/* add constants to global table */
|
|
while (sqlite_constants[i].name) {
|
|
while (sqlite_constants[i].name) {
|
|
lua_pushstring(L, sqlite_constants[i].name);
|
|
lua_pushstring(L, sqlite_constants[i].name);
|
|
- lua_pushnumber(L, sqlite_constants[i].value);
|
|
|
|
|
|
+ lua_pushinteger(L, sqlite_constants[i].value);
|
|
lua_rawset(L, -3);
|
|
lua_rawset(L, -3);
|
|
++i;
|
|
++i;
|
|
}
|
|
}
|