/* sqlite.h -- Generic functions to simplify SQLite3 queries - data structures defined here * * GPLv2 only - Copyright (C) 2008 - 2012 * David Sommerseth * * 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 * @date 2008-08-06 * * @brief Generic functions to simplify the SQLite3 integration. * */ #ifndef SQLITE_H_ # define SQLITE_H_ #include #ifdef HAVE_LIBXML2 # include #endif #include /** * 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_ */