GENERIC: db-open ( db -- db-connection )
GENERIC: db-close ( handle -- )
-HOOK: parse-db-error db-connection ( error -- error' )
M: db-connection dispose ( db-connection -- )
[ db-close ] [ f >>handle drop ] bi ;
: sql-query ( sql -- sequence )
f f <statement> [ statement>result-sequence ] with-disposal ;
+
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors combinators db2.connections db2.sqlite
-db2.sqlite.errors db2.sqlite.lib kernel ;
+db2.sqlite.errors db2.sqlite.lib kernel db2.errors ;
IN: db2.sqlite.connections
TUPLE: sqlite-db-connection < db-connection ;
M: sqlite-db-connection db-close ( db-connection -- )
handle>> sqlite-close ;
-M: sqlite-db-connection parse-db-error ( error -- error' )
+M: sqlite-db-connection parse-sql-error ( error -- error' )
dup n>> {
{ 1 [ string>> parse-sqlite-sql-error ] }
[ drop ]
ERROR: sqlite-error < db-error n string ;
ERROR: sqlite-sql-error < sql-error n string ;
-: throw-sqlite-error ( n -- * )
- dup sqlite-error-messages nth sqlite-error ;
-
: sqlite-statement-error ( -- * )
SQLITE_ERROR
db-connection get handle>> sqlite3_errmsg sqlite-sql-error ;
TUPLE: unparsed-sqlite-error error ;
C: <unparsed-sqlite-error> unparsed-sqlite-error
-: sqlite-table-error ( table message -- error )
- {
- { sql-table-exists [ <sql-table-exists> ] }
- } case ;
-
EBNF: parse-sqlite-sql-error
-TableMessage = " already exists" => [[ sql-table-exists ]]
+TableMessage = " already exists"
+SyntaxError = ": syntax error"
SqliteError =
"table " (!(TableMessage).)+:table TableMessage:message
- => [[ table >string message sqlite-table-error ]]
+ => [[ table >string <sql-table-exists> ]]
+ | "near " (!(SyntaxError).)+:syntax SyntaxError:message
+ => [[ syntax >string <sql-syntax-error> ]]
| "no such table: " .+:table
=> [[ table >string <sql-table-missing> ]]
| .*:error
=> [[ error >string <unparsed-sqlite-error> ]]
;EBNF
+
+: throw-sqlite-error ( n -- * )
+ dup sqlite-error-messages nth sqlite-error ;
: ?when ( object quot -- object' ) dupd when ; inline
-
: sqlite-check-result ( n -- )
{
{ SQLITE_OK [ ] }
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
-USING: db2.result-sets ;
+USING: accessors db2.result-sets db2.sqlite.statements
+db2.statements kernel db2.sqlite.lib destructors ;
IN: db2.sqlite.result-sets
TUPLE: sqlite-result-set < result-set has-more? ;
+M: sqlite-result-set dispose
+ f >>handle drop ;
+
+M: sqlite-statement statement>result-set*
+ sqlite-maybe-prepare
+ dup handle>> sqlite-result-set new-result-set
+ dup advance-row ;
+
+M: sqlite-result-set advance-row ( result-set -- )
+ dup handle>> sqlite-next >>has-more? drop ;
+
+M: sqlite-result-set more-rows? ( result-set -- )
+ has-more?>> ;
+
+M: sqlite-result-set #columns ( result-set -- n )
+ handle>> sqlite-#columns ;
+
+M: sqlite-result-set column ( result-set n -- obj )
+ [ handle>> ] [ sqlite-column ] bi* ;
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
-USING: db2.connections db2.statements db2.sqlite.connections
-db2.sqlite.lib ;
+USING: accessors db2.connections db2.sqlite.connections
+db2.sqlite.ffi db2.sqlite.lib db2.statements destructors kernel
+namespaces ;
IN: db2.sqlite.statements
TUPLE: sqlite-statement < statement ;
M: sqlite-db-connection <statement> ( string in out -- obj )
sqlite-statement new-statement ;
+M: sqlite-statement dispose
+ handle>>
+ [ [ sqlite3_reset drop ] [ sqlite-finalize ] bi ] when* ;
+
+: sqlite-maybe-prepare ( statement -- statement )
+ dup handle>> [
+ db-connection get handle>> over sql>> sqlite-prepare
+ >>handle
+ ] unless ;
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
-USING: tools.test db2.statements kernel ;
+USING: tools.test db2.statements kernel db2 db2.tester
+continuations db2.errors ;
IN: db2.statements.tests
{ 1 0 } [ [ drop ] statement-each ] must-infer-as
{ 1 1 } [ [ ] statement-map ] must-infer-as
-[ ]
-[
- "insert into computer (name, os) values('rocky', 'mac');"
+
+: test-sql-command ( -- )
+ [ "drop table computer;" sql-command ] ignore-errors
+
+ [ ] [
+ "create table computer(name varchar, os varchar);"
+ sql-command
+ ] unit-test
-] unit-test
+ [ ] [
+ "insert into computer (name, os) values('rocky', 'mac');"
+ sql-command
+ ] unit-test
+
+ [ { { "rocky" "mac" } } ]
+ [
+ "select name, os from computer;" sql-query
+ ] unit-test
+
+ [ "insert into" sql-command ]
+ [ sql-syntax-error? ] must-fail-with
+
+ [ "selectt" sql-query ]
+ [ sql-syntax-error? ] must-fail-with
+
+ ;
+
+[ test-sql-command ] test-dbs
+
! Copyright (C) 2009 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors continuations destructors fry kernel
-sequences db2.result-sets db2.connections ;
+sequences db2.result-sets db2.connections db2.errors ;
IN: db2.statements
-TUPLE: statement handle sql in out ;
+TUPLE: statement handle sql in out type ;
: new-statement ( sql in out class -- statement )
new
swap >>sql ;
HOOK: <statement> db-connection ( sql in out -- statement )
+GENERIC: statement>result-set* ( statement -- result-set )
GENERIC: execute-statement* ( statement type -- )
-GENERIC: statement>result-set ( statement -- result-set )
+
+: statement>result-set ( statement -- result-set )
+ [ statement>result-set* ]
+ [ dup sql-error? [ parse-sql-error ] when rethrow ] recover ;
M: object execute-statement* ( statement type -- )
- drop '[ _ statement>result-set dispose ]
- [ parse-db-error rethrow ] recover ;
+ drop statement>result-set dispose ;
: execute-one-statement ( statement -- )
dup type>> execute-statement* ;