4242#define TIMEOUT_INFINITY 365 * 86400 * 100.0
4343static const char mysql_driver_label [] = "__tnt_mysql_driver" ;
4444
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+
4558struct mysql_connection {
4659 MYSQL * raw_conn ;
4760 int use_numeric_result ;
61+ int keep_null ;
4862};
4963
5064/*
@@ -171,9 +185,16 @@ lua_mysql_field_type_to_string(enum enum_field_types type)
171185
172186/* Push value retrieved from mysql field to lua stack */
173187static 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 )
176190{
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 ;
177198 switch (field -> type ) {
178199 case MYSQL_TYPE_TINY :
179200 case MYSQL_TYPE_SHORT :
@@ -188,7 +209,10 @@ lua_mysql_push_value(struct lua_State *L, MYSQL_FIELD *field,
188209 }
189210
190211 case MYSQL_TYPE_NULL :
191- lua_pushnil (L );
212+ if (keep_null == 1 )
213+ luaL_pushnull (L );
214+ else
215+ lua_pushnil (L );
192216 break ;
193217
194218 case MYSQL_TYPE_LONGLONG : {
@@ -239,10 +263,11 @@ lua_mysql_fetch_result(struct lua_State *L)
239263 unsigned long * len = mysql_fetch_lengths (result );
240264 unsigned col_no ;
241265 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 );
246271 if (conn -> use_numeric_result ) {
247272 /* Assign to a column number. */
248273 lua_rawseti (L , -2 , col_no + 1 );
@@ -350,16 +375,19 @@ lua_mysql_stmt_push_row(struct lua_State *L)
350375 unsigned long col_count = lua_tonumber (L , 1 );
351376 MYSQL_BIND * results = (MYSQL_BIND * )lua_topointer (L , 2 );
352377 MYSQL_FIELD * fields = (MYSQL_FIELD * )lua_topointer (L , 3 );
378+ int keep_null = lua_tointeger (L , 4 );
353379
354380 lua_newtable (L );
355381 unsigned col_no ;
356382 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 )
358385 continue ;
386+ else if (!(* results [col_no ].is_null ))
387+ data = results [col_no ].buffer ;
359388 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 );
363391 lua_settable (L , -3 );
364392 }
365393 return 1 ;
@@ -371,7 +399,7 @@ lua_mysql_stmt_push_row(struct lua_State *L)
371399static int
372400lua_mysql_execute_prepared (struct lua_State * L )
373401{
374- MYSQL * raw_conn = lua_check_mysqlconn (L , 1 )-> raw_conn ;
402+ struct mysql_connection * conn = lua_check_mysqlconn (L , 1 );
375403 size_t len ;
376404 const char * sql = lua_tolstring (L , 2 , & len );
377405 int ret_count = 0 , fail = 0 , error = 0 ;
@@ -389,7 +417,7 @@ lua_mysql_execute_prepared(struct lua_State *L)
389417 lua_pushnumber (L , 0 );
390418 lua_newtable (L );
391419 ret_count = 2 ;
392- stmt = mysql_stmt_init (raw_conn );
420+ stmt = mysql_stmt_init (conn -> raw_conn );
393421 if ((error = !stmt ))
394422 goto done ;
395423 error = mysql_stmt_prepare (stmt , sql , len );
@@ -467,7 +495,8 @@ lua_mysql_execute_prepared(struct lua_State *L)
467495 lua_pushnumber (L , col_count );
468496 lua_pushlightuserdata (L , result_binds );
469497 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 )))
471500 goto done ;
472501 lua_settable (L , -3 );
473502 ++ row_idx ;
@@ -476,7 +505,7 @@ lua_mysql_execute_prepared(struct lua_State *L)
476505
477506done :
478507 if (error )
479- ret_count = lua_mysql_push_error (L , raw_conn );
508+ ret_count = lua_mysql_push_error (L , conn -> raw_conn );
480509 if (values )
481510 free (values );
482511 if (param_binds )
@@ -592,9 +621,9 @@ mysql_wait_for_io(my_socket socket, my_bool is_read, int timeout)
592621static int
593622lua_mysql_connect (struct lua_State * L )
594623{
595- if (lua_gettop (L ) < 6 ) {
624+ if (lua_gettop (L ) < 7 ) {
596625 luaL_error (L , "Usage: mysql.connect(host, port, user, "
597- "password, db, use_numeric_result)" );
626+ "password, db, use_numeric_result, keep_null )" );
598627 }
599628
600629 const char * host = lua_tostring (L , 1 );
@@ -603,6 +632,7 @@ lua_mysql_connect(struct lua_State *L)
603632 const char * pass = lua_tostring (L , 4 );
604633 const char * db = lua_tostring (L , 5 );
605634 const int use_numeric_result = lua_toboolean (L , 6 );
635+ const int keep_null = lua_toboolean (L , 7 );
606636
607637 MYSQL * raw_conn , * tmp_raw_conn = mysql_init (NULL );
608638 if (!tmp_raw_conn ) {
@@ -650,6 +680,7 @@ lua_mysql_connect(struct lua_State *L)
650680 * conn_p = conn ;
651681 (* conn_p )-> raw_conn = raw_conn ;
652682 (* conn_p )-> use_numeric_result = use_numeric_result ;
683+ (* conn_p )-> keep_null = keep_null ;
653684 luaL_getmetatable (L , mysql_driver_label );
654685 lua_setmetatable (L , -2 );
655686
@@ -679,6 +710,10 @@ luaopen_mysql_driver(lua_State *L)
679710 if (mysql_library_init (0 , NULL , NULL ))
680711 luaL_error (L , "Failed to initialize mysql library" );
681712
713+ /* Create NULL constant. */
714+ * (void * * ) luaL_pushcdata (L , luaL_ctypeid (L , "void *" )) = NULL ;
715+ luaL_nil_ref = luaL_ref (L , LUA_REGISTRYINDEX );
716+
682717 static const struct luaL_Reg methods [] = {
683718 {"execute_prepared" , lua_mysql_execute_prepared },
684719 {"execute" , lua_mysql_execute },
0 commit comments