OpenDNSSEC-enforcer
1.3.8
|
00001 /* 00002 * $Id: database_support_lite.c 1285 2009-07-15 14:07:41Z 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_support - Database Utility Functions 00031 * 00032 * Description: 00033 * Holds miscellaneous utility functions associated with the MySql 00034 * database. 00035 -*/ 00036 00037 #include <stdarg.h> 00038 #include <string.h> 00039 #include <stdio.h> 00040 #include <time.h> 00041 00042 #include <sqlite3.h> 00043 00044 #include "ksm/dbsdef.h" 00045 #include "ksm/database.h" 00046 #include "ksm/debug.h" 00047 #include "ksm/message.h" 00048 #include "ksm/string_util.h" 00049 #include "ksm/string_util2.h" 00050 00051 #define MIN(x, y) ((x) < (y) ? (x) : (y)) 00052 #define MAX(x, y) ((x) > (y) ? (x) : (y)) 00053 00054 00055 00056 /*+ 00057 * DbExecuteSqlNoResult - Execute SQL Statement and Ignore Result 00058 * 00059 * Description: 00060 * Executes the given SQL statement; any results are discarded. 00061 * 00062 * This function is useful for statements such as DELETE and INSERT. 00063 * 00064 * Arguments: 00065 * DB_HANDLE handle 00066 * Handle to the currently opened database. 00067 * 00068 * const char* stmt_str 00069 * Statement to execute 00070 * 00071 * Returns: 00072 * int 00073 * Status return. 00074 * 0 Success 00075 * Other Error. A message will have been output. 00076 -*/ 00077 00078 int DbExecuteSqlNoResult(DB_HANDLE handle, const char* stmt_str) 00079 { 00080 DB_RESULT result; /* Pointer to result string */ 00081 int status; /* Status return */ 00082 00083 status = DbExecuteSql(handle, stmt_str, &result); 00084 if (status == 0) { 00085 if (result) { 00086 00087 /* Result given - get rid of it, we don't want it */ 00088 00089 status = MsgLog(DBS_UNEXRES, stmt_str); 00090 DbFreeResult(result); 00091 } 00092 } 00093 00094 return status; 00095 } 00096 00097 00098 /*+ 00099 * DbRowId - Return ID of Current Row 00100 * 00101 * Description: 00102 * Returns the ID of the current row. This is assumed to be an auto- 00103 * increment column at index 0 of the table. 00104 * 00105 * Arguments: 00106 * DB_ROW row 00107 * Row in question. 00108 * 00109 * DB_ID* id 00110 * ID of the row is returned here. 00111 * 00112 * Returns: 00113 * int 00114 * Status return. 00115 * 00116 * 0 Success 00117 * Other Error. A message will have been output. 00118 -*/ 00119 00120 int DbRowId(DB_ROW row, DB_ID* id) 00121 { 00122 unsigned long rowid; /* ID of the row as a known type */ 00123 int status; /* Status return */ 00124 00125 if (id == NULL) { 00126 status = MsgLog(DBS_INVARG, "NULL id"); 00127 return -1; 00128 } 00129 00130 status = DbUnsignedLong(row, 0, &rowid); 00131 *id = (DB_ID) rowid; /* Do the conversion between types here */ 00132 00133 return status; 00134 } 00135 00136 00137 00138 00139 /*+ 00140 * DbInt - Return Integer from Field 00141 * 00142 * Description: 00143 * Returns an integer value from the current row. 00144 * 00145 * Arguments: 00146 * DB_ROW row 00147 * Pointer to the row object. 00148 * 00149 * int field_index 00150 * Index of the value required. 00151 * 00152 * int *value 00153 * Value returned. 00154 * 00155 * Returns: 00156 * int 00157 * Status return: 00158 * 0 Success 00159 * Other Error accessing data. A message will have been output. 00160 -*/ 00161 00162 int DbInt(DB_ROW row, int field_index, int *value) 00163 { 00164 char* buffer = NULL; /* Text buffer for returned string */ 00165 int status; /* Status return */ 00166 00167 /* Access the text in the field */ 00168 00169 status = DbString(row, field_index, &buffer); 00170 if (status == 0) { 00171 00172 /* Got the string, can we convert it? */ 00173 00174 if (buffer != NULL) { 00175 00176 /* Not best-efforts - ignore trailing non-numeric values */ 00177 00178 status = StrStrtoi(buffer, value); 00179 if (status == -1) { 00180 00181 /* Could not translate the string to an integer */ 00182 00183 status = MsgLog(DBS_NOTINT, buffer); 00184 *value = 0; 00185 } 00186 DbStringFree(buffer); 00187 } 00188 else { 00189 00190 /* Field is NULL, return 0 */ 00191 /* TODO should we do something better here ? */ 00192 00193 *value = 0; 00194 } 00195 } 00196 00197 return status; 00198 } 00199 00200 00201 00202 /*+ 00203 * DbUnsignedLong - Return Unsigned Long from Field 00204 * 00205 * Description: 00206 * Returns an integer value from the current row. 00207 * 00208 * Arguments: 00209 * DB_ROW row 00210 * Pointer to the row object. 00211 * 00212 * int field_index 00213 * Index of the value required. 00214 * 00215 * unsigned long *value 00216 * Value returned. 00217 * 00218 * Returns: 00219 * int 00220 * Status return: 00221 * 0 Success 00222 * Other Error accessing data. A message will have been output. 00223 -*/ 00224 00225 int DbUnsignedLong(DB_ROW row, int field_index, unsigned long *value) 00226 { 00227 char* buffer = NULL; /* Text buffer for returned string */ 00228 int status; /* Status return */ 00229 00230 /* Access the text in the field */ 00231 00232 status = DbString(row, field_index, &buffer); 00233 if (status == 0) { 00234 00235 /* Got the string, can we convert it? */ 00236 00237 if (buffer != NULL) { 00238 00239 /* Not best-efforts - ignore trailing non-numeric values */ 00240 00241 status = StrStrtoul(buffer, value); 00242 if (status == -1) { 00243 00244 /* Could not translate the string to an unsigned long */ 00245 00246 status = MsgLog(DBS_NOTINT, buffer); 00247 *value = 0; 00248 } 00249 DbStringFree(buffer); 00250 } 00251 else { 00252 00253 /* Field is NULL, return 0 */ 00254 00255 *value = 0; 00256 } 00257 } 00258 00259 return status; 00260 } 00261 00262 00263 00264 /*+ 00265 * DbIntQuery - Perform Query Returning Single Integer 00266 * 00267 * Description: 00268 * Many queries are of the form: 00269 * 00270 * SELECT COUNT(*) FROM ... 00271 * or 00272 * SELECT <single integer value> FROM ... 00273 * 00274 * This function performs the query and returns the single value. 00275 * 00276 * Arguments: 00277 * DB_HANDLE handle 00278 * Handle to the currently opened database. 00279 * 00280 * int* value 00281 * Result of the query. Note that if the query returns no rows, 00282 * a zero is returned. 00283 * 00284 * const char* query 00285 * Query to run. 00286 * 00287 * Returns: 00288 * int 00289 * 0 Success 00290 * Other Error (a message will have been output) 00291 -*/ 00292 00293 int DbIntQuery(DB_HANDLE handle, int* value, const char* query) 00294 { 00295 DB_RESULT result; /* Result object */ 00296 DB_ROW row = NULL; /* Row object */ 00297 int status; /* Status return */ 00298 00299 status = DbExecuteSql(handle, query, &result); 00300 if (status == SQLITE_OK) { 00301 00302 /* Get first row */ 00303 status = DbFetchRow(result, &row); 00304 if (status == 0) { 00305 /* Got the row, so convert to integer */ 00306 00307 status = DbInt(row, 0, value); 00308 00309 /* Query succeeded, but are there any more rows? */ 00310 if (DbFetchRow(result, &row) != -1) { 00311 (void) MsgLog(DBS_TOOMANYROW, query); /* Too much data */ 00312 } 00313 00314 } 00315 else 00316 { 00317 status = MsgLog(DBS_NORESULT); /* Query did not return a result */ 00318 } 00319 00320 DbFreeResult(result); 00321 DbFreeRow(row); 00322 00323 } 00324 00325 return status; 00326 } 00327 00328 00329 /*+ 00330 * DbStringBuffer - Return String Value into User-Supplied Buffer 00331 * 00332 * Description: 00333 * Returns string value from the current row into a user-supplied 00334 * buffer. The returned value is truncated if required. 00335 * 00336 * Arguments: 00337 * DB_ROW row 00338 * Pointer to the row object. 00339 * 00340 * int field_index 00341 * Index of the value required. 00342 * 00343 * char* buffer 00344 * Null-terminated buffer into which the data is put. If the returned 00345 * string is NULL, the buffer will contain a zero-length string. There 00346 * is no way to distinguish between this and the database holding an 00347 * empty string. 00348 * 00349 * size_t buflen 00350 * Length of the buffer. 00351 * 00352 * Returns: 00353 * int 00354 * 0 Success 00355 * Other Error. A message will have been output. 00356 -*/ 00357 00358 int DbStringBuffer(DB_ROW row, int field_index, char* buffer, size_t buflen) 00359 { 00360 char* data = NULL; /* Data returned from DbString */ 00361 int status; /* Status return */ 00362 00363 if (row && (row->magic == DB_ROW_MAGIC) && buffer && (buflen != 0)) { 00364 00365 /* Arguments OK, get the information */ 00366 00367 status = DbString(row, field_index, &data); 00368 if (status == 0) { 00369 00370 /* Success, copy the data into destination & free buffer 00371 Note the StrStrncpy copes with data == NULL */ 00372 00373 StrStrncpy(buffer, data, buflen); 00374 DbStringFree(data); 00375 } 00376 } 00377 else { 00378 00379 /* Invalid srguments, notify the user */ 00380 00381 status = MsgLog(DBS_INVARG, "DbStringBuffer"); 00382 } 00383 00384 return status; 00385 } 00386 00387 00388 00389 /*+ 00390 * DbErrno - Return Last Error Number 00391 * 00392 * Description: 00393 * Returns the numeric code associated with the last operation 00394 * on this connection that gave an error. 00395 * 00396 * Arguments: 00397 * DB_HANDLE handle 00398 * Handle to an open database. 00399 * 00400 * Returns: 00401 * int 00402 * Error number. 00403 -*/ 00404 00405 int DbErrno(DB_HANDLE handle) 00406 { 00407 return sqlite3_errcode((sqlite3*) handle); 00408 } 00409 00410 00411 00412 /*+ 00413 * DbErrmsg - Return Last Error Message 00414 * 00415 * Description: 00416 * Returns the last error on this connection. This is just an 00417 * encapsulation of mysql_error. 00418 * 00419 * Arguments: 00420 * DB_HANDLE handle 00421 * Handle to an open database. 00422 * 00423 * Returns: 00424 * const char* 00425 * Error string. This should be copied and must not be freed. 00426 -*/ 00427 00428 const char* DbErrmsg(DB_HANDLE handle) 00429 { 00430 return sqlite3_errmsg((sqlite3*) handle); 00431 } 00432 00433 00434 /*+ 00435 * DbLastRowId - Return Last Row ID 00436 * 00437 * Description: 00438 * Returns the ID field of the last row inserted. 00439 * 00440 * All tables are assumed to include an auto-incrementing ID field. Apart 00441 * from providing the unique primary key, this is a relatively 00442 * implementation-unique way of uniquely identifying a row in a table. 00443 * 00444 * Arguments: 00445 * DB_HANDLE handle 00446 * Handle to the database connection. 00447 * 00448 * DB_ID* id 00449 * ID of the last row inserted (into any table) on this connection. 00450 * 00451 * Returns: 00452 * int 00453 * Status return 00454 * 00455 * 0 Success 00456 * Other Error code. An error message will have been output. 00457 -*/ 00458 00459 int DbLastRowId(DB_HANDLE handle, DB_ID* id) 00460 { 00461 00462 if (id == NULL) { 00463 return MsgLog(DBS_INVARG, "NULL id"); 00464 } 00465 00466 /* TODO returns a sqlite_int64; can this be cast into an unsigned long? 00467 * do we need to check this for each platform? */ 00468 *id = (DB_ID) sqlite3_last_insert_rowid((sqlite3*) handle); 00469 00470 /* 00471 * In sqlite, there is no error code; a value of 0 is returned if there 00472 * is no matching row. In this case, convert it to an error code. 00473 */ 00474 00475 return (*id != 0) ? 0 : DBS_NOSUCHROW; 00476 }