1 /*
2 * libdbi - database independent abstraction layer for C.
3 * Copyright (C) 2001-2002, David Parker and Mark Tobenkin.
4 * http://libdbi.sourceforge.net
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * dbd_example.c: Example database support (using libexampleclient)
21 * Copyright (C) 2005, E.X. Ample <example@users.sourceforge.net>
22 * http://libdbi.sourceforge.net
23 *
24 * $Id: dbd_example.c,v 1.2 2008/01/02 16:14:40 mhoenicka Exp $
25 */
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30
31 #define _GNU_SOURCE /* we need asprintf */
32
33 #ifndef HAVE_ATOLL
34 long long atoll(const char *str);
35 #endif
36
37 #ifndef HAVE_STRTOLL
38 long long strtoll(const char *nptr, char **endptr, int base);
39 #endif
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <time.h>
45
46 #include <dbi/dbi.h>
47 #include <dbi/dbi-dev.h>
48 #include <dbi/dbd.h>
49
50 #include <example.h>
51 #include "dbd_example.h"
52
53 static const dbi_info_t driver_info = {
54 "example",
55 "Example database support (using libexampleclient)",
56 "E.X. Ample <example@users.sourceforge.net>",
57 "http://libdbi-drivers.sourceforge.net",
58 "dbd_example v" VERSION,
59 __DATE__
60 };
61
62 static const char *custom_functions[] = {NULL}; // TODO
63 static const char *reserved_words[] = EXAMPLE_RESERVED_WORDS;
64
65 /* encoding strings, array is terminated by a pair of empty strings */
66 static const char example_encoding_hash[][16] = {
67 /* Example, www.iana.org */
68 "ascii", "US-ASCII",
69 "utf8", "UTF-8",
70 "latin1", "ISO-8859-1",
71 "", ""
72 };
73
74 /* forward declarations of local functions */
75 void _translate_example_type(enum enum_field_types fieldtype, unsigned short *type, unsigned int *attribs);
76 void _get_field_info(dbi_result_t *result);
77 void _get_row_data(dbi_result_t *result, dbi_row_t *row, unsigned long long rowidx);
78
79
80
81 /* Driver Infrastructure Functions */
82
83
dbd_register_driver(const dbi_info_t ** _driver_info,const char *** _custom_functions,const char *** _reserved_words)84 void dbd_register_driver(const dbi_info_t **_driver_info, const char ***_custom_functions, const char ***_reserved_words) {
85 /* this is the first function called after the driver module is loaded into memory */
86 *_driver_info = &driver_info;
87 *_custom_functions = custom_functions;
88 *_reserved_words = reserved_words;
89 }
90
dbd_initialize(dbi_driver_t * driver)91 int dbd_initialize(dbi_driver_t *driver) {
92 /* perform any database-specific server initialization.
93 * this is called right after dbd_register_driver().
94 * return -1 on error, 0 on success. if -1 is returned, the driver will not
95 * be added to the list of available drivers. */
96
97 /* this indicates the driver can be safely unloaded when libdbi is
98 shut down. Change the value to '0' (zero) if the driver, or a
99 library it is linked against, installs exit handlers via
100 atexit() */
101 _dbd_register_driver_cap(driver, "safe_dlclose", 1);
102
103 return 0;
104 }
105
dbd_connect(dbi_conn_t * conn)106 int dbd_connect(dbi_conn_t *conn) {
107
108 /* set options */
109 /* create a database connection */
110 /* return 0 if successful, -1 if an error occurs */
111
112 return 0;
113 }
114
dbd_disconnect(dbi_conn_t * conn)115 int dbd_disconnect(dbi_conn_t *conn) {
116 /* close connection */
117 /* return 0 if successful, otherwise -1 */
118 return 0;
119 }
120
dbd_geterror(dbi_conn_t * conn,int * errno,char ** errstr)121 int dbd_geterror(dbi_conn_t *conn, int *errno, char **errstr) {
122 /* put error number into errno, error string into errstr
123 * return 0 if error, 1 if errno filled, 2 if errstr filled, 3 if both errno and errstr filled */
124
125 }
126
dbd_get_socket(dbi_conn_t * conn)127 int dbd_get_socket(dbi_conn_t *conn){
128 /* return connection socket, if any */
129 /* return -1 if an error occurs */
130 /* return 0 if the client library does not use sockets */
131 }
132
133
134 /* Internal Database Query Functions */
135
dbd_goto_row(dbi_result_t * result,unsigned long long rowidx)136 int dbd_goto_row(dbi_result_t *result, unsigned long long rowidx) {
137 /* move internal row index to rowidx (may be a no-op) */
138 return 1;
139 }
140
dbd_fetch_row(dbi_result_t * result,unsigned long long rowidx)141 int dbd_fetch_row(dbi_result_t *result, unsigned long long rowidx) {
142 /* 0 on error, 1 on successful fetchrow */
143 }
144
dbd_free_query(dbi_result_t * result)145 int dbd_free_query(dbi_result_t *result) {
146 /* free result data */
147 return 0;
148 }
149
150
151 /* Public Database Query Functions */
dbd_get_encoding(dbi_conn_t * conn)152 const char *dbd_get_encoding(dbi_conn_t *conn){
153 /* return connection encoding as an IANA name */
154 }
155
dbd_encoding_to_iana(const char * db_encoding)156 const char* dbd_encoding_to_iana(const char *db_encoding) {
157 int i = 0;
158
159 /* loop over all even entries in hash and compare to menc */
160 while (*example_encoding_hash[i]) {
161 if (!strncmp(example_encoding_hash[i], db_encoding, strlen(example_encoding_hash[i]))) {
162 /* return corresponding odd entry */
163 return example_encoding_hash[i+1];
164 }
165 i+=2;
166 }
167
168 /* don't know how to translate, return original encoding */
169 return db_encoding;
170 }
171
dbd_encoding_from_iana(const char * iana_encoding)172 const char* dbd_encoding_from_iana(const char *iana_encoding) {
173 int i = 0;
174
175 /* loop over all odd entries in hash and compare to ienc */
176 while (*example_encoding_hash[i+1]) {
177 if (!strcmp(example_encoding_hash[i+1], iana_encoding)) {
178 /* return corresponding even entry */
179 return example_encoding_hash[i];
180 }
181 i+=2;
182 }
183
184 /* don't know how to translate, return original encoding */
185 return iana_encoding;
186 }
187
dbd_list_dbs(dbi_conn_t * conn,const char * pattern)188 dbi_result_t *dbd_list_dbs(dbi_conn_t *conn, const char *pattern) {
189 /* return a list of available databases. If pattern is non-NULL,
190 return only the databases that match. Return NULL if an error
191 occurs */
192 }
193
dbd_list_tables(dbi_conn_t * conn,const char * db,const char * pattern)194 dbi_result_t *dbd_list_tables(dbi_conn_t *conn, const char *db, const char *pattern) {
195 /* return a list of available tables. If pattern is non-NULL,
196 return only the tables that match */
197 }
198
dbd_quote_string(dbi_driver_t * driver,const char * orig,char * dest)199 size_t dbd_quote_string(dbi_driver_t *driver, const char *orig, char *dest) {
200 /* foo's -> 'foo\'s' */
201 /* driver-specific, deprecated */
202 }
203
dbd_conn_quote_string(dbi_conn_t * conn,const char * orig,char * dest)204 size_t dbd_conn_quote_string(dbi_conn_t *conn, const char *orig, char *dest) {
205 /* foo's -> 'foo\'s' */
206 /* connection-specific. Should take character encoding of current
207 connection into account if db engine supports this */
208 }
209
dbd_quote_binary(dbi_conn_t * conn,const char * orig,size_t from_length,char ** ptr_dest)210 size_t dbd_quote_binary(dbi_conn_t *conn, const char* orig, size_t from_length, char **ptr_dest) {
211 /* *ptr_dest shall point to a zero-terminated string that can be
212 used in SQL queries. Returns the lenght of that string in
213 bytes, or DBI_LENGTH_ERROR in case of an error */
214 }
215
dbd_query(dbi_conn_t * conn,const char * statement)216 dbi_result_t *dbd_query(dbi_conn_t *conn, const char *statement) {
217 /* allocate a new dbi_result_t and fill its applicable members:
218 *
219 * result_handle, numrows_matched, and numrows_changed.
220 * everything else will be filled in by DBI */
221
222 }
223
dbd_query_null(dbi_conn_t * conn,const unsigned char * statement,size_t st_length)224 dbi_result_t *dbd_query_null(dbi_conn_t *conn, const unsigned char *statement, size_t st_length) {
225 /* run query using a query string that may contain NULL bytes */
226 }
227
dbd_select_db(dbi_conn_t * conn,const char * db)228 const char *dbd_select_db(dbi_conn_t *conn, const char *db) {
229 /* make the requested database the current database */
230 }
231
dbd_get_seq_last(dbi_conn_t * conn,const char * sequence)232 unsigned long long dbd_get_seq_last(dbi_conn_t *conn, const char *sequence) {
233 /* return ID of last INSERT */
234 }
235
dbd_get_seq_next(dbi_conn_t * conn,const char * sequence)236 unsigned long long dbd_get_seq_next(dbi_conn_t *conn, const char *sequence) {
237 /* return ID of next INSERT */
238 }
239
dbd_ping(dbi_conn_t * conn)240 int dbd_ping(dbi_conn_t *conn) {
241 /* return 1 if connection is alive, otherwise 0 */
242 }
243
244 /* CORE EXAMPLE DATA FETCHING STUFF */
245
_translate_example_type(enum enum_field_types fieldtype,unsigned short * type,unsigned int * attribs)246 void _translate_example_type(enum enum_field_types fieldtype, unsigned short *type, unsigned int *attribs) {
247 unsigned int _type = 0;
248 unsigned int _attribs = 0;
249
250 switch (fieldtype) {
251 case FIELD_TYPE_TINY:
252 _type = DBI_TYPE_INTEGER;
253 _attribs |= DBI_INTEGER_SIZE1;
254 break;
255 case FIELD_TYPE_YEAR:
256 _attribs |= DBI_INTEGER_UNSIGNED;
257 case FIELD_TYPE_SHORT:
258 _type = DBI_TYPE_INTEGER;
259 _attribs |= DBI_INTEGER_SIZE2;
260 break;
261 case FIELD_TYPE_INT24:
262 _type = DBI_TYPE_INTEGER;
263 _attribs |= DBI_INTEGER_SIZE3;
264 break;
265 case FIELD_TYPE_LONG:
266 _type = DBI_TYPE_INTEGER;
267 _attribs |= DBI_INTEGER_SIZE4;
268 break;
269 case FIELD_TYPE_LONGLONG:
270 _type = DBI_TYPE_INTEGER;
271 _attribs |= DBI_INTEGER_SIZE8;
272 break;
273
274 case FIELD_TYPE_FLOAT:
275 _type = DBI_TYPE_DECIMAL;
276 _attribs |= DBI_DECIMAL_SIZE4;
277 break;
278 case FIELD_TYPE_DOUBLE:
279 _type = DBI_TYPE_DECIMAL;
280 _attribs |= DBI_DECIMAL_SIZE8;
281 break;
282
283 case FIELD_TYPE_DATE: /* TODO parse n stuph to native DBI unixtime type. for now, string */
284 _type = DBI_TYPE_DATETIME;
285 _attribs |= DBI_DATETIME_DATE;
286 break;
287 case FIELD_TYPE_TIME:
288 _type = DBI_TYPE_DATETIME;
289 _attribs |= DBI_DATETIME_TIME;
290 break;
291 case FIELD_TYPE_DATETIME:
292 case FIELD_TYPE_TIMESTAMP:
293 _type = DBI_TYPE_DATETIME;
294 _attribs |= DBI_DATETIME_DATE;
295 _attribs |= DBI_DATETIME_TIME;
296 break;
297
298 case FIELD_TYPE_DECIMAL: /* decimal is actually a string, has arbitrary precision, no floating point rounding */
299 case FIELD_TYPE_ENUM:
300 case FIELD_TYPE_SET:
301 case FIELD_TYPE_VAR_STRING:
302 case FIELD_TYPE_STRING:
303 _type = DBI_TYPE_STRING;
304 break;
305
306 case FIELD_TYPE_TINY_BLOB:
307 case FIELD_TYPE_MEDIUM_BLOB:
308 case FIELD_TYPE_LONG_BLOB:
309 case FIELD_TYPE_BLOB:
310 _type = DBI_TYPE_BINARY;
311 break;
312
313 default:
314 _type = DBI_TYPE_STRING;
315 break;
316 }
317
318 *type = _type;
319 *attribs = _attribs;
320 }
321
_get_field_info(dbi_result_t * result)322 void _get_field_info(dbi_result_t *result) {
323 /* retrieve field meta info */
324 }
325
_get_row_data(dbi_result_t * result,dbi_row_t * row,unsigned long long rowidx)326 void _get_row_data(dbi_result_t *result, dbi_row_t *row, unsigned long long rowidx) {
327 /* get data of the current row */
328 }
329
330
331