mirror of
https://github.com/Egor00f/luasqlite3-kolibrios.git
synced 2025-09-11 14:39:57 +02:00
upload luasqlite3
This commit is contained in:
32
.vscode/c_cpp_properties.json
vendored
Normal file
32
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/../kolibrios/contrib/sdk/sources/newlib/libc/include",
|
||||
"${workspaceFolder}/../kolibrios/contrib/sdk/sources/sqlite3",
|
||||
"${workspaceFolder}/../kolibrios/contrib/C_Layer/INCLUDE",
|
||||
"${workspaceFolder}/../lua-kolibrios/src"
|
||||
],
|
||||
"defines": [],
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++11",
|
||||
"compilerPath": "C:/MinGW/msys/1.0/home/autobuild/tools/win32/bin/kos32-gcc.exe",
|
||||
"intelliSenseMode": "gcc-x86"
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/../kolibrios/contrib/sdk/sources/newlib/libc/include",
|
||||
"${workspaceFolder}/../kolibrios/contrib/sdk/sources/sqlite3",
|
||||
"${workspaceFolder}/../kolibrios/contrib/C_Layer/INCLUDE",
|
||||
"${workspaceFolder}/../lua-kolibrios/src"
|
||||
],
|
||||
"defines": [],
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++11",
|
||||
"compilerPath": "/home/autobuild/tools/win32/bin/kos32-gcc"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
9
.vscode/extensions.json
vendored
Normal file
9
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.cpptools-themes",
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"usernamehw.errorlens",
|
||||
"github.vscode-github-actions"
|
||||
]
|
||||
}
|
33
.vscode/settings.json
vendored
Normal file
33
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"kolibri_libini.h": "c",
|
||||
"lua.hpp": "cpp",
|
||||
"ksys.h": "c",
|
||||
"lua.h": "c",
|
||||
"luaconf.h": "c"
|
||||
},
|
||||
"editor.insertSpaces": false,
|
||||
"cSpell.enabled": true,
|
||||
"cSpell.words": [
|
||||
"kolibrios",
|
||||
"libini",
|
||||
"ksys_",
|
||||
"kolibri",
|
||||
"luaL_newlib",
|
||||
"luaL_pushfail",
|
||||
"luaL_checkinteger",
|
||||
"luaL_checkstring",
|
||||
"lua_pushstring",
|
||||
"lua_pushinteger",
|
||||
"lua_pushboolean",
|
||||
"lua_pushnil",
|
||||
"lua_setfield",
|
||||
"lua_gettop",
|
||||
"lua_isfunction",
|
||||
"lua_createtable",
|
||||
"lua_pcall",
|
||||
"LUALIB_API",
|
||||
"luaopen_",
|
||||
"lualibini_"
|
||||
],
|
||||
}
|
59
.vscode/tasks.json
vendored
Normal file
59
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Rebuild",
|
||||
"command": "-C ${workspaceFolder} rebuild",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"detail": "Rebuild this lib",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"options": {
|
||||
"shell": {
|
||||
"executable": "make",
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Build",
|
||||
"command": "-C ${workspaceFolder} build",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": false
|
||||
},
|
||||
"detail": "Build this lib",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"options": {
|
||||
"shell": {
|
||||
"executable": "make",
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Debug Build",
|
||||
"command": "-C ${workspaceFolder} \"MYCFLAGS=-DNDEBUG\" build",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": false
|
||||
},
|
||||
"detail": "Debug build this lib",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"options": {
|
||||
"shell": {
|
||||
"executable": "make",
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"version": "2.0.0"
|
||||
}
|
272
HISTORY
Normal file
272
HISTORY
Normal file
@@ -0,0 +1,272 @@
|
||||
2025-Januar-07
|
||||
|
||||
Port for KolibriOS
|
||||
|
||||
|
||||
2023-June-06
|
||||
|
||||
Version "0.9.6"
|
||||
|
||||
Added parameterised iterators.
|
||||
Added documentation warning static link issues.
|
||||
Fixed old links in docs.
|
||||
Added support for comercial CEROD feature.
|
||||
|
||||
2018-June-30
|
||||
|
||||
Version "0.9.5"
|
||||
|
||||
Since the "0.9.4-devel" release of this Lua library...
|
||||
|
||||
Lua 5.4 compatibility (backward compatible with Lua 5.3, 5.2, and Lua 5.1.5).
|
||||
|
||||
2016-November-13
|
||||
|
||||
Version "0.9.4"
|
||||
|
||||
Since the "0.9.3-devel" release of this Lua library...
|
||||
|
||||
Add functions db:get_ptr() and sqlite3.open_ptr(db_ptr) to pass a db connection between threads.
|
||||
Add function db:db_filename(name).
|
||||
Update sqlite3_open to sqlite3_open_v2 and add open flags constants.
|
||||
Thanks to Wolfgang Oertl!
|
||||
|
||||
Added second module 'lsqlite3complete' that statically links sqlite.c. Continue to use
|
||||
'lsqlite3' for dynamic linking to 'sqlite3.so' or 'sqlite3.dll'.
|
||||
|
||||
Added Online Backup API
|
||||
|
||||
Added unit tests for NULs in BLOBs and TEXT columns. (Refute defect report.)
|
||||
|
||||
Use lua_createtable() in lieu of lua_newtable() when number of table elements is known.
|
||||
This will improve performance.
|
||||
Thanks to Egil Hjelmeland for the suggestion.
|
||||
|
||||
2015-January-06
|
||||
|
||||
Version "0.9.3"
|
||||
|
||||
Since the "0.9.2-devel" release of this Lua library...
|
||||
|
||||
Added lversion() function to report library version, "0.9.3".
|
||||
|
||||
Added db:load_extension() function to support SQLite extension libraries.
|
||||
|
||||
Added some tests for new funcitons and Lua 5.3 64-bit integers in the database.
|
||||
|
||||
Fixed longstanding bug: if db is no longer live, it is auto-closed by gc, but there may still
|
||||
be live prepared statements. Executing these statements would produce an error. Prepared
|
||||
statements now hold a reference to the db to prevent it from being collected while the prepared
|
||||
statement is live. Manually closing the db will continue to finalize the statements, as before.
|
||||
|
||||
Fixed bug in PUSH_INT64 macro for Lua < 5.3 introduced in version 0.9.2-devel.
|
||||
|
||||
2015-January-04
|
||||
|
||||
Version "0.9.2-devel"
|
||||
|
||||
Since the "0.9.1-devel" release of this Lua library...
|
||||
|
||||
Lua 5.3 compatibility (backward compatible with Lua 5.2 and Lua 5.1.5).
|
||||
|
||||
Finally uses sqlite3_prepare_v2() to preserve detailed error codes in statement stepping
|
||||
|
||||
With Lua 5.3, 64-bit integer database values are supported for reading and writing columns;
|
||||
all other values, e.g., status and counts, are now also returned as integers. The only use of
|
||||
doubles is for values of that type read from or written to columns.
|
||||
|
||||
Added support for stmt:last_insert_rowid() as requested
|
||||
|
||||
2013-April-08
|
||||
|
||||
Version "0.9.1-devel"
|
||||
|
||||
Since the "0.9-devel" release of this Lua library...
|
||||
|
||||
Updated examples and tests from Dmitry Pashkevich.
|
||||
|
||||
2013-March-30
|
||||
|
||||
Version "0.9-devel"
|
||||
|
||||
Since the "0.8-devel" release of this Lua library...
|
||||
|
||||
Updates for Lua 5.2 (backward compatible with Lua 5.1.5).
|
||||
|
||||
Uses lunitx-0.6-1.rockspec for Lua 5.2 compatible testing.
|
||||
|
||||
Added sqlite3.update_hook(), sqlite3.commit_hook() and
|
||||
sqlite3.rollback_hook() at the suggesiton of Dmitry Pashkevich, who
|
||||
also contributed examples and some testing assistance on this release.
|
||||
|
||||
Converted Makefile to depend on luarocks.
|
||||
|
||||
2011-January-10
|
||||
|
||||
Version "0.8-devel"
|
||||
|
||||
Since the "0.7-devel" release of this Lua library...
|
||||
|
||||
Added a missing lua_pop in dbvm_bind_names()
|
||||
Now dbvm_bind_index() binds a boolean as 1 or 0
|
||||
Thanks to Ronny Dierckx
|
||||
|
||||
Since the "0.6-devel" release of this Lua library...
|
||||
|
||||
Made db_exec_callback thread safe.
|
||||
Thanks to Grant Robinson.
|
||||
|
||||
Bug fix in dbvm_bind_index error message.
|
||||
Thanks to Dirk Feytons.
|
||||
|
||||
Added a few casts and changed a few comments to ANSI C style.
|
||||
Thanks to Corey Stup.
|
||||
|
||||
Note that Thomas Lauer has a patch referenced on LuaForge
|
||||
to make collations thread safe(r). This issue is still
|
||||
under investigation: the patch has wide ranging affect
|
||||
and to me it appears unsafe wrt GC. The whole issue of
|
||||
thread references in callbacks deserves thorough review.
|
||||
A new design that places referenced values in the upvalues
|
||||
of the callback function (rather than in the registry of
|
||||
the function defining thread) would be preferable. It may
|
||||
also make sense to keep thread references in a shared
|
||||
environment of the library's functions, and/or require
|
||||
all callbacks to be defined in the main lua state (so
|
||||
they the state is guaranteed to outlive other threads).
|
||||
|
||||
-=-
|
||||
|
||||
2007-August-15 e
|
||||
|
||||
Version "0.6-devel"
|
||||
|
||||
Since the "0.5-devel" release of this Lua library...
|
||||
|
||||
Tested with SQLite 3.4.2
|
||||
|
||||
Added some documentation.
|
||||
|
||||
Thanks to Thomas Lauer...
|
||||
|
||||
Moved line 525 ("luaL_checktype(L, 2, LUA_TTABLE);")
|
||||
below the declarations to eliminate non-gcc compiler errors.
|
||||
|
||||
Added create-collation, and associated test case.
|
||||
|
||||
-=-
|
||||
|
||||
2006-October-02 e
|
||||
|
||||
Since the "0.1-devel" release of this Lua library...
|
||||
- updated for Lua 5.1
|
||||
- provide automatic re-preparation of queries after schema changes
|
||||
- made prepared statements with bindings work with for-loops
|
||||
- added some compatibility names
|
||||
- added many test cases, and ported Mike Roth's tests and examples
|
||||
|
||||
-=-
|
||||
|
||||
Below is a header comment from the 2004 "0.1" version of the library...
|
||||
|
||||
/************************************************************************
|
||||
$Id: lsqlite3.c,v 1.3 2004/09/05 17:50:32 tngd Exp $
|
||||
|
||||
To consider:
|
||||
------------
|
||||
|
||||
EXPERIMENTAL APIs
|
||||
|
||||
* sqlite3_progress_handler (implemented)
|
||||
* sqlite3_commit_hook
|
||||
|
||||
TODO?
|
||||
|
||||
* sqlite3_create_collation
|
||||
|
||||
Changes:
|
||||
04-09-2004
|
||||
----------
|
||||
* changed second return value of db:compile to be the rest of the
|
||||
sql statement that was not processed instead of the number of
|
||||
characters of sql not processed (situation in case of success).
|
||||
* progress callback register function parameter order changed.
|
||||
number of opcodes is given before the callback now.
|
||||
|
||||
29-08-2004 e
|
||||
------------
|
||||
* added version() (now supported in sqlite 3.0.5)
|
||||
* added db:errmsg db:errcode db:total_changes
|
||||
* rename vm:get_column to vm:get_value
|
||||
* merge in Tiago's v1.11 change in dbvm_tostring
|
||||
|
||||
23-06-2004 e
|
||||
------------
|
||||
* heavily revised for SQLite3 C API
|
||||
* row values now returned as native type (not always text)
|
||||
* added db:nrows (named rows)
|
||||
* added vm:bind_blob
|
||||
* added vm:get_column
|
||||
* removed encode_binary decode_binary (no longer needed or supported)
|
||||
* removed version encoding error_string (unsupported in v 3.0.1 -- soon?)
|
||||
|
||||
09-04-2004
|
||||
----------
|
||||
* renamed db:rows to db:urows
|
||||
* renamed db:prows to db:rows
|
||||
|
||||
* added vm:get_unames()
|
||||
* added vm:get_utypes()
|
||||
* added vm:get_uvalues()
|
||||
|
||||
08-04-2004
|
||||
----------
|
||||
* changed db:encoding() and db:version() to use sqlite_libencoding() and
|
||||
sqlite_libversion()
|
||||
|
||||
* added vm:columns()
|
||||
* added vm:get_named_types()
|
||||
* added vm:get_named_values()
|
||||
|
||||
* added db:prows - like db:rows but returns a table with the column values
|
||||
instead of returning multiple columns seperatly on each iteration
|
||||
|
||||
* added compatibility functions idata,iname,itype,data,type
|
||||
|
||||
* added luaopen_sqlite_module. allow the library to be loaded without
|
||||
setting a global variable. does the same as luaopen_sqlite, but does not
|
||||
set the global name "sqlite".
|
||||
|
||||
* vm:bind now also returns an error string in case of error
|
||||
|
||||
31-03-2004 - 01-04-2004
|
||||
-----------------------
|
||||
* changed most of the internals. now using references (luaL_ref) in
|
||||
most of the places
|
||||
|
||||
* make the virtual machine interface seperate from the database
|
||||
handle. db:compile now returns a vm handle
|
||||
|
||||
* added db:rows [for ... in db:rows(...) do ... end]
|
||||
|
||||
* added db:close_vm
|
||||
|
||||
* added sqlite.encode_binary and sqlite.decode_binary
|
||||
|
||||
* attempt to do a strict checking on the return type of the user
|
||||
defined functions returned values
|
||||
|
||||
18-01-2004
|
||||
----------
|
||||
* add check on sql function callback to ensure there is enough stack
|
||||
space to pass column values as parameters
|
||||
|
||||
03-12-2003
|
||||
----------
|
||||
* callback functions now have to return boolean values to abort or
|
||||
continue operation instead of a zero or non-zero value
|
||||
|
||||
06-12-2003
|
||||
----------
|
||||
* make version member of sqlite table a function instead of a string
|
||||
************************************************************************/
|
98
Makefile
Normal file
98
Makefile
Normal file
@@ -0,0 +1,98 @@
|
||||
# Makefile for lsqlite3 library for Lua
|
||||
# This file is old and crufty.
|
||||
# manual setup (change these to reflect your Lua installation)
|
||||
|
||||
|
||||
CC=kos32-gcc
|
||||
LD=kos32-ld
|
||||
STRIP=kos32-strip
|
||||
OBJCOPY=kos32-objcopy
|
||||
|
||||
KOLIBRIOS_REPO=../../kolibrios
|
||||
|
||||
C_LAYER_DIR=$(KOLIBRIOS_REPO)/contrib/C_Layer
|
||||
LUA_DIR=../../lua-kolibrios
|
||||
SQLITE3_DIR=$(SDK_DIR)/sources/sqlite3
|
||||
|
||||
SDK_DIR=$(KOLIBRIOS_REPO)/contrib/sdk
|
||||
NewLib_DIR=$(SDK_DIR)/sources/newlib
|
||||
SYSCFLAGS=-fno-ident -fomit-frame-pointer -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -I$(NewLib_DIR)/libc/include -I$(C_LAYER_DIR)/INCLUDE -I$(LUA_DIR)/src
|
||||
SYSLDFLAGS=--image-base 0 -Tapp-dynamic.lds
|
||||
SYSLIBS=-nostdlib -L $(SDK_DIR)/lib -L$(TOOLCHAIN_PATH)/lib -L$(TOOLCHAIN_PATH)/mingw32/lib -lgcc -lc.dll -ldll
|
||||
|
||||
LUAINC= -I$(LUA_DIR)/src
|
||||
LUALIB=$(LUA_DIR)/src/lua54.dll
|
||||
SQLITE3INC= -I$(SQLITE3_DIR)
|
||||
SQLITE3LIB= -L$(SQLITE3_DIR) -lsqlite3.dll
|
||||
# Windows' LUALIB is the same as the Lua executable's directory...
|
||||
# LUALIB= -L$(BASE)/bin -llua51
|
||||
#
|
||||
POD2HTML= perl -x -S doc/pod2html.pl
|
||||
|
||||
TMP=./tmp
|
||||
DISTDIR=./archive
|
||||
|
||||
# OS detection
|
||||
#
|
||||
SHFLAGS=-shared
|
||||
UNAME= $(shell uname)
|
||||
|
||||
_SO=dll
|
||||
|
||||
ifndef _SO
|
||||
$(error $(UNAME))
|
||||
$(error Unknown OS)
|
||||
endif
|
||||
|
||||
# no need to change anything below here - HAH!
|
||||
CFLAGS=$(SYSCFLAGS) $(INCS) $(DEFS) $(WARN) -O2 #$(SHFLAGS)
|
||||
WARN= -Wall #-ansi -pedantic
|
||||
INCS= $(LUAINC) $(SQLITE3INC)
|
||||
LIBS= $(SYSLIBS) $(LUALIB) $(SQLITE3LIB)
|
||||
SOFLAGS=-T dll.lds --entry _DllStartup
|
||||
|
||||
MYNAME= sqlite3
|
||||
MYLIB= l$(MYNAME)
|
||||
|
||||
VER=$(shell svnversion -c . | sed 's/.*://')
|
||||
TARFILE = $(DISTDIR)/$(MYLIB)-$(VER).tar.gz
|
||||
|
||||
OBJS= extras/extension-functions.o $(MYLIB).o
|
||||
T= $(MYLIB).$(_SO)
|
||||
|
||||
all: $(T)
|
||||
|
||||
test: $(T)
|
||||
$(LUAEXE) test.lua
|
||||
$(LUAEXE) tests-sqlite3.lua
|
||||
|
||||
$(T): $(OBJS) $()
|
||||
$(CC) $(SHFLAGS) $(SOFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
install: $(T) $(OBJS) $(SQLITE3_DIR)/libsqlite3.dll.a
|
||||
$(INSTALL) $< `$(INSTALLPATH) $(MYLIB)`
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $T core core.* a.out test.db
|
||||
|
||||
html:
|
||||
$(POD2HTML) --title="LuaSQLite 3" --infile=doc/lsqlite3.pod --outfile=doc/lsqlite3.html
|
||||
|
||||
dist: html
|
||||
echo 'Exporting...'
|
||||
mkdir -p $(TMP)
|
||||
mkdir -p $(DISTDIR)
|
||||
svn export . $(TMP)/$(MYLIB)-$(VER)
|
||||
mkdir -p $(TMP)/$(MYLIB)-$(VER)/doc
|
||||
cp -p doc/lsqlite3.html $(TMP)/$(MYLIB)-$(VER)/doc
|
||||
echo 'Compressing...'
|
||||
tar -zcf $(TARFILE) -C $(TMP) $(MYLIB)-$(VER)
|
||||
rm -fr $(TMP)/$(MYLIB)-$(VER)
|
||||
echo 'Done.'
|
||||
|
||||
.PHONY: all test clean dist install
|
||||
|
||||
$(MYLIB).o: lsqlite3.c
|
||||
extras/extension-functions.o: extras/extension-functions.c
|
||||
$(SQLITE3_DIR)/libsqlite3.dll.a:
|
||||
$(MAKE) -C $(SQLITE3_DIR) libsqlite3.dll.a
|
37
README
Normal file
37
README
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
LuaSQLite3 provides a means to manipulate SQLite3
|
||||
databases directly from lua using Lua 5.
|
||||
|
||||
There are two modules, identical except that one links
|
||||
SQLite3 dynamically, the other statically.
|
||||
|
||||
The module lsqlite3 links SQLite3 dynamically.
|
||||
To use this module you need the SQLite3 library.
|
||||
You can get it from http://www.sqlite.org/
|
||||
|
||||
The module lsqlite3complete links SQLite3 statically.
|
||||
The SQLite3 amalgamation source code is included in
|
||||
the LuaSQLite3 distribution.
|
||||
|
||||
Lua 5 is available from http://www.lua.org/
|
||||
|
||||
|
||||
## Build
|
||||
|
||||
```
|
||||
git clone https://github.com/Egor00f/lua-kolibrios.git
|
||||
git clone https://github.com/KolibriOS/kolibrios.git
|
||||
git clone https://github.com/Egor00f/luasqlite3-kolibrios.git
|
||||
|
||||
cd luasqlite3-kolibrios
|
||||
make all
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Instalation
|
||||
|
||||
1. install lua
|
||||
2. move `lsqlite3.dll` to `/kolibrios/lib/lua`
|
||||
3. rename(or copy) `/kolibrios/lib/sqlite.dll` to `/kolibrios/lib/libsqlite.dll`
|
||||
|
1207
doc/lsqlite3.wiki
Normal file
1207
doc/lsqlite3.wiki
Normal file
File diff suppressed because it is too large
Load Diff
35
examples/aggregate.lua
Normal file
35
examples/aggregate.lua
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
local sqlite3 = require("lsqlite3")
|
||||
|
||||
local db = sqlite3.open_memory()
|
||||
|
||||
assert( db:exec "CREATE TABLE test (col1, col2)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (1, 2)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (2, 4)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (3, 6)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (4, 8)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (5, 10)" )
|
||||
|
||||
do
|
||||
|
||||
local square_error_sum = 0
|
||||
|
||||
local function step(ctx, a, b)
|
||||
local error = a - b
|
||||
local square_error = error * error
|
||||
square_error_sum = square_error_sum + square_error
|
||||
end
|
||||
|
||||
local function final(ctx)
|
||||
ctx:result_number( square_error_sum / ctx:aggregate_count() )
|
||||
end
|
||||
|
||||
assert( db:create_aggregate("my_stats", 2, step, final) )
|
||||
|
||||
end
|
||||
|
||||
--for a,b in db:urows("SELECT col1, col2 FROM test")
|
||||
--do print("a b: ", a, b) end
|
||||
|
||||
for my_stats in db:urows("SELECT my_stats(col1, col2) FROM test")
|
||||
do print("my_stats:", my_stats) end
|
21
examples/function.lua
Normal file
21
examples/function.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
local sqlite3 = require("lsqlite3")
|
||||
|
||||
|
||||
local db = sqlite3.open_memory()
|
||||
|
||||
assert( db:exec "CREATE TABLE test (col1, col2)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (1, 2)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (2, 4)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (3, 6)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (4, 8)" )
|
||||
assert( db:exec "INSERT INTO test VALUES (5, 10)" )
|
||||
|
||||
assert( db:create_function("my_sum", 2, function(ctx, a, b)
|
||||
ctx:result_number( a + b )
|
||||
end))
|
||||
|
||||
|
||||
for col1, col2, sum in db:urows("SELECT *, my_sum(col1, col2) FROM test") do
|
||||
print(col1, col2, sum)
|
||||
end
|
349
examples/hooks_advanced.lua
Normal file
349
examples/hooks_advanced.lua
Normal file
@@ -0,0 +1,349 @@
|
||||
|
||||
local sqlite3 = require("lsqlite3")
|
||||
local db
|
||||
|
||||
optbl = { [sqlite3.UPDATE] = "UPDATE";
|
||||
[sqlite3.INSERT] = "INSERT";
|
||||
[sqlite3.DELETE] = "DELETE"
|
||||
}
|
||||
setmetatable(optbl,
|
||||
{__index=function(t,n) return string.format("Unknown op %d",n) end})
|
||||
|
||||
|
||||
function update_hook(ud, op, dname, tname, rowid)
|
||||
print("Sqlite Update Hook:", optbl[op], dname, tname, rowid)
|
||||
end
|
||||
|
||||
function commit_hook(ud)
|
||||
print("<Sqlite Commit Hook>")
|
||||
end
|
||||
|
||||
function rollback_hook(ud)
|
||||
print("<Sqlite Rollback Hook>")
|
||||
end
|
||||
|
||||
-- db:exec wrapper with result assertion
|
||||
function db_exec(stmt)
|
||||
if db:exec(stmt) ~= sqlite3.OK then
|
||||
print("Sqlite ERROR: ", db:errmsg())
|
||||
end
|
||||
end
|
||||
|
||||
-- debug output for database table
|
||||
function db_print_tables(...)
|
||||
for i = 1,select('#',...) do
|
||||
name = select(i,...)
|
||||
print(string.format("\n%s contents:", name))
|
||||
for row in db:nrows("SELECT * FROM " .. name) do
|
||||
print(row.id, row.content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tests = {}
|
||||
|
||||
-- runs specified test with all necessary setup
|
||||
-- @param string name
|
||||
function run_test(name)
|
||||
-- banner
|
||||
print(string.format([[
|
||||
|
||||
|
||||
==========================
|
||||
%s
|
||||
==========================
|
||||
]], name))
|
||||
|
||||
-- setup
|
||||
db = sqlite3.open_memory()
|
||||
local udtbl = {0, 0, 0}
|
||||
db:update_hook(update_hook, udtbl)
|
||||
db:commit_hook(commit_hook, udtbl)
|
||||
db:rollback_hook(rollback_hook, udtbl)
|
||||
|
||||
-- run test
|
||||
tests[name]()
|
||||
|
||||
-- destroy
|
||||
db:close()
|
||||
end
|
||||
|
||||
|
||||
function tests.insert_select()
|
||||
db_exec[[
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello World');
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Lua');
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Sqlite3');
|
||||
|
||||
INSERT INTO T2 SELECT * FROM T1;
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2')
|
||||
end
|
||||
|
||||
function tests.trigger_insert()
|
||||
db_exec[[
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
|
||||
CREATE TRIGGER after_insert_T1
|
||||
AFTER INSERT ON T1
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT INTO T2 VALUES(NEW.id, NEW.content);
|
||||
END;
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello World');
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Lua');
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Sqlite3');
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2')
|
||||
end
|
||||
|
||||
function tests.cascade_delete()
|
||||
db_exec[[
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY REFERENCES T1 ON DELETE CASCADE, content VARCHAR );
|
||||
CREATE TABLE T3 ( id INTEGER PRIMARY KEY REFERENCES T2 ON DELETE CASCADE, content VARCHAR );
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'a');
|
||||
INSERT INTO T1 VALUES (NULL, 'b');
|
||||
INSERT INTO T1 VALUES (NULL, 'c');
|
||||
INSERT INTO T1 VALUES (NULL, 'd');
|
||||
|
||||
INSERT INTO T2 SELECT * FROM T1;
|
||||
INSERT INTO T3 SELECT * FROM T2;
|
||||
|
||||
DELETE FROM T1 WHERE id < 3;
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2', 'T3')
|
||||
end
|
||||
|
||||
function tests.cascade_update()
|
||||
db_exec[[
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY REFERENCES T1 ON UPDATE CASCADE, content VARCHAR );
|
||||
CREATE TABLE T3 ( id INTEGER PRIMARY KEY REFERENCES T2 ON UPDATE CASCADE, content VARCHAR );
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'a');
|
||||
INSERT INTO T1 VALUES (NULL, 'b');
|
||||
INSERT INTO T1 VALUES (NULL, 'c');
|
||||
INSERT INTO T1 VALUES (NULL, 'd');
|
||||
|
||||
INSERT INTO T2 SELECT * FROM T1;
|
||||
INSERT INTO T3 SELECT * FROM T2;
|
||||
|
||||
UPDATE T1 SET id = id + 10 WHERE id < 3;
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2', 'T3')
|
||||
end
|
||||
|
||||
-- hook "anomaly"
|
||||
-- implicit one-statement transaction rollback demonstration
|
||||
function tests.cascade_update_restrict()
|
||||
db_exec[[
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY REFERENCES T1 ON UPDATE RESTRICT, content VARCHAR );
|
||||
CREATE TABLE T3 ( id INTEGER PRIMARY KEY REFERENCES T2 ON UPDATE RESTRICT, content VARCHAR );
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'a');
|
||||
INSERT INTO T1 VALUES (NULL, 'b');
|
||||
INSERT INTO T1 VALUES (NULL, 'c');
|
||||
INSERT INTO T1 VALUES (NULL, 'd');
|
||||
|
||||
INSERT INTO T2 SELECT * FROM T1;
|
||||
INSERT INTO T3 SELECT * FROM T2;
|
||||
|
||||
-- this update gets reverted but the update_hook with rowid=11 *DOES* get triggered
|
||||
UPDATE T1 SET id = id + 10 WHERE id < 3;
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2', 'T3')
|
||||
end
|
||||
|
||||
-- hook "anomaly"
|
||||
-- case is analogous to cascade_update_restrict
|
||||
function tests.cascade_delete_restrict()
|
||||
db_exec[[
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY REFERENCES T1 ON DELETE RESTRICT, content VARCHAR );
|
||||
CREATE TABLE T3 ( id INTEGER PRIMARY KEY REFERENCES T2 ON DELETE RESTRICT, content VARCHAR );
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'a');
|
||||
INSERT INTO T1 VALUES (NULL, 'b');
|
||||
INSERT INTO T1 VALUES (NULL, 'c');
|
||||
INSERT INTO T1 VALUES (NULL, 'd');
|
||||
|
||||
INSERT INTO T2 SELECT * FROM T1;
|
||||
INSERT INTO T3 SELECT * FROM T2;
|
||||
|
||||
DELETE FROM T1 WHERE id < 3;
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2', 'T3')
|
||||
end
|
||||
|
||||
-- no anomalies here
|
||||
function tests.fk_violate_insert()
|
||||
db_exec[[
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY REFERENCES T1, content VARCHAR);
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'a');
|
||||
INSERT INTO T1 VALUES (NULL, 'b');
|
||||
|
||||
INSERT INTO T2 VALUES(99, 'xxx');
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2')
|
||||
end
|
||||
|
||||
-- hook "anomaly"
|
||||
function tests.fk_violate_update()
|
||||
db_exec[[
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY REFERENCES T1, content VARCHAR);
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'a');
|
||||
INSERT INTO T1 VALUES (NULL, 'b');
|
||||
INSERT INTO T2 VALUES(1, 'a');
|
||||
|
||||
-- update doesn't succeed but we get a hook for tuple with rowid=99 in T2
|
||||
UPDATE T2 SET id = 99 WHERE id = 1;
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2')
|
||||
end
|
||||
|
||||
-- like fk_violate_update but wrapped inside an explicit transaction
|
||||
function tests.transaction_fk_violate_update()
|
||||
db_exec[[
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY REFERENCES T1, content VARCHAR);
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
INSERT INTO T1 VALUES (NULL, 'a');
|
||||
INSERT INTO T1 VALUES (NULL, 'b');
|
||||
INSERT INTO T2 VALUES(1, 'a');
|
||||
|
||||
-- Doesn't trigger rollback hook because the implicit update statement transaction
|
||||
-- is nested inside our explicit transaction. However we *do* get an error.
|
||||
UPDATE T2 SET id = 99 WHERE id = 1;
|
||||
COMMIT;
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2')
|
||||
end
|
||||
|
||||
function tests.cascade_update_setnull()
|
||||
db_exec[[
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
CREATE TABLE T2 ( id INTEGER PRIMARY KEY, content INTEGER REFERENCES T1(id) ON UPDATE SET NULL);
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'a');
|
||||
INSERT INTO T1 VALUES (NULL, 'b');
|
||||
INSERT INTO T1 VALUES (NULL, 'c');
|
||||
INSERT INTO T1 VALUES (NULL, 'd');
|
||||
|
||||
INSERT INTO T2 SELECT NULL, id FROM T1;
|
||||
|
||||
UPDATE T1 SET id = id + 10 WHERE id < 3;
|
||||
]]
|
||||
|
||||
db_print_tables('T1', 'T2')
|
||||
end
|
||||
|
||||
function tests.transaction_commit()
|
||||
db_exec[[
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello World');
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Lua');
|
||||
COMMIT;
|
||||
]]
|
||||
|
||||
db_print_tables('T1')
|
||||
end
|
||||
|
||||
function tests.transaction_rollback()
|
||||
db_exec[[
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello World');
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Lua');
|
||||
ROLLBACK;
|
||||
]]
|
||||
|
||||
db_print_tables('T1')
|
||||
end
|
||||
|
||||
function tests.savepoint_nested_commit()
|
||||
db_exec[[
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
|
||||
SAVEPOINT S1;
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello World');
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Lua');
|
||||
|
||||
SAVEPOINT S2;
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Sqlite3');
|
||||
-- nested commit doesn't trigger commit_hook
|
||||
RELEASE S2;
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello transactions');
|
||||
RELEASE S1;
|
||||
]]
|
||||
|
||||
db_print_tables('T1')
|
||||
end
|
||||
|
||||
function tests.savepoint_nested_rollback()
|
||||
db_exec[[
|
||||
CREATE TABLE T1 ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
|
||||
SAVEPOINT S1;
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello World');
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Lua');
|
||||
|
||||
SAVEPOINT S2;
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello Sqlite3');
|
||||
-- nested rollback doesn't trigger rollback_hook
|
||||
ROLLBACK TO S2;
|
||||
|
||||
INSERT INTO T1 VALUES (NULL, 'Hello transactions');
|
||||
RELEASE S1;
|
||||
]]
|
||||
|
||||
db_print_tables('T1')
|
||||
end
|
||||
|
||||
|
||||
-- run_test('fk_violate_insert')
|
||||
|
||||
for k,v in pairs(tests) do
|
||||
run_test(k)
|
||||
end
|
122
examples/order.lua
Normal file
122
examples/order.lua
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
local sqlite3 = require("lsqlite3")
|
||||
|
||||
local db = assert( sqlite3:open_memory() )
|
||||
|
||||
assert( db:exec[[
|
||||
|
||||
CREATE TABLE customer (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name VARCHAR(40)
|
||||
);
|
||||
|
||||
CREATE TABLE invoice (
|
||||
id INTEGER PRIMARY KEY,
|
||||
customer INTEGER NOT NULL,
|
||||
title VARCHAR(80) NOT NULL,
|
||||
article1 VARCHAR(40) NOT NULL,
|
||||
price1 REAL NOT NULL,
|
||||
article2 VARCHAR(40),
|
||||
price2 REAL
|
||||
);
|
||||
|
||||
CREATE TABLE invoice_overflow (
|
||||
id INTEGER PRIMARY KEY,
|
||||
invoice INTEGER NOT NULL,
|
||||
article VARCHAR(40) NOT NULL,
|
||||
price REAL NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO customer VALUES(
|
||||
1, "Michael" );
|
||||
|
||||
INSERT INTO invoice VALUES(
|
||||
1, 1, "Computer parts", "harddisc", 89.90, "floppy", 9.99 );
|
||||
|
||||
INSERT INTO customer VALUES(
|
||||
2, "John" );
|
||||
|
||||
INSERT INTO invoice VALUES(
|
||||
2, 2, "Somme food", "apples", 2.79, "pears", 5.99 );
|
||||
|
||||
INSERT INTO invoice_overflow VALUES(
|
||||
NULL, 2, "grapes", 6.34 );
|
||||
|
||||
INSERT INTO invoice_overflow VALUES(
|
||||
NULL, 2, "strawberries", 4.12 );
|
||||
|
||||
INSERT INTO invoice_overflow VALUES(
|
||||
NULL, 2, "tomatoes", 6.17 );
|
||||
|
||||
INSERT INTO invoice VALUES(
|
||||
3, 2, "A new car", "Cybercar XL-1000", 65000.00, NULL, NULL );
|
||||
|
||||
]] )
|
||||
|
||||
|
||||
local function customer_name(id)
|
||||
local stmt = db:prepare("SELECT name FROM customer WHERE id = ?")
|
||||
stmt:bind_values(id)
|
||||
stmt:step()
|
||||
local r = stmt:get_uvalues()
|
||||
stmt:finalize()
|
||||
return r
|
||||
end
|
||||
|
||||
|
||||
local function all_invoices()
|
||||
return db:nrows("SELECT id, customer, title FROM invoice")
|
||||
end
|
||||
|
||||
|
||||
local function all_articles(invoice)
|
||||
|
||||
local function iterator()
|
||||
local stmt, row
|
||||
|
||||
-- Get the articles that are contained in the invoice table itself.
|
||||
stmt = db:prepare("SELECT article1, price1, article2, price2 FROM invoice WHERE id = ?")
|
||||
stmt:bind_values(invoice)
|
||||
stmt:step()
|
||||
row = stmt:get_named_values()
|
||||
|
||||
-- Every Invoice has at least one article.
|
||||
coroutine.yield(row.article1, row.price1)
|
||||
|
||||
-- Maybe the Invoice has a second article?
|
||||
if row.article2 then
|
||||
|
||||
-- Yes, there is a second article, so return it.
|
||||
coroutine.yield(row.article2, row.price2)
|
||||
|
||||
-- When there was an second article, maybe there are even
|
||||
-- more articles in the overflow table? We will see...
|
||||
|
||||
stmt = db:prepare("SELECT article, price FROM invoice_overflow WHERE invoice = ? ORDER BY id")
|
||||
stmt:bind_values(invoice)
|
||||
|
||||
for row in stmt:nrows() do
|
||||
coroutine.yield(row.article, row.price)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return coroutine.wrap(iterator)
|
||||
end
|
||||
|
||||
|
||||
for invoice in all_invoices() do
|
||||
local id = invoice.id
|
||||
local name = customer_name(invoice.customer)
|
||||
local title = invoice.title
|
||||
|
||||
print()
|
||||
print("Invoice #"..id..", "..name..": '"..title.."'")
|
||||
print("----------------------------------------")
|
||||
|
||||
for article, price in all_articles(id) do
|
||||
print( string.format("%20s %8.2f", article, price) )
|
||||
end
|
||||
|
||||
print()
|
||||
end
|
16
examples/simple.lua
Normal file
16
examples/simple.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
local sqlite3 = require("lsqlite3")
|
||||
|
||||
local db = sqlite3.open_memory()
|
||||
|
||||
db:exec[[
|
||||
CREATE TABLE test (id INTEGER PRIMARY KEY, content);
|
||||
|
||||
INSERT INTO test VALUES (NULL, 'Hello World');
|
||||
INSERT INTO test VALUES (NULL, 'Hello Lua');
|
||||
INSERT INTO test VALUES (NULL, 'Hello Sqlite3')
|
||||
]]
|
||||
|
||||
for row in db:nrows("SELECT * FROM test") do
|
||||
print(row.id, row.content)
|
||||
end
|
22
examples/smart.lua
Normal file
22
examples/smart.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
local sqlite3 = require("lsqlite3")
|
||||
|
||||
local db = sqlite3.open_memory()
|
||||
|
||||
db:exec[[ CREATE TABLE test (id INTEGER PRIMARY KEY, content) ]]
|
||||
|
||||
local stmt = db:prepare[[ INSERT INTO test VALUES (:key, :value) ]]
|
||||
|
||||
stmt:bind_names{ key = 1, value = "Hello World" }
|
||||
stmt:step()
|
||||
stmt:reset()
|
||||
stmt:bind_names{ key = 2, value = "Hello Lua" }
|
||||
stmt:step()
|
||||
stmt:reset()
|
||||
stmt:bind_names{ key = 3, value = "Hello Sqlite3" }
|
||||
stmt:step()
|
||||
stmt:finalize()
|
||||
|
||||
for row in db:nrows("SELECT * FROM test") do
|
||||
print(row.id, row.content)
|
||||
end
|
39
examples/statement.lua
Normal file
39
examples/statement.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
local sqlite3 = require("lsqlite3")
|
||||
|
||||
local db = sqlite3.open_memory()
|
||||
|
||||
db:exec[[
|
||||
CREATE TABLE test (
|
||||
id INTEGER PRIMARY KEY,
|
||||
content VARCHAR
|
||||
);
|
||||
]]
|
||||
|
||||
local insert_stmt = assert( db:prepare("INSERT INTO test VALUES (NULL, ?)") )
|
||||
|
||||
local function insert(data)
|
||||
insert_stmt:bind_values(data)
|
||||
insert_stmt:step()
|
||||
insert_stmt:reset()
|
||||
end
|
||||
|
||||
local select_stmt = assert( db:prepare("SELECT * FROM test") )
|
||||
|
||||
local function select()
|
||||
for row in select_stmt:nrows() do
|
||||
print(row.id, row.content)
|
||||
end
|
||||
end
|
||||
|
||||
insert("Hello World")
|
||||
print("First:")
|
||||
select()
|
||||
|
||||
insert("Hello Lua")
|
||||
print("Second:")
|
||||
select()
|
||||
|
||||
insert("Hello Sqlite3")
|
||||
print("Third:")
|
||||
select()
|
20
examples/tracing.lua
Normal file
20
examples/tracing.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
local sqlite3 = require("lsqlite3")
|
||||
|
||||
local db = sqlite3.open_memory()
|
||||
|
||||
db:trace( function(ud, sql)
|
||||
print("Sqlite Trace:", sql)
|
||||
end )
|
||||
|
||||
db:exec[[
|
||||
CREATE TABLE test ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
|
||||
INSERT INTO test VALUES (NULL, 'Hello World');
|
||||
INSERT INTO test VALUES (NULL, 'Hello Lua');
|
||||
INSERT INTO test VALUES (NULL, 'Hello Sqlite3');
|
||||
]]
|
||||
|
||||
for row in db:rows("SELECT * FROM test") do
|
||||
-- NOP
|
||||
end
|
31
examples/update_hook.lua
Normal file
31
examples/update_hook.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
local sqlite3 = require("lsqlite3")
|
||||
|
||||
local db = sqlite3.open_memory()
|
||||
|
||||
optbl = { [sqlite3.UPDATE] = "UPDATE";
|
||||
[sqlite3.INSERT] = "INSERT";
|
||||
[sqlite3.DELETE] = "DELETE"
|
||||
}
|
||||
setmetatable(optbl,
|
||||
{__index=function(t,n) return string.format("Unknown op %d",n) end})
|
||||
|
||||
udtbl = {0, 0, 0}
|
||||
|
||||
db:update_hook( function(ud, op, dname, tname, rowid)
|
||||
print("Sqlite Update Hook:", optbl[op], dname, tname, rowid)
|
||||
end, udtbl)
|
||||
|
||||
db:exec[[
|
||||
CREATE TABLE test ( id INTEGER PRIMARY KEY, content VARCHAR );
|
||||
|
||||
INSERT INTO test VALUES (NULL, 'Hello World');
|
||||
INSERT INTO test VALUES (NULL, 'Hello Lua');
|
||||
INSERT INTO test VALUES (NULL, 'Hello Sqlite3');
|
||||
UPDATE test SET content = 'Hello Again World' WHERE id = 1;
|
||||
DELETE FROM test WHERE id = 2;
|
||||
]]
|
||||
|
||||
for row in db:nrows("SELECT * FROM test") do
|
||||
print(row.id, row.content)
|
||||
end
|
1947
extras/extension-functions.c
Normal file
1947
extras/extension-functions.c
Normal file
File diff suppressed because it is too large
Load Diff
14
extras/installpath.lua
Normal file
14
extras/installpath.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
-- Script to find the install path for a C module. Public domain.
|
||||
|
||||
if not arg or not arg[1] then
|
||||
io.write("Usage: lua installpath.lua modulename\n")
|
||||
os.exit(1)
|
||||
end
|
||||
for p in string.gfind(package.cpath, "[^;]+") do
|
||||
if string.sub(p, 1, 1) ~= "." then
|
||||
local p2 = string.gsub(arg[1], "%.", string.sub(package.config, 1, 1))
|
||||
io.write(string.gsub(p, "%?", p2), "\n")
|
||||
return
|
||||
end
|
||||
end
|
||||
error("no suitable installation path found")
|
39
lsqlite3-0.9.6-1.rockspec
Normal file
39
lsqlite3-0.9.6-1.rockspec
Normal file
@@ -0,0 +1,39 @@
|
||||
package = "lsqlite3"
|
||||
version = "0.9.6-1"
|
||||
source = {
|
||||
url = "http://lua.sqlite.org/index.cgi/zip/lsqlite3_v096.zip?uuid=v0.9.6",
|
||||
file = "lsqlite3_v096.zip",
|
||||
}
|
||||
description = {
|
||||
summary = "A binding for Lua to the SQLite3 database library",
|
||||
detailed = [[
|
||||
lsqlite3 is a thin wrapper around the public domain SQLite3 database engine. SQLite3 is
|
||||
dynamically linked to lsqlite3. The statically linked alternative is lsqlite3complete.
|
||||
The lsqlite3 module supports the creation and manipulation of SQLite3 databases.
|
||||
Most sqlite3 functions are called via an object-oriented interface to either
|
||||
database or SQL statement objects.
|
||||
]],
|
||||
license = "MIT",
|
||||
homepage = "http://lua.sqlite.org/",
|
||||
}
|
||||
dependencies = {
|
||||
"lua >= 5.1, < 5.5",
|
||||
}
|
||||
external_dependencies = {
|
||||
SQLITE = {
|
||||
header = "sqlite3.h",
|
||||
},
|
||||
}
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
lsqlite3 = {
|
||||
sources = { "lsqlite3.c" },
|
||||
defines = { 'LSQLITE_VERSION="0.9.6"' },
|
||||
libraries = { "sqlite3" },
|
||||
incdirs = { "$(SQLITE_INCDIR)" },
|
||||
libdirs = { "$(SQLITE_LIBDIR)" },
|
||||
},
|
||||
},
|
||||
copy_directories = { 'doc', 'examples' },
|
||||
}
|
2459
lsqlite3.c
Normal file
2459
lsqlite3.c
Normal file
File diff suppressed because it is too large
Load Diff
40
lsqlite3complete-0.9.6-1.rockspec
Normal file
40
lsqlite3complete-0.9.6-1.rockspec
Normal file
@@ -0,0 +1,40 @@
|
||||
package = "lsqlite3complete"
|
||||
version = "0.9.6-1"
|
||||
source = {
|
||||
url = "http://lua.sqlite.org/index.cgi/zip/lsqlite3_v096.zip?uuid=v0.9.6",
|
||||
file = "lsqlite3_v096.zip",
|
||||
}
|
||||
description = {
|
||||
summary = "A binding for Lua to the SQLite3 database library",
|
||||
detailed = [[
|
||||
lsqlite3complete is a thin wrapper around the public domain SQLite3 database engine.
|
||||
SQLite3 is included and statically linked. (The dynamically linked alternative is lsqlite3).
|
||||
The lsqlite3complete module supports the creation and manipulation of SQLite3 databases.
|
||||
Most sqlite3 functions are called via an object-oriented interface to either database
|
||||
or SQL statement objects.
|
||||
]],
|
||||
license = "MIT",
|
||||
homepage = "http://lua.sqlite.org/",
|
||||
}
|
||||
dependencies = {
|
||||
"lua >= 5.1, < 5.5",
|
||||
}
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
lsqlite3complete = {
|
||||
sources = { "lsqlite3.c", "sqlite3.c" },
|
||||
defines = {'LSQLITE_VERSION="0.9.6"', 'luaopen_lsqlite3=luaopen_lsqlite3complete'},
|
||||
},
|
||||
},
|
||||
platforms = {
|
||||
unix = {
|
||||
modules = {
|
||||
lsqlite3complete = {
|
||||
libraries = { "pthread", "m", "dl" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
copy_directories = { 'doc', 'examples' }
|
||||
}
|
68
test/test-dyld.lua
Normal file
68
test/test-dyld.lua
Normal file
@@ -0,0 +1,68 @@
|
||||
--
|
||||
-- test for load_extension
|
||||
--
|
||||
-- before running this script, you must compile extension-functions.c
|
||||
-- e.g., in directory extras:
|
||||
-- gcc -fno-common -dynamiclib extension-functions.c -o libsqlitefunctions.dylib
|
||||
--
|
||||
-- then run this script from the top level directory: lua test/test-dyld.lua
|
||||
|
||||
local sqlite3 = require "lsqlite3"
|
||||
|
||||
local os = os
|
||||
|
||||
local lunit = require "lunitx"
|
||||
|
||||
local tests_sqlite3
|
||||
|
||||
if _VERSION >= 'Lua 5.2' then
|
||||
|
||||
tests_sqlite3 = lunit.module('tests-sqlite3','seeall')
|
||||
_ENV = tests_sqlite3
|
||||
|
||||
else
|
||||
|
||||
module('tests_sqlite3', lunit.testcase, package.seeall)
|
||||
tests_sqlite3 = _M
|
||||
|
||||
end
|
||||
|
||||
-- compat
|
||||
|
||||
function lunit_wrap (name, fcn)
|
||||
tests_sqlite3['test_o_'..name] = fcn
|
||||
end
|
||||
|
||||
function lunit_TestCase (name)
|
||||
return lunit.module(name,'seeall')
|
||||
end
|
||||
|
||||
local db_dyld = lunit_TestCase("Load Extension")
|
||||
|
||||
function db_dyld.setup()
|
||||
db_dyld.db = assert( sqlite3.open_memory() )
|
||||
assert_equal( sqlite3.OK, db_dyld.db:exec("CREATE TABLE test (id, name)") )
|
||||
assert_equal( sqlite3.OK, db_dyld.db:exec("INSERT INTO test VALUES (1, 'Hello World')") )
|
||||
assert_equal( sqlite3.OK, db_dyld.db:exec("INSERT INTO test VALUES (2, 'Hello Lua')") )
|
||||
assert_equal( sqlite3.OK, db_dyld.db:exec("INSERT INTO test VALUES (3, 'Hello sqlite3')") )
|
||||
end
|
||||
|
||||
function db_dyld.teardown()
|
||||
assert( db_dyld.db:close() )
|
||||
end
|
||||
|
||||
function db_dyld.test()
|
||||
local db = db_dyld.db
|
||||
assert_function( db.load_extension )
|
||||
assert_true( db:load_extension "extras/libsqlitefunctions" )
|
||||
for row in db:nrows("SELECT log10(id) as val FROM test WHERE name='Hello World'") do
|
||||
assert_equal (row.val, 0.0)
|
||||
end
|
||||
for row in db:nrows("SELECT reverse(name) as val FROM test WHERE id = 2") do
|
||||
assert_equal (row.val, 'auL olleH')
|
||||
end
|
||||
for row in db:nrows("SELECT padl(name, 16) as val FROM test WHERE id = 3") do
|
||||
assert_equal (row.val, ' Hello sqlite3')
|
||||
end
|
||||
end
|
||||
|
153
test/test.lua
Normal file
153
test/test.lua
Normal file
@@ -0,0 +1,153 @@
|
||||
local sqlite3 = require("lsqlite3")
|
||||
|
||||
local width = 78
|
||||
local function line(pref, suff)
|
||||
pref = pref or ''
|
||||
suff = suff or ''
|
||||
local len = width - 2 - string.len(pref) - string.len(suff)
|
||||
print(pref .. string.rep('-', len) .. suff)
|
||||
end
|
||||
|
||||
local db, vm
|
||||
local assert_, assert = assert, function (test)
|
||||
if (not test) then
|
||||
error(db:errmsg(), 2)
|
||||
end
|
||||
end
|
||||
|
||||
line(sqlite3.version())
|
||||
|
||||
os.remove('test.db')
|
||||
db = sqlite3.open('test.db')
|
||||
|
||||
line(nil, 'db:exec')
|
||||
db:exec('CREATE TABLE t(a, b)')
|
||||
|
||||
line(nil, 'prepare')
|
||||
vm = db:prepare('insert into t values(?, :bork)')
|
||||
assert(vm, db:errmsg())
|
||||
assert(vm:bind_parameter_count() == 2)
|
||||
assert(vm:bind_values(2, 4) == sqlite3.OK)
|
||||
assert(vm:step() == sqlite3.DONE)
|
||||
assert(vm:reset() == sqlite3.OK)
|
||||
assert(vm:bind_names{ 'pork', bork = 'nono' } == sqlite3.OK)
|
||||
assert(vm:step() == sqlite3.DONE)
|
||||
assert(vm:reset() == sqlite3.OK)
|
||||
assert(vm:bind_names{ bork = 'sisi' } == sqlite3.OK)
|
||||
assert(vm:step() == sqlite3.DONE)
|
||||
assert(vm:reset() == sqlite3.OK)
|
||||
assert(vm:bind_names{ 1 } == sqlite3.OK)
|
||||
assert(vm:step() == sqlite3.DONE)
|
||||
assert(vm:finalize() == sqlite3.OK)
|
||||
|
||||
line("select * from t", 'db:exec')
|
||||
|
||||
assert(db:exec('select * from t', function (ud, ncols, values, names)
|
||||
--table.setn(values, 2)
|
||||
print((unpack or table.unpack)(values))
|
||||
return sqlite3.OK
|
||||
end) == sqlite3.OK)
|
||||
|
||||
line("select * from t", 'db:prepare')
|
||||
|
||||
vm = db:prepare('select * from t')
|
||||
assert(vm, db:errmsg())
|
||||
print(vm:get_unames())
|
||||
while (vm:step() == sqlite3.ROW) do
|
||||
print(vm:get_uvalues())
|
||||
end
|
||||
assert(vm:finalize() == sqlite3.OK)
|
||||
|
||||
|
||||
|
||||
line('udf', 'scalar')
|
||||
|
||||
local function do_query(sql)
|
||||
local r
|
||||
local vm = db:prepare(sql)
|
||||
assert(vm, db:errmsg())
|
||||
print('====================================')
|
||||
print(vm:get_unames())
|
||||
print('------------------------------------')
|
||||
r = vm:step()
|
||||
while (r == sqlite3.ROW) do
|
||||
print(vm:get_uvalues())
|
||||
r = vm:step()
|
||||
end
|
||||
assert(r == sqlite3.DONE)
|
||||
assert(vm:finalize() == sqlite3.OK)
|
||||
print('====================================')
|
||||
end
|
||||
|
||||
local function udf1_scalar(ctx, v)
|
||||
local ud = ctx:user_data()
|
||||
ud.r = (ud.r or '') .. tostring(v)
|
||||
ctx:result_text(ud.r)
|
||||
end
|
||||
|
||||
db:create_function('udf1', 1, udf1_scalar, { })
|
||||
do_query('select udf1(a) from t')
|
||||
|
||||
|
||||
line('udf', 'aggregate')
|
||||
|
||||
local function udf2_aggregate(ctx, ...)
|
||||
local ud = ctx:get_aggregate_data()
|
||||
if (not ud) then
|
||||
ud = {}
|
||||
ctx:set_aggregate_data(ud)
|
||||
end
|
||||
ud.r = (ud.r or 0) + 2
|
||||
end
|
||||
|
||||
local function udf2_aggregate_finalize(ctx, v)
|
||||
local ud = ctx:get_aggregate_data()
|
||||
ctx:result_number(ud and ud.r or 0)
|
||||
end
|
||||
|
||||
db:create_aggregate('udf2', 1, udf2_aggregate, udf2_aggregate_finalize, { })
|
||||
do_query('select udf2(a) from t')
|
||||
|
||||
if (true) then
|
||||
line(nil, '100 insert exec')
|
||||
db:exec('delete from t')
|
||||
local t = os.time()
|
||||
for i = 1, 100 do
|
||||
db:exec('insert into t values('..i..', '..(i * 2 * -1^i)..')')
|
||||
end
|
||||
print('elapsed: '..(os.time() - t))
|
||||
do_query('select count(*) from t')
|
||||
|
||||
line(nil, '100000 insert exec T')
|
||||
db:exec('delete from t')
|
||||
local t = os.time()
|
||||
db:exec('begin')
|
||||
for i = 1, 100000 do
|
||||
db:exec('insert into t values('..i..', '..(i * 2 * -1^i)..')')
|
||||
end
|
||||
db:exec('commit')
|
||||
print('elapsed: '..(os.time() - t))
|
||||
do_query('select count(*) from t')
|
||||
|
||||
line(nil, '100000 insert prepare/bind T')
|
||||
db:exec('delete from t')
|
||||
local t = os.time()
|
||||
local vm = db:prepare('insert into t values(?, ?)')
|
||||
db:exec('begin')
|
||||
for i = 1, 100000 do
|
||||
vm:bind_values(i, i * 2 * -1^i)
|
||||
vm:step()
|
||||
vm:reset()
|
||||
end
|
||||
vm:finalize()
|
||||
db:exec('commit')
|
||||
print('elapsed: '..(os.time() - t))
|
||||
do_query('select count(*) from t')
|
||||
|
||||
end
|
||||
|
||||
line(nil, "db:close")
|
||||
|
||||
assert(db:close() == sqlite3.OK)
|
||||
|
||||
line(sqlite3.version())
|
1408
test/tests-sqlite3.lua
Normal file
1408
test/tests-sqlite3.lua
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user