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