Changeset 15334 in project


Ignore:
Timestamp:
08/06/09 17:25:19 (10 years ago)
Author:
Thomas Chust
bzr:base-revision:
svn-v4:fca3e652-9b03-0410-8d7b-ac86a6ce46c4:release/4/sqlite3/trunk:15333
bzr:committer:
Thomas Chust <chust@web.de>
bzr:file-ids:

.bzrignore bzrignore-20090804013807-8nv9nqnf35k281ii-1
Makefile 4989@fca3e652-9b03-0410-8d7b-ac86a6ce46c4:sqlite3%2Ftags%2F1.5.9%2FMakefile
doc.scm 4989@fca3e652-9b03-0410-8d7b-ac86a6ce46c4:sqlite3%2Ftags%2F1.5.9%2Fdoc.scm
sqlite3.html 4989@fca3e652-9b03-0410-8d7b-ac86a6ce46c4:sqlite3%2Ftags%2F1.5.9%2Fsqlite3.html
sqlite3.meta 4989@fca3e652-9b03-0410-8d7b-ac86a6ce46c4:sqlite3%2Ftags%2F1.5.9%2Fsqlite3.meta
sqlite3.scm 4989@fca3e652-9b03-0410-8d7b-ac86a6ce46c4:sqlite3%2Ftags%2F1.5.9%2Fsqlite3.scm
sqlite3.setup 4989@fca3e652-9b03-0410-8d7b-ac86a6ce46c4:sqlite3%2Ftags%2F1.5.9%2Fsqlite3.setup
tests tests-20090806135642-4ijg0ujxlfdmodmf-1
tests/run.scm sqlite3.scm-20090806135642-4ijg0ujxlfdmodmf-2
bzr:mapping-version:
v4
bzr:merge:

chust@web.de-20090806152813-9djst8elxfwmb4rq
bzr:repository-uuid:
fca3e652-9b03-0410-8d7b-ac86a6ce46c4
bzr:revision-id:
chust@web.de-20090806154120-2raf4ni32ue1x6vx
bzr:revno:
21
bzr:revprop:branch-nick:
release/4/sqlite3/trunk
bzr:root:
release/4/sqlite3/trunk
bzr:text-parents:

Makefile chust@web.de-20090806124749-l4qrpxxy5vm80tfn
doc.scm chust@web.de-20090806124749-l4qrpxxy5vm80tfn
sqlite3.html chust@web.de-20090805163358-afe9cj0jwwj7hifx
sqlite3.meta chust@web.de-20090806124824-1xpbd04q591wqgeg
sqlite3.scm chust@web.de-20090806124749-l4qrpxxy5vm80tfn
sqlite3.setup chust@web.de-20090805231436-o4erfsxlsvqfzlpo
bzr:text-revisions:

.bzrignore chust@web.de-20090804013900-qyo15zusf90y1eo5
Makefile chust@web.de-20090806144351-ew266bq108o4vbqu
doc.scm chust@web.de-20090806144351-ew266bq108o4vbqu
sqlite3.html chust@web.de-20090806144351-ew266bq108o4vbqu
sqlite3.meta chust@web.de-20090806144351-ew266bq108o4vbqu
sqlite3.scm chust@web.de-20090806135452-oojz3c1m5ckhl4uk
sqlite3.setup chust@web.de-20090806144351-ew266bq108o4vbqu
tests chust@web.de-20090806144351-ew266bq108o4vbqu
tests/run.scm chust@web.de-20090806144351-ew266bq108o4vbqu
bzr:timestamp:
2009-08-06 17:41:20.256000042 +0200
bzr:user-agent:
bzr1.17+bzr-svn0.6.3
svn:original-date:
2009-08-06T15:41:20.256000Z
Message:

[sqlite3] Merged CHICKEN 4 specific local changes back into Subversion.

