(module sqlite3 mzscheme
(require (lib "unitsig.ss"))
(require (planet "gen.ss" ("untyped" "unlib.plt" 2))
(planet "parameter.ss" ("untyped" "unlib.plt" 2)))
(require (prefix sqlite: (planet "sqlite.ss" ("jaymccarthy" "sqlite.plt" 3))))
(require (file "../generic/util.ss")
(file "../base.ss")
(file "../db-sig.ss")
(prefix era: (file "../era.ss"))
(file "../query-core.ss")
(file "../transaction.ss")
(file "../type.ss")
(file "extract.ss")
(file "sql.ss"))
(provide (struct config (path))
db@)
(define-struct config (path))
(define db@
(unit/sig db^
(import)
(define (connect config)
(with-snooze-reraise (sqlite:exn:sqlite? "Could not connect to database")
(sqlite:open (config-path config))))
(define (disconnect conn)
(with-snooze-reraise (sqlite:exn:sqlite? "Could not disconnect to database")
(sqlite:close conn)))
(define (create-table conn entity)
(with-snooze-reraise (sqlite:exn:sqlite? (format "Could not create table for ~a" entity))
(sqlite:exec/ignore conn (create-sql entity))))
(define (drop-table conn entity)
(with-snooze-reraise (sqlite:exn:sqlite? (format "Could not drop table for ~a" entity))
(sqlite:exec/ignore conn (drop-sql entity))))
(define (insert-record conn struct)
(with-snooze-reraise (sqlite:exn:sqlite? (format "Could not insert database record for ~a" struct))
(sqlite:insert conn (insert-sql struct))))
(define (update-record conn struct)
(with-snooze-reraise (sqlite:exn:sqlite? (format "Could not update database record for ~a" struct))
(sqlite:exec/ignore conn (update-sql struct)))
(void))
(define (delete-record conn entity id)
(with-snooze-reraise (sqlite:exn:sqlite? (format "Could not delete database record for ~a ~a" entity id))
(sqlite:exec/ignore conn (delete-sql entity id)))
(void))
(define (find-gen conn select)
(with-snooze-reraise (sqlite:exn:sqlite? (format "Could not execute SELECT query: ~a" select))
(let ([results (sqlite:select conn (select-sql select))])
(g:map (make-struct-extractor (select-what-entities select) (select-single-item? select))
(g:map (make-data-unquoter (select-what-types select))
(list->generator (if (null? results) null (cdr results))))))))
(define (call-with-transaction conn body)
(if (in-transaction?)
(body)
(sqlite:with-transaction
(conn sqlite-escape)
(let ([frame (make-frame)]
[body-complete-cell (make-thread-cell #f)] [transaction-complete-cell (make-thread-cell #f)]) (dynamic-wind
(lambda ()
(when (thread-cell-ref transaction-complete-cell)
(raise-exn exn:fail:snooze:transaction
"Transaction block was interrupted and cannot be resumed.")))
(lambda ()
(call-with-frame frame
(lambda ()
(begin0 (body)
(thread-cell-set! body-complete-cell #t)))))
(lambda ()
(if (thread-cell-ref transaction-complete-cell)
(raise-exn exn:fail:snooze:transaction
"Transaction block was interrupted and resumed.")
(begin
(unless (thread-cell-ref body-complete-cell)
(roll-back-frame! frame))
(thread-cell-set! transaction-complete-cell #t)))))))))
(define (dump-sql select output-port format)
(fprintf output-port format (select-sql select))
select)
))
)