Mercurial > dovecot > core-2.2
annotate src/lib-sql/driver-sqlite.c @ 23017:c1d36f2575c7 default tip
lib-imap: Fix "Don't accept strings with NULs" cherry-pick
author | Timo Sirainen <timo.sirainen@open-xchange.com> |
---|---|
date | Thu, 29 Aug 2019 09:55:25 +0300 |
parents | cb108f786fb4 |
children |
rev | line source |
---|---|
22713
cb108f786fb4
Updated copyright notices to include the year 2018.
Stephan Bosch <stephan.bosch@dovecot.fi>
parents:
22513
diff
changeset
|
1 /* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */ |
3923 | 2 |
3 #include "lib.h" | |
6476
af14dc005392
Let deinit() free all the memory itself after all.
Timo Sirainen <tss@iki.fi>
parents:
6474
diff
changeset
|
4 #include "array.h" |
3923 | 5 #include "str.h" |
19072
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
6 #include "hex-binary.h" |
3923 | 7 #include "sql-api-private.h" |
8 | |
3943
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
9 #ifdef BUILD_SQLITE |
3923 | 10 #include <sqlite3.h> |
11 | |
12 /* retry time if db is busy (in ms) */ | |
8027
62cf70991cf2
extern/static fixes (from a sparse check by Diego Liziero)
Timo Sirainen <tss@iki.fi>
parents:
6476
diff
changeset
|
13 static const int sqlite_busy_timeout = 1000; |
3923 | 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 | |
11253
da497a62cf44
lib-sql: Make driver structs const.
Timo Sirainen <tss@iki.fi>
parents:
10410
diff
changeset
|
37 extern const struct sql_db driver_sqlite_db; |
da497a62cf44
lib-sql: Make driver structs const.
Timo Sirainen <tss@iki.fi>
parents:
10410
diff
changeset
|
38 extern const struct sql_result driver_sqlite_result; |
da497a62cf44
lib-sql: Make driver structs const.
Timo Sirainen <tss@iki.fi>
parents:
10410
diff
changeset
|
39 extern const struct sql_result driver_sqlite_error_result; |
3923 | 40 |
41 static int driver_sqlite_connect(struct sql_db *_db) | |
42 { | |
43 struct sqlite_db *db = (struct sqlite_db *)_db; | |
44 | |
45 if (db->connected) | |
46 return 1; | |
47 | |
48 db->rc = sqlite3_open(db->dbfile, &db->sqlite); | |
49 | |
50 if (db->rc == SQLITE_OK) { | |
51 db->connected = TRUE; | |
52 sqlite3_busy_timeout(db->sqlite, sqlite_busy_timeout); | |
53 return 1; | |
54 } else { | |
55 i_error("sqlite: open(%s) failed: %s", db->dbfile, | |
56 sqlite3_errmsg(db->sqlite)); | |
57 sqlite3_close(db->sqlite); | |
11261
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
58 db->sqlite = NULL; |
3923 | 59 return -1; |
60 } | |
61 } | |
62 | |
11261
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
63 static void driver_sqlite_disconnect(struct sql_db *_db) |
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
64 { |
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
65 struct sqlite_db *db = (struct sqlite_db *)_db; |
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
66 |
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
67 sqlite3_close(db->sqlite); |
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
68 db->sqlite = NULL; |
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
69 } |
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
70 |
6420
a8b515e1a26f
Removed _ prefixes from function names.
Timo Sirainen <tss@iki.fi>
parents:
6411
diff
changeset
|
71 static struct sql_db *driver_sqlite_init_v(const char *connect_string) |
3923 | 72 { |
73 struct sqlite_db *db; | |
6476
af14dc005392
Let deinit() free all the memory itself after all.
Timo Sirainen <tss@iki.fi>
parents:
6474
diff
changeset
|
74 pool_t pool; |
3923 | 75 |
76 i_assert(connect_string != NULL); | |
77 | |
6476
af14dc005392
Let deinit() free all the memory itself after all.
Timo Sirainen <tss@iki.fi>
parents:
6474
diff
changeset
|
78 pool = pool_alloconly_create("sqlite driver", 512); |
af14dc005392
Let deinit() free all the memory itself after all.
Timo Sirainen <tss@iki.fi>
parents:
6474
diff
changeset
|
79 db = p_new(pool, struct sqlite_db, 1); |
af14dc005392
Let deinit() free all the memory itself after all.
Timo Sirainen <tss@iki.fi>
parents:
6474
diff
changeset
|
80 db->pool = pool; |
3923 | 81 db->api = driver_sqlite_db; |
82 db->dbfile = p_strdup(db->pool, connect_string); | |
83 db->connected = FALSE; | |
84 | |
85 return &db->api; | |
86 } | |
87 | |
6420
a8b515e1a26f
Removed _ prefixes from function names.
Timo Sirainen <tss@iki.fi>
parents:
6411
diff
changeset
|
88 static void driver_sqlite_deinit_v(struct sql_db *_db) |
3923 | 89 { |
90 struct sqlite_db *db = (struct sqlite_db *)_db; | |
91 | |
11407
f9e5c73a988b
lib-sql: Don't try to reconnect on deinit or intentional disconnect. Fixes a timeout leak.
Timo Sirainen <tss@iki.fi>
parents:
11406
diff
changeset
|
92 _db->no_reconnect = TRUE; |
11406
8c521fd311c6
mysql, sqlite: Update db state to disconnected on deinit.
Timo Sirainen <tss@iki.fi>
parents:
11261
diff
changeset
|
93 sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED); |
8c521fd311c6
mysql, sqlite: Update db state to disconnected on deinit.
Timo Sirainen <tss@iki.fi>
parents:
11261
diff
changeset
|
94 |
3923 | 95 sqlite3_close(db->sqlite); |
6476
af14dc005392
Let deinit() free all the memory itself after all.
Timo Sirainen <tss@iki.fi>
parents:
6474
diff
changeset
|
96 array_free(&_db->module_contexts); |
6428
7cad076906eb
pool_unref() now takes ** pointer.
Timo Sirainen <tss@iki.fi>
parents:
6420
diff
changeset
|
97 pool_unref(&db->pool); |
3923 | 98 } |
99 | |
4458
3e196acd60b7
sql_escape_string() should return const char *, not char *.
Timo Sirainen <tss@iki.fi>
parents:
4444
diff
changeset
|
100 static const char * |
6411
6a64e64fa3a3
Renamed __attr_*__ to ATTR_*. Renamed __attrs_used__ to ATTRS_DEFINED.
Timo Sirainen <tss@iki.fi>
parents:
5496
diff
changeset
|
101 driver_sqlite_escape_string(struct sql_db *_db ATTR_UNUSED, |
4458
3e196acd60b7
sql_escape_string() should return const char *, not char *.
Timo Sirainen <tss@iki.fi>
parents:
4444
diff
changeset
|
102 const char *string) |
4294 | 103 { |
4444
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
104 const char *p; |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
105 char *dest, *destbegin; |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
106 |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
107 /* find the first ' */ |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
108 for (p = string; *p != '\''; p++) { |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
109 if (*p == '\0') |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
110 return t_strdup_noconst(string); |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
111 } |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
112 |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
113 /* @UNSAFE: escape ' with '' */ |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
114 dest = destbegin = t_buffer_get((p - string) + strlen(string) * 2 + 1); |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
115 |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
116 memcpy(dest, string, p - string); |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
117 dest += p - string; |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
118 |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
119 for (; *p != '\0'; p++) { |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
120 *dest++ = *p; |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
121 if (*p == '\'') |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
122 *dest++ = *p; |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
123 } |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
124 *dest++ = '\0'; |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
125 t_buffer_alloc(dest - destbegin); |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
126 |
d0d04db8e7a6
Escape ' with '' instead of with \'.
Timo Sirainen <tss@iki.fi>
parents:
4294
diff
changeset
|
127 return destbegin; |
4294 | 128 } |
129 | |
3923 | 130 static void driver_sqlite_exec(struct sql_db *_db, const char *query) |
131 { | |
132 struct sqlite_db *db = (struct sqlite_db *)_db; | |
133 | |
8102
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
134 if (driver_sqlite_connect(_db) < 0) |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
135 return; |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
136 |
17398
552cab8feb5f
various - trivial NULL-related sparse cleanups
Phil Carmody <phil@dovecot.fi>
parents:
17130
diff
changeset
|
137 db->rc = sqlite3_exec(db->sqlite, query, NULL, NULL, NULL); |
3923 | 138 if (db->rc != SQLITE_OK) { |
139 i_error("sqlite: exec(%s) failed: %s (%d)", | |
140 query, sqlite3_errmsg(db->sqlite), db->rc); | |
141 } | |
142 } | |
143 | |
144 static void driver_sqlite_query(struct sql_db *db, const char *query, | |
5496
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
145 sql_query_callback_t *callback, void *context) |
3923 | 146 { |
147 struct sql_result *result; | |
148 | |
149 result = sql_query_s(db, query); | |
150 result->callback = TRUE; | |
151 callback(result, context); | |
3946 | 152 result->callback = FALSE; |
9270
f9ebd72a73e8
SQL API change: SQL results can be now refed/unrefed.
Timo Sirainen <tss@iki.fi>
parents:
8102
diff
changeset
|
153 sql_result_unref(result); |
3923 | 154 } |
155 | |
156 static struct sql_result * | |
157 driver_sqlite_query_s(struct sql_db *_db, const char *query) | |
158 { | |
159 struct sqlite_db *db = (struct sqlite_db *)_db; | |
160 struct sqlite_result *result; | |
161 int rc; | |
162 | |
163 result = i_new(struct sqlite_result, 1); | |
164 | |
8102
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
165 if (driver_sqlite_connect(_db) < 0) { |
3923 | 166 result->api = driver_sqlite_error_result; |
167 result->stmt = NULL; | |
168 result->cols = 0; | |
8102
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
169 } else { |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
170 rc = sqlite3_prepare(db->sqlite, query, -1, &result->stmt, NULL); |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
171 if (rc == SQLITE_OK) { |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
172 result->api = driver_sqlite_result; |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
173 result->cols = sqlite3_column_count(result->stmt); |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
174 result->row = i_new(const char *, result->cols); |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
175 } else { |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
176 result->api = driver_sqlite_error_result; |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
177 result->stmt = NULL; |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
178 result->cols = 0; |
277aadb0ef8c
sqlite crashed with dict server. Patch by Bernhard Herzog.
Timo Sirainen <tss@iki.fi>
parents:
8027
diff
changeset
|
179 } |
3923 | 180 } |
181 result->api.db = _db; | |
9270
f9ebd72a73e8
SQL API change: SQL results can be now refed/unrefed.
Timo Sirainen <tss@iki.fi>
parents:
8102
diff
changeset
|
182 result->api.refcount = 1; |
3923 | 183 |
184 return &result->api; | |
185 } | |
186 | |
187 static void driver_sqlite_result_free(struct sql_result *_result) | |
188 { | |
189 struct sqlite_result *result = (struct sqlite_result *)_result; | |
190 struct sqlite_db *db = (struct sqlite_db *) result->api.db; | |
191 int rc; | |
192 | |
3947 | 193 if (_result->callback) |
194 return; | |
195 | |
3923 | 196 if (result->stmt != NULL) { |
197 if ((rc = sqlite3_finalize(result->stmt)) != SQLITE_OK) { | |
198 i_warning("sqlite: finalize failed: %s (%d)", | |
199 sqlite3_errmsg(db->sqlite), rc); | |
200 } | |
201 i_free(result->row); | |
202 } | |
203 i_free(result); | |
204 } | |
205 | |
206 static int driver_sqlite_result_next_row(struct sql_result *_result) | |
207 { | |
208 struct sqlite_result *result = (struct sqlite_result *)_result; | |
209 | |
210 switch (sqlite3_step(result->stmt)) { | |
211 case SQLITE_ROW: | |
212 return 1; | |
213 case SQLITE_DONE: | |
214 return 0; | |
215 default: | |
216 return -1; | |
217 } | |
218 } | |
219 | |
220 static unsigned int | |
221 driver_sqlite_result_get_fields_count(struct sql_result *_result) | |
222 { | |
223 struct sqlite_result *result = (struct sqlite_result *)_result; | |
224 | |
225 return result->cols; | |
226 } | |
227 | |
228 static const char * | |
229 driver_sqlite_result_get_field_name(struct sql_result *_result, | |
230 unsigned int idx) | |
231 { | |
232 struct sqlite_result *result = (struct sqlite_result *)_result; | |
233 | |
234 return sqlite3_column_name(result->stmt, idx); | |
235 } | |
236 | |
237 static int driver_sqlite_result_find_field(struct sql_result *_result, | |
238 const char *field_name) | |
239 { | |
240 struct sqlite_result *result = (struct sqlite_result *)_result; | |
241 unsigned int i; | |
242 | |
243 for (i = 0; i < result->cols; ++i) { | |
244 const char *col = sqlite3_column_name(result->stmt, i); | |
245 | |
246 if (strcmp(col, field_name) == 0) | |
247 return i; | |
248 } | |
249 | |
250 return -1; | |
251 } | |
252 | |
253 static const char * | |
254 driver_sqlite_result_get_field_value(struct sql_result *_result, | |
5496
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
255 unsigned int idx) |
3923 | 256 { |
257 struct sqlite_result *result = (struct sqlite_result *)_result; | |
258 | |
3936
8e827b05047b
Compiler warning fix. Patch by Marcus Rueckert
Timo Sirainen <tss@iki.fi>
parents:
3923
diff
changeset
|
259 return (const char*)sqlite3_column_text(result->stmt, idx); |
3923 | 260 } |
261 | |
5496
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
262 static const unsigned char * |
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
263 driver_sqlite_result_get_field_value_binary(struct sql_result *_result, |
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
264 unsigned int idx, size_t *size_r) |
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
265 { |
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
266 struct sqlite_result *result = (struct sqlite_result *)_result; |
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
267 |
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
268 *size_r = sqlite3_column_bytes(result->stmt, idx); |
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
269 return sqlite3_column_blob(result->stmt, idx); |
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
270 } |
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
271 |
3923 | 272 static const char * |
273 driver_sqlite_result_find_field_value(struct sql_result *result, | |
274 const char *field_name) | |
275 { | |
276 int idx; | |
277 | |
278 idx = driver_sqlite_result_find_field(result, field_name); | |
279 if (idx < 0) | |
280 return NULL; | |
281 return driver_sqlite_result_get_field_value(result, idx); | |
282 } | |
283 | |
284 static const char *const * | |
285 driver_sqlite_result_get_values(struct sql_result *_result) | |
286 { | |
287 struct sqlite_result *result = (struct sqlite_result *)_result; | |
288 unsigned int i; | |
289 | |
290 for (i = 0; i < result->cols; ++i) { | |
291 result->row[i] = | |
292 driver_sqlite_result_get_field_value(_result, i); | |
293 } | |
294 | |
295 return (const char *const *)result->row; | |
296 } | |
297 | |
298 static const char *driver_sqlite_result_get_error(struct sql_result *_result) | |
299 { | |
300 struct sqlite_result *result = (struct sqlite_result *)_result; | |
301 struct sqlite_db *db = (struct sqlite_db *)result->api.db; | |
302 | |
303 return sqlite3_errmsg(db->sqlite); | |
304 } | |
305 | |
306 static struct sql_transaction_context * | |
307 driver_sqlite_transaction_begin(struct sql_db *_db) | |
308 { | |
309 struct sqlite_transaction_context *ctx; | |
310 struct sqlite_db *db = (struct sqlite_db *)_db; | |
311 | |
312 ctx = i_new(struct sqlite_transaction_context, 1); | |
313 ctx->ctx.db = _db; | |
314 | |
315 sql_exec(_db, "BEGIN TRANSACTION"); | |
316 if (db->rc != SQLITE_OK) | |
317 ctx->failed = TRUE; | |
318 | |
319 return &ctx->ctx; | |
320 } | |
321 | |
322 static void | |
323 driver_sqlite_transaction_rollback(struct sql_transaction_context *_ctx) | |
324 { | |
325 struct sqlite_transaction_context *ctx = | |
326 (struct sqlite_transaction_context *)_ctx; | |
327 | |
328 sql_exec(_ctx->db, "ROLLBACK"); | |
329 i_free(ctx); | |
330 } | |
331 | |
332 static void | |
333 driver_sqlite_transaction_commit(struct sql_transaction_context *_ctx, | |
334 sql_commit_callback_t *callback, void *context) | |
335 { | |
336 struct sqlite_transaction_context *ctx = | |
337 (struct sqlite_transaction_context *)_ctx; | |
338 struct sqlite_db *db = (struct sqlite_db *)ctx->ctx.db; | |
339 const char *errmsg; | |
340 | |
341 if (!ctx->failed) { | |
342 sql_exec(_ctx->db, "COMMIT"); | |
343 if (db->rc != SQLITE_OK) | |
344 ctx->failed = TRUE; | |
345 } | |
346 | |
347 if (ctx->failed) { | |
348 errmsg = sqlite3_errmsg(db->sqlite); | |
349 callback(errmsg, context); | |
350 /* also does i_free(ctx) */ | |
351 driver_sqlite_transaction_rollback(_ctx); | |
352 } else { | |
353 callback(NULL, context); | |
354 i_free(ctx); | |
355 } | |
356 } | |
357 | |
358 static int | |
359 driver_sqlite_transaction_commit_s(struct sql_transaction_context *_ctx, | |
360 const char **error_r) | |
361 { | |
362 struct sqlite_transaction_context *ctx = | |
363 (struct sqlite_transaction_context *)_ctx; | |
364 struct sqlite_db *db = (struct sqlite_db *) ctx->ctx.db; | |
365 | |
366 if (ctx->failed) { | |
367 /* also does i_free(ctx) */ | |
368 driver_sqlite_transaction_rollback(_ctx); | |
369 return -1; | |
370 } | |
371 | |
372 sql_exec(_ctx->db, "COMMIT"); | |
373 *error_r = sqlite3_errmsg(db->sqlite); | |
374 i_free(ctx); | |
375 return 0; | |
376 } | |
377 | |
378 static void | |
9888
551c273f4844
lib-sql: Added sql_update_get_rows().
Timo Sirainen <tss@iki.fi>
parents:
9270
diff
changeset
|
379 driver_sqlite_update(struct sql_transaction_context *_ctx, const char *query, |
551c273f4844
lib-sql: Added sql_update_get_rows().
Timo Sirainen <tss@iki.fi>
parents:
9270
diff
changeset
|
380 unsigned int *affected_rows) |
3923 | 381 { |
382 struct sqlite_transaction_context *ctx = | |
383 (struct sqlite_transaction_context *)_ctx; | |
384 struct sqlite_db *db = (struct sqlite_db *)ctx->ctx.db; | |
385 | |
386 if (ctx->failed) | |
387 return; | |
388 | |
389 sql_exec(_ctx->db, query); | |
390 if (db->rc != SQLITE_OK) | |
391 ctx->failed = TRUE; | |
9888
551c273f4844
lib-sql: Added sql_update_get_rows().
Timo Sirainen <tss@iki.fi>
parents:
9270
diff
changeset
|
392 else if (affected_rows != NULL) |
551c273f4844
lib-sql: Added sql_update_get_rows().
Timo Sirainen <tss@iki.fi>
parents:
9270
diff
changeset
|
393 *affected_rows = sqlite3_changes(db->sqlite); |
3923 | 394 } |
395 | |
19072
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
396 static const char * |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
397 driver_sqlite_escape_blob(struct sql_db *_db ATTR_UNUSED, |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
398 const unsigned char *data, size_t size) |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
399 { |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
400 string_t *str = t_str_new(128); |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
401 |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
402 str_append(str, "x'"); |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
403 binary_to_hex_append(str, data, size); |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
404 str_append_c(str, '\''); |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
405 return str_c(str); |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
406 } |
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
407 |
11253
da497a62cf44
lib-sql: Make driver structs const.
Timo Sirainen <tss@iki.fi>
parents:
10410
diff
changeset
|
408 const struct sql_db driver_sqlite_db = { |
11261
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
409 .name = "sqlite", |
1c8cc349ef55
lib-sql: Use generic sql connection pooling code for mysql/pgsql.
Timo Sirainen <tss@iki.fi>
parents:
11253
diff
changeset
|
410 .flags = SQL_DB_FLAG_BLOCKING, |
3923 | 411 |
10410
b757dab45756
Removed MEMBER() macro. Require C99 style struct initializer.
Timo Sirainen <tss@iki.fi>
parents:
9888
diff
changeset
|
412 .v = { |
22513
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
413 .init = driver_sqlite_init_v, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
414 .deinit = driver_sqlite_deinit_v, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
415 .connect = driver_sqlite_connect, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
416 .disconnect = driver_sqlite_disconnect, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
417 .escape_string = driver_sqlite_escape_string, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
418 .exec = driver_sqlite_exec, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
419 .query = driver_sqlite_query, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
420 .query_s = driver_sqlite_query_s, |
3923 | 421 |
22513
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
422 .transaction_begin = driver_sqlite_transaction_begin, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
423 .transaction_commit = driver_sqlite_transaction_commit, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
424 .transaction_commit_s = driver_sqlite_transaction_commit_s, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
425 .transaction_rollback = driver_sqlite_transaction_rollback, |
19072
113f4e32cb19
lib-sql: Implemented sql_escape_blob()
Timo Sirainen <tss@iki.fi>
parents:
18137
diff
changeset
|
426 |
22513
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
427 .update = driver_sqlite_update, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
428 |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
429 .escape_blob = driver_sqlite_escape_blob, |
6474
46c3e1ee196f
Added module_contexts to struct sql_db.
Timo Sirainen <tss@iki.fi>
parents:
6428
diff
changeset
|
430 } |
3923 | 431 }; |
432 | |
11253
da497a62cf44
lib-sql: Make driver structs const.
Timo Sirainen <tss@iki.fi>
parents:
10410
diff
changeset
|
433 const struct sql_result driver_sqlite_result = { |
10410
b757dab45756
Removed MEMBER() macro. Require C99 style struct initializer.
Timo Sirainen <tss@iki.fi>
parents:
9888
diff
changeset
|
434 .v = { |
22513
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
435 .free = driver_sqlite_result_free, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
436 .next_row = driver_sqlite_result_next_row, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
437 .get_fields_count = driver_sqlite_result_get_fields_count, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
438 .get_field_name = driver_sqlite_result_get_field_name, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
439 .find_field = driver_sqlite_result_find_field, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
440 .get_field_value = driver_sqlite_result_get_field_value, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
441 .get_field_value_binary = driver_sqlite_result_get_field_value_binary, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
442 .find_field_value = driver_sqlite_result_find_field_value, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
443 .get_values = driver_sqlite_result_get_values, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
444 .get_error = driver_sqlite_result_get_error, |
5496
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
445 } |
3923 | 446 }; |
447 | |
448 static int | |
6411
6a64e64fa3a3
Renamed __attr_*__ to ATTR_*. Renamed __attrs_used__ to ATTRS_DEFINED.
Timo Sirainen <tss@iki.fi>
parents:
5496
diff
changeset
|
449 driver_sqlite_result_error_next_row(struct sql_result *result ATTR_UNUSED) |
3923 | 450 { |
451 return -1; | |
452 } | |
453 | |
11253
da497a62cf44
lib-sql: Make driver structs const.
Timo Sirainen <tss@iki.fi>
parents:
10410
diff
changeset
|
454 const struct sql_result driver_sqlite_error_result = { |
10410
b757dab45756
Removed MEMBER() macro. Require C99 style struct initializer.
Timo Sirainen <tss@iki.fi>
parents:
9888
diff
changeset
|
455 .v = { |
22513
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
456 .free = driver_sqlite_result_free, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
457 .next_row = driver_sqlite_result_error_next_row, |
59b0c5ee8adf
lib-sql: Explicitly specify used *_vfuncs methods for drivers.
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22354
diff
changeset
|
458 .get_error = driver_sqlite_result_get_error, |
5496
72ee0521dfaf
Added sql_result_setup_fetch() which makes it easier to fetch rows into
Timo Sirainen <tss@iki.fi>
parents:
4458
diff
changeset
|
459 } |
3923 | 460 }; |
461 | |
15199
73916b7be94e
Plugin ABI version checking improvements.
Timo Sirainen <tss@iki.fi>
parents:
15188
diff
changeset
|
462 const char *driver_sqlite_version = DOVECOT_ABI_VERSION; |
12676
b8896cfa38cb
lib-sql: Include Dovecot version number check when loading SQL plugins.
Timo Sirainen <tss@iki.fi>
parents:
11407
diff
changeset
|
463 |
3943
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
464 void driver_sqlite_init(void); |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
465 void driver_sqlite_deinit(void); |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
466 |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
467 void driver_sqlite_init(void) |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
468 { |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
469 sql_driver_register(&driver_sqlite_db); |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
470 } |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
471 |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
472 void driver_sqlite_deinit(void) |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
473 { |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
474 sql_driver_unregister(&driver_sqlite_db); |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
475 } |
cbe5c6772e0d
Added support for dynamically building SQL drivers.
Timo Sirainen <tss@iki.fi>
parents:
3936
diff
changeset
|
476 |
3923 | 477 #endif |