Changeset 15423 in project


Ignore:
Timestamp:
08/13/09 04:47:09 (10 years ago)
Author:
Thomas Chust
bzr:base-revision:
chust@web.de-20090807084745-n1gf84i4nk0xwd62
bzr:committer:
Thomas Chust <chust@web.de>
bzr:file-ids:

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

chust@web.de-20090812224645-3rapn9yhqrf8ejsr
bzr:repository-uuid:
fca3e652-9b03-0410-8d7b-ac86a6ce46c4
bzr:revision-id:
chust@web.de-20090813030331-91naxc6zk11gsksq
bzr:revno:
24
bzr:revprop:branch-nick:
release/4/sqlite3/trunk
bzr:root:
release/4/sqlite3/trunk
bzr:text-parents:

Makefile chust@web.de-20090807084543-0k93k145degvpz8r
doc.scm chust@web.de-20090812185541-no3uxu74n4nzlycc
sqlite3.html chust@web.de-20090812185541-no3uxu74n4nzlycc
sqlite3.scm chust@web.de-20090812192958-3lpqpd32ykm9s4rb
sqlite3.setup chust@web.de-20090807084543-0k93k145degvpz8r
tests/run.scm chust@web.de-20090812155541-z305916bq0gu4bv6
bzr:text-revisions:

Makefile chust@web.de-20090812224645-3rapn9yhqrf8ejsr
doc.scm chust@web.de-20090812224317-n00i5xc16i2vkdv7
sqlite3.html chust@web.de-20090812224317-n00i5xc16i2vkdv7
sqlite3.scm chust@web.de-20090812224443-0cf9nydbnjbog1i7
sqlite3.setup chust@web.de-20090812224645-3rapn9yhqrf8ejsr
tests/run.scm chust@web.de-20090812190752-dgc8qkkorg5500qf
bzr:timestamp:
2009-08-13 05:03:31.085000038 +0200
bzr:user-agent:
bzr1.17+bzr-svn0.6.3
svn:original-date:
2009-08-13T03:03:31.085000Z
Message:

[sqlite3] Modernization of C API use, support for automatic statement finalization.

Location:
release/4/sqlite3/trunk
Files:
6 edited

