#lang scheme
(require (prefix-in dbd: (planet jaymccarthy/sqlite:4:5))
(planet bzlib/base)
(planet bzlib/dbi)
(prefix-in s: srfi/19)
)
(define (sqlite-connect driver path . attrs)
(let-values (((loader attrs)
(filter-file-loader/attrs attrs)))
(let ((handle (make-handle driver (dbd:open path)
(make-immutable-hash-registry)
0)))
(load-files! handle (if (list? loader) loader
(list loader)))
handle)))
(define (sqlite-disconnect handle)
(hash-for-each (registry-table (handle-query handle))
(lambda (key prepared)
(dbd:finalize (prepared-inner prepared))))
(dbd:close (handle-conn handle)))
(define (sqlite-query handle stmt (args '()))
(define (run! query stmt)
(dbd:run stmt))
(define (insert! query stmt)
(run! query stmt)
(dbd:last-insert-rowid (handle-conn handle)))
(define (select query stmt)
(cons (dbd:statement-names stmt)
(dbd:step* stmt)))
(define (exec! query stmt)
(apply dbd:load-params stmt (map cell->sql-cell (phq-map-values query args)))
(begin0 (cond ((regexp-match #px"^(?i:select)" (phq-query query))
(select query stmt))
((regexp-match #px"^(?i:insert)" (phq-query query))
(insert! query stmt))
(else
(run! query stmt)))
(dbd:reset stmt)))
(if-it (registry-ref (handle-query handle) stmt) (convert-result
(exec! (prepared-query it) (prepared-inner it)))
(begin
(sqlite-prepare handle stmt stmt)
(sqlite-query handle stmt args))))
(define (sqlite-query/effect handle stmt (args '()))
(define (helper rs)
(if (or (null? rs) (pair? rs))
rs
(let ((conn (handle-conn handle)))
(make-effect (dbd:changes-count conn)
(let ((id (dbd:last-insert-rowid conn)))
(if (= 0 id) #f id))
#f
#f
(dbd:errmsg conn)
(let ((v (dbd:errmsg conn)))
(if (equal? v "not an error")
#f
v))))))
(helper (sqlite-query handle stmt args)))
(define (sqlite-query/effect-set handle stmt (args '()))
(result-set-or-effect->result-set (sqlite-query/effect handle stmt args)))
(define (sqlite-prepare handle key stmt)
(let ((query (make-place-holder-query question-converter stmt)))
(registry-set! (handle-query handle)
key
(make-prepared query
(dbd:prepare (handle-conn handle) (phq-converted query))))))
(define (convert-result result)
(cond ((null? result) (void))
((pair? result)
(map (lambda (rec)
(map sql-cell->cell (vector->list rec)))
result))
(else result)))
(define (sql-cell->cell cell)
(cond ((eq? #f cell) '())
(else cell)))
(define (cell->sql-cell cell)
(cond ((null? cell) #f)
((s:date? cell)
(s:date->string cell "~Y-~m-~d ~H:~M:~S~z"))
(else cell)))
(registry-set! drivers 'jsqlite/pass-thru-effect
(make-driver sqlite-connect
sqlite-disconnect
sqlite-query
sqlite-prepare
default-begin
default-commit
default-rollback))
(registry-set! drivers 'jsqlite/effect
(make-driver sqlite-connect
sqlite-disconnect
sqlite-query/effect
sqlite-prepare
default-begin
default-commit
default-rollback))
(registry-set! drivers 'jsqlite/effect-set
(make-driver sqlite-connect
sqlite-disconnect
sqlite-query/effect-set
sqlite-prepare
default-begin
default-commit
default-rollback))
(registry-set! drivers 'jsqlite (registry-ref drivers 'jsqlite/effect))