Fri, 18 Sep 2009 12:40:53 +0000
* Fix MySQL date/time types
* Add VC++ build projects
* Misc fixes for Windows DLL building
1 | 1 | #include "dbd_mysql.h" |
2 | ||
3 | static lua_push_type_t mysql_to_lua_push(unsigned int mysql_type) { | |
4 | lua_push_type_t lua_type; | |
5 | ||
6 | switch(mysql_type) { | |
7 | case MYSQL_TYPE_NULL: | |
8 | lua_type = LUA_PUSH_NIL; | |
9 | break; | |
10 | ||
11 | case MYSQL_TYPE_TINY: | |
33 | 12 | case MYSQL_TYPE_YEAR: |
1 | 13 | case MYSQL_TYPE_SHORT: |
14 | case MYSQL_TYPE_LONG: | |
15 | lua_type = LUA_PUSH_INTEGER; | |
16 | break; | |
17 | ||
18 | case MYSQL_TYPE_DOUBLE: | |
19 | case MYSQL_TYPE_LONGLONG: | |
20 | lua_type = LUA_PUSH_NUMBER; | |
21 | break; | |
22 | ||
23 | default: | |
24 | lua_type = LUA_PUSH_STRING; | |
25 | } | |
26 | ||
27 | return lua_type; | |
28 | } | |
29 | ||
33 | 30 | static size_t mysql_buffer_size(MYSQL_FIELD *field) { |
31 | unsigned int mysql_type = field->type; | |
32 | size_t size = 0; | |
33 | ||
34 | switch (mysql_type) { | |
35 | case MYSQL_TYPE_TINY: | |
36 | size = 4; | |
37 | break; | |
38 | case MYSQL_TYPE_YEAR: | |
39 | case MYSQL_TYPE_SHORT: | |
40 | size = 4; | |
41 | break; | |
42 | case MYSQL_TYPE_INT24: | |
43 | size = 4; | |
44 | break; | |
45 | case MYSQL_TYPE_LONG: | |
46 | size = 4; | |
47 | break; | |
48 | case MYSQL_TYPE_LONGLONG: | |
49 | size = 8; | |
50 | break; | |
51 | case MYSQL_TYPE_FLOAT: | |
52 | size = 4; | |
53 | break; | |
54 | case MYSQL_TYPE_DOUBLE: | |
55 | size = 8; | |
56 | break; | |
57 | case MYSQL_TYPE_TIME: | |
58 | case MYSQL_TYPE_DATE: | |
59 | case MYSQL_TYPE_DATETIME: | |
60 | case MYSQL_TYPE_TIMESTAMP: | |
61 | size = sizeof(MYSQL_TIME); | |
62 | break; | |
63 | default: | |
64 | size = field->length; | |
65 | } | |
66 | ||
67 | return size; | |
68 | } | |
69 | ||
2 | 70 | /* |
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
71 | * num_affected_rows = statement:affected() |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
72 | */ |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
73 | static int statement_affected(lua_State *L) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
74 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
75 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
76 | if (!statement->stmt) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
77 | luaL_error(L, DBI_ERR_INVALID_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
78 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
79 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
80 | lua_pushinteger(L, mysql_stmt_affected_rows(statement->stmt)); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
81 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
82 | return 1; |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
83 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
84 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
85 | /* |
2 | 86 | * success = statement:close() |
87 | */ | |
1 | 88 | static int statement_close(lua_State *L) { |
89 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT); | |
90 | ||
91 | if (statement->metadata) { | |
92 | mysql_free_result(statement->metadata); | |
3 | 93 | statement->metadata = NULL; |
1 | 94 | } |
95 | ||
96 | if (statement->stmt) { | |
3 | 97 | mysql_stmt_close(statement->stmt); |
98 | statement->stmt = NULL; | |
1 | 99 | } |
100 | ||
3 | 101 | lua_pushboolean(L, 1); |
1 | 102 | return 1; |
103 | } | |
104 | ||
2 | 105 | /* |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
106 | * column_names = statement:columns() |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
107 | */ |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
108 | static int statement_columns(lua_State *L) { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
109 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
110 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
111 | MYSQL_FIELD *fields; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
112 | int i; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
113 | int num_columns; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
114 | int d = 1; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
115 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
116 | if (!statement->stmt) { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
117 | luaL_error(L, DBI_ERR_INVALID_STATEMENT); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
118 | return 0; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
119 | } |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
120 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
121 | fields = mysql_fetch_fields(statement->metadata); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
122 | num_columns = mysql_num_fields(statement->metadata); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
123 | lua_newtable(L); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
124 | for (i = 0; i < num_columns; i++) { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
125 | const char *name = fields[i].name; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
126 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
127 | LUA_PUSH_ARRAY_STRING(d, name); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
128 | } |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
129 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
130 | return 1; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
131 | } |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
132 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
133 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
134 | /* |
3 | 135 | * success,err = statement:execute(...) |
2 | 136 | */ |
1 | 137 | static int statement_execute(lua_State *L) { |
138 | int n = lua_gettop(L); | |
139 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT); | |
140 | int num_bind_params = n - 1; | |
3 | 141 | int expected_params; |
14 | 142 | |
25 | 143 | unsigned char *buffer = NULL; |
14 | 144 | int offset = 0; |
1 | 145 | |
146 | MYSQL_BIND *bind = NULL; | |
147 | MYSQL_RES *metadata = NULL; | |
148 | ||
149 | char *error_message = NULL; | |
10 | 150 | char *errstr = NULL; |
1 | 151 | |
152 | int p; | |
153 | ||
3 | 154 | if (!statement->stmt) { |
155 | lua_pushboolean(L, 0); | |
4 | 156 | lua_pushstring(L, DBI_ERR_EXECUTE_INVALID); |
3 | 157 | return 2; |
158 | } | |
159 | ||
160 | expected_params = mysql_stmt_param_count(statement->stmt); | |
161 | ||
162 | if (expected_params != num_bind_params) { | |
163 | /* | |
10 | 164 | * mysql_stmt_bind_param does not handle this condition, |
3 | 165 | * and the client library will segfault if these do no match |
166 | */ | |
167 | lua_pushboolean(L, 0); | |
4 | 168 | lua_pushfstring(L, DBI_ERR_PARAM_MISCOUNT, expected_params, num_bind_params); |
3 | 169 | return 2; |
170 | } | |
171 | ||
26 | 172 | if (num_bind_params > 0) { |
25 | 173 | bind = malloc(sizeof(MYSQL_BIND) * num_bind_params); |
174 | if (bind == NULL) { | |
175 | luaL_error(L, "Could not alloc bind params\n"); | |
176 | } | |
177 | ||
26 | 178 | buffer = (unsigned char *)malloc(num_bind_params * sizeof(double)); |
25 | 179 | memset(bind, 0, sizeof(MYSQL_BIND) * num_bind_params); |
23
a4825c3e65e9
Bugfix: memory corruption possible after reallocs. Using a static buffer instead. Will need to check for overflows on static buffer.
nrich@ii.net
parents:
21
diff
changeset
|
180 | } |
a4825c3e65e9
Bugfix: memory corruption possible after reallocs. Using a static buffer instead. Will need to check for overflows on static buffer.
nrich@ii.net
parents:
21
diff
changeset
|
181 | |
1 | 182 | for (p = 2; p <= n; p++) { |
183 | int type = lua_type(L, p); | |
184 | int i = p - 2; | |
185 | ||
186 | const char *str = NULL; | |
7
4480ae002881
Bugfix - the size of strings for bind params pointed to the same memory
nrich@ii.net
parents:
6
diff
changeset
|
187 | size_t *str_len = NULL; |
6
22046b996150
Fixed bug: double bind params were using the same variables memory space so they were all being set to the same number.
nrich@ii.net
parents:
4
diff
changeset
|
188 | double *num = NULL; |
9 | 189 | int *boolean = NULL; |
10 | 190 | char err[64]; |
1 | 191 | |
192 | switch(type) { | |
193 | case LUA_TNIL: | |
194 | bind[i].buffer_type = MYSQL_TYPE_NULL; | |
195 | bind[i].is_null = (my_bool*)1; | |
196 | break; | |
197 | ||
9 | 198 | case LUA_TBOOLEAN: |
26 | 199 | boolean = (int *)(buffer + offset); |
14 | 200 | offset += sizeof(int); |
9 | 201 | *boolean = lua_toboolean(L, p); |
14 | 202 | |
9 | 203 | bind[i].buffer_type = MYSQL_TYPE_LONG; |
204 | bind[i].is_null = (my_bool*)0; | |
205 | bind[i].buffer = (char *)boolean; | |
206 | bind[i].length = 0; | |
207 | break; | |
208 | ||
1 | 209 | case LUA_TNUMBER: |
6
22046b996150
Fixed bug: double bind params were using the same variables memory space so they were all being set to the same number.
nrich@ii.net
parents:
4
diff
changeset
|
210 | /* |
22046b996150
Fixed bug: double bind params were using the same variables memory space so they were all being set to the same number.
nrich@ii.net
parents:
4
diff
changeset
|
211 | * num needs to be it's own |
22046b996150
Fixed bug: double bind params were using the same variables memory space so they were all being set to the same number.
nrich@ii.net
parents:
4
diff
changeset
|
212 | * memory here |
22046b996150
Fixed bug: double bind params were using the same variables memory space so they were all being set to the same number.
nrich@ii.net
parents:
4
diff
changeset
|
213 | */ |
26 | 214 | num = (double *)(buffer + offset); |
14 | 215 | offset += sizeof(double); |
9 | 216 | *num = lua_tonumber(L, p); |
1 | 217 | |
218 | bind[i].buffer_type = MYSQL_TYPE_DOUBLE; | |
219 | bind[i].is_null = (my_bool*)0; | |
6
22046b996150
Fixed bug: double bind params were using the same variables memory space so they were all being set to the same number.
nrich@ii.net
parents:
4
diff
changeset
|
220 | bind[i].buffer = (char *)num; |
1 | 221 | bind[i].length = 0; |
222 | break; | |
223 | ||
224 | case LUA_TSTRING: | |
26 | 225 | str_len = (size_t *)(buffer + offset); |
14 | 226 | offset += sizeof(size_t); |
9 | 227 | str = lua_tolstring(L, p, str_len); |
1 | 228 | |
229 | bind[i].buffer_type = MYSQL_TYPE_STRING; | |
230 | bind[i].is_null = (my_bool*)0; | |
231 | bind[i].buffer = (char *)str; | |
7
4480ae002881
Bugfix - the size of strings for bind params pointed to the same memory
nrich@ii.net
parents:
6
diff
changeset
|
232 | bind[i].length = str_len; |
1 | 233 | break; |
234 | ||
235 | default: | |
10 | 236 | snprintf(err, sizeof(err)-1, DBI_ERR_BINDING_TYPE_ERR, lua_typename(L, type)); |
237 | errstr = err; | |
238 | error_message = DBI_ERR_BINDING_PARAMS; | |
1 | 239 | goto cleanup; |
240 | } | |
241 | } | |
242 | ||
243 | if (mysql_stmt_bind_param(statement->stmt, bind)) { | |
4 | 244 | error_message = DBI_ERR_BINDING_PARAMS; |
1 | 245 | goto cleanup; |
246 | } | |
247 | ||
248 | if (mysql_stmt_execute(statement->stmt)) { | |
4 | 249 | error_message = DBI_ERR_BINDING_EXEC; |
1 | 250 | goto cleanup; |
251 | } | |
252 | ||
253 | metadata = mysql_stmt_result_metadata(statement->stmt); | |
254 | ||
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
255 | if (metadata) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
256 | mysql_stmt_store_result(statement->stmt); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
257 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
258 | |
1 | 259 | cleanup: |
23
a4825c3e65e9
Bugfix: memory corruption possible after reallocs. Using a static buffer instead. Will need to check for overflows on static buffer.
nrich@ii.net
parents:
21
diff
changeset
|
260 | if (bind) { |
1 | 261 | free(bind); |
23
a4825c3e65e9
Bugfix: memory corruption possible after reallocs. Using a static buffer instead. Will need to check for overflows on static buffer.
nrich@ii.net
parents:
21
diff
changeset
|
262 | } |
1 | 263 | |
25 | 264 | if (buffer) { |
265 | free(buffer); | |
266 | } | |
267 | ||
1 | 268 | if (error_message) { |
3 | 269 | lua_pushboolean(L, 0); |
10 | 270 | lua_pushfstring(L, error_message, errstr ? errstr : mysql_stmt_error(statement->stmt)); |
3 | 271 | return 2; |
1 | 272 | } |
273 | ||
274 | statement->metadata = metadata; | |
275 | ||
3 | 276 | lua_pushboolean(L, 1); |
1 | 277 | return 1; |
278 | } | |
279 | ||
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
280 | static int statement_fetch_impl(lua_State *L, statement_t *statement, int named_columns) { |
1 | 281 | int column_count; |
282 | MYSQL_BIND *bind = NULL; | |
283 | const char *error_message = NULL; | |
284 | ||
285 | if (!statement->stmt) { | |
4 | 286 | luaL_error(L, DBI_ERR_FETCH_INVALID); |
3 | 287 | return 0; |
288 | } | |
289 | ||
290 | if (!statement->metadata) { | |
4 | 291 | luaL_error(L, DBI_ERR_FETCH_NO_EXECUTE); |
3 | 292 | return 0; |
1 | 293 | } |
294 | ||
295 | column_count = mysql_num_fields(statement->metadata); | |
296 | ||
297 | if (column_count > 0) { | |
298 | int i; | |
299 | MYSQL_FIELD *fields; | |
300 | ||
301 | bind = malloc(sizeof(MYSQL_BIND) * column_count); | |
302 | memset(bind, 0, sizeof(MYSQL_BIND) * column_count); | |
303 | ||
304 | fields = mysql_fetch_fields(statement->metadata); | |
305 | ||
306 | for (i = 0; i < column_count; i++) { | |
33 | 307 | unsigned int length = mysql_buffer_size(&fields[i]); |
1 | 308 | char *buffer = (char *)malloc(length); |
309 | memset(buffer, 0, length); | |
310 | ||
311 | bind[i].buffer_type = fields[i].type; | |
312 | bind[i].buffer = buffer; | |
313 | bind[i].buffer_length = length; | |
314 | } | |
315 | ||
316 | if (mysql_stmt_bind_result(statement->stmt, bind)) { | |
4 | 317 | error_message = DBI_ERR_BINDING_RESULTS; |
1 | 318 | goto cleanup; |
319 | } | |
320 | ||
321 | if (!mysql_stmt_fetch(statement->stmt)) { | |
322 | int d = 1; | |
323 | ||
324 | lua_newtable(L); | |
325 | for (i = 0; i < column_count; i++) { | |
326 | lua_push_type_t lua_push = mysql_to_lua_push(fields[i].type); | |
327 | const char *name = fields[i].name; | |
328 | ||
329 | if (lua_push == LUA_PUSH_NIL) { | |
330 | if (named_columns) { | |
331 | LUA_PUSH_ATTRIB_NIL(name); | |
332 | } else { | |
333 | LUA_PUSH_ARRAY_NIL(d); | |
334 | } | |
335 | } else if (lua_push == LUA_PUSH_INTEGER) { | |
336 | if (named_columns) { | |
337 | LUA_PUSH_ATTRIB_INT(name, *(int *)(bind[i].buffer)); | |
338 | } else { | |
339 | LUA_PUSH_ARRAY_INT(d, *(int *)(bind[i].buffer)); | |
340 | } | |
341 | } else if (lua_push == LUA_PUSH_NUMBER) { | |
342 | if (named_columns) { | |
343 | LUA_PUSH_ATTRIB_FLOAT(name, *(double *)(bind[i].buffer)); | |
344 | } else { | |
345 | LUA_PUSH_ARRAY_FLOAT(d, *(double *)(bind[i].buffer)); | |
346 | } | |
347 | } else if (lua_push == LUA_PUSH_STRING) { | |
33 | 348 | |
349 | if (fields[i].type == MYSQL_TYPE_TIMESTAMP || fields[i].type == MYSQL_TYPE_DATETIME) { | |
350 | char str[20]; | |
351 | struct st_mysql_time *t = bind[i].buffer; | |
352 | ||
353 | snprintf(str, 20, "%d-%02d-%02d %02d:%02d:%02d", t->year, t->month, t->day, t->hour, t->minute, t->second); | |
354 | ||
355 | if (named_columns) { | |
356 | LUA_PUSH_ATTRIB_STRING(name, str); | |
357 | } else { | |
358 | LUA_PUSH_ARRAY_STRING(d, str); | |
359 | } | |
360 | } else if (fields[i].type == MYSQL_TYPE_TIME) { | |
361 | char str[9]; | |
362 | struct st_mysql_time *t = bind[i].buffer; | |
363 | ||
364 | snprintf(str, 9, "%02d:%02d:%02d", t->hour, t->minute, t->second); | |
365 | ||
366 | if (named_columns) { | |
367 | LUA_PUSH_ATTRIB_STRING(name, str); | |
368 | } else { | |
369 | LUA_PUSH_ARRAY_STRING(d, str); | |
370 | } | |
371 | } else if (fields[i].type == MYSQL_TYPE_DATE) { | |
372 | char str[20]; | |
373 | struct st_mysql_time *t = bind[i].buffer; | |
374 | ||
375 | snprintf(str, 11, "%d-%02d-%02d", t->year, t->month, t->day); | |
376 | ||
377 | if (named_columns) { | |
378 | LUA_PUSH_ATTRIB_STRING(name, str); | |
379 | } else { | |
380 | LUA_PUSH_ARRAY_STRING(d, str); | |
381 | } | |
382 | ||
1 | 383 | } else { |
33 | 384 | if (named_columns) { |
385 | LUA_PUSH_ATTRIB_STRING(name, bind[i].buffer); | |
386 | } else { | |
387 | LUA_PUSH_ARRAY_STRING(d, bind[i].buffer); | |
388 | } | |
1 | 389 | } |
390 | } else if (lua_push == LUA_PUSH_BOOLEAN) { | |
391 | if (named_columns) { | |
392 | LUA_PUSH_ATTRIB_BOOL(name, *(int *)(bind[i].buffer)); | |
393 | } else { | |
394 | LUA_PUSH_ARRAY_BOOL(d, *(int *)(bind[i].buffer)); | |
395 | } | |
396 | } else { | |
4 | 397 | luaL_error(L, DBI_ERR_UNKNOWN_PUSH); |
1 | 398 | } |
399 | } | |
400 | } else { | |
401 | lua_pushnil(L); | |
402 | } | |
403 | } | |
404 | ||
405 | cleanup: | |
406 | if (bind) { | |
407 | int i; | |
408 | ||
409 | for (i = 0; i < column_count; i++) { | |
410 | free(bind[i].buffer); | |
411 | } | |
412 | ||
413 | free(bind); | |
414 | } | |
415 | ||
416 | if (error_message) { | |
417 | luaL_error(L, error_message, mysql_stmt_error(statement->stmt)); | |
418 | return 0; | |
419 | } | |
420 | ||
421 | return 1; | |
422 | } | |
423 | ||
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
424 | static int next_iterator(lua_State *L) { |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
425 | statement_t *statement = (statement_t *)luaL_checkudata(L, lua_upvalueindex(1), DBD_MYSQL_STATEMENT); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
426 | int named_columns = lua_toboolean(L, lua_upvalueindex(2)); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
427 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
428 | return statement_fetch_impl(L, statement, named_columns); |
1 | 429 | } |
430 | ||
2 | 431 | /* |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
432 | * table = statement:fetch(named_indexes) |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
433 | */ |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
434 | static int statement_fetch(lua_State *L) { |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
435 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT); |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
436 | int named_columns = lua_toboolean(L, 2); |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
437 | |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
438 | return statement_fetch_impl(L, statement, named_columns); |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
439 | } |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
440 | |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
441 | /* |
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
442 | * num_rows = statement:rowcount() |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
443 | */ |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
444 | static int statement_rowcount(lua_State *L) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
445 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
446 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
447 | if (!statement->stmt) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
448 | luaL_error(L, DBI_ERR_INVALID_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
449 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
450 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
451 | lua_pushinteger(L, mysql_stmt_num_rows(statement->stmt)); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
452 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
453 | return 1; |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
454 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
455 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
456 | /* |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
457 | * iterfunc = statement:rows(named_indexes) |
2 | 458 | */ |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
459 | static int statement_rows(lua_State *L) { |
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
460 | if (lua_gettop(L) == 1) { |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
461 | lua_pushvalue(L, 1); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
462 | lua_pushboolean(L, 0); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
463 | } else { |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
464 | lua_pushvalue(L, 1); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
465 | lua_pushboolean(L, lua_toboolean(L, 2)); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
466 | } |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
467 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
468 | lua_pushcclosure(L, next_iterator, 2); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
469 | return 1; |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
470 | } |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
471 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
472 | /* |
2 | 473 | * __gc |
474 | */ | |
1 | 475 | static int statement_gc(lua_State *L) { |
476 | /* always free the handle */ | |
477 | statement_close(L); | |
478 | ||
479 | return 0; | |
480 | } | |
481 | ||
32
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
482 | /* |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
483 | * __tostring |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
484 | */ |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
485 | static int statement_tostring(lua_State *L) { |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
486 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_MYSQL_STATEMENT); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
487 | |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
488 | lua_pushfstring(L, "%s: %p", DBD_MYSQL_STATEMENT, statement); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
489 | |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
490 | return 1; |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
491 | } |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
492 | |
1 | 493 | int dbd_mysql_statement_create(lua_State *L, connection_t *conn, const char *sql_query) { |
494 | unsigned long sql_len = strlen(sql_query); | |
495 | ||
496 | statement_t *statement = NULL; | |
497 | ||
498 | MYSQL_STMT *stmt = mysql_stmt_init(conn->mysql); | |
499 | ||
500 | if (!stmt) { | |
3 | 501 | lua_pushnil(L); |
4 | 502 | lua_pushfstring(L, DBI_ERR_ALLOC_STATEMENT, mysql_error(conn->mysql)); |
3 | 503 | return 2; |
1 | 504 | } |
505 | ||
506 | if (mysql_stmt_prepare(stmt, sql_query, sql_len)) { | |
3 | 507 | lua_pushnil(L); |
4 | 508 | lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, mysql_stmt_error(stmt)); |
3 | 509 | return 2; |
1 | 510 | } |
511 | ||
512 | statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t)); | |
513 | statement->mysql = conn->mysql; | |
514 | statement->stmt = stmt; | |
515 | statement->metadata = NULL; | |
516 | ||
33 | 517 | /* |
518 | mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (my_bool*)0); | |
519 | */ | |
520 | ||
1 | 521 | luaL_getmetatable(L, DBD_MYSQL_STATEMENT); |
522 | lua_setmetatable(L, -2); | |
523 | ||
524 | return 1; | |
525 | } | |
526 | ||
527 | int dbd_mysql_statement(lua_State *L) { | |
2 | 528 | static const luaL_Reg statement_methods[] = { |
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
529 | {"affected", statement_affected}, |
2 | 530 | {"close", statement_close}, |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
26
diff
changeset
|
531 | {"columns", statement_columns}, |
2 | 532 | {"execute", statement_execute}, |
533 | {"fetch", statement_fetch}, | |
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
14
diff
changeset
|
534 | {"rowcount", statement_rowcount}, |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
535 | {"rows", statement_rows}, |
2 | 536 | {NULL, NULL} |
537 | }; | |
538 | ||
539 | static const luaL_Reg statement_class_methods[] = { | |
540 | {NULL, NULL} | |
541 | }; | |
542 | ||
1 | 543 | luaL_newmetatable(L, DBD_MYSQL_STATEMENT); |
544 | luaL_register(L, 0, statement_methods); | |
545 | lua_pushvalue(L,-1); | |
546 | lua_setfield(L, -2, "__index"); | |
547 | ||
548 | lua_pushcfunction(L, statement_gc); | |
549 | lua_setfield(L, -2, "__gc"); | |
550 | ||
32
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
551 | lua_pushcfunction(L, statement_tostring); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
552 | lua_setfield(L, -2, "__tostring"); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
553 | |
1 | 554 | luaL_register(L, DBD_MYSQL_STATEMENT, statement_class_methods); |
555 | ||
556 | return 1; | |
557 | } |