Changeset 8688 in project


Ignore:
Timestamp:
02/23/08 17:16:34 (12 years ago)
Author:
Kon Lovett
Message:

Rel 2.0.5

Location:
release/3/sqlite3
Files:
10 edited
1 copied

Legend:

Unmodified
Added
Removed
  • release/3/sqlite3/tags/2.0.5/doc.scm

    r8020 r8688  
    11(use eggdoc)
    22
    3 (define doc
    4   '((eggdoc:begin
    5      (name "sqlite3")
    6      (description (p "Bindings to version 3.x of the SQLite API."))
    7      (author (url "http://www.chust.org/" "Thomas Chust"))
    8      (usage)
    9      (download "sqlite3.egg")
    10      (requires "synch" "tinyclos" "easyffi" "miscmacros")
    11 
    12      (documentation
     3(define doc '(
     4  (eggdoc:begin
     5
     6    (name "sqlite3")
     7    (description (p "Bindings to version 3.x of the SQLite API."))
     8    (author
     9      (url "http://www.chust.org/" "Thomas Chust"))
     10    (usage)
     11    (download "sqlite3.egg")
     12    (requires "synch" "tinyclos" "easyffi" "miscmacros")
     13
     14    (documentation
     15
    1316      (p "The API of SQLite changed significantly from version 2.x to 3.x. These are new bindings to the modified API, which are reasonably complete -- most procedures that take callback arguments are missing, though.")
    1417      (p "For in-depth information on the functionality of the routines and general information you should consult the " (url "http://www.sqlite.org/" "SQLite documentation") " as well as this manual.")
    1518
    16       (subsection
    17        "Exceptions"
    18        (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:"
     19      (subsection "Exceptions"
     20
     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:"
    1922        (table
    20          (tr (th "Symbol") (th "Meaning"))
    21          #;(tr (td (tt "ok")) (td "Successful result"))
    22          (tr (td (tt "error")) (td "SQL error or missing database "))
    23          (tr (td (tt "internal")) (td "An internal logic error in SQLite "))
    24          (tr (td (tt "permission")) (td "Access permission denied "))
    25          (tr (td (tt "abort")) (td "Callback routine requested an abort "))
    26          (tr (td (tt "busy")) (td "The database file is locked "))
    27          (tr (td (tt "locked")) (td "A table in the database is locked "))
    28          (tr (td (tt "no-memory")) (td "A malloc() failed "))
    29          (tr (td (tt "read-only")) (td "Attempt to write a readonly database "))
    30          (tr (td (tt "interrupt")) (td "Operation terminated by sqlite-interrupt() "))
    31          (tr (td (tt "io-error")) (td "Some kind of disk I/O error occurred "))
    32          (tr (td (tt "corrupt")) (td "The database disk image is malformed "))
    33          (tr (td (tt "not-found")) (td "(Internal Only) Table or record not found "))
    34          (tr (td (tt "full")) (td "Insertion failed because database is full "))
    35          (tr (td (tt "cant-open")) (td "Unable to open the database file "))
    36          (tr (td (tt "protocol")) (td "Database lock protocol error "))
    37          (tr (td (tt "empty")) (td "(Internal Only) Database table is empty "))
    38          (tr (td (tt "schema")) (td "The database schema changed "))
    39          (tr (td (tt "too-big")) (td "Too much data for one row of a table "))
    40          (tr (td (tt "constraint")) (td "Abort due to contraint violation "))
    41          (tr (td (tt "mismatch")) (td "Data type mismatch "))
    42          (tr (td (tt "misuse")) (td "Library used incorrectly "))
    43          (tr (td (tt "no-lfs")) (td "Uses OS features not supported on host "))
    44          (tr (td (tt "authorization")) (td " Authorization denied"))
    45          #;(tr (td (tt "row")) (td (tt "sqlite3:step!") " has another row ready "))
    46          (tr (td (tt "done")) (td (tt "sqlite3:step!") " has finished executing, so no further data is ready")))))
    47 
    48       (subsection
    49        "Classes"
    50        (group
    51         (definition
    52           (signatures
    53            (signature "class" "<sqlite3:database>")
    54            (signature "class" "<sqlite3:statement>"))
    55           (p "These classes are derived from " (tt "<c++-object>") ". They hold a pointer to the underlying C-structure in their " (tt "this") " slot.")
    56           (p (tt "<sqlite3:statement>") " also has a " (tt "database") " slot pointing to the database object it belongs to."))))
    57 
    58       (subsection
    59        "Managing databases"
    60        (group
    61         (procedure
    62          "(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         (definition
    66           (signatures
    67            (signature "method" "(sqlite3:define-collation (db <sqlite3:database>) (name <string>)) => <void>")
    68            (signature "method" "(sqlite3:define-collation (db <sqlite3:database>) (name <string>) (proc <procedure-class>)) => <void>"))
    69           (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.")
    70           (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.")
    71           (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."))
    72         (definition
    73           (signatures
    74            (signature "method" "(sqlite3:define-function (db <sqlite3:database>) (name <string>) (n <exact>) (proc <procedure-class>)) => <void>")
    75            (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>"))
    76           (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.")
    77           (p (tt "n") " is the number of parameters the new SQL function takes or " (tt "-1") " to allow any number of arguments.")
    78           (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.")
    79           (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.")
    80           (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.")
    81           (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."))
    82         (procedure
    83          "(sqlite3:set-busy-timeout! (db <sqlite3:database>) #!optional ((ms <exact>) 0)) => <void>"
    84          (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."))
    85         (procedure
    86          "(sqlite3:interrupt! (db <sqlite3:database>)) => <void>"
    87          (p "Cancels any running database operation as soon as possible.")
    88          (p "This function is always successful and never throws an exception."))
    89         (procedure
    90          "(sqlite3:auto-committing? (db <sqlite3:database>)) => <bool>"
    91          (p "Checks whether the database is currently in auto committing mode, i.e. no transaction is currently active.")
    92          (p "This function always returns a state and never throws an exception."))
    93         (procedure
    94          "(sqlite3:changes (db <sqlite3:database>) #!optional ((total <bool>) #f)) => <number>"
    95          (p "Returns the number of rows changed by the last statement (if " (tt "(not total)") ") or since the database was opened (if " (tt "total") ").")
    96          (p "This function always returns a count and never throws an exception."))
    97         (procedure
    98          "(sqlite3:last-insert-rowid (db <sqlite3:database>)) => <number>"
    99          (p "Returns the row ID of the last row inserted in " (tt "db") ".")
    100          (p "This function always returns a number and never throws an exception."))
    101         (method
    102          "(sqlite3:finalize! (db <sqlite3:database>)) => <void>"
    103          (p "Closes the given database."))))
    104 
    105       (subsection
    106        "Managing statements"
    107        (group
    108         (procedure
    109          "(sqlite3:prepare (db <sqlite3:database>) (sql <string>)) => <sqlite3:statement>, <string>"
    110          (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)."))
    111         (procedure
    112          "(sqlite3:repair! (stmt <sqlite3:statement>)) => <void>"
    113          (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.")
    114          (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.")
    115          (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."))
    116         (procedure
    117          "(sqlite3:column-count (stmt <sqlite3:statement>)) => <exact>"
    118          (p "Can be applied to any statement and returns the number of columns it will return as results.")
    119          (p "This procedure always succeeds and never throws an exception."))
    120         (procedure
    121          "(sqlite3:column-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
    122          (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.")
    123          (p "This procedure always succeeds and never throws an exception."))
    124         (procedure
    125          "(sqlite3:column-declared-type (stmt <sqlite3:statement>) (i <exact>)) => <string>"
    126          (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.")
    127          (p "This procedure always succeeds and never throws an exception."))
    128         (procedure
    129          "(sqlite3:bind-parameter-count (stmt <sqlite3:statement>)) => <exact>"
    130          (p "Can be applied to any statement and returns the number of free parameters that can be bound in the statement.")
    131          (p "This procedure always succeeds and never throws an exception."))
    132         (procedure
    133          "(sqlite3:bind-parameter-index (stmt <sqlite3:statement>) (name <string>)) => <exact>"
    134          (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.")
    135          (p "This procedure always succeeds and never throws an exception."))
    136         (procedure
    137          "(sqlite3:bind-parameter-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
    138          (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.")
    139          (p "This procedure always succeeds and never throws an exception."))
    140         (definition
    141           (signatures
    142            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)) => <void>")
    143            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <void>)) => <void>")
    144            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <exact>)) => <void>")
    145            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <number>)) => <void>")
    146            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <string>)) => <void>")
    147            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <blob>)) => <void>"))
    148           (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:"
    149              (table
    150               (tr (th "Scheme type") (th "SQLite type"))
    151               (tr (td "none") (td (tt "null")))
    152               (tr (td (tt "<sqlite3:null-value>")) (td (tt "null")))
    153               (tr (td (tt "<exact>")) (td (tt "integer")))
    154               (tr (td (tt "<number>")) (td (tt "float")))
    155               (tr (td (tt "<string>")) (td (tt "text")))
    156               (tr (td (tt "<blob>")) (td (tt "blob")))))
    157           (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."))
    158         (procedure
    159          "(sqlite3:bind-parameters! (stmt <sqlite3:statement>) . params) => <void>"
    160          (p "Binds the statement's free parameters."))
    161         (procedure
    162          "(sqlite3:step! (stmt <sqlite3:statement>)) => <boolean>"
    163          (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."))
    164         (procedure
    165          "(sqlite3:column-type (stmt <sqlite3:statement>) (i <exact>)) => <symbol>"
    166          (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.")
    167          (p "The return value can be one of the symbols " (tt "null") ", " (tt "integer") ", " (tt "float") ", " (tt "text") " or " (tt "blob") ".")
    168          (p "This procedure always succeeds and never throws an exception."))
    169         (procedure
    170          "(sqlite3:column-data (stmt <sqlite3:statement>) (i <exact>)) => <void | exact | number | string | blob>"
    171          (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.")
    172          (p "See " (tt "sqlite3:bind!") " for the mapping between Scheme and SQLite data types. Columns of type " (tt "null") " are returned as " (tt "<sqlite3:null-value>") ". 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>") ".")
    173          (p "This procedure always succeeds and never throws an exception."))
    174         (procedure
    175          "(sqlite3:reset! (stmt <sqlite3:statement>)) => <void>"
    176          (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."))
    177         (method
    178          "(sqlite3:finalize! (stmt <sqlite3:statement>)) => <void>"
    179          (p "Must be applied to every statement to free its resources and discard it.")
    180          (p (tt "sqlite3:close") " will not be able to close a database that has associated unfinalized statements."))))
    181 
    182       (subsection
    183        "Simple statement interface"
    184        (group
    185         (procedure
    186          "(sqlite3:call-with-temporary-statements (proc <procedure-class>) (db <sqlite3:database>) . sqls) => <top>"
    187          (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") "."))
    188         (definition
    189           (signatures
    190            (signature "method" "(sqlite3:exec (stmt <sqlite3:statement>) . params) => <void>")
    191            (signature "method" "(sqlite3:exec (db <sqlite3:database>) (sql <string>) . params) => <void>"))
    192           (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it."))
    193         (definition
    194           (signatures
    195            (signature "method" "(sqlite3:update (stmt <sqlite3:statement>) . params) => <exact>")
    196            (signature "method" "(sqlite3:update (db <sqlite3:database>) (sql <string>) . params) => <exact>"))
    197           (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."))
    198         (definition
    199           (signatures
    200            (signature "method" "(sqlite3:first-result (stmt <sqlite3:statement>) . params) => <void | exact | number | string | blob>")
    201            (signature "method" "(sqlite3:first-result (db <sqlite3:database>) (sql <string>) . params) => <void | exact | number | string | blob>"))
    202           (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.")
    203           (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") "."))
    204         (definition
    205           (signatures
    206            (signature "method" "(sqlite3:first-row (stmt <sqlite3:statement>) . params) => <list>")
    207            (signature "method" "(sqlite3:first-row (db <sqlite3:database>) (sql <string>) . params) => <list>"))
    208           (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.")
    209           (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") "."))(definition
    210           (signatures
    211            (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (stmt <sqlite3:statement>) initial . params) => <list>")
    212            (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) initial . params) => <list>"))
    213           (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."))
    214         (definition
    215           (signatures
    216            (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <void>")
    217            (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <void>"))
    218           (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."))
    219         (definition
    220           (signatures
    221            (signature "method" "(sqlite3:map-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <list>")
    222            (signature "method" "(sqlite3:map-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <list>"))
    223           (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."))))
    224 
    225       (subsection
    226        "Utility functions"
    227        (group
    228         (procedure
    229          "(sqlite3:with-transaction (db <sqlite3:database>) (thunk <procedure-class>) #!optional ((type <symbol>) 'deferred)) => <void>"
    230          (p "Runs " (tt "thunk") " within the scope of a transaction on the dataase " (tt "db") ".")
    231          (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.")
    232          (p "The " (tt "type") " of the transaction can be specified as one of the symbols " (tt "deferred") ", " (tt "immediate") " or " (tt "exclusive") "."))
    233         (procedure
    234          "(sqlite3:complete? (sql <string>)) => <boolean>"
    235          (p "Checks whether " (tt "sql") " comprises at least one complete SQL statement."))
    236         (procedure
    237          "(sqlite3:library-version) => <string>"
    238          (p "Returns a string identifying the version of SQLite in use."))
    239         (procedure
    240          "(sqlite3:null-value? <object>) => <boolean>"
    241          (p "Is the " (tt "<object>") " a <sqlite3:null-value>?")
    242          (p "The <sqlite3:null-value> is compatible with the \"sql-null\" egg. "
    243             "The default \"sql-null\" egg function " (code "(sql-null)") " "
    244             "= the <sqlite3:null-value>. "
    245             "But to ensure equality - " (code "(define sql-null sqlite3:null)") ".")))))
    246 
    247      (history
     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.") ) )
     59
     60      (subsection "Managing databases"
     61
     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
     88        (procedure "(sqlite3:interrupt! (db <sqlite3:database>)) => <void>"
     89          (p "Cancels any running database operation as soon as possible.")
     90          (p "This function is always successful and never throws an exception."))
     91
     92        (procedure "(sqlite3:auto-committing? (db <sqlite3:database>)) => <bool>"
     93          (p "Checks whether the database is currently in auto committing mode, i.e. no transaction is currently active.")
     94          (p "This function always returns a state and never throws an exception."))
     95
     96        (procedure "(sqlite3:changes (db <sqlite3:database>) #!optional ((total <bool>) #f)) => <number>"
     97          (p "Returns the number of rows changed by the last statement (if " (tt "(not total)") ") or since the database was opened (if " (tt "total") ").")
     98          (p "This function always returns a count and never throws an exception."))
     99
     100        (procedure "(sqlite3:last-insert-rowid (db <sqlite3:database>)) => <number>"
     101          (p "Returns the row ID of the last row inserted in " (tt "db") ".")
     102          (p "This function always returns a number and never throws an exception."))
     103
     104        (method "(sqlite3:finalize! (db <sqlite3:database>)) => <void>"
     105          (p "Closes the given database.") ) )
     106
     107      (subsection "Managing statements"
     108
     109        (procedure "(sqlite3:prepare (db <sqlite3:database>) (sql <string>)) => <sqlite3:statement>, <string>"
     110          (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)."))
     111
     112        (procedure "(sqlite3:repair! (stmt <sqlite3:statement>)) => <void>"
     113          (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.")
     114          (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.")
     115          (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."))
     116
     117        (procedure "(sqlite3:column-count (stmt <sqlite3:statement>)) => <exact>"
     118          (p "Can be applied to any statement and returns the number of columns it will return as results.")
     119          (p "This procedure always succeeds and never throws an exception."))
     120
     121        (procedure "(sqlite3:column-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
     122          (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.")
     123          (p "This procedure always succeeds and never throws an exception."))
     124
     125        (procedure "(sqlite3:column-declared-type (stmt <sqlite3:statement>) (i <exact>)) => <string>"
     126          (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.")
     127          (p "This procedure always succeeds and never throws an exception."))
     128
     129        (procedure "(sqlite3:bind-parameter-count (stmt <sqlite3:statement>)) => <exact>"
     130          (p "Can be applied to any statement and returns the number of free parameters that can be bound in the statement.")
     131          (p "This procedure always succeeds and never throws an exception."))
     132
     133        (procedure "(sqlite3:bind-parameter-index (stmt <sqlite3:statement>) (name <string>)) => <exact>"
     134          (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.")
     135          (p "This procedure always succeeds and never throws an exception."))
     136
     137        (procedure "(sqlite3:bind-parameter-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
     138          (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.")
     139          (p "This procedure always succeeds and never throws an exception."))
     140
     141        (definition
     142          (signatures
     143            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)) => <void>")
     144            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <boolean>)) => <void>")
     145            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <exact>)) => <void>")
     146            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <number>)) => <void>")
     147            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <string>)) => <void>")
     148            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <blob>)) => <void>"))
     149          (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:"
     150          (table
     151            (tr (th "Scheme type") (th "SQLite type"))
     152            (tr (td "none") (td (tt "null")))
     153            (tr (td (tt "<boolean>")) (td (tt "integer: #t = 1, #f = 0")))
     154            (tr (td (tt "<exact>")) (td (tt "integer")))
     155            (tr (td (tt "<number>")) (td (tt "float")))
     156            (tr (td (tt "<string>")) (td (tt "text")))
     157            (tr (td (tt "<blob>")) (td (tt "blob")))))
     158          (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."))
     159
     160        (procedure "(sqlite3:bind-parameters! (stmt <sqlite3:statement>) . params) => <void>"
     161          (p "Binds the statement's free parameters.")
     162          (p "Allows " (code "<void>") " as a parameter.") )
     163
     164        (procedure "(sqlite3:step! (stmt <sqlite3:statement>)) => <boolean>"
     165          (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."))
     166
     167        (procedure "(sqlite3:column-type (stmt <sqlite3:statement>) (i <exact>)) => <symbol>"
     168          (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.")
     169          (p "The return value can be one of the symbols " (tt "null") ", " (tt "integer") ", " (tt "float") ", " (tt "text") " or " (tt "blob") ".")
     170          (p "This procedure always succeeds and never throws an exception."))
     171
     172        (procedure "(sqlite3:column-data (stmt <sqlite3:statement>) (i <exact>)) => <void | exact | number | string | blob>"
     173          (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.")
     174          (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>") ".")
     175          (p "This procedure always succeeds and never throws an exception."))
     176
     177        (procedure "(sqlite3:reset! (stmt <sqlite3:statement>)) => <void>"
     178          (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."))
     179
     180        (method "(sqlite3:finalize! (stmt <sqlite3:statement>)) => <void>"
     181          (p "Must be applied to every statement to free its resources and discard it.")
     182          (p (tt "sqlite3:close") " will not be able to close a database that has associated unfinalized statements.") ) )
     183
     184      (subsection "Simple statement interface"
     185
     186        (procedure "(sqlite3:call-with-temporary-statements (proc <procedure-class>) (db <sqlite3:database>) . sqls) => <top>"
     187          (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") "."))
     188
     189        (definition
     190          (signatures
     191            (signature "method" "(sqlite3:exec (stmt <sqlite3:statement>) . params) => <void>")
     192            (signature "method" "(sqlite3:exec (db <sqlite3:database>) (sql <string>) . params) => <void>"))
     193          (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it.")
     194          (p "Allows " (code "<void>") " as a parameter.") )
     195
     196        (definition
     197          (signatures
     198            (signature "method" "(sqlite3:update (stmt <sqlite3:statement>) . params) => <exact>")
     199            (signature "method" "(sqlite3:update (db <sqlite3:database>) (sql <string>) . params) => <exact>"))
     200          (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.")
     201          (p "Allows " (code "<void>") " as a parameter.") )
     202
     203        (definition
     204          (signatures
     205            (signature "method" "(sqlite3:first-result (stmt <sqlite3:statement>) . params) => <void | exact | number | string | blob>")
     206            (signature "method" "(sqlite3:first-result (db <sqlite3:database>) (sql <string>) . params) => <void | exact | number | string | blob>"))
     207          (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.")
     208          (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") ".")
     209          (p "Allows " (code "<void>") " as a parameter.") )
     210
     211        (definition
     212          (signatures
     213            (signature "method" "(sqlite3:first-row (stmt <sqlite3:statement>) . params) => <list>")
     214            (signature "method" "(sqlite3:first-row (db <sqlite3:database>) (sql <string>) . params) => <list>"))
     215          (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.")
     216          (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") ".")
     217          (p "Allows " (code "<void>") " as a parameter.") )
     218
     219        (definition
     220          (signatures
     221            (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (stmt <sqlite3:statement>) initial . params) => <list>")
     222            (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) initial . params) => <list>"))
     223          (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.")
     224          (p "Allows " (code "<void>") " as a parameter.") )
     225
     226        (definition
     227          (signatures
     228            (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <void>")
     229            (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <void>"))
     230          (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.")
     231          (p "Allows " (code "<void>") " as a parameter.") )
     232
     233        (definition
     234          (signatures
     235            (signature "method" "(sqlite3:map-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <list>")
     236            (signature "method" "(sqlite3:map-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <list>"))
     237          (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.")
     238          (p "Allows " (code "<void>") " as a parameter.") ) )
     239
     240      (subsection "Utility functions"
     241
     242        (procedure "(sqlite3:with-transaction (db <sqlite3:database>) (thunk <procedure-class>) #!optional ((type <symbol>) 'deferred)) => <void>"
     243          (p "Runs " (tt "thunk") " within the scope of a transaction on the database " (tt "db") ".")
     244          (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.")
     245          (p "The " (tt "type") " of the transaction can be specified as one of the symbols " (tt "deferred") ", " (tt "immediate") " or " (tt "exclusive") "."))
     246
     247        (procedure "(sqlite3:complete? (sql <string>)) => <boolean>"
     248          (p "Checks whether " (tt "sql") " comprises at least one complete SQL statement."))
     249
     250        (procedure "(sqlite3:library-version) => <string>"
     251          (p "Returns a string identifying the version of SQLite in use.") )
     252
     253        (procedure "(sqlite3:boolean-value v) => <boolean>"
     254          (p "Returns a Scheme boolean for the usual SQLite column boolean values.")
     255          (p "Truth values are " (code "Y") ", " (code "y") ", " (code "YES") ", " (code "yes") ", " (code "Yes") ", and " (code "(not (zero? v))") ".")
     256          (p "Anything else is considered false.") ) ) )
     257
     258    (history
     259      (version "2.0.5" "Added some <boolean> support. Change for NULL (<void>) handling. [Kon Lovett]")
    248260      (version "2.0.4" "Added " (code "sqlite3:fold-row") " & " (code "sqlite3:bind-parameters!") ". Fix for introduced bug in " (code "sqlite3:changes") ". [Kon Lovett]")
    249261      (version "2.0.3" "Added " (code "sqlite3:null-value") ", " (code "sqlite3:null-value?") ", and " (code "sqlite3:null") ". [Kon Lovett]")
     
    273285      (version "1.0.2" "Added a typecheck for increased safety")
    274286      (version "1.0.1" "Fixed type mistakes in the source")
    275       (version "1.0.0" "Initial release"))
    276 
    277       (license
    278        "Copyright (c) 2005, Thomas Chust <chust@web.de>.  All rights reserved.
     287      (version "1.0.0" "Initial release") )
     288
     289     (license #<<EOS
     290Copyright (c) 2005, Thomas Chust <chust@web.de>.  All rights reserved.
    279291
    280292Redistribution and use in source and binary forms, with or without
     
    300312LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    301313NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    302 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."))))
    303 
    304 (eggdoc->html
    305  doc
    306  (append
    307   (eggdoc:make-stylesheet doc)
    308   `((method *macro* . ,eggdoc:make-defsig))))
     314SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     315EOS
     316) ) ) )
     317
     318(eggdoc->html doc
     319              (append (eggdoc:make-stylesheet doc)
     320                      `((method *macro* . ,eggdoc:make-defsig))))
  • release/3/sqlite3/tags/2.0.5/sqlite3.html

    r8020 r8688  
    251251<div class="subsection">
    252252<h4>Classes</h4>
    253 <dl>
    254253<dt class="definition"><strong>class:</strong> &lt;sqlite3:database&gt;
    255254<br /><strong>class:</strong> &lt;sqlite3:statement&gt;</dt>
    256255<dd>
    257256<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>
    258 <p><tt>&lt;sqlite3:statement&gt;</tt> also has a <tt>database</tt> slot pointing to the database object it belongs to.</p></dd></dl></div>
     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>
    259258<div class="subsection">
    260259<h4>Managing databases</h4>
    261 <dl>
    262260<dt class="definition"><strong>procedure:</strong> (sqlite3:open (path &lt;string&gt;)) =&gt; &lt;sqlite3:database&gt;</dt>
    263261<dd>
     
    301299<dt class="definition"><strong>method:</strong> (sqlite3:finalize! (db &lt;sqlite3:database&gt;)) =&gt; &lt;void&gt;</dt>
    302300<dd>
    303 <p>Closes the given database.</p></dd></dl></div>
     301<p>Closes the given database.</p></dd></div>
    304302<div class="subsection">
    305303<h4>Managing statements</h4>
    306 <dl>
    307304<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>
    308305<dd>
     
    338335<p>This procedure always succeeds and never throws an exception.</p></dd>
    339336<dt class="definition"><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;)) =&gt; &lt;void&gt;
    340 <br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;void&gt;)) =&gt; &lt;void&gt;
     337<br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;boolean&gt;)) =&gt; &lt;void&gt;
    341338<br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;exact&gt;)) =&gt; &lt;void&gt;
    342339<br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;number&gt;)) =&gt; &lt;void&gt;
     
    353350<td><tt>null</tt></td></tr>
    354351<tr>
    355 <td><tt>&lt;sqlite3:null-value&gt;</tt></td>
    356 <td><tt>null</tt></td></tr>
     352<td><tt>&lt;boolean&gt;</tt></td>
     353<td><tt>integer: #t = 1, #f = 0</tt></td></tr>
    357354<tr>
    358355<td><tt>&lt;exact&gt;</tt></td>
     
    370367<dt class="definition"><strong>procedure:</strong> (sqlite3:bind-parameters! (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;void&gt;</dt>
    371368<dd>
    372 <p>Binds the statement's free parameters.</p></dd>
     369<p>Binds the statement's free parameters.</p>
     370<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    373371<dt class="definition"><strong>procedure:</strong> (sqlite3:step! (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;boolean&gt;</dt>
    374372<dd>
     
    382380<dd>
    383381<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>
    384 <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;sqlite3:null-value&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>
     382<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>
    385383<p>This procedure always succeeds and never throws an exception.</p></dd>
    386384<dt class="definition"><strong>procedure:</strong> (sqlite3:reset! (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;void&gt;</dt>
     
    390388<dd>
    391389<p>Must be applied to every statement to free its resources and discard it.</p>
    392 <p><tt>sqlite3:close</tt> will not be able to close a database that has associated unfinalized statements.</p></dd></dl></div>
     390<p><tt>sqlite3:close</tt> will not be able to close a database that has associated unfinalized statements.</p></dd></div>
    393391<div class="subsection">
    394392<h4>Simple statement interface</h4>
    395 <dl>
    396393<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>
    397394<dd>
     
    400397<br /><strong>method:</strong> (sqlite3:exec (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;void&gt;</dt>
    401398<dd>
    402 <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>
     399<p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it.</p>
     400<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    403401<dt class="definition"><strong>method:</strong> (sqlite3:update (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;exact&gt;
    404402<br /><strong>method:</strong> (sqlite3:update (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;exact&gt;</dt>
    405403<dd>
    406 <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></dd>
     404<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>
     405<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    407406<dt class="definition"><strong>method:</strong> (sqlite3:first-result (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;void | exact | number | string | blob&gt;
    408407<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>
    409408<dd>
    410409<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>
    411 <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>
     410<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>
     411<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    412412<dt class="definition"><strong>method:</strong> (sqlite3:first-row (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;list&gt;
    413413<br /><strong>method:</strong> (sqlite3:first-row (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;list&gt;</dt>
    414414<dd>
    415415<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>
    416 <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>
     416<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>
     417<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    417418<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;
    418419<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>
    419420<dd>
    420 <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></dd>
     421<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>
     422<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    421423<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;
    422424<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>
    423425<dd>
    424 <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>
     426<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>
     427<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    425428<dt class="definition"><strong>method:</strong> (sqlite3:map-row (proc &lt;procedure-class&gt;) (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;list&gt;
    426429<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>
    427430<dd>
    428 <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></dl></div>
     431<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>
     432<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd></div>
    429433<div class="subsection">
    430434<h4>Utility functions</h4>
    431 <dl>
    432435<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>
    433436<dd>
    434 <p>Runs <tt>thunk</tt> within the scope of a transaction on the dataase <tt>db</tt>.</p>
     437<p>Runs <tt>thunk</tt> within the scope of a transaction on the database <tt>db</tt>.</p>
    435438<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>
    436439<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>
     
    441444<dd>
    442445<p>Returns a string identifying the version of SQLite in use.</p></dd>
    443 <dt class="definition"><strong>procedure:</strong> (sqlite3:null-value? &lt;object&gt;) =&gt; &lt;boolean&gt;</dt>
    444 <dd>
    445 <p>Is the <tt>&lt;object&gt;</tt> a &lt;sqlite3:null-value&gt;?</p>
    446 <p>The &lt;sqlite3:null-value&gt; is compatible with the &quot;sql-null&quot; egg. The default &quot;sql-null&quot; egg function <code>(sql-null)</code> = the &lt;sqlite3:null-value&gt;. But to ensure equality - <code>(define sql-null sqlite3:null)</code>.</p></dd></dl></div></div>
     446<dt class="definition"><strong>procedure:</strong> (sqlite3:boolean-value v) =&gt; &lt;boolean&gt;</dt>
     447<dd>
     448<p>Returns a Scheme boolean for the usual SQLite column boolean values.</p>
     449<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>
     450<p>Anything else is considered false.</p></dd></div></div>
    447451<div class="section">
    448452<h3>Version</h3>
    449453<ul>
     454<li>2.0.5 Added some &lt;boolean&gt; support. Change for NULL (&lt;void&gt;) handling. [Kon Lovett]</li>
    450455<li>2.0.4 Added <code>sqlite3:fold-row</code> &amp; <code>sqlite3:bind-parameters!</code>. Fix for introduced bug in <code>sqlite3:changes</code>. [Kon Lovett]</li>
    451456<li>2.0.3 Added <code>sqlite3:null-value</code>, <code>sqlite3:null-value?</code>, and <code>sqlite3:null</code>. [Kon Lovett]</li>
     
    492497  written permission.
    493498
    494 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS
    495 IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     499THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \&quot;AS
     500IS\&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    496501THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    497502PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
  • release/3/sqlite3/tags/2.0.5/sqlite3.scm

    r8020 r8688  
    4949    sqlite3:complete?
    5050    sqlite3:library-version
    51     ;; null type
    52     sqlite3:null
    53     sqlite3:null-value?
    54     sqlite3:null-value) )
     51    sqlite3:boolean-value ) )
    5552
    5653(declare
     
    6158  (disable-warning redef)
    6259  (unused
    63     ; global variable '...' is never used
     60    ; Stop annoying messages
    6461    chicken_sqlite3_function_stub
    6562    chicken_sqlite3_collation_stub
     
    6966    ##sys#expand-home-path
    7067    #;##sys#pathname-resolution
     68    abort-sqlite3-null-error
    7169    sqlite3:errmsg ) )
    7270
    7371#>#include <sqlite3.h><#
    7472
    75 (use srfi-1 srfi-12 srfi-13 srfi-18 srfi-26 extras lolevel)
     73#;(use srfi-1 srfi-12 srfi-13 srfi-18 srfi-26 srfi-69 extras lolevel)
     74(use (srfi 1 12 13 18 26 69) extras lolevel)
    7675(use tinyclos synch miscmacros)
    7776
     
    132131(define-foreign-type sqlite3:value (c-pointer "sqlite3_value"))
    133132
    134 (define sqlite3:null void)
    135 
    136 (define sqlite3:null-value (sqlite3:null))
    137 
    138 (define (sqlite3:null-value? obj)
    139   (eq? sqlite3:null-value obj) )
    140 
    141133;;; Classes for databases and statements
    142134
     
    146138  (lambda (db)
    147139    (unless (slot-ref db 'this)
    148       (signal-sqlite3-null-error 'sqlite3:database->c-pointer db))
     140      (abort-sqlite3-null-error 'sqlite3:database->c-pointer db))
    149141    db))
    150142
     
    154146  (lambda (stmt)
    155147    (unless (slot-ref stmt 'this)
    156       (signal-sqlite3-null-error 'sqlite3:statement->c-pointer stmt))
     148      (abort-sqlite3-null-error 'sqlite3:statement->c-pointer stmt))
    157149    stmt))
    158150
     
    167159  ##sys#expand-home-path
    168160  #; ;not needed, yet
    169   (cut ##sys#pathname-resolution <> identity) )
     161  (cute ##sys#pathname-resolution <> identity) )
    170162
    171163;; Conditions
     
    190182;; Errors
    191183
    192 (define ((signal-sqlite3-error loc db . args) sta)
    193   (signal
     184(define ((abort-sqlite3-error loc db . args) sta)
     185  (abort
    194186   (apply make-sqlite3-error-condition loc
    195187                                       (if db (sqlite3:errmsg db) (symbol->string sta))
     
    209201      (make-sqlite3-condition 'error)))) )
    210202
    211 (define (signal-sqlite3-null-error loc obj)
    212   (signal
     203(define (abort-sqlite3-null-error loc obj)
     204  (abort
    213205   (make-sqlite3-error-condition loc
    214206                                 (string-append
     
    228220  (if (null? (cdr keys))
    229221      (hash-table-set! ht-tree (car keys) value)
    230       (hash-table-update!
    231        ht-tree
    232        (car keys)
    233        (cut hash-table-tree-set! <> (cdr keys) value)
    234        (thunker make-hash-table)) )
     222      (hash-table-update! ht-tree
     223                          (car keys)
     224                          (cute hash-table-tree-set! <> (cdr keys) value)
     225                          (thunker make-hash-table)) )
    235226  ht-tree )
    236227
     
    238229  (if (null? (cdr keys))
    239230      (hash-table-delete! ht-tree (car keys))
    240       (hash-table-update!
    241        ht-tree
    242        (car keys)
    243        (cut hash-table-tree-delete! <> (cdr keys))
    244        (thunker make-hash-table)) )
     231      (hash-table-update! ht-tree
     232                          (car keys)
     233                          (cute hash-table-tree-delete! <> (cdr keys))
     234                          (thunker make-hash-table)) )
    245235  ht-tree )
    246236
     
    248238         ht-tree keys
    249239         #!optional
    250          (thunk (thunker signal
     240         (thunk (thunker abort
    251241                         (make-composite-condition
    252                           (make-exn-condition
    253                            'hash-table-tree-ref
    254                            "hash-table-tree does not contain path"
    255                            ht-tree keys)
     242                          (make-exn-condition 'hash-table-tree-ref
     243                                              "hash-table-tree does not contain path"
     244                                              ht-tree keys)
    256245                          (make-property-condition 'access)))))
    257246  (let/cc return
    258     (let loop ((ht ht-tree)
    259                (keys keys))
     247    (let loop ([ht ht-tree]
     248               [keys keys] )
    260249      (if (null? keys)
    261250          ht
     
    267256
    268257(define (hash-table-tree-clear! htt id elt-clear)
    269   (cond ((hash-table-ref/default htt id #f)
    270          => (cut hash-table-walk <> elt-clear)))
     258  (cond [(hash-table-ref/default htt id #f)
     259         => (cute hash-table-walk <> elt-clear) ] )
    271260  (hash-table-delete! htt id) )
    272261
     
    280269                 int
    281270  (let/cc return
    282     (let ((r #f))
     271    (let ([r #f])
    283272      (dynamic-wind
    284         noop
    285         (lambda ()
    286           (handle-exceptions exn
    287                              (print-error "in collation function" exn)
    288             (let ((a (make-string la)) (b (make-string lb)))
    289               (move-memory! da a la)
    290               (move-memory! db b lb)
    291               (set! r
    292                     ((vector-ref (call-with/synch *sqlite3:collations*
    293                                    (cut hash-table-tree-ref <> qn))
    294                                  1)
    295                      a b)))))
    296         (lambda ()
    297           (if (and (integer? r) (exact? r))
    298               (return r)
    299               (begin
    300                 (print-error "in collation function: invalid return value" (->string r))
    301                 (return 0))))) ) ) )
     273          noop
     274          (lambda ()
     275            (handle-exceptions exn
     276                               (print-error "in collation function" exn)
     277              (let ([a (make-string la)]
     278                    [b (make-string lb)] )
     279                (move-memory! da a la)
     280                (move-memory! db b lb)
     281                (set! r
     282                      ((vector-ref (call-with/synch *sqlite3:collations*
     283                                     (cute hash-table-tree-ref <> qn))
     284                                   1)
     285                       a b)))))
     286          (lambda ()
     287            (if (and (integer? r) (exact? r))
     288                (return r)
     289                (begin
     290                  (print-error "in collation function: invalid return value" (->string r))
     291                  (return 0))))) ) ) )
    302292
    303293(define sqlite3_create_collation
    304294  (foreign-lambda* sqlite3:status
    305295                  ((sqlite3:database db) (c-string name) (scheme-object qn))
    306 #<<END
     296#<<EOS
    307297  if (qn == C_SCHEME_FALSE)
    308298    return(sqlite3_create_collation(db, name, SQLITE_UTF8, NULL, NULL));
     
    314304                                               int, const void *))
    315305                                        &chicken_sqlite3_collation_stub));
    316 END
     306EOS
    317307  ))
    318308
     
    320310(define-method (sqlite3:define-collation (db <sqlite3:database>)
    321311                                         (name <string>))
    322   (cond
    323    ((sqlite3_create_collation db name #f)
    324     => (signal-sqlite3-error 'sqlite3:define-collation db name))
    325    (else
    326     (let ((qn (list (pointer->address (slot-ref db 'this)) name)))
    327       (call-with/synch *sqlite3:collations*
    328         (lambda (col)
    329           (cond
    330            ((hash-table-tree-ref/default col qn #f)
    331             => (lambda (info)
    332                  (hash-table-tree-delete! col qn)
    333                  (object-release (vector-ref info 0))))))) ) ) ) )
     312  (cond [(sqlite3_create_collation db name #f)
     313         => (abort-sqlite3-error 'sqlite3:define-collation db name) ]
     314        [else
     315         (let ([qn (list (pointer->address (slot-ref db 'this)) name)])
     316           (call-with/synch *sqlite3:collations*
     317             (lambda (col)
     318               (cond [(hash-table-tree-ref/default col qn #f)
     319                      => (lambda (info)
     320                           (hash-table-tree-delete! col qn)
     321                           (object-release (vector-ref info 0))) ] ) ) ) ) ] ) )
    334322
    335323(define-method (sqlite3:define-collation (db <sqlite3:database>)
    336324                                          (name <string>)
    337325                                          (proc <procedure-class>))
    338   (let ((qn (object-evict (list (pointer->address (slot-ref db 'this)) name))))
    339     (cond
    340      ((sqlite3_create_collation db name qn)
    341       => (lambda (s)
    342            (object-release qn)
    343            ((signal-sqlite3-error 'sqlite3:define-collation db name proc) s)))
    344      (else
    345       (call-with/synch *sqlite3:collations*
    346         (cut hash-table-tree-set! <> qn (vector qn proc))) ) ) ) )
     326  (let ([qn (object-evict (list (pointer->address (slot-ref db 'this)) name))])
     327    (cond [(sqlite3_create_collation db name qn)
     328           => (lambda (s)
     329                (object-release qn)
     330                ((abort-sqlite3-error 'sqlite3:define-collation db name proc) s)) ]
     331          [else
     332           (call-with/synch *sqlite3:collations*
     333        (cute hash-table-tree-set! <> qn (vector qn proc))) ] ) ) )
    347334
    348335;;; SQL function interface
     
    353340
    354341(define (sqlite3:parameter-data n args)
    355   (let loop ((i 0))
    356     (if (< i n)
    357         (cons
    358          (case ((foreign-lambda* sqlite3:type
    359                                  (((c-pointer sqlite3:value) args) (int i))
    360                  "return(sqlite3_value_type(args[i]));")
    361                 args i)
    362            ((integer)
    363             ((foreign-lambda* integer
    364                               (((c-pointer sqlite3:value) args) (int i))
    365               "return(sqlite3_value_double(args[i]));")
    366              args i))
    367            ((float)
    368             ((foreign-lambda* double
    369                               (((c-pointer sqlite3:value) args) (int i))
    370               "return(sqlite3_value_double(args[i]));")
    371              args i))
    372            ((text)
    373             ((foreign-primitive scheme-object
    374                                 (((c-pointer sqlite3:value) args) (int i))
    375               "int n = sqlite3_value_bytes(args[i]);"
    376               "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    377               "return(C_string(&s, n, (char *)sqlite3_value_text(args[i])));")
    378              args i))
    379            ((blob)
    380             ((foreign-primitive scheme-object
    381                                 (((c-pointer sqlite3:value) args) (int i))
    382               "int n = sqlite3_value_bytes(args[i]);"
    383               "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    384               "return(C_bytevector(&s, n, (char *)sqlite3_value_blob(args[i])));")
    385              args i))
    386            (else
    387             sqlite3:null-value))
    388          (loop (add1 i)))
    389         '() ) ) )
     342  (let loop ([i 0])
     343    (if (<= n i)
     344        '()
     345        (cons (case ((foreign-lambda* sqlite3:type
     346                                      (((c-pointer sqlite3:value) args) (int i))
     347                      "return(sqlite3_value_type(args[i]));")
     348                     args i)
     349                [(integer)
     350                 ((foreign-lambda* integer
     351                                   (((c-pointer sqlite3:value) args) (int i))
     352                   "return(sqlite3_value_double(args[i]));")
     353                  args i) ]
     354                [(float)
     355                 ((foreign-lambda* double
     356                                   (((c-pointer sqlite3:value) args) (int i))
     357                   "return(sqlite3_value_double(args[i]));")
     358                  args i) ]
     359                [(text)
     360                 ((foreign-primitive scheme-object
     361                                     (((c-pointer sqlite3:value) args) (int i))
     362                   "int n = sqlite3_value_bytes(args[i]);"
     363                   "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
     364                   "return(C_string(&s, n, (char *)sqlite3_value_text(args[i])));")
     365                  args i) ]
     366                [(blob)
     367                 ((foreign-primitive scheme-object
     368                                     (((c-pointer sqlite3:value) args) (int i))
     369                   "int n = sqlite3_value_bytes(args[i]);"
     370                   "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
     371                   "return(C_bytevector(&s, n, (char *)sqlite3_value_blob(args[i])));")
     372                  args i) ]
     373                [else
     374                 <void> ] )
     375              (loop (add1 i)) ) ) ) )
    390376
    391377(define-generic sqlite3:set-result!)
     
    432418  (let/cc return
    433419    (dynamic-wind
    434       noop
    435       (lambda ()
    436         (handle-exceptions exn
    437                            (print-error "in SQL function" exn)
    438           (sqlite3:set-result!
    439            ctx
    440            (apply
    441             (vector-ref
    442              (call-with/synch *sqlite3:functions*
    443               (cut hash-table-tree-ref <> (sqlite3_user_data ctx)))
    444              1)
    445             (sqlite3:parameter-data n args)))))
    446      (lambda ()
    447        (return (void)))) ) )
     420        noop
     421        (lambda ()
     422          (handle-exceptions exn
     423                             (print-error "in SQL function" exn)
     424            (sqlite3:set-result!
     425             ctx
     426             (apply (vector-ref
     427                     (call-with/synch *sqlite3:functions*
     428                      (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))
     429                     1)
     430                    (sqlite3:parameter-data n args) ) ) ) )
     431       (lambda ()
     432         (return (void)) ) ) ) )
    448433
    449434(define sqlite3_aggregate_context
     
    455440  (let/cc return
    456441    (dynamic-wind
    457       noop
    458       (lambda ()
    459         (handle-exceptions exn
    460                            (print-error "in step of SQL function" exn)
    461           (let ((info (call-with/synch *sqlite3:functions*
    462                        (cut hash-table-tree-ref <> (sqlite3_user_data ctx)))))
    463             (call-with/synch *sqlite3:seeds*
    464              (cut hash-table-update!/default
    465                   <>
    466                   (sqlite3_aggregate_context ctx)
    467                   (lambda (seed)
    468                     (apply (vector-ref info 1) seed (sqlite3:parameter-data n args)))
    469                   (vector-ref info 2))))))
    470          (lambda ()
    471            (return (void)))) ) )
     442        noop
     443        (lambda ()
     444          (handle-exceptions exn
     445                             (print-error "in step of SQL function" exn)
     446            (let ([info (call-with/synch *sqlite3:functions*
     447                          (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))])
     448              (call-with/synch *sqlite3:seeds*
     449               (cute hash-table-update!/default
     450                     <>
     451                     (sqlite3_aggregate_context ctx)
     452                     (lambda (seed)
     453                       (apply (vector-ref info 1) seed (sqlite3:parameter-data n args)))
     454                     (vector-ref info 2)) ) ) ) )
     455           (lambda ()
     456             (return (void)) ) ) ) )
    472457
    473458(define-external (chicken_sqlite3_final_stub (c-pointer ctx))
    474459                 void
    475460  (let/cc return
    476     (let ((agc (sqlite3_aggregate_context ctx)))
     461    (let ([agc (sqlite3_aggregate_context ctx)])
    477462      (dynamic-wind
    478         noop
    479         (lambda ()
    480           (handle-exceptions exn
    481                              (print-error "in final of SQL function" exn)
    482             (let ((info (call-with/synch *sqlite3:functions*
    483                          (cut hash-table-tree-ref <> (sqlite3_user_data ctx)))))
    484               (cond
    485                 (((vector-ref info 3)
    486                   (call-with/synch *sqlite3:seeds*
    487                    (cut hash-table-ref/default <> agc (vector-ref info 2))))
    488                  => (cut sqlite3:set-result! ctx <>))
    489                 (else
    490                   (sqlite3:set-result! ctx))))))
    491         (lambda ()
    492           (call-with/synch *sqlite3:seeds*
    493            (cut hash-table-delete! <> agc))
    494           (return (void)))) ) ) )
     463          noop
     464          (lambda ()
     465            (handle-exceptions exn
     466                               (print-error "in final of SQL function" exn)
     467              (let ([info (call-with/synch *sqlite3:functions*
     468                           (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))])
     469                (cond [((vector-ref info 3)
     470                 (call-with/synch *sqlite3:seeds*
     471                   (cute hash-table-ref/default <> agc (vector-ref info 2))))
     472                 => (cute sqlite3:set-result! ctx <>) ]
     473                [else
     474                 (sqlite3:set-result! ctx) ] ) ) ) )
     475          (lambda ()
     476            (call-with/synch *sqlite3:seeds*
     477             (cute hash-table-delete! <> agc))
     478            (return (void)) ) ) ) ) )
    495479
    496480(define-generic sqlite3:define-function)
     
    499483                                         (n <exact>)
    500484                                         (proc <procedure-class>))
    501   (let ((qn (object-evict (list (pointer->address (slot-ref db 'this)) name))))
    502     (cond
    503      (((foreign-lambda* sqlite3:status
    504                         ((sqlite3:database db) (c-string name) (int n) (scheme-object qn))
    505 #<<END
     485  (let ([qn (object-evict (list (pointer->address (slot-ref db 'this)) name))])
     486    (cond [((foreign-lambda* sqlite3:status
     487                             ((sqlite3:database db)
     488                              (c-string name) (int n) (scheme-object qn))
     489#<<EOS
    506490        return(sqlite3_create_function(db, name, n, SQLITE_UTF8,
    507491                                       (void *)qn,
     
    511495                                       NULL,
    512496                                       NULL));
    513 END
    514        )
    515        db name n qn)
    516       => (lambda (s)
    517            (object-release qn)
    518            ((signal-sqlite3-error 'sqlite3:define-function db name n proc) s)))
    519      (else
    520       (call-with/synch *sqlite3:functions*
    521         (cut hash-table-tree-set! <> qn (vector qn proc))) ) ) ) )
     497EOS
     498            )
     499            db name n qn)
     500           => (lambda (s)
     501                (object-release qn)
     502                ((abort-sqlite3-error 'sqlite3:define-function db name n proc) s)) ]
     503          [else
     504           (call-with/synch *sqlite3:functions*
     505        (cute hash-table-tree-set! <> qn (vector qn proc))) ] ) ) )
    522506
    523507(define-method (sqlite3:define-function (db <sqlite3:database>)
     
    528512                                         #!optional (final-proc identity))
    529513  (check-sqlite3-type 'sqlite3:define-function final-proc <procedure-class>)
    530   (let ((qn (object-evict (list (pointer->address (slot-ref db 'this)) name))))
    531     (cond
    532      (((foreign-lambda* sqlite3:status
    533                         ((sqlite3:database db) (c-string name) (int n) (scheme-object qn))
    534 #<<END
     514  (let ([qn (object-evict (list (pointer->address (slot-ref db 'this)) name))])
     515    (cond [((foreign-lambda* sqlite3:status
     516                             ((sqlite3:database db)
     517                              (c-string name) (int n) (scheme-object qn))
     518#<<EOS
    535519        return(sqlite3_create_function(db, name, n, SQLITE_UTF8,
    536520                                       (void *)qn,
     
    541525                                       ((void (*)(sqlite3_context *))
    542526                                         &chicken_sqlite3_final_stub)));
    543 END
    544        )
    545        db name n qn)
    546       => (lambda (s)
    547            (object-release qn)
    548            ((signal-sqlite3-error
    549               'sqlite3:define-function db name n step-proc seed final-proc)
    550             s)))
    551      (else
    552       (call-with/synch *sqlite3:functions*
    553         (cut hash-table-tree-set! <> qn (vector qn step-proc seed final-proc))) ) ) ) )
     527EOS
     528            )
     529            db name n qn)
     530           => (lambda (s)
     531                (object-release qn)
     532                ((abort-sqlite3-error
     533                   'sqlite3:define-function db name n step-proc seed final-proc) s)) ]
     534          [else
     535           (call-with/synch *sqlite3:functions*
     536        (cute hash-table-tree-set! <> qn (vector qn step-proc seed final-proc))) ] ) ) )
    554537
    555538;;; Database interface
     
    562545(define (sqlite3:open path)
    563546  (check-sqlite3-type 'sqlite3:open path <string>)
    564   (let-location ((db c-pointer))
    565     (cond
    566      (((foreign-lambda sqlite3:status "sqlite3_open"
    567                                       nonnull-c-string (c-pointer sqlite3:database))
    568        (sqlite3:resolve-pathname path) (location db))
    569       => (signal-sqlite3-error 'sqlite3:open #f path))
    570      (else
    571       (make <sqlite3:database> 'this db) ) ) ) )
     547  (let-location ([db c-pointer])
     548    (cond [((foreign-lambda sqlite3:status "sqlite3_open"
     549                                           nonnull-c-string (c-pointer sqlite3:database))
     550            (sqlite3:resolve-pathname path) #$db)
     551           => (abort-sqlite3-error 'sqlite3:open #f path) ]
     552          [else
     553           (make <sqlite3:database> 'this db) ] ) ) )
    572554
    573555;; Set a timeout until a busy error is thrown
    574556(define (sqlite3:set-busy-timeout! db #!optional (ms 0))
    575557  (check-sqlite3-type 'sqlite3:set-busy-timeout! db <sqlite3:database>)
    576   (cond
    577    (((foreign-lambda sqlite3:status "sqlite3_busy_timeout" sqlite3:database int) db ms)
    578     => (signal-sqlite3-error 'sqlite3:set-busy-timeout! db db ms))) )
     558  (cond [((foreign-lambda sqlite3:status "sqlite3_busy_timeout" sqlite3:database int) db ms)
     559         => (abort-sqlite3-error 'sqlite3:set-busy-timeout! db db ms) ] ) )
    579560
    580561;; Cancel any running database operation as soon as possible
     
    603584(define-generic sqlite3:finalize!)
    604585(define-method (sqlite3:finalize! (db <sqlite3:database>))
    605   (cond
    606    ((not (slot-ref db 'this))
    607     (void))
    608    (((foreign-lambda sqlite3:status "sqlite3_close" sqlite3:database) db)
    609     => (signal-sqlite3-error 'sqlite3:finalize! db db))
    610    (else
    611     (let ((id (pointer->address (slot-ref db 'this)))
    612           (release-qns (lambda (_ info) (object-release (vector-ref info 0)))))
    613       (call-with/synch *sqlite3:collations*
    614         (cut hash-table-tree-clear! <> id release-qns))
    615       (call-with/synch *sqlite3:functions*
    616         (cut hash-table-tree-clear! <> id release-qns)) )
    617     (slot-set! db 'this #f) ) ) )
     586  (cond [(not (slot-ref db 'this))
     587         (void) ]
     588        [((foreign-lambda sqlite3:status "sqlite3_close" sqlite3:database) db)
     589         => (abort-sqlite3-error 'sqlite3:finalize! db db) ]
     590        [else
     591         (let ([id (pointer->address (slot-ref db 'this))]
     592               [release-qns (lambda (_ info) (object-release (vector-ref info 0)))] )
     593           (call-with/synch *sqlite3:collations*
     594             (cute hash-table-tree-clear! <> id release-qns))
     595           (call-with/synch *sqlite3:functions*
     596             (cute hash-table-tree-clear! <> id release-qns)) )
     597           (slot-set! db 'this #f) ] ) )
    618598
    619599;;; Statement interface
     
    623603  (check-sqlite3-type 'sqlite3:prepare db <sqlite3:database>)
    624604  (check-sqlite3-type 'sqlite3:prepare sql <string>)
    625   (let-location ((stmt c-pointer) (tail c-string))
    626     (cond
    627      (((foreign-lambda sqlite3:status "sqlite3_prepare"
    628                                       sqlite3:database scheme-pointer int
    629                                       (c-pointer sqlite3:statement)
    630                                       (c-pointer (const c-string)))
    631        db sql (string-length sql) (location stmt) (location tail))
    632       => (signal-sqlite3-error 'sqlite3:prepare db db sql))
    633      (else
    634       (values
    635        (make <sqlite3:statement> 'this stmt 'database db 'sql sql)
    636        tail) ) ) ) )
     605  (let-location ([stmt c-pointer] [tail c-string])
     606    (cond [((foreign-lambda sqlite3:status "sqlite3_prepare"
     607                                            sqlite3:database scheme-pointer int
     608                                            (c-pointer sqlite3:statement)
     609                                            (c-pointer (const c-string)))
     610            db sql (string-length sql) #$stmt #$tail)
     611           => (abort-sqlite3-error 'sqlite3:prepare db db sql) ]
     612          [else
     613           (values
     614            (make <sqlite3:statement> 'this stmt 'database db 'sql sql)
     615            tail) ] ) ) )
    637616
    638617;; Recompile an existing statement and transfer all bindings
    639618(define (sqlite3:repair! stmt)
    640619  (check-sqlite3-type 'sqlite3:repair! stmt <sqlite3:statement>)
    641   (let ((fresh (sqlite3:prepare
    642                 (slot-ref stmt 'database) (slot-ref stmt 'sql))))
     620  (let ([fresh (sqlite3:prepare
     621                (slot-ref stmt 'database) (slot-ref stmt 'sql))])
    643622    (dynamic-wind
    644623        noop
    645624        (lambda ()
    646           (let ((old (slot-ref stmt 'this))
    647                 (new (slot-ref fresh 'this)))
    648             (cond
    649              (((foreign-lambda sqlite3:status "sqlite3_transfer_bindings"
    650                                               c-pointer c-pointer)
    651                old new)
    652               => (signal-sqlite3-error 'sqlite3:repair! (slot-ref stmt 'database) stmt))
    653              (else
    654               (slot-set! stmt 'this new)
    655               (slot-set! fresh 'this old)))))
     625          (let ([old (slot-ref stmt 'this)]
     626                [new (slot-ref fresh 'this)] )
     627            (cond [((foreign-lambda sqlite3:status "sqlite3_transfer_bindings"
     628                                             c-pointer c-pointer)
     629              old new)
     630             => (abort-sqlite3-error 'sqlite3:repair! (slot-ref stmt 'database) stmt) ]
     631            [else
     632             (slot-set! stmt 'this new)
     633             (slot-set! fresh 'this old) ] ) ) )
    656634        (lambda ()
    657635          (sqlite3:finalize! fresh))) ) )
     
    660638;; (define-generic sqlite3:finalize!)
    661639(define-method (sqlite3:finalize! (stmt <sqlite3:statement>))
    662   (cond
    663    ((not (slot-ref stmt 'this))
    664     (void))
    665    (((foreign-lambda sqlite3:status "sqlite3_finalize" sqlite3:statement) stmt)
    666     => (signal-sqlite3-error 'sqlite3:finalize! (slot-ref stmt 'database) stmt))
    667    (else
    668     (slot-set! stmt 'this #f) ) ) )
     640  (cond [(not (slot-ref stmt 'this))
     641         (void) ]
     642        [((foreign-lambda sqlite3:status "sqlite3_finalize" sqlite3:statement) stmt)
     643         => (abort-sqlite3-error 'sqlite3:finalize! (slot-ref stmt 'database) stmt) ]
     644        [else
     645         (slot-set! stmt 'this #f) ] ) )
    669646
    670647;; Reset an existing statement to process it again
     
    674651(define (sqlite3:reset! stmt)
    675652  (check-sqlite3-type 'sqlite3:reset! stmt <sqlite3:statement>)
    676   (cond
    677    ((sqlite3_reset stmt)
    678     => (signal-sqlite3-error 'sqlite3:reset! (slot-ref stmt 'database) stmt))) )
     653  (cond [(sqlite3_reset stmt)
     654         => (abort-sqlite3-error 'sqlite3:reset! (slot-ref stmt 'database) stmt) ] ) )
    679655
    680656;; Get number of bindable parameters
     
    687663(define (sqlite3:bind-parameter-index stmt name)
    688664  (check-sqlite3-type 'sqlite3:bind-parameter-index stmt <sqlite3:statement>)
    689   (let ((i ((foreign-lambda int "sqlite3_bind_parameter_index"
     665  (let ([i ((foreign-lambda int "sqlite3_bind_parameter_index"
    690666                                sqlite3:statement nonnull-c-string)
    691             stmt name)))
     667            stmt name)])
    692668    (if (zero? i)
    693669        #f
     
    697673(define (sqlite3:bind-parameter-name stmt i)
    698674  (check-sqlite3-type 'sqlite3:bind-parameter-name stmt <sqlite3:statement>)
    699   ((foreign-lambda c-string "sqlite3_bind_parameter_name" sqlite3:statement int) stmt (add1 i)) )
     675  ((foreign-lambda c-string "sqlite3_bind_parameter_name" sqlite3:statement int)
     676   stmt (add1 i)) )
    700677
    701678;; Bind data as parameters to an existing statement
     
    704681(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    705682                              (v <blob>))
    706   (cond
    707    (((foreign-lambda* sqlite3:status
    708                       ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
    709       "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
    710      stmt (add1 i) v (blob-size v))
    711     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))) )
     683  (cond [((foreign-lambda* sqlite3:status
     684                           ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
     685           "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
     686          stmt (add1 i) v (blob-size v))
     687         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    712688
    713689; Deprecated
    714690(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    715691                              (v <byte-vector>))
    716   (cond
    717    (((foreign-lambda* sqlite3:status
    718                       ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
    719       "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
    720      stmt (add1 i) v (byte-vector-length v))
    721     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))) )
     692  (cond [((foreign-lambda* sqlite3:status
     693                           ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
     694           "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
     695          stmt (add1 i) v (byte-vector-length v))
     696         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
     697
     698(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
     699                              (v <boolean>))
     700  (cond [((foreign-lambda sqlite3:status "sqlite3_bind_int"
     701                                         sqlite3:statement int int)
     702          stmt (add1 i) (or (and v 1) 0))
     703         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    722704
    723705(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    724706                              (v <exact>))
    725   (cond
    726    (((foreign-lambda sqlite3:status "sqlite3_bind_int"
    727                                     sqlite3:statement int int)
    728      stmt (add1 i) v)
    729     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))))
     707  (cond [((foreign-lambda sqlite3:status "sqlite3_bind_int"
     708                                         sqlite3:statement int int)
     709          stmt (add1 i) v)
     710         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    730711
    731712(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    732713                              (v <number>))
    733   (cond
    734    (((foreign-lambda sqlite3:status "sqlite3_bind_double"
    735                                     sqlite3:statement int double)
    736      stmt (add1 i) v)
    737     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))) )
     714  (cond [((foreign-lambda sqlite3:status "sqlite3_bind_double"
     715                                          sqlite3:statement int double)
     716          stmt (add1 i) v)
     717         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    738718
    739719(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    740720                              (v <string>))
    741   (cond
    742    (((foreign-lambda* sqlite3:status
    743                       ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
    744       "return(sqlite3_bind_text(stmt, i, v, n, SQLITE_TRANSIENT));")
    745      stmt (add1 i) v (string-length v))
    746     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))))
    747 
    748 (define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    749                               (v <void>))
    750   (cond
    751    (((foreign-lambda sqlite3:status "sqlite3_bind_null" sqlite3:statement int) stmt (add1 i))
    752     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i))) )
     721  (cond [((foreign-lambda* sqlite3:status
     722                           ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
     723           "return(sqlite3_bind_text(stmt, i, v, n, SQLITE_TRANSIENT));")
     724          stmt (add1 i) v (string-length v))
     725         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    753726
    754727(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>))
    755   (cond
    756    (((foreign-lambda sqlite3:status "sqlite3_bind_null" sqlite3:statement int) stmt (add1 i))
    757     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i))) )
     728  (cond [((foreign-lambda sqlite3:status "sqlite3_bind_null" sqlite3:statement int)
     729         stmt (add1 i))
     730         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i) ] ) )
    758731
    759732; Helper
     733
    760734(define (bind-parameters! loc stmt params)
    761735  (sqlite3:reset! stmt)
    762   (let ((cnt (sqlite3:bind-parameter-count stmt)))
    763     (unless (= cnt (length params))
    764       (abort
    765        (make-composite-condition
    766         (make-exn-condition loc "too few parameters" cnt params)
    767         (make-property-condition 'arity)
    768         (make-sqlite3-condition 'error))) )
    769     (for-each (cut sqlite3:bind! stmt <> <>) (iota cnt) params) ) )
     736  (let ([cnt (sqlite3:bind-parameter-count stmt)])
     737    (if (= cnt (length params))
     738        (unless (zero? cnt)
     739          (for-each
     740           (lambda (i v)
     741             (if (eq? <void> v)
     742                 (sqlite3:bind! stmt i)
     743                 (sqlite3:bind! stmt i v) ) )
     744           (iota cnt) params) )
     745        (abort
     746         (make-composite-condition
     747          (make-exn-condition
     748           loc
     749           (conc "bad parameter count - received " (length params) " but expected " cnt))
     750          (make-property-condition 'arity)
     751          (make-sqlite3-condition 'error))) ) ) )
    770752
    771753(define (sqlite3:bind-parameters! stmt . params)
     
    777759  (check-sqlite3-type 'sqlite3:step! stmt <sqlite3:statement>)
    778760  (let retry ()
    779     (let ((s ((foreign-safe-lambda
     761    (let ([s ((foreign-safe-lambda
    780762               sqlite3:status "sqlite3_step" sqlite3:statement)
    781               stmt)))
     763              stmt)])
    782764      (case s
    783         ((row) #t)
    784         ((done) #f)
    785         ((error)
    786          (let ((s (sqlite3_reset stmt)))
     765        [(row)
     766         #t ]
     767        [(done)
     768         #f ]
     769        [(error)
     770         (let ([s (sqlite3_reset stmt)])
    787771           (case s
    788              ((schema)
     772             [(schema)
    789773              (sqlite3:repair! stmt)
    790               (retry))
    791              (else
    792               ((signal-sqlite3-error
    793                 'sqlite3:step! (slot-ref stmt 'database) stmt) s)))))
    794         (else
    795          ((signal-sqlite3-error 'sqlite3:step! (slot-ref stmt 'database) stmt) s) ) ) ) ) )
     774              (retry) ]
     775             [else
     776              ((abort-sqlite3-error 'sqlite3:step! (slot-ref stmt 'database) stmt) s) ] ) ) ]
     777        [else
     778         ((abort-sqlite3-error 'sqlite3:step! (slot-ref stmt 'database) stmt) s) ] ) ) ) )
    796779
    797780;; Retrieve information from a prepared/stepped statement
     
    815798(define (sqlite3:column-data stmt i)
    816799  (case (sqlite3:column-type stmt i)
    817     ((integer)
    818      ((foreign-lambda integer "sqlite3_column_double" sqlite3:statement int) stmt i))
    819     ((float)
    820      ((foreign-lambda double "sqlite3_column_double" sqlite3:statement int) stmt i))
    821     ((text)
     800    [(integer)
     801     ((foreign-lambda integer "sqlite3_column_double" sqlite3:statement int) stmt i) ]
     802    [(float)
     803     ((foreign-lambda double "sqlite3_column_double" sqlite3:statement int) stmt i) ]
     804    [(text)
    822805     ((foreign-primitive scheme-object ((sqlite3:statement stmt) (int i))
    823806       "int n = sqlite3_column_bytes(stmt, i);"
    824807       "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    825808       "return(C_string(&s, n, (char *)sqlite3_column_text(stmt, i)));")
    826       stmt i))
    827     ((blob)
     809      stmt i) ]
     810    [(blob)
    828811     ((foreign-primitive scheme-object ((sqlite3:statement stmt) (int i))
    829812       "int n = sqlite3_column_bytes(stmt, i);"
    830813       "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    831814       "return(C_bytevector(&s, n, (char *)sqlite3_column_blob(stmt, i)));")
    832       stmt i))
    833     (else
    834      sqlite3:null-value ) ) )
     815      stmt i) ]
     816    [else
     817     <void> ] ) )
    835818
    836819;;; Easy statement interface
     
    840823(define (sqlite3:call-with-temporary-statements proc db . sqls)
    841824  (check-sqlite3-type 'sqlite3:call-with-temporary-statements db <sqlite3:database>)
    842   (let ((stmts #f))
     825  (let ([stmts #f])
    843826    (dynamic-wind
    844827        (lambda ()
    845828          (unless stmts
    846             (set! stmts (map (cut sqlite3:prepare db <>) sqls))))
     829            (set! stmts (map (cute sqlite3:prepare db <>) sqls))))
    847830        (lambda ()
    848831          (apply proc stmts))
     
    857840  (bind-parameters! 'sqlite3:exec stmt params)
    858841  (while (sqlite3:step! stmt))
    859   sqlite3:null-value )
     842  (void) )
    860843
    861844(define-method (sqlite3:exec (db <sqlite3:database>) (sql <string>) . params)
    862845  (sqlite3:call-with-temporary-statements
    863    (cut apply sqlite3:exec <> params)
     846   (cute apply sqlite3:exec <> params)
    864847   db sql) )
    865848
     
    883866  (bind-parameters! 'sqlite3:first-result stmt params)
    884867  (if (sqlite3:step! stmt)
    885       (let ((r (sqlite3:column-data stmt 0)))
     868      (let ([r (sqlite3:column-data stmt 0)])
    886869        (sqlite3:reset! stmt)
    887870        r )
    888       (signal (make-no-data-condition 'sqlite3:first-result stmt params)) ) )
     871      (abort (make-no-data-condition 'sqlite3:first-result stmt params)) ) )
    889872
    890873(define-method (sqlite3:first-result
    891874                (db <sqlite3:database>) (sql <string>) . params)
    892875  (sqlite3:call-with-temporary-statements
    893    (cut apply sqlite3:first-result <> params)
     876   (cute apply sqlite3:first-result <> params)
    894877   db sql) )
    895878
     
    900883  (bind-parameters! 'sqlite3:first-row stmt params)
    901884  (if (sqlite3:step! stmt)
    902       (map (cut sqlite3:column-data stmt <>)
     885      (map (cute sqlite3:column-data stmt <>)
    903886           (iota (sqlite3:column-count stmt)))
    904       (signal (make-no-data-condition 'sqlite3:first-row stmt params)) ) )
     887      (abort (make-no-data-condition 'sqlite3:first-row stmt params)) ) )
    905888
    906889(define-method (sqlite3:first-row
    907890                (db <sqlite3:database>) (sql <string>) . params)
    908891  (sqlite3:call-with-temporary-statements
    909    (cut apply sqlite3:first-row <> params)
     892   (cute apply sqlite3:first-row <> params)
    910893   db sql))
    911894
     
    915898(define (%fold-row loc proc stmt init params)
    916899  (bind-parameters! loc stmt params)
    917   (let ((cl (iota (sqlite3:column-count stmt))))
    918     (let loop ((acc init))
     900  (let ([cl (iota (sqlite3:column-count stmt))])
     901    (let loop ([acc init])
    919902      (if (sqlite3:step! stmt)
    920           (loop (apply proc acc (map (cut sqlite3:column-data stmt <>) cl)))
     903          (loop (apply proc acc (map (cute sqlite3:column-data stmt <>) cl)))
    921904          acc ) ) ) )
    922905
     
    932915                                 (init <object>) . params)
    933916  (sqlite3:call-with-temporary-statements
    934    (cut apply sqlite3:fold-row proc <> init params)
     917   (cute apply sqlite3:fold-row proc <> init params)
    935918   db sql) )
    936919
     
    952935                                     (sql <string>) . params)
    953936  (sqlite3:call-with-temporary-statements
    954    (cut apply sqlite3:for-each-row proc <> params)
     937   (cute apply sqlite3:for-each-row proc <> params)
    955938   db sql) )
    956939
     
    971954                                (sql <string>) . params)
    972955  (sqlite3:call-with-temporary-statements
    973    (cut apply sqlite3:map-row proc <> params)
     956   (cute apply sqlite3:map-row proc <> params)
    974957   db sql) )
    975958
     
    989972                          type)
    990973      (make-property-condition 'type))) )
    991   (let ((success? #f))
     974  (let ([success? #f])
    992975    (dynamic-wind
    993976        (lambda ()
     
    1009992(define sqlite3:library-version
    1010993  (foreign-lambda c-string "sqlite3_libversion") )
     994
     995;; Return a Scheme boolean for the usual SQLite column boolean values
     996(define (sqlite3:boolean-value v)
     997  (cond [(string? v)
     998         (or (string-ci=? "Y" v)
     999             (string-ci=? "YES" v)
     1000             (string=? "Yes" v)) ]
     1001        [(and (integer? v) (exact? v))
     1002         (not (zero? v)) ]
     1003        [else
     1004          #f ] ) )
  • release/3/sqlite3/tags/2.0.5/sqlite3.setup

    r8020 r8688  
    1212  `(,so-file
    1313    "sqlite3.html" "egg.jpg")
    14   '((version "2.0.4")
     14  '((version "2.0.5")
    1515    (documentation "sqlite3.html")))
  • release/3/sqlite3/tags/2.0.5/tests/sqlite3-test.scm

    r8020 r8688  
    1111;;;
    1212
    13 ;; This is needed due to a testbase bug!
    14 
    15 (define-for-syntax (SQL-QUERY . lines)
    16   (apply string-append (intersperse lines "\n")) )
    17 
    18 ;;;
     13;; SQL Source
    1914
    2015(define *mak-source-table-sql*
    21   (SQL-QUERY
     16  (MULTILINE-STRING
    2217    "CREATE TABLE IF NOT EXISTS source ("
    2318    "  oid INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,"
    24     "  dir TEXT,"
    25     "  fil TEXT NOT NULL,"
    26     "  ext TEXT,"
     19    "  dir VARCHAR,"
     20    "  fil VARCHAR NOT NULL,"
     21    "  ext VARCHAR,"
     22    "  cnt INTEGER,"
     23    "  foo INTEGER,"
    2724    "  UNIQUE (dir, fil, ext) ON CONFLICT ROLLBACK"
    2825    ");"))
    2926
    3027(define *ins-source-entry-sql*
    31   (SQL-QUERY
    32     "INSERT INTO source (oid, dir, fil, ext)"
    33     "  VALUES (NULL, ?001, ?002, ?003);"))
     28  (MULTILINE-STRING
     29    "INSERT INTO source (oid, dir, fil, ext, cnt, foo)"
     30    "  VALUES (NULL, ?001, ?002, ?003, ?004, ?005);"))
    3431
    3532(define *sel-maximum-dir-length-sql*
    36   (SQL-QUERY
     33  (MULTILINE-STRING
    3734    "SELECT Max(length(source.dir)) FROM source;"))
    3835
     
    4542(define-test string-queries-test "String Queries"
    4643  (initial
    47     (define db)
    48   )
     44    (define dbpn "sqlite3test-strq.db")
     45    (define db) )
    4946
    5047  (setup (delete-file* *db-name*))
     48  #; ; Leave so "sqlite3" command can be used
    5149  (teardown (delete-file* *db-name*))
    5250
     
    5553  (expect-success (sqlite3:exec db *mak-source-table-sql*))
    5654
    57   (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory1" "file1" "ext1"))
    58   (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory10" "file10" "ext10"))
    59   (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory1000" "file1000" "ext1000"))
    60   (expect-success (sqlite3:exec db *ins-source-entry-sql* "" "" ""))
     55  (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory1" "file1" "ext1" 1 <void>))
     56  (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory10" "file10" "ext10" 2 <void>))
     57  (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory1000" "file1000" "ext1000" 3 <void>))
     58  (expect-success (sqlite3:exec db *ins-source-entry-sql* "" "" "" 4 <void>))
    6159
    6260  (expect-eqv 13 (sqlite3:first-result db *sel-maximum-dir-length-sql*))
     
    6967(define-test statement-queries-test "Statement Queries"
    7068  (initial
    71     (define dbpn "sqlit3test.db")
     69    (define dbpn "sqlite3test-stmtq.db")
    7270    (define db)
    7371    (define mak-source-table)
    7472    (define ins-source-entry)
    75     (define sel-maximum-dir-length)
    76   )
     73    (define sel-maximum-dir-length) )
    7774
    7875  (setup (delete-file* dbpn))
     76  #; ; Leave so "sqlite3" command can be used
    7977  (teardown (delete-file* dbpn))
    8078
     
    8684
    8785  (expect-set! ins-source-entry (sqlite3:prepare db *ins-source-entry-sql*))
     86  (expect-eqv 5 (sqlite3:bind-parameter-count ins-source-entry))
    8887  (expect-set! sel-maximum-dir-length (sqlite3:prepare db *sel-maximum-dir-length-sql*))
     88  (expect-eqv 0 (sqlite3:bind-parameter-count sel-maximum-dir-length))
    8989
    90   (expect-success (sqlite3:exec ins-source-entry "directory1" "file1" "ext1"))
    91   (expect-success (sqlite3:exec ins-source-entry "directory10" "file10" "ext10"))
    92   (expect-success (sqlite3:exec ins-source-entry "directory1000" "file1000" "ext1000"))
    93   (expect-success (sqlite3:exec ins-source-entry "" "" ""))
     90  ;#<condition: (exn type) ((exn . message) "call of non-procedure" (exn . arguments) (4) (exn . location) #f)>
     91  (expect-failure (warn "This shouldn't occur: should be an arity error")
     92   (sqlite3:exec ins-source-entry "directory1" "file1" "ext1" 11))
     93
     94  (expect-success (sqlite3:exec ins-source-entry "directory1" "file1" "ext1" 11 <void>))
     95  (expect-success (sqlite3:exec ins-source-entry "directory10" "file10" "ext10" 12 <void>))
     96  (expect-success (sqlite3:exec ins-source-entry "directory1000" "file1000" "ext1000" 13 <void>))
     97  (expect-success (sqlite3:exec ins-source-entry "" "" "" 14 <void>))
    9498
    9599  (expect-eqv 13 (sqlite3:first-result sel-maximum-dir-length))
  • release/3/sqlite3/trunk/doc.scm

    r8020 r8688  
    11(use eggdoc)
    22
    3 (define doc
    4   '((eggdoc:begin
    5      (name "sqlite3")
    6      (description (p "Bindings to version 3.x of the SQLite API."))
    7      (author (url "http://www.chust.org/" "Thomas Chust"))
    8      (usage)
    9      (download "sqlite3.egg")
    10      (requires "synch" "tinyclos" "easyffi" "miscmacros")
    11 
    12      (documentation
     3(define doc '(
     4  (eggdoc:begin
     5
     6    (name "sqlite3")
     7    (description (p "Bindings to version 3.x of the SQLite API."))
     8    (author
     9      (url "http://www.chust.org/" "Thomas Chust"))
     10    (usage)
     11    (download "sqlite3.egg")
     12    (requires "synch" "tinyclos" "easyffi" "miscmacros")
     13
     14    (documentation
     15
    1316      (p "The API of SQLite changed significantly from version 2.x to 3.x. These are new bindings to the modified API, which are reasonably complete -- most procedures that take callback arguments are missing, though.")
    1417      (p "For in-depth information on the functionality of the routines and general information you should consult the " (url "http://www.sqlite.org/" "SQLite documentation") " as well as this manual.")
    1518
    16       (subsection
    17        "Exceptions"
    18        (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:"
     19      (subsection "Exceptions"
     20
     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:"
    1922        (table
    20          (tr (th "Symbol") (th "Meaning"))
    21          #;(tr (td (tt "ok")) (td "Successful result"))
    22          (tr (td (tt "error")) (td "SQL error or missing database "))
    23          (tr (td (tt "internal")) (td "An internal logic error in SQLite "))
    24          (tr (td (tt "permission")) (td "Access permission denied "))
    25          (tr (td (tt "abort")) (td "Callback routine requested an abort "))
    26          (tr (td (tt "busy")) (td "The database file is locked "))
    27          (tr (td (tt "locked")) (td "A table in the database is locked "))
    28          (tr (td (tt "no-memory")) (td "A malloc() failed "))
    29          (tr (td (tt "read-only")) (td "Attempt to write a readonly database "))
    30          (tr (td (tt "interrupt")) (td "Operation terminated by sqlite-interrupt() "))
    31          (tr (td (tt "io-error")) (td "Some kind of disk I/O error occurred "))
    32          (tr (td (tt "corrupt")) (td "The database disk image is malformed "))
    33          (tr (td (tt "not-found")) (td "(Internal Only) Table or record not found "))
    34          (tr (td (tt "full")) (td "Insertion failed because database is full "))
    35          (tr (td (tt "cant-open")) (td "Unable to open the database file "))
    36          (tr (td (tt "protocol")) (td "Database lock protocol error "))
    37          (tr (td (tt "empty")) (td "(Internal Only) Database table is empty "))
    38          (tr (td (tt "schema")) (td "The database schema changed "))
    39          (tr (td (tt "too-big")) (td "Too much data for one row of a table "))
    40          (tr (td (tt "constraint")) (td "Abort due to contraint violation "))
    41          (tr (td (tt "mismatch")) (td "Data type mismatch "))
    42          (tr (td (tt "misuse")) (td "Library used incorrectly "))
    43          (tr (td (tt "no-lfs")) (td "Uses OS features not supported on host "))
    44          (tr (td (tt "authorization")) (td " Authorization denied"))
    45          #;(tr (td (tt "row")) (td (tt "sqlite3:step!") " has another row ready "))
    46          (tr (td (tt "done")) (td (tt "sqlite3:step!") " has finished executing, so no further data is ready")))))
    47 
    48       (subsection
    49        "Classes"
    50        (group
    51         (definition
    52           (signatures
    53            (signature "class" "<sqlite3:database>")
    54            (signature "class" "<sqlite3:statement>"))
    55           (p "These classes are derived from " (tt "<c++-object>") ". They hold a pointer to the underlying C-structure in their " (tt "this") " slot.")
    56           (p (tt "<sqlite3:statement>") " also has a " (tt "database") " slot pointing to the database object it belongs to."))))
    57 
    58       (subsection
    59        "Managing databases"
    60        (group
    61         (procedure
    62          "(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         (definition
    66           (signatures
    67            (signature "method" "(sqlite3:define-collation (db <sqlite3:database>) (name <string>)) => <void>")
    68            (signature "method" "(sqlite3:define-collation (db <sqlite3:database>) (name <string>) (proc <procedure-class>)) => <void>"))
    69           (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.")
    70           (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.")
    71           (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."))
    72         (definition
    73           (signatures
    74            (signature "method" "(sqlite3:define-function (db <sqlite3:database>) (name <string>) (n <exact>) (proc <procedure-class>)) => <void>")
    75            (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>"))
    76           (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.")
    77           (p (tt "n") " is the number of parameters the new SQL function takes or " (tt "-1") " to allow any number of arguments.")
    78           (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.")
    79           (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.")
    80           (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.")
    81           (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."))
    82         (procedure
    83          "(sqlite3:set-busy-timeout! (db <sqlite3:database>) #!optional ((ms <exact>) 0)) => <void>"
    84          (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."))
    85         (procedure
    86          "(sqlite3:interrupt! (db <sqlite3:database>)) => <void>"
    87          (p "Cancels any running database operation as soon as possible.")
    88          (p "This function is always successful and never throws an exception."))
    89         (procedure
    90          "(sqlite3:auto-committing? (db <sqlite3:database>)) => <bool>"
    91          (p "Checks whether the database is currently in auto committing mode, i.e. no transaction is currently active.")
    92          (p "This function always returns a state and never throws an exception."))
    93         (procedure
    94          "(sqlite3:changes (db <sqlite3:database>) #!optional ((total <bool>) #f)) => <number>"
    95          (p "Returns the number of rows changed by the last statement (if " (tt "(not total)") ") or since the database was opened (if " (tt "total") ").")
    96          (p "This function always returns a count and never throws an exception."))
    97         (procedure
    98          "(sqlite3:last-insert-rowid (db <sqlite3:database>)) => <number>"
    99          (p "Returns the row ID of the last row inserted in " (tt "db") ".")
    100          (p "This function always returns a number and never throws an exception."))
    101         (method
    102          "(sqlite3:finalize! (db <sqlite3:database>)) => <void>"
    103          (p "Closes the given database."))))
    104 
    105       (subsection
    106        "Managing statements"
    107        (group
    108         (procedure
    109          "(sqlite3:prepare (db <sqlite3:database>) (sql <string>)) => <sqlite3:statement>, <string>"
    110          (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)."))
    111         (procedure
    112          "(sqlite3:repair! (stmt <sqlite3:statement>)) => <void>"
    113          (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.")
    114          (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.")
    115          (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."))
    116         (procedure
    117          "(sqlite3:column-count (stmt <sqlite3:statement>)) => <exact>"
    118          (p "Can be applied to any statement and returns the number of columns it will return as results.")
    119          (p "This procedure always succeeds and never throws an exception."))
    120         (procedure
    121          "(sqlite3:column-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
    122          (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.")
    123          (p "This procedure always succeeds and never throws an exception."))
    124         (procedure
    125          "(sqlite3:column-declared-type (stmt <sqlite3:statement>) (i <exact>)) => <string>"
    126          (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.")
    127          (p "This procedure always succeeds and never throws an exception."))
    128         (procedure
    129          "(sqlite3:bind-parameter-count (stmt <sqlite3:statement>)) => <exact>"
    130          (p "Can be applied to any statement and returns the number of free parameters that can be bound in the statement.")
    131          (p "This procedure always succeeds and never throws an exception."))
    132         (procedure
    133          "(sqlite3:bind-parameter-index (stmt <sqlite3:statement>) (name <string>)) => <exact>"
    134          (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.")
    135          (p "This procedure always succeeds and never throws an exception."))
    136         (procedure
    137          "(sqlite3:bind-parameter-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
    138          (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.")
    139          (p "This procedure always succeeds and never throws an exception."))
    140         (definition
    141           (signatures
    142            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)) => <void>")
    143            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <void>)) => <void>")
    144            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <exact>)) => <void>")
    145            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <number>)) => <void>")
    146            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <string>)) => <void>")
    147            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <blob>)) => <void>"))
    148           (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:"
    149              (table
    150               (tr (th "Scheme type") (th "SQLite type"))
    151               (tr (td "none") (td (tt "null")))
    152               (tr (td (tt "<sqlite3:null-value>")) (td (tt "null")))
    153               (tr (td (tt "<exact>")) (td (tt "integer")))
    154               (tr (td (tt "<number>")) (td (tt "float")))
    155               (tr (td (tt "<string>")) (td (tt "text")))
    156               (tr (td (tt "<blob>")) (td (tt "blob")))))
    157           (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."))
    158         (procedure
    159          "(sqlite3:bind-parameters! (stmt <sqlite3:statement>) . params) => <void>"
    160          (p "Binds the statement's free parameters."))
    161         (procedure
    162          "(sqlite3:step! (stmt <sqlite3:statement>)) => <boolean>"
    163          (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."))
    164         (procedure
    165          "(sqlite3:column-type (stmt <sqlite3:statement>) (i <exact>)) => <symbol>"
    166          (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.")
    167          (p "The return value can be one of the symbols " (tt "null") ", " (tt "integer") ", " (tt "float") ", " (tt "text") " or " (tt "blob") ".")
    168          (p "This procedure always succeeds and never throws an exception."))
    169         (procedure
    170          "(sqlite3:column-data (stmt <sqlite3:statement>) (i <exact>)) => <void | exact | number | string | blob>"
    171          (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.")
    172          (p "See " (tt "sqlite3:bind!") " for the mapping between Scheme and SQLite data types. Columns of type " (tt "null") " are returned as " (tt "<sqlite3:null-value>") ". 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>") ".")
    173          (p "This procedure always succeeds and never throws an exception."))
    174         (procedure
    175          "(sqlite3:reset! (stmt <sqlite3:statement>)) => <void>"
    176          (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."))
    177         (method
    178          "(sqlite3:finalize! (stmt <sqlite3:statement>)) => <void>"
    179          (p "Must be applied to every statement to free its resources and discard it.")
    180          (p (tt "sqlite3:close") " will not be able to close a database that has associated unfinalized statements."))))
    181 
    182       (subsection
    183        "Simple statement interface"
    184        (group
    185         (procedure
    186          "(sqlite3:call-with-temporary-statements (proc <procedure-class>) (db <sqlite3:database>) . sqls) => <top>"
    187          (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") "."))
    188         (definition
    189           (signatures
    190            (signature "method" "(sqlite3:exec (stmt <sqlite3:statement>) . params) => <void>")
    191            (signature "method" "(sqlite3:exec (db <sqlite3:database>) (sql <string>) . params) => <void>"))
    192           (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it."))
    193         (definition
    194           (signatures
    195            (signature "method" "(sqlite3:update (stmt <sqlite3:statement>) . params) => <exact>")
    196            (signature "method" "(sqlite3:update (db <sqlite3:database>) (sql <string>) . params) => <exact>"))
    197           (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."))
    198         (definition
    199           (signatures
    200            (signature "method" "(sqlite3:first-result (stmt <sqlite3:statement>) . params) => <void | exact | number | string | blob>")
    201            (signature "method" "(sqlite3:first-result (db <sqlite3:database>) (sql <string>) . params) => <void | exact | number | string | blob>"))
    202           (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.")
    203           (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") "."))
    204         (definition
    205           (signatures
    206            (signature "method" "(sqlite3:first-row (stmt <sqlite3:statement>) . params) => <list>")
    207            (signature "method" "(sqlite3:first-row (db <sqlite3:database>) (sql <string>) . params) => <list>"))
    208           (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.")
    209           (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") "."))(definition
    210           (signatures
    211            (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (stmt <sqlite3:statement>) initial . params) => <list>")
    212            (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) initial . params) => <list>"))
    213           (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."))
    214         (definition
    215           (signatures
    216            (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <void>")
    217            (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <void>"))
    218           (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."))
    219         (definition
    220           (signatures
    221            (signature "method" "(sqlite3:map-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <list>")
    222            (signature "method" "(sqlite3:map-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <list>"))
    223           (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."))))
    224 
    225       (subsection
    226        "Utility functions"
    227        (group
    228         (procedure
    229          "(sqlite3:with-transaction (db <sqlite3:database>) (thunk <procedure-class>) #!optional ((type <symbol>) 'deferred)) => <void>"
    230          (p "Runs " (tt "thunk") " within the scope of a transaction on the dataase " (tt "db") ".")
    231          (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.")
    232          (p "The " (tt "type") " of the transaction can be specified as one of the symbols " (tt "deferred") ", " (tt "immediate") " or " (tt "exclusive") "."))
    233         (procedure
    234          "(sqlite3:complete? (sql <string>)) => <boolean>"
    235          (p "Checks whether " (tt "sql") " comprises at least one complete SQL statement."))
    236         (procedure
    237          "(sqlite3:library-version) => <string>"
    238          (p "Returns a string identifying the version of SQLite in use."))
    239         (procedure
    240          "(sqlite3:null-value? <object>) => <boolean>"
    241          (p "Is the " (tt "<object>") " a <sqlite3:null-value>?")
    242          (p "The <sqlite3:null-value> is compatible with the \"sql-null\" egg. "
    243             "The default \"sql-null\" egg function " (code "(sql-null)") " "
    244             "= the <sqlite3:null-value>. "
    245             "But to ensure equality - " (code "(define sql-null sqlite3:null)") ".")))))
    246 
    247      (history
     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.") ) )
     59
     60      (subsection "Managing databases"
     61
     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
     88        (procedure "(sqlite3:interrupt! (db <sqlite3:database>)) => <void>"
     89          (p "Cancels any running database operation as soon as possible.")
     90          (p "This function is always successful and never throws an exception."))
     91
     92        (procedure "(sqlite3:auto-committing? (db <sqlite3:database>)) => <bool>"
     93          (p "Checks whether the database is currently in auto committing mode, i.e. no transaction is currently active.")
     94          (p "This function always returns a state and never throws an exception."))
     95
     96        (procedure "(sqlite3:changes (db <sqlite3:database>) #!optional ((total <bool>) #f)) => <number>"
     97          (p "Returns the number of rows changed by the last statement (if " (tt "(not total)") ") or since the database was opened (if " (tt "total") ").")
     98          (p "This function always returns a count and never throws an exception."))
     99
     100        (procedure "(sqlite3:last-insert-rowid (db <sqlite3:database>)) => <number>"
     101          (p "Returns the row ID of the last row inserted in " (tt "db") ".")
     102          (p "This function always returns a number and never throws an exception."))
     103
     104        (method "(sqlite3:finalize! (db <sqlite3:database>)) => <void>"
     105          (p "Closes the given database.") ) )
     106
     107      (subsection "Managing statements"
     108
     109        (procedure "(sqlite3:prepare (db <sqlite3:database>) (sql <string>)) => <sqlite3:statement>, <string>"
     110          (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)."))
     111
     112        (procedure "(sqlite3:repair! (stmt <sqlite3:statement>)) => <void>"
     113          (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.")
     114          (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.")
     115          (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."))
     116
     117        (procedure "(sqlite3:column-count (stmt <sqlite3:statement>)) => <exact>"
     118          (p "Can be applied to any statement and returns the number of columns it will return as results.")
     119          (p "This procedure always succeeds and never throws an exception."))
     120
     121        (procedure "(sqlite3:column-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
     122          (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.")
     123          (p "This procedure always succeeds and never throws an exception."))
     124
     125        (procedure "(sqlite3:column-declared-type (stmt <sqlite3:statement>) (i <exact>)) => <string>"
     126          (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.")
     127          (p "This procedure always succeeds and never throws an exception."))
     128
     129        (procedure "(sqlite3:bind-parameter-count (stmt <sqlite3:statement>)) => <exact>"
     130          (p "Can be applied to any statement and returns the number of free parameters that can be bound in the statement.")
     131          (p "This procedure always succeeds and never throws an exception."))
     132
     133        (procedure "(sqlite3:bind-parameter-index (stmt <sqlite3:statement>) (name <string>)) => <exact>"
     134          (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.")
     135          (p "This procedure always succeeds and never throws an exception."))
     136
     137        (procedure "(sqlite3:bind-parameter-name (stmt <sqlite3:statement>) (i <exact>)) => <string>"
     138          (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.")
     139          (p "This procedure always succeeds and never throws an exception."))
     140
     141        (definition
     142          (signatures
     143            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)) => <void>")
     144            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <boolean>)) => <void>")
     145            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <exact>)) => <void>")
     146            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <number>)) => <void>")
     147            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <string>)) => <void>")
     148            (signature "method" "(sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>) (v <blob>)) => <void>"))
     149          (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:"
     150          (table
     151            (tr (th "Scheme type") (th "SQLite type"))
     152            (tr (td "none") (td (tt "null")))
     153            (tr (td (tt "<boolean>")) (td (tt "integer: #t = 1, #f = 0")))
     154            (tr (td (tt "<exact>")) (td (tt "integer")))
     155            (tr (td (tt "<number>")) (td (tt "float")))
     156            (tr (td (tt "<string>")) (td (tt "text")))
     157            (tr (td (tt "<blob>")) (td (tt "blob")))))
     158          (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."))
     159
     160        (procedure "(sqlite3:bind-parameters! (stmt <sqlite3:statement>) . params) => <void>"
     161          (p "Binds the statement's free parameters.")
     162          (p "Allows " (code "<void>") " as a parameter.") )
     163
     164        (procedure "(sqlite3:step! (stmt <sqlite3:statement>)) => <boolean>"
     165          (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."))
     166
     167        (procedure "(sqlite3:column-type (stmt <sqlite3:statement>) (i <exact>)) => <symbol>"
     168          (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.")
     169          (p "The return value can be one of the symbols " (tt "null") ", " (tt "integer") ", " (tt "float") ", " (tt "text") " or " (tt "blob") ".")
     170          (p "This procedure always succeeds and never throws an exception."))
     171
     172        (procedure "(sqlite3:column-data (stmt <sqlite3:statement>) (i <exact>)) => <void | exact | number | string | blob>"
     173          (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.")
     174          (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>") ".")
     175          (p "This procedure always succeeds and never throws an exception."))
     176
     177        (procedure "(sqlite3:reset! (stmt <sqlite3:statement>)) => <void>"
     178          (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."))
     179
     180        (method "(sqlite3:finalize! (stmt <sqlite3:statement>)) => <void>"
     181          (p "Must be applied to every statement to free its resources and discard it.")
     182          (p (tt "sqlite3:close") " will not be able to close a database that has associated unfinalized statements.") ) )
     183
     184      (subsection "Simple statement interface"
     185
     186        (procedure "(sqlite3:call-with-temporary-statements (proc <procedure-class>) (db <sqlite3:database>) . sqls) => <top>"
     187          (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") "."))
     188
     189        (definition
     190          (signatures
     191            (signature "method" "(sqlite3:exec (stmt <sqlite3:statement>) . params) => <void>")
     192            (signature "method" "(sqlite3:exec (db <sqlite3:database>) (sql <string>) . params) => <void>"))
     193          (p "(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it.")
     194          (p "Allows " (code "<void>") " as a parameter.") )
     195
     196        (definition
     197          (signatures
     198            (signature "method" "(sqlite3:update (stmt <sqlite3:statement>) . params) => <exact>")
     199            (signature "method" "(sqlite3:update (db <sqlite3:database>) (sql <string>) . params) => <exact>"))
     200          (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.")
     201          (p "Allows " (code "<void>") " as a parameter.") )
     202
     203        (definition
     204          (signatures
     205            (signature "method" "(sqlite3:first-result (stmt <sqlite3:statement>) . params) => <void | exact | number | string | blob>")
     206            (signature "method" "(sqlite3:first-result (db <sqlite3:database>) (sql <string>) . params) => <void | exact | number | string | blob>"))
     207          (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.")
     208          (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") ".")
     209          (p "Allows " (code "<void>") " as a parameter.") )
     210
     211        (definition
     212          (signatures
     213            (signature "method" "(sqlite3:first-row (stmt <sqlite3:statement>) . params) => <list>")
     214            (signature "method" "(sqlite3:first-row (db <sqlite3:database>) (sql <string>) . params) => <list>"))
     215          (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.")
     216          (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") ".")
     217          (p "Allows " (code "<void>") " as a parameter.") )
     218
     219        (definition
     220          (signatures
     221            (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (stmt <sqlite3:statement>) initial . params) => <list>")
     222            (signature "method" "(sqlite3:fold-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) initial . params) => <list>"))
     223          (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.")
     224          (p "Allows " (code "<void>") " as a parameter.") )
     225
     226        (definition
     227          (signatures
     228            (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <void>")
     229            (signature "method" "(sqlite3:for-each-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <void>"))
     230          (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.")
     231          (p "Allows " (code "<void>") " as a parameter.") )
     232
     233        (definition
     234          (signatures
     235            (signature "method" "(sqlite3:map-row (proc <procedure-class>) (stmt <sqlite3:statement>) . params) => <list>")
     236            (signature "method" "(sqlite3:map-row (proc <procedure-class>) (db <sqlite3:database>) (sql <string>) . params) => <list>"))
     237          (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.")
     238          (p "Allows " (code "<void>") " as a parameter.") ) )
     239
     240      (subsection "Utility functions"
     241
     242        (procedure "(sqlite3:with-transaction (db <sqlite3:database>) (thunk <procedure-class>) #!optional ((type <symbol>) 'deferred)) => <void>"
     243          (p "Runs " (tt "thunk") " within the scope of a transaction on the database " (tt "db") ".")
     244          (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.")
     245          (p "The " (tt "type") " of the transaction can be specified as one of the symbols " (tt "deferred") ", " (tt "immediate") " or " (tt "exclusive") "."))
     246
     247        (procedure "(sqlite3:complete? (sql <string>)) => <boolean>"
     248          (p "Checks whether " (tt "sql") " comprises at least one complete SQL statement."))
     249
     250        (procedure "(sqlite3:library-version) => <string>"
     251          (p "Returns a string identifying the version of SQLite in use.") )
     252
     253        (procedure "(sqlite3:boolean-value v) => <boolean>"
     254          (p "Returns a Scheme boolean for the usual SQLite column boolean values.")
     255          (p "Truth values are " (code "Y") ", " (code "y") ", " (code "YES") ", " (code "yes") ", " (code "Yes") ", and " (code "(not (zero? v))") ".")
     256          (p "Anything else is considered false.") ) ) )
     257
     258    (history
     259      (version "2.0.5" "Added some <boolean> support. Change for NULL (<void>) handling. [Kon Lovett]")
    248260      (version "2.0.4" "Added " (code "sqlite3:fold-row") " & " (code "sqlite3:bind-parameters!") ". Fix for introduced bug in " (code "sqlite3:changes") ". [Kon Lovett]")
    249261      (version "2.0.3" "Added " (code "sqlite3:null-value") ", " (code "sqlite3:null-value?") ", and " (code "sqlite3:null") ". [Kon Lovett]")
     
    273285      (version "1.0.2" "Added a typecheck for increased safety")
    274286      (version "1.0.1" "Fixed type mistakes in the source")
    275       (version "1.0.0" "Initial release"))
    276 
    277       (license
    278        "Copyright (c) 2005, Thomas Chust <chust@web.de>.  All rights reserved.
     287      (version "1.0.0" "Initial release") )
     288
     289     (license #<<EOS
     290Copyright (c) 2005, Thomas Chust <chust@web.de>.  All rights reserved.
    279291
    280292Redistribution and use in source and binary forms, with or without
     
    300312LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    301313NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    302 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."))))
    303 
    304 (eggdoc->html
    305  doc
    306  (append
    307   (eggdoc:make-stylesheet doc)
    308   `((method *macro* . ,eggdoc:make-defsig))))
     314SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     315EOS
     316) ) ) )
     317
     318(eggdoc->html doc
     319              (append (eggdoc:make-stylesheet doc)
     320                      `((method *macro* . ,eggdoc:make-defsig))))
  • release/3/sqlite3/trunk/sqlite3.html

    r8020 r8688  
    251251<div class="subsection">
    252252<h4>Classes</h4>
    253 <dl>
    254253<dt class="definition"><strong>class:</strong> &lt;sqlite3:database&gt;
    255254<br /><strong>class:</strong> &lt;sqlite3:statement&gt;</dt>
    256255<dd>
    257256<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>
    258 <p><tt>&lt;sqlite3:statement&gt;</tt> also has a <tt>database</tt> slot pointing to the database object it belongs to.</p></dd></dl></div>
     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>
    259258<div class="subsection">
    260259<h4>Managing databases</h4>
    261 <dl>
    262260<dt class="definition"><strong>procedure:</strong> (sqlite3:open (path &lt;string&gt;)) =&gt; &lt;sqlite3:database&gt;</dt>
    263261<dd>
     
    301299<dt class="definition"><strong>method:</strong> (sqlite3:finalize! (db &lt;sqlite3:database&gt;)) =&gt; &lt;void&gt;</dt>
    302300<dd>
    303 <p>Closes the given database.</p></dd></dl></div>
     301<p>Closes the given database.</p></dd></div>
    304302<div class="subsection">
    305303<h4>Managing statements</h4>
    306 <dl>
    307304<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>
    308305<dd>
     
    338335<p>This procedure always succeeds and never throws an exception.</p></dd>
    339336<dt class="definition"><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;)) =&gt; &lt;void&gt;
    340 <br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;void&gt;)) =&gt; &lt;void&gt;
     337<br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;boolean&gt;)) =&gt; &lt;void&gt;
    341338<br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;exact&gt;)) =&gt; &lt;void&gt;
    342339<br /><strong>method:</strong> (sqlite3:bind! (stmt &lt;sqlite3:statement&gt;) (i &lt;exact&gt;) (v &lt;number&gt;)) =&gt; &lt;void&gt;
     
    353350<td><tt>null</tt></td></tr>
    354351<tr>
    355 <td><tt>&lt;sqlite3:null-value&gt;</tt></td>
    356 <td><tt>null</tt></td></tr>
     352<td><tt>&lt;boolean&gt;</tt></td>
     353<td><tt>integer: #t = 1, #f = 0</tt></td></tr>
    357354<tr>
    358355<td><tt>&lt;exact&gt;</tt></td>
     
    370367<dt class="definition"><strong>procedure:</strong> (sqlite3:bind-parameters! (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;void&gt;</dt>
    371368<dd>
    372 <p>Binds the statement's free parameters.</p></dd>
     369<p>Binds the statement's free parameters.</p>
     370<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    373371<dt class="definition"><strong>procedure:</strong> (sqlite3:step! (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;boolean&gt;</dt>
    374372<dd>
     
    382380<dd>
    383381<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>
    384 <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;sqlite3:null-value&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>
     382<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>
    385383<p>This procedure always succeeds and never throws an exception.</p></dd>
    386384<dt class="definition"><strong>procedure:</strong> (sqlite3:reset! (stmt &lt;sqlite3:statement&gt;)) =&gt; &lt;void&gt;</dt>
     
    390388<dd>
    391389<p>Must be applied to every statement to free its resources and discard it.</p>
    392 <p><tt>sqlite3:close</tt> will not be able to close a database that has associated unfinalized statements.</p></dd></dl></div>
     390<p><tt>sqlite3:close</tt> will not be able to close a database that has associated unfinalized statements.</p></dd></div>
    393391<div class="subsection">
    394392<h4>Simple statement interface</h4>
    395 <dl>
    396393<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>
    397394<dd>
     
    400397<br /><strong>method:</strong> (sqlite3:exec (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;void&gt;</dt>
    401398<dd>
    402 <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>
     399<p>(Compiles the given SQL), resets the statement, binds the statement's free parameters and executes the statement ignoring possible results from it.</p>
     400<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    403401<dt class="definition"><strong>method:</strong> (sqlite3:update (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;exact&gt;
    404402<br /><strong>method:</strong> (sqlite3:update (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;exact&gt;</dt>
    405403<dd>
    406 <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></dd>
     404<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>
     405<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    407406<dt class="definition"><strong>method:</strong> (sqlite3:first-result (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;void | exact | number | string | blob&gt;
    408407<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>
    409408<dd>
    410409<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>
    411 <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>
     410<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>
     411<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    412412<dt class="definition"><strong>method:</strong> (sqlite3:first-row (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;list&gt;
    413413<br /><strong>method:</strong> (sqlite3:first-row (db &lt;sqlite3:database&gt;) (sql &lt;string&gt;) . params) =&gt; &lt;list&gt;</dt>
    414414<dd>
    415415<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>
    416 <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>
     416<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>
     417<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    417418<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;
    418419<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>
    419420<dd>
    420 <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></dd>
     421<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>
     422<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    421423<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;
    422424<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>
    423425<dd>
    424 <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>
     426<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>
     427<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd>
    425428<dt class="definition"><strong>method:</strong> (sqlite3:map-row (proc &lt;procedure-class&gt;) (stmt &lt;sqlite3:statement&gt;) . params) =&gt; &lt;list&gt;
    426429<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>
    427430<dd>
    428 <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></dl></div>
     431<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>
     432<p>Allows <code>&lt;void&gt;</code> as a parameter.</p></dd></div>
    429433<div class="subsection">
    430434<h4>Utility functions</h4>
    431 <dl>
    432435<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>
    433436<dd>
    434 <p>Runs <tt>thunk</tt> within the scope of a transaction on the dataase <tt>db</tt>.</p>
     437<p>Runs <tt>thunk</tt> within the scope of a transaction on the database <tt>db</tt>.</p>
    435438<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>
    436439<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>
     
    441444<dd>
    442445<p>Returns a string identifying the version of SQLite in use.</p></dd>
    443 <dt class="definition"><strong>procedure:</strong> (sqlite3:null-value? &lt;object&gt;) =&gt; &lt;boolean&gt;</dt>
    444 <dd>
    445 <p>Is the <tt>&lt;object&gt;</tt> a &lt;sqlite3:null-value&gt;?</p>
    446 <p>The &lt;sqlite3:null-value&gt; is compatible with the &quot;sql-null&quot; egg. The default &quot;sql-null&quot; egg function <code>(sql-null)</code> = the &lt;sqlite3:null-value&gt;. But to ensure equality - <code>(define sql-null sqlite3:null)</code>.</p></dd></dl></div></div>
     446<dt class="definition"><strong>procedure:</strong> (sqlite3:boolean-value v) =&gt; &lt;boolean&gt;</dt>
     447<dd>
     448<p>Returns a Scheme boolean for the usual SQLite column boolean values.</p>
     449<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>
     450<p>Anything else is considered false.</p></dd></div></div>
    447451<div class="section">
    448452<h3>Version</h3>
    449453<ul>
     454<li>2.0.5 Added some &lt;boolean&gt; support. Change for NULL (&lt;void&gt;) handling. [Kon Lovett]</li>
    450455<li>2.0.4 Added <code>sqlite3:fold-row</code> &amp; <code>sqlite3:bind-parameters!</code>. Fix for introduced bug in <code>sqlite3:changes</code>. [Kon Lovett]</li>
    451456<li>2.0.3 Added <code>sqlite3:null-value</code>, <code>sqlite3:null-value?</code>, and <code>sqlite3:null</code>. [Kon Lovett]</li>
     
    492497  written permission.
    493498
    494 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS
    495 IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     499THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \&quot;AS
     500IS\&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    496501THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    497502PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
  • release/3/sqlite3/trunk/sqlite3.scm

    r8020 r8688  
    4949    sqlite3:complete?
    5050    sqlite3:library-version
    51     ;; null type
    52     sqlite3:null
    53     sqlite3:null-value?
    54     sqlite3:null-value) )
     51    sqlite3:boolean-value ) )
    5552
    5653(declare
     
    6158  (disable-warning redef)
    6259  (unused
    63     ; global variable '...' is never used
     60    ; Stop annoying messages
    6461    chicken_sqlite3_function_stub
    6562    chicken_sqlite3_collation_stub
     
    6966    ##sys#expand-home-path
    7067    #;##sys#pathname-resolution
     68    abort-sqlite3-null-error
    7169    sqlite3:errmsg ) )
    7270
    7371#>#include <sqlite3.h><#
    7472
    75 (use srfi-1 srfi-12 srfi-13 srfi-18 srfi-26 extras lolevel)
     73#;(use srfi-1 srfi-12 srfi-13 srfi-18 srfi-26 srfi-69 extras lolevel)
     74(use (srfi 1 12 13 18 26 69) extras lolevel)
    7675(use tinyclos synch miscmacros)
    7776
     
    132131(define-foreign-type sqlite3:value (c-pointer "sqlite3_value"))
    133132
    134 (define sqlite3:null void)
    135 
    136 (define sqlite3:null-value (sqlite3:null))
    137 
    138 (define (sqlite3:null-value? obj)
    139   (eq? sqlite3:null-value obj) )
    140 
    141133;;; Classes for databases and statements
    142134
     
    146138  (lambda (db)
    147139    (unless (slot-ref db 'this)
    148       (signal-sqlite3-null-error 'sqlite3:database->c-pointer db))
     140      (abort-sqlite3-null-error 'sqlite3:database->c-pointer db))
    149141    db))
    150142
     
    154146  (lambda (stmt)
    155147    (unless (slot-ref stmt 'this)
    156       (signal-sqlite3-null-error 'sqlite3:statement->c-pointer stmt))
     148      (abort-sqlite3-null-error 'sqlite3:statement->c-pointer stmt))
    157149    stmt))
    158150
     
    167159  ##sys#expand-home-path
    168160  #; ;not needed, yet
    169   (cut ##sys#pathname-resolution <> identity) )
     161  (cute ##sys#pathname-resolution <> identity) )
    170162
    171163;; Conditions
     
    190182;; Errors
    191183
    192 (define ((signal-sqlite3-error loc db . args) sta)
    193   (signal
     184(define ((abort-sqlite3-error loc db . args) sta)
     185  (abort
    194186   (apply make-sqlite3-error-condition loc
    195187                                       (if db (sqlite3:errmsg db) (symbol->string sta))
     
    209201      (make-sqlite3-condition 'error)))) )
    210202
    211 (define (signal-sqlite3-null-error loc obj)
    212   (signal
     203(define (abort-sqlite3-null-error loc obj)
     204  (abort
    213205   (make-sqlite3-error-condition loc
    214206                                 (string-append
     
    228220  (if (null? (cdr keys))
    229221      (hash-table-set! ht-tree (car keys) value)
    230       (hash-table-update!
    231        ht-tree
    232        (car keys)
    233        (cut hash-table-tree-set! <> (cdr keys) value)
    234        (thunker make-hash-table)) )
     222      (hash-table-update! ht-tree
     223                          (car keys)
     224                          (cute hash-table-tree-set! <> (cdr keys) value)
     225                          (thunker make-hash-table)) )
    235226  ht-tree )
    236227
     
    238229  (if (null? (cdr keys))
    239230      (hash-table-delete! ht-tree (car keys))
    240       (hash-table-update!
    241        ht-tree
    242        (car keys)
    243        (cut hash-table-tree-delete! <> (cdr keys))
    244        (thunker make-hash-table)) )
     231      (hash-table-update! ht-tree
     232                          (car keys)
     233                          (cute hash-table-tree-delete! <> (cdr keys))
     234                          (thunker make-hash-table)) )
    245235  ht-tree )
    246236
     
    248238         ht-tree keys
    249239         #!optional
    250          (thunk (thunker signal
     240         (thunk (thunker abort
    251241                         (make-composite-condition
    252                           (make-exn-condition
    253                            'hash-table-tree-ref
    254                            "hash-table-tree does not contain path"
    255                            ht-tree keys)
     242                          (make-exn-condition 'hash-table-tree-ref
     243                                              "hash-table-tree does not contain path"
     244                                              ht-tree keys)
    256245                          (make-property-condition 'access)))))
    257246  (let/cc return
    258     (let loop ((ht ht-tree)
    259                (keys keys))
     247    (let loop ([ht ht-tree]
     248               [keys keys] )
    260249      (if (null? keys)
    261250          ht
     
    267256
    268257(define (hash-table-tree-clear! htt id elt-clear)
    269   (cond ((hash-table-ref/default htt id #f)
    270          => (cut hash-table-walk <> elt-clear)))
     258  (cond [(hash-table-ref/default htt id #f)
     259         => (cute hash-table-walk <> elt-clear) ] )
    271260  (hash-table-delete! htt id) )
    272261
     
    280269                 int
    281270  (let/cc return
    282     (let ((r #f))
     271    (let ([r #f])
    283272      (dynamic-wind
    284         noop
    285         (lambda ()
    286           (handle-exceptions exn
    287                              (print-error "in collation function" exn)
    288             (let ((a (make-string la)) (b (make-string lb)))
    289               (move-memory! da a la)
    290               (move-memory! db b lb)
    291               (set! r
    292                     ((vector-ref (call-with/synch *sqlite3:collations*
    293                                    (cut hash-table-tree-ref <> qn))
    294                                  1)
    295                      a b)))))
    296         (lambda ()
    297           (if (and (integer? r) (exact? r))
    298               (return r)
    299               (begin
    300                 (print-error "in collation function: invalid return value" (->string r))
    301                 (return 0))))) ) ) )
     273          noop
     274          (lambda ()
     275            (handle-exceptions exn
     276                               (print-error "in collation function" exn)
     277              (let ([a (make-string la)]
     278                    [b (make-string lb)] )
     279                (move-memory! da a la)
     280                (move-memory! db b lb)
     281                (set! r
     282                      ((vector-ref (call-with/synch *sqlite3:collations*
     283                                     (cute hash-table-tree-ref <> qn))
     284                                   1)
     285                       a b)))))
     286          (lambda ()
     287            (if (and (integer? r) (exact? r))
     288                (return r)
     289                (begin
     290                  (print-error "in collation function: invalid return value" (->string r))
     291                  (return 0))))) ) ) )
    302292
    303293(define sqlite3_create_collation
    304294  (foreign-lambda* sqlite3:status
    305295                  ((sqlite3:database db) (c-string name) (scheme-object qn))
    306 #<<END
     296#<<EOS
    307297  if (qn == C_SCHEME_FALSE)
    308298    return(sqlite3_create_collation(db, name, SQLITE_UTF8, NULL, NULL));
     
    314304                                               int, const void *))
    315305                                        &chicken_sqlite3_collation_stub));
    316 END
     306EOS
    317307  ))
    318308
     
    320310(define-method (sqlite3:define-collation (db <sqlite3:database>)
    321311                                         (name <string>))
    322   (cond
    323    ((sqlite3_create_collation db name #f)
    324     => (signal-sqlite3-error 'sqlite3:define-collation db name))
    325    (else
    326     (let ((qn (list (pointer->address (slot-ref db 'this)) name)))
    327       (call-with/synch *sqlite3:collations*
    328         (lambda (col)
    329           (cond
    330            ((hash-table-tree-ref/default col qn #f)
    331             => (lambda (info)
    332                  (hash-table-tree-delete! col qn)
    333                  (object-release (vector-ref info 0))))))) ) ) ) )
     312  (cond [(sqlite3_create_collation db name #f)
     313         => (abort-sqlite3-error 'sqlite3:define-collation db name) ]
     314        [else
     315         (let ([qn (list (pointer->address (slot-ref db 'this)) name)])
     316           (call-with/synch *sqlite3:collations*
     317             (lambda (col)
     318               (cond [(hash-table-tree-ref/default col qn #f)
     319                      => (lambda (info)
     320                           (hash-table-tree-delete! col qn)
     321                           (object-release (vector-ref info 0))) ] ) ) ) ) ] ) )
    334322
    335323(define-method (sqlite3:define-collation (db <sqlite3:database>)
    336324                                          (name <string>)
    337325                                          (proc <procedure-class>))
    338   (let ((qn (object-evict (list (pointer->address (slot-ref db 'this)) name))))
    339     (cond
    340      ((sqlite3_create_collation db name qn)
    341       => (lambda (s)
    342            (object-release qn)
    343            ((signal-sqlite3-error 'sqlite3:define-collation db name proc) s)))
    344      (else
    345       (call-with/synch *sqlite3:collations*
    346         (cut hash-table-tree-set! <> qn (vector qn proc))) ) ) ) )
     326  (let ([qn (object-evict (list (pointer->address (slot-ref db 'this)) name))])
     327    (cond [(sqlite3_create_collation db name qn)
     328           => (lambda (s)
     329                (object-release qn)
     330                ((abort-sqlite3-error 'sqlite3:define-collation db name proc) s)) ]
     331          [else
     332           (call-with/synch *sqlite3:collations*
     333        (cute hash-table-tree-set! <> qn (vector qn proc))) ] ) ) )
    347334
    348335;;; SQL function interface
     
    353340
    354341(define (sqlite3:parameter-data n args)
    355   (let loop ((i 0))
    356     (if (< i n)
    357         (cons
    358          (case ((foreign-lambda* sqlite3:type
    359                                  (((c-pointer sqlite3:value) args) (int i))
    360                  "return(sqlite3_value_type(args[i]));")
    361                 args i)
    362            ((integer)
    363             ((foreign-lambda* integer
    364                               (((c-pointer sqlite3:value) args) (int i))
    365               "return(sqlite3_value_double(args[i]));")
    366              args i))
    367            ((float)
    368             ((foreign-lambda* double
    369                               (((c-pointer sqlite3:value) args) (int i))
    370               "return(sqlite3_value_double(args[i]));")
    371              args i))
    372            ((text)
    373             ((foreign-primitive scheme-object
    374                                 (((c-pointer sqlite3:value) args) (int i))
    375               "int n = sqlite3_value_bytes(args[i]);"
    376               "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    377               "return(C_string(&s, n, (char *)sqlite3_value_text(args[i])));")
    378              args i))
    379            ((blob)
    380             ((foreign-primitive scheme-object
    381                                 (((c-pointer sqlite3:value) args) (int i))
    382               "int n = sqlite3_value_bytes(args[i]);"
    383               "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    384               "return(C_bytevector(&s, n, (char *)sqlite3_value_blob(args[i])));")
    385              args i))
    386            (else
    387             sqlite3:null-value))
    388          (loop (add1 i)))
    389         '() ) ) )
     342  (let loop ([i 0])
     343    (if (<= n i)
     344        '()
     345        (cons (case ((foreign-lambda* sqlite3:type
     346                                      (((c-pointer sqlite3:value) args) (int i))
     347                      "return(sqlite3_value_type(args[i]));")
     348                     args i)
     349                [(integer)
     350                 ((foreign-lambda* integer
     351                                   (((c-pointer sqlite3:value) args) (int i))
     352                   "return(sqlite3_value_double(args[i]));")
     353                  args i) ]
     354                [(float)
     355                 ((foreign-lambda* double
     356                                   (((c-pointer sqlite3:value) args) (int i))
     357                   "return(sqlite3_value_double(args[i]));")
     358                  args i) ]
     359                [(text)
     360                 ((foreign-primitive scheme-object
     361                                     (((c-pointer sqlite3:value) args) (int i))
     362                   "int n = sqlite3_value_bytes(args[i]);"
     363                   "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
     364                   "return(C_string(&s, n, (char *)sqlite3_value_text(args[i])));")
     365                  args i) ]
     366                [(blob)
     367                 ((foreign-primitive scheme-object
     368                                     (((c-pointer sqlite3:value) args) (int i))
     369                   "int n = sqlite3_value_bytes(args[i]);"
     370                   "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
     371                   "return(C_bytevector(&s, n, (char *)sqlite3_value_blob(args[i])));")
     372                  args i) ]
     373                [else
     374                 <void> ] )
     375              (loop (add1 i)) ) ) ) )
    390376
    391377(define-generic sqlite3:set-result!)
     
    432418  (let/cc return
    433419    (dynamic-wind
    434       noop
    435       (lambda ()
    436         (handle-exceptions exn
    437                            (print-error "in SQL function" exn)
    438           (sqlite3:set-result!
    439            ctx
    440            (apply
    441             (vector-ref
    442              (call-with/synch *sqlite3:functions*
    443               (cut hash-table-tree-ref <> (sqlite3_user_data ctx)))
    444              1)
    445             (sqlite3:parameter-data n args)))))
    446      (lambda ()
    447        (return (void)))) ) )
     420        noop
     421        (lambda ()
     422          (handle-exceptions exn
     423                             (print-error "in SQL function" exn)
     424            (sqlite3:set-result!
     425             ctx
     426             (apply (vector-ref
     427                     (call-with/synch *sqlite3:functions*
     428                      (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))
     429                     1)
     430                    (sqlite3:parameter-data n args) ) ) ) )
     431       (lambda ()
     432         (return (void)) ) ) ) )
    448433
    449434(define sqlite3_aggregate_context
     
    455440  (let/cc return
    456441    (dynamic-wind
    457       noop
    458       (lambda ()
    459         (handle-exceptions exn
    460                            (print-error "in step of SQL function" exn)
    461           (let ((info (call-with/synch *sqlite3:functions*
    462                        (cut hash-table-tree-ref <> (sqlite3_user_data ctx)))))
    463             (call-with/synch *sqlite3:seeds*
    464              (cut hash-table-update!/default
    465                   <>
    466                   (sqlite3_aggregate_context ctx)
    467                   (lambda (seed)
    468                     (apply (vector-ref info 1) seed (sqlite3:parameter-data n args)))
    469                   (vector-ref info 2))))))
    470          (lambda ()
    471            (return (void)))) ) )
     442        noop
     443        (lambda ()
     444          (handle-exceptions exn
     445                             (print-error "in step of SQL function" exn)
     446            (let ([info (call-with/synch *sqlite3:functions*
     447                          (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))])
     448              (call-with/synch *sqlite3:seeds*
     449               (cute hash-table-update!/default
     450                     <>
     451                     (sqlite3_aggregate_context ctx)
     452                     (lambda (seed)
     453                       (apply (vector-ref info 1) seed (sqlite3:parameter-data n args)))
     454                     (vector-ref info 2)) ) ) ) )
     455           (lambda ()
     456             (return (void)) ) ) ) )
    472457
    473458(define-external (chicken_sqlite3_final_stub (c-pointer ctx))
    474459                 void
    475460  (let/cc return
    476     (let ((agc (sqlite3_aggregate_context ctx)))
     461    (let ([agc (sqlite3_aggregate_context ctx)])
    477462      (dynamic-wind
    478         noop
    479         (lambda ()
    480           (handle-exceptions exn
    481                              (print-error "in final of SQL function" exn)
    482             (let ((info (call-with/synch *sqlite3:functions*
    483                          (cut hash-table-tree-ref <> (sqlite3_user_data ctx)))))
    484               (cond
    485                 (((vector-ref info 3)
    486                   (call-with/synch *sqlite3:seeds*
    487                    (cut hash-table-ref/default <> agc (vector-ref info 2))))
    488                  => (cut sqlite3:set-result! ctx <>))
    489                 (else
    490                   (sqlite3:set-result! ctx))))))
    491         (lambda ()
    492           (call-with/synch *sqlite3:seeds*
    493            (cut hash-table-delete! <> agc))
    494           (return (void)))) ) ) )
     463          noop
     464          (lambda ()
     465            (handle-exceptions exn
     466                               (print-error "in final of SQL function" exn)
     467              (let ([info (call-with/synch *sqlite3:functions*
     468                           (cute hash-table-tree-ref <> (sqlite3_user_data ctx)))])
     469                (cond [((vector-ref info 3)
     470                 (call-with/synch *sqlite3:seeds*
     471                   (cute hash-table-ref/default <> agc (vector-ref info 2))))
     472                 => (cute sqlite3:set-result! ctx <>) ]
     473                [else
     474                 (sqlite3:set-result! ctx) ] ) ) ) )
     475          (lambda ()
     476            (call-with/synch *sqlite3:seeds*
     477             (cute hash-table-delete! <> agc))
     478            (return (void)) ) ) ) ) )
    495479
    496480(define-generic sqlite3:define-function)
     
    499483                                         (n <exact>)
    500484                                         (proc <procedure-class>))
    501   (let ((qn (object-evict (list (pointer->address (slot-ref db 'this)) name))))
    502     (cond
    503      (((foreign-lambda* sqlite3:status
    504                         ((sqlite3:database db) (c-string name) (int n) (scheme-object qn))
    505 #<<END
     485  (let ([qn (object-evict (list (pointer->address (slot-ref db 'this)) name))])
     486    (cond [((foreign-lambda* sqlite3:status
     487                             ((sqlite3:database db)
     488                              (c-string name) (int n) (scheme-object qn))
     489#<<EOS
    506490        return(sqlite3_create_function(db, name, n, SQLITE_UTF8,
    507491                                       (void *)qn,
     
    511495                                       NULL,
    512496                                       NULL));
    513 END
    514        )
    515        db name n qn)
    516       => (lambda (s)
    517            (object-release qn)
    518            ((signal-sqlite3-error 'sqlite3:define-function db name n proc) s)))
    519      (else
    520       (call-with/synch *sqlite3:functions*
    521         (cut hash-table-tree-set! <> qn (vector qn proc))) ) ) ) )
     497EOS
     498            )
     499            db name n qn)
     500           => (lambda (s)
     501                (object-release qn)
     502                ((abort-sqlite3-error 'sqlite3:define-function db name n proc) s)) ]
     503          [else
     504           (call-with/synch *sqlite3:functions*
     505        (cute hash-table-tree-set! <> qn (vector qn proc))) ] ) ) )
    522506
    523507(define-method (sqlite3:define-function (db <sqlite3:database>)
     
    528512                                         #!optional (final-proc identity))
    529513  (check-sqlite3-type 'sqlite3:define-function final-proc <procedure-class>)
    530   (let ((qn (object-evict (list (pointer->address (slot-ref db 'this)) name))))
    531     (cond
    532      (((foreign-lambda* sqlite3:status
    533                         ((sqlite3:database db) (c-string name) (int n) (scheme-object qn))
    534 #<<END
     514  (let ([qn (object-evict (list (pointer->address (slot-ref db 'this)) name))])
     515    (cond [((foreign-lambda* sqlite3:status
     516                             ((sqlite3:database db)
     517                              (c-string name) (int n) (scheme-object qn))
     518#<<EOS
    535519        return(sqlite3_create_function(db, name, n, SQLITE_UTF8,
    536520                                       (void *)qn,
     
    541525                                       ((void (*)(sqlite3_context *))
    542526                                         &chicken_sqlite3_final_stub)));
    543 END
    544        )
    545        db name n qn)
    546       => (lambda (s)
    547            (object-release qn)
    548            ((signal-sqlite3-error
    549               'sqlite3:define-function db name n step-proc seed final-proc)
    550             s)))
    551      (else
    552       (call-with/synch *sqlite3:functions*
    553         (cut hash-table-tree-set! <> qn (vector qn step-proc seed final-proc))) ) ) ) )
     527EOS
     528            )
     529            db name n qn)
     530           => (lambda (s)
     531                (object-release qn)
     532                ((abort-sqlite3-error
     533                   'sqlite3:define-function db name n step-proc seed final-proc) s)) ]
     534          [else
     535           (call-with/synch *sqlite3:functions*
     536        (cute hash-table-tree-set! <> qn (vector qn step-proc seed final-proc))) ] ) ) )
    554537
    555538;;; Database interface
     
    562545(define (sqlite3:open path)
    563546  (check-sqlite3-type 'sqlite3:open path <string>)
    564   (let-location ((db c-pointer))
    565     (cond
    566      (((foreign-lambda sqlite3:status "sqlite3_open"
    567                                       nonnull-c-string (c-pointer sqlite3:database))
    568        (sqlite3:resolve-pathname path) (location db))
    569       => (signal-sqlite3-error 'sqlite3:open #f path))
    570      (else
    571       (make <sqlite3:database> 'this db) ) ) ) )
     547  (let-location ([db c-pointer])
     548    (cond [((foreign-lambda sqlite3:status "sqlite3_open"
     549                                           nonnull-c-string (c-pointer sqlite3:database))
     550            (sqlite3:resolve-pathname path) #$db)
     551           => (abort-sqlite3-error 'sqlite3:open #f path) ]
     552          [else
     553           (make <sqlite3:database> 'this db) ] ) ) )
    572554
    573555;; Set a timeout until a busy error is thrown
    574556(define (sqlite3:set-busy-timeout! db #!optional (ms 0))
    575557  (check-sqlite3-type 'sqlite3:set-busy-timeout! db <sqlite3:database>)
    576   (cond
    577    (((foreign-lambda sqlite3:status "sqlite3_busy_timeout" sqlite3:database int) db ms)
    578     => (signal-sqlite3-error 'sqlite3:set-busy-timeout! db db ms))) )
     558  (cond [((foreign-lambda sqlite3:status "sqlite3_busy_timeout" sqlite3:database int) db ms)
     559         => (abort-sqlite3-error 'sqlite3:set-busy-timeout! db db ms) ] ) )
    579560
    580561;; Cancel any running database operation as soon as possible
     
    603584(define-generic sqlite3:finalize!)
    604585(define-method (sqlite3:finalize! (db <sqlite3:database>))
    605   (cond
    606    ((not (slot-ref db 'this))
    607     (void))
    608    (((foreign-lambda sqlite3:status "sqlite3_close" sqlite3:database) db)
    609     => (signal-sqlite3-error 'sqlite3:finalize! db db))
    610    (else
    611     (let ((id (pointer->address (slot-ref db 'this)))
    612           (release-qns (lambda (_ info) (object-release (vector-ref info 0)))))
    613       (call-with/synch *sqlite3:collations*
    614         (cut hash-table-tree-clear! <> id release-qns))
    615       (call-with/synch *sqlite3:functions*
    616         (cut hash-table-tree-clear! <> id release-qns)) )
    617     (slot-set! db 'this #f) ) ) )
     586  (cond [(not (slot-ref db 'this))
     587         (void) ]
     588        [((foreign-lambda sqlite3:status "sqlite3_close" sqlite3:database) db)
     589         => (abort-sqlite3-error 'sqlite3:finalize! db db) ]
     590        [else
     591         (let ([id (pointer->address (slot-ref db 'this))]
     592               [release-qns (lambda (_ info) (object-release (vector-ref info 0)))] )
     593           (call-with/synch *sqlite3:collations*
     594             (cute hash-table-tree-clear! <> id release-qns))
     595           (call-with/synch *sqlite3:functions*
     596             (cute hash-table-tree-clear! <> id release-qns)) )
     597           (slot-set! db 'this #f) ] ) )
    618598
    619599;;; Statement interface
     
    623603  (check-sqlite3-type 'sqlite3:prepare db <sqlite3:database>)
    624604  (check-sqlite3-type 'sqlite3:prepare sql <string>)
    625   (let-location ((stmt c-pointer) (tail c-string))
    626     (cond
    627      (((foreign-lambda sqlite3:status "sqlite3_prepare"
    628                                       sqlite3:database scheme-pointer int
    629                                       (c-pointer sqlite3:statement)
    630                                       (c-pointer (const c-string)))
    631        db sql (string-length sql) (location stmt) (location tail))
    632       => (signal-sqlite3-error 'sqlite3:prepare db db sql))
    633      (else
    634       (values
    635        (make <sqlite3:statement> 'this stmt 'database db 'sql sql)
    636        tail) ) ) ) )
     605  (let-location ([stmt c-pointer] [tail c-string])
     606    (cond [((foreign-lambda sqlite3:status "sqlite3_prepare"
     607                                            sqlite3:database scheme-pointer int
     608                                            (c-pointer sqlite3:statement)
     609                                            (c-pointer (const c-string)))
     610            db sql (string-length sql) #$stmt #$tail)
     611           => (abort-sqlite3-error 'sqlite3:prepare db db sql) ]
     612          [else
     613           (values
     614            (make <sqlite3:statement> 'this stmt 'database db 'sql sql)
     615            tail) ] ) ) )
    637616
    638617;; Recompile an existing statement and transfer all bindings
    639618(define (sqlite3:repair! stmt)
    640619  (check-sqlite3-type 'sqlite3:repair! stmt <sqlite3:statement>)
    641   (let ((fresh (sqlite3:prepare
    642                 (slot-ref stmt 'database) (slot-ref stmt 'sql))))
     620  (let ([fresh (sqlite3:prepare
     621                (slot-ref stmt 'database) (slot-ref stmt 'sql))])
    643622    (dynamic-wind
    644623        noop
    645624        (lambda ()
    646           (let ((old (slot-ref stmt 'this))
    647                 (new (slot-ref fresh 'this)))
    648             (cond
    649              (((foreign-lambda sqlite3:status "sqlite3_transfer_bindings"
    650                                               c-pointer c-pointer)
    651                old new)
    652               => (signal-sqlite3-error 'sqlite3:repair! (slot-ref stmt 'database) stmt))
    653              (else
    654               (slot-set! stmt 'this new)
    655               (slot-set! fresh 'this old)))))
     625          (let ([old (slot-ref stmt 'this)]
     626                [new (slot-ref fresh 'this)] )
     627            (cond [((foreign-lambda sqlite3:status "sqlite3_transfer_bindings"
     628                                             c-pointer c-pointer)
     629              old new)
     630             => (abort-sqlite3-error 'sqlite3:repair! (slot-ref stmt 'database) stmt) ]
     631            [else
     632             (slot-set! stmt 'this new)
     633             (slot-set! fresh 'this old) ] ) ) )
    656634        (lambda ()
    657635          (sqlite3:finalize! fresh))) ) )
     
    660638;; (define-generic sqlite3:finalize!)
    661639(define-method (sqlite3:finalize! (stmt <sqlite3:statement>))
    662   (cond
    663    ((not (slot-ref stmt 'this))
    664     (void))
    665    (((foreign-lambda sqlite3:status "sqlite3_finalize" sqlite3:statement) stmt)
    666     => (signal-sqlite3-error 'sqlite3:finalize! (slot-ref stmt 'database) stmt))
    667    (else
    668     (slot-set! stmt 'this #f) ) ) )
     640  (cond [(not (slot-ref stmt 'this))
     641         (void) ]
     642        [((foreign-lambda sqlite3:status "sqlite3_finalize" sqlite3:statement) stmt)
     643         => (abort-sqlite3-error 'sqlite3:finalize! (slot-ref stmt 'database) stmt) ]
     644        [else
     645         (slot-set! stmt 'this #f) ] ) )
    669646
    670647;; Reset an existing statement to process it again
     
    674651(define (sqlite3:reset! stmt)
    675652  (check-sqlite3-type 'sqlite3:reset! stmt <sqlite3:statement>)
    676   (cond
    677    ((sqlite3_reset stmt)
    678     => (signal-sqlite3-error 'sqlite3:reset! (slot-ref stmt 'database) stmt))) )
     653  (cond [(sqlite3_reset stmt)
     654         => (abort-sqlite3-error 'sqlite3:reset! (slot-ref stmt 'database) stmt) ] ) )
    679655
    680656;; Get number of bindable parameters
     
    687663(define (sqlite3:bind-parameter-index stmt name)
    688664  (check-sqlite3-type 'sqlite3:bind-parameter-index stmt <sqlite3:statement>)
    689   (let ((i ((foreign-lambda int "sqlite3_bind_parameter_index"
     665  (let ([i ((foreign-lambda int "sqlite3_bind_parameter_index"
    690666                                sqlite3:statement nonnull-c-string)
    691             stmt name)))
     667            stmt name)])
    692668    (if (zero? i)
    693669        #f
     
    697673(define (sqlite3:bind-parameter-name stmt i)
    698674  (check-sqlite3-type 'sqlite3:bind-parameter-name stmt <sqlite3:statement>)
    699   ((foreign-lambda c-string "sqlite3_bind_parameter_name" sqlite3:statement int) stmt (add1 i)) )
     675  ((foreign-lambda c-string "sqlite3_bind_parameter_name" sqlite3:statement int)
     676   stmt (add1 i)) )
    700677
    701678;; Bind data as parameters to an existing statement
     
    704681(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    705682                              (v <blob>))
    706   (cond
    707    (((foreign-lambda* sqlite3:status
    708                       ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
    709       "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
    710      stmt (add1 i) v (blob-size v))
    711     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))) )
     683  (cond [((foreign-lambda* sqlite3:status
     684                           ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
     685           "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
     686          stmt (add1 i) v (blob-size v))
     687         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    712688
    713689; Deprecated
    714690(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    715691                              (v <byte-vector>))
    716   (cond
    717    (((foreign-lambda* sqlite3:status
    718                       ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
    719       "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
    720      stmt (add1 i) v (byte-vector-length v))
    721     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))) )
     692  (cond [((foreign-lambda* sqlite3:status
     693                           ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
     694           "return(sqlite3_bind_blob(stmt, i, v, n, SQLITE_TRANSIENT));")
     695          stmt (add1 i) v (byte-vector-length v))
     696         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
     697
     698(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
     699                              (v <boolean>))
     700  (cond [((foreign-lambda sqlite3:status "sqlite3_bind_int"
     701                                         sqlite3:statement int int)
     702          stmt (add1 i) (or (and v 1) 0))
     703         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    722704
    723705(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    724706                              (v <exact>))
    725   (cond
    726    (((foreign-lambda sqlite3:status "sqlite3_bind_int"
    727                                     sqlite3:statement int int)
    728      stmt (add1 i) v)
    729     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))))
     707  (cond [((foreign-lambda sqlite3:status "sqlite3_bind_int"
     708                                         sqlite3:statement int int)
     709          stmt (add1 i) v)
     710         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    730711
    731712(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    732713                              (v <number>))
    733   (cond
    734    (((foreign-lambda sqlite3:status "sqlite3_bind_double"
    735                                     sqlite3:statement int double)
    736      stmt (add1 i) v)
    737     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))) )
     714  (cond [((foreign-lambda sqlite3:status "sqlite3_bind_double"
     715                                          sqlite3:statement int double)
     716          stmt (add1 i) v)
     717         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    738718
    739719(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    740720                              (v <string>))
    741   (cond
    742    (((foreign-lambda* sqlite3:status
    743                       ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
    744       "return(sqlite3_bind_text(stmt, i, v, n, SQLITE_TRANSIENT));")
    745      stmt (add1 i) v (string-length v))
    746     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v))))
    747 
    748 (define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>)
    749                               (v <void>))
    750   (cond
    751    (((foreign-lambda sqlite3:status "sqlite3_bind_null" sqlite3:statement int) stmt (add1 i))
    752     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i))) )
     721  (cond [((foreign-lambda* sqlite3:status
     722                           ((sqlite3:statement stmt) (int i) (scheme-pointer v) (int n))
     723           "return(sqlite3_bind_text(stmt, i, v, n, SQLITE_TRANSIENT));")
     724          stmt (add1 i) v (string-length v))
     725         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i v) ] ) )
    753726
    754727(define-method (sqlite3:bind! (stmt <sqlite3:statement>) (i <exact>))
    755   (cond
    756    (((foreign-lambda sqlite3:status "sqlite3_bind_null" sqlite3:statement int) stmt (add1 i))
    757     => (signal-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i))) )
     728  (cond [((foreign-lambda sqlite3:status "sqlite3_bind_null" sqlite3:statement int)
     729         stmt (add1 i))
     730         => (abort-sqlite3-error 'sqlite3:bind! (slot-ref stmt 'database) stmt i) ] ) )
    758731
    759732; Helper
     733
    760734(define (bind-parameters! loc stmt params)
    761735  (sqlite3:reset! stmt)
    762   (let ((cnt (sqlite3:bind-parameter-count stmt)))
    763     (unless (= cnt (length params))
    764       (abort
    765        (make-composite-condition
    766         (make-exn-condition loc "too few parameters" cnt params)
    767         (make-property-condition 'arity)
    768         (make-sqlite3-condition 'error))) )
    769     (for-each (cut sqlite3:bind! stmt <> <>) (iota cnt) params) ) )
     736  (let ([cnt (sqlite3:bind-parameter-count stmt)])
     737    (if (= cnt (length params))
     738        (unless (zero? cnt)
     739          (for-each
     740           (lambda (i v)
     741             (if (eq? <void> v)
     742                 (sqlite3:bind! stmt i)
     743                 (sqlite3:bind! stmt i v) ) )
     744           (iota cnt) params) )
     745        (abort
     746         (make-composite-condition
     747          (make-exn-condition
     748           loc
     749           (conc "bad parameter count - received " (length params) " but expected " cnt))
     750          (make-property-condition 'arity)
     751          (make-sqlite3-condition 'error))) ) ) )
    770752
    771753(define (sqlite3:bind-parameters! stmt . params)
     
    777759  (check-sqlite3-type 'sqlite3:step! stmt <sqlite3:statement>)
    778760  (let retry ()
    779     (let ((s ((foreign-safe-lambda
     761    (let ([s ((foreign-safe-lambda
    780762               sqlite3:status "sqlite3_step" sqlite3:statement)
    781               stmt)))
     763              stmt)])
    782764      (case s
    783         ((row) #t)
    784         ((done) #f)
    785         ((error)
    786          (let ((s (sqlite3_reset stmt)))
     765        [(row)
     766         #t ]
     767        [(done)
     768         #f ]
     769        [(error)
     770         (let ([s (sqlite3_reset stmt)])
    787771           (case s
    788              ((schema)
     772             [(schema)
    789773              (sqlite3:repair! stmt)
    790               (retry))
    791              (else
    792               ((signal-sqlite3-error
    793                 'sqlite3:step! (slot-ref stmt 'database) stmt) s)))))
    794         (else
    795          ((signal-sqlite3-error 'sqlite3:step! (slot-ref stmt 'database) stmt) s) ) ) ) ) )
     774              (retry) ]
     775             [else
     776              ((abort-sqlite3-error 'sqlite3:step! (slot-ref stmt 'database) stmt) s) ] ) ) ]
     777        [else
     778         ((abort-sqlite3-error 'sqlite3:step! (slot-ref stmt 'database) stmt) s) ] ) ) ) )
    796779
    797780;; Retrieve information from a prepared/stepped statement
     
    815798(define (sqlite3:column-data stmt i)
    816799  (case (sqlite3:column-type stmt i)
    817     ((integer)
    818      ((foreign-lambda integer "sqlite3_column_double" sqlite3:statement int) stmt i))
    819     ((float)
    820      ((foreign-lambda double "sqlite3_column_double" sqlite3:statement int) stmt i))
    821     ((text)
     800    [(integer)
     801     ((foreign-lambda integer "sqlite3_column_double" sqlite3:statement int) stmt i) ]
     802    [(float)
     803     ((foreign-lambda double "sqlite3_column_double" sqlite3:statement int) stmt i) ]
     804    [(text)
    822805     ((foreign-primitive scheme-object ((sqlite3:statement stmt) (int i))
    823806       "int n = sqlite3_column_bytes(stmt, i);"
    824807       "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    825808       "return(C_string(&s, n, (char *)sqlite3_column_text(stmt, i)));")
    826       stmt i))
    827     ((blob)
     809      stmt i) ]
     810    [(blob)
    828811     ((foreign-primitive scheme-object ((sqlite3:statement stmt) (int i))
    829812       "int n = sqlite3_column_bytes(stmt, i);"
    830813       "C_word *s = C_alloc(C_SIZEOF_STRING(n));"
    831814       "return(C_bytevector(&s, n, (char *)sqlite3_column_blob(stmt, i)));")
    832       stmt i))
    833     (else
    834      sqlite3:null-value ) ) )
     815      stmt i) ]
     816    [else
     817     <void> ] ) )
    835818
    836819;;; Easy statement interface
     
    840823(define (sqlite3:call-with-temporary-statements proc db . sqls)
    841824  (check-sqlite3-type 'sqlite3:call-with-temporary-statements db <sqlite3:database>)
    842   (let ((stmts #f))
     825  (let ([stmts #f])
    843826    (dynamic-wind
    844827        (lambda ()
    845828          (unless stmts
    846             (set! stmts (map (cut sqlite3:prepare db <>) sqls))))
     829            (set! stmts (map (cute sqlite3:prepare db <>) sqls))))
    847830        (lambda ()
    848831          (apply proc stmts))
     
    857840  (bind-parameters! 'sqlite3:exec stmt params)
    858841  (while (sqlite3:step! stmt))
    859   sqlite3:null-value )
     842  (void) )
    860843
    861844(define-method (sqlite3:exec (db <sqlite3:database>) (sql <string>) . params)
    862845  (sqlite3:call-with-temporary-statements
    863    (cut apply sqlite3:exec <> params)
     846   (cute apply sqlite3:exec <> params)
    864847   db sql) )
    865848
     
    883866  (bind-parameters! 'sqlite3:first-result stmt params)
    884867  (if (sqlite3:step! stmt)
    885       (let ((r (sqlite3:column-data stmt 0)))
     868      (let ([r (sqlite3:column-data stmt 0)])
    886869        (sqlite3:reset! stmt)
    887870        r )
    888       (signal (make-no-data-condition 'sqlite3:first-result stmt params)) ) )
     871      (abort (make-no-data-condition 'sqlite3:first-result stmt params)) ) )
    889872
    890873(define-method (sqlite3:first-result
    891874                (db <sqlite3:database>) (sql <string>) . params)
    892875  (sqlite3:call-with-temporary-statements
    893    (cut apply sqlite3:first-result <> params)
     876   (cute apply sqlite3:first-result <> params)
    894877   db sql) )
    895878
     
    900883  (bind-parameters! 'sqlite3:first-row stmt params)
    901884  (if (sqlite3:step! stmt)
    902       (map (cut sqlite3:column-data stmt <>)
     885      (map (cute sqlite3:column-data stmt <>)
    903886           (iota (sqlite3:column-count stmt)))
    904       (signal (make-no-data-condition 'sqlite3:first-row stmt params)) ) )
     887      (abort (make-no-data-condition 'sqlite3:first-row stmt params)) ) )
    905888
    906889(define-method (sqlite3:first-row
    907890                (db <sqlite3:database>) (sql <string>) . params)
    908891  (sqlite3:call-with-temporary-statements
    909    (cut apply sqlite3:first-row <> params)
     892   (cute apply sqlite3:first-row <> params)
    910893   db sql))
    911894
     
    915898(define (%fold-row loc proc stmt init params)
    916899  (bind-parameters! loc stmt params)
    917   (let ((cl (iota (sqlite3:column-count stmt))))
    918     (let loop ((acc init))
     900  (let ([cl (iota (sqlite3:column-count stmt))])
     901    (let loop ([acc init])
    919902      (if (sqlite3:step! stmt)
    920           (loop (apply proc acc (map (cut sqlite3:column-data stmt <>) cl)))
     903          (loop (apply proc acc (map (cute sqlite3:column-data stmt <>) cl)))
    921904          acc ) ) ) )
    922905
     
    932915                                 (init <object>) . params)
    933916  (sqlite3:call-with-temporary-statements
    934    (cut apply sqlite3:fold-row proc <> init params)
     917   (cute apply sqlite3:fold-row proc <> init params)
    935918   db sql) )
    936919
     
    952935                                     (sql <string>) . params)
    953936  (sqlite3:call-with-temporary-statements
    954    (cut apply sqlite3:for-each-row proc <> params)
     937   (cute apply sqlite3:for-each-row proc <> params)
    955938   db sql) )
    956939
     
    971954                                (sql <string>) . params)
    972955  (sqlite3:call-with-temporary-statements
    973    (cut apply sqlite3:map-row proc <> params)
     956   (cute apply sqlite3:map-row proc <> params)
    974957   db sql) )
    975958
     
    989972                          type)
    990973      (make-property-condition 'type))) )
    991   (let ((success? #f))
     974  (let ([success? #f])
    992975    (dynamic-wind
    993976        (lambda ()
     
    1009992(define sqlite3:library-version
    1010993  (foreign-lambda c-string "sqlite3_libversion") )
     994
     995;; Return a Scheme boolean for the usual SQLite column boolean values
     996(define (sqlite3:boolean-value v)
     997  (cond [(string? v)
     998         (or (string-ci=? "Y" v)
     999             (string-ci=? "YES" v)
     1000             (string=? "Yes" v)) ]
     1001        [(and (integer? v) (exact? v))
     1002         (not (zero? v)) ]
     1003        [else
     1004          #f ] ) )
  • release/3/sqlite3/trunk/sqlite3.setup

    r8020 r8688  
    1212  `(,so-file
    1313    "sqlite3.html" "egg.jpg")
    14   '((version "2.0.4")
     14  '((version "2.0.5")
    1515    (documentation "sqlite3.html")))
  • release/3/sqlite3/trunk/tests/sqlite3-test.scm

    r8020 r8688  
    1111;;;
    1212
    13 ;; This is needed due to a testbase bug!
    14 
    15 (define-for-syntax (SQL-QUERY . lines)
    16   (apply string-append (intersperse lines "\n")) )
    17 
    18 ;;;
     13;; SQL Source
    1914
    2015(define *mak-source-table-sql*
    21   (SQL-QUERY
     16  (MULTILINE-STRING
    2217    "CREATE TABLE IF NOT EXISTS source ("
    2318    "  oid INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,"
    24     "  dir TEXT,"
    25     "  fil TEXT NOT NULL,"
    26     "  ext TEXT,"
     19    "  dir VARCHAR,"
     20    "  fil VARCHAR NOT NULL,"
     21    "  ext VARCHAR,"
     22    "  cnt INTEGER,"
     23    "  foo INTEGER,"
    2724    "  UNIQUE (dir, fil, ext) ON CONFLICT ROLLBACK"
    2825    ");"))
    2926
    3027(define *ins-source-entry-sql*
    31   (SQL-QUERY
    32     "INSERT INTO source (oid, dir, fil, ext)"
    33     "  VALUES (NULL, ?001, ?002, ?003);"))
     28  (MULTILINE-STRING
     29    "INSERT INTO source (oid, dir, fil, ext, cnt, foo)"
     30    "  VALUES (NULL, ?001, ?002, ?003, ?004, ?005);"))
    3431
    3532(define *sel-maximum-dir-length-sql*
    36   (SQL-QUERY
     33  (MULTILINE-STRING
    3734    "SELECT Max(length(source.dir)) FROM source;"))
    3835
     
    4542(define-test string-queries-test "String Queries"
    4643  (initial
    47     (define db)
    48   )
     44    (define dbpn "sqlite3test-strq.db")
     45    (define db) )
    4946
    5047  (setup (delete-file* *db-name*))
     48  #; ; Leave so "sqlite3" command can be used
    5149  (teardown (delete-file* *db-name*))
    5250
     
    5553  (expect-success (sqlite3:exec db *mak-source-table-sql*))
    5654
    57   (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory1" "file1" "ext1"))
    58   (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory10" "file10" "ext10"))
    59   (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory1000" "file1000" "ext1000"))
    60   (expect-success (sqlite3:exec db *ins-source-entry-sql* "" "" ""))
     55  (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory1" "file1" "ext1" 1 <void>))
     56  (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory10" "file10" "ext10" 2 <void>))
     57  (expect-success (sqlite3:exec db *ins-source-entry-sql* "directory1000" "file1000" "ext1000" 3 <void>))
     58  (expect-success (sqlite3:exec db *ins-source-entry-sql* "" "" "" 4 <void>))
    6159
    6260  (expect-eqv 13 (sqlite3:first-result db *sel-maximum-dir-length-sql*))
     
    6967(define-test statement-queries-test "Statement Queries"
    7068  (initial
    71     (define dbpn "sqlit3test.db")
     69    (define dbpn "sqlite3test-stmtq.db")
    7270    (define db)
    7371    (define mak-source-table)
    7472    (define ins-source-entry)
    75     (define sel-maximum-dir-length)
    76   )
     73    (define sel-maximum-dir-length) )
    7774
    7875  (setup (delete-file* dbpn))
     76  #; ; Leave so "sqlite3" command can be used
    7977  (teardown (delete-file* dbpn))
    8078
     
    8684
    8785  (expect-set! ins-source-entry (sqlite3:prepare db *ins-source-entry-sql*))
     86  (expect-eqv 5 (sqlite3:bind-parameter-count ins-source-entry))
    8887  (expect-set! sel-maximum-dir-length (sqlite3:prepare db *sel-maximum-dir-length-sql*))
     88  (expect-eqv 0 (sqlite3:bind-parameter-count sel-maximum-dir-length))
    8989
    90   (expect-success (sqlite3:exec ins-source-entry "directory1" "file1" "ext1"))
    91   (expect-success (sqlite3:exec ins-source-entry "directory10" "file10" "ext10"))
    92   (expect-success (sqlite3:exec ins-source-entry "directory1000" "file1000" "ext1000"))
    93   (expect-success (sqlite3:exec ins-source-entry "" "" ""))
     90  ;#<condition: (exn type) ((exn . message) "call of non-procedure" (exn . arguments) (4) (exn . location) #f)>
     91  (expect-failure (warn "This shouldn't occur: should be an arity error")
     92   (sqlite3:exec ins-source-entry "directory1" "file1" "ext1" 11))
     93
     94  (expect-success (sqlite3:exec ins-source-entry "directory1" "file1" "ext1" 11 <void>))
     95  (expect-success (sqlite3:exec ins-source-entry "directory10" "file10" "ext10" 12 <void>))
     96  (expect-success (sqlite3:exec ins-source-entry "directory1000" "file1000" "ext1000" 13 <void>))
     97  (expect-success (sqlite3:exec ins-source-entry "" "" "" 14 <void>))
    9498
    9599  (expect-eqv 13 (sqlite3:first-result sel-maximum-dir-length))
Note: See TracChangeset for help on using the changeset viewer.