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 /** reference to db connection */
136 } sqlite_enumerator_t
;
139 * destroy a sqlite enumerator
141 static void sqlite_enumerator_destroy(sqlite_enumerator_t
*this)
143 sqlite3_finalize(this->stmt
);
149 * Implementation of database.query().enumerate
151 static bool sqlite_enumerator_enumerate(sqlite_enumerator_t
*this, ...)
156 switch (sqlite3_step(this->stmt
))
161 DBG1("stepping sqlite statement failed: %s", sqlite3_errmsg(this->db
));
166 va_start(args
, this);
167 for (i
= 0; i
< this->count
; i
++)
169 switch (this->columns
[i
])
173 int *value
= va_arg(args
, int*);
174 *value
= sqlite3_column_int(this->stmt
, i
);
179 u_int
*value
= va_arg(args
, u_int
*);
180 *value
= (u_int
)sqlite3_column_int64(this->stmt
, i
);
185 const unsigned char **value
= va_arg(args
, const unsigned char**);
186 *value
= sqlite3_column_text(this->stmt
, i
);
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
);
198 double *value
= va_arg(args
, double*);
199 *value
= sqlite3_column_double(this->stmt
, i
);
203 DBG1("invalid result type supplied");
212 * Implementation of database_t.query.
214 static enumerator_t
* query(private_sqlite_database_t
*this, char *sql
, ...)
218 sqlite_enumerator_t
*enumerator
= NULL
;
223 stmt
= run(this, sql
, &args
);
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
++)
235 enumerator
->columns
[i
] = va_arg(args
, db_type_t
);
239 return (enumerator_t
*)enumerator
;
243 * Implementation of database_t.execute.
245 static int execute(private_sqlite_database_t
*this, int *rowid
, char *sql
, ...)
251 /* we need a lock to get our rowid/changes correctly */
252 this->mutex
->lock(this->mutex
);
254 stmt
= run(this, sql
, &args
);
258 if (sqlite3_step(stmt
) == SQLITE_DONE
)
262 *rowid
= sqlite3_last_insert_rowid(this->db
);
264 affected
= sqlite3_changes(this->db
);
268 DBG1("sqlite execute failed: %s", sqlite3_errmsg(this->db
));
270 sqlite3_finalize(stmt
);
272 this->mutex
->unlock(this->mutex
);
277 * Implementation of database_t.destroy
279 static void destroy(private_sqlite_database_t
*this)
281 sqlite3_close(this->db
);
282 this->mutex
->destroy(this->mutex
);
289 sqlite_database_t
*sqlite_database_create(char *uri
)
292 private_sqlite_database_t
*this;
295 * parse sqlite:///path/to/file.db uri
297 if (!strneq(uri
, "sqlite://", 9))
303 this = malloc_thing(private_sqlite_database_t
);
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
;
309 this->mutex
= mutex_create(MUTEX_DEFAULT
);
311 if (sqlite3_open(file
, &this->db
) != SQLITE_OK
)
313 DBG1("opening SQLite database '%s' failed: %s",
314 file
, sqlite3_errmsg(this->db
));
319 return &this->public;