99f86a84a583a5f3cd771d1518b75e73ac63788f
[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 /** reference to db connection */
135 sqlite3 *db;
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 free(this->columns);
145 free(this);
146 }
147
148 /**
149 * Implementation of database.query().enumerate
150 */
151 static bool sqlite_enumerator_enumerate(sqlite_enumerator_t *this, ...)
152 {
153 int i;
154 va_list args;
155
156 switch (sqlite3_step(this->stmt))
157 {
158 case SQLITE_ROW:
159 break;
160 default:
161 DBG1("stepping sqlite statement failed: %s", sqlite3_errmsg(this->db));
162 /* fall */
163 case SQLITE_DONE:
164 return FALSE;
165 }
166 va_start(args, this);
167 for (i = 0; i < this->count; i++)
168 {
169 switch (this->columns[i])
170 {
171 case DB_INT:
172 {
173 int *value = va_arg(args, int*);
174 *value = sqlite3_column_int(this->stmt, i);
175 break;
176 }
177 case DB_UINT:
178 {
179 u_int *value = va_arg(args, u_int*);
180 *value = (u_int)sqlite3_column_int64(this->stmt, i);
181 break;
182 }
183 case DB_TEXT:
184 {
185 const unsigned char **value = va_arg(args, const unsigned char**);
186 *value = sqlite3_column_text(this->stmt, i);
187 break;
188 }
189 case DB_BLOB:
190 {
191 chunk_t *chunk = va_arg(args, chunk_t*);
192 chunk->len = sqlite3_column_bytes(this->stmt, i);
193 chunk->ptr = (u_char*)sqlite3_column_blob(this->stmt, i);
194 break;
195 }
196 case DB_DOUBLE:
197 {
198 double *value = va_arg(args, double*);
199 *value = sqlite3_column_double(this->stmt, i);
200 break;
201 }
202 default:
203 DBG1("invalid result type supplied");
204 return FALSE;
205 }
206 }
207 va_end(args);
208 return TRUE;
209 }
210
211 /**
212 * Implementation of database_t.query.
213 */
214 static enumerator_t* query(private_sqlite_database_t *this, char *sql, ...)
215 {
216 sqlite3_stmt *stmt;
217 va_list args;
218 sqlite_enumerator_t *enumerator = NULL;
219 int i;
220
221
222 va_start(args, sql);
223 stmt = run(this, sql, &args);
224 if (stmt)
225 {
226 enumerator = malloc_thing(sqlite_enumerator_t);
227 enumerator->public.enumerate = (void*)sqlite_enumerator_enumerate;
228 enumerator->public.destroy = (void*)sqlite_enumerator_destroy;
229 enumerator->stmt = stmt;
230 enumerator->count = sqlite3_column_count(stmt);
231 enumerator->columns = malloc(sizeof(db_type_t) * enumerator->count);
232 enumerator->db = this->db;
233 for (i = 0; i < enumerator->count; i++)
234 {
235 enumerator->columns[i] = va_arg(args, db_type_t);
236 }
237 }
238 va_end(args);
239 return (enumerator_t*)enumerator;
240 }
241
242 /**
243 * Implementation of database_t.execute.
244 */
245 static int execute(private_sqlite_database_t *this, int *rowid, char *sql, ...)
246 {
247 sqlite3_stmt *stmt;
248 int affected = -1;
249 va_list args;
250
251 /* we need a lock to get our rowid/changes correctly */
252 this->mutex->lock(this->mutex);
253 va_start(args, sql);
254 stmt = run(this, sql, &args);
255 va_end(args);
256 if (stmt)
257 {
258 if (sqlite3_step(stmt) == SQLITE_DONE)
259 {
260 if (rowid)
261 {
262 *rowid = sqlite3_last_insert_rowid(this->db);
263 }
264 affected = sqlite3_changes(this->db);
265 }
266 else
267 {
268 DBG1("sqlite execute failed: %s", sqlite3_errmsg(this->db));
269 }
270 sqlite3_finalize(stmt);
271 }
272 this->mutex->unlock(this->mutex);
273 return affected;
274 }
275
276 /**
277 * Implementation of database_t.destroy
278 */
279 static void destroy(private_sqlite_database_t *this)
280 {
281 sqlite3_close(this->db);
282 this->mutex->destroy(this->mutex);
283 free(this);
284 }
285
286 /*
287 * see header file
288 */
289 sqlite_database_t *sqlite_database_create(char *uri)
290 {
291 char *file;
292 private_sqlite_database_t *this;
293
294 /**
295 * parse sqlite:///path/to/file.db uri
296 */
297 if (!strneq(uri, "sqlite://", 9))
298 {
299 return NULL;
300 }
301 file = uri + 9;
302
303 this = malloc_thing(private_sqlite_database_t);
304
305 this->public.db.query = (enumerator_t* (*)(database_t *this, char *sql, ...))query;
306 this->public.db.execute = (int (*)(database_t *this, int *rowid, char *sql, ...))execute;
307 this->public.db.destroy = (void(*)(database_t*))destroy;
308
309 this->mutex = mutex_create(MUTEX_DEFAULT);
310
311 if (sqlite3_open(file, &this->db) != SQLITE_OK)
312 {
313 DBG1("opening SQLite database '%s' failed: %s",
314 file, sqlite3_errmsg(this->db));
315 destroy(this);
316 return NULL;
317 }
318
319 return &this->public;
320 }
321