1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
/* sqlite.h -- Generic functions to simplify SQLite3 queries - data structures defined here
*
* GPLv2 only - Copyright (C) 2008 - 2012
* David Sommerseth <dazo@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/**
* @file sqlite.h
* @author David Sommerseth <dazo@users.sourceforge.net>
* @date 2008-08-06
*
* @brief Generic functions to simplify the SQLite3 integration.
*
*/
#ifndef SQLITE_H_
# define SQLITE_H_
#include <stdarg.h>
#ifdef HAVE_LIBXML2
# include <libxml/tree.h>
#endif
#include <eurephiadb_mapping.h>
/**
* Defines XML field types, used when extracting SQLite3 results directly into an xmlNode
*/
typedef enum _xmlFieldType { XML_ATTR, XML_NODE } xmlFieldType;
/**
* Contains information about all fields/columns in an SQLite3 result.
* It also keeps track over the length of the longest record/field value in the given field.
*
* This struct is built up as a dual-way chain pointer ring. So you need to keep an eye
* on the fieldid value to know if you have gone one round or not.
*/
typedef struct __sqlite_header {
unsigned int fieldid; /**< Numeric field ID, starts at 1 and increases */
char *name; /**< Name of the field/column */
// char *type;
size_t namelength; /**< Length of the field name */
size_t maxvaluelength; /**< Length of the longest record in this column */
struct __sqlite_header *next; /**< Pointer to the next field */
struct __sqlite_header *prev; /**< Pointer to the previous field */
} _sqlite_header;
/**
* Contains information about a particular data cell. That means one specific record
* in one specific column.
*
* This struct is built up as a dual-way chain pointer ring. So you need to keep an eye
* on the fieldid and/or tupleid value to know if you have gone one round or not.
*/
typedef struct __sqlite_tuples {
unsigned int tupleid; /**< Defines the "record number" */
unsigned int fieldid; /**< Defines the field ID this record belongs to */
char *value; /**< Pointer to the value of this field */
size_t length; /**< Length of the value of this field */
_sqlite_header *header; /**< A pointer to the header record with more info about this field/column */
struct __sqlite_tuples *nextfield; /**< Pointer to the same record, but the next field in it */
struct __sqlite_tuples *prevfield; /**< Pointer to the same record, but the previous field in it */
struct __sqlite_tuples *nexttuple; /**< Pointer to the same field, but the next record */
struct __sqlite_tuples *prevtuple; /**< Pointer to the same field, but the previous record */
} _sqlite_tuples;
/**
* Defines dbresult status types
*/
typedef enum _QueryStatus { dbEMPTY, /**< No SQL query has been performed */
dbSUCCESS, /**< SQL query was successful */
dbERROR, /**< SQL query failed */
dbINVALID /**< Invalid dbresult (NULL value) */
} QueryStatus;
/**
* Defines error severities
*/
typedef enum _ErrorSeverity { sevWARNING, /**< Query returns some data, but with errors in completeing it */
sevERROR, /**< Query could not complete, but may try again */
sevCRITICAL, /**< Query failed and there is no point of trying again */
sevPANIC /**< Query failed and eurephia should shutdown */
} ErrorSeverity;
/**
* The main definition of the dbresult strucutre. This structure keeps the
* complete information about both fields and values of all records from a query.
*
* This structure keeps to "search" pointers. This is used when the sqlite_get_value() or
* sqlite_xml_value() functions are called. These pointers will point at the last record being looked
* up, so that if you do sequencial look ups, it will not loop through the whole chain from the start.
* Even if you go a little bit back an forth, it will find the quickest way to avoid as many iterations
* as possible.
*/
typedef struct __sqlite_dbresult {
QueryStatus status; /**< Indicates if the query was successful or not */
char *query; /**< Copy of the parsed SQL query */
// Query results
_sqlite_tuples *tuples; /**< Pointer to the chains which contains field values */
_sqlite_header *headerrec; /**< Pointer to the chains with info about the field/columns */
size_t num_tuples; /**< Number of records received in the SELECT query */
size_t num_fields; /**< Number of fields for each record */
sqlite_int64 last_insert_id; /**< Reference to the last record from a INSERT INTO statement */
int affected_rows; /**< How many records where INSERTed, UPDATEd or DELETEd */
// "Search" pointers
_sqlite_tuples *srch_tuples; /**< "Cache" of the last record being looked up */
_sqlite_header *srch_headerrec; /**< "Cache" of the last header record being looked up */
// Error handling
ErrorSeverity errSeverity; /**< Severity of the error */
char *errMsg; /**< If status == dbERROR, a error message can be found here */
} dbresult;
/**
* Enumeration of suported SQL queries via the sqlite_query_mapped() API
*/
typedef enum _SQLqueryType { SQL_SELECT, SQL_INSERT, SQL_UPDATE, SQL_DELETE } SQLqueryType;
int sqlite_init_functions(eurephiaCTX *ctx);
/**
* Free up a dbresult structure. This is the public interface for the
* internal function _sqlite_free_results()
*
* @param r Pointer to the dbresult to be freed
*/
#define sqlite_free_results(r) { _sqlite_free_results(r); r = NULL; }
void _sqlite_free_results(dbresult *);
void sqlite_log_error(eurephiaCTX *ctx, dbresult *dbres );
#ifdef HAVE_LIBXML2
xmlNode *sqlite_log_error_xml(eurephiaCTX *ctx, dbresult *dbres );
#endif
dbresult *sqlite_query(eurephiaCTX *ctx, const char *, ...);
dbresult *sqlite_query_mapped(eurephiaCTX *ctx, SQLqueryType type, const char *sqlstub,
eDBfieldMap *valMap, eDBfieldMap *whereMap, const char *sortkeys);
#define sqlite_query_status(res) (QueryStatus) (res != NULL ? res->status : dbINVALID)
char *sqlite_get_value(dbresult *res, int, int);
#ifdef HAVE_LIBXML2
xmlNodePtr sqlite_xml_value(xmlNodePtr node, xmlFieldType xmltyp, char *name, dbresult *res, int row, int col);
#endif
void sqlite_dump_result(FILE *, dbresult *);
/**
* Retrieve number of tuples in a given dbresult structure
*
* @param dbres Pointer to a dbresult
*
* @return Returns number of rows/number of tuples in the result.
*/
#define sqlite_get_numtuples(dbres) (dbres != NULL ? dbres->num_tuples : 0)
/**
* Retrieve number of affected tuples in current dbresult structure. This is only useful
* when called on a result from INSERT, UPDATE or DELETE queries.
*
* @param dbres Pointer to a dbresult
*
* @return Returns number of rows/tuples affected by the SQL query
*/
#define sqlite_get_affected_rows(dbres) (dbres != NULL ? dbres->affected_rows : 0)
#endif /* !SQLITE_H_ */
|