c1927b5bef124b5fd92bc895a736b1bd9341ecd1
[strongswan.git] / src / libstrongswan / plugins / sqlite / sqlite_database.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "sqlite_database.h"
19
20 #include <sqlite3.h>
21 #include <library.h>
22 #include <debug.h>
23 #include <utils/mutex.h>
24
25 typedef struct private_sqlite_database_t private_sqlite_database_t;
26
27 /**
28 * private data of sqlite_database
29 */
30 struct private_sqlite_database_t {
31
32 /**
33 * public functions
34 */
35 sqlite_database_t public;
36
37 /**
38 * sqlite database connection
39 */
40 sqlite3 *db;
41
42 /**
43 * mutex used to lock execute()
44 */
45 mutex_t *mutex;
46 };
47
48 /**
49 * Create and run a sqlite stmt using a sql string and args
50 */
51 static sqlite3_stmt* run(private_sqlite_database_t *this, char *sql,
52 va_list *args)
53 {
54 sqlite3_stmt *stmt = NULL;
55 int params, i, res = SQLITE_OK;
56
57 #ifdef HAVE_SQLITE3_PREPARE_V2
58 if (sqlite3_prepare_v2(this->db, sql, -1, &stmt, NULL) == SQLITE_OK)
59 #else
60 if (sqlite3_prepare(this->db, sql, -1, &stmt, NULL) == SQLITE_OK)
61 #endif
62 {
63 params = sqlite3_bind_parameter_count(stmt);
64 for (i = 1; i <= params; i++)
65 {
66 switch (va_arg(*args, db_type_t))
67 {
68 case DB_INT:
69 {
70 res = sqlite3_bind_int(stmt, i, va_arg(*args, int));
71 break;
72 }
73 case DB_UINT:
74 {
75 res = sqlite3_bind_int64(stmt, i, va_arg(*args, u_int));
76 break;
77 }
78 case DB_TEXT:
79 {
80 const char *text = va_arg(*args, const char*);
81 res = sqlite3_bind_text(stmt, i, text, -1, SQLITE_STATIC);
82 break;
83 }
84 case DB_BLOB:
85 {
86 chunk_t c = va_arg(*args, chunk_t);
87 res = sqlite3_bind_blob(stmt, i, c.ptr, c.len, SQLITE_STATIC);
88 break;
89 }
90 case DB_DOUBLE:
91 {
92 res = sqlite3_bind_double(stmt, i, va_arg(*args, double));
93 break;
94 }
95 case DB_NULL:
96 {
97 res = sqlite3_bind_null(stmt, i);
98 break;
99 }
100 default:
101 {
102 res = SQLITE_MISUSE;
103 break;
104 }
105 }
106 if (res != SQLITE_OK)
107 {
108 break;
109 }
110 }
111 }
112 else
113 {
114 DBG1("preparing sqlite statement failed: %s", sqlite3_errmsg(this->db));
115 }
116 if (res != SQLITE_OK)
117 {
118 DBG1("binding sqlite statement failed: %s", sqlite3_errmsg(this->db));
119 sqlite3_finalize(stmt);
120 return NULL;
121 }
122 return stmt;
123 }
124
125 typedef struct {
126 /** implements enumerator_t */
127 enumerator_t public;
128 /** associated sqlite statement */
129 sqlite3_stmt *stmt;
130 /** number of result columns */
131 int count;
132 /** column types */
133 db_type_t *columns;
134 /** back reference to parent */
135 private_sqlite_database_t *database;
136 } sqlite_enumerator_t;
137
138 /**
139 * destroy a sqlite enumerator
140 */
141 static void sqlite_enumerator_destroy(sqlite_enumerator_t *this)
142 {
143 sqlite3_finalize(this->stmt);
144 #if SQLITE_VERSION_NUMBER < 3005000
145 this->database->mutex->unlock(this->database->mutex);
146 #endif
147 free(this->columns);
148 free(this);
149 }
150
151 /**
152 * Implementation of database.query().enumerate
153 */
154 static bool sqlite_enumerator_enumerate(sqlite_enumerator_t *this, ...)
155 {
156 int i;
157 va_list args;
158
159 switch (sqlite3_step(this->stmt))
160 {
161 case SQLITE_ROW:
162 break;
163 default:
164 DBG1("stepping sqlite statement failed: %s",
165 sqlite3_errmsg(this->database->db));
166 /* fall */
167 case SQLITE_DONE:
168 return FALSE;
169 }
170 va_start(args, this);
171 for (i = 0; i < this->count; i++)
172 {
173 switch (this->columns[i])
174 {
175 case DB_INT:
176 {
177 int *value = va_arg(args, int*);
178 *value = sqlite3_column_int(this->stmt, i);
179 break;
180 }
181 case DB_UINT:
182 {
183 u_int *value = va_arg(args, u_int*);
184 *value = (u_int)sqlite3_column_int64(this->stmt, i);
185 break;
186 }
187 case DB_TEXT:
188 {
189 const unsigned char **value = va_arg(args, const unsigned char**);
190 *value = sqlite3_column_text(this->stmt, i);
191 break;
192 }
193 case DB_BLOB:
194 {
195 chunk_t *chunk = va_arg(args, chunk_t*);
196 chunk->len = sqlite3_column_bytes(this->stmt, i);
197 chunk->ptr = (u_char*)sqlite3_column_blob(this->stmt, i);
198 break;
199 }
200 case DB_DOUBLE:
201 {
202 double *value = va_arg(args, double*);
203 *value = sqlite3_column_double(this->stmt, i);
204 break;
205 }
206 default:
207 DBG1("invalid result type supplied");
208 return FALSE;
209 }
210 }
211 va_end(args);
212 return TRUE;
213 }
214
215 /**
216 * Implementation of database_t.query.
217 */
218 static enumerator_t* query(private_sqlite_database_t *this, char *sql, ...)
219 {
220 sqlite3_stmt *stmt;
221 va_list args;
222 sqlite_enumerator_t *enumerator = NULL;
223 int i;
224
225 #if SQLITE_VERSION_NUMBER < 3005000
226 /* sqlite connections prior to 3.5 may be used by a single thread only, */
227 this->mutex->lock(this->mutex);
228 #endif
229
230 va_start(args, sql);
231 stmt = run(this, sql, &args);
232 if (stmt)
233 {
234 enumerator = malloc_thing(sqlite_enumerator_t);
235 enumerator->public.enumerate = (void*)sqlite_enumerator_enumerate;
236 enumerator->public.destroy = (void*)sqlite_enumerator_destroy;
237 enumerator->stmt = stmt;
238 enumerator->count = sqlite3_column_count(stmt);
239 enumerator->columns = malloc(sizeof(db_type_t) * enumerator->count);
240 enumerator->database = this;
241 for (i = 0; i < enumerator->count; i++)
242 {
243 enumerator->columns[i] = va_arg(args, db_type_t);
244 }
245 }
246 va_end(args);
247 return (enumerator_t*)enumerator;
248 }
249
250 /**
251 * Implementation of database_t.execute.
252 */
253 static int execute(private_sqlite_database_t *this, int *rowid, char *sql, ...)
254 {
255 sqlite3_stmt *stmt;
256 int affected = -1;
257 va_list args;
258
259 /* we need a lock to get our rowid/changes correctly */
260 this->mutex->lock(this->mutex);
261 va_start(args, sql);
262 stmt = run(this, sql, &args);
263 va_end(args);
264 if (stmt)
265 {
266 if (sqlite3_step(stmt) == SQLITE_DONE)
267 {
268 if (rowid)
269 {
270 *rowid = sqlite3_last_insert_rowid(this->db);
271 }
272 affected = sqlite3_changes(this->db);
273 }
274 else
275 {
276 DBG1("sqlite execute failed: %s", sqlite3_errmsg(this->db));
277 }
278 sqlite3_finalize(stmt);
279 }
280 this->mutex->unlock(this->mutex);
281 return affected;
282 }
283
284 /**
285 * Implementation of database_t.get_driver
286 */
287 static db_driver_t get_driver(private_sqlite_database_t *this)
288 {
289 return DB_SQLITE;
290 }
291
292 /**
293 * Implementation of database_t.destroy
294 */
295 static void destroy(private_sqlite_database_t *this)
296 {
297 sqlite3_close(this->db);
298 this->mutex->destroy(this->mutex);
299 free(this);
300 }
301
302 /*
303 * see header file
304 */
305 sqlite_database_t *sqlite_database_create(char *uri)
306 {
307 char *file;
308 private_sqlite_database_t *this;
309
310 /**
311 * parse sqlite:///path/to/file.db uri
312 */
313 if (!strneq(uri, "sqlite://", 9))
314 {
315 return NULL;
316 }
317 file = uri + 9;
318
319 this = malloc_thing(private_sqlite_database_t);
320
321 this->public.db.query = (enumerator_t* (*)(database_t *this, char *sql, ...))query;
322 this->public.db.execute = (int (*)(database_t *this, int *rowid, char *sql, ...))execute;
323 this->public.db.get_driver = (db_driver_t(*)(database_t*))get_driver;
324 this->public.db.destroy = (void(*)(database_t*))destroy;
325
326 this->mutex = mutex_create(MUTEX_RECURSIVE);
327
328 if (sqlite3_open(file, &this->db) != SQLITE_OK)
329 {
330 DBG1("opening SQLite database '%s' failed: %s",
331 file, sqlite3_errmsg(this->db));
332 destroy(this);
333 return NULL;
334 }
335
336 return &this->public;
337 }
338