summaryrefslogtreecommitdiffstats
path: root/database/sqlite/sqlite.h
blob: b521687a9087805bbbfd0a27a88a51c7446731e6 (plain)
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 - 2010
 *               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_ */