|
42 | 42 | #define TIMEOUT_INFINITY 365 * 86400 * 100.0 |
43 | 43 | static const char mysql_driver_label[] = "__tnt_mysql_driver"; |
44 | 44 |
|
| 45 | +static int luaL_nil_ref = LUA_REFNIL; |
| 46 | + |
| 47 | +/** |
| 48 | + * Push ffi's NULL (cdata<void *>: NULL) onto the stack. |
| 49 | + * Can be used as replacement of nil in Lua tables. |
| 50 | + * @param L stack |
| 51 | + */ |
| 52 | +static inline void |
| 53 | +luaL_pushnull(struct lua_State *L) |
| 54 | +{ |
| 55 | + lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_nil_ref); |
| 56 | +} |
| 57 | + |
45 | 58 | struct mysql_connection { |
46 | 59 | MYSQL *raw_conn; |
47 | 60 | int use_numeric_result; |
@@ -188,7 +201,7 @@ lua_mysql_push_value(struct lua_State *L, MYSQL_FIELD *field, |
188 | 201 | } |
189 | 202 |
|
190 | 203 | case MYSQL_TYPE_NULL: |
191 | | - lua_pushnil(L); |
| 204 | + luaL_pushnull(L); |
192 | 205 | break; |
193 | 206 |
|
194 | 207 | case MYSQL_TYPE_LONGLONG: { |
@@ -239,10 +252,12 @@ lua_mysql_fetch_result(struct lua_State *L) |
239 | 252 | unsigned long *len = mysql_fetch_lengths(result); |
240 | 253 | unsigned col_no; |
241 | 254 | for (col_no = 0; col_no < num_fields; ++col_no) { |
242 | | - if (!row[col_no]) |
243 | | - continue; |
244 | | - lua_mysql_push_value(L, fields + col_no, |
245 | | - row[col_no], len[col_no]); |
| 255 | + if (!row[col_no]) { |
| 256 | + luaL_pushnull(L); |
| 257 | + } else { |
| 258 | + lua_mysql_push_value(L, fields + col_no, |
| 259 | + row[col_no], len[col_no]); |
| 260 | + } |
246 | 261 | if (conn->use_numeric_result) { |
247 | 262 | /* Assign to a column number. */ |
248 | 263 | lua_rawseti(L, -2, col_no + 1); |
@@ -354,12 +369,14 @@ lua_mysql_stmt_push_row(struct lua_State *L) |
354 | 369 | lua_newtable(L); |
355 | 370 | unsigned col_no; |
356 | 371 | for (col_no = 0; col_no < col_count; ++col_no) { |
357 | | - if (*results[col_no].is_null) |
358 | | - continue; |
359 | 372 | lua_pushstring(L, fields[col_no].name); |
360 | | - lua_mysql_push_value(L, fields + col_no, |
361 | | - results[col_no].buffer, |
362 | | - *results[col_no].length); |
| 373 | + if (*results[col_no].is_null) { |
| 374 | + luaL_pushnull(L); |
| 375 | + } else { |
| 376 | + lua_mysql_push_value(L, fields + col_no, |
| 377 | + results[col_no].buffer, |
| 378 | + *results[col_no].length); |
| 379 | + } |
363 | 380 | lua_settable(L, -3); |
364 | 381 | } |
365 | 382 | return 1; |
@@ -679,6 +696,10 @@ luaopen_mysql_driver(lua_State *L) |
679 | 696 | if (mysql_library_init(0, NULL, NULL)) |
680 | 697 | luaL_error(L, "Failed to initialize mysql library"); |
681 | 698 |
|
| 699 | + /* Create NULL constant */ |
| 700 | + *(void **) luaL_pushcdata(L, 17 /*CTID_P_VOID*/) = NULL; |
| 701 | + luaL_nil_ref = luaL_ref(L, LUA_REGISTRYINDEX); |
| 702 | + |
682 | 703 | static const struct luaL_Reg methods [] = { |
683 | 704 | {"execute_prepared", lua_mysql_execute_prepared}, |
684 | 705 | {"execute", lua_mysql_execute}, |
|
0 commit comments