]> jfr.im git - irc/quakenet/newserv.git/blame - lua/luadb.c
Merge pull request #80 from quakenet/retropc-patch-3
[irc/quakenet/newserv.git] / lua / luadb.c
CommitLineData
55cee062
CP
1#include "lua.h"
2#include "luabot.h"
d7839cef 3
dad344a7 4#include "../dbapi2/dbapi2.h"
d7839cef 5
dad344a7
CP
6typedef struct lua_callback {
7 lua_list *l;
8 long handler, args;
9} lua_callback;
55cee062 10
7697f3b1
CP
11static DBAPIConn *lua_getdb_l(lua_list *l) {
12 if(!l->db.attempted_load) {
13 char buf[512];
14 l->db.attempted_load = 1;
15 snprintf(buf, sizeof(buf), "lua_%s", l->name->content);
16
17 for(char *p=buf;*p;p++) {
18 char c = *p;
19 if(
20 (c >= 'A' && c <= 'Z') ||
21 (c >= 'a' && c <= 'z') ||
22 (c >= '0' && c <= '9') ||
23 (c == '_')
24 )
25 continue;
26
27 Error("lua", ERR_ERROR, "Can't load database due to illegal name: %s (only A-Za-z0-9_ permitted)", buf);
28 return NULL;
29 }
30
31 l->db.db = dbapi2open(NULL, buf);
32 }
33
34 return l->db.db;
35}
36
37static DBAPIConn *lua_getdb(lua_State *ps) {
38 return lua_getdb_l(lua_listfromstate(ps));
39}
40
55cee062
CP
41static int lua_dbcreatequery(lua_State *ps) {
42 char *s = (char *)lua_tostring(ps, 1);
43
7697f3b1 44 DBAPIConn *luadb = lua_getdb(ps);
dad344a7
CP
45 if(!luadb)
46 LUA_RETURN(ps, LUA_FAIL);
47
55cee062
CP
48 if(!s)
49 LUA_RETURN(ps, LUA_FAIL);
50
dad344a7 51 luadb->unsafecreatetable(luadb, NULL, NULL, "%s", s);
55cee062
CP
52 LUA_RETURN(ps, LUA_OK);
53}
54
dad344a7
CP
55static int lua_dbtablename(lua_State *ps) {
56 char *s = (char *)lua_tostring(ps, 1);
57
7697f3b1 58 DBAPIConn *luadb = lua_getdb(ps);
dad344a7 59 if(!luadb)
55cee062
CP
60 LUA_RETURN(ps, LUA_FAIL);
61
dad344a7
CP
62 if(!s)
63 LUA_RETURN(ps, LUA_FAIL);
64
65 char *tablename = luadb->tablename(luadb, s);
66 if(!tablename)
67 LUA_RETURN(ps, LUA_FAIL);
68
69 lua_pushstring(ps, tablename);
70 return 1;
55cee062 71}
55cee062 72
dad344a7
CP
73const static DBAPIResult *active_result;
74static void lua_dbcallback(const DBAPIResult *result, void *tag) {
75 lua_callback *c = (lua_callback *)tag;
76
77 if(!lua_listexists(c->l)) {
78 luafree(c);
79 return;
80 }
81
82 active_result = result;
83 _lua_vpcall(c->l->l, (void *)c->handler, LUA_POINTERMODE, "bR", result && result->success ? 1 : 0, c->args);
84 active_result = NULL;
55cee062 85
dad344a7
CP
86 if(result)
87 result->clear(result);
88
89 luaL_unref(c->l->l, LUA_REGISTRYINDEX, c->handler);
90 luaL_unref(c->l->l, LUA_REGISTRYINDEX, c->args);
91 luafree(c);
92}
55cee062
CP
93
94static int lua_dbnumfields(lua_State *ps) {
dad344a7
CP
95 if(!active_result)
96 return 0;
55cee062 97
dad344a7 98 lua_pushint(ps, active_result->fields);
55cee062
CP
99 return 1;
100}
101
dad344a7 102static int lua_dbgetvalue(lua_State *ps) {
dad344a7
CP
103 if(!active_result)
104 return 0;
55cee062 105
ee8cd7d0 106 if(!lua_isint(ps, 1))
55cee062
CP
107 return 0;
108
dad344a7
CP
109 int field = lua_toint(ps, 1);
110 if(field < 0 || field >= active_result->fields)
111 return 0;
112
113 char *value = active_result->get(active_result, field);
114 /* bit rubbish, no way to get the length... binary data is out then */
115 lua_pushstring(ps, value);
55cee062
CP
116
117 return 1;
118}
55cee062 119
dad344a7 120static int lua_dbnextrow(lua_State *ps) {
dad344a7
CP
121 if(!active_result)
122 return 0;
55cee062 123
dad344a7
CP
124 int r = active_result->next(active_result);
125 lua_pushboolean(ps, r?1:0);
126 return 1;
55cee062
CP
127}
128
129static int lua_dbquery(lua_State *ps) {
130 lua_list *l = lua_listfromstate(ps);
131 char *q = (char *)lua_tostring(ps, 1);
132 lua_callback *cb;
7697f3b1 133 DBAPIConn *luadb = lua_getdb_l(l);
55cee062 134
dad344a7
CP
135 if(!luadb)
136 LUA_RETURN(ps, LUA_FAIL);
137
55cee062
CP
138 /* what happens if 3 isn't there? */
139 if(!l || !q)
140 LUA_RETURN(ps, LUA_FAIL);
141
142 if(!lua_isfunction(ps, 2)) {
dad344a7 143 luadb->unsafesquery(luadb, "%s", q);
55cee062
CP
144 LUA_RETURN(ps, LUA_OK);
145 }
146
d0e17ef9 147 cb = (lua_callback *)luamalloc(sizeof(lua_callback));
55cee062
CP
148 if(!cb)
149 LUA_RETURN(ps, LUA_FAIL);
150
151 cb->l = l;
152 cb->args = luaL_ref(ps, LUA_REGISTRYINDEX);
153 cb->handler = luaL_ref(ps, LUA_REGISTRYINDEX);
154
dad344a7 155 luadb->unsafequery(luadb, lua_dbcallback, cb, "%s", q);
55cee062
CP
156
157 LUA_RETURN(ps, LUA_OK);
158}
159
160static int lua_dbescape(lua_State *ps) {
ee8cd7d0 161 char ebuf[8192 * 2 + 1];
55cee062
CP
162 char *s = (char *)lua_tostring(ps, 1);
163 int len;
55cee062 164
7697f3b1 165 DBAPIConn *luadb = lua_getdb(ps);
dad344a7
CP
166 if(!luadb)
167 return 0;
168
55cee062
CP
169 if(!s)
170 return 0;
171
172 len = lua_strlen(ps, 1);
173 if(len > sizeof(ebuf) / 2 - 5)
174 return 0;
175
dad344a7 176 luadb->escapestring(luadb, ebuf, s, len);
ee8cd7d0 177 lua_pushstring(ps, ebuf);
55cee062
CP
178
179 return 1;
180}
181
7697f3b1
CP
182void lua_registerdbcommands(lua_list *n) {
183 lua_State *l = n->l;
184
dad344a7 185 lua_register(l, "db_tablename", lua_dbtablename);
55cee062 186
dad344a7 187 lua_register(l, "db_createquery", lua_dbcreatequery);
55cee062
CP
188 lua_register(l, "db_query", lua_dbquery);
189 lua_register(l, "db_escape", lua_dbescape);
dad344a7 190
55cee062 191 lua_register(l, "db_numfields", lua_dbnumfields);
dad344a7
CP
192 lua_register(l, "db_getvalue", lua_dbgetvalue);
193 lua_register(l, "db_nextrow", lua_dbnextrow);
d7839cef 194
7697f3b1
CP
195 /* lazy open */
196 n->db.attempted_load = 0;
197 n->db.db = NULL;
d7839cef 198
dad344a7 199 /* TODO */
dad344a7
CP
200 /* parameterised queries (huge pain due to no va_args in dbapi2) */
201 /* loadtable */
202 /* getrow */
d7839cef
CP
203}
204
7697f3b1
CP
205void lua_destroydb(lua_list *n) {
206 if(!n->db.db)
207 return;
208
209 DBAPIConn *db = n->db.db;
210 db->close(db);
211 n->db.db = NULL;
212 n->db.attempted_load = 0;
dad344a7 213}