]> jfr.im git - irc/quakenet/newserv.git/blob - lua/luadb.c
LUA: port luadb to dbapi2 to drop postgres dependency
[irc/quakenet/newserv.git] / lua / luadb.c
1 #include "lua.h"
2 #include "luabot.h"
3
4 #include "../dbapi2/dbapi2.h"
5
6 static DBAPIConn *luadb;
7
8 typedef struct lua_callback {
9 lua_list *l;
10 long handler, args;
11 } lua_callback;
12
13 static int lua_dbcreatequery(lua_State *ps) {
14 char *s = (char *)lua_tostring(ps, 1);
15
16 if(!luadb)
17 LUA_RETURN(ps, LUA_FAIL);
18
19 if(!s)
20 LUA_RETURN(ps, LUA_FAIL);
21
22 luadb->unsafecreatetable(luadb, NULL, NULL, "%s", s);
23 LUA_RETURN(ps, LUA_OK);
24 }
25
26 static int lua_dbtablename(lua_State *ps) {
27 char *s = (char *)lua_tostring(ps, 1);
28
29 if(!luadb)
30 LUA_RETURN(ps, LUA_FAIL);
31
32 if(!s)
33 LUA_RETURN(ps, LUA_FAIL);
34
35 char *tablename = luadb->tablename(luadb, s);
36 if(!tablename)
37 LUA_RETURN(ps, LUA_FAIL);
38
39 lua_pushstring(ps, tablename);
40 return 1;
41 }
42
43 const static DBAPIResult *active_result;
44 static void lua_dbcallback(const DBAPIResult *result, void *tag) {
45 lua_callback *c = (lua_callback *)tag;
46
47 if(!lua_listexists(c->l)) {
48 luafree(c);
49 return;
50 }
51
52 active_result = result;
53 _lua_vpcall(c->l->l, (void *)c->handler, LUA_POINTERMODE, "bR", result && result->success ? 1 : 0, c->args);
54 active_result = NULL;
55
56 if(result)
57 result->clear(result);
58
59 luaL_unref(c->l->l, LUA_REGISTRYINDEX, c->handler);
60 luaL_unref(c->l->l, LUA_REGISTRYINDEX, c->args);
61 luafree(c);
62 }
63
64 static int lua_dbnumfields(lua_State *ps) {
65 if(!luadb)
66 return 0;
67
68 if(!active_result)
69 return 0;
70
71 lua_pushint(ps, active_result->fields);
72 return 1;
73 }
74
75 static int lua_dbgetvalue(lua_State *ps) {
76 if(!luadb)
77 return 0;
78
79 if(!active_result)
80 return 0;
81
82 if(!lua_isint(ps, 1))
83 return 0;
84
85 int field = lua_toint(ps, 1);
86 if(field < 0 || field >= active_result->fields)
87 return 0;
88
89 char *value = active_result->get(active_result, field);
90 /* bit rubbish, no way to get the length... binary data is out then */
91 lua_pushstring(ps, value);
92
93 return 1;
94 }
95
96 static int lua_dbnextrow(lua_State *ps) {
97 if(!luadb)
98 return 0;
99
100 if(!active_result)
101 return 0;
102
103 int r = active_result->next(active_result);
104 lua_pushboolean(ps, r?1:0);
105 return 1;
106 }
107
108 static int lua_dbquery(lua_State *ps) {
109 lua_list *l = lua_listfromstate(ps);
110 char *q = (char *)lua_tostring(ps, 1);
111 lua_callback *cb;
112
113 if(!luadb)
114 LUA_RETURN(ps, LUA_FAIL);
115
116 /* what happens if 3 isn't there? */
117 if(!l || !q)
118 LUA_RETURN(ps, LUA_FAIL);
119
120 if(!lua_isfunction(ps, 2)) {
121 luadb->unsafesquery(luadb, "%s", q);
122 LUA_RETURN(ps, LUA_OK);
123 }
124
125 cb = (lua_callback *)luamalloc(sizeof(lua_callback));
126 if(!cb)
127 LUA_RETURN(ps, LUA_FAIL);
128
129 cb->l = l;
130 cb->args = luaL_ref(ps, LUA_REGISTRYINDEX);
131 cb->handler = luaL_ref(ps, LUA_REGISTRYINDEX);
132
133 luadb->unsafequery(luadb, lua_dbcallback, cb, "%s", q);
134
135 LUA_RETURN(ps, LUA_OK);
136 }
137
138 static int lua_dbescape(lua_State *ps) {
139 char ebuf[8192 * 2 + 1];
140 char *s = (char *)lua_tostring(ps, 1);
141 int len;
142
143 if(!luadb)
144 return 0;
145
146 if(!s)
147 return 0;
148
149 len = lua_strlen(ps, 1);
150 if(len > sizeof(ebuf) / 2 - 5)
151 return 0;
152
153 luadb->escapestring(luadb, ebuf, s, len);
154 lua_pushstring(ps, ebuf);
155
156 return 1;
157 }
158
159 void lua_registerdbcommands(lua_State *l) {
160 lua_register(l, "db_tablename", lua_dbtablename);
161
162 lua_register(l, "db_createquery", lua_dbcreatequery);
163 lua_register(l, "db_query", lua_dbquery);
164 lua_register(l, "db_escape", lua_dbescape);
165
166 lua_register(l, "db_numfields", lua_dbnumfields);
167 lua_register(l, "db_getvalue", lua_dbgetvalue);
168 lua_register(l, "db_nextrow", lua_dbnextrow);
169
170 luadb = dbapi2open(NULL, "lua");
171
172 /* TODO */
173 /* open gets you a unique db */
174 /* parameterised queries (huge pain due to no va_args in dbapi2) */
175 /* loadtable */
176 /* getrow */
177 }
178
179 void lua_destroydb(void) {
180 if(luadb)
181 luadb->close(luadb);
182 }