]> jfr.im git - irc/quakenet/newserv.git/blob - dbapi2/dbapi2-adapter.inc
cfb555a3d9e4ab90f04484cd5043ff42b2bd64cf
[irc/quakenet/newserv.git] / dbapi2 / dbapi2-adapter.inc
1 #include <stdarg.h>
2 #include <stdio.h>
3
4 #define DBAPI2_ADAPTER
5 #include "../dbapi/dbapi.h"
6
7 #define DBAPI2_RESULT_HANDLE DBResult
8
9 #include "../dbapi2/dbapi2.h"
10 #include "../lib/stringbuf.h"
11 #include "../lib/version.h"
12
13 static DBAPI2_HANDLE *dbapi2_adapter_new(const DBAPIConn *);
14 static void dbapi2_adapter_close(DBAPIConn *);
15
16 static void dbapi2_adapter_query(const DBAPIConn *, DBAPIQueryCallback, DBAPIUserData, const char *);
17 static void dbapi2_adapter_createtable(const DBAPIConn *, DBAPIQueryCallback, DBAPIUserData, const char *);
18 static void dbapi2_adapter_loadtable(const DBAPIConn *, DBAPIQueryCallback, DBAPIQueryCallback, DBAPIQueryCallback, DBAPIUserData data, const char *);
19
20 static void dbapi2_adapter_escapestring(const DBAPIConn *, char *, const char *, size_t);
21 static int dbapi2_adapter_quotestring(const DBAPIConn *, char *, size_t, const char *, size_t);
22
23 static char *dbapi2_adapter_tablename(const DBAPIConn *, const char *);
24
25 static void dbapi2_adapter_call(const DBAPIConn *, DBAPIQueryCallback, DBAPIUserData, const char *, const char *);
26
27 static 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,
36 .quotestring = dbapi2_adapter_quotestring,
37
38 .tablename = dbapi2_adapter_tablename,
39
40 .call = dbapi2_adapter_call,
41 };
42
43 struct DBAPI2AdapterQueryCallback {
44 const DBAPIConn *db;
45 DBAPIUserData data;
46 DBAPIQueryCallback callback;
47 };
48
49 struct DBAPI2AdapterLoadTableCallback {
50 const DBAPIConn *db;
51 DBAPIUserData data;
52 DBAPIQueryCallback init, callback, fini;
53 };
54
55 static int adapterhandle;
56
57 static void registeradapterprovider(void) {
58 adapterhandle = registerdbprovider(DBAPI2_ADAPTER_NAME, &adapterprovider);
59 }
60
61 static void deregisteradapterprovider(void) {
62 deregisterdbprovider(adapterhandle);
63 }
64
65 static DBAPI2_HANDLE *dbapi2_adapter_new(const DBAPIConn *db) {
66 long id = dbgetid();
67
68 dbattach(((DBAPIConn *)db)->name);
69
70 return (void *)id;
71 }
72
73 static void dbapi2_adapter_close(DBAPIConn *db) {
74 dbfreeid((int)(long)db->handle);
75 dbdetach(db->name);
76 }
77
78 static char *dbapi2_adapter_result_get(const DBAPIResult *r, unsigned int column) {
79 return dbgetvalue(r->handle, column);
80 }
81
82 static int dbapi2_adapter_result_next(const DBAPIResult *r) {
83 return dbfetchrow(r->handle);
84 }
85
86 static void dbapi2_adapter_result_clear(const DBAPIResult *r) {
87 if(!r)
88 return;
89
90 dbclear(r->handle);
91 }
92
93 static 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
115 static void dbapi2_adapter_querywrapper(DBConn *c, void *data) {
116 struct DBAPI2AdapterQueryCallback *a = data;
117 DBAPIResult r;
118
119 a->callback(wrapresult(&r, c), a->data);
120
121 free(a);
122 }
123
124 static void sqquery(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, int flags, const char *query) {
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
137 dbasyncqueryf((int)(long)db->handle, cb?dbapi2_adapter_querywrapper:NULL, a, flags, "%s", query);
138 }
139
140 static void dbapi2_adapter_query(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, const char *query) {
141 sqquery(db, cb, data, 0, query);
142 }
143
144 static void dbapi2_adapter_createtable(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, const char *query) {
145 sqquery(db, cb, data, DB_CREATE, query);
146 }
147
148 static void dbapi2_adapter_loadtablewrapper_init(DBConn *c, void *data) {
149 struct DBAPI2AdapterLoadTableCallback *a = data;
150
151 a->init(NULL, a->data);
152 }
153
154 static void dbapi2_adapter_loadtablewrapper_data(DBConn *c, void *data) {
155 struct DBAPI2AdapterLoadTableCallback *a = data;
156 DBAPIResult r;
157
158 a->callback(wrapresult(&r, c), a->data);
159 }
160
161 static void dbapi2_adapter_loadtablewrapper_fini(DBConn *c, void *data) {
162 struct DBAPI2AdapterLoadTableCallback *a = data;
163
164 if(a->fini)
165 a->fini(NULL, a->data);
166
167 free(a);
168 }
169
170 static void dbapi2_adapter_loadtable(const DBAPIConn *db, DBAPIQueryCallback init, DBAPIQueryCallback cb, DBAPIQueryCallback final, DBAPIUserData data, const char *table) {
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
183 static void dbapi2_adapter_escapestring(const DBAPIConn *db, char *buf, const char *data, size_t len) {
184 dbescapestring(buf, (char *)data, len);
185 }
186
187 #ifndef DBAPI2_CUSTOM_QUOTESTRING
188 static int dbapi2_adapter_quotestring(const DBAPIConn *db, char *buf, size_t buflen, const char *data, size_t len) {
189 StringBuf b;
190 char xbuf[len * 2 + 5];
191 size_t esclen;
192
193 sbinit(&b, buf, buflen);
194 esclen = dbescapestring(xbuf, (char *)data, len);
195
196 sbaddchar(&b, '\'');
197 sbaddstrlen(&b, xbuf, esclen);
198 sbaddchar(&b, '\'');
199
200 if(!sbterminate(&b))
201 return 0;
202
203 return 1;
204 }
205 #endif
206
207 #ifndef DBAPI2_CUSTOM_TABLENAME
208 static char *dbapi2_adapter_tablename(const DBAPIConn *db, const char *tablename) {
209 static char buf[1024];
210
211 snprintf(buf, sizeof(buf), "%s.%s", db->name, tablename);
212
213 return buf;
214 }
215 #endif
216
217 static 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