OpenDNSSEC-enforcer  1.4.9
database_access_lite.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /*+
28  * database_access_lite - database Access Functions
29  *
30  * Description:
31  * Holds miscellaneous utility functions associated with the sqlite
32  * database.
33  *
34  * This particular file holds encapsulations of the underlying access
35  * functions - querying/modifying the database and retrieving results.
36 -*/
37 
38 #include <stdarg.h>
39 #include <string.h>
40 #include <stdio.h>
41 #include <time.h>
42 #include <unistd.h>
43 
44 #include <sqlite3.h>
45 
46 #include "ksm/dbsdef.h"
47 #include "ksm/database.h"
48 #include "ksm/debug.h"
49 #include "ksm/memory.h"
50 #include "ksm/message.h"
51 #include "ksm/string_util.h"
52 
53 #define MIN(x, y) ((x) < (y) ? (x) : (y))
54 #define MAX(x, y) ((x) > (y) ? (x) : (y))
55 
56 /* possible wrapper for sqlite3_step which will wait for a block to go */
57 int sqlite3_my_step(sqlite3_stmt *pStmt)
58 {
59  int rc;
60  struct timeval tv;
61 
62  rc = sqlite3_step(pStmt);
63 
64  while (rc == SQLITE_LOCKED || rc == SQLITE_BUSY) {
65  tv.tv_sec = 1;
66  tv.tv_usec = 0;
67  select(0, NULL, NULL, NULL, &tv);
68 
69  rc = sqlite3_step(pStmt);
70  }
71 
72  return rc;
73 
74 }
75 
76 /*+
77  * DbExecuteSqlStatement - Execute SQL Statement
78  *
79  * Description:
80  * A wrapper round sqlite3_prepare_v2 and one call to sqlite3_step
81  * that outputs the query being executed if the appropriate debug flag
82  * is set.
83  *
84  * Arguments:
85  * DB_HANDLE handle
86  * Handle to the currently opened database.
87  *
88  * const char* stmt_str
89  * SQL statement to execute.
90  *
91  * Returns:
92  * int
93  * Any return value from sqlite3_prepare_v2 or sqlite3_step.
94  * SQLITE_OK if the command executes correctly
95 -*/
96 
97 static int DbExecuteSqlStatement(DB_HANDLE handle, const char* stmt_str, DB_RESULT* result)
98 {
99  int rc;
100  DbgOutput(DBG_M_SQL, "%s\n", stmt_str);
101  rc = sqlite3_prepare_v2((sqlite3*) handle, stmt_str, -1, &((*result)->data), 0);
102  if( rc != SQLITE_OK )
103  {
104  return rc;
105  }
106 
107  return sqlite3_step((*result)->data);
108 }
109 
110 
111 
112 /*+
113  * DbExecuteSql - Execute SQL Statement
114  *
115  * Description:
116  * Executes the given SQL statement and returns the results (if any).
117  *
118  * Arguments:
119  * DB_HANDLE handle
120  * Handle to the currently opened database.
121  *
122  * const char* stmt_str
123  * Statement to execute.
124  *
125  * DB_RESULT* result
126  * Pointer to the result set is put here. It must be freed by
127  * DbFreeResult(). This is NULL if no data is returned; on error, the
128  * value is undefined.
129  *
130  * Returns:
131  * int
132  * 0 Success
133  * Other Error code. A message will have been output.
134 -*/
135 
136 int DbExecuteSql(DB_HANDLE handle, const char* stmt_str, DB_RESULT* result)
137 {
138  const char* errmsg = NULL; /* Error message from MySql on failure */
139  int status = 0; /* Status return */
140 
141  /* Argument check */
142 
143  if ((!handle) || (!stmt_str) || (*stmt_str == '\0') || (! result)) {
144  status = MsgLog(DBS_INVARG, "DbExecuteSql");
145  return status;
146  }
147 
148  /* Allocate the result structure */
149 
150  *result = (DB_RESULT) MemCalloc(1, sizeof(struct db_result));
151  (*result)->magic = DB_RESULT_MAGIC;
152  (*result)->handle = handle;
153  (*result)->first_row = 1;
154 
155  /* Execute statement */
156 
157  status = DbExecuteSqlStatement(handle, stmt_str, result);
158  if (status == SQLITE_ROW) {
159  /* Reset the status so that it is consistent across db engines */
160  status = 0;
161 
162  /* Check the pointer to the result set */
163  if ((*result)->data == NULL) {
164 
165  /*
166  * No result set, so could be some error. See if this is the case
167  * by checking if there is error text. If not, there are no results
168  * from the SQL - it could have been a statement such as DELETE or
169  * INSERT.
170  */
171 
172  errmsg = DbErrmsg(handle);
173  if (errmsg && *errmsg) {
174 
175  /* Error text, so error occurred. Output message & tidy up */
176 
177  status = MsgLog(DBS_SQLFAIL, errmsg);
178  }
179  /*
180  * else {
181  *
182  * No error, so we just don't have any results.
183  * }
184  */
185 
186  /*
187  * Regardless of what heppened, there is no result set, so free up
188  * allocated memory.
189  */
190 
191  MemFree(*result);
192  *result = NULL;
193  }
194  else {
195 
196  /*
197  * Success. "result" holds the result set. Store the number of
198  * fields along with the length of each one for possible later use.
199  */
200 
201  (*result)->count = sqlite3_data_count((sqlite3_stmt*) (*result)->data);
202  }
203  }
204  else if (status == SQLITE_DONE)
205  {
206  /* Correct for one-shot statements like insert etc
207  * finalise the statement to avoid locking the database */
208  status = sqlite3_finalize((sqlite3_stmt*) (*result)->data);
209 
210  MemFree(*result);
211  *result = NULL;
212  }
213  else {
214 
215  /* Query failed. Log the error and free up the structure */
216 
217  status = MsgLog(DBS_SQLFAIL, DbErrmsg(handle));
218  MemFree(*result);
219  *result = NULL;
220  }
221 
222  return status;
223 }
224 
225 /*+
226  * DbFreeResult - Free Result
227  *
228  * Description:
229  * Frees up resources allocated for the result by DbExecuteSql.
230  *
231  * Arguments:
232  * DB_RESULT result
233  * Handle to the query result. May be NULL, in which case this
234  * function is a no-op.
235  *
236  * If invalid, an error message will be output.
237 -*/
238 
240 {
241  if (result) {
242  if (result->magic == DB_RESULT_MAGIC) {
243 
244  /* Free up data */
245 
246  sqlite3_finalize(result->data);
247  MemFree(result);
248  result = NULL;
249  }
250  else {
251 
252  /* Invalid structure - output a warning but do nothing */
253 
254  (void) MsgLog(DBS_INVARG, "DbFreeResult");
255  }
256  }
257 
258  return;
259 }
260 
261 
262 
263 /*+
264  * DbFetchRow - Fetch Row from Result
265  *
266  * Description:
267  * Steps to the next row in the result set.
268  *
269  * Arguments:
270  * DB_RESULT result
271  * The result handle returned by the call to DbExecuteSql.
272  *
273  * DB_ROW* row
274  * This is really just the same as RESULT for sqlite, but it is left
275  * in for MySQL compatibility.
276  *
277  * Returns:
278  * int
279  * 0 Success, row information returned
280  * -1 Success, no more rows for this result
281  * Other Error code or error number from DbErrno().
282 -*/
283 
284 int DbFetchRow(DB_RESULT result, DB_ROW* row)
285 {
286  int status = 0; /* Status return */
287 
288  if (result && (result->magic == DB_RESULT_MAGIC) && row) {
289 
290  /* There is a result structure (and row pointer), do something */
291 
292  if (result->first_row == 1)
293  {
294  result->first_row = 0;
295  *row = (DB_ROW) MemCalloc(1, sizeof(struct db_row));
296  (*row)->magic = DB_ROW_MAGIC;
297  (*row)->result=result;
298  }
299  else
300  {
301  status = sqlite3_step(result->data);
302  if (status == SQLITE_DONE) {
303  /* End of result set */
304  /* leave freeing the row to the calling function */
305  /* *row = NULL; */
306 
307  status = -1;
308  }
309  else if (status == SQLITE_ROW)
310  {
311  *row = (DB_ROW) MemCalloc(1, sizeof(struct db_row));
312  (*row)->magic = DB_ROW_MAGIC;
313  (*row)->result=result;
314  status = 0;
315  }
316  }
317  }
318  else if (row) {
319  *row = NULL; /* no results to report */
320  status = -1;
321  }
322  else{
323  status = MsgLog(DBS_INVARG, "DbFetchRow");
324 
325  }
326 
327  return status;
328 }
329 
330 
331 
332 /*+
333  * DbFreeRow - Free Row
334  *
335  * Description:
336  * Frees up resources allocated for the row.
337  *
338  * Arguments:
339  * DB_RESULT result
340  * Handle to the query result. May be NULL, in which case this
341  * function is a no-op.
342 -*/
343 
344 void DbFreeRow(DB_ROW row)
345 {
346  if (row) {
347  if (row->magic == DB_ROW_MAGIC) {
348  MemFree(row);
349  }
350  else {
351 
352  /* Output warning, but otherwise do nothing */
353 
354  (void) MsgLog(DBS_INVARG, "DbFreeRow");
355  }
356  }
357 
358  return;
359 }
360 
361 
362 
363 /*+
364  * DbString - Return String Value
365  *
366  * Description:
367  * Returns string value from the current row.
368  *
369  * Arguments:
370  * DB_ROW row
371  * Pointer to the row object.
372  *
373  * int field_index
374  * Index of the value required.
375  *
376  * char** result
377  * Value of the field. It is up to the caller to free it with
378  * a call to DbStringFree(). Note that this can be NULL if the
379  * corresponding field is NULL.
380  *
381  * Returns:
382  * int
383  * 0 Success
384  * Other Some error. A message will have been output
385 -*/
386 
387 int DbString(DB_ROW row, int field_index, char** result)
388 {
389  int status = 0; /* Status return */
390  unsigned long width; /* Width of column */
391 
392  /* Check arguments */
393 
394  if (row && (row->magic == DB_ROW_MAGIC) && result) {
395 
396  /* Is the index requested valid? */
397 
398  if ((field_index >= 0) && (field_index < row->result->count)) {
399 
400  /* Get the width of the column */
401 
402  width = sqlite3_column_bytes(row->result->data, field_index);
403 
404  /* Get string into null-terminated form */
405 
406  if (sqlite3_column_text(row->result->data, field_index) != NULL) {
407  /* TODO replece the below with strdup or StrStrdup ? */
408  *result = MemMalloc(width + 1);
409  memcpy(*result, sqlite3_column_text(row->result->data, field_index), width);
410  (*result)[width] = 0;
411  }
412  else {
413  *result = NULL;
414  }
415  }
416  else {
417 
418  /* Invalid field, tell the user */
419 
420  status = MsgLog(DBS_INVINDEX, field_index, row->result->count-1);
421  }
422 
423  }
424  else {
425 
426  /* Problem with the command arguments */
427 
428  status = MsgLog(DBS_INVARG, "DbString");
429  }
430 
431  return status;
432 
433 }
434 
435 
436 /*+
437  * DbStringFree - Free String Returned by DbString
438  *
439  * Description:
440  * Frees the pointer-to string.
441  *
442  * Arguments:
443  * char* string
444  * String allocated by DbString. On exit, this pointer is invalid.
445 -*/
446 
447 void DbStringFree(char* string)
448 {
449  MemFree(string);
450 }
451 
452 /*+
453  * DbBeginTransaction - Start a (non-nested) transaction
454  *
455  * Description:
456  *
457  *
458  * Arguments:
459  * NONE
460 -*/
461 
463 {
464  const char* sql = "begin transaction";
465  return DbExecuteSqlNoResult(DbHandle(), sql);
466 }
467 
468 /*+
469  * DbCommit - End a (non-nested) transaction by commiting it
470  *
471  * Description:
472  *
473  *
474  * Arguments:
475  * NONE
476 -*/
477 
478 int DbCommit(void)
479 {
480  const char* sql = "commit transaction";
481  return DbExecuteSqlNoResult(DbHandle(), sql);
482 }
483 
484 /*+
485  * DbRollback - End a (non-nested) transaction by rolling it back
486  *
487  * Description:
488  *
489  *
490  * Arguments:
491  * NONE
492 -*/
493 
494 int DbRollback(void)
495 {
496  const char* sql = "rollback transaction";
497  return DbExecuteSqlNoResult(DbHandle(), sql);
498 }
void DbFreeResult(DB_RESULT result)
void * MemCalloc(size_t nmemb, size_t size)
Definition: memory.c:68
sqlite3 * DB_HANDLE
Definition: database.h:77
#define DB_RESULT_MAGIC
Definition: database.h:88
short first_row
Definition: database.h:86
int DbRollback(void)
void DbgOutput(unsigned int mask, const char *format,...)
Definition: debug.c:135
int DbFetchRow(DB_RESULT result, DB_ROW *row)
unsigned int magic
Definition: database.h:81
sqlite3_stmt * data
Definition: database.h:84
struct db_row * DB_ROW
Definition: database.h:98
int MsgLog(int status,...)
Definition: message.c:335
#define DBG_M_SQL
Definition: debug.h:43
#define DBS_INVARG
Definition: dbsdef.h:48
#define MemFree(ptr)
Definition: memory.h:48
DB_HANDLE DbHandle(void)
int DbString(DB_ROW row, int field_index, char **result)
int DbCommit(void)
struct db_result * DB_RESULT
Definition: database.h:90
const char * DbErrmsg(DB_HANDLE handle)
void DbFreeRow(DB_ROW row)
#define DBS_INVINDEX
Definition: dbsdef.h:49
int DbExecuteSql(DB_HANDLE handle, const char *stmt_str, DB_RESULT *result)
#define DB_ROW_MAGIC
Definition: database.h:97
DB_RESULT result
Definition: database.h:95
int count
Definition: database.h:82
void * MemMalloc(size_t size)
Definition: memory.c:57
#define DBS_SQLFAIL
Definition: dbsdef.h:55
int DbBeginTransaction(void)
int DbExecuteSqlNoResult(DB_HANDLE handle, const char *stmt_str)
int sqlite3_my_step(sqlite3_stmt *pStmt)
unsigned int magic
Definition: database.h:94
void DbStringFree(char *string)