Skip to content

Commit 88d0682

Browse files
darkwratromanhabibov
authored andcommitted
Return ffi's NULL instead of nil in conn:execute() and conn:prepare_executed()
1 parent 6f785f7 commit 88d0682

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

mysql/driver.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@
4242
#define TIMEOUT_INFINITY 365 * 86400 * 100.0
4343
static const char mysql_driver_label[] = "__tnt_mysql_driver";
4444

45+
extern int luaL_nil_ref;
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+
4558
struct mysql_connection {
4659
MYSQL *raw_conn;
4760
int use_numeric_result;
@@ -188,7 +201,7 @@ lua_mysql_push_value(struct lua_State *L, MYSQL_FIELD *field,
188201
}
189202

190203
case MYSQL_TYPE_NULL:
191-
lua_pushnil(L);
204+
luaL_pushnull(L);
192205
break;
193206

194207
case MYSQL_TYPE_LONGLONG: {
@@ -239,10 +252,12 @@ lua_mysql_fetch_result(struct lua_State *L)
239252
unsigned long *len = mysql_fetch_lengths(result);
240253
unsigned col_no;
241254
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+
}
246261
if (conn->use_numeric_result) {
247262
/* Assign to a column number. */
248263
lua_rawseti(L, -2, col_no + 1);
@@ -354,12 +369,14 @@ lua_mysql_stmt_push_row(struct lua_State *L)
354369
lua_newtable(L);
355370
unsigned col_no;
356371
for (col_no = 0; col_no < col_count; ++col_no) {
357-
if (*results[col_no].is_null)
358-
continue;
359372
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+
}
363380
lua_settable(L, -3);
364381
}
365382
return 1;

test/mysql.test.lua

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,18 @@ local function test_connection_reset(test, pool)
481481
assert(pool.queue:is_full(), 'test case postcondition fails')
482482
end
483483

484+
local function test_ffi_null_printing(test, pool)
485+
test:plan(1)
486+
local conn, err = mysql.connect({ host = host, port = port, user = user,
487+
password = password, db = db })
488+
if conn == nil then error(err) end
489+
local rows = conn:execute('SELECT 1 AS w, NULL AS x')
490+
local encoded = json.encode(rows)
491+
test:ok(encoded == '[[{"x":null,"w":1}]]', 'ffi null printing')
492+
end
493+
484494
local test = tap.test('mysql connector')
485-
test:plan(7)
495+
test:plan(8)
486496

487497
test:test('connection old api', test_old_api, conn)
488498
local pool_conn = p:get()
@@ -492,6 +502,7 @@ test:test('concurrent connections', test_conn_concurrent, p)
492502
test:test('int64', test_mysql_int64, p)
493503
test:test('connection pool', test_connection_pool, p)
494504
test:test('connection reset', test_connection_reset, p)
505+
test:test('ffi null printing', test_ffi_null_printing, p)
495506
p:close()
496507

497508
os.exit(test:check() and 0 or 1)

0 commit comments

Comments
 (0)