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