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