rename `NativeString` to `CString`
[nit.git] / lib / sqlite3 / native_sqlite3.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2013 Guillaume Auger <jeho@resist.ca>
4 # Copyright 2013-2014 Alexis Laferrière <alexis.laf@xymus.net>
5 #
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
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
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.
17
18 # Low-level Sqlite3 features
19 module native_sqlite3 is pkgconfig("sqlite3")
20
21 in "C header" `{
22 #include <sqlite3.h>
23 `}
24
25 in "C" `{
26 // Return code of the last call to the constructor of `NativeSqlite3`
27 static int nit_sqlite_open_error = SQLITE_OK;
28 `}
29
30 redef class Sys
31 # Last error raised when calling `Sqlite3::open`
32 fun sqlite_open_error: Sqlite3Code `{ return nit_sqlite_open_error; `}
33 end
34
35 extern class Sqlite3Code `{int`}
36 new ok `{ return SQLITE_OK; `} # 0 /* Successful result */
37 fun is_ok: Bool `{ return self == SQLITE_OK; `}
38
39 # new `{ return SQLITE_ERROR; `} # 1 /* SQL error or missing database */
40 # new `{ return SQLITE_INTERNAL; `} # 2 /* Internal logic error in SQLite */
41 # new `{ return SQLITE_PERM; `} # 3 /* Access permission denied */
42 # new `{ return SQLITE_ABORT; `} # 4 /* Callback routine requested an abort */
43 # new `{ return SQLITE_BUSY; `} # 5 /* The database file is locked */
44 # new `{ return SQLITE_LOCKED; `} # 6 /* A table in the database is locked */
45 # new `{ return SQLITE_NOMEM; `} # 7 /* A malloc() failed */
46 # new `{ return SQLITE_READONLY; `} # 8 /* Attempt to write a readonly database */
47 # new `{ return SQLITE_INTERRUPT; `} # 9 /* Operation terminated by sqlite3_interrupt()*/
48 # new `{ return SQLITE_IOERR; `} # 10 /* Some kind of disk I/O error occurred */
49 # new `{ return SQLITE_CORRUPT; `} # 11 /* The database disk image is malformed */
50 # new `{ return SQLITE_NOTFOUND; `} # 12 /* Unknown opcode in sqlite3_file_control() */
51 # new `{ return SQLITE_FULL; `} # 13 /* Insertion failed because database is full */
52 # new `{ return SQLITE_CANTOPEN; `} # 14 /* Unable to open the database file */
53 # new `{ return SQLITE_PROTOCOL; `} # 15 /* Database lock protocol error */
54 # new `{ return SQLITE_EMPTY; `} # 16 /* Database is empty */
55 # new `{ return SQLITE_SCHEMA; `} # 17 /* The database schema changed */
56 # new `{ return SQLITE_TOOBIG; `} # 18 /* String or BLOB exceeds size limit */
57 # new `{ return SQLITE_CONSTRAINT; `} # 19 /* Abort due to constraint violation */
58 # new `{ return SQLITE_MISMATCH; `} # 20 /* Data type mismatch */
59 # new `{ return SQLITE_MISUSE; `} # 21 /* Library used incorrectly */
60 # new `{ return SQLITE_NOLFS; `} # 22 /* Uses OS features not supported on host */
61 # new `{ return SQLITE_AUTH; `} # 23 /* Authorization denied */
62 # new `{ return SQLITE_FORMAT; `} # 24 /* Auxiliary database format error */
63 # new `{ return SQLITE_RANGE; `} # 25 /* 2nd parameter to sqlite3_bind out of range */
64 # new `{ return SQLITE_NOTADB; `} # 26 /* File opened that is not a database file */
65 # new `{ return SQLITE_NOTICE; `} # 27 /* Notifications from sqlite3_log() */
66 # new `{ return SQLITE_WARNING; `} # 28 /* Warnings from sqlite3_log() */
67
68 new row `{ return SQLITE_ROW; `} # 100 /* sqlite3_step() has another row ready */
69 fun is_row: Bool `{ return self == SQLITE_ROW; `}
70
71 new done `{ return SQLITE_DONE; `} # 101 /* sqlite3_step() has finished executing */
72 fun is_done: Bool `{ return self == SQLITE_DONE; `}
73
74 redef fun to_s
75 do
76 var err = native_to_s
77 if err.address_is_null then return "Unknown error"
78 return err.to_s
79 end
80
81 private fun native_to_s: CString `{
82 #if SQLITE_VERSION_NUMBER >= 3007015
83 return (char *)sqlite3_errstr(self);
84 #else
85 return "sqlite3_errstr is not supported in version < 3.7.15";
86 #endif
87 `}
88 end
89
90 # A prepared statement
91 extern class NativeStatement `{sqlite3_stmt*`}
92
93 # Evaluate the statement
94 fun step: Sqlite3Code `{
95 return sqlite3_step(self);
96 `}
97
98 fun column_name(i: Int): CString `{
99 return (char *)sqlite3_column_name(self, i);
100 `}
101
102 # Number of bytes in the blob or string at row `i`
103 fun column_bytes(i: Int) : Int `{
104 return sqlite3_column_bytes(self, i);
105 `}
106
107 fun column_double(i: Int) : Float `{
108 return sqlite3_column_double(self, i);
109 `}
110
111 fun column_int(i: Int) : Int `{
112 return sqlite3_column_int(self, i);
113 `}
114
115 fun column_text(i: Int): CString `{
116 return (char *)sqlite3_column_text(self, i);
117 `}
118
119 # Type of the entry at row `i`
120 fun column_type(i: Int): DataType `{
121 return sqlite3_column_type(self, i);
122 `}
123
124 fun column_blob(i: Int): Pointer `{ return (void*)sqlite3_column_blob(self, i); `}
125
126 fun column_count: Int `{
127 return sqlite3_column_count(self);
128 `}
129
130 # Reset this statement to its original state, to be reexecuted
131 fun reset: Sqlite3Code `{ return sqlite3_reset(self); `}
132
133 # Delete this statement
134 fun finalize: Sqlite3Code `{ return sqlite3_finalize(self); `}
135 end
136
137 # A database connection
138 extern class NativeSqlite3 `{sqlite3 *`}
139
140 # Open a connection to a database in UTF-8
141 new open(filename: CString) `{
142 sqlite3 *self = NULL;
143 int err = sqlite3_open(filename, &self);
144 nit_sqlite_open_error = err;
145 return self;
146 `}
147
148 # Has this DB been correctly opened?
149 #
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
152
153 # Close this connection
154 fun close `{
155 #if SQLITE_VERSION_NUMBER >= 3007014
156 sqlite3_close_v2(self);
157 #else
158 // A program using the older version should not rely on the garbage-collector
159 // to close its connections. They must be closed manually after the associated
160 // prepare statements have been finalized.
161 sqlite3_close(self);
162 #endif
163 `}
164
165 # Execute a SQL statement
166 fun exec(sql: CString): Sqlite3Code `{
167 return sqlite3_exec(self, sql, NULL, NULL, NULL);
168 `}
169
170 # Prepare a SQL statement
171 fun prepare(sql: CString): NativeStatement `{
172 sqlite3_stmt *stmt;
173 int res = sqlite3_prepare_v2(self, sql, -1, &stmt, 0);
174 if (res == SQLITE_OK)
175 return stmt;
176 else
177 return NULL;
178 `}
179
180 fun last_insert_rowid: Int `{
181 return sqlite3_last_insert_rowid(self);
182 `}
183
184 fun error: Sqlite3Code `{
185 return sqlite3_errcode(self);
186 `}
187 end
188
189 # Sqlite data types
190 extern class DataType `{ int `}
191 fun is_integer: Bool `{ return self == SQLITE_INTEGER; `}
192 fun is_float: Bool `{ return self == SQLITE_FLOAT; `}
193 fun is_blob: Bool `{ return self == SQLITE_BLOB; `}
194 fun is_null: Bool `{ return self == SQLITE_NULL; `}
195 fun is_text: Bool `{ return self == SQLITE_TEXT; `}
196
197 fun to_i: Int `{ return self; `}
198 end