Location:
release/4/sqlite3/trunk
Files:
3 added
1 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • release/4/sqlite3/trunk/Makefile

    r4995 r15334  
     1# Makefile
     2# :tabSize=2:indentSize=2:noTabs=false:
     3# Egg build control
     4
    15CSI=csi
    26CSC=csc
    37TAR=tar
    48
    5 CSCFLAGS=-O2 -d0 -X easyffi -X tinyclos -check-imports
     9CSCFLAGS=-O2 -d1
     10IMPORT_CSCFLAGS=-O2 -d0
    611LDLIBS=-lsqlite3
    712
    813NAME=sqlite3
    9 VERSION=2.0.0
     14VERSION=3.2.1
    1015
    1116.PHONY: all clean
     
    1621        $(RM) $(addprefix $(NAME),.egg .so .html .setup)
    1722
    18 $(NAME).egg: $(addprefix $(NAME),.scm .html .setup) egg.jpg doc.scm Makefile
     23$(NAME).egg:    $(addprefix $(NAME),.scm .html .setup .meta) tests/run.scm egg.jpg doc.scm Makefile
    1924        $(TAR) czf $@ $^
    2025
     
    2328
    2429$(NAME).setup: Makefile
    25         echo "(define so-file \"sqlite3.so\")" >$@; \
    26         echo "(compile" >>$@; \
    27         echo "  $(CSCFLAGS) -s \"$(NAME).scm\" $(LDLIBS)" >>$@; \
    28         echo "  -o ,so-file -emit-exports \"$(NAME).exports\")" >>$@; \
     30        echo "(compile $(CSCFLAGS)" >$@; \
     31        echo "  -s \"$(NAME).scm\" $(LDLIBS) -j \"$(NAME)\")" >>$@; \
     32        echo "(compile $(IMPORT_CSCFLAGS)" >>$@; \
     33        echo "  -s \"$(NAME).import.scm\")" >>$@; \
     34        echo "(compile $(CSCFLAGS)" >>$@; \
     35        echo "  -c \"$(NAME).scm\" -unit \"$(NAME)\" -o \"$(NAME)-static.o\")" >>$@; \
    2936        echo "(install-extension" >>$@; \
    3037        echo "  '$(NAME)" >>$@; \
    31         echo "  \`(,so-file" >>$@; \
    32         echo "    \"$(NAME).html\" \"egg.jpg\")" >>$@; \
    33         echo "  '((version \"$(VERSION)\") (documentation \"$(NAME).html\")))" >>$@
     38        echo "  '(\"$(NAME).so\" \"$(NAME).import.so\" \"$(NAME)-static.o\")" >>$@; \
     39        echo "  '((version \"$(VERSION)\")" >>$@; \
     40        echo "    (static \"$(NAME)-static.o\")" >>$@; \
     41        echo "    (documentation \"$(NAME).html\" \"egg.jpg\")))" >>$@
    3442
    3543%.so: %.scm
  • release/4/sqlite3/trunk/doc.scm

    r10382 r15334  
     1;;;; doc.scm
     2;;;; :tabSize=2:indentSize=2:noTabs=true:
     3;;;; Documentation of the SQLite3 bindings
     4
    15(use eggdoc)
    26
     
    1014    (usage)
    1115    (download "sqlite3.egg")
    12     (requires "synch" "tinyclos" "easyffi" "miscmacros")
     16    (requires "check-errors" "synch" "miscmacros" "matchable")
    1317
    1418    (documentation
     
    1923      (subsection "Exceptions"
    2024
    21         (p "Unless otherwise indicated, all procedures and methods in this egg may throw an exception of the kind " (tt "(exn sqlite3)") " if something goes wrong. This exception will contain a " (tt "status") " property indicating the return value of the operation that failed:"
    22         (table
    23           (tr (th "Symbol") (th "Meaning"))
    24           #;(tr (td (tt "ok")) (td "Successful result"))
    25           (tr (td (tt "error")) (td "SQL error or missing database "))
    26           (tr (td (tt "internal")) (td "An internal logic error in SQLite "))
    27           (tr (td (tt "permission")) (td "Access permission denied "))
    28           (tr (td (tt "abort")) (td "Callback routine requested an abort "))
    29           (tr (td (tt "busy")) (td "The database file is locked "))
    30           (tr (td (tt "locked")) (td "A table in the database is locked "))
    31           (tr (td (tt "no-memory")) (td "A malloc() failed "))
    32           (tr (td (tt "read-only")) (td "Attempt to write a readonly database "))
    33           (tr (td (tt "interrupt")) (td "Operation terminated by sqlite-interrupt() "))
    34           (tr (td (tt "io-error")) (td "Some kind of disk I/O error occurred "))
    35           (tr (td (tt "corrupt")) (td "The database disk image is malformed "))
    36           (tr (td (tt "not-found")) (td "(Internal Only) Table or record not found "))
    37           (tr (td (tt "full")) (td "Insertion failed because database is full "))
    38           (tr (td (tt "cant-open")) (td "Unable to open the database file "))
    39           (tr (td (tt "protocol")) (td "Database lock protocol error "))
    40           (tr (td (tt "empty")) (td "(Internal Only) Database table is empty "))
    41           (tr (td (tt "schema")) (td "The database schema changed "))
    42           (tr (td (tt "too-big")) (td "Too much data for one row of a table "))
    43           (tr (td (tt "constraint")) (td "Abort due to contraint violation "))
    44           (tr (td (tt "mismatch")) (td "Data type mismatch "))
    45           (tr (td (tt "misuse")) (td "Library used incorrectly "))
    46           (tr (td (tt "no-lfs")) (td "Uses OS features not supported on host "))
    47           (tr (td (tt "authorization")) (td " Authorization denied"))
    48           #;(tr (td (tt "row")) (td (tt "sqlite3:step!") " has another row ready "))
    49           (tr (td (tt "done")) (td (tt "sqlite3:step!") " has finished executing, so no further data is ready")))))
    50 
    51       (subsection "Classes"
    52 
    53         (definition
    54           (signatures
    55             (signature "class" "<sqlite3:database>")
    56             (signature "class" "<sqlite3:statement>"))
    57           (p "These classes are derived from " (tt "<c++-object>") ". They hold a pointer to the underlying C-structure in their " (tt "this") " slot.")
    58           (p (tt "<sqlite3:statement>") " also has a " (tt "database") " slot pointing to the database object it belongs to.") ) )
     25  (p "Unless otherwise indicated, all procedures and methods in this egg may throw an exception of the kind " (tt "(exn sqlite3)") " if something goes wrong. This exception will contain a " (tt "status") " property indicating the return value of the operation that failed:"
     26  (table
     27    (tr (th "Symbol") (th "Meaning"))
     28    #;(tr (td (tt "ok")) (td "Successful result"))
     29    (tr (td (tt "error")) (td "SQL error or missing database "))
     30    (tr (td (tt "internal")) (td "An internal logic error in SQLite "))
     31    (tr (td (tt "permission")) (td "Access permission denied "))
     32    (tr (td (tt "abort")) (td "Callback routine requested an abort "))
     33    (tr (td (tt "busy")) (td "The database file is locked "))
     34    (tr (td (tt "locked")) (td "A table in the database is locked "))
     35    (tr (td (tt "no-memory")) (td "A malloc() failed "))
     36    (tr (td (tt "read-only")) (td "Attempt to write a readonly database "))
     37    (tr (td (tt "interrupt")) (td "Operation terminated by sqlite-interrupt() "))
     38    (tr (td (tt "io-error")) (td "Some kind of disk I/O error occurred "))
     39    (tr (td (tt "corrupt")) (td "The database disk image is malformed "))
     40    (tr (td (tt "not-found")) (td "(Internal Only) Table or record not found "))
     41    (tr (td (tt "full")) (td "Insertion failed because database is full "))
     42    (tr (td (tt "cant-open")) (td "Unable to open the database file "))
     43    (tr (td (tt "protocol")) (td "Database lock protocol error "))
     44    (tr (td (tt "empty")) (td "(Internal Only) Database table is empty "))
     45    (tr (td (tt "schema")) (td "The database schema changed "))
     46    (tr (td (tt "too-big")) (td "Too much data for one row of a table "))
     47    (tr (td (tt "constraint")) (td "Abort due to contraint violation "))
     48    (tr (td (tt "mismatch")) (td "Data type mismatch "))
     49    (tr (td (tt "misuse")) (td "Library used incorrectly "))
     50    (tr (td (tt "no-lfs")) (td "Uses OS features not supported on host "))
     51    (tr (td (tt "authorization")) (td " Authorization denied"))
     52    #;(tr (td (tt "row")) (td (tt "step!") " has another row ready "))
     53    (tr (td (tt "done")) (td (tt "step!") " has finished executing, so no further data is ready")))))
     54
     55      (subsection "Abstract data types"
     56
     57  (procedure ("(database? OBJECT) " (& "rArr") " BOOLEAN")
     58    (p "Checks whether a value represents an SQLite database."))
     59  (procedure ("(error-database LOCATION OBJECT [ARGUMENT-NAME]) " (& "rArr") " VOID")
     60    (p "Raises a type error saying that a database was expected instead "
     61       "of the given value."))
     62  (procedure ("(check-database LOCATION OBJECT [ARGUMENT-NAME]) " (& "rArr") " VOID")
     63    (p "Raises a type error like " (tt "error-database") " does, unless "
     64       "the given value satisfies " (tt "database?")))
     65
     66  (procedure ("(statement? OBJECT) " (& "rArr") " BOOLEAN")
     67    (p "Checks whether the value " (tt "v") " represents an SQL statement."))
     68  (procedure ("(error-statement LOCATION OBJECT [ARGUMENT-NAME]) " (& "rArr") " VOID")
     69    (p "Raises a type error saying that a statement was expected instead of the given value."))
     70  (procedure ("(check-statement LOCATION OBJECT [ARGUMENT-NAME]) " (& "rArr") " VOID")
     71    (p "Raises a type error like " (tt "error-statement") " does, unless the given value satisfies " (tt "statement?"))))
    5972
    6073      (subsection "Managing databases"
    6174
    62         (procedure "(sqlite3:open (path <string>)) => <sqlite3:database>"
    63           (p "Opens the indicated database file and returns a " (tt "<sqlite3:database>") " object for it.")
    64           (p "The given path is subject to the same special expansion as paths passed to " (p "open-input-file") " and similar procedures."))
    65 
    66         (definition
    67           (signatures
    68             (signature "method" "(sqlite3:define-collation (db <sqlite3:database>) (name <string>)) => <void>")
    69             (signature "method" "(sqlite3:define-collation (db <sqlite3:database>) (name <string>) (proc <procedure-class>)) => <void>"))
    70           (p "If " (tt "proc") " is given, registers a new collation sequence identified by " (tt "name") " for use in the context of database handle " (tt "db") ". If no procedure is passed, the collation sequence with the given name is removed.")
    71           (p (tt "proc") " should have the signature " (tt "(proc (a <string>) (b <string>)) => <exact>") ". It should return a negative number if " (tt "a") " sorts before " (tt "b") ", a positive number if " (tt "b") " sorts before " (tt "a") " and zero if " (tt "a") " and " (tt "b") " are equal.")
    72           (p "As " (tt "proc") " will be called in a callback context from within " (tt "sqlite3:step!") ", safety measures are installed to avoid throwing any exceptions, invoking continuations or returning invalid values from it. Attempts to do so will result in a " (tt "0") " return value and warning messages."))
    73 
    74         (definition
    75           (signatures
    76             (signature "method" "(sqlite3:define-function (db <sqlite3:database>) (name <string>) (n <exact>) (proc <procedure-class>)) => <void>")
    77             (signature "method" "(sqlite3:define-function (db <sqlite3:database>) (name <string>) (n <exact>) (step-proc <procedure-class>) (seed <top>) #!optional ((final-proc <procedure-class>) identity)) => <void>"))
    78           (p "If " (tt "proc") " is given, registers a new SQL function identified by " (tt "name") " for use in the context of database handle " (tt "db") ". If " (tt "step-proc") " and " (tt "final-proc") " are given, the new function becomes an aggregate function. Once registered, functions cannot be deleted.")
    79           (p (tt "n") " is the number of parameters the new SQL function takes or " (tt "-1") " to allow any number of arguments.")
    80           (p (tt "proc") " should have the signature " (tt "(proc . params) => <top>") ". It is called with the " (tt "n") " parameters given to the SQL function converted into Scheme objects like by " (tt "sqlite3:column-data") ". The return value is converted into an SQLite3 data object like by " (tt "sqlite3:bind!") ". A return value of " (tt "(void)") " corresponds to " (tt "NULL") " in SQLite3.")
    81           (p (tt "step-proc") " should have the signature " (tt "(step-proc (seed <top>) . params) => <top>") ". It is called with the parameters given to the SQL function for every row being processed. The seed value passed is initially the one given as an argument to " (tt "sqlite3:define-function") "; for subsequent calls it is the last value returned by " (tt "step-proc") " and after completion of " (tt "final-proc") " it will be the initial value again.")
    82           (p (tt "final-proc") " should have the signature " (tt "(final-proc (seed <top>)) => <top>") " and transforms the last seed value into the value to be returned from the aggregate function.")
    83           (p "As " (tt "proc") ", " (tt "step-proc") " and " (tt "final-proc") " will be called in a callback context from within " (tt "sqlite3:step!") ", safety measures are installed to avoid throwing any exceptions, invoking continuations or returning invalid values from them. Attempts to do such things will result in " (tt "NULL") " return values and warning messages."))
    84 
    85         (procedure "(sqlite3:set-busy-timeout! (db <sqlite3:database>) #!optional ((ms <exact>) 0)) => <void>"
    86           (p "Installs a busy handler that waits at least the specified amount of milliseconds for locks on the given database. If " (tt "(<= ms 0)") " though, all busy handlers for the database are uninstalled."))
    87         (procedure "(sqlite3:set-busy-handler! (db <sqlite3:database>) (handler <procedure-class>)) => <void>"
    88           (p "Installs the supplied procedure as the library's busy handler, or removes it if " (tt "#f") ".  When the database is busy, SQLite will invoke this handler repeatedly until it returns " (tt "#f") ".  The handler will be called with arguments " (tt "db") " (database) and " (tt "count") " (number of times invoked for the same operation).")
    89           (p "As " (tt "handler") " will be called in a callback context from within the library, safety measures are installed to avoid throwing any exceptions or invoking continuations.  Attempts to do such things will result in " (tt "#f") " return values and warning messages.")
    90           (p "Notably, you may " (b "not") " use this procedure in the presence of multiple threads unless you can ensure no other thread will invoke a C to Scheme callback while this handler is executing.  In other words, callback entrance and exit must occur in order.  Use " (tt "set-safe-busy-handler!") " in this case.")
    91           (pre "Example:
    92 (sqlite3:set-busy-handler! db
    93  (lambda (db count)
    94    (cond ((< count 5)
    95           (sleep 1)
    96           #t)
    97          (else #f)))))"))
    98         (procedure "(sqlite3:set-safe-busy-handler! (db <sqlite3:database>) (handler <procedure-class>)) => <void>"
    99           (p "Installs the supplied procedure as the application's busy handler, or removes it if " (tt "#f") ".  When the database returns a busy error code, the egg will invoke this handler repeatedly until it returns " (tt "#f") ".  The handler will be called with arguments " (tt "db") " (database), " (tt "count") " (number of times invoked for the same operation), and " (tt "last") " (the previous value the handler returned for this operation).")
    100           (p "As " (tt "handler") " is not called in a callback context, it is legal to invoke captured continuations, and it is safe in the presence of multiple threads.  In general, this handler should give up at some point to avoid possible deadlock.")
    101           (p "For an example handler, see the code of " (tt "default-safe-busy-handler") "."))
    102         (procedure "(sqlite3:default-safe-busy-handler (ms <exact>)) => <procedure-class>"
    103           (p "Returns a handler suitable for use with " (tt "set-safe-busy-handler!") ".  The behavior is identical to the default SQLite busy handler installed via " (tt "set-busy-timeout!") (& "mdash") "it polls in increasing intervals until the timeout in milliseconds is reached" (& "mdash") "but this version is non-blocking.")
    104           (pre "Example:
    105 (define open-db
    106   (let ((handler (sqlite3:default-safe-busy-handler 2000)))
     75  (procedure ("(open-database PATH) " (& "rArr") " DATABASE")
     76    (p "Opens the indicated database file and returns a database object for it.")
     77    (p "The given path is subject to the same special expansion as paths passed to " (tt "open-input-file") " and similar procedures."))
     78
     79  (procedure ("(define-collation DATABASE NAME [PROC]) " (& "rArr") " VOID")
     80    (p "If a procedure is given, registers a new collation sequence identified by " (tt "name") " for use in the context of database handle " (tt "db") ". If no procedure is passed, the collation sequence with the given name is removed.")
     81    (p (tt "PROC") " should have the signature " (tt "(PROC STRING STRING) " (& "rArr") " FIXNUM") ". It should return a negative number if the first argument sorts before the second, a positive number if the second sorts before the first and zero if they are equal.")
     82    (p "As " (tt "PROC") " will be called in a callback context from within " (tt "step!") ", safety measures are installed to avoid throwing any exceptions, invoking continuations or returning invalid values from it. Attempts to do so will result in a " (tt "0") " return value and warning messages."))
     83
     84  (definition
     85    (signatures
     86      (signature "procedure" ("(define-function DATABASE NAME N PROC) " (& "rArr") " VOID"))
     87      (signature "procedure" ("(define-function DATABASE NAME N STEP-PROC SEED [FINAL-PROC]) " (& "rArr") " VOID")))
     88    (p "Registers a new SQL function identified by " (tt "NAME") " for use in the context of the given database handle. If " (tt "STEP-PROC") " and " (tt "SEED") " are given, the new function becomes an aggregate function. Once registered, functions cannot be deleted.")
     89    (p (tt "N") " is the number of parameters the new SQL function takes or " (tt "-1") " to allow any number of arguments.")
     90    (p (tt "PROC") " should have the signature " (tt "(PROC . PARAMS) " (& "rArr") " OBJECT") ". It is called with the " (tt "N") " parameters given to the SQL function converted into Scheme objects like by " (tt "column-data") ". The return value is converted into an SQLite data object like by " (tt "bind!") ". A return value of " (tt "(void)") " corresponds to " (tt "NULL") " in SQLite.")
     91    (p (tt "STEP-PROC") " should have the signature " (tt "(STEP-PROC SEED . PARAMS) " (& "rArr") " SEED") ". It is called with the parameters given to the SQL function for every row being processed. The seed value passed is initially the one given as an argument to " (tt "define-function") "; for subsequent calls it is the last value returned by " (tt "STEP-PROC") " and after completion of " (tt "FINAL-PROC") " it will be the initial value again.")
     92    (p (tt "FINAL-PROC") " should have the signature " (tt "(FINAL-PROC SEED) " (& "rArr") " OBJECT") " and transforms the last seed value into the value to be returned from the aggregate function. If it is not explicitly specified, " (tt "STEP-PROC") " defaults to the identity function.")
     93    (p "As " (tt "PROC") ", " (tt "STEP-PROC") " and " (tt "FINAL-PROC") " will be called in a callback context from within " (tt "step!") ", safety measures are installed to avoid throwing any exceptions, invoking continuations or returning invalid values from them. Attempts to do such things will result in " (tt "NULL") " return values and warning messages."))
     94
     95  (procedure ("(set-busy-handler! DATABASE PROC) " (& "rArr") " VOID")
     96    (p "Installs the supplied procedure as the application's busy handler, or removes it if " (tt "#f") ".  When the database returns a busy error code, the egg will invoke this handler repeatedly until it returns " (tt "#f") ".  The handler will be called with arguments " (tt "DATABASE") " and " (tt "COUNT") " (number of times invoked for the same operation).")
     97    (p "As " (tt "PROC") " is not called in a callback context, it is legal to invoke captured continuations, and it is safe in the presence of multiple threads.  In general, this handler should give up at some point to avoid possible deadlock.")
     98    (p "For an example handler, see the code of " (tt "make-busy-timeout") "."))
     99  (procedure ("(make-busy-timeout MS) " (& "rArr") " PROC")
     100    (p "Returns a handler suitable for use with " (tt "set-busy-handler!") ". It polls in increasing intervals until the timeout in milliseconds is reached. The handler is non-blocking.")
     101    (pre ";; Example:
     102(define open-database/timeout
     103  (let ((handler (make-busy-timeout 2000)))
    107104    (lambda (db-name)
    108       (let ((db (sqlite3:open db-name)))
    109         (sqlite3:set-safe-busy-handler! db handler)
    110         db))))"))
    111 
    112         (procedure "(sqlite3:interrupt! (db <sqlite3:database>)) => <void>"
    113           (p "Cancels any running database operation as soon as possible.")
    114           (p "This function is always successful and never throws an exception."))
    115 
    116         (procedure "(sqlite3:auto-committing? (db <sqlite3:database>)) => <bool>"
    117           (p "Checks whether the database is currently in auto committing mode, i.e. no transaction is currently active.")
    118           (p "This function always returns a state and never throws an exception."))
    119 
    120         (procedure "(sqlite3:changes (db <sqlite3:database>) #!optional ((total <bool>) #f)) => <number>"
    121           (p "Returns the number of rows changed by the last statement (if " (tt "(not total)") ") or since the database was opened (if " (tt "total") ").")
    122           (p "This function always returns a count and never throws an exception."))
    123 
    124         (procedure "(sqlite3:last-insert-rowid (db <sqlite3:database>)) => <number>"
    125           (p "Returns the row ID of the last row inserted in " (tt "db") ".")
    126           (p "This function always returns a number and never throws an exception."))
    127 
    128         (method "(sqlite3:finalize! (db <sqlite3:database>)) => <void>"
    129           (p "Closes the given database.") ) )
     105      (let ((db (open-database db-name)))
     106  (set-busy-handler! db handler)
     107  db))))"))
     108
     109  (procedure ("(interrupt! DATABASE) " (& "rArr") " VOID")
     110    (p "Cancels any running database operation as soon as possible.")
     111    (p "This function is always successful and never throws an exception."))
     112
     113  (procedure ("(auto-committing? DATABASE) " (& "rArr") " BOOLEAN")
     114    (p "Checks whether the database is currently in auto committing mode, i.e. no transaction is currently active.")
     115    (p "This function always returns a state and never throws an exception."))
     116
     117  (procedure ("(change-count DATABASE [TOTAL]) " (& "rArr") " CARDINAL-INTEGER")
     118    (p "Returns the number of rows changed by the last statement (if " (tt "(not TOTAL)") ", which is the default) or since the database was opened (if " (tt "TOTAL") ").")
     119    (p "This function always returns a count and never throws an exception."))
     120
     121  (procedure ("(last-insert-rowid DATABASE) " (& "rArr") " INTEGER")
     122    (p "Returns the row ID of the last row inserted in " (tt "db") ".")
     123    (p "This function always returns a number and never throws an exception."))
     124
     125  (procedure ("(finalize! DATABASE-OR-STATEMENT) " (& "rArr") " VOID")
     126    (p "Closes the given database or finalizes the given statement.")
     127    (p "Every statement must be finalized to free its resources and discard it before the database itself can be finalized.")))
    130128
    131129      (subsection "Managing statements"
    132130
    133         (procedure "(sqlite3:prepare (db <sqlite3:database>) (sql <string>)) => <sqlite3:statement>, <string>"
    134           (p "Compiles the first SQL statement in " (tt "sql") " and returns a " (tt "<sqlite3:statement>") " and the rest of " (tt "sql") ", which was not compiled (or an empty string)."))
    135 
    136         (procedure "(sqlite3:repair! (stmt <sqlite3:statement>)) => <void>"
    137           (p "Recompiles the SQL statement used to create " (tt "stmt") ", transfers all existing bindings from the old statement handle to the new one and destructively modifies " (tt "stmt") " to point to the new statement handle.")
    138           (p "If the operation is successful, the old handle is finalized, in case of error, the new handle is finalized and the old one stays untouched.")
    139           (p "Usually you should not have to call this routine by hand. It is invoked by " (tt "sqlite3:step!") " to automagically repair a stale statement handle after a database schema change."))
    140 
    141         (procedure "(sqlite3:column-count (stmt <sqlite3:statement>)) => <exact>"
    142           (p "Can be applied to any statement and returns the number of columns it will return as results.")
    143           (p "This procedure always succeeds and never throws an exception."))
    144 
    145         (procedure "(sqlite3:column-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
    146           (p "Can be applied to any statement and returns the name of the column number " (tt "i") " (counting from 0) as a string or " (tt "#f") " if the column has no name.")
    147           (p "This procedure always succeeds and never throws an exception."))
    148 
    149         (procedure "(sqlite3:column-declared-type (stmt <sqlite3:statement>) (i <exact>)) => <string>"
    150           (p "Can be applied to any statement and returns the declared type (as given in the " (tt "CREATE") " statement) of the column number " (tt "i") " (counting from 0) as a string or " (tt "#f") " if the column has no declared type.")
    151           (p "This procedure always succeeds and never throws an exception."))
    152 
    153         (procedure "(sqlite3:bind-parameter-count (stmt <sqlite3:statement>)) => <exact>"
    154           (p "Can be applied to any statement and returns the number of free parameters that can be bound in the statement.")
    155           (p "This procedure always succeeds and never throws an exception."))
    156 
    157         (procedure "(sqlite3:bind-parameter-index (stmt <sqlite3:statement>) (name <string>)) => <exact>"
    158           (p "Can be applied to any statement and returns the index of the bindable parameter called " (tt "name") " or " (tt "#f") " if no such parameter exists.")
    159           (p "This procedure always succeeds and never throws an exception."))
    160 
    161         (procedure "(sqlite3:bind-parameter-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
    162           (p "Can be applied to any statement and returns the name of the bindable parameter number " (tt "i") " (counting from 0) or " (tt "#f") " if no such parameter exists or the parameter has no name.")
    163           (p "This procedure always succeeds and never throws an exception."))
    164 
    165         (definition
    166           (signatures
    167             (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)) => <void>")
    168             (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <boolean>)) => <void>")
    169             (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <exact>)) => <void>")
    170             (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <number>)) => <void>")
    171             (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <string>)) => <void>")
    172             (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <blob>)) => <void>"))
    173           (p "Can be applied to any statement to bind its free parameter number " (tt "i") " (counting from 0) to the given value. Scheme types of the value map to SQLite types as follows:"
    174           (table
    175             (tr (th "Scheme type") (th "SQLite type"))
    176             (tr (td "none") (td (tt "null")))
    177             (tr (td (tt "<boolean>")) (td (tt "integer: #t = 1, #f = 0")))
    178             (tr (td (tt "<exact>")) (td (tt "integer")))
    179             (tr (td (tt "<number>")) (td (tt "float")))
    180             (tr (td (tt "<string>")) (td (tt "text")))
    181             (tr (td (tt "<blob>")) (td (tt "blob")))))
    182           (p "Unless there is internal trouble in SQLite3, this method should always succeeds and never throw an exception. For invalid parameter indices the method just silently does nothing."))
    183 
    184         (procedure "(sqlite3:bind-parameters! (stmt <sqlite3:statement>) . params) => <void>"
    185           (p "Binds the statement's free parameters.")
    186           (p "Allows " (code "<void>") " as a parameter.") )
    187 
    188         (procedure "(sqlite3:step! (stmt <sqlite3:statement>)) => <boolean>"
    189           (p "Single-steps the execution of " (tt "stmt") " and returns " (tt "#t") " if a result row was produced, " (tt "#f") " if no further results are available as the statement has been stepped through. This procedure must be called at least once before any results can be retrieved from the statement."))
    190 
    191         (procedure "(sqlite3:column-type (stmt <sqlite3:statement>) (i <exact>)) => <symbol>"
    192           (p "Can be applied to a statement that has just been stepped (otherwise it returns " (tt "#f") ") and returns the SQLite type of the result column number " (tt "i") " (counting from 0) as a symbol.")
    193           (p "The return value can be one of the symbols " (tt "null") ", " (tt "integer") ", " (tt "float") ", " (tt "text") " or " (tt "blob") ".")
    194           (p "This procedure always succeeds and never throws an exception."))
    195 
    196         (procedure "(sqlite3:column-data (stmt <sqlite3:statement>) (i <exact>)) => <void | exact | number | string | blob>"
    197           (p "Can be applied to a statement that has just been stepped. Consults " (tt "sqlite3:column-type") " to determine the type of the indicated column and to return its data as an appropriate scheme object.")
    198           (p "See " (tt "sqlite3:bind!") " for the mapping between Scheme and SQLite data types. Columns of type " (tt "null") " are returned as " (tt "<void>") ". Also keep in mind that CHICKEN's " (tt "<exact>") " datatype can only hold a subset of the values an SQLite " (tt "integer") " can store. Large integer values may therefore be returned as floating point numbers from the database, but they will still be of class " (tt "<integer>") ".")
    199           (p "This procedure always succeeds and never throws an exception."))
    200 
    201         (procedure "(sqlite3:reset! (stmt <sqlite3:statement>)) => <void>"
    202           (p "Can be applied to any statement and resets it such that execution using " (tt "sqlite3:step!") " will perform all operations of the statement again."))
    203 
    204         (method "(sqlite3:finalize! (stmt <sqlite3:statement>)) => <void>"
    205           (p "Must be applied to every statement to free its resources and discard it.")
    206           (p (tt "sqlite3:close") " will not be able to close a database that has associated unfinalized statements.") ) )
     131  (procedure ("(prepare DATABASE SQL) " (& "rArr") " STATEMENT, SQL")
     132    (p "Compiles the first SQL statement in " (tt "SQL") " and returns a statement and the tail of the SQL code, which was not compiled (or an empty string)."))
     133
     134  (procedure ("(repair! STATEMENT) " (& "rArr") " VOID")
     135    (p "Recompiles the SQL code used to create the statement, transfers all existing bindings from the old statement handle to the new one and destructively modifies " (tt "STATEMENT") " to point to the new statement handle.")
     136    (p "If the operation is successful, the old handle is finalized, in case of error, the new handle is finalized and the old one stays untouched.")
     137    (p "Usually you should not have to call this routine by hand. It is invoked by " (tt "step!") " to automagically repair a stale statement handle after a database schema change."))
     138
     139  (procedure ("(column-count STATEMENT) " (& "rArr") " CARDINAL-INTEGER")
     140    (p "Can be applied to any statement and returns the number of columns it will return as results.")
     141    (p "This procedure always succeeds and never throws an exception."))
     142
     143  (procedure ("(column-name STATEMENT I) " (& "rArr") " STRING")
     144    (p "Can be applied to any statement and returns the name of the column number " (tt "I") " (counting from 0) as a string or " (tt "#f") " if the column has no name.")
     145    (p "This procedure always succeeds and never throws an exception."))
     146
     147  (procedure ("(column-declared-type STATEMENT I) " (& "rArr") " STRING")
     148    (p "Can be applied to any statement and returns the declared type (as given in the " (tt "CREATE") " statement) of the column number " (tt "I") " (counting from 0) as a string or " (tt "#f") " if the column has no declared type.")
     149    (p "This procedure always succeeds and never throws an exception."))
     150
     151  (procedure ("(bind-parameter-count STATEMENT) " (& "rArr") " CARDINAL-INTEGER")
     152    (p "Can be applied to any statement and returns the number of free parameters that can be bound in the statement.")
     153    (p "This procedure always succeeds and never throws an exception."))
     154
     155  (procedure ("(bind-parameter-index STATEMENT NAME) " (& "rArr") " CARDINAL-INTEGER")
     156    (p "Can be applied to any statement and returns the index of the bindable parameter called " (tt "NAME") " or " (tt "#f") " if no such parameter exists.")
     157    (p "This procedure always succeeds and never throws an exception."))
     158
     159  (procedure ("(bind-parameter-name STATEMENT I) " (& "rArr") " STRING")
     160    (p "Can be applied to any statement and returns the name of the bindable parameter number " (tt "I") " (counting from 0) or " (tt "#f") " if no such parameter exists or the parameter has no name.")
     161    (p "This procedure always succeeds and never throws an exception."))
     162
     163  (procedure ("(bind! STATEMENT I OBJECT) " (& "rArr") " VOID")
     164    (p "Can be applied to any statement to bind its free parameter number " (tt "I") " (counting from 0) to the given value. Scheme types of the value map to SQLite types as follows:"
     165    (table
     166      (tr (th "Scheme type") (th "SQLite type"))
     167      (tr (td (tt "boolean?")) (td (tt "integer: #t = 1, #f = 0")))
     168      (tr (td (tt "fixnum?")) (td (tt "integer")))
     169      (tr (td (tt "real?")) (td (tt "float")))
     170      (tr (td (tt "string?")) (td (tt "text")))
     171      (tr (td (tt "blob?")) (td (tt "blob")))
     172      (tr (td (tt "(void)")) (td (tt "null")))))
     173    (p "Unless there is internal trouble in SQLite, this method should always succeeds and never throw an exception. For invalid parameter indices the method just silently does nothing."))
     174
     175  (procedure ("(bind-parameters! STATEMENT . PARAMETERS) " (& "rArr") " VOID")
     176    (p "Resets the statement and binds all its free parameters.")
     177    (p "In addition to just listing the values to bind to the statement's parameters in sequence, you may specify parameters prefixed by keywords that are resolved to parameter indices by prefixing their names with " (tt "\":\"") " and resolving them using " (tt "bind-parameter-index") "."))
     178
     179  (procedure ("(step! STATEMENT) " (& "rArr") " BOOLEAN")
     180    (p "Single-steps the execution of " (tt "STATEMENT") " and returns " (tt "#t") " if a result row was produced, " (tt "#f") " if no further results are available as the statement has been stepped through. This procedure must be called at least once before any results can be retrieved from the statement."))
     181
     182  (procedure ("(column-type STATEMENT I) " (& "rArr") " SYMBOL")
     183    (p "Can be applied to a statement that has just been stepped (otherwise it returns " (tt "#f") ") and returns the SQLite type of the result column number " (tt "I") " (counting from 0) as a symbol.")
     184    (p "The return value can be one of the symbols " (tt "null") ", " (tt "integer") ", " (tt "float") ", " (tt "text") " or " (tt "blob") ".")
     185    (p "This procedure always succeeds and never throws an exception."))
     186
     187  (procedure ("(column-data STATEMENT I) " (& "rArr") " OBJECT")
     188    (p "Can be applied to a statement that has just been stepped. Consults " (tt "column-type") " and " (tt "column-declared-type") " to determine the type of the indicated column and to return its data as an appropriate Scheme object:"
     189    (table
     190      (tr (th "SQLite type") (th "Scheme type"))
     191      (tr (td (tt "integer") ", declared " (tt "\"bool\"")) (td (tt "boolean?")))
     192      (tr (td (tt "integer")) (td (tt "integer?")))
     193      (tr (td (tt "float")) (td (tt "real?")))
     194      (tr (td (tt "text")) (td (tt "string?")))
     195      (tr (td (tt "blob")) (td (tt "blob?")))
     196      (tr (td (tt "null")) (td (tt "(void)")))))
     197    (p "The declared type of a column is considered to be boolean if the type declaration contains the character sequence \"bool\" anywhere, ignoring case.")
     198    (p "This procedure always succeeds and never throws an exception."))
     199
     200  (procedure ("(reset! STATEMENT) " (& "rArr") " VOID")
     201    (p "Can be applied to any statement and resets it such that execution using " (tt "step!") " will perform all operations of the statement again.")))
    207202
    208203      (subsection "Simple statement interface"
    209204
    210         (procedure "(sqlite3:call-with-temporary-statements (proc <procedure-class>) (db <sqlite3:database>) . sqls) => <top>"
    211           (p "Compiles the SQL sources in " (tt "sqls") " into statements in the context of " (tt "db") ", applies " (tt "proc") " to these statements and returns " (tt "proc") "'s result. The statements are created and finalized in " (tt "dynamic-wind") " entry and exit blocks around the application of " (tt "proc") "."))
    212 
    213         (definition
    214           (signatures
    215             (signature "method" "(sqlite3:exec (stmt <sqlite3:statement>) . params) => <void>")
    216             (signature "method" "(sqlite3:exec (db <sqlite3:database>) (sql <string>) . params) => <void>"))
    217           (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it.")
    218           (p "Allows " (code "<void>") " as a parameter.") )
    219 
    220         (definition
    221           (signatures
    222             (signature "method" "(sqlite3:update (stmt <sqlite3:statement>) . params) => <exact>")
    223             (signature "method" "(sqlite3:update (db <sqlite3:database>) (sql <string>) . params) => <exact>"))
    224           (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the specified statement ignoring possible results from it, returning the result of applying " (tt "sqlite3:changes") " to the affected database after the execution of the statement instead.")
    225           (p "Allows " (code "<void>") " as a parameter.") )
    226 
    227         (definition
    228           (signatures
    229             (signature "method" "(sqlite3:first-result (stmt <sqlite3:statement>) . params) => <void | exact | number | string | blob>")
    230             (signature "method" "(sqlite3:first-result (db <sqlite3:database>) (sql <string>) . params) => <void | exact | number | string | blob>"))
    231           (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and single-steps the statement once returning the value of the first column in the first result row. Resets the statement again just before returning.")
    232           (p "If the given statement does not yield any results, an " (tt "(exn sqlite3)") " is thrown with the " (tt "status") "-property set to " (tt "done") ".")
    233           (p "Allows " (code "<void>") " as a parameter.") )
    234 
    235         (definition
    236           (signatures
    237             (signature "method" "(sqlite3:first-row (stmt <sqlite3:statement>) . params) => <list>")
    238             (signature "method" "(sqlite3:first-row (db <sqlite3:database>) (sql <string>) . params) => <list>"))
    239           (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and single-steps the statement once returning all columns in the first result row as a list.")
    240           (p "If the given statement does not yield any results, an " (tt "(exn sqlite3)") " is thrown with the " (tt "status") "-property set to " (tt "done") ".")
    241           (p "Allows " (code "<void>") " as a parameter.") )
    242 
    243         (definition
    244           (signatures
    245             (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (stmt <sqlite3:statement>) initial . params) => <list>")
    246             (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) initial . params) => <list>"))
    247           (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and " (tt "proc") " is applied to the current folded value and the column values. The result of the application becomes the new folded value.")
    248           (p "Allows " (code "<void>") " as a parameter.") )
    249 
    250         (definition
    251           (signatures
    252             (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <void>")
    253             (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <void>"))
    254           (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and " (tt "proc") " is applied to them. The results of this application are discarded.")
    255           (p "Allows " (code "<void>") " as a parameter.") )
    256 
    257         (definition
    258           (signatures
    259             (signature "method" "(sqlite3:map-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <list>")
    260             (signature "method" "(sqlite3:map-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <list>"))
    261           (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and " (tt "proc") " is applied to them. The results of these applications are collected into a list.")
    262           (p "Allows " (code "<void>") " as a parameter.") ) )
     205  (procedure ("(call-with-temporary-statements PROC DATABASE . SQLS) " (& "rArr") " OBJECT")
     206    (p "Compiles the SQL sources into statements in the context of " (tt "DATABASE") ", applies " (tt "PROC") " to these statements and returns " (tt "PROC") "'s result. The statements are created and finalized in " (tt "dynamic-wind") " entry and exit blocks around the application of " (tt "PROC") "."))
     207
     208  (definition
     209    (signatures
     210      (signature "procedure" ("(execute STATEMENT . PARAMETERS) " (& "rArr") " VOID"))
     211      (signature "procedure" ("(execute DATABASE SQL . PARAMETERS) " (& "rArr") " VOID")))
     212    (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it."))
     213
     214  (definition
     215    (signatures
     216      (signature "procedure" ("(update STATEMENT . PARAMETERS) " (& "rArr") " CARDINAL-INTEGER"))
     217      (signature "procedure" ("(update DATABASE SQL . PARAMETERS) " (& "rArr") " CARDINAL-INTEGER")))
     218    (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the specified statement ignoring possible results from it, returning the result of applying " (tt "change-count") " to the affected database after the execution of the statement instead."))
     219
     220  (definition
     221    (signatures
     222      (signature "procedure" ("(first-result STATEMENT . PARAMETERS) " (& "rArr") " OBJECT"))
     223      (signature "procedure" ("(first-result DATABASE SQL . PARAMETERS) " (& "rArr") " OBJECT")))
     224    (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and single-steps the statement once returning the value of the first column in the first result row. Resets the statement again just before returning.")
     225    (p "If the given statement does not yield any results, an " (tt "(exn sqlite3)") " is thrown with the " (tt "status") "-property set to " (tt "done") "."))
     226
     227  (definition
     228    (signatures
     229      (signature "procedure" ("(first-row STATEMENT . PARAMETERS) " (& "rArr") " LIST"))
     230      (signature "procedure" ("(first-row DATABASE SQL . PARAMETERS) " (& "rArr") " LIST")))
     231    (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and single-steps the statement once returning all columns in the first result row as a list.")
     232    (p "If the given statement does not yield any results, an " (tt "(exn sqlite3)") " is thrown with the " (tt "status") "-property set to " (tt "done") "."))
     233
     234  (definition
     235    (signatures
     236      (signature "procedure" ("(fold-row PROC INIT STATEMENT . PARAMETERS) " (& "rArr") " OBJECT"))
     237      (signature "procedure" ("(fold-row PROC INIT DATABASE SQL . PARAMETERS) " (& "rArr") " OBJECT")))
     238    (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and " (tt "PROC") " is applied to the current folded value, set to " (tt "INIT") " in the first step, and the column values. The result of the application becomes the new folded value."))
     239
     240  (definition
     241    (signatures
     242      (signature "procedure" ("(for-each-row PROC STATEMENT . PARAMETERS) " (& "rArr") " VOID"))
     243      (signature "procedure" ("(for-each-row PROC DATABASE SQL . PARAMETERS) " (& "rArr") " VOID")))
     244    (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and " (tt "PROC") " is applied to them. The results of this application are discarded."))
     245
     246  (definition
     247    (signatures
     248      (signature "procedure" ("(map-row PROC STATEMENT . PARAMETERS) " (& "rArr") " LIST"))
     249      (signature "procedure" ("(map-row PROC DATABASE SQL . PARAMETERS) " (& "rArr") " LIST")))
     250    (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and " (tt "PROC") " is applied to them. The results of these applications are collected into a list."))
    263251
    264252      (subsection "Utility functions"
    265253
    266         (procedure "(sqlite3:with-transaction (db <sqlite3:database>) (thunk <procedure-class>) #!optional ((type <symbol>) 'deferred)) => <void>"
    267           (p "Runs " (tt "thunk") " within the scope of a transaction on the database " (tt "db") ".")
    268           (p "The transaction is committed upon exit from " (tt "thunk") " if " (tt "thunk") " returns a true value. If " (tt "thunk") " returns a false value or throws an exception, the transaction is rolled back.")
    269           (p "The " (tt "type") " of the transaction can be specified as one of the symbols " (tt "deferred") ", " (tt "immediate") " or " (tt "exclusive") "."))
    270 
    271         (procedure "(sqlite3:complete? (sql <string>)) => <boolean>"
    272           (p "Checks whether " (tt "sql") " comprises at least one complete SQL statement."))
    273 
    274         (procedure "(sqlite3:enable-shared-cache! <boolean>) => <void>"
    275           (p "Enables (or disables) the sharing of the database cache and schema data structures between connections to the same database."))
    276 
    277         (procedure "(sqlite3:library-version) => <string>"
    278           (p "Returns a string identifying the version of SQLite in use.") )
    279 
    280         (procedure "(sqlite3:boolean-value v) => <boolean>"
    281           (p "Returns a Scheme boolean for the usual SQLite column boolean values.")
    282           (p "Truth values are " (code "Y") ", " (code "y") ", " (code "YES") ", " (code "yes") ", " (code "Yes") ", and " (code "(not (zero? v))") ".")
    283           (p "Anything else is considered false.") ) ) )
     254  (procedure ("(with-transaction DATABASE THUNK [TYPE]) " (& "rArr") " OBJECT")
     255    (p "Runs " (tt "THUNK") " within the scope of a transaction on the database and returns the return value from " (tt "THUNK") ".")
     256    (p "The transaction is committed upon exit from " (tt "THUNK") " if " (tt "THUNK") " returns a true value. If " (tt "THUNK") " returns a false value or throws an exception, the transaction is rolled back.")
     257    (p "The " (tt "TYPE") " of the transaction can be specified as one of the symbols " (tt "deferred") "(the default), " (tt "immediate") " or " (tt "exclusive") "."))
     258
     259  (procedure ("(sql-complete? SQL) " (& "rArr") " BOOLEAN")
     260    (p "Checks whether " (tt "SQL") " comprises at least one complete SQL statement."))
     261
     262  (procedure ("(enable-shared-cache! BOOLEAN) " (& "rArr") " VOID")
     263    (p "Enables (or disables) the sharing of the database cache and schema data structures between connections to the same database."))
     264
     265  (procedure ("(database-version) " (& "rArr") " STRING")
     266    (p "Returns a string identifying the version of SQLite in use.")))))
    284267
    285268    (history
     269      (version "3.2.1" "Added a test suite")
     270      (version "3.2.0" "Removed the unsafe busy handler and timeout APIs, since a safe API exists")
     271      (version "3.1.0" (tt "bind-parameters!") " can now handle keyword arguments")
     272      (version "3.0.0" "Ported to CHICKEN 4, removed dependencies on TinyCLOS and EasyFFI")
    286273      (version "2.0.8" "Add busy handler callbacks; ensure finalize! is called on exception. [Jim Ursetto]")
    287274      (version "2.0.7" "Restore error reporting. [Jim Ursetto]")
     
    318305
    319306     (license #<<EOS
    320 Copyright (c) 2005, Thomas Chust <chust@web.de>.  All rights reserved.
     307Copyright (c) 2005-2009, Thomas Chust <chust@web.de>.  All rights reserved.
    321308
    322309Redistribution and use in source and binary forms, with or without
     
    332319  written permission.
    333320
    334 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS
    335 IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     321THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     322IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    336323THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    337324PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
     
    347334
    348335(eggdoc->html doc
    349               (append (eggdoc:make-stylesheet doc)
    350                       `((method *macro* . ,eggdoc:make-defsig))))
     336  (append (eggdoc:make-stylesheet doc)
     337    `((method *macro* . ,eggdoc:make-defsig))))
  • release/4/sqlite3/trunk/sqlite3.html

    r10382 r15334  
    33<html>
    44<head>
    5 <title>Eggs Unlimited - sqlite3</title><style type="text/css"> <!--
    6       CODE {
    7             color: #666666;
    8           }
    9 /*   DT.definition EM { font-weight: bold; font-style: normal; } */
    10 
    11      DT.definition {
    12                    background: #eee;
     5<title>Eggs Unlimited - sqlite3</title><style type="text/css"><!--
     6       CODE {
     7             color: #666666;
     8           }
     9 /*   DT.definition EM { font-weight: bold; font-style: normal; } */
     10;      DT.definition {
     11                    background: #eee;
    1312                   color: black;
    1413                   padding: 0.2em 1em 0.2em 0.7em;
     
    162161<h3>Requires</h3>
    163162<ul>
     163<li>check-errors</li>
    164164<li>synch</li>
    165 <li>tinyclos</li>
    166 <li>easyffi</li>
    167 <li>miscmacros</li></ul></div>
     165<li>miscmacros</li>
     166<li>matchable</li></ul></div>
    168167<div class="section">
    169168<h3>Documentation</h3>
     
    248247<tr>
    249248<td><tt>done</tt></td>
    250 <td><tt>sqlite3:step!</tt> has finished executing, so no further data is ready</td></tr></table></p></div>
     249<td><tt>step!</tt> has finished executing, so no further data is ready</td></tr></table></p></div>
    251250<div class="subsection">
    252 <h4>Classes</h4>
    253 <dt class="definition"><strong>class:</strong> &lt;sqlite3:database&gt;
    254 <br /><strong>class:</strong> &lt;sqlite3:statement&gt;</dt>
    255 <dd>
    256 <p>These classes are derived from <tt>&lt;c++-object&gt;</tt>. They hold a pointer to the underlying C-structure in their <tt>this</tt> slot.</p>
    257 <p><tt>&lt;sqlite3:statement&gt;</tt> also has a <tt>database</tt> slot pointing to the database object it belongs to.</p></dd></div>
     251<h4>Abstract data types</h4>
     252<dt class="definition"><strong>procedure:</strong> (database? OBJECT) &rArr; BOOLEAN</dt>
     253<dd>
     254<p>Checks whether a value represents an SQLite database.</p></dd>
     255<dt class="definition"><strong>procedure:</strong> (error-database LOCATION OBJECT [ARGUMENT-NAME]) &rArr; VOID</dt>
     256<dd>
     257<p>Raises a type error saying that a database was expected instead of the given value.</p></dd>
     258<dt class="definition"><strong>procedure:</strong> (check-database LOCATION OBJECT [ARGUMENT-NAME]) &rArr; VOID</dt>
     259<dd>
     260<p>Raises a type error like <tt>error-database</tt> does, unless the given value satisfies <tt>database?</tt></p></dd>
     261<dt class="definition"><strong>procedure:</strong> (statement? OBJECT) &rArr; BOOLEAN</dt>
     262<dd>
     263<p>Checks whether the value <tt>v</tt> represents an SQL statement.</p></dd>
     264<dt class="definition"><strong>procedure:</strong> (error-statement LOCATION OBJECT [ARGUMENT-NAME]) &rArr; VOID</dt>
     265<dd>
     266<p>Raises a type error saying that a statement was expected instead of the given value.</p></dd>
     267<dt class="definition"><strong>procedure:</strong> (check-statement LOCATION OBJECT [ARGUMENT-NAME]) &rArr; VOID</dt>
     268<dd>
     269<p>Raises a type error like <tt>error-statement</tt> does, unless the given value satisfies <tt>statement?</tt></p></dd></div>
    258270<div class="subsection">
    259271<h4>Managing databases</h4>
    260 <dt class="definition"><strong>procedure:</strong> (sqlite3:open (path &lt;string&gt;)) =&gt; &lt;sqlite3:database&gt;</dt>
    261 <dd>
    262 <p>Opens the indicated database file and returns a <tt>&lt;sqlite3:database&gt;</tt> object for it.</p>
    263 <p>The given path is subject to the same special expansion as paths passed to
    264 <p>open-input-file</p> and similar procedures.</p></dd>
    265 <dt class="definition"><strong>method:</strong> (sqlite3:define-collation (db &lt;sqlite3:database&gt;) (name &lt;string&gt;)) =&gt; &lt;void&gt;
    266 <br /><strong>method:</strong> (sqlite3:define-collation (db &lt;sqlite3:database&gt;) (name &lt;string&gt;) (proc &lt;procedure-class&gt;)) =&gt; &lt;void&gt;</dt>
    267 <dd>
    268 <p>If <tt>proc</tt> is given, registers a new collation sequence identified by <tt>name</tt> for use in the context of database handle <tt>db</tt>. If no procedure is passed, the collation sequence with the given name is removed.</p>
    269 <p><tt>proc</tt> should have the signature <tt>(proc (a &lt;string&gt;) (b &lt;string&gt;)) =&gt; &lt;exact&gt;</tt>. It should return a negative number if <tt>a</tt> sorts before <tt>b</tt>, a positive number if <tt>b</tt> sorts before <tt>a</tt> and zero if <tt>a</tt> and <tt>b</tt> are equal.</p>
    270 <p>As <tt>proc</tt> will be called in a callback context from within <tt>sqlite3:step!</tt>, safety measures are installed to avoid throwing any exceptions, invoking continuations or returning invalid values from it. Attempts to do so will result in a <tt>0</tt> return value and warning messages.</p></dd>
    271 <dt class="definition"><strong>method:</strong> (sqlite3:define-function (db &lt;sqlite3:database&gt;) (name &lt;string&gt;) (n &lt;exact&gt;) (proc &lt;procedure-class&gt;)) =&gt; &lt;void&gt;
    272 <br /><strong>method:</strong> (sqlite3:define-function (db &lt;sqlite3:database&gt;) (name &lt;string&gt;) (n &lt;exact&gt;) (step-proc &lt;procedure-class&gt;) (seed &lt;top&gt;) #!optional ((final-proc &lt;procedure-class&gt;) identity)) =&gt; &lt;void&gt;</dt>
    273 <dd>
    274 <p>If <tt>proc</tt> is given, registers a new SQL function identified by <tt>name</tt> for use in the context of database handle <tt>db</tt>. If <tt>step-proc</tt> and <tt>final-proc</tt> are given, the new function becomes an aggregate function. Once registered, functions cannot be deleted.</p>
    275 <p><tt>n</tt> is the number of parameters the new SQL function takes or <tt>-1</tt> to allow any number of arguments.</p>
    276 <p><tt>proc</tt> should have the signature <tt>(proc . params) =&gt; &lt;top&gt;</tt>. It is called with the <tt>n</tt> parameters given to the SQL function converted into Scheme objects like by <tt>sqlite3:column-data</tt>. The return value is converted into an SQLite3 data object like by <tt>sqlite3:bind!</tt>. A return value of <tt>(void)</tt> corresponds to <tt>NULL</tt> in SQLite3.</p>
    277 <p><tt>step-proc</tt> should have the signature <tt>(step-proc (seed &lt;top&gt;) . params) =&gt; &lt;top&gt;</tt>. It is called with the parameters given to the SQL function for every row being processed. The seed value passed is initially the one given as an argument to <tt>sqlite3:define-function</tt>; for subsequent calls it is the last value returned by <tt>step-proc</tt> and after completion of <tt>final-proc</tt> it will be the initial value again.</p>
    278 <p><tt>final-proc</tt> should have the signature <tt>(final-proc (seed &lt;top&gt;)) =&gt; &lt;top&gt;</tt> and transforms the last seed value into the value to be returned from the aggregate function.</p>
    279 <p>As <tt>proc</tt>, <tt>step-proc</tt> and <tt>final-proc</tt> will be called in a callback context from within <tt>sqlite3:step!</tt>, safety measures are installed to avoid throwing any exceptions, invoking continuations or returning invalid values from them. Attempts to do such things will result in <tt>NULL</tt> return values and warning messages.</p></dd>
    280 <dt class="definition"><strong>procedure:</strong> (sqlite3:set-busy-timeout! (db &lt;sqlite3:database&gt;) #!optional ((ms &lt;exact&gt;) 0)) =&gt; &lt;void&gt;</dt>
    281 <dd>
    282 <p>Installs a busy handler that waits at least the specified amount of milliseconds for locks on the given database. If <tt>(&lt;= ms 0)</tt> though, all busy handlers for the database are uninstalled.</p></dd>
    283 <dt class="definition"><strong>procedure:</strong> (sqlite3:set-busy-handler! (db &lt;sqlite3:database&gt;) (handler &lt;procedure-class&gt;)) =&gt; &lt;void&gt;</dt>
    284 <dd>
    285 <p>Installs the supplied procedure as the library's busy handler, or removes it if <tt>#f</tt>.  When the database is busy, SQLite will invoke this handler repeatedly until it returns <tt>#f</tt>.  The handler will be called with arguments <tt>db</tt> (database) and <tt>count</tt> (number of times invoked for the same operation).</p>
    286 <p>As <tt>handler</tt> will be called in a callback context from within the library, safety measures are installed to avoid throwing any exceptions or invoking continuations.  Attempts to do such things will result in <tt>#f</tt> return values and warning messages.</p>
    287 <p>Notably, you may <b>not</b> use this procedure in the presence of multiple threads unless you can ensure no other thread will invoke a C to Scheme callback while this handler is executing.  In other words, callback entrance and exit must occur in order.  Use <tt>set-safe-busy-handler!</tt> in this case.</p>
    288 <pre>Example:
    289 (sqlite3:set-busy-handler! db
    290  (lambda (db count)
    291    (cond ((&lt; count 5)
    292           (sleep 1)
    293           #t)
    294          (else #f)))))</pre></dd>
    295 <dt class="definition"><strong>procedure:</strong> (sqlite3:set-safe-busy-handler! (db &lt;sqlite3:database&gt;) (handler &lt;procedure-class&gt;)) =&gt; &lt;void&gt;</dt>
    296 <dd>
    297 <p>Installs the supplied procedure as the application's busy handler, or removes it if <tt>#f</tt>.  When the database returns a busy error code, the egg will invoke this handler repeatedly until it returns <tt>#f</tt>.  The handler will be called with arguments <tt>db</tt> (database), <tt>count</tt> (number of times invoked for the same operation), and <tt>last</tt> (the previous value the handler returned for this operation).</p>
    298 <p>As <tt>handler</tt> is not called in a callback context, it is legal to invoke captured continuations, and it is safe in the presence of multiple threads.  In general, this handler should give up at some point to avoid possible deadlock.</p>
    299 <p>For an example handler, see the code of <tt>default-safe-busy-handler</tt>.</p></dd>
    300 <dt class="definition"><strong>procedure:</strong> (sqlite3:default-safe-busy-handler (ms &lt;exact&gt;)) =&gt; &lt;procedure-class&gt;</dt>
    301 <dd>
    302 <p>Returns a handler suitable for use with <tt>set-safe-busy-handler!</tt>.  The behavior is identical to the default SQLite busy handler installed via <tt>set-busy-timeout!</tt>&mdash;it polls in increasing intervals until the timeout in milliseconds is reached&mdash;but this version is non-blocking.</p>
    303 <pre>Example:
    304 (define open-db
    305   (let ((handler (sqlite3:default-safe-busy-handler 2000)))
     272<dt class="definition"><strong>procedure:</strong> (open-database PATH) &rArr; DATABASE</dt>
     273<dd>
     274<p>Opens the indicated database file and returns a database object for it.</p>
     275<p>The given path is subject to the same special expansion as paths passed to <tt>open-input-file</tt> and similar procedures.</p></dd>
     276<dt class="definition"><strong>procedure:</strong> (define-collation DATABASE NAME [PROC]) &rArr; VOID</dt>
     277<dd>
     278<p>If a procedure is given, registers a new collation sequence identified by <tt>name</tt> for use in the context of database handle <tt>db</tt>. If no procedure is passed, the collation sequence with the given name is removed.</p>
     279<p><tt>PROC</tt> should have the signature <tt>(PROC STRING STRING) &rArr; FIXNUM</tt>. It should return a negative number if the first argument sorts before the second, a positive number if the second sorts before the first and zero if they are equal.</p>
     280<p>As <tt>PROC</tt> will be called in a callback context from within <tt>step!</tt>, safety measures are installed to avoid throwing any exceptions, invoking continuations or returning invalid values from it. Attempts to do so will result in a <tt>0</tt> return value and warning messages.</p></dd>
     281<dt class="definition"><strong>procedure:</strong> (define-function DATABASE NAME N PROC) &rArr; VOID
     282<br /><strong>procedure:</strong> (define-function DATABASE NAME N STEP-PROC SEED [FINAL-PROC]) &rArr; VOID</dt>
     283<dd>
     284<p>Registers a new SQL function identified by <tt>NAME</tt> for use in the context of the given database handle. If <tt>STEP-PROC</tt> and <tt>SEED</tt> are given, the new function becomes an aggregate function. Once registered, functions cannot be deleted.</p>
     285<p><tt>N</tt> is the number of parameters the new SQL function takes or <tt>-1</tt> to allow any number of arguments.</p>
     286<p><tt>PROC</tt> should have the signature <tt>(PROC . PARAMS) &rArr; OBJECT</tt>. It is called with the <tt>N</tt> parameters given to the SQL function converted into Scheme objects like by <tt>column-data</tt>. The return value is converted into an SQLite data object like by <tt>bind!</tt>. A return value of <tt>(void)</tt> corresponds to <tt>NULL</tt> in SQLite.</p>
     287<p><tt>STEP-PROC</tt> should have the signature <tt>(STEP-PROC SEED . PARAMS) &rArr; SEED</tt>. It is called with the parameters given to the SQL function for every row being processed. The seed value passed is initially the one given as an argument to <tt>define-function</tt>; for subsequent calls it is the last value returned by <tt>STEP-PROC</tt> and after completion of <tt>FINAL-PROC</tt> it will be the initial value again.</p>
     288<p><tt>FINAL-PROC</tt> should have the signature <tt>(FINAL-PROC SEED) &rArr; OBJECT</tt> and transforms the last seed value into the value to be returned from the aggregate function. If it is not explicitly specified, <tt>STEP-PROC</tt> defaults to the identity function.</p>
     289<p>As <tt>PROC</tt>, <tt>STEP-PROC</tt> and <tt>FINAL-PROC</tt> will be called in a callback context from within <tt>step!</tt>, safety measures are installed to avoid throwing any exceptions, invoking continuations or returning invalid values from them. Attempts to do such things will result in <tt>NULL</tt> return values and warning messages.</p></dd>
     290<dt class="definition"><strong>procedure:</strong> (set-busy-handler! DATABASE PROC) &rArr; VOID</dt>
     291<dd>
     292<p>Installs the supplied procedure as the application's busy handler, or removes it if <tt>#f</tt>.  When the database returns a busy error code, the egg will invoke this handler repeatedly until it returns <tt>#f</tt>.  The handler will be called with arguments <tt>DATABASE</tt> and <tt>COUNT</tt> (number of times invoked for the same operation).</p>
     293<p>As <tt>PROC</tt> is not called in a callback context, it is legal to invoke captured continuations, and it is safe in the presence of multiple threads.  In general, this handler should give up at some point to avoid possible deadlock.</p>
     294<p>For an example handler, see the code of <tt>make-busy-timeout</tt>.</p></dd>
     295<dt class="definition"><strong>procedure:</strong> (make-busy-timeout MS) &rArr; PROC</dt>
     296<dd>
     297<p>Returns a handler suitable for use with <tt>set-busy-handler!</tt>. It polls in increasing intervals until the timeout in milliseconds is reached. The handler is non-blocking.</p>
     298<pre>;; Example:
     299(define open-database/timeout
     300  (let ((handler (make-busy-timeout 2000)))
    306301    (lambda (db-name)
    307       (let ((db (sqlite3:open db-name)))
    308         (sqlite3:set-safe-busy-handler! db handler)
    309         db))))</pre></dd>
    310 <dt class="definition"><strong>procedure:</strong> (sqlite3:interrupt! (db &lt;sqlite3:database&gt;)) =&gt; &lt;void&gt;</dt>
     302      (let ((db (open-database db-name)))
     303  (set-busy-handler! db handler)
     304  db))))</pre></dd>
     305<dt class="definition"><strong>procedure:</strong> (interrupt! DATABASE) &rArr; VOID</dt>
    311306<dd>
    312307<p>Cancels any running database operation as soon as possible.</p>
    313308<p>This function is always successful and never throws an exception.</p></dd>
    314 <dt class="definition"><strong>procedure:</strong> (sqlite3:auto-committing? (db &lt;sqlite3:database&gt;)) =&gt; &lt;bool&gt;</dt>
     309<dt class="definition"><strong>procedure:</strong> (auto-committing? DATABASE) &rArr; BOOLEAN</dt>
    315310<dd>
    316311<p>Checks whether the database is currently in auto committing mode, i.e. no transaction is currently active.</p>
    317312<p>This function always returns a state and never throws an exception.</p></dd>
    318 <dt class="definition"><strong>procedure:</strong> (sqlite3:changes (db &lt;sqlite3:database&gt;) #!optional ((total &lt;bool&gt;) #f)) =&gt; &lt;number&gt;</dt>
    319 <dd>
    320 <p>Returns the number of rows changed by the last statement (if <tt>(not total)</tt>) or since the database was opened (if <tt>total</tt>).</p>
     313<dt class="definition"><strong>procedure:</strong> (change-count DATABASE [TOTAL]) &rArr; CARDINAL-INTEGER</dt>
     314<dd>
     315<p>Returns the number of rows changed by the last statement (if <tt>(not TOTAL)</tt>, which is the default) or since the database was opened (if <tt>TOTAL</tt>).</p>
    321316<p>This function always returns a count and never throws an exception.</p></dd>
    322 <dt class="definition"><strong>procedure:</strong> (sqlite3:last-insert-rowid (db &lt;sqlite3:database&gt;)) =&gt; &lt;number&gt;</dt>
     317<dt class="definition"><strong>procedure:</strong> (last-insert-rowid DATABASE) &rArr; INTEGER</dt>
    323318<dd>
    324319<p>Returns the row ID of the last row inserted in <tt>db</tt>.</p>
    325320<p>This function always returns a number and never throws an exception.</p></dd>
    326 <dt class="definition"><strong>method:</strong> (sqlite3:finalize! (db &lt;sqlite3:database&gt;)) =&gt; &lt;void&gt;</dt>
    327 <dd>
    328 <p>Closes the given database.</p></dd></div>
     321<dt class="definition"><strong>procedure:</strong> (finalize! DATABASE-OR-STATEMENT) &rArr; VOID</dt>
     322<dd>
     323<p>Closes the given database or finalizes the given statement.</p>
     324<p>Every statement must be finalized to free its resources and discard it before the database itself can be finalized.</p></dd></div>
    329325<div class="subsection">
    330326<h4>Managing statements</h4>
    331 <dt class="definition"><strong>procedure:</strong> (sqlite3:prepare (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;)) =&gt; &lt;sqlite3:statement&gt;, &lt;string&gt;</dt>
    332 <dd>
    333 <p>Compiles the first SQL statement in <tt>sql</tt> and returns a <tt>&lt;sqlite3:statement&gt;</tt> and the rest of <tt>sql</tt>, which was not compiled (or an empty string).</p></dd>
    334 <dt class="definition"><strong>procedure:</strong> (sqlite3:repair! (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;void&gt;</dt>
    335 <dd>
    336 <p>Recompiles the SQL statement used to create <tt>stmt</tt>, transfers all existing bindings from the old statement handle to the new one and destructively modifies <tt>stmt</tt> to point to the new statement handle.</p>
     327<dt class="definition"><strong>procedure:</strong> (prepare DATABASE SQL) &rArr; STATEMENT, SQL</dt>
     328<dd>
     329<p>Compiles the first SQL statement in <tt>SQL</tt> and returns a statement and the tail of the SQL code, which was not compiled (or an empty string).</p></dd>
     330<dt class="definition"><strong>procedure:</strong> (repair! STATEMENT) &rArr; VOID</dt>
     331<dd>
     332<p>Recompiles the SQL code used to create the statement, transfers all existing bindings from the old statement handle to the new one and destructively modifies <tt>STATEMENT</tt> to point to the new statement handle.</p>
    337333<p>If the operation is successful, the old handle is finalized, in case of error, the new handle is finalized and the old one stays untouched.</p>
    338 <p>Usually you should not have to call this routine by hand. It is invoked by <tt>sqlite3:step!</tt> to automagically repair a stale statement handle after a database schema change.</p></dd>
    339 <dt class="definition"><strong>procedure:</strong> (sqlite3:column-count (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;exact&gt;</dt>
     334<p>Usually you should not have to call this routine by hand. It is invoked by <tt>step!</tt> to automagically repair a stale statement handle after a database schema change.</p></dd>
     335<dt class="definition"><strong>procedure:</strong> (column-count STATEMENT) &rArr; CARDINAL-INTEGER</dt>
    340336<dd>
    341337<p>Can be applied to any statement and returns the number of columns it will return as results.</p>
    342338<p>This procedure always succeeds and never throws an exception.</p></dd>
    343 <dt class="definition"><strong>procedure:</strong> (sqlite3:column-name (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;)) =&gt; &lt;string&gt;</dt>
    344 <dd>
    345 <p>Can be applied to any statement and returns the name of the column number <tt>i</tt> (counting from 0) as a string or <tt>#f</tt> if the column has no name.</p>
    346 <p>This procedure always succeeds and never throws an exception.</p></dd>
    347 <dt class="definition"><strong>procedure:</strong> (sqlite3:column-declared-type (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;)) =&gt; &lt;string&gt;</dt>
    348 <dd>
    349 <p>Can be applied to any statement and returns the declared type (as given in the <tt>CREATE</tt> statement) of the column number <tt>i</tt> (counting from 0) as a string or <tt>#f</tt> if the column has no declared type.</p>
    350 <p>This procedure always succeeds and never throws an exception.</p></dd>
    351 <dt class="definition"><strong>procedure:</strong> (sqlite3:bind-parameter-count (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;exact&gt;</dt>
     339<dt class="definition"><strong>procedure:</strong> (column-name STATEMENT I) &rArr; STRING</dt>
     340<dd>
     341<p>Can be applied to any statement and returns the name of the column number <tt>I</tt> (counting from 0) as a string or <tt>#f</tt> if the column has no name.</p>
     342<p>This procedure always succeeds and never throws an exception.</p></dd>
     343<dt class="definition"><strong>procedure:</strong> (column-declared-type STATEMENT I) &rArr; STRING</dt>
     344<dd>
     345<p>Can be applied to any statement and returns the declared type (as given in the <tt>CREATE</tt> statement) of the column number <tt>I</tt> (counting from 0) as a string or <tt>#f</tt> if the column has no declared type.</p>
     346<p>This procedure always succeeds and never throws an exception.</p></dd>
     347<dt class="definition"><strong>procedure:</strong> (bind-parameter-count STATEMENT) &rArr; CARDINAL-INTEGER</dt>
    352348<dd>
    353349<p>Can be applied to any statement and returns the number of free parameters that can be bound in the statement.</p>
    354350<p>This procedure always succeeds and never throws an exception.</p></dd>
    355 <dt class="definition"><strong>procedure:</strong> (sqlite3:bind-parameter-index (stmt &lt;sqlite3:statement&gt;) (name &lt;string&gt;)) =&gt; &lt;exact&gt;</dt>
    356 <dd>
    357 <p>Can be applied to any statement and returns the index of the bindable parameter called <tt>name</tt> or <tt>#f</tt> if no such parameter exists.</p>
    358 <p>This procedure always succeeds and never throws an exception.</p></dd>
    359 <dt class="definition"><strong>procedure:</strong> (sqlite3:bind-parameter-name (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;)) =&gt; &lt;string&gt;</dt>
    360 <dd>
    361 <p>Can be applied to any statement and returns the name of the bindable parameter number <tt>i</tt> (counting from 0) or <tt>#f</tt> if no such parameter exists or the parameter has no name.</p>
    362 <p>This procedure always succeeds and never throws an exception.</p></dd>
    363 <dt class="definition"><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;)) =&gt; &lt;void&gt;
    364 <br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;boolean&gt;)) =&gt; &lt;void&gt;
    365 <br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;exact&gt;)) =&gt; &lt;void&gt;
    366 <br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;number&gt;)) =&gt; &lt;void&gt;
    367 <br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;string&gt;)) =&gt; &lt;void&gt;
    368 <br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;blob&gt;)) =&gt; &lt;void&gt;</dt>
    369 <dd>
    370 <p>Can be applied to any statement to bind its free parameter number <tt>i</tt> (counting from 0) to the given value. Scheme types of the value map to SQLite types as follows:
     351<dt class="definition"><strong>procedure:</strong> (bind-parameter-index STATEMENT NAME) &rArr; CARDINAL-INTEGER</dt>
     352<dd>
     353<p>Can be applied to any statement and returns the index of the bindable parameter called <tt>NAME</tt> or <tt>#f</tt> if no such parameter exists.</p>
     354<p>This procedure always succeeds and never throws an exception.</p></dd>
     355<dt class="definition"><strong>procedure:</strong> (bind-parameter-name STATEMENT I) &rArr; STRING</dt>
     356<dd>
     357<p>Can be applied to any statement and returns the name of the bindable parameter number <tt>I</tt> (counting from 0) or <tt>#f</tt> if no such parameter exists or the parameter has no name.</p>
     358<p>This procedure always succeeds and never throws an exception.</p></dd>
     359<dt class="definition"><strong>procedure:</strong> (bind! STATEMENT I OBJECT) &rArr; VOID</dt>
     360<dd>
     361<p>Can be applied to any statement to bind its free parameter number <tt>I</tt> (counting from 0) to the given value. Scheme types of the value map to SQLite types as follows:
    371362<table>
    372363<tr>
     
    374365<th>SQLite type</th></tr>
    375366<tr>
    376 <td>none</td>
    377 <td><tt>null</tt></td></tr>
    378 <tr>
    379 <td><tt>&lt;boolean&gt;</tt></td>
     367<td><tt>boolean?</tt></td>
    380368<td><tt>integer: #t = 1, #f = 0</tt></td></tr>
    381369<tr>
    382 <td><tt>&lt;exact&gt;</tt></td>
     370<td><tt>fixnum?</tt></td>
    383371<td><tt>integer</tt></td></tr>
    384372<tr>
    385 <td><tt>&lt;number&gt;</tt></td>
     373<td><tt>real?</tt></td>
    386374<td><tt>float</tt></td></tr>
    387375<tr>
    388 <td><tt>&lt;string&gt;</tt></td>
     376<td><tt>string?</tt></td>
    389377<td><tt>text</tt></td></tr>
    390378<tr>
    391 <td><tt>&lt;blob&gt;</tt></td>
    392 <td><tt>blob</tt></td></tr></table></p>
    393 <p>Unless there is internal trouble in SQLite3, this method should always succeeds and never throw an exception. For invalid parameter indices the method just silently does nothing.</p></dd>
    394 <dt class="definition"><strong>procedure:</strong> (sqlite3:bind-parameters! (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;void&gt;</dt>
    395 <dd>
    396 <p>Binds the statement's free parameters.</p>
    397 <p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    398 <dt class="definition"><strong>procedure:</strong> (sqlite3:step! (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;boolean&gt;</dt>
    399 <dd>
    400 <p>Single-steps the execution of <tt>stmt</tt> and returns <tt>#t</tt> if a result row was produced, <tt>#f</tt> if no further results are available as the statement has been stepped through. This procedure must be called at least once before any results can be retrieved from the statement.</p></dd>
    401 <dt class="definition"><strong>procedure:</strong> (sqlite3:column-type (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;)) =&gt; &lt;symbol&gt;</dt>
    402 <dd>
    403 <p>Can be applied to a statement that has just been stepped (otherwise it returns <tt>#f</tt>) and returns the SQLite type of the result column number <tt>i</tt> (counting from 0) as a symbol.</p>
     379<td><tt>blob?</tt></td>
     380<td><tt>blob</tt></td></tr>
     381<tr>
     382<td><tt>(void)</tt></td>
     383<td><tt>null</tt></td></tr></table></p>
     384<p>Unless there is internal trouble in SQLite, this method should always succeeds and never throw an exception. For invalid parameter indices the method just silently does nothing.</p></dd>
     385<dt class="definition"><strong>procedure:</strong> (bind-parameters! STATEMENT . PARAMETERS) &rArr; VOID</dt>
     386<dd>
     387<p>Resets the statement and binds all its free parameters.</p>
     388<p>In addition to just listing the values to bind to the statement's parameters in sequence, you may specify parameters prefixed by keywords that are resolved to parameter indices by prefixing their names with <tt>&quot;:&quot;</tt> and resolving them using <tt>bind-parameter-index</tt>.</p></dd>
     389<dt class="definition"><strong>procedure:</strong> (step! STATEMENT) &rArr; BOOLEAN</dt>
     390<dd>
     391<p>Single-steps the execution of <tt>STATEMENT</tt> and returns <tt>#t</tt> if a result row was produced, <tt>#f</tt> if no further results are available as the statement has been stepped through. This procedure must be called at least once before any results can be retrieved from the statement.</p></dd>
     392<dt class="definition"><strong>procedure:</strong> (column-type STATEMENT I) &rArr; SYMBOL</dt>
     393<dd>
     394<p>Can be applied to a statement that has just been stepped (otherwise it returns <tt>#f</tt>) and returns the SQLite type of the result column number <tt>I</tt> (counting from 0) as a symbol.</p>
    404395<p>The return value can be one of the symbols <tt>null</tt>, <tt>integer</tt>, <tt>float</tt>, <tt>text</tt> or <tt>blob</tt>.</p>
    405396<p>This procedure always succeeds and never throws an exception.</p></dd>
    406 <dt class="definition"><strong>procedure:</strong> (sqlite3:column-data (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;)) =&gt; &lt;void | exact | number | string | blob&gt;</dt>
    407 <dd>
    408 <p>Can be applied to a statement that has just been stepped. Consults <tt>sqlite3:column-type</tt> to determine the type of the indicated column and to return its data as an appropriate scheme object.</p>
    409 <p>See <tt>sqlite3:bind!</tt> for the mapping between Scheme and SQLite data types. Columns of type <tt>null</tt> are returned as <tt>&lt;void&gt;</tt>. Also keep in mind that CHICKEN's <tt>&lt;exact&gt;</tt> datatype can only hold a subset of the values an SQLite <tt>integer</tt> can store. Large integer values may therefore be returned as floating point numbers from the database, but they will still be of class <tt>&lt;integer&gt;</tt>.</p>
    410 <p>This procedure always succeeds and never throws an exception.</p></dd>
    411 <dt class="definition"><strong>procedure:</strong> (sqlite3:reset! (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;void&gt;</dt>
    412 <dd>
    413 <p>Can be applied to any statement and resets it such that execution using <tt>sqlite3:step!</tt> will perform all operations of the statement again.</p></dd>
    414 <dt class="definition"><strong>method:</strong> (sqlite3:finalize! (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;void&gt;</dt>
    415 <dd>
    416 <p>Must be applied to every statement to free its resources and discard it.</p>
    417 <p><tt>sqlite3:close</tt> will not be able to close a database that has associated unfinalized statements.</p></dd></div>
     397<dt class="definition"><strong>procedure:</strong> (column-data STATEMENT I) &rArr; OBJECT</dt>
     398<dd>
     399<p>Can be applied to a statement that has just been stepped. Consults <tt>column-type</tt> and <tt>column-declared-type</tt> to determine the type of the indicated column and to return its data as an appropriate Scheme object:
     400<table>
     401<tr>
     402<th>SQLite type</th>
     403<th>Scheme type</th></tr>
     404<tr>
     405<td><tt>integer</tt>, declared <tt>&quot;bool&quot;</tt></td>
     406<td><tt>boolean?</tt></td></tr>
     407<tr>
     408<td><tt>integer</tt></td>
     409<td><tt>integer?</tt></td></tr>
     410<tr>
     411<td><tt>float</tt></td>
     412<td><tt>real?</tt></td></tr>
     413<tr>
     414<td><tt>text</tt></td>
     415<td><tt>string?</tt></td></tr>
     416<tr>
     417<td><tt>blob</tt></td>
     418<td><tt>blob?</tt></td></tr>
     419<tr>
     420<td><tt>null</tt></td>
     421<td><tt>(void)</tt></td></tr></table></p>
     422<p>The declared type of a column is considered to be boolean if the type declaration contains the character sequence &quot;bool&quot; anywhere, ignoring case.</p>
     423<p>This procedure always succeeds and never throws an exception.</p></dd>
     424<dt class="definition"><strong>procedure:</strong> (reset! STATEMENT) &rArr; VOID</dt>
     425<dd>
     426<p>Can be applied to any statement and resets it such that execution using <tt>step!</tt> will perform all operations of the statement again.</p></dd></div>
    418427<div class="subsection">
    419428<h4>Simple statement interface</h4>
    420 <dt class="definition"><strong>procedure:</strong> (sqlite3:call-with-temporary-statements (proc &lt;procedure-class&gt;) (db &lt;sqlite3:database&gt;) . sqls) =&gt; &lt;top&gt;</dt>
    421 <dd>
    422 <p>Compiles the SQL sources in <tt>sqls</tt> into statements in the context of <tt>db</tt>, applies <tt>proc</tt> to these statements and returns <tt>proc</tt>'s result. The statements are created and finalized in <tt>dynamic-wind</tt> entry and exit blocks around the application of <tt>proc</tt>.</p></dd>
    423 <dt class="definition"><strong>method:</strong> (sqlite3:exec (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;void&gt;
    424 <br /><strong>method:</strong> (sqlite3:exec (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;void&gt;</dt>
    425 <dd>
    426 <p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it.</p>
    427 <p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    428 <dt class="definition"><strong>method:</strong> (sqlite3:update (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;exact&gt;
    429 <br /><strong>method:</strong> (sqlite3:update (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;exact&gt;</dt>
    430 <dd>
    431 <p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the specified statement ignoring possible results from it, returning the result of applying <tt>sqlite3:changes</tt> to the affected database after the execution of the statement instead.</p>
    432 <p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    433 <dt class="definition"><strong>method:</strong> (sqlite3:first-result (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;void | exact | number | string | blob&gt;
    434 <br /><strong>method:</strong> (sqlite3:first-result (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;void | exact | number | string | blob&gt;</dt>
     429<dt class="definition"><strong>procedure:</strong> (call-with-temporary-statements PROC DATABASE . SQLS) &rArr; OBJECT</dt>
     430<dd>
     431<p>Compiles the SQL sources into statements in the context of <tt>DATABASE</tt>, applies <tt>PROC</tt> to these statements and returns <tt>PROC</tt>'s result. The statements are created and finalized in <tt>dynamic-wind</tt> entry and exit blocks around the application of <tt>PROC</tt>.</p></dd>
     432<dt class="definition"><strong>procedure:</strong> (execute STATEMENT . PARAMETERS) &rArr; VOID
     433<br /><strong>procedure:</strong> (execute DATABASE SQL . PARAMETERS) &rArr; VOID</dt>
     434<dd>
     435<p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it.</p></dd>
     436<dt class="definition"><strong>procedure:</strong> (update STATEMENT . PARAMETERS) &rArr; CARDINAL-INTEGER
     437<br /><strong>procedure:</strong> (update DATABASE SQL . PARAMETERS) &rArr; CARDINAL-INTEGER</dt>
     438<dd>
     439<p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the specified statement ignoring possible results from it, returning the result of applying <tt>change-count</tt> to the affected database after the execution of the statement instead.</p></dd>
     440<dt class="definition"><strong>procedure:</strong> (first-result STATEMENT . PARAMETERS) &rArr; OBJECT
     441<br /><strong>procedure:</strong> (first-result DATABASE SQL . PARAMETERS) &rArr; OBJECT</dt>
    435442<dd>
    436443<p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and single-steps the statement once returning the value of the first column in the first result row. Resets the statement again just before returning.</p>
    437 <p>If the given statement does not yield any results, an <tt>(exn sqlite3)</tt> is thrown with the <tt>status</tt>-property set to <tt>done</tt>.</p>
    438 <p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    439 <dt class="definition"><strong>method:</strong> (sqlite3:first-row (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;list&gt;
    440 <br /><strong>method:</strong> (sqlite3:first-row (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;list&gt;</dt>
     444<p>If the given statement does not yield any results, an <tt>(exn sqlite3)</tt> is thrown with the <tt>status</tt>-property set to <tt>done</tt>.</p></dd>
     445<dt class="definition"><strong>procedure:</strong> (first-row STATEMENT . PARAMETERS) &rArr; LIST
     446<br /><strong>procedure:</strong> (first-row DATABASE SQL . PARAMETERS) &rArr; LIST</dt>
    441447<dd>
    442448<p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and single-steps the statement once returning all columns in the first result row as a list.</p>
    443 <p>If the given statement does not yield any results, an <tt>(exn sqlite3)</tt> is thrown with the <tt>status</tt>-property set to <tt>done</tt>.</p>
    444 <p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    445 <dt class="definition"><strong>method:</strong> (sqlite3:fold-row (proc &lt;procedure-class&gt;) (stmt &lt;sqlite3:statement&gt;) initial . params) =&gt; &lt;list&gt;
    446 <br /><strong>method:</strong> (sqlite3:fold-row (proc &lt;procedure-class&gt;) (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) initial . params) =&gt; &lt;list&gt;</dt>
    447 <dd>
    448 <p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and <tt>proc</tt> is applied to the current folded value and the column values. The result of the application becomes the new folded value.</p>
    449 <p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    450 <dt class="definition"><strong>method:</strong> (sqlite3:for-each-row (proc &lt;procedure-class&gt;) (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;void&gt;
    451 <br /><strong>method:</strong> (sqlite3:for-each-row (proc &lt;procedure-class&gt;) (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;void&gt;</dt>
    452 <dd>
    453 <p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and <tt>proc</tt> is applied to them. The results of this application are discarded.</p>
    454 <p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    455 <dt class="definition"><strong>method:</strong> (sqlite3:map-row (proc &lt;procedure-class&gt;) (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;list&gt;
    456 <br /><strong>method:</strong> (sqlite3:map-row (proc &lt;procedure-class&gt;) (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;list&gt;</dt>
    457 <dd>
    458 <p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and <tt>proc</tt> is applied to them. The results of these applications are collected into a list.</p>
    459 <p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd></div>
     449<p>If the given statement does not yield any results, an <tt>(exn sqlite3)</tt> is thrown with the <tt>status</tt>-property set to <tt>done</tt>.</p></dd>
     450<dt class="definition"><strong>procedure:</strong> (fold-row PROC INIT STATEMENT . PARAMETERS) &rArr; OBJECT
     451<br /><strong>procedure:</strong> (fold-row PROC INIT DATABASE SQL . PARAMETERS) &rArr; OBJECT</dt>
     452<dd>
     453<p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and <tt>PROC</tt> is applied to the current folded value, set to <tt>INIT</tt> in the first step, and the column values. The result of the application becomes the new folded value.</p></dd>
     454<dt class="definition"><strong>procedure:</strong> (for-each-row PROC STATEMENT . PARAMETERS) &rArr; VOID
     455<br /><strong>procedure:</strong> (for-each-row PROC DATABASE SQL . PARAMETERS) &rArr; VOID</dt>
     456<dd>
     457<p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and <tt>PROC</tt> is applied to them. The results of this application are discarded.</p></dd>
     458<dt class="definition"><strong>procedure:</strong> (map-row PROC STATEMENT . PARAMETERS) &rArr; LIST
     459<br /><strong>procedure:</strong> (map-row PROC DATABASE SQL . PARAMETERS) &rArr; LIST</dt>
     460<dd>
     461<p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes it step by step. After each step, the column values of the current result row are retrieved and <tt>PROC</tt> is applied to them. The results of these applications are collected into a list.</p></dd>
    460462<div class="subsection">
    461463<h4>Utility functions</h4>
    462 <dt class="definition"><strong>procedure:</strong> (sqlite3:with-transaction (db &lt;sqlite3:database&gt;) (thunk &lt;procedure-class&gt;) #!optional ((type &lt;symbol&gt;) 'deferred)) =&gt; &lt;void&gt;</dt>
    463 <dd>
    464 <p>Runs <tt>thunk</tt> within the scope of a transaction on the database <tt>db</tt>.</p>
    465 <p>The transaction is committed upon exit from <tt>thunk</tt> if <tt>thunk</tt> returns a true value. If <tt>thunk</tt> returns a false value or throws an exception, the transaction is rolled back.</p>
    466 <p>The <tt>type</tt> of the transaction can be specified as one of the symbols <tt>deferred</tt>, <tt>immediate</tt> or <tt>exclusive</tt>.</p></dd>
    467 <dt class="definition"><strong>procedure:</strong> (sqlite3:complete? (sql &lt;string&gt;)) =&gt; &lt;boolean&gt;</dt>
    468 <dd>
    469 <p>Checks whether <tt>sql</tt> comprises at least one complete SQL statement.</p></dd>
    470 <dt class="definition"><strong>procedure:</strong> (sqlite3:enable-shared-cache! &lt;boolean&gt;) =&gt; &lt;void&gt;</dt>
     464<dt class="definition"><strong>procedure:</strong> (with-transaction DATABASE THUNK [TYPE]) &rArr; OBJECT</dt>
     465<dd>
     466<p>Runs <tt>THUNK</tt> within the scope of a transaction on the database and returns the return value from <tt>THUNK</tt>.</p>
     467<p>The transaction is committed upon exit from <tt>THUNK</tt> if <tt>THUNK</tt> returns a true value. If <tt>THUNK</tt> returns a false value or throws an exception, the transaction is rolled back.</p>
     468<p>The <tt>TYPE</tt> of the transaction can be specified as one of the symbols <tt>deferred</tt>(the default), <tt>immediate</tt> or <tt>exclusive</tt>.</p></dd>
     469<dt class="definition"><strong>procedure:</strong> (sql-complete? SQL) &rArr; BOOLEAN</dt>
     470<dd>
     471<p>Checks whether <tt>SQL</tt> comprises at least one complete SQL statement.</p></dd>
     472<dt class="definition"><strong>procedure:</strong> (enable-shared-cache! BOOLEAN) &rArr; VOID</dt>
    471473<dd>
    472474<p>Enables (or disables) the sharing of the database cache and schema data structures between connections to the same database.</p></dd>
    473 <dt class="definition"><strong>procedure:</strong> (sqlite3:library-version) =&gt; &lt;string&gt;</dt>
    474 <dd>
    475 <p>Returns a string identifying the version of SQLite in use.</p></dd>
    476 <dt class="definition"><strong>procedure:</strong> (sqlite3:boolean-value v) =&gt; &lt;boolean&gt;</dt>
    477 <dd>
    478 <p>Returns a Scheme boolean for the usual SQLite column boolean values.</p>
    479 <p>Truth values are <code>Y</code>, <code>y</code>, <code>YES</code>, <code>yes</code>, <code>Yes</code>, and <code>(not (zero? v))</code>.</p>
    480 <p>Anything else is considered false.</p></dd></div></div>
     475<dt class="definition"><strong>procedure:</strong> (database-version) &rArr; STRING</dt>
     476<dd>
     477<p>Returns a string identifying the version of SQLite in use.</p></dd></div></div></div>
    481478<div class="section">
    482479<h3>Version</h3>
    483480<ul>
     481<li>3.2.1 Added a test suite</li>
     482<li>3.2.0 Removed the unsafe busy handler and timeout APIs, since a safe API exists</li>
     483<li>3.1.0 <tt>bind-parameters!</tt> can now handle keyword arguments</li>
     484<li>3.0.0 Ported to CHICKEN 4, removed dependencies on TinyCLOS and EasyFFI</li>
    484485<li>2.0.8 Add busy handler callbacks; ensure finalize! is called on exception. [Jim Ursetto]</li>
    485486<li>2.0.7 Restore error reporting. [Jim Ursetto]</li>
     
    516517<div class="section">
    517518<h3>License</h3>
    518 <pre id="license">Copyright (c) 2005, Thomas Chust &lt;chust@web.de&gt;.  All rights reserved.
     519<pre id="license">Copyright (c) 2005-2009, Thomas Chust &lt;chust@web.de&gt;.  All rights reserved.
    519520
    520521Redistribution and use in source and binary forms, with or without
     
    530531  written permission.
    531532
    532 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \&quot;AS
    533 IS\&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     533THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS
     534IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    534535THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    535536PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
  • release/4/sqlite3/trunk/sqlite3.meta

    r8022 r15334  
    1 ;;; sqlite3.meta -*- Hen -*-
     1;;;; sqlite3.meta
     2;;;; :tabSize=2:indentSize=2:noTabs=true:
    23
    34((egg "sqlite3.egg")
     
    56 (category db)
    67 (eggdoc "doc.scm")
    7  (needs synch tinyclos easyffi miscmacros)
     8 (needs check-errors synch miscmacros matchable)
    89 (license "BSD")
    910 (author "Thomas Chust")
    10  (files "egg.jpg" "sqlite3.html" "sqlite3.scm" "sqlite3.setup" "tests"))
     11 (files "sqlite3.scm" "sqlite3.html" "sqlite3.setup" "tests/run.scm" "egg.jpg"))
  • release/4/sqlite3/trunk/sqlite3.scm

    r10528 r15334  
    11;;;; sqlite3.scm
     2;;;; :tabSize=2:indentSize=2:noTabs=true:
    23;;;; bindings to the SQLite3 database library
    34
     
    89;; into the top-level a byte length will result.
    910
    10 (define-extension sqlite3
    11   (export
    12     ;; classes
    13     initialize
    14     <sqlite3:database>
    15     <sqlite3:statement>
    16     ;; methods & procedures
    17     sqlite3:open
    18     sqlite3:define-collation
    19     sqlite3:define-function
    20     sqlite3:set-busy-timeout!
    21     sqlite3:set-busy-handler!
    22     sqlite3:set-safe-busy-handler!
    23     sqlite3:default-safe-busy-handler
    24     sqlite3:interrupt!
    25     sqlite3:auto-committing?
    26     sqlite3:changes
    27     sqlite3:last-insert-rowid
    28     sqlite3:finalize!
    29     sqlite3:prepare
    30     sqlite3:repair!
    31     sqlite3:reset!
    32     sqlite3:bind-parameter-count
    33     sqlite3:bind-parameter-index
    34     sqlite3:bind-parameter-name
    35     sqlite3:bind!
    36     sqlite3:bind-parameters!
    37     sqlite3:step!
    38     sqlite3:column-count
    39     sqlite3:column-type
    40     sqlite3:column-declared-type
    41     sqlite3:column-name
    42     sqlite3:column-data
    43     sqlite3:call-with-temporary-statements
    44     sqlite3:exec
    45     sqlite3:update
    46     sqlite3:first-result
    47     sqlite3:first-row
    48     sqlite3:fold-row
    49     sqlite3:for-each-row
    50     sqlite3:map-row
    51     sqlite3:with-transaction
    52     sqlite3:complete?
    53     sqlite3:library-version
    54     sqlite3:enable-shared-cache!
    55     sqlite3:boolean-value ) )
    56 
    5711(declare
    5812  (usual-integrations)
    5913  (fixnum-arithmetic)
    6014  (no-procedure-checks-for-usual-bindings)
    61   ; redefinition of imported variable `initialize' from `tinyclos'
    62   (disable-warning redef)
    6315  (unused
    6416    ; Stop annoying messages
    65     chicken_sqlite3_function_stub
    66     chicken_sqlite3_collation_stub
    67     chicken_sqlite3_final_stub
    68     chicken_sqlite3_step_stub
    69     chicken_sqlite3_busy_handler_stub )
     17    sqlite3#chicken_sqlite3_function_stub
     18    sqlite3#chicken_sqlite3_collation_stub
     19    sqlite3#chicken_sqlite3_final_stub
     20    sqlite3#chicken_sqlite3_step_stub
     21    ; These may have to be changed if definitions are added,
     22    ; removed or reordered:
     23    sqlite3#g104 sqlite3#g304 sqlite3#g422 sqlite3#g508)
    7024  (bound-to-procedure
    7125    ##sys#expand-home-path
    72     #;##sys#pathname-resolution
    73     abort-sqlite3-null-error
    74     sqlite3:errmsg ) )
     26    sqlite3#sqlite3_errmsg))
    7527
    7628#>#include <sqlite3.h><#
    7729
    78 (use (srfi 1 12 13 18 26 69) extras lolevel)
    79 (use tinyclos synch miscmacros)
    80 
    81 ;;;
    82 
    83 ;; Only works when the invoked object is a procedure.
    84 ;; Macros & values will not work.
    85 (define-macro thunker cut)
    86 
    87 (define core:abort abort)   ; abort overridden by sqlite3:status enum
     30(module sqlite3
     31  ( ;; type predicates and checks
     32    database?
     33    error-database
     34    check-database
     35    statement?
     36    error-statement
     37    check-statement
     38    ;; procedures
     39    open-database
     40    define-collation
     41    define-function
     42    set-busy-handler!
     43    make-busy-timeout
     44    interrupt!
     45    auto-committing?
     46    change-count
     47    last-insert-rowid
     48    finalize!
     49    prepare
     50    repair!
     51    reset!
     52    bind-parameter-count
     53    bind-parameter-index
     54    bind-parameter-name
     55    bind!
     56    bind-parameters!
     57    step!
     58    column-count
     59    column-type
     60    column-declared-type
     61    column-name
     62    column-data
     63    call-with-temporary-statements
     64    execute
     65    update
     66    first-result
     67    first-row
     68    fold-row
     69    for-each-row
     70    map-row
     71    with-transaction
     72    sql-complete?
     73    database-version
     74    enable-shared-cache!
     75  )
     76
     77(import
     78  scheme srfi-1 srfi-13 srfi-18 srfi-69
     79  chicken data-structures extras foreign lolevel
     80  type-errors type-checks synch miscmacros matchable)
     81
     82(require-library
     83  srfi-1 srfi-13 srfi-18 srfi-69
     84  data-structures extras lolevel
     85  type-errors type-checks synch miscmacros matchable)
    8886
    8987;;; Foreign types & values
     
    9189;; Enumeration and constant definitions
    9290
    93 (define-foreign-enum (sqlite3:status int)
    94   #f ; no aliases
    95   (ok               SQLITE_OK   #f)       ; Successful result
    96   (error            SQLITE_ERROR)         ; SQL error or missing database
    97   (internal         SQLITE_INTERNAL)      ; NOT USED. Internal logic error in SQLite
    98   (permission       SQLITE_PERM)          ; Access permission denied
    99   (abort            SQLITE_ABORT)         ; Callback routine requested an abort
    100   (busy             SQLITE_BUSY)          ; The database file is locked
    101   (locked           SQLITE_LOCKED)        ; A table in the database is locked
    102   (no-memory        SQLITE_NOMEM)         ; A malloc() failed
    103   (read-only        SQLITE_READONLY)      ; Attempt to write a readonly database
    104   (interrupt        SQLITE_INTERRUPT)     ; Operation terminated by sqlite3_interrupt()
    105   (io-error         SQLITE_IOERR)         ; Some kind of disk I/O error occurred
    106   (corrupt          SQLITE_CORRUPT)       ; The database disk image is malformed
    107   (not-found        SQLITE_NOTFOUND)      ; NOT USED. Table or record not found
    108   (full             SQLITE_FULL)          ; Insertion failed because database is full
    109   (cant-open        SQLITE_CANTOPEN)      ; Unable to open the database file
    110   (protocol         SQLITE_PROTOCOL)      ; NOT USED. Database lock protocol error
    111   (empty            SQLITE_EMPTY)         ; Database is empty
    112   (schema           SQLITE_SCHEMA)        ; The database schema changed
    113   (too-big          SQLITE_TOOBIG)        ; String or BLOB exceeds size limit
    114   (constraint       SQLITE_CONSTRAINT)    ; Abort due to contraint violation
    115   (mismatch         SQLITE_MISMATCH)      ; Data type mismatch
    116   (misuse           SQLITE_MISUSE)        ; Library used incorrectly
    117   (no-lfs           SQLITE_NOLFS)         ; Uses OS features not supported on host
    118   (authorization    SQLITE_AUTH)          ; Authorization denied
    119   (format           SQLITE_FORMAT)        ; Auxiliary database format error
    120   (range            SQLITE_RANGE)         ; 2nd parameter to sqlite3_bind out of range
    121   (not-a-database   SQLITE_NOTADB)        ; File opened that is not a database file
    122   (row              SQLITE_ROW)           ; sqlite3_step() has another row ready
    123   (done             SQLITE_DONE) )        ; sqlite3_step() has finished executing
    124 
    125 (define-foreign-enum (sqlite3:type int)
    126   #f ; no aliases
    127   (integer  SQLITE_INTEGER)
    128   (float    SQLITE_FLOAT)
    129   (text     SQLITE_TEXT)
    130   (blob     SQLITE_BLOB)
    131   (null     SQLITE_NULL) )
    132 
    133 ;; Types
    134 
    135 (define-foreign-type sqlite3:context (c-pointer "sqlite3_context"))
    136 
    137 (define-foreign-type sqlite3:value (c-pointer "sqlite3_value"))
    138 
    139 ;;; Classes for databases and statements
    140 
    141 (define-class <sqlite3:database> (<c++-object>) (busy-handler))
     91(define-syntax %define-enum-type
     92  (syntax-rules ()
     93    [(%define-enum-type (sname cname) (sv cv) ...)
     94    (define-foreign-type sname
     95      (enum cname)
     96      (lambda (v)
     97  (case v
     98    [(sv) (foreign-value cv int)]
     99    ...
     100    [else
     101      (error-argument-type 'sname v "enumeration value")]))
     102      (lambda (v)
     103  (select v
     104    [((foreign-value cv int)) 'sv]
     105    ...
     106    [else
     107      (error-argument-type 'sname v "enumeration index")])))]))
     108
     109(%define-enum-type (sqlite3:status "sqlite3_status")
     110  (#f                                                           "SQLITE_OK")      ; Successful result
     111  (error                                "SQLITE_ERROR")   ; SQL error or missing database
     112  (internal                                     "SQLITE_INTERNAL")        ; NOT USED. Internal logic error in SQLite
     113  (permission                           "SQLITE_PERM")    ; Access permission denied
     114  (abort                                "SQLITE_ABORT")   ; Callback routine requested an abort
     115  (busy                                 "SQLITE_BUSY")    ; The database file is locked
     116  (locked                               "SQLITE_LOCKED")          ; A table in the database is locked
     117  (no-memory                    "SQLITE_NOMEM")   ; A malloc() failed
     118  (read-only                    "SQLITE_READONLY")        ; Attempt to write a readonly database
     119  (interrupt                    "SQLITE_INTERRUPT")       ; Operation terminated by sqlite3_interrupt()
     120  (io-error                     "SQLITE_IOERR")   ; Some kind of disk I/O error occurred
     121  (corrupt                      "SQLITE_CORRUPT")         ; The database disk image is malformed
     122  (not-found                    "SQLITE_NOTFOUND")        ; NOT USED. Table or record not found
     123  (full                                 "SQLITE_FULL")    ; Insertion failed because database is full
     124  (cant-open                    "SQLITE_CANTOPEN")        ; Unable to open the database file
     125  (protocol                     "SQLITE_PROTOCOL")        ; NOT USED. Database lock protocol error
     126  (empty                                "SQLITE_EMPTY")   ; Database is empty
     127  (schema                               "SQLITE_SCHEMA")          ; The database schema changed
     128  (too-big                      "SQLITE_TOOBIG")          ; String or BLOB exceeds size limit
     129  (constraint                   "SQLITE_CONSTRAINT")      ; Abort due to contraint violation
     130  (mismatch                     "SQLITE_MISMATCH")        ; Data type mismatch
     131  (misuse                               "SQLITE_MISUSE")          ; Library used incorrectly
     132  (no-lfs                               "SQLITE_NOLFS")   ; Uses OS features not supported on host
     133  (authorization                "SQLITE_AUTH")    ; Authorization denied
     134  (format                               "SQLITE_FORMAT")          ; Auxiliary database format error
     135  (range                                "SQLITE_RANGE")   ; 2nd parameter to sqlite3_bind out of range
     136  (not-a-database               "SQLITE_NOTADB")          ; File opened that is not a database file
     137  (row                                  "SQLITE_ROW")             ; sqlite3_step() has another row ready
     138  (done                                 "SQLITE_DONE"))   ; sqlite3_step() has finished executing
     139
     140(%define-enum-type (sqlite3:type "sqlite3_type")
     141  (integer      "SQLITE_INTEGER")
     142  (float                "SQLITE_FLOAT")
     143  (text                 "SQLITE_TEXT")
     144  (blob                 "SQLITE_BLOB")
     145  (null                 "SQLITE_NULL"))
     146
     147;; Auxiliary types
     148
     149(define-foreign-type sqlite3:context
     150  (c-pointer "sqlite3_context"))
     151
     152(define-foreign-type sqlite3:value
     153  (c-pointer "sqlite3_value"))
     154
     155;; Types for databases and statements
     156
     157(define-record-type sqlite3:database
     158  (make-database ptr busy-handler)
     159  database?
     160  (ptr database-ptr database-ptr-set!)
     161  (busy-handler database-busy-handler database-busy-handler-set!))
     162
     163(define-record-printer (sqlite3:database db out)
     164  (display
     165    (if (database-ptr db)
     166      "#<sqlite3:database>"
     167      "#<sqlite3:database zombie>")
     168    out))
     169
     170(define-check+error-type database)
     171
    142172(define-foreign-type sqlite3:database
    143   (instance "sqlite3" <sqlite3:database>)
    144   (lambda (db)
    145     (unless (slot-ref db 'this)
    146       (abort-sqlite3-null-error 'sqlite3:database->c-pointer db))
    147     db))
    148 (define-method (initialize (this <sqlite3:database>) initargs)
    149   (call-next-method)
    150   (initialize-slots this initargs) )
    151 
    152 (define-class <sqlite3:statement> (<c++-object>) (database sql))
     173  (nonnull-c-pointer "sqlite3")
     174  database-ptr
     175  (cut make-database <> #f))
     176
     177(define-record-type sqlite3:statement
     178  (make-statement ptr database sql)
     179  statement?
     180  (ptr statement-ptr statement-ptr-set!)
     181  (database statement-database)
     182  (sql statement-sql))
     183
     184(define-record-printer (sqlite3:statement stmt out)
     185  (display
     186    (if (statement-ptr stmt)
     187      (sprintf "#<sqlite3:statement sql=~s>" (statement-sql stmt))
     188      "#<sqlite3:statement zombie>")
     189    out))
     190
     191(define-check+error-type statement)
     192
    153193(define-foreign-type sqlite3:statement
    154   (instance "sqlite3_stmt" <sqlite3:statement>)
    155   (lambda (stmt)
    156     (unless (slot-ref stmt 'this)
    157       (abort-sqlite3-null-error 'sqlite3:statement->c-pointer stmt))
    158     stmt))
    159 
    160 (define-method (initialize (this <sqlite3:statement>) initargs)
    161   (call-next-method)
    162   (initialize-slots this initargs) )
     194  (nonnull-c-pointer "sqlite3_stmt")
     195  statement-ptr
     196  (cut make-statement <> #f #f))
    163197
    164198;;; Helpers
    165199
    166 ;; Expand variables in pathname
    167 (define sqlite3:resolve-pathname
    168   ##sys#expand-home-path
    169   #; ;not needed, yet
    170   (cute ##sys#pathname-resolution <> identity) )
    171 
    172200;; Conditions
    173201
    174202(define (make-exn-condition loc msg . args)
    175   (make-property-condition 'exn 'location loc 'message msg 'arguments args) )
     203  (make-property-condition 'exn 'location loc 'message msg 'arguments args))
    176204
    177205(define (make-sqlite3-condition sta)
    178   (make-property-condition 'sqlite3 'status sta) )
     206  (make-property-condition 'sqlite3 'status sta))
    179207
    180208(define (make-sqlite3-error-condition loc msg sta . args)
    181    (make-composite-condition
     209  (make-composite-condition
    182210    (apply make-exn-condition loc msg args)
    183     (make-sqlite3-condition sta)) )
     211    (make-sqlite3-condition sta)))
    184212
    185213(define (make-no-data-condition loc stmt params)
    186214  (make-sqlite3-error-condition loc
    187                                 "the statement returned no data"
    188                                 'done
    189                                 stmt params) )
     215    "the statement returned no data"
     216    'done
     217    stmt params))
    190218
    191219;; Errors
    192220(define ((abort-sqlite3-error loc db . args) sta)
    193   (core:abort
    194    (apply make-sqlite3-error-condition
    195           loc
    196           (if db (sqlite3:errmsg db) (symbol->string sta))
    197           sta
    198           args)))
    199 
    200 (define (check-sqlite3-type loc obj class)
    201   (unless (instance-of? obj class)
    202     (core:abort
    203      (make-composite-condition
    204       (make-exn-condition loc
    205                           (string-append
    206                            "bad argument type " (class-name (class-of obj))
    207                            ", expected " (class-name class))
    208                           obj)
    209       (make-property-condition 'type)
    210       (make-sqlite3-condition 'error)))) )
    211 
    212 (define (abort-sqlite3-null-error loc obj)
    213   (core:abort
    214    (make-sqlite3-error-condition loc
    215                                  (string-append
    216                                   "bad " (class-name (class-of obj))
    217                                   " object, contained pointer is #f")
    218                                  'error
    219                                  obj)) )
     221  (abort
     222    (apply make-sqlite3-error-condition
     223      loc
     224      (if db (sqlite3_errmsg db) (symbol->string sta))
     225      sta
     226      args)))
     227
    220228(define (print-error msg obj)
    221   (print-error-message obj (current-error-port) (string-append "Error: " msg)) )
     229  (print-error-message obj (current-error-port) (string-append "Error: " msg)))
    222230
    223231;; Tree dictionary
    224232
    225233(define (make-hash-table-tree/synch id . args)
    226   (make-object/synch (apply make-hash-table args) id) )
     234  (make-object/synch (apply make-hash-table args) id))
    227235
    228236(define (hash-table-tree-set! ht-tree keys value)
    229237  (if (null? (cdr keys))
    230       (hash-table-set! ht-tree (car keys) value)
    231       (hash-table-update! ht-tree
    232                           (car keys)
    233                           (cute hash-table-tree-set! <> (cdr keys) value)
    234                           (thunker make-hash-table)) )
    235   ht-tree )
     238    (hash-table-set! ht-tree (car keys) value)
     239    (hash-table-update! ht-tree
     240      (car keys)
     241      (cute hash-table-tree-set! <> (cdr keys) value)
     242      (cut make-hash-table)))
     243  ht-tree)
    236244
    237245(define (hash-table-tree-delete! ht-tree keys)
    238246  (if (null? (cdr keys))
    239       (hash-table-delete! ht-tree (car keys))
    240       (hash-table-update! ht-tree
    241                           (car keys)
    242                           (cute hash-table-tree-delete! <> (cdr keys))
    243                           (thunker make-hash-table)) )
    244   ht-tree )
     247    (hash-table-delete! ht-tree (car keys))
     248    (hash-table-update! ht-tree
     249      (car keys)
     250      (cute hash-table-tree-delete! <> (cdr keys))
     251      (cut make-hash-table)))
     252  ht-tree)
    245253
    246254(define (hash-table-tree-ref
    247         ht-tree keys
    248         #!optional
    249          (thunk (thunker abort
    250                          (make-composite-condition
    251                           (make-exn-condition 'hash-table-tree-ref
    252                                               "hash-table-tree does not contain path"
    253                                               ht-tree keys)
    254                           (make-property-condition 'access)))))
     255    ht-tree keys
     256    #!optional
     257    (thunk (cut abort
     258      (make-composite-condition
     259        (make-exn-condition 'hash-table-tree-ref
     260          "hash-table-tree does not contain path"
     261          ht-tree keys)
     262        (make-property-condition 'access)))))
    255263  (let/cc return
    256264    (let loop ([ht ht-tree]
    257                [keys keys] )
     265  [keys keys])
    258266      (if (null? keys)
    259           ht
    260           (loop (hash-table-ref ht (car keys) (thunker return (thunk)))
    261                 (cdr keys)) ) ) ) )
     267  ht
     268  (loop (hash-table-ref ht (car keys) (cut return (thunk)))
     269    (cdr keys))))))
    262270
    263271(define (hash-table-tree-ref/default ht-tree keys default)
    264   (hash-table-tree-ref ht-tree keys (lambda () default)) )
     272  (hash-table-tree-ref ht-tree keys (lambda () default)))
    265273
    266274(define (hash-table-tree-clear! htt id elt-clear)
    267275  (cond [(hash-table-ref/default htt id #f)
    268          => (cute hash-table-walk <> elt-clear) ] )
    269   (hash-table-delete! htt id) )
     276    => (cute hash-table-walk <> elt-clear)])
     277  (hash-table-delete! htt id))
    270278
    271279;; SQL collation sequence interface
    272280
    273 (define *sqlite3:collations* (make-hash-table-tree/synch 'sqlite3:collations))
    274 
    275 (define-external (chicken_sqlite3_collation_stub (scheme-object qn) (int la)
    276                                                  (c-pointer da) (int lb)
    277                                                  (c-pointer db))
    278                 int
     281(define *collations* (make-hash-table-tree/synch 'sqlite3:collations))
     282
     283(define-external (chicken_sqlite3_collation_stub
     284      (scheme-object qn) (int la)
     285      (c-pointer da) (int lb)
     286      (c-pointer db)) int
    279287  (let/cc return
    280288    (let ([r #f])
    281289      (dynamic-wind
    282           noop
    283           (lambda ()
    284             (handle-exceptions exn
    285                                (print-error "in collation function" exn)
    286               (let ([a (make-string la)]
    287                     [b (make-string lb)] )
    288                 (move-memory! da a la)
    289                 (move-memory! db b lb)
    290                 (set! r
    291                       ((vector-ref (call-with/synch *sqlite3:collations*
    292                                      (cute hash-table-tree-ref <> qn))
    293                                    1)
    294                        a b)))))
    295           (lambda ()
    296             (if (and (integer? r) (exact? r))
    297                 (return r)
    298                 (begin
    299                   (print-error "in collation function: invalid return value" (->string r))
    300                   (return 0))))) ) ) )
     290  noop
     291  (lambda ()
     292    (handle-exceptions exn
     293      (print-error "in collation function" exn)
     294      (let ([a (make-string la)]
     295    [b (make-string lb)])
     296        (move-memory! da a la)
     297        (move-memory! db b lb)
     298        (set! r
     299    ((vector-ref
     300      (call-with/synch *collations*
     301        (cute hash-table-tree-ref <> qn))
     302      1)
     303      a b)))))
     304  (lambda ()
     305    (if (fixnum? r)
     306      (return r)
     307      (begin
     308        (print-error "in collation function: invalid return value" (->string r))
     309        (return 0))))))))
    301310
    302311(define sqlite3_create_collation
    303312  (foreign-lambda* sqlite3:status
    304                   ((sqlite3:database db) (c-string name) (scheme-object qn))
     313    ((sqlite3:database db) (c-string name) (scheme-object qn))
    305314#<<EOS
    306   if (qn == C_SCHEME_FALSE)
     315    if (qn == C_SCHEME_FALSE)
    307316    return(sqlite3_create_collation(db, name, SQLITE_UTF8, NULL, NULL));
    308   else
     317    else
    309318    return(sqlite3_create_collation(db, name, SQLITE_UTF8,
    310                                       (void *)qn,
    311                                       (int (*)(void *,
    312                                                int, const void *,
    313                                                int, const void *))
    314                                         &chicken_sqlite3_collation_stub));
     319  (void *)qn,
     320  (int (*)(void *,
     321      int, const void *,
     322      int, const void *))
     323  &chicken_sqlite3_collation_stub));
    315324EOS
    316   ))
    317 
    318 (define-generic sqlite3:define-collation)
    319 (define-method (sqlite3:define-collation (db <sqlite3:database>)
    320                                          (name <string>))
    321   (cond [(sqlite3_create_collation db name #f)
    322          => (abort-sqlite3-error 'sqlite3:define-collation db name) ]
    323         [else
    324          (let ([qn (list (pointer->address (slot-ref db 'this)) name)])
    325            (call-with/synch *sqlite3:collations*
    326              (lambda (col)
    327                (cond [(hash-table-tree-ref/default col qn #f)
    328                       => (lambda (info)
    329                            (hash-table-tree-delete! col qn)
    330                            (object-release (vector-ref info 0))) ] ) ) ) ) ] ) )
    331 
    332 (define-method (sqlite3:define-collation (db <sqlite3:database>)
    333                                           (name <string>)
    334                                           (proc <procedure-class>))
    335   (let ([qn (object-evict (list (pointer->address (slot-ref db 'this)) name))])
    336     (cond [(sqlite3_create_collation db name qn)
    337            => (lambda (s)
    338                 (object-release qn)
    339                 ((abort-sqlite3-error 'sqlite3:define-collation db name proc) s)) ]
    340           [else
    341            (call-with/synch *sqlite3:collations*
    342         (cute hash-table-tree-set! <> qn (vector qn proc))) ] ) ) )
     325    ))
     326
     327(define (define-collation db name #!optional proc)
     328  (check-database 'define-collation db)
     329  (check-string 'define-collation name)
     330  (if proc
     331    (begin
     332      (check-procedure 'define-collation proc)
     333      (let ([qn (object-evict (list (pointer->address (database-ptr db)) name))])
     334  (cond
     335    [(sqlite3_create_collation db name qn)
     336      => (lambda (s)
     337    (object-release qn)
     338    ((abort-sqlite3-error 'define-collation db name proc) s))]
     339    [else
     340      (call-with/synch *collations*
     341        (cute hash-table-tree-set! <> qn (vector qn proc)))])))
     342    (cond
     343      [(sqlite3_create_collation db name #f)
     344  => (abort-sqlite3-error 'define-collation db name)]
     345      [else
     346  (let ([qn (list (pointer->address (database-ptr db)) name)])
     347    (call-with/synch *collations*
     348      (lambda (col)
     349        (cond [(hash-table-tree-ref/default col qn #f)
     350    => (lambda (info)
     351      (hash-table-tree-delete! col qn)
     352      (object-release (vector-ref info 0)))]))))])))
    343353
    344354;;; SQL function interface
    345355
    346 (define *sqlite3:functions* (make-hash-table-tree/synch 'sqlite3:functions))
    347 
    348 (define *sqlite3:seeds* (make-hash-table-tree/synch 'sqlite3:seeds))
    349 
    350 (define (sqlite3:parameter-data n args)
     356(define *functions* (make-hash-table-tree/synch 'sqlite3:functions))
     357
     358(define *seeds* (make-hash-table-tree/synch 'sqlite3:seeds))
     359
     360(define (parameter-data n args)
    351361  (let loop ([i 0])
    352362    (if (<= n i)
    353         '()
    354         (cons (case ((foreign-lambda* sqlite3:type
    355                                       (((c-pointer sqlite3:value) args) (int i))
    356                       "return(sqlite3_value_type(args[i]));")
    357                      args i)
    358                 [(integer)
    359                  ((foreign-lambda* integer
    360                                    (((c-pointer sqlite3:value) args) (int i))
    361                    "return(sqlite3_value_double(args[i]));")
    362                   args i) ]
    363                 [(float)
    364                  ((foreign-lambda* double
    365                                    (((c-pointer sqlite3:value) args) (int i))
    366                    "return(sqlite3_value_double(args[i]));")
    367                   args i) ]
    368                 [(text)
    369                  ((foreign-primitive scheme-object
    370                                      (((c-pointer sqlite3:value) args) (int i))
    371                    "int n = sqlite3_value_bytes(args[i]);"
    372                    "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    373                    "return(C_string(&s, n, (char *)sqlite3_value_text(args[i])));")
    374                   args i) ]
    375                 [(blob)
    376                  ((foreign-primitive scheme-object
    377                                      (((c-pointer sqlite3:value) args) (int i))
    378                    "int n = sqlite3_value_bytes(args[i]);"
    379                    "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    380                    "return(C_bytevector(&s, n, (char *)sqlite3_value_blob(args[i])));")
    381                   args i) ]
    382                 [else
    383                  <void> ] )
    384               (loop (add1 i)) ) ) ) )
    385 
    386 (define-generic sqlite3:set-result!)
    387 (define-method (sqlite3:set-result! (ctx <pointer>) (v <blob>))
    388   ((foreign-lambda* void
    389                     ((sqlite3:context ctx) (scheme-pointer v) (int n))
    390       "sqlite3_result_blob(ctx, v, n, SQLITE_TRANSIENT);")
    391    ctx v (blob-size v)) )
    392 
    393 ; Deprecated
    394 (define-method (sqlite3:set-result! (ctx <pointer>) (v <byte-vector>))
    395   ((foreign-lambda* void
    396                     ((sqlite3:context ctx) (scheme-pointer v) (int n))
    397       "sqlite3_result_blob(ctx, v, n, SQLITE_TRANSIENT);")
    398    ctx v (byte-vector-length v)) )
    399 
    400 (define-method (sqlite3:set-result! (ctx <pointer>) (v <exact>))
    401   ((foreign-lambda void "sqlite3_result_int" sqlite3:context int)
    402    ctx v) )
    403 
    404 (define-method (sqlite3:set-result! (ctx <pointer>) (v <number>))
    405   ((foreign-lambda void "sqlite3_result_double" sqlite3:context double)
    406    ctx v) )
    407 
    408 (define-method (sqlite3:set-result! (ctx <pointer>) (v <string>))
    409   ((foreign-lambda* void
    410                     ((sqlite3:context ctx) (scheme-pointer v) (int n))
     363      '()
     364      (cons (case ((foreign-lambda* sqlite3:type
     365          (((c-pointer sqlite3:value) args) (int i))
     366          "return(sqlite3_value_type(args[i]));")
     367        args i)
     368        [(integer)
     369    ((foreign-lambda* integer
     370        (((c-pointer sqlite3:value) args) (int i))
     371        "return(sqlite3_value_double(args[i]));")
     372      args i)]
     373        [(float)
     374    ((foreign-lambda* double
     375        (((c-pointer sqlite3:value) args) (int i))
     376        "return(sqlite3_value_double(args[i]));")
     377      args i)]
     378        [(text)
     379    ((foreign-primitive scheme-object
     380        (((c-pointer sqlite3:value) args) (int i))
     381        "int n = sqlite3_value_bytes(args[i]);"
     382        "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
     383        "return(C_string(&s, n, (char *)sqlite3_value_text(args[i])));")
     384      args i)]
     385        [(blob)
     386    ((foreign-primitive scheme-object
     387        (((c-pointer sqlite3:value) args) (int i))
     388        "int n = sqlite3_value_bytes(args[i]);"
     389        "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
     390        "return(C_bytevector(&s, n, (char *)sqlite3_value_blob(args[i])));")
     391      args i)]
     392        [else
     393    (void)])
     394  (loop (add1 i))))))
     395
     396(define (set-result! ctx v)
     397  (cond
     398    [(blob? v)
     399      ((foreign-lambda* void
     400    ((sqlite3:context ctx) (scheme-pointer v) (int n))
     401    "sqlite3_result_blob(ctx, v, n, SQLITE_TRANSIENT);")
     402  ctx v (blob-size v))]
     403    [(or (and (fixnum? v) v) (and (boolean? v) (if v 1 0)))
     404      => (lambda (v)
     405    ((foreign-lambda void "sqlite3_result_int" sqlite3:context int)
     406      ctx v))]
     407    [(real? v)
     408      ((foreign-lambda void "sqlite3_result_double" sqlite3:context double)
     409  ctx v)]
     410    [(string? v)
     411      ((foreign-lambda* void
     412    ((sqlite3:context ctx) (scheme-pointer v) (int n))
    411413    "sqlite3_result_text(ctx, v, n, SQLITE_TRANSIENT);")
    412    ctx v (string-length v)) )
    413 
    414 (define-method (sqlite3:set-result! (ctx <pointer>) (v <void>))
    415   ((foreign-lambda void "sqlite3_result_null" sqlite3:context)
    416    ctx) )
    417 
    418 (define-method (sqlite3:set-result! (ctx <pointer>))
    419   ((foreign-lambda void "sqlite3_result_null" sqlite3:context)
    420    ctx) )
     414  ctx v (string-length v))]
     415    [(eq? v (void))
     416      ((foreign-lambda void "sqlite3_result_null" sqlite3:context)
     417  ctx)]
     418    [else
     419      (error-argument-type 'set-result! v "blob, number, boolean, string or void")]))
    421420
    422421(define sqlite3_user_data
    423422  (foreign-lambda scheme-object "sqlite3_user_data" sqlite3:context))
    424423
    425 (define-external (chicken_sqlite3_function_stub (c-pointer ctx) (int n) (c-pointer args))
    426                 void
     424(define-external (chicken_sqlite3_function_stub
     425      (c-pointer ctx) (int n) (c-pointer args)) void
    427426  (let/cc return
    428427    (dynamic-wind
    429         noop
    430         (lambda ()
    431           (handle-exceptions exn
    432                              (print-error "in SQL function" exn)
    433             (sqlite3:set-result!
    434              ctx
    435              (apply (vector-ref
    436                      (call-with/synch *sqlite3:functions*
    437                       (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))
    438                      1)
    439                     (sqlite3:parameter-data n args) ) ) ) )
    440        (lambda ()
    441          (return (void)) ) ) ) )
     428      noop
     429      (lambda ()
     430  (handle-exceptions exn
     431    (print-error "in SQL function" exn)
     432    (set-result!
     433      ctx
     434      (apply (vector-ref
     435    (call-with/synch *functions*
     436      (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))
     437    1)
     438        (parameter-data n args)))))
     439      (lambda ()
     440  (return (void))))))
    442441
    443442(define sqlite3_aggregate_context
    444443  (foreign-lambda* integer ((sqlite3:context ctx))
    445    "return((int)sqlite3_aggregate_context(ctx, 1));"))
    446 
    447 (define-external (chicken_sqlite3_step_stub (c-pointer ctx) (int n) (c-pointer args))
    448                 void
     444    "return((int)sqlite3_aggregate_context(ctx, 1));"))
     445
     446(define-external (chicken_sqlite3_step_stub
     447      (c-pointer ctx) (int n) (c-pointer args)) void
    449448  (let/cc return
    450449    (dynamic-wind
    451         noop
    452         (lambda ()
    453           (handle-exceptions exn
    454                              (print-error "in step of SQL function" exn)
    455             (let ([info (call-with/synch *sqlite3:functions*
    456                           (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))])
    457               (call-with/synch *sqlite3:seeds*
    458                (cute hash-table-update!/default
    459                      <>
    460                      (sqlite3_aggregate_context ctx)
    461                      (lambda (seed)
    462                        (apply (vector-ref info 1) seed (sqlite3:parameter-data n args)))
    463                      (vector-ref info 2)) ) ) ) )
    464            (lambda ()
    465              (return (void)) ) ) ) )
     450      noop
     451      (lambda ()
     452  (handle-exceptions exn
     453    (print-error "in step of SQL function" exn)
     454    (let ([info (call-with/synch *functions*
     455    (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))])
     456      (call-with/synch *seeds*
     457        (cute hash-table-update!/default
     458    <>
     459    (sqlite3_aggregate_context ctx)
     460    (lambda (seed)
     461      (apply (vector-ref info 1) seed (parameter-data n args)))
     462    (vector-ref info 2))))))
     463      (lambda ()
     464  (return (void))))))
    466465
    467466(define-external (chicken_sqlite3_final_stub (c-pointer ctx))
    468                  void
     467  void
    469468  (let/cc return
    470469    (let ([agc (sqlite3_aggregate_context ctx)])
    471470      (dynamic-wind
    472           noop
    473           (lambda ()
    474             (handle-exceptions exn
    475                                (print-error "in final of SQL function" exn)
    476               (let ([info (call-with/synch *sqlite3:functions*
    477                            (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))])
    478                 (cond [((vector-ref info 3)
    479                  (call-with/synch *sqlite3:seeds*
    480                    (cute hash-table-ref/default <> agc (vector-ref info 2))))
    481                  => (cute sqlite3:set-result! ctx <>) ]
    482                 [else
    483                  (sqlite3:set-result! ctx) ] ) ) ) )
    484           (lambda ()
    485             (call-with/synch *sqlite3:seeds*
    486              (cute hash-table-delete! <> agc))
    487             (return (void)) ) ) ) ) )
    488 
    489 (define-generic sqlite3:define-function)
    490 (define-method (sqlite3:define-function (db <sqlite3:database>)
    491                                          (name <string>)
    492                                          (n <exact>)
    493                                          (proc <procedure-class>))
    494   (let ([qn (object-evict (list (pointer->address (slot-ref db 'this)) name))])
    495     (cond [((foreign-lambda* sqlite3:status
    496                              ((sqlite3:database db)
    497                               (c-string name) (int n) (scheme-object qn))
     471  noop
     472  (lambda ()
     473    (handle-exceptions exn
     474      (print-error "in final of SQL function" exn)
     475      (let ([info (call-with/synch *functions*
     476      (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))])
     477        (cond
     478    [((vector-ref info 3)
     479      (call-with/synch *seeds*
     480        (cute hash-table-ref/default <> agc (vector-ref info 2))))
     481      => (cute set-result! ctx <>)]
     482    [else
     483      (set-result! ctx (void))]))))
     484  (lambda ()
     485    (call-with/synch *seeds*
     486      (cute hash-table-delete! <> agc))
     487    (return (void)))))))
     488
     489(define define-function
     490  (case-lambda
     491    [(db name n proc)
     492      (check-database 'define-function db)
     493      (check-string 'define-function name)
     494      (check-cardinal-number 'define-function n)
     495      (check-procedure 'define-function proc)
     496      (let ([qn (object-evict (list (pointer->address (database-ptr db)) name))])
     497  (cond
     498    [((foreign-lambda* sqlite3:status
     499        ((sqlite3:database db)
     500    (c-string name) (int n) (scheme-object qn))
    498501#<<EOS
    499502        return(sqlite3_create_function(db, name, n, SQLITE_UTF8,
    500                                        (void *)qn,
    501                                        (void (*)(sqlite3_context *, int,
    502                                                  sqlite3_value **))
    503                                        &chicken_sqlite3_function_stub,
    504                                        NULL,
    505                                        NULL));
     503      (void *)qn,
     504      (void (*)(sqlite3_context *, int,
     505          sqlite3_value **))
     506      &chicken_sqlite3_function_stub,
     507      NULL,
     508      NULL));
    506509EOS
    507             )
    508             db name n qn)
    509            => (lambda (s)
    510                 (object-release qn)
    511                 ((abort-sqlite3-error 'sqlite3:define-function db name n proc) s)) ]
    512           [else
    513            (call-with/synch *sqlite3:functions*
    514         (cute hash-table-tree-set! <> qn (vector qn proc))) ] ) ) )
    515 
    516 (define-method (sqlite3:define-function (db <sqlite3:database>)
    517                                          (name <string>)
    518                                          (n <exact>)
    519                                          (step-proc <procedure-class>)
    520                                          (seed <top>)
    521                                          #!optional (final-proc identity))
    522   (check-sqlite3-type 'sqlite3:define-function final-proc <procedure-class>)
    523   (let ([qn (object-evict (list (pointer->address (slot-ref db 'this)) name))])
    524     (cond [((foreign-lambda* sqlite3:status
    525                              ((sqlite3:database db)
    526                               (c-string name) (int n) (scheme-object qn))
     510      )
     511      db name n qn)
     512      => (lambda (s)
     513    (object-release qn)
     514    ((abort-sqlite3-error 'define-function db name n proc) s))]
     515    [else
     516    (call-with/synch *functions*
     517      (cute hash-table-tree-set! <> qn (vector qn proc)))]))]
     518    [(db name n step-proc seed . final-proc)
     519      (check-database 'define-function db)
     520      (check-string 'define-function name)
     521      (check-cardinal-number 'define-function n)
     522      (let ([final-proc (optional final-proc identity)])
     523  (check-procedure 'define-function step-proc)
     524  (check-procedure 'define-function final-proc)
     525  (let ([qn (object-evict (list (pointer->address (database-ptr db)) name))])
     526    (cond
     527      [((foreign-lambda* sqlite3:status
     528    ((sqlite3:database db)
     529      (c-string name) (int n) (scheme-object qn))
    527530#<<EOS
    528         return(sqlite3_create_function(db, name, n, SQLITE_UTF8,
    529                                        (void *)qn,
    530                                        NULL,
    531                                        (void (*)(sqlite3_context *, int,
    532                                                  sqlite3_value **))
    533                                        &chicken_sqlite3_step_stub,
    534                                        ((void (*)(sqlite3_context *))
    535                                          &chicken_sqlite3_final_stub)));
     531    return(sqlite3_create_function(db, name, n, SQLITE_UTF8,
     532        (void *)qn,
     533        NULL,
     534        (void (*)(sqlite3_context *, int,
     535      sqlite3_value **))
     536        &chicken_sqlite3_step_stub,
     537        ((void (*)(sqlite3_context *))
     538          &chicken_sqlite3_final_stub)));
    536539EOS
    537             )
    538             db name n qn)
    539            => (lambda (s)
    540                 (object-release qn)
    541                 ((abort-sqlite3-error
    542                    'sqlite3:define-function db name n step-proc seed final-proc) s)) ]
    543           [else
    544            (call-with/synch *sqlite3:functions*
    545         (cute hash-table-tree-set! <> qn (vector qn step-proc seed final-proc))) ] ) ) )
     540        )
     541        db name n qn)
     542        => (lambda (s)
     543      (object-release qn)
     544      ((abort-sqlite3-error
     545          'define-function db name n step-proc seed final-proc) s))]
     546      [else
     547        (call-with/synch *functions*
     548    (cute hash-table-tree-set! <> qn (vector qn step-proc seed final-proc)))])))]))
    546549
    547550;;; Database interface
    548551
    549552;; Get any error message
    550 (define sqlite3:errmsg
    551   (foreign-lambda c-string "sqlite3_errmsg" sqlite3:database) )
     553(define sqlite3_errmsg
     554  (foreign-lambda c-string "sqlite3_errmsg" sqlite3:database))
    552555
    553556;; Open a database
    554 (define (sqlite3:open path)
    555   (check-sqlite3-type 'sqlite3:open path <string>)
     557(define (open-database path)
     558  (check-string 'open-database path)
    556559  (let-location ([db c-pointer])
    557     (cond [((foreign-lambda sqlite3:status "sqlite3_open"
    558                                            nonnull-c-string (c-pointer sqlite3:database))
    559             (sqlite3:resolve-pathname path) #$db)
    560            => (abort-sqlite3-error 'sqlite3:open #f path) ]
    561           [else
    562            (make <sqlite3:database> 'this db 'busy-handler #f) ] ) ) )
    563 
    564 ;; Set a timeout until a busy error is thrown
    565 
    566 (define *sqlite3:busy-handlers* (make-hash-table-tree/synch 'sqlite3:busy-handlers))
    567 
    568 (define (sqlite3:set-busy-timeout! db #!optional (ms 0))
    569   (check-sqlite3-type 'sqlite3:set-busy-timeout! db <sqlite3:database>)
    570   (cond [((foreign-lambda sqlite3:status "sqlite3_busy_timeout" sqlite3:database int) db ms)
    571          => (abort-sqlite3-error 'sqlite3:set-busy-timeout! db db ms) ]
    572         (else
    573           (call-with/synch *sqlite3:busy-handlers*   ; unregister scheme handler
    574             (lambda (busy)
    575               (hash-table-delete! busy
    576                                   (pointer->address (slot-ref db 'this))))))))
    577 
    578 (define-record busy-handler proc db)
    579 (define-external (chicken_sqlite3_busy_handler_stub (c-pointer data) (int count)) int
    580   (let/cc return
    581     (let ((r #f))
    582       (dynamic-wind
    583           noop
    584           (lambda ()
    585             (handle-exceptions exn (print-error "in busy timeout handler" exn)
    586               (let* ((db-addr (pointer->address data))
    587                      (data (call-with/synch *sqlite3:busy-handlers*
    588                                             (lambda (busy) (hash-table-ref busy db-addr))))
    589                      (handler (busy-handler-proc data))
    590                      (db (busy-handler-db data)))
    591                 (set! r (handler db count)))))
    592           (lambda ()
    593             (return (if r 1 0)))))))
    594 
    595 ;; Set SQLite library busy handler callback.  This handler must not yield.
    596 ;; Callback is called with arguments DB and COUNT.
    597 (define (sqlite3:set-busy-handler! db handler)
    598   (check-sqlite3-type 'sqlite3:set-busy-handler! db <sqlite3:database>)
    599   (let ((sqlite3_busy_handler
    600          (foreign-lambda sqlite3:status "sqlite3_busy_handler"
    601                          sqlite3:database c-pointer c-pointer))
    602         (db-ptr (slot-ref db 'this)))
    603     (cond ((not handler)
    604            (cond ((sqlite3_busy_handler db #f #f)
    605                   => (abort-sqlite3-error 'sqlite3:set-busy-handler! db db handler))
    606                  (else (call-with/synch *sqlite3:busy-handlers*
    607                          (lambda (busy)
    608                            (hash-table-delete! busy (pointer->address db-ptr))
    609                            (void))))))
    610           ((sqlite3_busy_handler db #$chicken_sqlite3_busy_handler_stub db-ptr)
    611            => (abort-sqlite3-error 'sqlite3:set-busy-handler! db db handler))
    612           (else
    613            (call-with/synch *sqlite3:busy-handlers*
    614                             (lambda (busy)
    615                               (hash-table-set! busy
    616                                                (pointer->address db-ptr)
    617                                                (make-busy-handler handler db))))))))
     560    (cond
     561      [((foreign-lambda sqlite3:status "sqlite3_open"
     562    nonnull-c-string (c-pointer sqlite3:database))
     563  (##sys#expand-home-path path) #$db)
     564  => (abort-sqlite3-error 'open-database #f path)]
     565      [else
     566  (make-database db #f)])))
    618567
    619568;; Set application busy handler.  Does not use a callback, so it is safe
    620569;; to yield.  Handler is called with DB, COUNT and LAST (the last value
    621570;; it returned).  Return true value to continue trying, or #f to stop.
    622 (define (sqlite3:set-safe-busy-handler! db handler)
    623   (check-sqlite3-type 'sqlite3:set-safe-busy-handler! db <sqlite3:database>)
    624   (slot-set! db 'busy-handler handler))
    625 
    626 ;; Returns a closure suitable for use with set-safe-busy-handler!.  Identical
    627 ;; to sqlite's default busy handler (set-busy-timeout!), but does not block.
    628 (define (sqlite3:default-safe-busy-handler timeout)
     571(define (set-busy-handler! db handler)
     572  (check-database 'set-busy-handler! db)
     573  (database-busy-handler-set! db handler))
     574
     575;; Returns a closure suitable for use with set-busy-handler!.  Identical
     576;; to sqlite's default busy handler, but does not block.
     577(define (make-busy-timeout timeout)
    629578  (define (thread-sleep!/ms ms)
    630579    (thread-sleep!
    631      (milliseconds->time (+ ms (current-milliseconds)))))
    632   (let* ((delays '#(1 2 5 10 15 20 25 25 25 50 50 100))
    633          (totals '#(0 1 3  8 18 33 53 78 103 128 178 228))
    634          (ndelay (vector-length delays)))
    635     (lambda (db count last)
    636       last   ; ignored
    637       (let* ((delay (vector-ref delays (min count (- ndelay 1))))
    638              (prior (if (< count ndelay)
    639                         (vector-ref totals count)
    640                         (+ (vector-ref totals (- ndelay 1))
    641                            (* delay (- count (- ndelay 1)))))))
    642         (let ((delay (if (> (+ prior delay) timeout)
    643                          (- timeout prior)
    644                          delay)))
    645           (cond ((<= delay 0) #f)
    646                 (else
    647                  (thread-sleep!/ms delay)
    648                  #t)))))))
     580      (milliseconds->time (+ ms (current-milliseconds)))))
     581  (let* ([delays '#(1 2 5 10 15 20 25 25 25 50 50 100)]
     582   [totals '#(0 1 3  8 18 33 53 78 103 128 178 228)]
     583   [ndelay (vector-length delays)])
     584    (lambda (db count)
     585      (let* ([delay (vector-ref delays (min count (- ndelay 1)))]
     586       [prior (if (< count ndelay)
     587         (vector-ref totals count)
     588         (+ (vector-ref totals (- ndelay 1))
     589           (* delay (- count (- ndelay 1)))))])
     590  (let ([delay (if (> (+ prior delay) timeout)
     591    (- timeout prior)
     592    delay)])
     593    (cond
     594      [(<= delay 0) #f]
     595      [else
     596        (thread-sleep!/ms delay)
     597        #t]))))))
    649598
    650599;; Cancel any running database operation as soon as possible
    651 (define (sqlite3:interrupt! db)
    652   (check-sqlite3-type 'sqlite3:interrupt! db <sqlite3:database>)
    653   ((foreign-lambda void "sqlite3_interrupt" sqlite3:database) db) )
     600(define (interrupt! db)
     601  (check-database 'interrupt! db)
     602  ((foreign-lambda void "sqlite3_interrupt" sqlite3:database) db))
    654603
    655604;; Check whether the database is in autocommit mode
    656 (define (sqlite3:auto-committing? db)
    657   (check-sqlite3-type 'sqlite3:auto-committing? db <sqlite3:database>)
    658   ((foreign-lambda bool "sqlite3_get_autocommit" sqlite3:database) db) )
     605(define (auto-committing? db)
     606  (check-database 'auto-committing? db)
     607  ((foreign-lambda bool "sqlite3_get_autocommit" sqlite3:database) db))
    659608
    660609;; Get the number of changes made to the database
    661 (define (sqlite3:changes db #!optional (total #f))
    662   (check-sqlite3-type 'sqlite3:changes db <sqlite3:database>)
     610(define (change-count db #!optional (total #f))
     611  (check-database 'change-count db)
    663612  (if total
    664       ((foreign-lambda number "sqlite3_total_changes" sqlite3:database) db)
    665       ((foreign-lambda number "sqlite3_changes" sqlite3:database) db) ) )
     613    ((foreign-lambda number "sqlite3_total_changes" sqlite3:database) db)
     614    ((foreign-lambda number "sqlite3_changes" sqlite3:database) db)))
    666615
    667616;; Get the row ID of the last inserted row
    668 (define (sqlite3:last-insert-rowid db)
    669   (check-sqlite3-type 'sqlite3:last-insert-rowid db <sqlite3:database>)
    670   ((foreign-lambda number "sqlite3_last_insert_rowid" sqlite3:database) db) )
    671 
    672 ;; Close a database
    673 (define-generic sqlite3:finalize!)
    674 (define-method (sqlite3:finalize! (db <sqlite3:database>))
    675   (cond [(not (slot-ref db 'this))
    676          (void) ]
    677         [((foreign-safe-lambda sqlite3:status "sqlite3_close" sqlite3:database) db)
    678          => (abort-sqlite3-error 'sqlite3:finalize! db db) ]
    679         [else
    680          (let ([id (pointer->address (slot-ref db 'this))]
    681                [release-qns (lambda (_ info) (object-release (vector-ref info 0)))] )
    682            (call-with/synch *sqlite3:collations*
    683              (cute hash-table-tree-clear! <> id release-qns))
    684            (call-with/synch *sqlite3:functions*
    685              (cute hash-table-tree-clear! <> id release-qns)) )
    686            (slot-set! db 'this #f)
    687            (slot-set! db 'busy-handler #f)] ) )
     617(define (last-insert-rowid db)
     618  (check-database 'last-insert-rowid db)
     619  ((foreign-lambda number "sqlite3_last_insert_rowid" sqlite3:database) db))
     620
     621;; Close a database or statement handle
     622(define (finalize! db-or-stmt)
     623  (cond
     624    [(database? db-or-stmt)
     625      (cond
     626  [(not (database-ptr db-or-stmt))
     627    (void)]
     628  [((foreign-safe-lambda sqlite3:status "sqlite3_close" sqlite3:database) db-or-stmt)
     629    => (abort-sqlite3-error 'finalize! db-or-stmt db-or-stmt)]
     630  [else
     631    (let ([id (pointer->address (database-ptr db-or-stmt))]
     632        [release-qns (lambda (_ info) (object-release (vector-ref info 0)))])
     633      (call-with/synch *collations*
     634        (cute hash-table-tree-clear! <> id release-qns))
     635      (call-with/synch *functions*
     636        (cute hash-table-tree-clear! <> id release-qns)))
     637    (database-ptr-set! db-or-stmt #f)
     638    (database-busy-handler-set! db-or-stmt #f)])]
     639    [(statement? db-or-stmt)
     640      (cond
     641  [(not (statement-ptr db-or-stmt))
     642    (void)]
     643  [((foreign-lambda sqlite3:status "sqlite3_finalize" sqlite3:statement) db-or-stmt)
     644    => (abort-sqlite3-error 'finalize! (statement-database db-or-stmt) db-or-stmt)]
     645  [else
     646    (statement-ptr-set! db-or-stmt #f)])]))
    688647
    689648;;; Statement interface
    690649
    691650;; Create a new statement
    692 (define (sqlite3:prepare db sql)
    693   (check-sqlite3-type 'sqlite3:prepare db <sqlite3:database>)
    694   (check-sqlite3-type 'sqlite3:prepare sql <string>)
    695   (let retry ((retries 0) (last-busy #f))
     651(define (prepare db sql)
     652  (check-database 'prepare db)
     653  (check-string 'prepare sql)
     654  (let retry ([retries 0])
    696655    (let-location ([stmt c-pointer] [tail c-string])
    697       (cond [((foreign-safe-lambda sqlite3:status "sqlite3_prepare"
    698                                    sqlite3:database scheme-pointer int
    699                                    (c-pointer sqlite3:statement)
    700                                    (c-pointer (const c-string)))
    701               db sql (string-length sql) #$stmt #$tail)
    702              => (lambda (err)
    703                   (case err
    704                     ((busy)
    705                      (let ((h (slot-ref db 'busy-handler)))
    706                        (cond ((and h (h db retries last-busy))
    707                               => (lambda (last-busy)
    708                                    (retry (+ retries 1) last-busy)))
    709                              (else
    710                               ((abort-sqlite3-error 'sqlite3:prepare db db sql) err)))))
    711                     (else
    712                      ((abort-sqlite3-error 'sqlite3:prepare db db sql) err))))]
    713             [else
    714              (values
    715               (make <sqlite3:statement> 'this stmt 'database db 'sql sql)
    716               tail) ] ) )) )
     656      (cond
     657  [((foreign-safe-lambda sqlite3:status "sqlite3_prepare"
     658      sqlite3:database scheme-pointer int
     659      (c-pointer sqlite3:statement)
     660      (c-pointer (const c-string)))
     661    db (string-append sql "\x00") (string-length sql) #$stmt #$tail)
     662    => (lambda (err)
     663        (case err
     664    [(busy)
     665      (let ([h (database-busy-handler db)])
     666        (cond
     667          [(and h (h db retries))
     668      (retry (add1 retries))]
     669          [else
     670      ((abort-sqlite3-error 'prepare db db sql) err)]))]
     671    [else
     672      ((abort-sqlite3-error 'prepare db db sql) err)]))]
     673  [else
     674    (values
     675      (make-statement stmt db sql)
     676      tail)]))))
    717677
    718678;; Recompile an existing statement and transfer all bindings
    719 (define (sqlite3:repair! stmt)
    720   (check-sqlite3-type 'sqlite3:repair! stmt <sqlite3:statement>)
    721   (let ([fresh (sqlite3:prepare
    722                 (slot-ref stmt 'database) (slot-ref stmt 'sql))])
     679(define (repair! stmt)
     680  (check-statement 'repair! stmt)
     681  (let ([fresh (prepare
     682    (statement-database stmt)
     683    (statement-sql stmt))])
    723684    (dynamic-wind
    724         noop
    725         (lambda ()
    726           (let ([old (slot-ref stmt 'this)]
    727                 [new (slot-ref fresh 'this)] )
    728             (cond [((foreign-lambda sqlite3:status "sqlite3_transfer_bindings"
    729                                              c-pointer c-pointer)
    730               old new)
    731              => (abort-sqlite3-error 'sqlite3:repair! (slot-ref stmt 'database) stmt) ]
    732             [else
    733              (slot-set! stmt 'this new)
    734              (slot-set! fresh 'this old) ] ) ) )
    735         (lambda ()
    736           (sqlite3:finalize! fresh))) ) )
    737 
    738 ;; Discard an existing statement
    739 ;; (define-generic sqlite3:finalize!)
    740 (define-method (sqlite3:finalize! (stmt <sqlite3:statement>))
    741   (cond [(not (slot-ref stmt 'this))
    742          (void) ]
    743         [((foreign-lambda sqlite3:status "sqlite3_finalize" sqlite3:statement) stmt)
    744          => (abort-sqlite3-error 'sqlite3:finalize! (slot-ref stmt 'database) stmt) ]
    745         [else
    746          (slot-set! stmt 'this #f) ] ) )
     685      noop
     686      (lambda ()
     687  (let ([old (statement-ptr stmt)]
     688        [new (statement-ptr fresh)])
     689    (cond
     690      [((foreign-lambda sqlite3:status "sqlite3_transfer_bindings"
     691    c-pointer c-pointer)
     692        old new)
     693        => (abort-sqlite3-error 'repair! (statement-database stmt) stmt)]
     694      [else
     695        (statement-ptr-set! stmt new)
     696        (statement-ptr-set! fresh old)])))
     697      (lambda ()
     698  (finalize! fresh)))))
    747699
    748700;; Reset an existing statement to process it again
     
    750702  (foreign-lambda sqlite3:status "sqlite3_reset" sqlite3:statement))
    751703
    752 (define (sqlite3:reset! stmt)
    753   (check-sqlite3-type 'sqlite3:reset! stmt <sqlite3:statement>)
     704(define (reset! stmt)
     705  (check-statement 'reset! stmt)
    754706  (cond [(sqlite3_reset stmt)
    755          => (abort-sqlite3-error 'sqlite3:reset! (slot-ref stmt 'database) stmt) ] ) )
     707    => (abort-sqlite3-error 'reset! (statement-database stmt) stmt)]))
    756708
    757709;; Get number of bindable parameters
    758 (define (sqlite3:bind-parameter-count stmt)
    759   (check-sqlite3-type 'sqlite3:bind-parameter-count stmt <sqlite3:statement>)
    760   ((foreign-lambda int "sqlite3_bind_parameter_count" sqlite3:statement) stmt) )
     710(define (bind-parameter-count stmt)
     711  (check-statement 'bind-parameter-count stmt)
     712  ((foreign-lambda int "sqlite3_bind_parameter_count" sqlite3:statement) stmt))
    761713
    762714;; Get index of a bindable parameter or #f if no parameter with the
    763715;; given name exists
    764 (define (sqlite3:bind-parameter-index stmt name)
    765   (check-sqlite3-type 'sqlite3:bind-parameter-index stmt <sqlite3:statement>)
     716(define (bind-parameter-index stmt name)
     717  (check-statement 'bind-parameter-index stmt)
    766718  (let ([i ((foreign-lambda int "sqlite3_bind_parameter_index"
    767                                 sqlite3:statement nonnull-c-string)
    768             stmt name)])
     719        sqlite3:statement nonnull-c-string)
     720      stmt name)])
    769721    (if (zero? i)
    770         #f
    771         (sub1 i) ) ) )
     722      #f
     723      (sub1 i))))
    772724
    773725;; Get the name of a bindable parameter
    774 (define (sqlite3:bind-parameter-name stmt i)
    775   (check-sqlite3-type 'sqlite3:bind-parameter-name stmt <sqlite3:statement>)
     726(define (bind-parameter-name stmt i)
     727  (check-statement 'bind-parameter-name stmt)
    776728  ((foreign-lambda c-string "sqlite3_bind_parameter_name" sqlite3:statement int)
    777    stmt (add1 i)) )
     729    stmt (add1 i)))
    778730
    779731;; Bind data as parameters to an existing statement
    780732
    781 (define-generic sqlite3:bind!)
    782 (define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    783                               (v <blob>))
    784   (cond [((foreign-lambda* sqlite3:status
    785                            ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
    786            "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
    787           stmt (add1 i) v (blob-size v))
    788          => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    789 
    790 ; Deprecated
    791 (define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    792                               (v <byte-vector>))
    793   (cond [((foreign-lambda* sqlite3:status
    794                            ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
    795            "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
    796           stmt (add1 i) v (byte-vector-length v))
    797          => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    798 
    799 (define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    800                               (v <boolean>))
    801   (cond [((foreign-lambda sqlite3:status "sqlite3_bind_int"
    802                                          sqlite3:statement int int)
    803           stmt (add1 i) (or (and v 1) 0))
    804          => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    805 
    806 (define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    807                               (v <exact>))
    808   (cond [((foreign-lambda sqlite3:status "sqlite3_bind_int"
    809                                          sqlite3:statement int int)
    810           stmt (add1 i) v)
    811          => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    812 
    813 (define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    814                               (v <number>))
    815   (cond [((foreign-lambda sqlite3:status "sqlite3_bind_double"
    816                                           sqlite3:statement int double)
    817           stmt (add1 i) v)
    818          => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    819 
    820 (define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    821                               (v <string>))
    822   (cond [((foreign-lambda* sqlite3:status
    823                            ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
    824            "return(sqlite3_bind_text(stmt, i, v, n, SQLITE_TRANSIENT));")
    825           stmt (add1 i) v (string-length v))
    826          => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    827 
    828 (define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>))
    829   (cond [((foreign-lambda sqlite3:status "sqlite3_bind_null" sqlite3:statement int)
    830           stmt (add1 i))
    831          => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i) ] ) )
     733(define (bind! stmt i v)
     734  (check-statement 'bind! stmt)
     735  (check-cardinal-integer 'bind! i)
     736  (cond
     737    [(blob? v)
     738      (cond [((foreign-lambda* sqlite3:status
     739    ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
     740    "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
     741        stmt (add1 i) v (blob-size v))
     742        => (abort-sqlite3-error 'bind! (statement-database stmt) stmt i v)])]
     743    [(or (and (fixnum? v) v) (and (boolean? v) (if v 1 0)))
     744      => (lambda (v)
     745    (cond [((foreign-lambda sqlite3:status "sqlite3_bind_int"
     746        sqlite3:statement int int)
     747      stmt (add1 i) v)
     748      => (abort-sqlite3-error 'bind! (statement-database stmt) stmt i v)]))]
     749    [(real? v)
     750      (cond [((foreign-lambda sqlite3:status "sqlite3_bind_double"
     751    sqlite3:statement int double)
     752        stmt (add1 i) v)
     753        => (abort-sqlite3-error 'bind! (statement-database stmt) stmt i v)])]
     754    [(string? v)
     755      (cond [((foreign-lambda* sqlite3:status
     756    ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
     757    "return(sqlite3_bind_text(stmt, i, v, n, SQLITE_TRANSIENT));")
     758        stmt (add1 i) v (string-length v))
     759        => (abort-sqlite3-error 'bind! (statement-database stmt) stmt i v)])]
     760    [(eq? v (void))
     761      (cond [((foreign-lambda sqlite3:status "sqlite3_bind_null" sqlite3:statement int)
     762        stmt (add1 i))
     763        => (abort-sqlite3-error 'bind! (statement-database stmt) stmt i)])]
     764    [else
     765      (error-argument-type 'bind! v "blob, number, boolean, string or void")]))
    832766
    833767; Helper
    834768
    835 (define (bind-parameters! loc stmt params)
    836   (sqlite3:reset! stmt)
    837   (let ([cnt (sqlite3:bind-parameter-count stmt)])
    838     (if (= cnt (length params))
    839         (unless (zero? cnt)
    840           (for-each
    841            (lambda (i v)
    842              (if (eq? <void> v)
    843                  (sqlite3:bind! stmt i)
    844                  (sqlite3:bind! stmt i v) ) )
    845            (iota cnt) params) )
    846         (core:abort
    847          (make-composite-condition
    848           (make-exn-condition
    849            loc
    850            (conc "bad parameter count - received " (length params) " but expected " cnt))
    851           (make-property-condition 'arity)
    852           (make-sqlite3-condition 'error))) ) ) )
    853 
    854 (define (sqlite3:bind-parameters! stmt . params)
    855   (bind-parameters! 'sqlite3:bind-parameters! stmt params) )
     769(define (%bind-parameters! loc stmt params)
     770  (reset! stmt)
     771  (let ([cnt (bind-parameter-count stmt)]
     772  [vs (make-hash-table)])
     773    (let loop ([i 0] [params params])
     774      (match params
     775  [((? keyword? k) v . rest)
     776    (cond
     777      [(bind-parameter-index stmt (string-append ":" (keyword->string k)))
     778        => (lambda (j)
     779       (hash-table-set! vs j v)
     780       (loop i rest))]
     781      [else
     782        (error-argument-type loc k "value or keyword matching a bind parameter name")])]
     783  [(v . rest)
     784    (hash-table-set! vs i v)
     785    (loop (add1 i) rest)]
     786  [()
     787    (void)]))
     788    (if (= (hash-table-size vs) cnt)
     789      (unless (zero? cnt)
     790  (hash-table-walk vs (cut bind! stmt <> <>)))
     791      (abort
     792  (make-composite-condition
     793    (make-exn-condition
     794      loc
     795      (conc "bad parameter count - received " (hash-table-size vs) " but expected " cnt))
     796    (make-property-condition 'arity)
     797    (make-sqlite3-condition 'error))))))
     798
     799(define (bind-parameters! stmt . params)
     800  (%bind-parameters! 'bind-parameters! stmt params))
    856801
    857802;; Single-step a prepared statement, return #t if data is available,
     
    859804(define sqlite3_step
    860805  (foreign-safe-lambda sqlite3:status "sqlite3_step" sqlite3:statement))
    861 (define (sqlite3:step! stmt)
    862   (check-sqlite3-type 'sqlite3:step! stmt <sqlite3:statement>)
    863   (let* ((db (slot-ref stmt 'database))
    864          (abort (abort-sqlite3-error 'sqlite3:step! db stmt)))
    865     (let retry ((retries 0) (last-busy #f))
     806(define (step! stmt)
     807  (check-statement 'step! stmt)
     808  (let ([db (statement-database stmt)])
     809    (let retry ([retries 0])
    866810      (define (busy-retry s)
    867         (let ((h (slot-ref db 'busy-handler)))
    868           (cond ((and h (h db retries last-busy))
    869                  => (lambda (last-busy)
    870                       (retry (+ retries 1) last-busy)))
    871                 (else
    872                  (abort s)))))
     811  (let ([h (database-busy-handler db)])
     812    (cond
     813      [(and h (h db retries))
     814        (retry (add1 retries))]
     815      [else
     816        ((abort-sqlite3-error 'step! db stmt) s)])))
    873817      (let ([s (sqlite3_step stmt)])
    874         (case s
    875           [(row)
    876            #t ]
    877           [(done)
    878            #f ]
    879           [(error)
    880            (let ([s (sqlite3_reset stmt)])
    881              (case s
    882                [(schema)
    883                 (sqlite3:repair! stmt)
    884                 (retry retries last-busy)]
    885                [(busy)          ; Passed thru sometimes (e.g. ATTACH).
    886                 (busy-retry s)]
    887                [else
    888                 (abort s) ] ) ) ]
    889           [(busy)
    890            (busy-retry s)]
    891           [else
    892            (abort s) ] )) )) )
     818  (case s
     819    [(row)
     820      #t]
     821    [(done)
     822      #f]
     823    [(error)
     824      (let ([s (sqlite3_reset stmt)])
     825        (case s
     826    [(schema)
     827      (repair! stmt)
     828      (retry retries)]
     829    [(busy)             ; Passed thru sometimes (e.g. ATTACH).
     830      (busy-retry s)]
     831    [else
     832      ((abort-sqlite3-error 'step! db stmt) s)]))]
     833    [(busy)
     834      (busy-retry s)]
     835    [else
     836      ((abort-sqlite3-error 'step! db stmt) s)])))))
    893837
    894838;; Retrieve information from a prepared/stepped statement
    895 (define (sqlite3:column-count stmt)
    896   (check-sqlite3-type 'sqlite3:column-count stmt <sqlite3:statement>)
    897   ((foreign-lambda int "sqlite3_column_count" sqlite3:statement) stmt) )
    898 
    899 (define (sqlite3:column-type stmt i)
    900   (check-sqlite3-type 'sqlite3:column-type stmt <sqlite3:statement>)
    901   ((foreign-lambda sqlite3:type "sqlite3_column_type" sqlite3:statement int) stmt i) )
    902 
    903 (define (sqlite3:column-declared-type stmt i)
    904   (check-sqlite3-type 'sqlite3:column-declared-type stmt <sqlite3:statement>)
    905   ((foreign-lambda c-string "sqlite3_column_decltype" sqlite3:statement int) stmt i) )
    906 
    907 (define (sqlite3:column-name stmt i)
    908   (check-sqlite3-type 'sqlite3:column-name stmt <sqlite3:statement>)
    909   ((foreign-lambda c-string "sqlite3_column_name" sqlite3:statement int) stmt i) )
     839(define (column-count stmt)
     840  (check-statement 'column-count stmt)
     841  ((foreign-lambda int "sqlite3_column_count" sqlite3:statement) stmt))
     842
     843(define (column-type stmt i)
     844  (check-statement 'column-type stmt)
     845  ((foreign-lambda sqlite3:type "sqlite3_column_type" sqlite3:statement int) stmt i))
     846
     847(define (column-declared-type stmt i)
     848  (check-statement 'column-declared-type stmt)
     849  ((foreign-lambda c-string "sqlite3_column_decltype" sqlite3:statement int) stmt i))
     850
     851(define (column-name stmt i)
     852  (check-statement 'column-name stmt)
     853  ((foreign-lambda c-string "sqlite3_column_name" sqlite3:statement int) stmt i))
    910854
    911855;; Retrieve data from a stepped statement
    912 (define (sqlite3:column-data stmt i)
    913   (case (sqlite3:column-type stmt i)
     856(define (column-data stmt i)
     857  (case (column-type stmt i)
    914858    [(integer)
    915      ((foreign-lambda integer "sqlite3_column_double" sqlite3:statement int) stmt i) ]
     859      (if (let ([declared (column-declared-type stmt i)])
     860      (and declared (string-contains-ci declared "bool")))
     861  ((foreign-lambda bool "sqlite3_column_int" sqlite3:statement int) stmt i)
     862  ((foreign-lambda integer "sqlite3_column_double" sqlite3:statement int) stmt i))]
    916863    [(float)
    917      ((foreign-lambda double "sqlite3_column_double" sqlite3:statement int) stmt i) ]
     864      ((foreign-lambda double "sqlite3_column_double" sqlite3:statement int) stmt i)]
    918865    [(text)
    919      ((foreign-primitive scheme-object ((sqlite3:statement stmt) (int i))
    920        "int n = sqlite3_column_bytes(stmt, i);"
    921        "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    922        "return(C_string(&s, n, (char *)sqlite3_column_text(stmt, i)));")
    923       stmt i) ]
     866      ((foreign-primitive scheme-object ((sqlite3:statement stmt) (int i))
     867    "int n = sqlite3_column_bytes(stmt, i);"
     868    "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
     869    "return(C_string(&s, n, (char *)sqlite3_column_text(stmt, i)));")
     870  stmt i)]
    924871    [(blob)
    925      ((foreign-primitive scheme-object ((sqlite3:statement stmt) (int i))
    926        "int n = sqlite3_column_bytes(stmt, i);"
    927        "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    928        "return(C_bytevector(&s, n, (char *)sqlite3_column_blob(stmt, i)));")
    929       stmt i) ]
     872      ((foreign-primitive scheme-object ((sqlite3:statement stmt) (int i))
     873    "int n = sqlite3_column_bytes(stmt, i);"
     874    "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
     875    "return(C_bytevector(&s, n, (char *)sqlite3_column_blob(stmt, i)));")
     876  stmt i)]
    930877    [else
    931      <void> ] ) )
     878      (void)]))
    932879
    933880;;; Easy statement interface
     
    935882;; Compile a statement and call a procedure on it, then finalize the
    936883;; statement in a dynamic-wind exit block if it hasn't been finalized yet.
    937 (define (sqlite3:call-with-temporary-statements proc db . sqls)
    938   (check-sqlite3-type 'sqlite3:call-with-temporary-statements db <sqlite3:database>)
     884(define (call-with-temporary-statements proc db . sqls)
     885  (check-database 'call-with-temporary-statements db)
    939886  (let ([stmts #f] [e #f])
    940887    (dynamic-wind
    941         (lambda ()
    942           (unless stmts
    943             (set! stmts (map (cute sqlite3:prepare db <>) sqls))))
    944         (lambda ()
    945           (handle-exceptions exn (set! e exn)
    946             (apply proc stmts)))
    947         (lambda ()
    948           (when stmts
    949             (map sqlite3:finalize! stmts) ;; leaks if error occurs before last stmt
    950             (set! stmts #f))
    951           (and-let* ((ec e))
    952             (set! e #f)
    953             (signal ec))))))
     888      (lambda ()
     889  (unless stmts
     890    (set! stmts (map (cute prepare db <>) sqls))))
     891      (lambda ()
     892  (handle-exceptions exn (set! e exn)
     893    (apply proc stmts)))
     894      (lambda ()
     895  (when stmts
     896    (map finalize! stmts) ;; leaks if error occurs before last stmt
     897    (set! stmts #f))
     898  (and-let* ([exn e])
     899    (set! e #f)
     900    (signal exn))))))
     901
     902(define-syntax %define/statement+params
     903  (syntax-rules ()
     904    [(%define/statement+params ((name loc) (init ...) (stmt params))
     905       body ...)
     906      (define name
     907  (let ([impl (lambda (init ... stmt params) body ...)])
     908    (lambda (init ... db-or-stmt . params)
     909      (cond
     910        [(database? db-or-stmt)
     911    (call-with-temporary-statements
     912      (cute impl init ... <> (cdr params))
     913      db-or-stmt (car params))]
     914        [(statement? db-or-stmt)
     915    (impl init ... db-or-stmt params)]
     916        [else
     917    (error-argument-type loc db-or-stmt "database or statement")]))))]
     918    [(%define/statement+params (name (init ...) (stmt params))
     919       body ...)
     920      (%define/statement+params ((name 'name) (init ...) (stmt params))
     921  body ...)]
     922    [(%define/statement+params (name stmt params)
     923       body ...)
     924      (%define/statement+params ((name 'name) () (stmt params))
     925  body ...)]))
    954926
    955927;; Step through a statement and ignore possible results
    956 (define-generic sqlite3:exec)
    957 (define-method (sqlite3:exec (stmt <sqlite3:statement>) . params)
    958   (bind-parameters! 'sqlite3:exec stmt params)
    959   (while (sqlite3:step! stmt))
    960   (void) )
    961 
    962 (define-method (sqlite3:exec (db <sqlite3:database>) (sql <string>) . params)
    963   (sqlite3:call-with-temporary-statements
    964    (cute apply sqlite3:exec <> params)
    965    db sql) )
     928(define (%execute loc stmt params)
     929  (%bind-parameters! loc stmt params)
     930  (while (step! stmt))
     931  (void))
     932
     933(%define/statement+params (execute stmt params)
     934  (%execute 'execute stmt params))
    966935
    967936;; Step through a statement, ignore possible results and return the
    968937;; count of changes performed by this statement
    969 (define-generic sqlite3:update)
    970 (define-method (sqlite3:update (stmt <sqlite3:statement>) . params)
    971   (sqlite3:reset! stmt)
    972   (apply sqlite3:exec stmt params)
    973   (sqlite3:changes (slot-ref stmt 'database)) )
    974 
    975 (define-method (sqlite3:update (db <sqlite3:database>) (sql <string>) . params)
    976   (apply sqlite3:exec db sql params)
    977   (sqlite3:changes db) )
     938(%define/statement+params (update stmt params)
     939  (%execute 'update stmt params)
     940  (change-count (statement-database stmt)))
    978941
    979942;; Return only the first column of the first result row produced by this
    980943;; statement
    981944
    982 (define-generic sqlite3:first-result)
    983 (define-method (sqlite3:first-result (stmt <sqlite3:statement>) . params)
    984   (bind-parameters! 'sqlite3:first-result stmt params)
    985   (if (sqlite3:step! stmt)
    986       (let ([r (sqlite3:column-data stmt 0)])
    987         (sqlite3:reset! stmt)
    988         r )
    989       (core:abort (make-no-data-condition 'sqlite3:first-result stmt params)) ) )
    990 
    991 (define-method (sqlite3:first-result
    992                 (db <sqlite3:database>) (sql <string>) . params)
    993   (sqlite3:call-with-temporary-statements
    994    (cute apply sqlite3:first-result <> params)
    995    db sql) )
     945(%define/statement+params (first-result stmt params)
     946  (%bind-parameters! 'first-result stmt params)
     947  (if (step! stmt)
     948    (let ([r (column-data stmt 0)])
     949      (reset! stmt)
     950      r)
     951    (abort (make-no-data-condition 'first-result stmt params))))
    996952
    997953;; Return only the first result row produced by this statement as a list
    998954
    999 (define-generic sqlite3:first-row)
    1000 (define-method (sqlite3:first-row (stmt <sqlite3:statement>) . params)
    1001   (bind-parameters! 'sqlite3:first-row stmt params)
    1002   (if (sqlite3:step! stmt)
    1003       (map (cute sqlite3:column-data stmt <>)
    1004            (iota (sqlite3:column-count stmt)))
    1005       (core:abort (make-no-data-condition 'sqlite3:first-row stmt params)) ) )
    1006 
    1007 (define-method (sqlite3:first-row
    1008                 (db <sqlite3:database>) (sql <string>) . params)
    1009   (sqlite3:call-with-temporary-statements
    1010    (cute apply sqlite3:first-row <> params)
    1011    db sql))
     955(%define/statement+params (first-row stmt params)
     956  (%bind-parameters! 'first-row stmt params)
     957  (if (step! stmt)
     958    (map (cute column-data stmt <>)
     959      (iota (column-count stmt)))
     960    (abort (make-no-data-condition 'first-row stmt params))))
    1012961
    1013962;; Apply a procedure to the values of the result columns for each result row
    1014963;; while executing the statement and accumulating results.
    1015964
    1016 (define (%fold-row loc proc stmt init params)
    1017   (bind-parameters! loc stmt params)
    1018   (let ([cl (iota (sqlite3:column-count stmt))])
     965(%define/statement+params ((%fold-row loc) (loc proc init) (stmt params))
     966  (%bind-parameters! loc stmt params)
     967  (let ([cl (iota (column-count stmt))])
    1019968    (let loop ([acc init])
    1020       (if (sqlite3:step! stmt)
    1021           (loop (apply proc acc (map (cute sqlite3:column-data stmt <>) cl)))
    1022           acc ) ) ) )
    1023 
    1024 (define-generic sqlite3:fold-row)
    1025 (define-method (sqlite3:fold-row (proc <procedure-class>)
    1026                                  (stmt <sqlite3:statement>)
    1027                                  (init <object>) . params)
    1028   (%fold-row 'sqlite3:fold-row proc stmt init params) )
    1029 
    1030 (define-method (sqlite3:fold-row (proc <procedure-class>)
    1031                                  (db <sqlite3:database>)
    1032                                  (sql <string>)
    1033                                  (init <object>) . params)
    1034   (sqlite3:call-with-temporary-statements
    1035    (cute apply sqlite3:fold-row proc <> init params)
    1036    db sql) )
     969      (if (step! stmt)
     970  (loop (apply proc acc (map (cute column-data stmt <>) cl)))
     971  acc))))
     972
     973(define (fold-row proc init db-or-stmt . params)
     974  (check-procedure 'fold-row proc)
     975  (apply %fold-row 'fold-row proc init db-or-stmt params))
    1037976
    1038977;; Apply a procedure to the values of the result columns for each result row
    1039978;; while executing the statement and discard the results
    1040979
    1041 (define (for-each-row-proc proc)
    1042   (lambda (acc . cols)
    1043     (apply proc cols)
    1044     acc ) )
    1045 
    1046 (define-generic sqlite3:for-each-row)
    1047 (define-method (sqlite3:for-each-row (proc <procedure-class>)
    1048                                      (stmt <sqlite3:statement>) . params)
    1049   (%fold-row 'sqlite3:for-each-row (for-each-row-proc proc) stmt (void) params) )
    1050 
    1051 (define-method (sqlite3:for-each-row (proc <procedure-class>)
    1052                                      (db <sqlite3:database>)
    1053                                      (sql <string>) . params)
    1054   (sqlite3:call-with-temporary-statements
    1055    (cute apply sqlite3:for-each-row proc <> params)
    1056    db sql) )
     980(define (for-each-row proc db-or-stmt . params)
     981  (check-procedure 'for-each-row proc)
     982  (apply %fold-row
     983    'for-each-row
     984    (lambda (acc . columns)
     985      (apply proc columns))
     986    (void)
     987    db-or-stmt params))
    1057988
    1058989;; Apply a procedure to the values of the result columns for each result row
    1059990;; while executing the statement and accumulate the results in a list
    1060991
    1061 (define (map-row-proc proc)
    1062   (lambda (acc . cols)
    1063     (cons (apply proc cols) acc) ) )
    1064 
    1065 (define-generic sqlite3:map-row)
    1066 (define-method (sqlite3:map-row (proc <procedure-class>)
    1067                                 (stmt <sqlite3:statement>) . params)
    1068   (reverse! (%fold-row 'sqlite3:map-row (map-row-proc proc) stmt '() params)) )
    1069 
    1070 (define-method (sqlite3:map-row (proc <procedure-class>)
    1071                                 (db <sqlite3:database>)
    1072                                 (sql <string>) . params)
    1073   (sqlite3:call-with-temporary-statements
    1074    (cute apply sqlite3:map-row proc <> params)
    1075    db sql) )
     992(define (map-row proc db-or-stmt . params)
     993  (check-procedure 'map-row proc)
     994  (reverse!
     995    (apply %fold-row
     996      'map-row
     997      (lambda (acc . columns)
     998        (cons (apply proc columns) acc))
     999      '()
     1000      db-or-stmt params)))
    10761001
    10771002;;; Utility procedures
     
    10801005;; true, rollback if return value is false or the thunk is interrupted by
    10811006;; an exception
    1082 (define (sqlite3:with-transaction db thunk #!optional (type 'deferred))
    1083   (check-sqlite3-type 'sqlite3:with-transaction db <sqlite3:database>)
    1084   (check-sqlite3-type 'sqlite3:with-transaction thunk <procedure-class>)
     1007(define (with-transaction db thunk #!optional (type 'deferred))
     1008  (check-database 'with-transaction db)
     1009  (check-procedure 'with-transaction thunk)
    10851010  (unless (memq type '(deferred immediate exclusive))
    1086     (core:abort
    1087      (make-composite-condition
    1088       (make-exn-condition 'sqlite3:with-transaction
    1089                           "bad argument: expected deferred, immediate or exclusive"
    1090                           type)
    1091       (make-property-condition 'type))) )
     1011    (abort
     1012      (make-composite-condition
     1013  (make-exn-condition 'with-transaction
     1014    "bad argument: expected deferred, immediate or exclusive"
     1015    type)
     1016  (make-property-condition 'type))))
    10921017  (let ([success? #f] [e #f])
    10931018    (dynamic-wind
    1094         (lambda ()
    1095           (sqlite3:exec db
    1096            (string-append "BEGIN " (symbol->string type) " TRANSACTION;")))
    1097         (lambda ()
    1098           (handle-exceptions exn (begin
    1099                                    (print-error "with-transaction" exn)
    1100                                    (set! e exn))
    1101             (set! success? (thunk))
    1102             success?))
    1103         (lambda ()
    1104           (sqlite3:exec db
    1105                         (if success?
    1106                             "COMMIT TRANSACTION;"
    1107                             "ROLLBACK TRANSACTION;"))
    1108           (and-let* ((exn e))
    1109             (set! e #f)
    1110             (signal exn))))))
     1019      (lambda ()
     1020  (execute db
     1021    (string-append "BEGIN " (symbol->string type) " TRANSACTION;")))
     1022      (lambda ()
     1023  (handle-exceptions exn (begin
     1024      (print-error "with-transaction" exn)
     1025      (set! e exn))
     1026    (set! success? (thunk))
     1027    success?))
     1028      (lambda ()
     1029  (execute db
     1030    (if success?
     1031      "COMMIT TRANSACTION;"
     1032      "ROLLBACK TRANSACTION;"))
     1033  (and-let* ([exn e])
     1034    (set! e #f)
     1035    (signal exn))))))
    11111036
    11121037;; Check if the given string is a valid SQL statement
    1113 (define sqlite3:complete?
     1038(define sql-complete?
    11141039  (foreign-lambda bool "sqlite3_complete" nonnull-c-string))
    11151040
    11161041;; Return a descriptive version string
    1117 (define sqlite3:library-version
    1118   (foreign-lambda c-string "sqlite3_libversion") )
     1042(define database-version
     1043  (foreign-lambda c-string "sqlite3_libversion"))
    11191044
    11201045;; Enables (disables) the sharing of the database cache and schema data
    11211046;; structures between connections to the same database.
    1122 (define (sqlite3:enable-shared-cache! enable?)
     1047(define (enable-shared-cache! enable?)
    11231048  (cond
    1124    (((foreign-lambda sqlite3:status "sqlite3_enable_shared_cache" bool) enable?)
    1125     => (abort-sqlite3-error 'sqlite3:enable-shared-cache! #f))))
    1126 
    1127 ;; Return a Scheme boolean for the usual SQLite column boolean values
    1128 (define (sqlite3:boolean-value v)
    1129   (cond [(string? v)
    1130          (or (string-ci=? "Y" v)
    1131              (string-ci=? "YES" v)
    1132              (string=? "Yes" v)) ]
    1133         [(and (integer? v) (exact? v))
    1134          (not (zero? v)) ]
    1135         [else
    1136           #f ] ) )
     1049    [((foreign-lambda sqlite3:status "sqlite3_enable_shared_cache" bool) enable?)
     1050      => (abort-sqlite3-error 'enable-shared-cache! #f)]))
     1051
     1052)
  • release/4/sqlite3/trunk/sqlite3.setup

    r10382 r15334  
    1 (required-extension-version 'tinyclos "1.4" 'synch "1.3" 'miscmacros "2.5")
    2 
    3 (define so-file "sqlite3.so")
    4 
    5 (compile
    6   -O2 -d0 -X easyffi -X tinyclos -s sqlite3.scm -lsqlite3
    7   -o ,so-file
    8   -check-imports -emit-exports "sqlite3.exports")
    9 
     1(compile -O2 -d1
     2  -s "sqlite3.scm" -lsqlite3 -j "sqlite3")
     3(compile -O2 -d0
     4  -s "sqlite3.import.scm")
     5(compile -O2 -d1
     6  -c "sqlite3.scm" -unit "sqlite3" -o "sqlite3-static.o")
    107(install-extension
    118  'sqlite3
    12   `(,so-file
    13     "sqlite3.html" "egg.jpg")
    14   '((version "2.0.8")
    15     (documentation "sqlite3.html")))
     9  '("sqlite3.so" "sqlite3.import.so" "sqlite3-static.o")
     10  '((version "3.2.1")
     11    (static "sqlite3-static.o")
     12    (documentation "sqlite3.html" "egg.jpg")))
Note: See TracChangeset for help on using the changeset viewer.