3923
|
1 /* Copyright (C) 2006 Jakob Hirsch */
|
|
2
|
|
3 #include "lib.h"
|
|
4 #include "str.h"
|
|
5 #include "sql-api-private.h"
|
|
6
|
|
7 #ifdef HAVE_SQLITE
|
|
8 #include <stdlib.h>
|
|
9 #include <time.h>
|
|
10 #include <sqlite3.h>
|
|
11
|
|
12 /* retry time if db is busy (in ms) */
|
|
13 const int sqlite_busy_timeout = 1000;
|
|
14
|
|
15 struct sqlite_db {
|
|
16 struct sql_db api;
|
|
17
|
|
18 pool_t pool;
|
|
19 const char *dbfile;
|
|
20 sqlite3 *sqlite;
|
|
21 unsigned int connected:1;
|
|
22 int rc;
|
|
23 };
|
|
24
|
|
25 struct sqlite_result {
|
|
26 struct sql_result api;
|
|
27 sqlite3_stmt *stmt;
|
|
28 unsigned int cols;
|
|
29 const char **row;
|
|
30 };
|
|
31
|
|
32 struct sqlite_transaction_context {
|
|
33 struct sql_transaction_context ctx;
|
|
34 unsigned int failed:1;
|
|
35 };
|
|
36
|
|
37 extern struct sql_result driver_sqlite_result;
|
|
38 extern struct sql_result driver_sqlite_error_result;
|
|
39
|
|
40 static int driver_sqlite_connect(struct sql_db *_db)
|
|
41 {
|
|
42 struct sqlite_db *db = (struct sqlite_db *)_db;
|
|
43
|
|
44 if (db->connected)
|
|
45 return 1;
|
|
46
|
|
47 db->rc = sqlite3_open(db->dbfile, &db->sqlite);
|
|
48
|
|
49 if (db->rc == SQLITE_OK) {
|
|
50 db->connected = TRUE;
|
|
51 sqlite3_busy_timeout(db->sqlite, sqlite_busy_timeout);
|
|
52 return 1;
|
|
53 } else {
|
|
54 i_error("sqlite: open(%s) failed: %s", db->dbfile,
|
|
55 sqlite3_errmsg(db->sqlite));
|
|
56 sqlite3_close(db->sqlite);
|
|
57 return -1;
|
|
58 }
|
|
59 }
|
|
60
|
|
61 static struct sql_db *driver_sqlite_init(const char *connect_string)
|
|
62 {
|
|
63 struct sqlite_db *db;
|
|
64 pool_t pool;
|
|
65
|
|
66 i_assert(connect_string != NULL);
|
|
67
|
|
68 pool = pool_alloconly_create("sqlite driver", 512);
|
|
69 db = p_new(pool, struct sqlite_db, 1);
|
|
70 db->pool = pool;
|
|
71 db->api = driver_sqlite_db;
|
|
72 db->dbfile = p_strdup(db->pool, connect_string);
|
|
73 db->connected = FALSE;
|
|
74
|
|
75 return &db->api;
|
|
76 }
|
|
77
|
|
78 static void driver_sqlite_deinit(struct sql_db *_db)
|
|
79 {
|
|
80 struct sqlite_db *db = (struct sqlite_db *)_db;
|
|
81
|
|
82 sqlite3_close(db->sqlite);
|
|
83 pool_unref(db->pool);
|
|
84 }
|
|
85
|
|
86 static enum sql_db_flags
|
|
87 driver_sqlite_get_flags(struct sql_db *db __attr_unused__)
|
|
88 {
|
|
89 return SQL_DB_FLAG_BLOCKING;
|
|
90 }
|
|
91
|
|
92 static void driver_sqlite_exec(struct sql_db *_db, const char *query)
|
|
93 {
|
|
94 struct sqlite_db *db = (struct sqlite_db *)_db;
|
|
95
|
|
96 db->rc = sqlite3_exec(db->sqlite, query, NULL, 0, NULL);
|
|
97 if (db->rc != SQLITE_OK) {
|
|
98 i_error("sqlite: exec(%s) failed: %s (%d)",
|
|
99 query, sqlite3_errmsg(db->sqlite), db->rc);
|
|
100 }
|
|
101 }
|
|
102
|
|
103 static void driver_sqlite_query(struct sql_db *db, const char *query,
|
|
104 sql_query_callback_t *callback, void *context)
|
|
105 {
|
|
106 struct sql_result *result;
|
|
107
|
|
108 result = sql_query_s(db, query);
|
|
109 result->callback = TRUE;
|
|
110 callback(result, context);
|
|
111 sql_result_free(result);
|
|
112 }
|
|
113
|
|
114 static struct sql_result *
|
|
115 driver_sqlite_query_s(struct sql_db *_db, const char *query)
|
|
116 {
|
|
117 struct sqlite_db *db = (struct sqlite_db *)_db;
|
|
118 struct sqlite_result *result;
|
|
119 int rc;
|
|
120
|
|
121 result = i_new(struct sqlite_result, 1);
|
|
122
|
|
123 rc = sqlite3_prepare(db->sqlite, query, -1, &result->stmt, NULL);
|
|
124 if (rc == SQLITE_OK) {
|
|
125 result->api = driver_sqlite_result;
|
|
126 result->cols = sqlite3_column_count(result->stmt);
|
|
127 result->row = i_new(const char *, result->cols);
|
|
128 } else {
|
|
129 result->api = driver_sqlite_error_result;
|
|
130 result->stmt = NULL;
|
|
131 result->cols = 0;
|
|
132 }
|
|
133 result->api.db = _db;
|
|
134
|
|
135 return &result->api;
|
|
136 }
|
|
137
|
|
138 static void driver_sqlite_result_free(struct sql_result *_result)
|
|
139 {
|
|
140 struct sqlite_result *result = (struct sqlite_result *)_result;
|
|
141 struct sqlite_db *db = (struct sqlite_db *) result->api.db;
|
|
142 int rc;
|
|
143
|
|
144 if (result->stmt != NULL) {
|
|
145 if ((rc = sqlite3_finalize(result->stmt)) != SQLITE_OK) {
|
|
146 i_warning("sqlite: finalize failed: %s (%d)",
|
|
147 sqlite3_errmsg(db->sqlite), rc);
|
|
148 }
|
|
149 i_free(result->row);
|
|
150 }
|
|
151 i_free(result);
|
|
152 }
|
|
153
|
|
154 static int driver_sqlite_result_next_row(struct sql_result *_result)
|
|
155 {
|
|
156 struct sqlite_result *result = (struct sqlite_result *)_result;
|
|
157
|
|
158 switch (sqlite3_step(result->stmt)) {
|
|
159 case SQLITE_ROW:
|
|
160 return 1;
|
|
161 case SQLITE_DONE:
|
|
162 return 0;
|
|
163 default:
|
|
164 return -1;
|
|
165 }
|
|
166 }
|
|
167
|
|
168 static unsigned int
|
|
169 driver_sqlite_result_get_fields_count(struct sql_result *_result)
|
|
170 {
|
|
171 struct sqlite_result *result = (struct sqlite_result *)_result;
|
|
172
|
|
173 return result->cols;
|
|
174 }
|
|
175
|
|
176 static const char *
|
|
177 driver_sqlite_result_get_field_name(struct sql_result *_result,
|
|
178 unsigned int idx)
|
|
179 {
|
|
180 struct sqlite_result *result = (struct sqlite_result *)_result;
|
|
181
|
|
182 return sqlite3_column_name(result->stmt, idx);
|
|
183 }
|
|
184
|
|
185 static int driver_sqlite_result_find_field(struct sql_result *_result,
|
|
186 const char *field_name)
|
|
187 {
|
|
188 struct sqlite_result *result = (struct sqlite_result *)_result;
|
|
189 unsigned int i;
|
|
190
|
|
191 for (i = 0; i < result->cols; ++i) {
|
|
192 const char *col = sqlite3_column_name(result->stmt, i);
|
|
193
|
|
194 if (strcmp(col, field_name) == 0)
|
|
195 return i;
|
|
196 }
|
|
197
|
|
198 return -1;
|
|
199 }
|
|
200
|
|
201 static const char *
|
|
202 driver_sqlite_result_get_field_value(struct sql_result *_result,
|
|
203 unsigned int idx)
|
|
204 {
|
|
205 struct sqlite_result *result = (struct sqlite_result *)_result;
|
|
206
|
|
207 return sqlite3_column_text(result->stmt, idx);
|
|
208 }
|
|
209
|
|
210 static const char *
|
|
211 driver_sqlite_result_find_field_value(struct sql_result *result,
|
|
212 const char *field_name)
|
|
213 {
|
|
214 int idx;
|
|
215
|
|
216 idx = driver_sqlite_result_find_field(result, field_name);
|
|
217 if (idx < 0)
|
|
218 return NULL;
|
|
219 return driver_sqlite_result_get_field_value(result, idx);
|
|
220 }
|
|
221
|
|
222 static const char *const *
|
|
223 driver_sqlite_result_get_values(struct sql_result *_result)
|
|
224 {
|
|
225 struct sqlite_result *result = (struct sqlite_result *)_result;
|
|
226 unsigned int i;
|
|
227
|
|
228 for (i = 0; i < result->cols; ++i) {
|
|
229 result->row[i] =
|
|
230 driver_sqlite_result_get_field_value(_result, i);
|
|
231 }
|
|
232
|
|
233 return (const char *const *)result->row;
|
|
234 }
|
|
235
|
|
236 static const char *driver_sqlite_result_get_error(struct sql_result *_result)
|
|
237 {
|
|
238 struct sqlite_result *result = (struct sqlite_result *)_result;
|
|
239 struct sqlite_db *db = (struct sqlite_db *)result->api.db;
|
|
240
|
|
241 return sqlite3_errmsg(db->sqlite);
|
|
242 }
|
|
243
|
|
244 static struct sql_transaction_context *
|
|
245 driver_sqlite_transaction_begin(struct sql_db *_db)
|
|
246 {
|
|
247 struct sqlite_transaction_context *ctx;
|
|
248 struct sqlite_db *db = (struct sqlite_db *)_db;
|
|
249
|
|
250 ctx = i_new(struct sqlite_transaction_context, 1);
|
|
251 ctx->ctx.db = _db;
|
|
252
|
|
253 sql_exec(_db, "BEGIN TRANSACTION");
|
|
254 if (db->rc != SQLITE_OK)
|
|
255 ctx->failed = TRUE;
|
|
256
|
|
257 return &ctx->ctx;
|
|
258 }
|
|
259
|
|
260 static void
|
|
261 driver_sqlite_transaction_rollback(struct sql_transaction_context *_ctx)
|
|
262 {
|
|
263 struct sqlite_transaction_context *ctx =
|
|
264 (struct sqlite_transaction_context *)_ctx;
|
|
265
|
|
266 sql_exec(_ctx->db, "ROLLBACK");
|
|
267 i_free(ctx);
|
|
268 }
|
|
269
|
|
270 static void
|
|
271 driver_sqlite_transaction_commit(struct sql_transaction_context *_ctx,
|
|
272 sql_commit_callback_t *callback, void *context)
|
|
273 {
|
|
274 struct sqlite_transaction_context *ctx =
|
|
275 (struct sqlite_transaction_context *)_ctx;
|
|
276 struct sqlite_db *db = (struct sqlite_db *)ctx->ctx.db;
|
|
277 const char *errmsg;
|
|
278
|
|
279 if (!ctx->failed) {
|
|
280 sql_exec(_ctx->db, "COMMIT");
|
|
281 if (db->rc != SQLITE_OK)
|
|
282 ctx->failed = TRUE;
|
|
283 }
|
|
284
|
|
285 if (ctx->failed) {
|
|
286 errmsg = sqlite3_errmsg(db->sqlite);
|
|
287 callback(errmsg, context);
|
|
288 /* also does i_free(ctx) */
|
|
289 driver_sqlite_transaction_rollback(_ctx);
|
|
290 } else {
|
|
291 callback(NULL, context);
|
|
292 i_free(ctx);
|
|
293 }
|
|
294 }
|
|
295
|
|
296 static int
|
|
297 driver_sqlite_transaction_commit_s(struct sql_transaction_context *_ctx,
|
|
298 const char **error_r)
|
|
299 {
|
|
300 struct sqlite_transaction_context *ctx =
|
|
301 (struct sqlite_transaction_context *)_ctx;
|
|
302 struct sqlite_db *db = (struct sqlite_db *) ctx->ctx.db;
|
|
303
|
|
304 if (ctx->failed) {
|
|
305 /* also does i_free(ctx) */
|
|
306 driver_sqlite_transaction_rollback(_ctx);
|
|
307 return -1;
|
|
308 }
|
|
309
|
|
310 sql_exec(_ctx->db, "COMMIT");
|
|
311 *error_r = sqlite3_errmsg(db->sqlite);
|
|
312 i_free(ctx);
|
|
313 return 0;
|
|
314 }
|
|
315
|
|
316 static void
|
|
317 driver_sqlite_update(struct sql_transaction_context *_ctx, const char *query)
|
|
318 {
|
|
319 struct sqlite_transaction_context *ctx =
|
|
320 (struct sqlite_transaction_context *)_ctx;
|
|
321 struct sqlite_db *db = (struct sqlite_db *)ctx->ctx.db;
|
|
322
|
|
323 if (ctx->failed)
|
|
324 return;
|
|
325
|
|
326 sql_exec(_ctx->db, query);
|
|
327 if (db->rc != SQLITE_OK)
|
|
328 ctx->failed = TRUE;
|
|
329 }
|
|
330
|
|
331 struct sql_db driver_sqlite_db = {
|
|
332 "sqlite",
|
|
333
|
|
334 driver_sqlite_init,
|
|
335 driver_sqlite_deinit,
|
|
336 driver_sqlite_get_flags,
|
|
337 driver_sqlite_connect,
|
|
338 driver_sqlite_exec,
|
|
339 driver_sqlite_query,
|
|
340 driver_sqlite_query_s,
|
|
341
|
|
342 driver_sqlite_transaction_begin,
|
|
343 driver_sqlite_transaction_commit,
|
|
344 driver_sqlite_transaction_commit_s,
|
|
345 driver_sqlite_transaction_rollback,
|
|
346 driver_sqlite_update
|
|
347 };
|
|
348
|
|
349 struct sql_result driver_sqlite_result = {
|
|
350 NULL,
|
|
351
|
|
352 driver_sqlite_result_free,
|
|
353 driver_sqlite_result_next_row,
|
|
354 driver_sqlite_result_get_fields_count,
|
|
355 driver_sqlite_result_get_field_name,
|
|
356 driver_sqlite_result_find_field,
|
|
357 driver_sqlite_result_get_field_value,
|
|
358 driver_sqlite_result_find_field_value,
|
|
359 driver_sqlite_result_get_values,
|
|
360 driver_sqlite_result_get_error,
|
|
361
|
|
362 FALSE
|
|
363 };
|
|
364
|
|
365 static int
|
|
366 driver_sqlite_result_error_next_row(struct sql_result *result __attr_unused__)
|
|
367 {
|
|
368 return -1;
|
|
369 }
|
|
370
|
|
371 struct sql_result driver_sqlite_error_result = {
|
|
372 NULL,
|
|
373
|
|
374 driver_sqlite_result_free,
|
|
375 driver_sqlite_result_error_next_row,
|
|
376 NULL, NULL, NULL, NULL, NULL, NULL,
|
|
377 driver_sqlite_result_get_error,
|
|
378
|
|
379 FALSE
|
|
380 };
|
|
381
|
|
382 #endif
|