]> jfr.im git - irc/quakenet/newserv.git/blame - dbapi2/dbapi2-adapter.inc
Make the pool allocator Valgrind-aware.
[irc/quakenet/newserv.git] / dbapi2 / dbapi2-adapter.inc
CommitLineData
39c33a3d 1#include <stdarg.h>
4277aef7 2#include <stdio.h>
39c33a3d
CP
3
4#define DBAPI2_ADAPTER
5#include "../dbapi/dbapi.h"
6
7#define DBAPI2_RESULT_HANDLE DBResult
8
9#include "../dbapi2/dbapi2.h"
39c33a3d 10#include "../lib/stringbuf.h"
8f072e42 11#include "../lib/version.h"
39c33a3d 12
4a532778 13static DBAPI2_HANDLE *dbapi2_adapter_new(const DBAPIConn *);
39c33a3d
CP
14static void dbapi2_adapter_close(DBAPIConn *);
15
24e1aba8
CP
16static void dbapi2_adapter_query(const DBAPIConn *, DBAPIQueryCallback, DBAPIUserData, const char *);
17static void dbapi2_adapter_createtable(const DBAPIConn *, DBAPIQueryCallback, DBAPIUserData, const char *);
4a532778 18static void dbapi2_adapter_loadtable(const DBAPIConn *, DBAPIQueryCallback, DBAPIQueryCallback, DBAPIQueryCallback, DBAPIUserData data, const char *);
39c33a3d 19
4a532778
CP
20static void dbapi2_adapter_escapestring(const DBAPIConn *, char *, const char *, size_t);
21static int dbapi2_adapter_quotestring(const DBAPIConn *, char *, size_t, const char *, size_t);
39c33a3d 22
4a532778 23static char *dbapi2_adapter_tablename(const DBAPIConn *, const char *);
4277aef7 24
4d47ff97
CP
25static void dbapi2_adapter_call(const DBAPIConn *, DBAPIQueryCallback, DBAPIUserData, const char *, const char *);
26
39c33a3d
CP
27static DBAPIProvider adapterprovider = {
28 .new = dbapi2_adapter_new,
29 .close = dbapi2_adapter_close,
30
31 .query = dbapi2_adapter_query,
32 .createtable = dbapi2_adapter_createtable,
33 .loadtable = dbapi2_adapter_loadtable,
34
35 .escapestring = dbapi2_adapter_escapestring,
4277aef7
CP
36 .quotestring = dbapi2_adapter_quotestring,
37
38 .tablename = dbapi2_adapter_tablename,
4d47ff97
CP
39
40 .call = dbapi2_adapter_call,
39c33a3d
CP
41};
42
43struct DBAPI2AdapterQueryCallback {
4a532778 44 const DBAPIConn *db;
39c33a3d
CP
45 DBAPIUserData data;
46 DBAPIQueryCallback callback;
47};
48
49struct DBAPI2AdapterLoadTableCallback {
4a532778 50 const DBAPIConn *db;
39c33a3d
CP
51 DBAPIUserData data;
52 DBAPIQueryCallback init, callback, fini;
53};
54
55static int adapterhandle;
56
57static void registeradapterprovider(void) {
58 adapterhandle = registerdbprovider(DBAPI2_ADAPTER_NAME, &adapterprovider);
59}
60
61static void deregisteradapterprovider(void) {
62 deregisterdbprovider(adapterhandle);
63}
64
4a532778 65static DBAPI2_HANDLE *dbapi2_adapter_new(const DBAPIConn *db) {
39c33a3d
CP
66 long id = dbgetid();
67
4a532778 68 dbattach(((DBAPIConn *)db)->name);
39c33a3d
CP
69
70 return (void *)id;
71}
72
73static void dbapi2_adapter_close(DBAPIConn *db) {
74 dbfreeid((int)(long)db->handle);
75 dbdetach(db->name);
76}
77
4a532778 78static char *dbapi2_adapter_result_get(const DBAPIResult *r, unsigned int column) {
39c33a3d
CP
79 return dbgetvalue(r->handle, column);
80}
81
4a532778 82static int dbapi2_adapter_result_next(const DBAPIResult *r) {
39c33a3d
CP
83 return dbfetchrow(r->handle);
84}
85
4a532778 86static void dbapi2_adapter_result_clear(const DBAPIResult *r) {
39c33a3d
CP
87 if(!r)
88 return;
89
90 dbclear(r->handle);
91}
92
93static DBAPIResult *wrapresult(DBAPIResult *r, DBConn *c) {
94 if(!c)
95 return NULL;
96
97 if(!r)
98 r = calloc(1, sizeof(DBAPIResult));
99
100 r->clear = dbapi2_adapter_result_clear;
101 r->handle = dbgetresult(c);
102
103 if(!dbquerysuccessful(r->handle))
104 return r;
105
106 r->success = 1;
107 r->fields = dbnumfields(r->handle);
108
109 r->get = dbapi2_adapter_result_get;
110 r->next = dbapi2_adapter_result_next;
111
112 return r;
113}
114
115static void dbapi2_adapter_querywrapper(DBConn *c, void *data) {
116 struct DBAPI2AdapterQueryCallback *a = data;
76286174 117 DBAPIResult r;
39c33a3d 118
76286174 119 a->callback(wrapresult(&r, c), a->data);
39c33a3d
CP
120
121 free(a);
122}
123
24e1aba8 124static void sqquery(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, int flags, const char *query) {
39c33a3d
CP
125 struct DBAPI2AdapterQueryCallback *a;
126
127 if(cb) {
128 a = malloc(sizeof(struct DBAPI2AdapterQueryCallback));
129
130 a->db = db;
131 a->data = data;
132 a->callback = cb;
133 } else {
134 a = NULL;
135 }
136
24e1aba8 137 dbasyncqueryf((int)(long)db->handle, cb?dbapi2_adapter_querywrapper:NULL, a, flags, "%s", query);
39c33a3d
CP
138}
139
24e1aba8
CP
140static void dbapi2_adapter_query(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, const char *query) {
141 sqquery(db, cb, data, 0, query);
39c33a3d
CP
142}
143
24e1aba8
CP
144static void dbapi2_adapter_createtable(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, const char *query) {
145 sqquery(db, cb, data, DB_CREATE, query);
39c33a3d
CP
146}
147
148static void dbapi2_adapter_loadtablewrapper_init(DBConn *c, void *data) {
149 struct DBAPI2AdapterLoadTableCallback *a = data;
150
c73fb0ab 151 a->init(NULL, a->data);
39c33a3d
CP
152}
153
154static void dbapi2_adapter_loadtablewrapper_data(DBConn *c, void *data) {
155 struct DBAPI2AdapterLoadTableCallback *a = data;
76286174 156 DBAPIResult r;
39c33a3d 157
76286174 158 a->callback(wrapresult(&r, c), a->data);
39c33a3d
CP
159}
160
161static void dbapi2_adapter_loadtablewrapper_fini(DBConn *c, void *data) {
162 struct DBAPI2AdapterLoadTableCallback *a = data;
163
164 if(a->fini)
c73fb0ab 165 a->fini(NULL, a->data);
39c33a3d
CP
166
167 free(a);
168}
169
4a532778 170static void dbapi2_adapter_loadtable(const DBAPIConn *db, DBAPIQueryCallback init, DBAPIQueryCallback cb, DBAPIQueryCallback final, DBAPIUserData data, const char *table) {
39c33a3d
CP
171 struct DBAPI2AdapterLoadTableCallback *a = malloc(sizeof(struct DBAPI2AdapterLoadTableCallback));
172
173 a->db = db;
174 a->data = data;
175
176 a->init = init;
177 a->callback = cb;
178 a->fini = final;
179
180 dbloadtable_tag((char *)table, init?dbapi2_adapter_loadtablewrapper_init:NULL, cb?dbapi2_adapter_loadtablewrapper_data:NULL, dbapi2_adapter_loadtablewrapper_fini, a);
181}
182
4a532778 183static void dbapi2_adapter_escapestring(const DBAPIConn *db, char *buf, const char *data, size_t len) {
39c33a3d
CP
184 dbescapestring(buf, (char *)data, len);
185}
186
187#ifndef DBAPI2_CUSTOM_QUOTESTRING
4a532778 188static int dbapi2_adapter_quotestring(const DBAPIConn *db, char *buf, size_t buflen, const char *data, size_t len) {
39c33a3d 189 StringBuf b;
39c33a3d
CP
190 char xbuf[len * 2 + 5];
191 size_t esclen;
192
2667bceb 193 sbinit(&b, buf, buflen);
39c33a3d
CP
194 esclen = dbescapestring(xbuf, (char *)data, len);
195
196 sbaddchar(&b, '\'');
197 sbaddstrlen(&b, xbuf, esclen);
198 sbaddchar(&b, '\'');
199
2667bceb 200 if(!sbterminate(&b))
39c33a3d
CP
201 return 0;
202
203 return 1;
204}
205#endif
4277aef7
CP
206
207#ifndef DBAPI2_CUSTOM_TABLENAME
4a532778 208static char *dbapi2_adapter_tablename(const DBAPIConn *db, const char *tablename) {
4277aef7
CP
209 static char buf[1024];
210
211 snprintf(buf, sizeof(buf), "%s.%s", db->name, tablename);
212
213 return buf;
214}
215#endif
4d47ff97
CP
216
217static void dbapi2_adapter_call(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, const char *function, const char *query) {
218 struct DBAPI2AdapterQueryCallback *a;
219 char buf[512];
220
221 if(cb) {
222 a = malloc(sizeof(struct DBAPI2AdapterQueryCallback));
223
224 a->db = db;
225 a->data = data;
226 a->callback = cb;
227 } else {
228 a = NULL;
229 }
230
231 snprintf(buf, sizeof(buf), "%s", db->tablename(db, function));
232 dbcall((int)(long)db->handle, cb?dbapi2_adapter_querywrapper:NULL, a, buf, query);
233}
234