diff --git a/include/mariadb_stmt.h b/include/mariadb_stmt.h index ffc3312b..812decb4 100644 --- a/include/mariadb_stmt.h +++ b/include/mariadb_stmt.h @@ -69,7 +69,8 @@ enum enum_stmt_attr_type STMT_ATTR_STATE, STMT_ATTR_CB_USER_DATA, STMT_ATTR_CB_PARAM, - STMT_ATTR_CB_RESULT + STMT_ATTR_CB_RESULT, + STMT_ATTR_SQL_STATEMENT }; enum enum_cursor_type @@ -204,6 +205,7 @@ struct st_mysql_stmt ps_result_callback result_callback; ps_param_callback param_callback; size_t request_length; + MARIADB_CONST_STRING sql; }; typedef void (*ps_field_fetch_func)(MYSQL_BIND *r_param, const MYSQL_FIELD * field, unsigned char **row); diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 12108c56..d82c5df1 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -971,7 +971,7 @@ static MARIADB_CONST_STRING null_const_string= {0,0}; /*************************************************************************** ** Allocate a string copy on memroot ***************************************************************************/ -static MARIADB_CONST_STRING ma_const_string_copy_root(MA_MEM_ROOT *memroot, +MARIADB_CONST_STRING ma_const_string_copy_root(MA_MEM_ROOT *memroot, const char *str, size_t length) { diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index 4a64471e..221e44b6 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -80,6 +80,9 @@ typedef struct } MADB_STMT_EXTENSION; static my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove); +extern MARIADB_CONST_STRING ma_const_string_copy_root(MA_MEM_ROOT *memroot, + const char *str, + size_t length); static my_bool is_not_null= 0; static my_bool is_null= 1; @@ -1186,6 +1189,9 @@ unsigned long long STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt) my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, void *value) { switch (attr_type) { + case STMT_ATTR_SQL_STATEMENT: + *(MARIADB_CONST_STRING *)value= stmt->sql; + break; case STMT_ATTR_STATE: *(enum mysql_stmt_state *)value= stmt->state; break; @@ -1841,6 +1847,8 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon sizeof(stmt_id), 1, stmt)) goto fail; } + stmt->sql= ma_const_string_copy_root(&stmt->mem_root, query, length); + if (mysql->methods->db_command(mysql, COM_STMT_PREPARE, query, length, 1, stmt)) goto fail; @@ -2398,10 +2406,16 @@ MYSQL_RES * STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt) my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt) { + my_bool rc= 0; if (stmt->stmt_id > 0 && stmt->stmt_id != (unsigned long) -1) - return mysql_stmt_internal_reset(stmt, 0); - return 0; + rc= mysql_stmt_internal_reset(stmt, 0); + + /* clear last sql statement */ + stmt->sql.str= 0; + stmt->sql.length= 0; + + return rc; } const char * STDCALL mysql_stmt_sqlstate(MYSQL_STMT *stmt) diff --git a/unittest/libmariadb/ps.c b/unittest/libmariadb/ps.c index 94d8d833..52abbead 100644 --- a/unittest/libmariadb/ps.c +++ b/unittest/libmariadb/ps.c @@ -5224,7 +5224,46 @@ end: return error ? FAIL : OK; } +static int test_conc691(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + MARIADB_CONST_STRING sql; + const char *sql_stmt[]= {"SELECT 'test' FROM DUAL", "This will return an error", "SELECT 1 FROM DUAL"}; + int rc, i; + + rc= mysql_stmt_attr_get(stmt, STMT_ATTR_SQL_STATEMENT, &sql); + check_stmt_rc(rc, stmt); + + FAIL_IF(sql.str, "Expected empty SQL string"); + FAIL_IF(sql.length, "Expected length=0"); + + + for (i=0; i < 3; i++) + { + rc= mysql_stmt_prepare(stmt, SL(sql_stmt[i])); + + rc= mysql_stmt_attr_get(stmt, STMT_ATTR_SQL_STATEMENT, &sql); + check_stmt_rc(rc, stmt); + + FAIL_IF(strncmp(sql.str, sql_stmt[i], strlen(sql_stmt[i])), "Wrong SQL statement"); + FAIL_IF(sql.length != strlen(sql_stmt[i]), "Wrong statement length"); + } + + rc= mysql_stmt_reset(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_attr_get(stmt, STMT_ATTR_SQL_STATEMENT, &sql); + check_stmt_rc(rc, stmt); + + FAIL_IF(sql.str, "Expected empty SQL string"); + FAIL_IF(sql.length, "Expected length=0"); + + mysql_stmt_close(stmt); + return OK; +} + struct my_tests_st my_tests[] = { + {"test_conc691", test_conc691, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc565", test_conc565, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc349", test_conc349, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_prepare_error", test_prepare_error, TEST_CONNECTION_NEW, 0, NULL, NULL},