~ubuntu-branches/ubuntu/trusty/libdbi/trusty

« back to all changes in this revision

Viewing changes to src/dbi_main.c

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS), Laszlo Boszormenyi (GCS), Prach Pongpanich
  • Date: 2014-01-20 21:19:50 UTC
  • mfrom: (3.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20140120211950-zyd6ykii7rd4vm7x
Tags: 0.9.0-1
[ Laszlo Boszormenyi (GCS) ]
* Correct debian/copyright .

[ Prach Pongpanich ]
* Imported Upstream version 0.9.0 (Closes: #708115, #717437)
* Use debhelper short rules with autoreconf (Closes: #565558)
* Add -dbg package
* Update symbols file for new symbols
* Add multiarch support
* Bump Standards-Version to 3.9.5
* Change Vcs fields to point to collab-maint
* Adopt package (Closes: #635659)

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 * License along with this library; if not, write to the Free Software
18
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
19
 * 
20
 
 * $Id: dbi_main.c,v 1.79 2008/02/06 16:21:29 mhoenicka Exp $
 
20
 * $Id: dbi_main.c,v 1.103 2013/01/24 22:10:18 mhoenicka Exp $
21
21
 */
22
22
 
 
23
/* silence the deprecated warnings as this lib must implement and call
 
24
   the deprecated functions for the time being */
 
25
#define LIBDBI_API_DEPRECATED /**/
 
26
 
23
27
#ifdef HAVE_CONFIG_H
24
28
#include <config.h>
25
29
#endif
26
30
 
27
 
#define _GNU_SOURCE /* since we need the asprintf() prototype */
 
31
/* #define _GNU_SOURCE */ /* we need the asprintf() prototype but _GNU_SOURCE should be defined in config.h */
28
32
 
29
33
#include <stdio.h>
30
34
#include <stdlib.h>
31
35
#include <stdarg.h>
32
36
#include <string.h>
 
37
#include <strings.h> /* for strcasecmp */
 
38
#include <sys/types.h>
 
39
#include <stddef.h>
33
40
 
34
41
/* Dlopen stuff */
35
42
#if HAVE_LTDL_H
78
85
/* end dlopen stuff */
79
86
 
80
87
#include <sys/stat.h>
81
 
#include <unistd.h>
 
88
#ifdef HAVE_UNISTD_H
 
89
  #include <unistd.h>
 
90
#endif
82
91
#include <dirent.h>
83
92
 
84
93
#include <math.h>
103
112
#define DLSYM_PREFIX ""
104
113
#endif
105
114
 
 
115
#ifndef RTLD_NEXT
 
116
#define RTLD_NEXT ((void *) -1) /* taken from FreeBSD, just a compile helper */
 
117
#endif
 
118
 
106
119
/* declarations of optional external functions */
107
 
#ifndef HAVE_VASPRINTF
108
 
int int_vasprintf(char **result, const char *format, va_list *args);
 
120
#if !HAVE_DECL_VASPRINTF
109
121
int vasprintf(char **result, const char *format, va_list args);
110
122
#endif
111
 
#ifndef HAVE_ASPRINTF
 
123
#if !HAVE_DECL_ASPRINTF
112
124
int asprintf(char **result, const char *format, ...);
113
125
#endif
114
126
 
115
127
/* declarations for internal functions -- anything declared as static won't be accessible by name from client programs */
116
 
static dbi_driver_t *_get_driver(const char *filename);
 
128
static dbi_driver_t *_get_driver(const char *filename, dbi_inst_t *inst);
117
129
static void _free_custom_functions(dbi_driver_t *driver);
118
130
static dbi_option_t *_find_or_create_option_node(dbi_conn Conn, const char *key);
119
131
static int _update_internal_conn_list(dbi_conn_t *conn, int operation);
131
143
 
132
144
/* must not be called "ERROR" due to a name clash on Windoze */
133
145
static const char *my_ERROR = "ERROR";
134
 
static dbi_driver_t *rootdriver;
135
 
static dbi_conn_t *rootconn;
136
 
int dbi_verbosity = 1;
 
146
static dbi_inst dbi_inst_legacy;
 
147
 
137
148
 
138
149
/* XXX DBI CORE FUNCTIONS XXX */
139
150
 
140
 
int dbi_initialize(const char *driverdir) {
 
151
int dbi_initialize_r(const char *driverdir, dbi_inst *pInst) {
 
152
        dbi_inst_t *inst;
141
153
        DIR *dir;
142
154
        struct dirent *driver_dirent = NULL;
143
155
        struct stat statbuf;
145
157
        char *effective_driverdir;
146
158
        
147
159
        int num_loaded = 0;
 
160
        *pInst = NULL; /* use a defined value if the function fails */
148
161
        dbi_driver_t *driver = NULL;
149
162
        dbi_driver_t *prevdriver = NULL;
150
163
#if HAVE_LTDL_H
151
164
        (void)lt_dlinit();
152
165
#endif  
153
 
        rootdriver = NULL;
 
166
        /* init the instance */
 
167
        inst = malloc(sizeof(dbi_inst_t));
 
168
        if (!inst) {
 
169
                return -1;
 
170
        }
 
171
        *pInst = (void*) inst;
 
172
        inst->rootdriver = NULL;
 
173
        inst->rootconn = NULL;
 
174
        inst->dbi_verbosity = 1; /* TODO: is this really the correct default? */
 
175
        /* end instance init */
154
176
        effective_driverdir = (driverdir ? (char *)driverdir : DBI_DRIVER_DIR);
155
177
        dir = opendir(effective_driverdir);
156
178
 
158
180
                return -1;
159
181
        }
160
182
        else {
161
 
                while ((driver_dirent = readdir(dir)) != NULL) {
 
183
                struct dirent *buffer;
 
184
                size_t buffer_size;
 
185
                int status;
 
186
 
 
187
                /* allocate memory for readdir_r(3) */
 
188
                buffer_size = _dirent_buf_size(dir);
 
189
                if (buffer_size == 0) {
 
190
                  return -1;
 
191
                }
 
192
 
 
193
                buffer = (struct dirent *) malloc (buffer_size);
 
194
                if (buffer == NULL) {
 
195
                  return -1;
 
196
                }
 
197
 
 
198
                memset (buffer, 0, buffer_size);
 
199
 
 
200
                status = 0;
 
201
                while (42) { /* yes, we all admire Douglas Adams */
 
202
                        driver_dirent = NULL;
 
203
                        status = readdir_r (dir, buffer, &driver_dirent);
 
204
                        if (status != 0 || driver_dirent == NULL) {
 
205
                          break;
 
206
                        }
 
207
 
162
208
                        driver = NULL;
163
209
                        snprintf(fullpath, FILENAME_MAX, "%s%s%s", effective_driverdir, DBI_PATH_SEPARATOR, driver_dirent->d_name);
164
210
                        if ((stat(fullpath, &statbuf) == 0) && S_ISREG(statbuf.st_mode) && strrchr(driver_dirent->d_name, '.') && (!strcmp(strrchr(driver_dirent->d_name, '.'), DRIVER_EXT))) {
165
211
                                /* file is a stat'able regular file that ends in .so (or appropriate dynamic library extension) */
166
 
                                driver = _get_driver(fullpath);
 
212
                                driver = _get_driver(fullpath, inst);
167
213
                                if (driver && (driver->functions->initialize(driver) != -1)) {
168
 
                                        if (!rootdriver) {
169
 
                                                rootdriver = driver;
 
214
                                        if (!inst->rootdriver) {
 
215
                                                inst->rootdriver = driver;
170
216
                                        }
171
217
                                        if (prevdriver) {
172
218
                                                prevdriver->next = driver;
179
225
                                        if (driver && driver->functions) free(driver->functions);
180
226
                                        if (driver) free(driver);
181
227
                                        driver = NULL; /* don't include in linked list */
182
 
                                        if (dbi_verbosity) fprintf(stderr, "libdbi: Failed to load driver: %s\n", fullpath);
 
228
                                        if (inst->dbi_verbosity) fprintf(stderr, "libdbi: Failed to load driver: %s\n", fullpath);
183
229
                                }
184
230
                        }
185
 
                }
 
231
                } /* while (42) */
186
232
                closedir(dir);
 
233
                free(buffer);
187
234
        }
188
235
        
189
236
        return num_loaded;
190
237
}
191
238
 
192
 
void dbi_shutdown() {
193
 
        dbi_conn_t *curconn = rootconn;
 
239
int dbi_initialize(const char *driverdir) {
 
240
  return (dbi_initialize_r(driverdir, &dbi_inst_legacy));
 
241
}
 
242
 
 
243
void dbi_shutdown_r(dbi_inst Inst) {
 
244
        dbi_inst_t *inst = (dbi_inst_t*) Inst;
 
245
        dbi_conn_t *curconn = inst->rootconn;
194
246
        dbi_conn_t *nextconn;
195
247
        
196
 
        dbi_driver_t *curdriver = rootdriver;
 
248
        dbi_driver_t *curdriver = inst->rootdriver;
197
249
        dbi_driver_t *nextdriver;
198
250
        
199
251
        while (curconn) {
204
256
        
205
257
        while (curdriver) {
206
258
                nextdriver = curdriver->next;
 
259
                curdriver->functions->finalize(curdriver);              
207
260
                _safe_dlclose(curdriver);
208
261
                free(curdriver->functions);
209
262
                _free_custom_functions(curdriver);
215
268
#if HAVE_LTDL_H
216
269
        (void)lt_dlexit();
217
270
#endif  
218
 
        rootdriver = NULL;
 
271
        free(inst);
 
272
}
 
273
 
 
274
void dbi_shutdown() {
 
275
        dbi_shutdown_r(dbi_inst_legacy);
219
276
}
220
277
 
221
278
const char *dbi_version() {
222
279
        return "libdbi v" VERSION;
223
280
}
224
281
 
225
 
int dbi_set_verbosity(int verbosity) {
 
282
unsigned int dbi_version_numeric() {
 
283
  return (unsigned int)LIBDBI_VERSION;
 
284
}
 
285
 
 
286
int dbi_set_verbosity_r(int verbosity, dbi_inst Inst) {
 
287
        dbi_inst_t *inst = (dbi_inst_t*) Inst;
226
288
        /* whether or not to spew stderr messages when something bad happens (and
227
289
         * isn't handled through the normal connection-oriented DBI error
228
290
         * mechanisms) */
229
291
 
230
 
        int prev = dbi_verbosity;
231
 
        dbi_verbosity = verbosity;
 
292
        int prev = inst->dbi_verbosity;
 
293
        inst->dbi_verbosity = verbosity;
232
294
        return prev;
233
295
}
 
296
int dbi_set_verbosity(int verbosity) {
 
297
        return dbi_set_verbosity_r(verbosity, dbi_inst_legacy);
 
298
}
234
299
 
235
300
/* XXX DRIVER FUNCTIONS XXX */
236
301
 
237
 
dbi_driver dbi_driver_list(dbi_driver Current) {
 
302
dbi_driver dbi_driver_list_r(dbi_driver Current, dbi_inst Inst) {
 
303
        dbi_inst_t *inst = (dbi_inst_t*) Inst;
238
304
        dbi_driver_t *current = Current;
239
305
 
240
306
        if (current == NULL) {
241
 
                return (dbi_driver)rootdriver;
 
307
                return (dbi_driver)inst->rootdriver;
242
308
        }
243
309
 
244
310
        return (dbi_driver)current->next;
245
311
}
 
312
dbi_driver dbi_driver_list(dbi_driver Current) {
 
313
        return dbi_driver_list_r(Current, dbi_inst_legacy);
 
314
}
246
315
 
247
 
dbi_driver dbi_driver_open(const char *name) {
248
 
        dbi_driver_t *driver = rootdriver;
 
316
dbi_driver dbi_driver_open_r(const char *name, dbi_inst Inst) {
 
317
        dbi_inst_t *inst = (dbi_inst_t*) Inst;
 
318
        dbi_driver_t *driver = inst->rootdriver;
249
319
 
250
320
        while (driver && strcasecmp(name, driver->info->name)) {
251
321
                driver = driver->next;
253
323
 
254
324
        return driver;
255
325
}
 
326
dbi_driver dbi_driver_open(const char *name) {
 
327
        return dbi_driver_open_r(name, dbi_inst_legacy);
 
328
}
 
329
 
 
330
dbi_inst dbi_driver_get_instance(dbi_driver Driver) {
 
331
        dbi_driver_t *driver = Driver;
 
332
        
 
333
        if (!driver) return NULL;
 
334
        
 
335
        return driver->dbi_inst;
 
336
}
256
337
 
257
338
int dbi_driver_is_reserved_word(dbi_driver Driver, const char *word) {
258
339
        unsigned int idx = 0;
445
526
 
446
527
/* XXX DRIVER FUNCTIONS XXX */
447
528
 
448
 
dbi_conn dbi_conn_new(const char *name) {
 
529
dbi_conn dbi_conn_new_r(const char *name, dbi_inst Inst) {
449
530
        dbi_driver driver;
450
531
        dbi_conn conn;
451
532
 
452
 
        driver = dbi_driver_open(name);
 
533
        driver = dbi_driver_open_r(name, Inst);
453
534
        conn = dbi_conn_open(driver);
454
535
 
455
536
        return conn;
456
537
}
 
538
dbi_conn dbi_conn_new(const char *name) {
 
539
  return (dbi_conn_new_r(name, dbi_inst_legacy));
 
540
}
457
541
 
458
542
dbi_conn dbi_conn_open(dbi_driver Driver) {
459
543
        dbi_driver_t *driver = Driver;
475
559
        conn->error_flag = DBI_ERROR_NONE; /* for legacy code only */
476
560
        conn->error_number = DBI_ERROR_NONE;
477
561
        conn->error_message = NULL;
 
562
        conn->full_errmsg = NULL;
478
563
        conn->error_handler = NULL;
479
564
        conn->error_handler_argument = NULL;
480
565
        _update_internal_conn_list(conn, 1);
503
588
void dbi_conn_close(dbi_conn Conn) {
504
589
        dbi_conn_t *conn = Conn;
505
590
        
506
 
        if (!conn) return;
 
591
        if (!conn || !(conn->connection)) return;
507
592
        
508
593
        _update_internal_conn_list(conn, -1);
509
594
        
515
600
        
516
601
        if (conn->current_db) free(conn->current_db);
517
602
        if (conn->error_message) free(conn->error_message);
 
603
        if (conn->full_errmsg) free(conn->full_errmsg);
518
604
        conn->error_number = 0;
519
605
        
520
606
        conn->error_handler = NULL;
536
622
int dbi_conn_error(dbi_conn Conn, const char **errmsg_dest) {
537
623
        dbi_conn_t *conn = Conn;
538
624
        char number_portion[20];
539
 
        static char *errmsg = NULL; // XXX quick hack, revisit this when API is redesigned
540
625
 
541
626
        if (errmsg_dest) {
542
 
                if (errmsg) free(errmsg);
 
627
                if (conn->full_errmsg) free(conn->full_errmsg);
543
628
                
544
629
                if (conn->error_number) {
545
630
                        snprintf(number_portion, 20, "%d: ", conn->error_number);
548
633
                        number_portion[0] = '\0';
549
634
                }
550
635
 
551
 
                asprintf(&errmsg, "%s%s", number_portion, conn->error_message ? conn->error_message : "");
552
 
                *errmsg_dest = errmsg;
 
636
                asprintf(&(conn->full_errmsg), "%s%s", number_portion, conn->error_message ? conn->error_message : "");
 
637
                *errmsg_dest = conn->full_errmsg;
553
638
        }
554
639
 
555
640
        return conn->error_number;
703
788
   do */
704
789
 
705
790
size_t dbi_conn_escape_string_copy(dbi_conn Conn, const char *orig, char **newquoted) {
706
 
        char *newstr;
707
791
        size_t newlen;
708
792
        
709
793
        if (!Conn) {
954
1038
        dbi_conn_t *conn = Conn;
955
1039
        int retval;
956
1040
 
957
 
        if (!conn) {
 
1041
        if (!conn || !(conn->connection)) {
958
1042
          return -1;
959
1043
        }
960
1044
 
969
1053
        dbi_conn_t *conn = Conn;
970
1054
        const char *retval;
971
1055
 
972
 
        if (!conn) return NULL;
 
1056
        if (!conn || !(conn->connection)) return NULL;
973
1057
 
974
1058
        _reset_conn_error(conn);
975
1059
 
982
1066
        dbi_conn_t *conn = Conn;
983
1067
        char versionstring[VERSIONSTRING_LENGTH];
984
1068
 
985
 
        if (!conn) return 0;
 
1069
        if (!conn || !(conn->connection)) return 0;
986
1070
 
987
1071
        _reset_conn_error(conn);
988
1072
 
994
1078
char* dbi_conn_get_engine_version_string(dbi_conn Conn, char *versionstring) {
995
1079
        dbi_conn_t *conn = Conn;
996
1080
 
997
 
        if (!conn) return 0;
 
1081
        if (!conn || !(conn->connection)) return 0;
998
1082
 
999
1083
        _reset_conn_error(conn);
1000
1084
 
1005
1089
        dbi_conn_t *conn = Conn;
1006
1090
        dbi_result_t *result;
1007
1091
        
1008
 
        if (!conn) return NULL;
 
1092
        if (!conn || !(conn->connection)) return NULL;
1009
1093
        
1010
1094
        _reset_conn_error(conn);
1011
1095
 
1022
1106
        dbi_conn_t *conn = Conn;
1023
1107
        dbi_result_t *result;
1024
1108
        
1025
 
        if (!conn) return NULL;
 
1109
        if (!conn || !(conn->connection)) return NULL;
1026
1110
        
1027
1111
        _reset_conn_error(conn);
1028
1112
 
1039
1123
        dbi_conn_t *conn = Conn;
1040
1124
        dbi_result_t *result;
1041
1125
 
1042
 
        if (!conn) return NULL;
 
1126
        if (!conn || !(conn->connection)) return NULL;
1043
1127
        
1044
1128
        _reset_conn_error(conn);
1045
1129
 
1059
1143
        dbi_result_t *result;
1060
1144
        va_list ap;
1061
1145
 
1062
 
        if (!conn) return NULL;
 
1146
        if (!conn || !(conn->connection)) return NULL;
1063
1147
        
1064
1148
        _reset_conn_error(conn);
1065
1149
 
1082
1166
        dbi_conn_t *conn = Conn;
1083
1167
        dbi_result_t *result;
1084
1168
 
1085
 
        if (!conn) return NULL;
 
1169
        if (!conn || !(conn->connection)) return NULL;
1086
1170
 
1087
1171
        _reset_conn_error(conn);
1088
1172
 
1089
 
        _logquery_null(conn, statement, st_length);
 
1173
        _logquery_null(conn, (const char *)statement, st_length);
1090
1174
        result = conn->driver->functions->query_null(conn, statement, st_length);
1091
1175
 
1092
1176
        if (result == NULL) {
1100
1184
        dbi_conn_t *conn = Conn;
1101
1185
        const char *retval;
1102
1186
        
1103
 
        if (!conn) return -1;
 
1187
        if (!conn || !(conn->connection)) return -1;
1104
1188
        
1105
1189
        _reset_conn_error(conn);
1106
1190
 
1129
1213
unsigned long long dbi_conn_sequence_last(dbi_conn Conn, const char *name) {
1130
1214
        dbi_conn_t *conn = Conn;
1131
1215
        unsigned long long result;
1132
 
        if (!conn) return 0;
 
1216
        if (!conn || !(conn->connection)) return 0;
1133
1217
 
1134
1218
        _reset_conn_error(conn);
1135
1219
 
1140
1224
unsigned long long dbi_conn_sequence_next(dbi_conn Conn, const char *name) {
1141
1225
        dbi_conn_t *conn = Conn;
1142
1226
        unsigned long long result;
1143
 
        if (!conn) return 0;
 
1227
        if (!conn || !(conn->connection)) return 0;
1144
1228
 
1145
1229
        _reset_conn_error(conn);
1146
1230
 
1152
1236
        dbi_conn_t *conn = Conn;
1153
1237
        int result;
1154
1238
 
1155
 
        if (!conn) return 0;
 
1239
        if (!conn || !(conn->connection)) return 0;
1156
1240
 
1157
1241
        _reset_conn_error(conn);
1158
1242
 
1160
1244
        return result;
1161
1245
}
1162
1246
 
 
1247
/* XXX TRANSACTION RELATED FUNCTIONS XXX */
 
1248
int dbi_conn_transaction_begin(dbi_conn Conn) {
 
1249
        dbi_conn_t *conn = Conn;
 
1250
        int result;
 
1251
 
 
1252
        if (!conn || !(conn->connection)) return 0;
 
1253
 
 
1254
        _reset_conn_error(conn);
 
1255
 
 
1256
        result = conn->driver->functions->transaction_begin(conn);
 
1257
        return result;
 
1258
}
 
1259
 
 
1260
int dbi_conn_transaction_commit(dbi_conn Conn) {
 
1261
        dbi_conn_t *conn = Conn;
 
1262
        int result;
 
1263
 
 
1264
        if (!conn || !(conn->connection)) return 0;
 
1265
 
 
1266
        _reset_conn_error(conn);
 
1267
 
 
1268
        result = conn->driver->functions->transaction_commit(conn);
 
1269
        return result;
 
1270
}
 
1271
 
 
1272
int dbi_conn_transaction_rollback(dbi_conn Conn) {
 
1273
        dbi_conn_t *conn = Conn;
 
1274
        int result;
 
1275
 
 
1276
        if (!conn || !(conn->connection)) return 0;
 
1277
 
 
1278
        _reset_conn_error(conn);
 
1279
 
 
1280
        result = conn->driver->functions->transaction_rollback(conn);
 
1281
        return result;
 
1282
}
 
1283
 
 
1284
int dbi_conn_savepoint(dbi_conn Conn, const char *savepoint) {
 
1285
        dbi_conn_t *conn = Conn;
 
1286
        int result;
 
1287
 
 
1288
        if (!conn || !(conn->connection)
 
1289
            || !savepoint) return 0;
 
1290
 
 
1291
        _reset_conn_error(conn);
 
1292
 
 
1293
        result = conn->driver->functions->savepoint(conn, savepoint);
 
1294
        return result;
 
1295
}
 
1296
 
 
1297
int dbi_conn_rollback_to_savepoint(dbi_conn Conn, const char *savepoint) {
 
1298
        dbi_conn_t *conn = Conn;
 
1299
        int result;
 
1300
 
 
1301
        if (!conn || !(conn->connection)
 
1302
            || !savepoint) return 0;
 
1303
 
 
1304
        _reset_conn_error(conn);
 
1305
 
 
1306
        result = conn->driver->functions->rollback_to_savepoint(conn, savepoint);
 
1307
        return result;
 
1308
}
 
1309
 
 
1310
int dbi_conn_release_savepoint(dbi_conn Conn, const char *savepoint) {
 
1311
        dbi_conn_t *conn = Conn;
 
1312
        int result;
 
1313
 
 
1314
        if (!conn || !(conn->connection)
 
1315
            || !savepoint) return 0;
 
1316
 
 
1317
        _reset_conn_error(conn);
 
1318
 
 
1319
        result = conn->driver->functions->release_savepoint(conn, savepoint);
 
1320
        return result;
 
1321
}
 
1322
 
 
1323
 
1163
1324
/* XXX INTERNAL PRIVATE IMPLEMENTATION FUNCTIONS XXX */
1164
1325
 
1165
 
static dbi_driver_t *_get_driver(const char *filename) {
 
1326
static dbi_driver_t *_get_driver(const char *filename, dbi_inst_t *inst) {
1166
1327
        dbi_driver_t *driver;
1167
1328
        void *dlhandle;
 
1329
        void *symhandle;
1168
1330
        const char **custom_functions_list;
1169
1331
        unsigned int idx = 0;
1170
1332
        dbi_custom_function_t *prevcustom = NULL;
1171
1333
        dbi_custom_function_t *custom = NULL;
1172
 
        char function_name[256];
 
1334
        const char* error;
1173
1335
 
1174
1336
        dlhandle = my_dlopen(filename, DLOPEN_FLAG); /* DLOPEN_FLAG defined by autoconf */
1175
1337
 
1183
1345
 
1184
1346
                driver->dlhandle = dlhandle;
1185
1347
                driver->filename = strdup(filename);
 
1348
                driver->dbi_inst = inst;
1186
1349
                driver->next = NULL;
1187
1350
                driver->caps = NULL;
1188
1351
                driver->functions = malloc(sizeof(dbi_functions_t));
1190
1353
                if ( /* nasty looking if block... is there a better way to do it? */
1191
1354
                        ((driver->functions->register_driver = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_register_driver")) == NULL) ||
1192
1355
                        ((driver->functions->initialize = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_initialize")) == NULL) ||
 
1356
                        ((driver->functions->finalize = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_finalize")) == NULL) ||
1193
1357
                        ((driver->functions->connect = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_connect")) == NULL) ||
1194
1358
                        ((driver->functions->disconnect = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_disconnect")) == NULL) ||
1195
1359
                        ((driver->functions->fetch_row = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_fetch_row")) == NULL) ||
1204
1368
                        ((driver->functions->list_tables = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_list_tables")) == NULL) ||
1205
1369
                        ((driver->functions->query = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_query")) == NULL) ||
1206
1370
                        ((driver->functions->query_null = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_query_null")) == NULL) ||
 
1371
                        ((driver->functions->transaction_begin = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_transaction_begin")) == NULL) ||
 
1372
                        ((driver->functions->transaction_commit = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_transaction_commit")) == NULL) ||
 
1373
                        ((driver->functions->transaction_rollback = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_transaction_rollback")) == NULL) ||
 
1374
                        ((driver->functions->savepoint = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_savepoint")) == NULL) ||
 
1375
                        ((driver->functions->rollback_to_savepoint = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_rollback_to_savepoint")) == NULL) ||
 
1376
                        ((driver->functions->release_savepoint = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_release_savepoint")) == NULL) ||
1207
1377
                        ((driver->functions->quote_string = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_quote_string")) == NULL) ||
1208
1378
                        ((driver->functions->quote_binary = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_quote_binary")) == NULL) ||
1209
1379
                        ((driver->functions->conn_quote_string = my_dlsym(dlhandle, DLSYM_PREFIX "dbd_conn_quote_string")) == NULL) ||
1221
1391
                }
1222
1392
                driver->functions->register_driver(&driver->info, &custom_functions_list, &driver->reserved_words);
1223
1393
                driver->custom_functions = NULL; /* in case no custom functions are available */
 
1394
 
 
1395
                /* this is a weird hack for the sake of dlsym
 
1396
                   portability. I can't imagine why using dlhandle
 
1397
                   fails on FreeBSD except that dlsym may expect a
 
1398
                   leading underscore in front of the function
 
1399
                   names. But then, why does RTLD_NEXT work? */
 
1400
                /* update 2008-11-28: this is most likely a FreeBSD
 
1401
                   bug which was fixed in 6.3. TODO: follow up on this
 
1402
                   once I have a 6.3 or later box */
 
1403
                if (DLSYM_HANDLE) { /* most OSes */
 
1404
                  symhandle = dlhandle;
 
1405
                }
 
1406
                else { /* the BSDs */
 
1407
                  symhandle = RTLD_NEXT;
 
1408
                }
 
1409
 
1224
1410
                while (custom_functions_list && custom_functions_list[idx] != NULL) {
1225
1411
                        custom = malloc(sizeof(dbi_custom_function_t));
1226
1412
                        if (!custom) {
1232
1418
                        }
1233
1419
                        custom->next = NULL;
1234
1420
                        custom->name = custom_functions_list[idx];
1235
 
                        snprintf(function_name, 256, DLSYM_PREFIX "dbd_%s", custom->name);
1236
 
                        custom->function_pointer = my_dlsym(dlhandle, function_name);
1237
 
                        if (!custom->function_pointer) {
1238
 
                                _free_custom_functions(driver);
1239
 
                                free(custom); /* not linked into the list yet */
1240
 
                                free(driver->functions);
1241
 
                                free(driver->filename);
1242
 
                                free(driver);
1243
 
                                return NULL;
 
1421
/*                      snprintf(function_name, 256, DLSYM_PREFIX "dbd_%s", custom->name); */
 
1422
/*                      printf("loading %s<<\n", custom->name); */
 
1423
                        my_dlerror(); /* clear any previous errors */
 
1424
                        custom->function_pointer = my_dlsym(symhandle, custom->name);
 
1425
/*                      if (!custom->function_pointer) { */
 
1426
                        if ((error = my_dlerror()) != NULL) {
 
1427
/*                        fprintf(STDERR, error); */
 
1428
 
 
1429
                          /* this usually fails because a function was
 
1430
                             renamed, is no longer available, or not
 
1431
                             yet available. Simply skip this
 
1432
                             function */
 
1433
                          free(custom); /* not linked into the list yet */
 
1434
                          idx++;
 
1435
                          continue;
1244
1436
                        }
1245
1437
                        if (driver->custom_functions == NULL) {
1246
1438
                                driver->custom_functions = custom;
1289
1481
         * operation = -1: remove conn
1290
1482
         *           =  0: just look for conn (return 1 if found, -1 if not)
1291
1483
         *           =  1: add conn */
1292
 
        dbi_conn_t *curconn = rootconn;
 
1484
        dbi_conn_t *curconn = conn->driver->dbi_inst->rootconn;
1293
1485
        dbi_conn_t *prevconn = NULL;
1294
1486
 
1295
1487
        if ((operation == -1) || (operation == 0)) {
1301
1493
                if (operation == 0) return 1;
1302
1494
                else if (operation == -1) {
1303
1495
                        if (prevconn) prevconn->next = curconn->next;
1304
 
                        else rootconn = NULL;
 
1496
                        else conn->driver->dbi_inst->rootconn = NULL;
1305
1497
                        return 0;
1306
1498
                }
1307
1499
        }
1313
1505
                        curconn->next = conn;
1314
1506
                }
1315
1507
                else {
1316
 
                        rootconn = conn;
 
1508
                        conn->driver->dbi_inst->rootconn = conn;
1317
1509
                }
1318
1510
                conn->next = NULL;
1319
1511
                return 0;
1468
1660
        /* hahaha! who woulda ever thunk strawberry's code would come in handy? */
1469
1661
        // find first (highest) bit set; methods not using FP can be found at 
1470
1662
        // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
1471
 
        unsigned startbit = log(rangemin)/log(2);
1472
 
        unsigned endbit = log(rangemax)/log(2);
 
1663
/*      unsigned startbit = log(rangemin)/log(2); */
 
1664
/*      unsigned endbit = log(rangemax)/log(2); */
 
1665
  unsigned int startbit = 0;
 
1666
  unsigned int endbit = 0;
 
1667
 
 
1668
  while (rangemin >>= 1) {
 
1669
    startbit++;
 
1670
  }
 
1671
 
 
1672
  while (rangemax >>= 1) {
 
1673
    endbit++;
 
1674
  }
 
1675
 
1473
1676
        // construct mask from startbit to endbit inclusive
1474
1677
        unsigned attrib_mask = ((1<<(endbit+1))-1) ^ ((1<<startbit)-1);
1475
1678
        return attribs & attrib_mask;
1535
1738
  return 1;
1536
1739
}
1537
1740
 
 
1741
 
1538
1742
#if HAVE_MACH_O_DYLD_H
1539
1743
static int dyld_error_set=0;
1540
1744
static void * dyld_dlopen(const char * file)