1 ! Copyright (C) 2008 Chris Double, Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien.c-types arrays assocs kernel math math.parser
4 namespaces sequences db.sqlite.ffi db combinators
5 continuations db.types calendar.format serialize
6 io.streams.byte-array byte-arrays io.encodings.binary
7 io.backend db.errors present urls io.encodings.utf8
8 io.encodings.string accessors shuffle ;
11 ERROR: sqlite-error < db-error n string ;
12 ERROR: sqlite-sql-error < sql-error n string ;
14 : throw-sqlite-error ( n -- * )
15 dup sqlite-error-messages nth sqlite-error ;
17 : sqlite-statement-error ( -- * )
19 db get handle>> sqlite3_errmsg sqlite-sql-error ;
21 : sqlite-check-result ( n -- )
24 { SQLITE_ERROR [ sqlite-statement-error ] }
25 [ throw-sqlite-error ]
28 : sqlite-open ( path -- db )
31 [ sqlite3_open sqlite-check-result ] keep *void* ;
33 : sqlite-close ( db -- )
34 sqlite3_close sqlite-check-result ;
36 : sqlite-prepare ( db sql -- handle )
37 utf8 encode dup length "void*" <c-object> "void*" <c-object>
38 [ sqlite3_prepare_v2 sqlite-check-result ] 2keep
41 : sqlite-bind-parameter-index ( handle name -- index )
42 sqlite3_bind_parameter_index ;
44 : parameter-index ( handle name text -- handle name text )
45 >r dupd sqlite-bind-parameter-index r> ;
47 : sqlite-bind-text ( handle index text -- )
48 utf8 encode dup length SQLITE_TRANSIENT
49 sqlite3_bind_text sqlite-check-result ;
51 : sqlite-bind-int ( handle i n -- )
52 sqlite3_bind_int sqlite-check-result ;
54 : sqlite-bind-int64 ( handle i n -- )
55 sqlite3_bind_int64 sqlite-check-result ;
57 : sqlite-bind-uint64 ( handle i n -- )
58 sqlite3-bind-uint64 sqlite-check-result ;
60 : sqlite-bind-double ( handle i x -- )
61 sqlite3_bind_double sqlite-check-result ;
63 : sqlite-bind-null ( handle i -- )
64 sqlite3_bind_null sqlite-check-result ;
66 : sqlite-bind-blob ( handle i byte-array -- )
67 dup length SQLITE_TRANSIENT
68 sqlite3_bind_blob sqlite-check-result ;
70 : sqlite-bind-text-by-name ( handle name text -- )
71 parameter-index sqlite-bind-text ;
73 : sqlite-bind-int-by-name ( handle name int -- )
74 parameter-index sqlite-bind-int ;
76 : sqlite-bind-int64-by-name ( handle name int64 -- )
77 parameter-index sqlite-bind-int64 ;
79 : sqlite-bind-uint64-by-name ( handle name int64 -- )
80 parameter-index sqlite-bind-uint64 ;
82 : sqlite-bind-boolean-by-name ( handle name obj -- )
83 >boolean 1 0 ? parameter-index sqlite-bind-int ;
85 : sqlite-bind-double-by-name ( handle name double -- )
86 parameter-index sqlite-bind-double ;
88 : sqlite-bind-blob-by-name ( handle name blob -- )
89 parameter-index sqlite-bind-blob ;
91 : sqlite-bind-null-by-name ( handle name obj -- )
92 parameter-index drop sqlite-bind-null ;
94 : (sqlite-bind-type) ( handle key value type -- )
95 dup array? [ first ] when
97 { INTEGER [ sqlite-bind-int-by-name ] }
98 { BIG-INTEGER [ sqlite-bind-int64-by-name ] }
99 { SIGNED-BIG-INTEGER [ sqlite-bind-int64-by-name ] }
100 { UNSIGNED-BIG-INTEGER [ sqlite-bind-uint64-by-name ] }
101 { BOOLEAN [ sqlite-bind-boolean-by-name ] }
102 { TEXT [ sqlite-bind-text-by-name ] }
103 { VARCHAR [ sqlite-bind-text-by-name ] }
104 { DOUBLE [ sqlite-bind-double-by-name ] }
105 { DATE [ timestamp>ymd sqlite-bind-text-by-name ] }
106 { TIME [ timestamp>hms sqlite-bind-text-by-name ] }
107 { DATETIME [ timestamp>ymdhms sqlite-bind-text-by-name ] }
108 { TIMESTAMP [ timestamp>ymdhms sqlite-bind-text-by-name ] }
109 { BLOB [ sqlite-bind-blob-by-name ] }
110 { FACTOR-BLOB [ object>bytes sqlite-bind-blob-by-name ] }
111 { URL [ present sqlite-bind-text-by-name ] }
112 { +db-assigned-id+ [ sqlite-bind-int-by-name ] }
113 { +random-id+ [ sqlite-bind-int64-by-name ] }
114 { NULL [ sqlite-bind-null-by-name ] }
118 : sqlite-bind-type ( handle key value type -- )
119 #! null and empty values need to be set by sqlite-bind-null-by-name
121 NULL = [ 2drop NULL NULL ] when
124 ] if* (sqlite-bind-type) ;
126 : sqlite-finalize ( handle -- ) sqlite3_finalize sqlite-check-result ;
127 : sqlite-reset ( handle -- ) sqlite3_reset sqlite-check-result ;
128 : sqlite-clear-bindings ( handle -- )
129 sqlite3_clear_bindings sqlite-check-result ;
130 : sqlite-#columns ( query -- int ) sqlite3_column_count ;
131 : sqlite-column ( handle index -- string ) sqlite3_column_text ;
132 : sqlite-column-name ( handle index -- string ) sqlite3_column_name ;
133 : sqlite-column-type ( handle index -- string ) sqlite3_column_type ;
135 : sqlite-column-blob ( handle index -- byte-array/f )
136 [ sqlite3_column_bytes ] 2keep
140 sqlite3_column_blob swap memory>byte-array
143 : sqlite-column-typed ( handle index type -- obj )
144 dup array? [ first ] when
146 { +db-assigned-id+ [ sqlite3_column_int64 ] }
147 { +random-id+ [ sqlite3-column-uint64 ] }
148 { INTEGER [ sqlite3_column_int ] }
149 { BIG-INTEGER [ sqlite3_column_int64 ] }
150 { SIGNED-BIG-INTEGER [ sqlite3_column_int64 ] }
151 { UNSIGNED-BIG-INTEGER [ sqlite3-column-uint64 ] }
152 { BOOLEAN [ sqlite3_column_int 1 = ] }
153 { DOUBLE [ sqlite3_column_double ] }
154 { TEXT [ sqlite3_column_text ] }
155 { VARCHAR [ sqlite3_column_text ] }
156 { DATE [ sqlite3_column_text dup [ ymd>timestamp ] when ] }
157 { TIME [ sqlite3_column_text dup [ hms>timestamp ] when ] }
158 { TIMESTAMP [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] }
159 { DATETIME [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] }
160 { BLOB [ sqlite-column-blob ] }
161 { URL [ sqlite3_column_text dup [ >url ] when ] }
162 { FACTOR-BLOB [ sqlite-column-blob dup [ bytes>object ] when ] }
166 : sqlite-row ( handle -- seq )
167 dup sqlite-#columns [ sqlite-column ] with map ;
169 : sqlite-step-has-more-rows? ( prepared -- ? )
172 { SQLITE_DONE [ f ] }
173 [ sqlite-check-result f ]
176 : sqlite-next ( prepared -- ? )
177 sqlite3_step sqlite-step-has-more-rows? ;