]> jfr.im git - irc/quakenet/newserv.git/blob - dbapi2/dbapi2-adapter.inc
merge
[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 DBAPIProvider adapterprovider = {
26 .new = dbapi2_adapter_new,
27 .close = dbapi2_adapter_close,
28
29 .query = dbapi2_adapter_query,
30 .createtable = dbapi2_adapter_createtable,
31 .loadtable = dbapi2_adapter_loadtable,
32
33 .escapestring = dbapi2_adapter_escapestring,
34 .quotestring = dbapi2_adapter_quotestring,
35
36 .tablename = dbapi2_adapter_tablename,
37 };
38
39 struct DBAPI2AdapterQueryCallback {
40 const DBAPIConn *db;
41 DBAPIUserData data;
42 DBAPIQueryCallback callback;
43 };
44
45 struct DBAPI2AdapterLoadTableCallback {
46 const DBAPIConn *db;
47 DBAPIUserData data;
48 DBAPIQueryCallback init, callback, fini;
49 };
50
51 static int adapterhandle;
52
53 static void registeradapterprovider(void) {
54 adapterhandle = registerdbprovider(DBAPI2_ADAPTER_NAME, &adapterprovider);
55 }
56
57 static void deregisteradapterprovider(void) {
58 deregisterdbprovider(adapterhandle);
59 }
60
61 static DBAPI2_HANDLE *dbapi2_adapter_new(const DBAPIConn *db) {
62 long id = dbgetid();
63
64 dbattach(((DBAPIConn *)db)->name);
65
66 return (void *)id;
67 }
68
69 static void dbapi2_adapter_close(DBAPIConn *db) {
70 dbfreeid((int)(long)db->handle);
71 dbdetach(db->name);
72 }
73
74 static char *dbapi2_adapter_result_get(const DBAPIResult *r, unsigned int column) {
75 return dbgetvalue(r->handle, column);
76 }
77
78 static int dbapi2_adapter_result_next(const DBAPIResult *r) {
79 return dbfetchrow(r->handle);
80 }
81
82 static void dbapi2_adapter_result_clear(const DBAPIResult *r) {
83 if(!r)
84 return;
85
86 dbclear(r->handle);
87 }
88
89 static DBAPIResult *wrapresult(DBAPIResult *r, DBConn *c) {
90 if(!c)
91 return NULL;
92
93 if(!r)
94 r = calloc(1, sizeof(DBAPIResult));
95
96 r->clear = dbapi2_adapter_result_clear;
97 r->handle = dbgetresult(c);
98
99 if(!dbquerysuccessful(r->handle))
100 return r;
101
102 r->success = 1;
103 r->fields = dbnumfields(r->handle);
104
105 r->get = dbapi2_adapter_result_get;
106 r->next = dbapi2_adapter_result_next;
107
108 return r;
109 }
110
111 static void dbapi2_adapter_querywrapper(DBConn *c, void *data) {
112 struct DBAPI2AdapterQueryCallback *a = data;
113 DBAPIResult r;
114
115 a->callback(wrapresult(&r, c), a->data);
116
117 free(a);
118 }
119
120 static void sqquery(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, int flags, const char *query) {
121 struct DBAPI2AdapterQueryCallback *a;
122
123 if(cb) {
124 a = malloc(sizeof(struct DBAPI2AdapterQueryCallback));
125
126 a->db = db;
127 a->data = data;
128 a->callback = cb;
129 } else {
130 a = NULL;
131 }
132
133 dbasyncqueryf((int)(long)db->handle, cb?dbapi2_adapter_querywrapper:NULL, a, flags, "%s", query);
134 }
135
136 static void dbapi2_adapter_query(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, const char *query) {
137 sqquery(db, cb, data, 0, query);
138 }
139
140 static void dbapi2_adapter_createtable(const DBAPIConn *db, DBAPIQueryCallback cb, DBAPIUserData data, const char *query) {
141 sqquery(db, cb, data, DB_CREATE, query);
142 }
143
144 static void dbapi2_adapter_loadtablewrapper_init(DBConn *c, void *data) {
145 struct DBAPI2AdapterLoadTableCallback *a = data;
146
147 a->init(NULL, a->data);
148 }
149
150 static void dbapi2_adapter_loadtablewrapper_data(DBConn *c, void *data) {
151 struct DBAPI2AdapterLoadTableCallback *a = data;
152 DBAPIResult r;
153
154 a->callback(wrapresult(&r, c), a->data);
155 }
156
157 static void dbapi2_adapter_loadtablewrapper_fini(DBConn *c, void *data) {
158 struct DBAPI2AdapterLoadTableCallback *a = data;
159
160 if(a->fini)
161 a->fini(NULL, a->data);
162
163 free(a);
164 }
165
166 static void dbapi2_adapter_loadtable(const DBAPIConn *db, DBAPIQueryCallback init, DBAPIQueryCallback cb, DBAPIQueryCallback final, DBAPIUserData data, const char *table) {
167 struct DBAPI2AdapterLoadTableCallback *a = malloc(sizeof(struct DBAPI2AdapterLoadTableCallback));
168
169 a->db = db;
170 a->data = data;
171
172 a->init = init;
173 a->callback = cb;
174 a->fini = final;
175
176 dbloadtable_tag((char *)table, init?dbapi2_adapter_loadtablewrapper_init:NULL, cb?dbapi2_adapter_loadtablewrapper_data:NULL, dbapi2_adapter_loadtablewrapper_fini, a);
177 }
178
179 static void dbapi2_adapter_escapestring(const DBAPIConn *db, char *buf, const char *data, size_t len) {
180 dbescapestring(buf, (char *)data, len);
181 }
182
183 #ifndef DBAPI2_CUSTOM_QUOTESTRING
184 static int dbapi2_adapter_quotestring(const DBAPIConn *db, char *buf, size_t buflen, const char *data, size_t len) {
185 StringBuf b;
186 char xbuf[len * 2 + 5];
187 size_t esclen;
188
189 sbinit(&b, buf, buflen);
190 esclen = dbescapestring(xbuf, (char *)data, len);
191
192 sbaddchar(&b, '\'');
193 sbaddstrlen(&b, xbuf, esclen);
194 sbaddchar(&b, '\'');
195
196 if(!sbterminate(&b))
197 return 0;
198
199 return 1;
200 }
201 #endif
202
203 #ifndef DBAPI2_CUSTOM_TABLENAME
204 static char *dbapi2_adapter_tablename(const DBAPIConn *db, const char *tablename) {
205 static char buf[1024];
206
207 snprintf(buf, sizeof(buf), "%s.%s", db->name, tablename);
208
209 return buf;
210 }
211 #endif