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 ;
61
+ int keep_null ;
48
62
};
49
63
50
64
/*
@@ -169,11 +183,23 @@ lua_mysql_field_type_to_string(enum enum_field_types type)
169
183
return mysql_field_type_strs [hash ];
170
184
}
171
185
172
- /* Push value retrieved from mysql field to lua stack */
186
+ /**
187
+ * Push value retrieved from mysql field to lua stack.
188
+ *
189
+ * When `data` is NULL, `field` and len` parameters are
190
+ * ignored and Lua nil or LuaJIT FFI NULL is pushed.
191
+ */
173
192
static void
174
- lua_mysql_push_value (struct lua_State * L , MYSQL_FIELD * field ,
175
- void * data , unsigned long len )
193
+ lua_mysql_push_value (struct lua_State * L , MYSQL_FIELD * field , void * data ,
194
+ unsigned long len , int keep_null )
176
195
{
196
+ /*
197
+ * Field type isn't MYSQL_TYPE_NULL actually in case of
198
+ * Lua's nil passed as value.
199
+ * Example: 'conn:execute('SELECT ? AS x', nil)'.
200
+ */
201
+ if (data == NULL )
202
+ field -> type = MYSQL_TYPE_NULL ;
177
203
switch (field -> type ) {
178
204
case MYSQL_TYPE_TINY :
179
205
case MYSQL_TYPE_SHORT :
@@ -188,7 +214,10 @@ lua_mysql_push_value(struct lua_State *L, MYSQL_FIELD *field,
188
214
}
189
215
190
216
case MYSQL_TYPE_NULL :
191
- lua_pushnil (L );
217
+ if (keep_null == 1 )
218
+ luaL_pushnull (L );
219
+ else
220
+ lua_pushnil (L );
192
221
break ;
193
222
194
223
case MYSQL_TYPE_LONGLONG : {
@@ -239,10 +268,8 @@ lua_mysql_fetch_result(struct lua_State *L)
239
268
unsigned long * len = mysql_fetch_lengths (result );
240
269
unsigned col_no ;
241
270
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 ]);
271
+ lua_mysql_push_value (L , fields + col_no , row [col_no ],
272
+ len [col_no ], conn -> keep_null );
246
273
if (conn -> use_numeric_result ) {
247
274
/* Assign to a column number. */
248
275
lua_rawseti (L , -2 , col_no + 1 );
@@ -350,16 +377,16 @@ lua_mysql_stmt_push_row(struct lua_State *L)
350
377
unsigned long col_count = lua_tonumber (L , 1 );
351
378
MYSQL_BIND * results = (MYSQL_BIND * )lua_topointer (L , 2 );
352
379
MYSQL_FIELD * fields = (MYSQL_FIELD * )lua_topointer (L , 3 );
380
+ int keep_null = lua_tointeger (L , 4 );
353
381
354
382
lua_newtable (L );
355
383
unsigned col_no ;
356
384
for (col_no = 0 ; col_no < col_count ; ++ col_no ) {
357
- if ( * results [col_no ].is_null )
358
- continue ;
385
+ void * data = * results [col_no ].is_null ? NULL :
386
+ results [ col_no ]. buffer ;
359
387
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 );
388
+ lua_mysql_push_value (L , fields + col_no , data ,
389
+ * results [col_no ].length , keep_null );
363
390
lua_settable (L , -3 );
364
391
}
365
392
return 1 ;
@@ -371,7 +398,7 @@ lua_mysql_stmt_push_row(struct lua_State *L)
371
398
static int
372
399
lua_mysql_execute_prepared (struct lua_State * L )
373
400
{
374
- MYSQL * raw_conn = lua_check_mysqlconn (L , 1 )-> raw_conn ;
401
+ struct mysql_connection * conn = lua_check_mysqlconn (L , 1 );
375
402
size_t len ;
376
403
const char * sql = lua_tolstring (L , 2 , & len );
377
404
int ret_count = 0 , fail = 0 , error = 0 ;
@@ -389,7 +416,7 @@ lua_mysql_execute_prepared(struct lua_State *L)
389
416
lua_pushnumber (L , 0 );
390
417
lua_newtable (L );
391
418
ret_count = 2 ;
392
- stmt = mysql_stmt_init (raw_conn );
419
+ stmt = mysql_stmt_init (conn -> raw_conn );
393
420
if ((error = !stmt ))
394
421
goto done ;
395
422
error = mysql_stmt_prepare (stmt , sql , len );
@@ -467,7 +494,8 @@ lua_mysql_execute_prepared(struct lua_State *L)
467
494
lua_pushnumber (L , col_count );
468
495
lua_pushlightuserdata (L , result_binds );
469
496
lua_pushlightuserdata (L , fields );
470
- if ((fail = lua_pcall (L , 3 , 1 , 0 )))
497
+ lua_pushinteger (L , conn -> keep_null );
498
+ if ((fail = lua_pcall (L , 4 , 1 , 0 )))
471
499
goto done ;
472
500
lua_settable (L , -3 );
473
501
++ row_idx ;
@@ -476,7 +504,7 @@ lua_mysql_execute_prepared(struct lua_State *L)
476
504
477
505
done :
478
506
if (error )
479
- ret_count = lua_mysql_push_error (L , raw_conn );
507
+ ret_count = lua_mysql_push_error (L , conn -> raw_conn );
480
508
if (values )
481
509
free (values );
482
510
if (param_binds )
@@ -592,9 +620,9 @@ mysql_wait_for_io(my_socket socket, my_bool is_read, int timeout)
592
620
static int
593
621
lua_mysql_connect (struct lua_State * L )
594
622
{
595
- if (lua_gettop (L ) < 6 ) {
623
+ if (lua_gettop (L ) < 7 ) {
596
624
luaL_error (L , "Usage: mysql.connect(host, port, user, "
597
- "password, db, use_numeric_result)" );
625
+ "password, db, use_numeric_result, keep_null )" );
598
626
}
599
627
600
628
const char * host = lua_tostring (L , 1 );
@@ -603,6 +631,7 @@ lua_mysql_connect(struct lua_State *L)
603
631
const char * pass = lua_tostring (L , 4 );
604
632
const char * db = lua_tostring (L , 5 );
605
633
const int use_numeric_result = lua_toboolean (L , 6 );
634
+ const int keep_null = lua_toboolean (L , 7 );
606
635
607
636
MYSQL * raw_conn , * tmp_raw_conn = mysql_init (NULL );
608
637
if (!tmp_raw_conn ) {
@@ -650,6 +679,7 @@ lua_mysql_connect(struct lua_State *L)
650
679
* conn_p = conn ;
651
680
(* conn_p )-> raw_conn = raw_conn ;
652
681
(* conn_p )-> use_numeric_result = use_numeric_result ;
682
+ (* conn_p )-> keep_null = keep_null ;
653
683
luaL_getmetatable (L , mysql_driver_label );
654
684
lua_setmetatable (L , -2 );
655
685
@@ -679,6 +709,10 @@ luaopen_mysql_driver(lua_State *L)
679
709
if (mysql_library_init (0 , NULL , NULL ))
680
710
luaL_error (L , "Failed to initialize mysql library" );
681
711
712
+ /* Create NULL constant. */
713
+ * (void * * ) luaL_pushcdata (L , luaL_ctypeid (L , "void *" )) = NULL ;
714
+ luaL_nil_ref = luaL_ref (L , LUA_REGISTRYINDEX );
715
+
682
716
static const struct luaL_Reg methods [] = {
683
717
{"execute_prepared" , lua_mysql_execute_prepared },
684
718
{"execute" , lua_mysql_execute },
0 commit comments