/*=============================================
// sqlite for Lua 5.0
// 2003-Feb-28 doug.currie@alum.mit.edu
// The author disclaims copyright to this document.  In place of
// a legal notice, here is a blessing:
//
//    May you do good and not evil.
//    May you find forgiveness for yourself and forgive others.
//    May you share freely, never taking more than you give.
//
// Thank-you to D. Richard Hipp.
// ============================================
// this Lua extension was built to be used
// with the 'loadmodule' by Thatcher Ulrich
// http://lua-users.org/wiki/LuaBinaryModules
//=============================================*/

----
== status ==

The LuaSqlite LuaBinaryModules module builds and is tested on Windows 2000 
with sqlite version 2.8.0. The included Makefile is used with mingw-msys to build
the module. There is a small test file that also serves as an example of usage.

The module is built with sqlite option {{THREADSAFE}} although this has not been
thoroughly tested.

The module uses the sqlite no-callback API. I found it necessary to include the sqlite 
{{exec}} function, a part of the callback API, because a bug in 2.8.0 prevents the 
use of some PRAGMAs with the no-callback API (even though there are no callbacks!).

The sqlite user functions, and other parts of the callback API (e.g., callbacks!) are 
not implemented. I have no need for them, but if you want to add them, go for it.
Also unimplemented is the {{sqlite_complete}} function; this can now be done with 
{{sqlite_compile}} in no-callback API style.

----
== guide ==

See [Files:wiki_insecure/binary_modules/luasqlite/test.lua test.lua] for examples of 
LuaSqlite usage.

See http://www.sqlite.org/ for info about using sqlite.

The module defines a userdata type usually referred to below as {{db}}. The {{db}}
holds the result of the {{sqlite.open}} call, and also the vm returned by 
{{sqlite.compile}}, and the data returned by {{sqlite.step}}. If you need to have 
several vm open at once, use multiple {{sqlite.open}} calls to create multiple {{db}}
instances. The {{db}} has a {{__gc}} method to reclaim the space used by the vm
and close the database. These things can also be done using the {{sqlite.finalize}} 
and {{sqlite.close}} calls.

{{sqlite.version()}} returns the sqlite version as a string, e.g., {{"2.8.0"}}

{{sqlite.encoding()}} returns the sqlite character encoding as a string, e.g., {{"iso8859"}}

The following values correspond to the like-named sqlite return codes:
	* {{sqlite.OK}}
	* {{sqlite.BUSY}}
	* {{sqlite.DONE}}
	* {{sqlite.ERROR}}
	* {{sqlite.MISUSE}}
	* {{sqlite.ROW}}

These return codes are the most useful with the no-callback API. Others may occur, and
can be grokked with...

{{sqlite.error_string(e)}} returns the sqlite error string corresponding to return code {{e}}

{{sqlite.open(filename)}} opens or creates a database file; it returns two values: a 
userdata {{db}} representing the database, and an error message string. The {{db}} 
will be {{nil}} if there is an error.

{{sqlite.close(db)}} closes the database {{db}} and reclaims memory.

Running a query is a three step process: compile the query, step it, finalize.

{{sqlite.compile(db,sql)}} compiles a query, and updates the {{db}} with the resulting 
vm. It returns the usual sqlite result code, and a number that tells the length of the 
query text. This number can be used to determine if all of {{sql}} was consumed.

{{sqlite.step(db)}} advances the compiled query to the next row, and returns the usual
sqlite return code. The row data is stored in the {db}. The result code will be 
{{sqlite.ROW}} is there is a row of data available, {{sqlite.DONE}} if the query is 
finished, and {{sqlite.BUSY}} is the database is locked. Other error codes are uncool.
''Note: there is a bug in sqlite 2.8.0 when processing EXPLAIN queries, instead of
{{sqlite.DONE}}, {{sqlite.OK}} is returned by {{sqlite.step(db)}}.'' 

After a call to {{sqlite.step(db)}} the following can be used to extract the info...

{{sqlite.row_data(db)}} returns a table of '''column name''' and '''row data''' pairs.

{{sqlite.row_type(db)}} returns a table of '''column name''' and '''column type''' pairs.

{{sqlite.row_idata(db)}} returns an array of '''row data'''.

{{sqlite.row_iname(db)}} returns an array of '''column name'''.

{{sqlite.row_itype(db)}} returns an array of '''column type'''.

{{sqlite.finalize(db)}} completes the query and reclaims any space used by the vm. It 
returns the usual sqlite result code. Finalize may be called before all the rows are read
if you are done with this query.

{{sqlite.last_insert_rowid(db)}} returns the row ID of the last insert.

{{sqlite.changes(db)}} returns the number of rows modified by the last query.

{{sqlite.interrupt(db)}} stops the query presently running on the {{db}} -- not tested.

{{sqlite.busy_timeout(db,ms)}} sets the busy timeout -- not tested.

{{sqlite.exec(db,sql)}} executes the sql string; it returns the usual result code.
The sql results are unavailable. This is provided to execute PRAGMAs that cannot 
be run with {{sqlite.compile(db,sql)}} due to a bug in 2.8.0.

----
== setup ==

See the mingw-msys heading in BuildingLua for my Lua 5.0-beta config and make files.

My setup for building LuaSqlite is to create a {{mods}} directory under {{lua-5.0-beta}} 
and a {{sqlite}} directory under {{mods}}. In the {{sqlite}} directory are
	* lsqlite.c [Files:wiki_insecure/binary_modules/luasqlite/lsqlite.c] 
	* Makefile [Files:wiki_insecure/binary_modules/luasqlite/Makefile] 
	* readme.txt [Files:wiki_insecure/binary_modules/luasqlite/readme.txt] 
	* test.lua [Files:wiki_insecure/binary_modules/luasqlite/test.lua] 

Then I place the pre-processed sqlite source files in a directory under {{sqlite}} also 
called {{sqlite}} -- these files may be obtained here (below, full source) or from the 
[http://www.sqlite.org/download.html official sqlite distribution].

----
== downloads ==

	* binary for Windows [Files:wiki_insecure/binary_modules/luasqlite/lsqlite.zip]
	* full source with sqlite 2.8.0 [Files:wiki_insecure/binary_modules/luasqlite/lsqlite_src.zip]
	* otherwise get the individual files as described above

----
== comments ==