Legend:

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

    r15347 r15423  
    1212
    1313NAME=sqlite3
    14 VERSION=3.3.1
     14VERSION=3.5.0
    1515
    1616.PHONY: all clean
  • release/4/sqlite3/trunk/doc.scm

    r15347 r15423  
    4949          (tr (td (tt "misuse")) (td "Library used incorrectly "))
    5050          (tr (td (tt "no-lfs")) (td "Uses OS features not supported on host "))
    51           (tr (td (tt "authorization")) (td " Authorization denied"))
     51          (tr (td (tt "authorization")) (td "Authorization denied"))
    5252          #;(tr (td (tt "row")) (td (tt "step!") " has another row ready "))
    5353          (tr (td (tt "done")) (td (tt "step!") " has finished executing, so no further data is ready")))))
     
    123123          (p "This function always returns a number and never throws an exception."))
    124124
    125         (procedure ("(finalize! DATABASE-OR-STATEMENT) " (& "rArr") " VOID")
     125        (definition
     126          (signatures
     127            (signature "procedure" ("(finalize! DATABASE [FINALIZE-STATEMENTS?]) " (& "rArr") " VOID"))
     128            (signature "procedure" ("(finalize! STATEMENT) " (& "rArr") " VOID")))
    126129          (p "Closes the given database or finalizes the given statement.")
    127           (p "Every statement must be finalized to free its resources and discard it before the database itself can be finalized.")))
     130          (p "Every statement must be finalized to free its resources and discard it before the database itself can be finalized. However, if " (tt "FINALIZE-STATEMENTS?") " is not " (tt "#f") ", finalizing the database triggers automatic finalization of all statements first. " (tt "FINALIZE-STATEMENTS?") " defaults to " (tt "#f") ".")
     131          (p "Note that both the SQLite3 egg and the SQLite3 library itself try to detect the use of already finalized statement or database handles in API calls, but the detection is not always possible and you might crash the program by using an already finalized handle.")))
    128132
    129133      (subsection "Managing statements"
     
    132136          (p "Compiles the first SQL statement in " (tt "SQL") " and returns a statement and the tail of the SQL code, which was not compiled (or an empty string)."))
    133137
    134         (procedure ("(repair! STATEMENT) " (& "rArr") " VOID")
    135           (p "Recompiles the SQL code used to create the statement, transfers all existing bindings from the old statement handle to the new one and destructively modifies " (tt "STATEMENT") " to point to the new statement handle.")
    136           (p "If the operation is successful, the old handle is finalized, in case of error, the new handle is finalized and the old one stays untouched.")
    137           (p "Usually you should not have to call this routine by hand. It is invoked by " (tt "step!") " to automagically repair a stale statement handle after a database schema change."))
     138        (procedure ("(source-sql STATEMENT) " (& "rArr") " STRING")
     139          (p "Retrieves the SQL source code of a statement."))
    138140
    139141        (procedure ("(column-count STATEMENT) " (& "rArr") " CARDINAL-INTEGER")
     
    273275
    274276    (history
     277      (version "3.5.0" "Switched to less error prone internal C API")
     278      (version "3.4.0" "Added optional automatic statement finalization when a database is finalized")
    275279      (version "3.3.1" "Added bindings for database memory statistics")
    276280      (version "3.3.0" "Switched to using " (tt "(sql-null)") " for " (tt "NULL") " values")
  • release/4/sqlite3/trunk/sqlite3.html

    r15347 r15423  
    245245<tr>
    246246<td><tt>authorization</tt></td>
    247 <td> Authorization denied</td></tr>
     247<td>Authorization denied</td></tr>
    248248<tr>
    249249<td><tt>done</tt></td>
     
    320320<p>Returns the row ID of the last row inserted in <tt>db</tt>.</p>
    321321<p>This function always returns a number and never throws an exception.</p></dd>
    322 <dt class="definition"><strong>procedure:</strong> (finalize! DATABASE-OR-STATEMENT) &rArr; VOID</dt>
     322<dt class="definition"><strong>procedure:</strong> (finalize! DATABASE [FINALIZE-STATEMENTS?]) &rArr; VOID
     323<br /><strong>procedure:</strong> (finalize! STATEMENT) &rArr; VOID</dt>
    323324<dd>
    324325<p>Closes the given database or finalizes the given statement.</p>
    325 <p>Every statement must be finalized to free its resources and discard it before the database itself can be finalized.</p></dd></div>
     326<p>Every statement must be finalized to free its resources and discard it before the database itself can be finalized. However, if <tt>FINALIZE-STATEMENTS?</tt> is not <tt>#f</tt>, finalizing the database triggers automatic finalization of all statements first. <tt>FINALIZE-STATEMENTS?</tt> defaults to <tt>#f</tt>.</p>
     327<p>Note that both the SQLite3 egg and the SQLite3 library itself try to detect the use of already finalized statement or database handles in API calls, but the detection is not always possible and you might crash the program by using an already finalized handle.</p></dd></div>
    326328<div class="subsection">
    327329<h4>Managing statements</h4>
     
    329331<dd>
    330332<p>Compiles the first SQL statement in <tt>SQL</tt> and returns a statement and the tail of the SQL code, which was not compiled (or an empty string).</p></dd>
    331 <dt class="definition"><strong>procedure:</strong> (repair! STATEMENT) &rArr; VOID</dt>
    332 <dd>
    333 <p>Recompiles the SQL code used to create the statement, transfers all existing bindings from the old statement handle to the new one and destructively modifies <tt>STATEMENT</tt> to point to the new statement handle.</p>
    334 <p>If the operation is successful, the old handle is finalized, in case of error, the new handle is finalized and the old one stays untouched.</p>
    335 <p>Usually you should not have to call this routine by hand. It is invoked by <tt>step!</tt> to automagically repair a stale statement handle after a database schema change.</p></dd>
     333<dt class="definition"><strong>procedure:</strong> (source-sql STATEMENT) &rArr; STRING</dt>
     334<dd>
     335<p>Retrieves the SQL source code of a statement.</p></dd>
    336336<dt class="definition"><strong>procedure:</strong> (column-count STATEMENT) &rArr; CARDINAL-INTEGER</dt>
    337337<dd>
     
    486486<h3>Version</h3>
    487487<ul>
     488<li>3.5.0 Switched to less error prone internal C API</li>
     489<li>3.4.0 Added optional automatic statement finalization when a database is finalized</li>
    488490<li>3.3.1 Added bindings for database memory statistics</li>
    489491<li>3.3.0 Switched to using <tt>(sql-null)</tt> for <tt>NULL</tt> values</li>
  • release/4/sqlite3/trunk/sqlite3.scm

    r15347 r15423  
    2121    ; These may have to be changed if definitions are added,
    2222    ; removed or reordered:
    23     sqlite3#g166 sqlite3#g366 sqlite3#g484 sqlite3#g570)
     23    sqlite3#g166 sqlite3#g366 sqlite3#g484 sqlite3#g566)
    2424  (bound-to-procedure
    2525    ##sys#expand-home-path
     
    4848    finalize!
    4949    prepare
    50     repair!
     50    source-sql
    5151    reset!
    5252    bind-parameter-count
     
    175175
    176176(define-record-type sqlite3:statement
    177   (make-statement ptr database sql)
     177  (make-statement ptr database)
    178178  statement?
    179179  (ptr statement-ptr statement-ptr-set!)
    180   (database statement-database)
    181   (sql statement-sql))
     180  (database statement-database))
    182181
    183182(define-record-printer (sqlite3:statement stmt out)
    184183  (display
    185184    (if (statement-ptr stmt)
    186       (sprintf "#<sqlite3:statement sql=~s>" (statement-sql stmt))
     185      (sprintf "#<sqlite3:statement sql=~s>" (source-sql stmt))
    187186      "#<sqlite3:statement zombie>")
    188187    out))
     
    193192  (nonnull-c-pointer "sqlite3_stmt")
    194193  statement-ptr
    195   (cut make-statement <> #f #f))
     194  (cut make-statement <> #f))
    196195
    197196;;; Helpers
     
    555554(define (open-database path)
    556555  (check-string 'open-database path)
    557   (let-location ([db c-pointer])
     556  (let-location ([db sqlite3:database])
    558557    (cond
    559558      [((foreign-lambda sqlite3:status "sqlite3_open"
     
    562561        => (abort-sqlite3-error 'open-database #f path)]
    563562      [else
    564         (make-database db #f)])))
     563        db])))
    565564
    566565;; Set application busy handler.  Does not use a callback, so it is safe
     
    618617
    619618;; Close a database or statement handle
     619(define sqlite3_finalize
     620  (foreign-lambda sqlite3:status "sqlite3_finalize" nonnull-c-pointer))
     621
     622(define sqlite3_next_stmt
     623  (foreign-lambda c-pointer "sqlite3_next_stmt" sqlite3:database c-pointer))
     624
    620625(define finalize!
    621   (match-lambda
    622     [(? database? db)
     626  (match-lambda*
     627    [((? database? db) . finalize-statements?)
    623628      (cond
    624629        [(not (database-ptr db))
    625630          (void)]
    626         [((foreign-safe-lambda sqlite3:status "sqlite3_close" sqlite3:database) db)
     631        [(let loop ([stmt
     632                      (and
     633                        (optional finalize-statements? #f)
     634                        (sqlite3_next_stmt db #f))])
     635           (if stmt
     636             (or (sqlite3_finalize stmt) (loop (sqlite3_next_stmt db stmt)))
     637             ((foreign-safe-lambda sqlite3:status "sqlite3_close" sqlite3:database) db)))
    627638          => (abort-sqlite3-error 'finalize! db db)]
    628639        [else
    629640          (let ([id (pointer->address (database-ptr db))]
    630               [release-qns (lambda (_ info) (object-release (vector-ref info 0)))])
     641                [release-qns (lambda (_ info) (object-release (vector-ref info 0)))])
    631642            (call-with/synch *collations*
    632643              (cute hash-table-tree-clear! <> id release-qns))
    633644            (call-with/synch *functions*
    634               (cute hash-table-tree-clear! <> id release-qns)))
    635           (database-ptr-set! db #f)
    636           (database-busy-handler-set! db #f)])]
    637     [(? statement? stmt)
     645              (cute hash-table-tree-clear! <> id release-qns))
     646            (database-ptr-set! db #f)
     647            (database-busy-handler-set! db #f))])]
     648    [((? statement? stmt))
    638649      (cond
    639650        [(not (statement-ptr stmt))
    640651          (void)]
    641         [((foreign-lambda sqlite3:status "sqlite3_finalize" sqlite3:statement) stmt)
     652        [(sqlite3_finalize (statement-ptr stmt))
    642653          => (abort-sqlite3-error 'finalize! (statement-database stmt) stmt)]
    643654        [else
    644           (statement-ptr-set! stmt #f)])]))
     655          (statement-ptr-set! stmt #f)])]
     656    [(v . _)
     657      (error-argument-type 'finalize! v "database or statement")]))
    645658
    646659;;; Statement interface
     
    653666    (let-location ([stmt c-pointer] [tail c-string])
    654667      (cond
    655         [((foreign-safe-lambda sqlite3:status "sqlite3_prepare"
     668        [((foreign-safe-lambda sqlite3:status "sqlite3_prepare_v2"
    656669            sqlite3:database scheme-pointer int
    657670            (c-pointer sqlite3:statement)
     
    670683                  ((abort-sqlite3-error 'prepare db db sql) err)]))]
    671684        [else
    672           (values
    673             (make-statement stmt db sql)
    674             tail)]))))
    675 
    676 ;; Recompile an existing statement and transfer all bindings
    677 (define (repair! stmt)
    678   (check-statement 'repair! stmt)
    679   (let ([fresh (prepare
    680     (statement-database stmt)
    681     (statement-sql stmt))])
    682     (dynamic-wind
    683       noop
    684       (lambda ()
    685         (let ([old (statement-ptr stmt)]
    686               [new (statement-ptr fresh)])
    687           (cond
    688             [((foreign-lambda sqlite3:status "sqlite3_transfer_bindings"
    689                 c-pointer c-pointer)
    690               old new)
    691               => (abort-sqlite3-error 'repair! (statement-database stmt) stmt)]
    692             [else
    693               (statement-ptr-set! stmt new)
    694               (statement-ptr-set! fresh old)])))
    695       (lambda ()
    696         (finalize! fresh)))))
     685          (values (make-statement stmt db) tail)]))))
     686
     687;; Retrieve the SQL source code of a statement
     688(define (source-sql stmt)
     689  (check-statement 'source-sql stmt)
     690  ((foreign-lambda c-string "sqlite3_sql" sqlite3:statement) stmt))
    697691
    698692;; Reset an existing statement to process it again
    699 (define sqlite3_reset
    700   (foreign-lambda sqlite3:status "sqlite3_reset" sqlite3:statement))
    701 
    702693(define (reset! stmt)
    703694  (check-statement 'reset! stmt)
    704   (cond [(sqlite3_reset stmt)
     695  (cond [((foreign-lambda sqlite3:status "sqlite3_reset" sqlite3:statement) stmt)
    705696    => (abort-sqlite3-error 'reset! (statement-database stmt) stmt)]))
    706697
     
    800791;; Single-step a prepared statement, return #t if data is available,
    801792;; #f otherwise
    802 (define sqlite3_step
    803   (foreign-safe-lambda sqlite3:status "sqlite3_step" sqlite3:statement))
    804793(define (step! stmt)
    805794  (check-statement 'step! stmt)
    806795  (let ([db (statement-database stmt)])
    807796    (let retry ([retries 0])
    808       (define (busy-retry s)
    809   (let ([h (database-busy-handler db)])
    810     (cond
    811       [(and h (h db retries))
    812         (retry (add1 retries))]
    813       [else
    814         ((abort-sqlite3-error 'step! db stmt) s)])))
    815       (let ([s (sqlite3_step stmt)])
    816   (case s
    817     [(row)
    818       #t]
    819     [(done)
    820       #f]
    821     [(error)
    822       (let ([s (sqlite3_reset stmt)])
     797      (let ([s ((foreign-safe-lambda
     798                  sqlite3:status "sqlite3_step" sqlite3:statement) stmt)])
    823799        (case s
    824     [(schema)
    825       (repair! stmt)
    826       (retry retries)]
    827     [(busy)             ; Passed thru sometimes (e.g. ATTACH).
    828       (busy-retry s)]
    829     [else
    830       ((abort-sqlite3-error 'step! db stmt) s)]))]
    831     [(busy)
    832       (busy-retry s)]
    833     [else
    834       ((abort-sqlite3-error 'step! db stmt) s)])))))
     800          [(row)
     801            #t]
     802          [(done)
     803            #f]
     804          [(busy)
     805            (let ([h (database-busy-handler db)])
     806              (cond
     807                [(and h (h db retries))
     808                  (retry (add1 retries))]
     809                [else
     810                  ((abort-sqlite3-error 'step! db stmt) s)]))]
     811          [else
     812            ((abort-sqlite3-error 'step! db stmt) s)])))))
    835813
    836814;; Retrieve information from a prepared/stepped statement
  • release/4/sqlite3/trunk/sqlite3.setup

    r15347 r15423  
    88  'sqlite3
    99  '("sqlite3.so" "sqlite3.import.so" "sqlite3-static.o")
    10   '((version "3.3.1")
     10  '((version "3.5.0")
    1111    (static "sqlite3-static.o")
    1212    (documentation "sqlite3.html" "egg.jpg")))
  • release/4/sqlite3/trunk/tests/run.scm

    r15347 r15423  
    99(define-syntax with-database
    1010  (syntax-rules ()
    11     [(with-database [db path]
     11    [(with-database [db path . finalize-statements?]
    1212        body ...)
    1313      (let ([db #f])
     
    2020            (and-let* ([d db])
    2121              (set! db #f)
    22               (finalize! d)))))]))
     22              (finalize! d . finalize-statements?)))))]))
    2323
    2424(define-syntax with-database+statement
     
    4343  (test-group "SQL completeness checks"
    4444
    45     (test-assert "Complete SQL"
     45    (test-assert "complete SQL"
    4646      (sql-complete? "SELECT 42;"))
    4747
    48     (test-assert "Incomplete SQL"
     48    (test-assert "incomplete SQL"
    4949      (not (sql-complete? "SELECT -- just a comment")))
    5050
     
    6868                (finalize! s)))))))
    6969
     70    (test-assert "unfinalized statement detection"
     71      (let ([db (open-database ":memory:")])
     72        (condition-case
     73          (begin
     74            (prepare db "SELECT 23;")
     75            (finalize! db #f)
     76            #f)
     77          [(exn sqlite3)
     78            (finalize! db #t)
     79            #t])))
     80
     81    (test-assert "automatic statement finalization"
     82      (with-database [db ":memory:" #t]
     83        (prepare db "SELECT 23;")
     84        #t))
     85
    7086    (test-error "SQL error detection"
    7187      (with-database [db ":memory:"]
Note: See TracChangeset for help on using the changeset viewer.