OpenDNSSEC-enforcer
1.3.8
|
00001 /* 00002 * $Id: database_access_lite.c 2676 2010-01-11 15:31:31Z sion $ 00003 * 00004 * Copyright (c) 2008-2009 Nominet UK. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 */ 00028 00029 /*+ 00030 * database_access_lite - database Access Functions 00031 * 00032 * Description: 00033 * Holds miscellaneous utility functions associated with the sqlite 00034 * database. 00035 * 00036 * This particular file holds encapsulations of the underlying access 00037 * functions - querying/modifying the database and retrieving results. 00038 -*/ 00039 00040 #include <stdarg.h> 00041 #include <string.h> 00042 #include <stdio.h> 00043 #include <time.h> 00044 #include <unistd.h> 00045 00046 #include <sqlite3.h> 00047 00048 #include "ksm/dbsdef.h" 00049 #include "ksm/database.h" 00050 #include "ksm/debug.h" 00051 #include "ksm/memory.h" 00052 #include "ksm/message.h" 00053 #include "ksm/string_util.h" 00054 00055 #define MIN(x, y) ((x) < (y) ? (x) : (y)) 00056 #define MAX(x, y) ((x) > (y) ? (x) : (y)) 00057 00058 /* possible wrapper for sqlite3_step which will wait for a block to go */ 00059 int sqlite3_my_step(sqlite3_stmt *pStmt) 00060 { 00061 int rc; 00062 struct timeval tv; 00063 00064 rc = sqlite3_step(pStmt); 00065 00066 while (rc == SQLITE_LOCKED || rc == SQLITE_BUSY) { 00067 tv.tv_sec = 1; 00068 tv.tv_usec = 0; 00069 select(0, NULL, NULL, NULL, &tv); 00070 00071 rc = sqlite3_step(pStmt); 00072 } 00073 00074 return rc; 00075 00076 } 00077 00078 /*+ 00079 * DbExecuteSqlStatement - Execute SQL Statement 00080 * 00081 * Description: 00082 * A wrapper round sqlite3_prepare_v2 and one call to sqlite3_step 00083 * that outputs the query being executed if the appropriate debug flag 00084 * is set. 00085 * 00086 * Arguments: 00087 * DB_HANDLE handle 00088 * Handle to the currently opened database. 00089 * 00090 * const char* stmt_str 00091 * SQL statement to execute. 00092 * 00093 * Returns: 00094 * int 00095 * Any return value from sqlite3_prepare_v2 or sqlite3_step. 00096 * SQLITE_OK if the command executes correctly 00097 -*/ 00098 00099 static int DbExecuteSqlStatement(DB_HANDLE handle, const char* stmt_str, DB_RESULT* result) 00100 { 00101 int rc; 00102 DbgOutput(DBG_M_SQL, "%s\n", stmt_str); 00103 rc = sqlite3_prepare_v2((sqlite3*) handle, stmt_str, -1, &((*result)->data), 0); 00104 if( rc != SQLITE_OK ) 00105 { 00106 return rc; 00107 } 00108 00109 return sqlite3_step((*result)->data); 00110 } 00111 00112 00113 00114 /*+ 00115 * DbExecuteSql - Execute SQL Statement 00116 * 00117 * Description: 00118 * Executes the given SQL statement and returns the results (if any). 00119 * 00120 * Arguments: 00121 * DB_HANDLE handle 00122 * Handle to the currently opened database. 00123 * 00124 * const char* stmt_str 00125 * Statement to execute. 00126 * 00127 * DB_RESULT* result 00128 * Pointer to the result set is put here. It must be freed by 00129 * DbFreeResult(). This is NULL if no data is returned; on error, the 00130 * value is undefined. 00131 * 00132 * Returns: 00133 * int 00134 * 0 Success 00135 * Other Error code. A message will have been output. 00136 -*/ 00137 00138 int DbExecuteSql(DB_HANDLE handle, const char* stmt_str, DB_RESULT* result) 00139 { 00140 const char* errmsg = NULL; /* Error message from MySql on failure */ 00141 int status = 0; /* Status return */ 00142 00143 /* Argument check */ 00144 00145 if ((!handle) || (!stmt_str) || (*stmt_str == '\0') || (! result)) { 00146 status = MsgLog(DBS_INVARG, "DbExecuteSql"); 00147 return status; 00148 } 00149 00150 /* Allocate the result structure */ 00151 00152 *result = (DB_RESULT) MemCalloc(1, sizeof(struct db_result)); 00153 (*result)->magic = DB_RESULT_MAGIC; 00154 (*result)->handle = handle; 00155 (*result)->first_row = 1; 00156 00157 /* Execute statement */ 00158 00159 status = DbExecuteSqlStatement(handle, stmt_str, result); 00160 if (status == SQLITE_ROW) { 00161 /* Reset the status so that it is consistent across db engines */ 00162 status = 0; 00163 00164 /* Check the pointer to the result set */ 00165 if ((*result)->data == NULL) { 00166 00167 /* 00168 * No result set, so could be some error. See if this is the case 00169 * by checking if there is error text. If not, there are no results 00170 * from the SQL - it could have been a statement such as DELETE or 00171 * INSERT. 00172 */ 00173 00174 errmsg = DbErrmsg(handle); 00175 if (errmsg && *errmsg) { 00176 00177 /* Error text, so error occurred. Output message & tidy up */ 00178 00179 status = MsgLog(DBS_SQLFAIL, errmsg); 00180 } 00181 /* 00182 * else { 00183 * 00184 * No error, so we just don't have any results. 00185 * } 00186 */ 00187 00188 /* 00189 * Regardless of what heppened, there is no result set, so free up 00190 * allocated memory. 00191 */ 00192 00193 MemFree(*result); 00194 *result = NULL; 00195 } 00196 else { 00197 00198 /* 00199 * Success. "result" holds the result set. Store the number of 00200 * fields along with the length of each one for possible later use. 00201 */ 00202 00203 (*result)->count = sqlite3_data_count((sqlite3_stmt*) (*result)->data); 00204 } 00205 } 00206 else if (status == SQLITE_DONE) 00207 { 00208 /* Correct for one-shot statements like insert etc 00209 * finalise the statement to avoid locking the database */ 00210 status = sqlite3_finalize((sqlite3_stmt*) (*result)->data); 00211 00212 MemFree(*result); 00213 *result = NULL; 00214 } 00215 else { 00216 00217 /* Query failed. Log the error and free up the structure */ 00218 00219 status = MsgLog(DBS_SQLFAIL, DbErrmsg(handle)); 00220 MemFree(*result); 00221 *result = NULL; 00222 } 00223 00224 return status; 00225 } 00226 00227 /*+ 00228 * DbFreeResult - Free Result 00229 * 00230 * Description: 00231 * Frees up resources allocated for the result by DbExecuteSql. 00232 * 00233 * Arguments: 00234 * DB_RESULT result 00235 * Handle to the query result. May be NULL, in which case this 00236 * function is a no-op. 00237 * 00238 * If invalid, an error message will be output. 00239 -*/ 00240 00241 void DbFreeResult(DB_RESULT result) 00242 { 00243 if (result) { 00244 if (result->magic == DB_RESULT_MAGIC) { 00245 00246 /* Free up data */ 00247 00248 sqlite3_finalize(result->data); 00249 MemFree(result); 00250 result = NULL; 00251 } 00252 else { 00253 00254 /* Invalid structure - output a warning but do nothing */ 00255 00256 (void) MsgLog(DBS_INVARG, "DbFreeResult"); 00257 } 00258 } 00259 00260 return; 00261 } 00262 00263 00264 00265 /*+ 00266 * DbFetchRow - Fetch Row from Result 00267 * 00268 * Description: 00269 * Steps to the next row in the result set. 00270 * 00271 * Arguments: 00272 * DB_RESULT result 00273 * The result handle returned by the call to DbExecuteSql. 00274 * 00275 * DB_ROW* row 00276 * This is really just the same as RESULT for sqlite, but it is left 00277 * in for MySQL compatibility. 00278 * 00279 * Returns: 00280 * int 00281 * 0 Success, row information returned 00282 * -1 Success, no more rows for this result 00283 * Other Error code or error number from DbErrno(). 00284 -*/ 00285 00286 int DbFetchRow(DB_RESULT result, DB_ROW* row) 00287 { 00288 int status = 0; /* Status return */ 00289 00290 if (result && (result->magic == DB_RESULT_MAGIC) && row) { 00291 00292 /* There is a result structure (and row pointer), do something */ 00293 00294 if (result->first_row == 1) 00295 { 00296 result->first_row = 0; 00297 *row = (DB_ROW) MemCalloc(1, sizeof(struct db_row)); 00298 (*row)->magic = DB_ROW_MAGIC; 00299 (*row)->result=result; 00300 } 00301 else 00302 { 00303 status = sqlite3_step(result->data); 00304 if (status == SQLITE_DONE) { 00305 /* End of result set */ 00306 /* leave freeing the row to the calling function */ 00307 /* *row = NULL; */ 00308 00309 status = -1; 00310 } 00311 else if (status == SQLITE_ROW) 00312 { 00313 *row = (DB_ROW) MemCalloc(1, sizeof(struct db_row)); 00314 (*row)->magic = DB_ROW_MAGIC; 00315 (*row)->result=result; 00316 status = 0; 00317 } 00318 } 00319 } 00320 else if (row) { 00321 *row = NULL; /* no results to report */ 00322 status = -1; 00323 } 00324 else{ 00325 status = MsgLog(DBS_INVARG, "DbFetchRow"); 00326 00327 } 00328 00329 return status; 00330 } 00331 00332 00333 00334 /*+ 00335 * DbFreeRow - Free Row 00336 * 00337 * Description: 00338 * Frees up resources allocated for the row. 00339 * 00340 * Arguments: 00341 * DB_RESULT result 00342 * Handle to the query result. May be NULL, in which case this 00343 * function is a no-op. 00344 -*/ 00345 00346 void DbFreeRow(DB_ROW row) 00347 { 00348 if (row) { 00349 if (row->magic == DB_ROW_MAGIC) { 00350 MemFree(row); 00351 } 00352 else { 00353 00354 /* Output warning, but otherwise do nothing */ 00355 00356 (void) MsgLog(DBS_INVARG, "DbFreeRow"); 00357 } 00358 } 00359 00360 return; 00361 } 00362 00363 00364 00365 /*+ 00366 * DbString - Return String Value 00367 * 00368 * Description: 00369 * Returns string value from the current row. 00370 * 00371 * Arguments: 00372 * DB_ROW row 00373 * Pointer to the row object. 00374 * 00375 * int field_index 00376 * Index of the value required. 00377 * 00378 * char** result 00379 * Value of the field. It is up to the caller to free it with 00380 * a call to DbStringFree(). Note that this can be NULL if the 00381 * corresponding field is NULL. 00382 * 00383 * Returns: 00384 * int 00385 * 0 Success 00386 * Other Some error. A message will have been output 00387 -*/ 00388 00389 int DbString(DB_ROW row, int field_index, char** result) 00390 { 00391 int status = 0; /* Status return */ 00392 unsigned long width; /* Width of column */ 00393 00394 /* Check arguments */ 00395 00396 if (row && (row->magic == DB_ROW_MAGIC) && result) { 00397 00398 /* Is the index requested valid? */ 00399 00400 if ((field_index >= 0) && (field_index < row->result->count)) { 00401 00402 /* Get the width of the column */ 00403 00404 width = sqlite3_column_bytes(row->result->data, field_index); 00405 00406 /* Get string into null-terminated form */ 00407 00408 if (sqlite3_column_text(row->result->data, field_index) != NULL) { 00409 /* TODO replece the below with strdup or StrStrdup ? */ 00410 *result = MemMalloc(width + 1); 00411 memcpy(*result, sqlite3_column_text(row->result->data, field_index), width); 00412 (*result)[width] = 0; 00413 } 00414 else { 00415 *result = NULL; 00416 } 00417 } 00418 else { 00419 00420 /* Invalid field, tell the user */ 00421 00422 status = MsgLog(DBS_INVINDEX, field_index, row->result->count); 00423 } 00424 00425 } 00426 else { 00427 00428 /* Problem with the command arguments */ 00429 00430 status = MsgLog(DBS_INVARG, "DbString"); 00431 } 00432 00433 return status; 00434 00435 } 00436 00437 00438 /*+ 00439 * DbStringFree - Free String Returned by DbString 00440 * 00441 * Description: 00442 * Frees the pointer-to string. 00443 * 00444 * Arguments: 00445 * char* string 00446 * String allocated by DbString. On exit, this pointer is invalid. 00447 -*/ 00448 00449 void DbStringFree(char* string) 00450 { 00451 MemFree(string); 00452 } 00453 00454 /*+ 00455 * DbBeginTransaction - Start a (non-nested) transaction 00456 * 00457 * Description: 00458 * 00459 * 00460 * Arguments: 00461 * NONE 00462 -*/ 00463 00464 int DbBeginTransaction(void) 00465 { 00466 const char* sql = "begin transaction"; 00467 return DbExecuteSqlNoResult(DbHandle(), sql); 00468 } 00469 00470 /*+ 00471 * DbCommit - End a (non-nested) transaction by commiting it 00472 * 00473 * Description: 00474 * 00475 * 00476 * Arguments: 00477 * NONE 00478 -*/ 00479 00480 int DbCommit(void) 00481 { 00482 const char* sql = "commit transaction"; 00483 return DbExecuteSqlNoResult(DbHandle(), sql); 00484 } 00485 00486 /*+ 00487 * DbRollback - End a (non-nested) transaction by rolling it back 00488 * 00489 * Description: 00490 * 00491 * 00492 * Arguments: 00493 * NONE 00494 -*/ 00495 00496 int DbRollback(void) 00497 { 00498 const char* sql = "rollback transaction"; 00499 return DbExecuteSqlNoResult(DbHandle(), sql); 00500 }