Wed, 26 Nov 2008 10:46:42 +0000
Fixed missing return.
1 | 1 | #include "dbd_sqlite3.h" |
2 | ||
2 | 3 | /* |
4 | * Converts SQLite types to Lua types | |
5 | */ | |
1 | 6 | static lua_push_type_t sqlite_to_lua_push(unsigned int sqlite_type) { |
7 | lua_push_type_t lua_type; | |
8 | ||
9 | switch(sqlite_type) { | |
10 | case SQLITE_NULL: | |
11 | lua_type = LUA_PUSH_NIL; | |
12 | break; | |
13 | ||
14 | case SQLITE_INTEGER: | |
15 | lua_type = LUA_PUSH_INTEGER; | |
16 | break; | |
17 | ||
18 | case SQLITE_FLOAT: | |
19 | lua_type = LUA_PUSH_NUMBER; | |
20 | break; | |
21 | ||
22 | default: | |
23 | lua_type = LUA_PUSH_STRING; | |
24 | } | |
25 | ||
26 | return lua_type; | |
27 | } | |
28 | ||
2 | 29 | /* |
30 | * runs sqlite3_step on a statement handle | |
31 | */ | |
1 | 32 | static int step(statement_t *statement) { |
33 | int res = sqlite3_step(statement->stmt); | |
34 | ||
35 | if (res == SQLITE_DONE) { | |
36 | statement->more_data = 0; | |
37 | return 1; | |
38 | } else if (res == SQLITE_ROW) { | |
39 | statement->more_data = 1; | |
40 | return 1; | |
41 | } | |
42 | ||
43 | return 0; | |
44 | } | |
45 | ||
2 | 46 | /* |
47 | * success = statement:close() | |
48 | */ | |
3 | 49 | int statement_close(lua_State *L) { |
1 | 50 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_SQLITE_STATEMENT); |
51 | int ok = 0; | |
52 | ||
53 | if (statement->stmt) { | |
54 | if (sqlite3_finalize(statement->stmt) == SQLITE_OK) { | |
55 | ok = 1; | |
56 | } | |
3 | 57 | |
58 | statement->stmt = NULL; | |
1 | 59 | } |
60 | ||
61 | lua_pushboolean(L, ok); | |
62 | return 1; | |
63 | } | |
64 | ||
2 | 65 | /* |
3 | 66 | * success,err = statement:execute(...) |
2 | 67 | */ |
3 | 68 | int statement_execute(lua_State *L) { |
1 | 69 | int n = lua_gettop(L); |
70 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_SQLITE_STATEMENT); | |
71 | int p; | |
3 | 72 | int err = 0; |
73 | ||
74 | ||
75 | if (!statement->stmt) { | |
76 | lua_pushboolean(L, 0); | |
4 | 77 | lua_pushstring(L, DBI_ERR_EXECUTE_INVALID); |
3 | 78 | return 2; |
79 | } | |
1 | 80 | |
2 | 81 | /* |
82 | * reset the handle before binding params | |
83 | * this wil be a NOP if the handle has not | |
84 | * been executed | |
85 | */ | |
1 | 86 | if (sqlite3_reset(statement->stmt) != SQLITE_OK) { |
87 | lua_pushboolean(L, 0); | |
4 | 88 | lua_pushfstring(L, DBI_ERR_EXECUTE_FAILED, sqlite3_errmsg(statement->sqlite)); |
3 | 89 | return 2; |
1 | 90 | } |
91 | ||
92 | for (p = 2; p <= n; p++) { | |
93 | int i = p - 1; | |
94 | ||
95 | if (lua_isnil(L, p)) { | |
96 | if (sqlite3_bind_null(statement->stmt, i) != SQLITE_OK) { | |
3 | 97 | err = 1; |
1 | 98 | } |
99 | } else if (lua_isnumber(L, p)) { | |
100 | if (sqlite3_bind_double(statement->stmt, i, luaL_checknumber(L, p)) != SQLITE_OK) { | |
3 | 101 | err = 1; |
1 | 102 | } |
103 | } else if (lua_isstring(L, p)) { | |
104 | if (sqlite3_bind_text(statement->stmt, i, luaL_checkstring(L, p), -1, SQLITE_STATIC) != SQLITE_OK) { | |
3 | 105 | err = 1; |
1 | 106 | } |
107 | } | |
3 | 108 | |
109 | if (err) | |
110 | break; | |
1 | 111 | } |
112 | ||
4 | 113 | if (err) { |
3 | 114 | lua_pushboolean(L, 0); |
4 | 115 | lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, sqlite3_errmsg(statement->sqlite)); |
3 | 116 | return 2; |
117 | } | |
118 | ||
4 | 119 | if (!step(statement)) { |
120 | lua_pushboolean(L, 0); | |
121 | lua_pushfstring(L, DBI_ERR_EXECUTE_FAILED, sqlite3_errmsg(statement->sqlite)); | |
5 | 122 | return 2; |
4 | 123 | } |
124 | ||
3 | 125 | lua_pushboolean(L, 1); |
1 | 126 | return 1; |
127 | } | |
128 | ||
2 | 129 | /* |
130 | * must be called after an execute | |
131 | */ | |
1 | 132 | static int statement_fetch_impl(lua_State *L, int named_columns) { |
133 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_SQLITE_STATEMENT); | |
134 | int num_columns; | |
135 | ||
3 | 136 | if (!statement->stmt) { |
4 | 137 | luaL_error(L, DBI_ERR_FETCH_INVALID); |
3 | 138 | return 0; |
139 | } | |
140 | ||
1 | 141 | if (!statement->more_data) { |
2 | 142 | /* |
143 | * Result set is empty, or not result set returned | |
144 | */ | |
145 | ||
1 | 146 | lua_pushnil(L); |
147 | return 1; | |
148 | } | |
149 | ||
150 | num_columns = sqlite3_column_count(statement->stmt); | |
151 | ||
152 | if (num_columns) { | |
153 | int i; | |
154 | int d = 1; | |
155 | ||
156 | lua_newtable(L); | |
157 | ||
158 | for (i = 0; i < num_columns; i++) { | |
159 | lua_push_type_t lua_push = sqlite_to_lua_push(sqlite3_column_type(statement->stmt, i)); | |
160 | const char *name = sqlite3_column_name(statement->stmt, i); | |
161 | ||
162 | if (lua_push == LUA_PUSH_NIL) { | |
163 | if (named_columns) { | |
164 | LUA_PUSH_ATTRIB_NIL(name); | |
165 | } else { | |
166 | LUA_PUSH_ARRAY_NIL(d); | |
167 | } | |
168 | } else if (lua_push == LUA_PUSH_INTEGER) { | |
169 | int val = sqlite3_column_int(statement->stmt, i); | |
170 | ||
171 | if (named_columns) { | |
172 | LUA_PUSH_ATTRIB_INT(name, val); | |
173 | } else { | |
174 | LUA_PUSH_ARRAY_INT(d, val); | |
175 | } | |
176 | } else if (lua_push == LUA_PUSH_NUMBER) { | |
177 | double val = sqlite3_column_double(statement->stmt, i); | |
178 | ||
179 | if (named_columns) { | |
180 | LUA_PUSH_ATTRIB_FLOAT(name, val); | |
181 | } else { | |
182 | LUA_PUSH_ARRAY_FLOAT(d, val); | |
183 | } | |
184 | } else if (lua_push == LUA_PUSH_STRING) { | |
185 | const char *val = (const char *)sqlite3_column_text(statement->stmt, i); | |
186 | ||
187 | if (named_columns) { | |
188 | LUA_PUSH_ATTRIB_STRING(name, val); | |
189 | } else { | |
190 | LUA_PUSH_ARRAY_STRING(d, val); | |
191 | } | |
192 | } else if (lua_push == LUA_PUSH_BOOLEAN) { | |
193 | int val = sqlite3_column_int(statement->stmt, i); | |
194 | ||
195 | if (named_columns) { | |
196 | LUA_PUSH_ATTRIB_BOOL(name, val); | |
197 | } else { | |
198 | LUA_PUSH_ARRAY_BOOL(d, val); | |
199 | } | |
200 | } else { | |
4 | 201 | luaL_error(L, DBI_ERR_UNKNOWN_PUSH); |
1 | 202 | } |
203 | } | |
2 | 204 | } else { |
205 | /* | |
206 | * no columns returned by statement? | |
207 | */ | |
208 | lua_pushnil(L); | |
1 | 209 | } |
210 | ||
211 | if (step(statement) == 0) { | |
212 | if (sqlite3_reset(statement->stmt) != SQLITE_OK) { | |
2 | 213 | /* |
214 | * reset needs to be called to retrieve the 'real' error message | |
215 | */ | |
4 | 216 | luaL_error(L, DBI_ERR_FETCH_FAILED, sqlite3_errmsg(statement->sqlite)); |
1 | 217 | } |
218 | } | |
219 | ||
220 | return 1; | |
221 | } | |
222 | ||
2 | 223 | /* |
224 | * array = statement:fetch() | |
225 | */ | |
1 | 226 | static int statement_fetch(lua_State *L) { |
227 | return statement_fetch_impl(L, 0); | |
228 | } | |
229 | ||
2 | 230 | /* |
231 | * hashmap = statement:fetchtable() | |
232 | */ | |
1 | 233 | static int statement_fetchtable(lua_State *L) { |
234 | return statement_fetch_impl(L, 1); | |
235 | } | |
236 | ||
2 | 237 | /* |
238 | * __gc | |
239 | */ | |
1 | 240 | static int statement_gc(lua_State *L) { |
241 | /* always free the handle */ | |
242 | statement_close(L); | |
243 | ||
244 | return 0; | |
245 | } | |
246 | ||
247 | int dbd_sqlite3_statement_create(lua_State *L, connection_t *conn, const char *sql_query) { | |
248 | statement_t *statement = NULL; | |
249 | ||
250 | statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t)); | |
251 | statement->sqlite = conn->sqlite; | |
252 | statement->stmt = NULL; | |
253 | statement->more_data = 0; | |
254 | ||
255 | if (sqlite3_prepare_v2(statement->sqlite, sql_query, strlen(sql_query), &statement->stmt, NULL) != SQLITE_OK) { | |
256 | lua_pushnil(L); | |
4 | 257 | lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, sqlite3_errmsg(statement->sqlite)); |
3 | 258 | return 2; |
1 | 259 | } |
260 | ||
261 | luaL_getmetatable(L, DBD_SQLITE_STATEMENT); | |
262 | lua_setmetatable(L, -2); | |
263 | return 1; | |
264 | } | |
265 | ||
266 | int dbd_sqlite3_statement(lua_State *L) { | |
2 | 267 | static const luaL_Reg statement_methods[] = { |
268 | {"close", statement_close}, | |
269 | {"execute", statement_execute}, | |
270 | {"fetch", statement_fetch}, | |
271 | {"fetchtable", statement_fetchtable}, | |
272 | {NULL, NULL} | |
273 | }; | |
274 | ||
275 | static const luaL_Reg statement_class_methods[] = { | |
276 | {NULL, NULL} | |
277 | }; | |
278 | ||
1 | 279 | luaL_newmetatable(L, DBD_SQLITE_STATEMENT); |
280 | luaL_register(L, 0, statement_methods); | |
281 | lua_pushvalue(L,-1); | |
282 | lua_setfield(L, -2, "__index"); | |
283 | ||
284 | lua_pushcfunction(L, statement_gc); | |
285 | lua_setfield(L, -2, "__gc"); | |
286 | ||
287 | luaL_register(L, DBD_SQLITE_STATEMENT, statement_class_methods); | |
288 | ||
289 | return 1; | |
290 | } |