1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2013 Guillaume Auger <jeho@resist.ca>
4 # Copyright 2013-2014 Alexis Laferrière <alexis.laf@xymus.net>
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
18 # Low-level Sqlite3 features
19 module native_sqlite3
is pkgconfig
("sqlite3")
26 # Last error raised when calling `Sqlite3::open`
27 var sqlite_open_error
: nullable Sqlite3Code = null
30 extern class Sqlite3Code `{int`}
31 new ok `{ return SQLITE_OK; `} # 0 /* Successful result */
32 fun is_ok
: Bool `{ return recv == SQLITE_OK; `}
34 # new `{ return SQLITE_ERROR; `} # 1 /* SQL error or missing database */
35 # new `{ return SQLITE_INTERNAL; `} # 2 /* Internal logic error in SQLite */
36 # new `{ return SQLITE_PERM; `} # 3 /* Access permission denied */
37 # new `{ return SQLITE_ABORT; `} # 4 /* Callback routine requested an abort */
38 # new `{ return SQLITE_BUSY; `} # 5 /* The database file is locked */
39 # new `{ return SQLITE_LOCKED; `} # 6 /* A table in the database is locked */
40 # new `{ return SQLITE_NOMEM; `} # 7 /* A malloc() failed */
41 # new `{ return SQLITE_READONLY; `} # 8 /* Attempt to write a readonly database */
42 # new `{ return SQLITE_INTERRUPT; `} # 9 /* Operation terminated by sqlite3_interrupt()*/
43 # new `{ return SQLITE_IOERR; `} # 10 /* Some kind of disk I/O error occurred */
44 # new `{ return SQLITE_CORRUPT; `} # 11 /* The database disk image is malformed */
45 # new `{ return SQLITE_NOTFOUND; `} # 12 /* Unknown opcode in sqlite3_file_control() */
46 # new `{ return SQLITE_FULL; `} # 13 /* Insertion failed because database is full */
47 # new `{ return SQLITE_CANTOPEN; `} # 14 /* Unable to open the database file */
48 # new `{ return SQLITE_PROTOCOL; `} # 15 /* Database lock protocol error */
49 # new `{ return SQLITE_EMPTY; `} # 16 /* Database is empty */
50 # new `{ return SQLITE_SCHEMA; `} # 17 /* The database schema changed */
51 # new `{ return SQLITE_TOOBIG; `} # 18 /* String or BLOB exceeds size limit */
52 # new `{ return SQLITE_CONSTRAINT; `} # 19 /* Abort due to constraint violation */
53 # new `{ return SQLITE_MISMATCH; `} # 20 /* Data type mismatch */
54 # new `{ return SQLITE_MISUSE; `} # 21 /* Library used incorrectly */
55 # new `{ return SQLITE_NOLFS; `} # 22 /* Uses OS features not supported on host */
56 # new `{ return SQLITE_AUTH; `} # 23 /* Authorization denied */
57 # new `{ return SQLITE_FORMAT; `} # 24 /* Auxiliary database format error */
58 # new `{ return SQLITE_RANGE; `} # 25 /* 2nd parameter to sqlite3_bind out of range */
59 # new `{ return SQLITE_NOTADB; `} # 26 /* File opened that is not a database file */
60 # new `{ return SQLITE_NOTICE; `} # 27 /* Notifications from sqlite3_log() */
61 # new `{ return SQLITE_WARNING; `} # 28 /* Warnings from sqlite3_log() */
63 new row
`{ return SQLITE_ROW; `} # 100 /* sqlite3_step() has another row ready */
64 fun is_row: Bool `{ return recv == SQLITE_ROW; `}
66 new done
`{ return SQLITE_DONE; `} # 101 /* sqlite3_step() has finished executing */
67 fun is_done: Bool `{ return recv == SQLITE_DONE; `}
69 redef fun to_s
: String import NativeString.to_s
`{
70 #if SQLITE_VERSION_NUMBER >= 3007015
71 char *err = (char *)sqlite3_errstr(recv);
73 char *err = "sqlite3_errstr supported only by version >= 3.7.15";
75 if (err == NULL) err = "";
76 return NativeString_to_s(err);
80 # A prepared statement
81 extern class NativeStatement `{sqlite3_stmt*`}
83 # Evaluate the statement
84 fun step: Sqlite3Code `{
85 return sqlite3_step
(recv
);
88 fun column_name(i: Int) : String import NativeString.to_s `{
89 const char
* name
= (sqlite3_column_name
(recv
, i
));
93 char
* ret
= (char
*) name
;
94 return NativeString_to_s(ret
);
97 # Number of bytes in the blob or string at row `i
`
98 fun column_bytes(i: Int) : Int `{
99 return sqlite3_column_bytes
(recv
, i
);
102 fun column_double(i: Int) : Float `{
103 return sqlite3_column_double
(recv
, i
);
106 fun column_int(i: Int) : Int `{
107 return sqlite3_column_int
(recv
, i
);
110 fun column_text(i: Int): NativeString `{
111 return (char
*)sqlite3_column_text
(recv
, i
);
114 # Type of the entry at row `i
`
115 fun column_type(i: Int): DataType `{
116 return sqlite3_column_type
(recv
, i
);
119 fun column_blob(i: Int): Pointer `{ return (void*)sqlite3_column_blob(recv, i); `}
121 fun column_count
: Int `{
122 return sqlite3_column_count(recv);
125 # Reset this statement to its original state, to be reexecuted
126 fun reset
: Sqlite3Code `{ return sqlite3_reset(recv); `}
128 # Delete this statement
129 fun finalize: Sqlite3Code `{ return sqlite3_finalize(recv); `}
132 # A database connection
133 extern class NativeSqlite3 `{sqlite3 *`}
135 # Open a connection to a database in UTF-8
136 new open(filename: String) import String.to_cstring, set_sys_sqlite_open_error `{
137 sqlite3
*self = NULL;
138 int err
= sqlite3_open
(String_to_cstring(filename
), &self);
139 NativeSqlite3_set_sys_sqlite_open_error(self, (void
*)(long
)err
);
140 // The previous cast
is a hack
, using non pointers
in extern classes
is not
141 // yet
in the spec of the
FFI.
145 # Utility method to set `Sys.sqlite_open_error
`
146 private fun set_sys_sqlite_open_error(err: Sqlite3Code) do sys.sqlite_open_error = err
148 # Has this DB been correctly opened?
150 # To know if it has been closed or interrupted, you must check for errors with `error
`.
151 fun is_valid: Bool do return not address_is_null
155 # Close this connection
157 #if SQLITE_VERSION_NUMBER >= 3007014
158 sqlite3_close_v2
(recv
);
160 // A program using the older version should
not rely on the garbage-collector
161 // to close its connections
. They must be closed manually after the associated
162 // prepare statements have been finalized
.
167 # Execute a SQL statement
168 fun exec(sql: String): Sqlite3Code import String.to_cstring `{
169 return sqlite3_exec
(recv
, String_to_cstring(sql
), 0, 0, 0);
172 # Prepare a SQL statement
173 fun prepare(sql: String): nullable NativeStatement import String.to_cstring, NativeStatement.as nullable `{
175 int res
= sqlite3_prepare_v2
(recv
, String_to_cstring(sql
), -1, &stmt
, 0);
176 if (res
== SQLITE_OK)
177 return NativeStatement_as_nullable(stmt
);
179 return null_NativeStatement
();
182 fun last_insert_rowid: Int `{
183 return sqlite3_last_insert_rowid
(recv
);
186 fun error: Sqlite3Code `{
187 return sqlite3_errcode
(recv
);
192 extern class DataType `{ int `}
193 fun is_integer
: Bool `{ return recv == SQLITE_INTEGER; `}
194 fun is_float: Bool `{ return recv == SQLITE_FLOAT; `}
195 fun is_blob
: Bool `{ return recv == SQLITE_BLOB; `}
196 fun is_null: Bool `{ return recv == SQLITE_NULL; `}
197 fun is_text
: Bool `{ return recv == SQLITE_TEXT; `}
199 fun to_i: Int `{ return recv; `}