2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
18 #include "sqlite_database.h"
23 #include <utils/mutex.h>
25 typedef struct private_sqlite_database_t private_sqlite_database_t
;
28 * private data of sqlite_database
30 struct private_sqlite_database_t
{
35 sqlite_database_t
public;
38 * sqlite database connection
43 * mutex used to lock execute()
49 * Create and run a sqlite stmt using a sql string and args
51 static sqlite3_stmt
* run(private_sqlite_database_t
*this, char *sql
,
54 sqlite3_stmt
*stmt
= NULL
;
55 int params
, i
, res
= SQLITE_OK
;
57 #ifdef HAVE_SQLITE3_PREPARE_V2
58 if (sqlite3_prepare_v2(this->db
, sql
, -1, &stmt
, NULL
) == SQLITE_OK
)
60 if (sqlite3_prepare(this->db
, sql
, -1, &stmt
, NULL
) == SQLITE_OK
)
63 params
= sqlite3_bind_parameter_count(stmt
);
64 for (i
= 1; i
<= params
; i
++)
66 switch (va_arg(*args
, db_type_t
))
70 res
= sqlite3_bind_int(stmt
, i
, va_arg(*args
, int));
75 res
= sqlite3_bind_int64(stmt
, i
, va_arg(*args
, u_int
));
80 const char *text
= va_arg(*args
, const char*);
81 res
= sqlite3_bind_text(stmt
, i
, text
, -1, SQLITE_STATIC
);
86 chunk_t c
= va_arg(*args
, chunk_t
);
87 res
= sqlite3_bind_blob(stmt
, i
, c
.ptr
, c
.len
, SQLITE_STATIC
);
92 res
= sqlite3_bind_double(stmt
, i
, va_arg(*args
, double));
97 res
= sqlite3_bind_null(stmt
, i
);
106 if (res
!= SQLITE_OK
)
114 DBG1("preparing sqlite statement failed: %s", sqlite3_errmsg(this->db
));
116 if (res
!= SQLITE_OK
)
118 DBG1("binding sqlite statement failed: %s", sqlite3_errmsg(this->db
));
119 sqlite3_finalize(stmt
);
126 /** implements enumerator_t */
128 /** associated sqlite statement */
130 /** number of result columns */
134 /** back reference to parent */
135 private_sqlite_database_t
*database
;
136 } sqlite_enumerator_t
;
139 * destroy a sqlite enumerator
141 static void sqlite_enumerator_destroy(sqlite_enumerator_t
*this)
143 sqlite3_finalize(this->stmt
);
144 #if SQLITE_VERSION_NUMBER < 3005000
145 this->database
->mutex
->unlock(this->database
->mutex
);
152 * Implementation of database.query().enumerate
154 static bool sqlite_enumerator_enumerate(sqlite_enumerator_t
*this, ...)
159 switch (sqlite3_step(this->stmt
))
164 DBG1("stepping sqlite statement failed: %s",
165 sqlite3_errmsg(this->database
->db
));
170 va_start(args
, this);
171 for (i
= 0; i
< this->count
; i
++)
173 switch (this->columns
[i
])
177 int *value
= va_arg(args
, int*);
178 *value
= sqlite3_column_int(this->stmt
, i
);
183 u_int
*value
= va_arg(args
, u_int
*);
184 *value
= (u_int
)sqlite3_column_int64(this->stmt
, i
);
189 const unsigned char **value
= va_arg(args
, const unsigned char**);
190 *value
= sqlite3_column_text(this->stmt
, i
);
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
);
202 double *value
= va_arg(args
, double*);
203 *value
= sqlite3_column_double(this->stmt
, i
);
207 DBG1("invalid result type supplied");
216 * Implementation of database_t.query.
218 static enumerator_t
* query(private_sqlite_database_t
*this, char *sql
, ...)
222 sqlite_enumerator_t
*enumerator
= NULL
;
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
);
231 stmt
= run(this, sql
, &args
);
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
++)
243 enumerator
->columns
[i
] = va_arg(args
, db_type_t
);
247 return (enumerator_t
*)enumerator
;
251 * Implementation of database_t.execute.
253 static int execute(private_sqlite_database_t
*this, int *rowid
, char *sql
, ...)
259 /* we need a lock to get our rowid/changes correctly */
260 this->mutex
->lock(this->mutex
);
262 stmt
= run(this, sql
, &args
);
266 if (sqlite3_step(stmt
) == SQLITE_DONE
)
270 *rowid
= sqlite3_last_insert_rowid(this->db
);
272 affected
= sqlite3_changes(this->db
);
276 DBG1("sqlite execute failed: %s", sqlite3_errmsg(this->db
));
278 sqlite3_finalize(stmt
);
280 this->mutex
->unlock(this->mutex
);
285 * Implementation of database_t.get_driver
287 static db_driver_t
get_driver(private_sqlite_database_t
*this)
293 * Implementation of database_t.destroy
295 static void destroy(private_sqlite_database_t
*this)
297 sqlite3_close(this->db
);
298 this->mutex
->destroy(this->mutex
);
305 sqlite_database_t
*sqlite_database_create(char *uri
)
308 private_sqlite_database_t
*this;
311 * parse sqlite:///path/to/file.db uri
313 if (!strneq(uri
, "sqlite://", 9))
319 this = malloc_thing(private_sqlite_database_t
);
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
;
326 this->mutex
= mutex_create(MUTEX_RECURSIVE
);
328 if (sqlite3_open(file
, &this->db
) != SQLITE_OK
)
330 DBG1("opening SQLite database '%s' failed: %s",
331 file
, sqlite3_errmsg(this->db
));
336 return &this->public;