Add sqlite wrapper module (:std/db/sqlite)
ober
ae945bac49d7084fbbc2a494f7f57e8a19bf58ba
--- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ SCHEME = scheme LIBDIRS = lib # External chez-* library paths for wrapper modules -CHEZ_EXT_LIBDIRS = $(HOME)/mine/chez-https/src:$(HOME)/mine/chez-ssl/src:$(HOME)/mine/chez-zlib/src:$(HOME)/mine/chez-pcre2:$(HOME)/mine/chez-yaml:$(HOME)/mine/chez-leveldb:$(HOME)/mine/chez-epoll/src:$(HOME)/mine/chez-inotify/src:$(HOME)/mine/chez-crypto/src +CHEZ_EXT_LIBDIRS = $(HOME)/mine/chez-https/src:$(HOME)/mine/chez-ssl/src:$(HOME)/mine/chez-zlib/src:$(HOME)/mine/chez-pcre2:$(HOME)/mine/chez-yaml:$(HOME)/mine/chez-leveldb:$(HOME)/mine/chez-epoll/src:$(HOME)/mine/chez-inotify/src:$(HOME)/mine/chez-crypto/src:$(HOME)/mine/chez-sqlite/src # Shared object paths for FFI-based chez-* libraries -CHEZ_EXT_LDPATH = $(HOME)/mine/chez-ssl:$(HOME)/mine/chez-zlib:$(HOME)/mine/chez-pcre2:$(HOME)/mine/chez-leveldb:$(HOME)/mine/chez-epoll:$(HOME)/mine/chez-inotify:$(HOME)/mine/chez-crypto +CHEZ_EXT_LDPATH = $(HOME)/mine/chez-ssl:$(HOME)/mine/chez-zlib:$(HOME)/mine/chez-pcre2:$(HOME)/mine/chez-leveldb:$(HOME)/mine/chez-epoll:$(HOME)/mine/chez-inotify:$(HOME)/mine/chez-crypto:$(HOME)/mine/chez-sqlite .PHONY: test test-reader test-core test-runtime test-stdlib test-ffi test-modules test-expanded test-wrappers clean @@ -66,6 +66,9 @@ test-wrappers: @LD_LIBRARY_PATH="$(CHEZ_EXT_LDPATH):$$LD_LIBRARY_PATH" \ $(SCHEME) --libdirs "$(LIBDIRS):$(CHEZ_EXT_LIBDIRS)" --script tests/test-wrapper-crypto.ss 2>/dev/null \ || echo " crypto: SKIP (requires chez_crypto_shim.so)" + @LD_LIBRARY_PATH="$(CHEZ_EXT_LDPATH):$$LD_LIBRARY_PATH" \ + $(SCHEME) --libdirs "$(LIBDIRS):$(CHEZ_EXT_LIBDIRS)" --script tests/test-wrapper-sqlite.ss 2>/dev/null \ + || echo " sqlite: SKIP (requires chez_sqlite_shim.so)" test-all: test test-wrappers new file mode 100644 --- /dev/null +++ b/lib/std/db/sqlite.sls @@ -0,0 +1,26 @@ +#!chezscheme +;;; :std/db/sqlite -- SQLite3 database (wraps chez-sqlite) +;;; Requires: chez_sqlite_shim.so, libsqlite3.so + +(library (std db sqlite) + (export + ;; Core + sqlite-open sqlite-close + sqlite-exec sqlite-eval sqlite-query + ;; Prepared statements + sqlite-prepare sqlite-finalize + sqlite-step sqlite-reset sqlite-clear-bindings + ;; Binding + sqlite-bind! sqlite-bind-null! + ;; Column access + sqlite-column-count sqlite-column-name sqlite-column-type + sqlite-column-value sqlite-columns + ;; Metadata + sqlite-last-insert-rowid sqlite-changes sqlite-errmsg + ;; Constants + SQLITE_ROW SQLITE_DONE SQLITE_OK + SQLITE_INTEGER SQLITE_FLOAT SQLITE_TEXT SQLITE_BLOB SQLITE_NULL) + + (import (chez-sqlite)) + + ) ;; end library new file mode 100644 --- /dev/null +++ b/tests/test-wrapper-sqlite.ss @@ -0,0 +1,45 @@ +#!chezscheme +(import (chezscheme) (std db sqlite)) + +(define pass 0) +(define fail 0) +(define-syntax chk + (syntax-rules (=>) + [(_ expr => expected) + (let ([r expr] [e expected]) + (if (equal? r e) + (set! pass (+ pass 1)) + (begin (set! fail (+ fail 1)) + (display "FAIL: ") (write 'expr) + (display " => ") (write r) + (display " expected ") (write e) (newline))))])) + +(define test-db "/tmp/jerboa-sqlite-test.db") +(when (file-exists? test-db) (delete-file test-db)) + +;; Open +(define db (sqlite-open test-db)) +(chk (not (zero? db)) => #t) + +;; Create + insert +(sqlite-exec db "CREATE TABLE t (id INTEGER PRIMARY KEY, val TEXT)") +(sqlite-eval db "INSERT INTO t (val) VALUES (?)" "hello") +(sqlite-eval db "INSERT INTO t (val) VALUES (?)" "world") +(chk (sqlite-last-insert-rowid db) => 2) +(chk (sqlite-changes db) => 1) + +;; Query +(let ([rows (sqlite-query db "SELECT id, val FROM t ORDER BY id")]) + (chk (length rows) => 2) + (chk (vector-ref (car rows) 1) => "hello") + (chk (vector-ref (cadr rows) 1) => "world")) + +;; Cleanup +(sqlite-close db) +(delete-file test-db) + +(newline) +(display "sqlite wrapper: ") +(display pass) (display " passed, ") +(display fail) (display " failed") (newline) +(when (> fail 0) (exit 1))