OpenDNSSEC-enforcer
1.3.4
|
00001 /* 00002 * $Id: database_support_mysql.c 2592 2009-12-09 15:06:39Z rb $ 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 <mysql.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 return MsgLog(DBS_INVARG, "NULL id"); 00127 } 00128 00129 status = DbUnsignedLong(row, 0, &rowid); 00130 *id = (DB_ID) rowid; /* Do the conversion between types here */ 00131 00132 return status; 00133 } 00134 00135 00136 00137 00138 /*+ 00139 * DbInt - Return Integer from Field 00140 * 00141 * Description: 00142 * Returns an integer value from the current row. 00143 * 00144 * Arguments: 00145 * DB_ROW row 00146 * Pointer to the row object. 00147 * 00148 * int field_index 00149 * Index of the value required. 00150 * 00151 * int *value 00152 * Value returned. 00153 * 00154 * Returns: 00155 * int 00156 * Status return: 00157 * 0 Success 00158 * Other Error accessing data. A message will have been output. 00159 -*/ 00160 00161 int DbInt(DB_ROW row, int field_index, int *value) 00162 { 00163 char* buffer = NULL; /* Text buffer for returned string */ 00164 int status; /* Status return */ 00165 00166 /* Access the text in the field */ 00167 00168 status = DbString(row, field_index, &buffer); 00169 if (status == 0) { 00170 00171 /* Got the string, can we convert it? */ 00172 00173 if (buffer != NULL) { 00174 00175 /* Not best-efforts - ignore trailing non-numeric values */ 00176 00177 status = StrStrtoi(buffer, value); 00178 if (status == -1) { 00179 00180 /* Could not translate the string to an integer */ 00181 00182 status = MsgLog(DBS_NOTINT, buffer); 00183 *value = 0; 00184 } 00185 DbStringFree(buffer); 00186 } 00187 else { 00188 00189 /* Field is NULL, return 0 */ 00190 00191 *value = 0; 00192 } 00193 } 00194 00195 return status; 00196 } 00197 00198 00199 00200 /*+ 00201 * DbUnsignedLong - Return Unsigned Long from Field 00202 * 00203 * Description: 00204 * Returns an integer value from the current row. 00205 * 00206 * Arguments: 00207 * DB_ROW row 00208 * Pointer to the row object. 00209 * 00210 * int field_index 00211 * Index of the value required. 00212 * 00213 * unsigned long *value 00214 * Value returned. 00215 * 00216 * Returns: 00217 * int 00218 * Status return: 00219 * 0 Success 00220 * Other Error accessing data. A message will have been output. 00221 -*/ 00222 00223 int DbUnsignedLong(DB_ROW row, int field_index, unsigned long *value) 00224 { 00225 char* buffer = NULL; /* Text buffer for returned string */ 00226 int status; /* Status return */ 00227 00228 /* Access the text in the field */ 00229 00230 status = DbString(row, field_index, &buffer); 00231 if (status == 0) { 00232 00233 /* Got the string, can we convert it? */ 00234 00235 if (buffer != NULL) { 00236 00237 /* Not best-efforts - ignore trailing non-numeric values */ 00238 00239 status = StrStrtoul(buffer, value); 00240 if (status == -1) { 00241 00242 /* Could not translate the string to an unsigned long */ 00243 00244 status = MsgLog(DBS_NOTINT, buffer); 00245 *value = 0; 00246 } 00247 DbStringFree(buffer); 00248 } 00249 else { 00250 00251 /* Field is NULL, return 0 */ 00252 00253 *value = 0; 00254 } 00255 } 00256 00257 return status; 00258 } 00259 00260 00261 00262 /*+ 00263 * DbIntQuery - Perform Query Returning Single Integer 00264 * 00265 * Description: 00266 * Many queries are of the form: 00267 * 00268 * SELECT COUNT(*) FROM ... 00269 * or 00270 * SELECT <single integer value> FROM ... 00271 * 00272 * This function performs the query and returns the single value. 00273 * 00274 * Arguments: 00275 * DB_HANDLE handle 00276 * Handle to the currently opened database. 00277 * 00278 * int* value 00279 * Result of the query. Note that if the query returns no rows, 00280 * a zero is returned. 00281 * 00282 * const char* query 00283 * Query to run. 00284 * 00285 * Returns: 00286 * int 00287 * 0 Success 00288 * Other Error (a message will have been output) 00289 -*/ 00290 00291 int DbIntQuery(DB_HANDLE handle, int* value, const char* query) 00292 { 00293 DB_RESULT result = NULL; /* Result object */ 00294 DB_ROW row = NULL; /* Row object */ 00295 int status; /* Status return */ 00296 00297 status = DbExecuteSql(handle, query, &result); 00298 if (status == 0) { 00299 00300 /* Get first row */ 00301 status = DbFetchRow(result, &row); 00302 if (status == 0) { 00303 /* Got the row, so convert to integer */ 00304 00305 status = DbInt(row, 0, value); 00306 00307 /* Query succeeded, but are there any more rows? */ 00308 if (DbFetchRow(result, &row) != -1) { 00309 (void) MsgLog(DBS_TOOMANYROW, query); /* Too much data */ 00310 } 00311 } 00312 else 00313 { 00314 status = MsgLog(DBS_NORESULT); /* Query did not return a result */ 00315 } 00316 00317 DbFreeResult(result); 00318 DbFreeRow(row); 00319 } 00320 00321 return status; 00322 } 00323 00324 00325 /*+ 00326 * DbStringBuffer - Return String Value into User-Supplied Buffer 00327 * 00328 * Description: 00329 * Returns string value from the current row into a user-supplied 00330 * buffer. The returned value is truncated if required. 00331 * 00332 * Arguments: 00333 * DB_ROW row 00334 * Pointer to the row object. 00335 * 00336 * int field_index 00337 * Index of the value required. 00338 * 00339 * char* buffer 00340 * Null-terminated buffer into which the data is put. If the returned 00341 * string is NULL, the buffer will contain a zero-length string. There 00342 * is no way to distinguish between this and the database holding an 00343 * empty string. 00344 * 00345 * size_t buflen 00346 * Length of the buffer. 00347 * 00348 * Returns: 00349 * int 00350 * 0 Success 00351 * Other Error. A message will have been output. 00352 -*/ 00353 00354 int DbStringBuffer(DB_ROW row, int field_index, char* buffer, size_t buflen) 00355 { 00356 char* data; /* Data returned from DbString */ 00357 int status; /* Status return */ 00358 00359 if (row && (row->magic == DB_ROW_MAGIC) && buffer && (buflen != 0)) { 00360 00361 /* Arguments OK, get the information */ 00362 00363 status = DbString(row, field_index, &data); 00364 if (status == 0) { 00365 00366 /* Success, copy the data into destination & free buffer 00367 Note the StrStrncpy copes with data == NULL */ 00368 00369 StrStrncpy(buffer, data, buflen); 00370 DbStringFree(data); 00371 } 00372 } 00373 else { 00374 00375 /* Invalid srguments, notify the user */ 00376 00377 status = MsgLog(DBS_INVARG, "DbStringBuffer"); 00378 } 00379 00380 return status; 00381 } 00382 00383 00384 00385 /*+ 00386 * DbErrno - Return Last Error Number 00387 * 00388 * Description: 00389 * Returns the numeric code associated with the last operation 00390 * on this connection that gave an error. 00391 * 00392 * Arguments: 00393 * DB_HANDLE handle 00394 * Handle to an open database. 00395 * 00396 * Returns: 00397 * int 00398 * Error number. 00399 -*/ 00400 00401 int DbErrno(DB_HANDLE handle) 00402 { 00403 return mysql_errno((MYSQL*) handle); 00404 } 00405 00406 00407 00408 /*+ 00409 * DbErrmsg - Return Last Error Message 00410 * 00411 * Description: 00412 * Returns the last error on this connection. This is just an 00413 * encapsulation of mysql_error. 00414 * 00415 * Arguments: 00416 * DB_HANDLE handle 00417 * Handle to an open database. 00418 * 00419 * Returns: 00420 * const char* 00421 * Error string. This should be copied and must not be freed. 00422 -*/ 00423 00424 const char* DbErrmsg(DB_HANDLE handle) 00425 { 00426 return mysql_error((MYSQL*) handle); 00427 } 00428 00429 00430 /*+ 00431 * DbLastRowId - Return Last Row ID 00432 * 00433 * Description: 00434 * Returns the ID field of the last row inserted. 00435 * 00436 * All tables are assumed to include an auto-incrementing ID field. Apart 00437 * from providing the unique primary key, this is a relatively 00438 * implementation-unique way of uniquely identifying a row in a table. 00439 * 00440 * Arguments: 00441 * DB_HANDLE handle 00442 * Handle to the database connection. 00443 * 00444 * DB_ID* id 00445 * ID of the last row inserted (into any table) on this connection. 00446 * 00447 * Returns: 00448 * int 00449 * Status return 00450 * 00451 * 0 Success 00452 * Other Error code. An error message will have been output. 00453 -*/ 00454 00455 int DbLastRowId(DB_HANDLE handle, DB_ID* id) 00456 { 00457 00458 if (id == NULL) { 00459 return MsgLog(DBS_INVARG, "NULL id"); 00460 } 00461 00462 *id = (DB_ID) mysql_insert_id((MYSQL*) handle); 00463 00464 /* 00465 * In MySql, there is no error code; a value of 0 is returned if there 00466 * is no matching row. In this case, convert it to an error code. 00467 */ 00468 00469 return (*id != 0) ? 0 : DBS_NOSUCHROW; 00470 }