You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
Fixed crash when calling mysql_close_options twice (pointer weren't adjusted to NULL)
Fixed wrong behaviour when using stored procedures inside prepared statements Fixed identiation in my_stmt.h
This commit is contained in:
@@ -196,7 +196,7 @@ struct st_mysql_stmt
|
||||
|
||||
my_bool cursor_exists;
|
||||
|
||||
void *ext_stmt;
|
||||
void *extension;
|
||||
mysql_stmt_fetch_row_func fetch_row_func;
|
||||
unsigned int execute_count;/* count how many times the stmt was executed */
|
||||
mysql_stmt_use_or_store_func default_rset_handler;
|
||||
|
@@ -69,6 +69,8 @@
|
||||
#ifdef DBUG_OFF
|
||||
#undef DBUG_OFF
|
||||
#endif
|
||||
|
||||
#undef SAVE_MUTEX
|
||||
#include <my_global.h>
|
||||
#include <m_string.h>
|
||||
#include <errno.h>
|
||||
|
@@ -1886,7 +1886,7 @@ static my_bool mysql_reconnect(MYSQL *mysql)
|
||||
bzero((char*) &mysql->options,sizeof(mysql->options));
|
||||
if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
|
||||
mysql->db, mysql->port, mysql->unix_socket,
|
||||
mysql->client_flag))
|
||||
mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
|
||||
{
|
||||
my_set_error(mysql, tmp_mysql.net.last_errno,
|
||||
tmp_mysql.net.sqlstate,
|
||||
@@ -2035,6 +2035,8 @@ static void mysql_close_options(MYSQL *mysql)
|
||||
my_free(mysql->options.extension->default_auth, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free((gptr)mysql->options.extension->db_driver, MYF(MY_ALLOW_ZERO_PTR));
|
||||
}
|
||||
/* clear all pointer */
|
||||
memset(&mysql->options, 0, sizeof(mysql->options));
|
||||
}
|
||||
|
||||
static void mysql_close_memory(MYSQL *mysql)
|
||||
|
@@ -18,7 +18,7 @@
|
||||
|
||||
Part of this code includes code from the PHP project which
|
||||
is freely available from http://www.php.net
|
||||
*****************************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
/* The implementation for prepared statements was ported from PHP's mysqlnd
|
||||
extension, written by Andrey Hristov, Georg Richter and Ulf Wendel
|
||||
@@ -41,7 +41,7 @@
|
||||
| Andrey Hristov <andrey@mysql.com> |
|
||||
| Ulf Wendel <uwendel@mysql.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
*/
|
||||
|
||||
#include "my_global.h"
|
||||
#include <my_sys.h>
|
||||
@@ -63,6 +63,12 @@
|
||||
#define MADB_RESET_LONGDATA 2
|
||||
#define MADB_RESET_SERVER 4
|
||||
#define MADB_RESET_BUFFER 8
|
||||
#define MADB_RESET_STORED 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MEM_ROOT fields_alloc_root;
|
||||
} MADB_STMT_EXTENSION;
|
||||
|
||||
static my_bool is_not_null= 0;
|
||||
static my_bool is_null= 1;
|
||||
@@ -99,7 +105,6 @@ my_bool mthd_supported_buffer_type(enum enum_field_types type)
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,8 +207,8 @@ int mthd_stmt_read_all_rows(MYSQL_STMT *stmt)
|
||||
cp+= len;
|
||||
if (len > stmt->fields[i].max_length)
|
||||
stmt->fields[i].max_length= (ulong)len;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (!stmt->fields[i].max_length)
|
||||
stmt->fields[i].max_length= mysql_ps_fetch_functions[stmt->fields[i].type].max_len;
|
||||
@@ -431,8 +436,8 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p)
|
||||
memcpy(*p, t_buffer, len);
|
||||
len++;
|
||||
(*p)+= len;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_DATE:
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
@@ -463,8 +468,8 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p)
|
||||
memcpy(*p, t_buffer, len);
|
||||
len++;
|
||||
(*p)+= len;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
@@ -482,9 +487,9 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p)
|
||||
if (len)
|
||||
memcpy(to, stmt->params[column].buffer, len);
|
||||
(*p) = to + len;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
/* unsupported parameter type */
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_UNSUPPORTED_PARAM_TYPE, SQLSTATE_UNKNOWN, 0);
|
||||
@@ -664,7 +669,7 @@ mem_error:
|
||||
|
||||
\param[in] stmt The statement handle
|
||||
*******************************************************************************
|
||||
*/
|
||||
*/
|
||||
my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
|
||||
{
|
||||
return stmt->upsert_status.affected_rows;
|
||||
@@ -698,7 +703,7 @@ my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type a
|
||||
case STMT_ATTR_UPDATE_MAX_LENGTH:
|
||||
stmt->update_max_length= *(my_bool *)value;
|
||||
break;
|
||||
case STMT_ATTR_CURSOR_TYPE: {
|
||||
case STMT_ATTR_CURSOR_TYPE:
|
||||
if (*(ulong *)value > (unsigned long) CURSOR_TYPE_READ_ONLY)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
|
||||
@@ -706,14 +711,12 @@ my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type a
|
||||
}
|
||||
stmt->flags = *(ulong *)value;
|
||||
break;
|
||||
}
|
||||
case STMT_ATTR_PREFETCH_ROWS: {
|
||||
case STMT_ATTR_PREFETCH_ROWS:
|
||||
if (*(ulong *)value == 0)
|
||||
*(long *)value= MYSQL_DEFAULT_PREFETCH_ROWS;
|
||||
else
|
||||
stmt->prefetch_rows= *(long *)value;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
@@ -828,9 +831,13 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
/* In case of a stored procedure we don't allocate memory for bind
|
||||
in mysql_stmt_prepare
|
||||
*/
|
||||
|
||||
if (stmt->field_count && !stmt->bind)
|
||||
{
|
||||
if (!(stmt->bind= (MYSQL_BIND *)alloc_root(&stmt->mem_root, stmt->field_count * sizeof(MYSQL_BIND))))
|
||||
MEM_ROOT *fields_alloc_root=
|
||||
&((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root;
|
||||
// free_root(fields_alloc_root, MYF(0));
|
||||
if (!(stmt->bind= (MYSQL_BIND *)alloc_root(fields_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
@@ -895,9 +902,12 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove)
|
||||
{
|
||||
char stmt_id[STMT_ID_LENGTH];
|
||||
MEM_ROOT *fields_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root;
|
||||
|
||||
/* clear memory */
|
||||
free_root(&stmt->result.alloc, MYF(00)); /* allocated in mysql_stmt_store_result */
|
||||
free_root(&stmt->result.alloc, MYF(0)); /* allocated in mysql_stmt_store_result */
|
||||
free_root(&stmt->mem_root,MYF(0));
|
||||
free_root(fields_alloc_root, MYF(0));
|
||||
|
||||
if (stmt->mysql)
|
||||
{
|
||||
@@ -930,9 +940,13 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
|
||||
{
|
||||
DBUG_ENTER("mysql_stmt_close");
|
||||
|
||||
if (stmt->mysql && stmt->mysql->net.vio)
|
||||
mysql_stmt_reset(stmt);
|
||||
net_stmt_close(stmt, 1);
|
||||
|
||||
my_free((char *)stmt->extension, MYF(MY_WME));
|
||||
my_free((char *)stmt, MYF(MY_WME));
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@@ -998,7 +1012,7 @@ int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
|
||||
stmt->state= MYSQL_STMT_FETCH_DONE;
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
/* to fetch data again, stmt must be executed again */
|
||||
DBUG_RETURN(MYSQL_NO_DATA);
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
|
||||
if ((rc= stmt->mysql->methods->db_stmt_fetch_to_bind(stmt, row)))
|
||||
@@ -1057,21 +1071,25 @@ unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
|
||||
|
||||
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
|
||||
{
|
||||
return madb_reset_stmt(stmt, MADB_RESET_LONGDATA | MADB_RESET_BUFFER | MADB_RESET_ERROR);
|
||||
return madb_reset_stmt(stmt, MADB_RESET_LONGDATA | MADB_RESET_STORED | MADB_RESET_ERROR);
|
||||
}
|
||||
|
||||
MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql)
|
||||
{
|
||||
|
||||
MYSQL_STMT *stmt = (MYSQL_STMT *)my_malloc(sizeof(MYSQL_STMT), MYF(MY_WME | MY_ZEROFILL));
|
||||
MYSQL_STMT *stmt;
|
||||
DBUG_ENTER("mysql_stmt_init");
|
||||
|
||||
if (!stmt)
|
||||
if (!(stmt= (MYSQL_STMT *)my_malloc(sizeof(MYSQL_STMT), MYF(MY_WME | MY_ZEROFILL))) ||
|
||||
!(stmt->extension= (MADB_STMT_EXTENSION *)my_malloc(sizeof(MADB_STMT_EXTENSION),
|
||||
MYF(MY_WME | MY_ZEROFILL))))
|
||||
{
|
||||
my_free((gptr)stmt, MYF(MY_ALLOW_ZERO_PTR));
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
|
||||
|
||||
/* fill mysql's stmt list */
|
||||
stmt->list.data= stmt;
|
||||
stmt->mysql= mysql;
|
||||
@@ -1086,6 +1104,10 @@ MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql)
|
||||
/* set default */
|
||||
stmt->prefetch_rows= 1;
|
||||
|
||||
init_alloc_root(&stmt->mem_root, 2048, 0);
|
||||
init_alloc_root(&stmt->result.alloc, 4096, 0);
|
||||
init_alloc_root(&((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root, 2048, 0);
|
||||
|
||||
DBUG_RETURN(stmt);
|
||||
}
|
||||
|
||||
@@ -1138,11 +1160,12 @@ my_bool mthd_stmt_get_param_metadata(MYSQL_STMT *stmt)
|
||||
my_bool mthd_stmt_get_result_metadata(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL_DATA *result;
|
||||
MEM_ROOT *fields_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root;
|
||||
DBUG_ENTER("stmt_read_result_metadata");
|
||||
|
||||
if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7)))
|
||||
DBUG_RETURN(1);
|
||||
if (!(stmt->fields= unpack_fields(result,&stmt->mem_root,
|
||||
if (!(stmt->fields= unpack_fields(result,fields_alloc_root,
|
||||
stmt->field_count, 0,
|
||||
stmt->mysql->server_capabilities & CLIENT_LONG_FLAG)))
|
||||
DBUG_RETURN(1);
|
||||
@@ -1176,6 +1199,8 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon
|
||||
mysql_stmt_reset(stmt);
|
||||
|
||||
free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
|
||||
free_root(&((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root, MYF(0));
|
||||
|
||||
stmt->param_count= 0;
|
||||
stmt->field_count= 0;
|
||||
|
||||
@@ -1215,7 +1240,8 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon
|
||||
/* allocated bind buffer for result */
|
||||
if (stmt->field_count)
|
||||
{
|
||||
if (!(stmt->bind= (MYSQL_BIND *)alloc_root(&stmt->mem_root, stmt->field_count * sizeof(MYSQL_BIND))))
|
||||
MEM_ROOT *fields_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root;
|
||||
if (!(stmt->bind= (MYSQL_BIND *)alloc_root(fields_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
goto fail;
|
||||
@@ -1297,12 +1323,14 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||
static int madb_alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
{
|
||||
int i;
|
||||
MEM_ROOT *fields_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root;
|
||||
|
||||
DBUG_ENTER("madb_alloc_stmt_fields");
|
||||
|
||||
if (stmt->mysql->field_count)
|
||||
{
|
||||
if (!(stmt->fields= (MYSQL_FIELD *)alloc_root(&stmt->mem_root,
|
||||
free_root(fields_alloc_root, MYF(0));
|
||||
if (!(stmt->fields= (MYSQL_FIELD *)alloc_root(fields_alloc_root,
|
||||
sizeof(MYSQL_FIELD) * stmt->mysql->field_count)))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
@@ -1313,25 +1341,26 @@ static int madb_alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
for (i=0; i < stmt->field_count; i++)
|
||||
{
|
||||
if (stmt->mysql->fields[i].db)
|
||||
stmt->fields[i].db= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].db);
|
||||
stmt->fields[i].db= strdup_root(fields_alloc_root, stmt->mysql->fields[i].db);
|
||||
if (stmt->mysql->fields[i].table)
|
||||
stmt->fields[i].table= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].table);
|
||||
stmt->fields[i].table= strdup_root(fields_alloc_root, stmt->mysql->fields[i].table);
|
||||
if (stmt->mysql->fields[i].org_table)
|
||||
stmt->fields[i].org_table= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].org_table);
|
||||
stmt->fields[i].org_table= strdup_root(fields_alloc_root, stmt->mysql->fields[i].org_table);
|
||||
if (stmt->mysql->fields[i].name)
|
||||
stmt->fields[i].name= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].name);
|
||||
stmt->fields[i].name= strdup_root(fields_alloc_root, stmt->mysql->fields[i].name);
|
||||
if (stmt->mysql->fields[i].org_name)
|
||||
stmt->fields[i].org_name= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].org_name);
|
||||
stmt->fields[i].org_name= strdup_root(fields_alloc_root, stmt->mysql->fields[i].org_name);
|
||||
if (stmt->mysql->fields[i].catalog)
|
||||
stmt->fields[i].catalog= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].catalog);
|
||||
stmt->fields[i].def= stmt->mysql->fields[i].def ? strdup_root(&stmt->mem_root, stmt->mysql->fields[i].def) : NULL;
|
||||
stmt->fields[i].catalog= strdup_root(fields_alloc_root, stmt->mysql->fields[i].catalog);
|
||||
stmt->fields[i].def= stmt->mysql->fields[i].def ? strdup_root(fields_alloc_root, stmt->mysql->fields[i].def) : NULL;
|
||||
stmt->fields[i].type= stmt->mysql->fields[i].type;
|
||||
stmt->fields[i].length= stmt->mysql->fields[i].length;
|
||||
stmt->fields[i].flags= stmt->mysql->fields[i].flags;
|
||||
stmt->fields[i].decimals= stmt->mysql->fields[i].decimals;
|
||||
stmt->fields[i].charsetnr= stmt->mysql->fields[i].charsetnr;
|
||||
stmt->fields[i].max_length= stmt->mysql->fields[i].max_length;
|
||||
}
|
||||
if (!(stmt->bind= (MYSQL_BIND *)alloc_root(&stmt->mem_root, stmt->field_count * sizeof(MYSQL_BIND))))
|
||||
if (!(stmt->bind= (MYSQL_BIND *)alloc_root(fields_alloc_root, stmt->field_count * sizeof(MYSQL_BIND))))
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
@@ -1427,13 +1456,20 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
|
||||
if (stmt->mysql->field_count)
|
||||
{
|
||||
if (!stmt->field_count) /* fix for ps_bug: test_misc */
|
||||
if (!stmt->field_count ||
|
||||
stmt->mysql->server_status & SERVER_MORE_RESULTS_EXIST) /* fix for ps_bug: test_misc */
|
||||
{
|
||||
MEM_ROOT *fields_alloc_root=
|
||||
&((MADB_STMT_EXTENSION *)stmt->extension)->fields_alloc_root;
|
||||
uint i;
|
||||
if (!(stmt->fields= (MYSQL_FIELD *)alloc_root(&stmt->mem_root,
|
||||
|
||||
free_root(fields_alloc_root, MYF(0));
|
||||
if (!(stmt->bind= (MYSQL_BIND *)alloc_root(fields_alloc_root,
|
||||
sizeof(MYSQL_BIND) * stmt->mysql->field_count)) ||
|
||||
!(stmt->fields= (MYSQL_FIELD *)alloc_root(fields_alloc_root,
|
||||
sizeof(MYSQL_FIELD) * stmt->mysql->field_count)))
|
||||
{
|
||||
/*todo: set error */
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
stmt->field_count= stmt->mysql->field_count;
|
||||
@@ -1441,18 +1477,18 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
for (i=0; i < stmt->field_count; i++)
|
||||
{
|
||||
if (stmt->mysql->fields[i].db)
|
||||
stmt->fields[i].db= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].db);
|
||||
stmt->fields[i].db= strdup_root(fields_alloc_root, stmt->mysql->fields[i].db);
|
||||
if (stmt->mysql->fields[i].table)
|
||||
stmt->fields[i].table= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].table);
|
||||
stmt->fields[i].table= strdup_root(fields_alloc_root, stmt->mysql->fields[i].table);
|
||||
if (stmt->mysql->fields[i].org_table)
|
||||
stmt->fields[i].org_table= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].org_table);
|
||||
stmt->fields[i].org_table= strdup_root(fields_alloc_root, stmt->mysql->fields[i].org_table);
|
||||
if (stmt->mysql->fields[i].name)
|
||||
stmt->fields[i].name= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].name);
|
||||
stmt->fields[i].name= strdup_root(fields_alloc_root, stmt->mysql->fields[i].name);
|
||||
if (stmt->mysql->fields[i].org_name)
|
||||
stmt->fields[i].org_name= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].org_name);
|
||||
stmt->fields[i].org_name= strdup_root(fields_alloc_root, stmt->mysql->fields[i].org_name);
|
||||
if (stmt->mysql->fields[i].catalog)
|
||||
stmt->fields[i].catalog= strdup_root(&stmt->mem_root, stmt->mysql->fields[i].catalog);
|
||||
stmt->fields[i].def= stmt->mysql->fields[i].def ? strdup_root(&stmt->mem_root, stmt->mysql->fields[i].def) : NULL;
|
||||
stmt->fields[i].catalog= strdup_root(fields_alloc_root, stmt->mysql->fields[i].catalog);
|
||||
stmt->fields[i].def= stmt->mysql->fields[i].def ? strdup_root(fields_alloc_root, stmt->mysql->fields[i].def) : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1496,6 +1532,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
stmt->fields[i].flags= stmt->mysql->fields[i].flags;
|
||||
stmt->fields[i].decimals= stmt->mysql->fields[i].decimals;
|
||||
stmt->fields[i].charsetnr= stmt->mysql->fields[i].charsetnr;
|
||||
stmt->fields[i].max_length= stmt->mysql->fields[i].max_length;
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -1527,6 +1564,19 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
|
||||
|
||||
if (stmt->stmt_id)
|
||||
{
|
||||
/* free buffered resultset, previously allocated
|
||||
* by mysql_stmt_store_result
|
||||
*/
|
||||
if (flags & MADB_RESET_STORED)
|
||||
{
|
||||
free_root(&stmt->result.alloc, MYF(MY_KEEP_PREALLOC));
|
||||
stmt->result.data= NULL;
|
||||
stmt->result.rows= 0;
|
||||
stmt->result_cursor= NULL;
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
|
||||
/* if there is a pending result set, we will flush it */
|
||||
if (flags & MADB_RESET_BUFFER)
|
||||
{
|
||||
if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
|
||||
@@ -1542,6 +1592,7 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (flags & MADB_RESET_SERVER)
|
||||
{
|
||||
/* reset statement on server side */
|
||||
@@ -1576,13 +1627,22 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
|
||||
my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
||||
{
|
||||
my_bool ret= 1;
|
||||
unsigned int flags= MADB_RESET_LONGDATA | MADB_RESET_BUFFER | MADB_RESET_ERROR;
|
||||
|
||||
DBUG_ENTER("mysql_stmt_reset");
|
||||
|
||||
ret= madb_reset_stmt(stmt, MADB_RESET_LONGDATA |
|
||||
MADB_RESET_SERVER | MADB_RESET_ERROR);
|
||||
if (stmt->state >= MYSQL_STMT_USER_FETCHING &&
|
||||
stmt->fetch_row_func == stmt_unbuffered_fetch)
|
||||
flags|= MADB_RESET_BUFFER;
|
||||
|
||||
ret= madb_reset_stmt(stmt, flags);
|
||||
|
||||
if (stmt->stmt_id)
|
||||
{
|
||||
if ((stmt->state > MYSQL_STMT_EXECUTED &&
|
||||
stmt->mysql->status != MYSQL_STATUS_READY) ||
|
||||
stmt->mysql->server_status & SERVER_MORE_RESULTS_EXIST)
|
||||
{
|
||||
/* flush any pending (multiple) result sets */
|
||||
if (stmt->state == MYSQL_STMT_WAITING_USE_OR_STORE)
|
||||
{
|
||||
@@ -1590,21 +1650,20 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
||||
stmt->state = MYSQL_STMT_USER_FETCHING;
|
||||
}
|
||||
|
||||
if (stmt->mysql->status!= MYSQL_STATUS_READY && stmt->field_count)
|
||||
if (stmt->field_count)
|
||||
{
|
||||
while (mysql_stmt_next_result(stmt) == 0);
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
|
||||
if (stmt->stmt_id)
|
||||
{
|
||||
}
|
||||
ret= madb_reset_stmt(stmt, MADB_RESET_SERVER);
|
||||
}
|
||||
stmt->state= MYSQL_STMT_PREPARED;
|
||||
stmt->upsert_status.affected_rows= stmt->mysql->affected_rows;
|
||||
stmt->upsert_status.last_insert_id= stmt->mysql->insert_id;
|
||||
stmt->upsert_status.server_status= stmt->mysql->server_status;
|
||||
stmt->upsert_status.warning_count= stmt->mysql->warning_count;
|
||||
stmt->mysql->status= MYSQL_STATUS_READY;
|
||||
}
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
@@ -1712,9 +1771,16 @@ MYSQL_RES* STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt)
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
|
||||
int STDCALL mysql_stmt_more_results(MYSQL_STMT *stmt)
|
||||
{
|
||||
return (stmt &&
|
||||
stmt->mysql &&
|
||||
(stmt->mysql->server_status & SERVER_MORE_RESULTS_EXIST));
|
||||
}
|
||||
|
||||
int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
|
||||
{
|
||||
int rc;
|
||||
int rc= 0;
|
||||
DBUG_ENTER("mysql_stmt_next_result");
|
||||
|
||||
if (!stmt->mysql)
|
||||
@@ -1730,9 +1796,11 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (!mysql_more_results(stmt->mysql))
|
||||
if (!mysql_stmt_more_results(stmt))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
if (stmt->state > MYSQL_STMT_EXECUTED &&
|
||||
stmt->state < MYSQL_STMT_FETCH_DONE)
|
||||
madb_reset_stmt(stmt, MADB_RESET_ERROR | MADB_RESET_BUFFER | MADB_RESET_LONGDATA);
|
||||
stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE;
|
||||
|
||||
@@ -1745,6 +1813,13 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
|
||||
|
||||
if (stmt->mysql->field_count)
|
||||
rc= madb_alloc_stmt_fields(stmt);
|
||||
else
|
||||
{
|
||||
stmt->upsert_status.affected_rows= stmt->mysql->affected_rows;
|
||||
stmt->upsert_status.last_insert_id= stmt->mysql->insert_id;
|
||||
stmt->upsert_status.server_status= stmt->mysql->server_status;
|
||||
stmt->upsert_status.warning_count= stmt->mysql->warning_count;
|
||||
}
|
||||
|
||||
stmt->field_count= stmt->mysql->field_count;
|
||||
|
||||
|
@@ -2252,7 +2252,7 @@ static int test_bug4079(MYSQL *mysql)
|
||||
mysql_stmt_bind_result(stmt, my_bind);
|
||||
|
||||
rc= mysql_stmt_fetch(stmt);
|
||||
FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
|
||||
FAIL_UNLESS(rc == 1, "rc != 1");
|
||||
/* buggy version of libmysql hanged up here */
|
||||
mysql_stmt_close(stmt);
|
||||
return OK;
|
||||
|
@@ -51,7 +51,7 @@ static int test_multi_result(MYSQL *mysql)
|
||||
stmt = mysql_stmt_init(mysql);
|
||||
if (!stmt)
|
||||
{
|
||||
printf("Could not initialize statement\n");
|
||||
diag("Could not initialize statement");
|
||||
exit(1);
|
||||
}
|
||||
rc = mysql_stmt_prepare(stmt, "CALL p1(?, ?, ?)", 16);
|
||||
@@ -105,8 +105,8 @@ static int test_multi_result(MYSQL *mysql)
|
||||
|
||||
FAIL_IF(int_data[0] != 10 || int_data[1] != 20 || int_data[2] != 30,
|
||||
"expected 10 20 30");
|
||||
|
||||
FAIL_IF(mysql_stmt_next_result(stmt) != 0, "expected more results");
|
||||
rc= mysql_stmt_next_result(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
rc= mysql_stmt_bind_result(stmt, rs_bind);
|
||||
|
||||
rc= mysql_stmt_fetch(stmt);
|
||||
@@ -126,21 +126,21 @@ static int test_multi_result(MYSQL *mysql)
|
||||
FAIL_IF(mysql_stmt_field_count(stmt) != 0, "expected 0 fields");
|
||||
|
||||
rc= mysql_stmt_close(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int test_sp_params(MYSQL *mysql)
|
||||
{
|
||||
int i, rc;
|
||||
MYSQL_STMT *stmt;
|
||||
|
||||
rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
int a[] = {10,20,30};
|
||||
MYSQL_BIND bind[3];
|
||||
char *stmtstr= "CALL P1(?,?,?)";
|
||||
char res[3][20];
|
||||
|
||||
rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19), IN p_in INT, INOUT p_inout INT)"
|
||||
"BEGIN "
|
||||
" SET p_in = 300, p_out := 'This is OUT param', p_inout = 200; "
|
||||
@@ -254,6 +254,9 @@ int test_sp_reset(MYSQL *mysql)
|
||||
rc= mysql_stmt_execute(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
rc= mysql_stmt_fetch(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
rc= mysql_stmt_reset(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
@@ -266,10 +269,214 @@ int test_sp_reset(MYSQL *mysql)
|
||||
return OK;
|
||||
}
|
||||
|
||||
int test_sp_reset1(MYSQL *mysql)
|
||||
{
|
||||
int rc;
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[1];
|
||||
|
||||
char tmp[20];
|
||||
char *stmtstr= "CALL P1(?)";
|
||||
|
||||
rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19))"
|
||||
"BEGIN "
|
||||
" SET p_out = 'foo';"
|
||||
" SELECT 'foo' FROM DUAL;"
|
||||
" SELECT 'bar' FROM DUAL;"
|
||||
"END");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr));
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
memset(bind, 0, sizeof(MYSQL_BIND));
|
||||
bind[0].buffer= tmp;
|
||||
bind[0].buffer_type= MYSQL_TYPE_STRING;
|
||||
bind[0].buffer_length= 4;
|
||||
|
||||
mysql_stmt_bind_param(stmt, bind);
|
||||
|
||||
rc= mysql_stmt_execute(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
rc= mysql_stmt_store_result(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
rc= mysql_stmt_next_result(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
rc= mysql_stmt_fetch(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
/* mysql_stmt_reset should set statement in prepared state.
|
||||
* this means: all subsequent result sets should be flushed.
|
||||
* Let's try!
|
||||
*/
|
||||
rc= mysql_stmt_reset(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
rc= mysql_query(mysql, "DROP PROCEDURE p1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
mysql_stmt_close(stmt);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int test_sp_reset2(MYSQL *mysql)
|
||||
{
|
||||
int rc, i;
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[4];
|
||||
long l[4];
|
||||
|
||||
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
char *stmtstr= "CALL P1()";
|
||||
|
||||
rc= mysql_query(mysql, "CREATE PROCEDURE p1()"
|
||||
"BEGIN "
|
||||
" SET @a:=1;"
|
||||
" INSERT INTO t1 VALUES(1);"
|
||||
" SELECT 1 FROM DUAL;"
|
||||
" SELECT 2,3 FROM DUAL;"
|
||||
" INSERT INTO t1 VALUES(2);"
|
||||
" SELECT 3,4,5 FROM DUAL;"
|
||||
" SELECT 4,5,6,7 FROM DUAL;"
|
||||
"END");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr));
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
rc= mysql_stmt_execute(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
memset(bind, 0, sizeof(MYSQL_BIND) * 4);
|
||||
for (i=0; i < 4; i++)
|
||||
{
|
||||
bind[i].buffer_type= MYSQL_TYPE_LONG;
|
||||
bind[i].buffer= &l[i];
|
||||
}
|
||||
|
||||
rc= mysql_stmt_bind_result(stmt, bind);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
while (rc != MYSQL_NO_DATA)
|
||||
{
|
||||
rc= mysql_stmt_fetch(stmt);
|
||||
diag("l=%d", l[0]);
|
||||
}
|
||||
diag("next result");
|
||||
|
||||
rc= mysql_stmt_next_result(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
/* now rebind since we expect 2 columns */
|
||||
rc= mysql_stmt_bind_result(stmt, bind);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
while (rc != MYSQL_NO_DATA)
|
||||
{
|
||||
rc= mysql_stmt_fetch(stmt);
|
||||
diag("l=%d l=%d", l[0], l[1]);
|
||||
}
|
||||
|
||||
diag("next result");
|
||||
|
||||
rc= mysql_stmt_next_result(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
/* now rebind since we expect 2 columns */
|
||||
rc= mysql_stmt_bind_result(stmt, bind);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
while (rc != MYSQL_NO_DATA)
|
||||
{
|
||||
rc= mysql_stmt_fetch(stmt);
|
||||
diag("l=%d l=%d l=%d", l[0], l[1], l[2]);
|
||||
}
|
||||
|
||||
rc= mysql_stmt_close(stmt);
|
||||
|
||||
|
||||
rc= mysql_query(mysql, "DROP PROCEDURE p1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int test_query(MYSQL *mysql)
|
||||
{
|
||||
int rc;
|
||||
int counter= 0;
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[1];
|
||||
|
||||
char tmp[20];
|
||||
char *stmtstr= "CALL P1(?)";
|
||||
|
||||
rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19))"
|
||||
"BEGIN "
|
||||
" SET p_out = 'foo';"
|
||||
" SELECT 'foo' FROM DUAL;"
|
||||
" SELECT 'bar' FROM DUAL;"
|
||||
"END");
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr));
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
memset(bind, 0, sizeof(MYSQL_BIND));
|
||||
bind[0].buffer= tmp;
|
||||
bind[0].buffer_type= MYSQL_TYPE_STRING;
|
||||
bind[0].buffer_length= 4;
|
||||
|
||||
mysql_stmt_bind_param(stmt, bind);
|
||||
|
||||
rc= mysql_stmt_execute(stmt);
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
do {
|
||||
if (!mysql_stmt_store_result(stmt))
|
||||
{
|
||||
counter++;
|
||||
mysql_stmt_free_result(stmt);
|
||||
}
|
||||
} while (mysql_more_results(stmt->mysql) && mysql_next_result(stmt->mysql) == 0);
|
||||
|
||||
diag ("result sets: %d", counter);
|
||||
mysql_stmt_close(stmt);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
struct my_tests_st my_tests[] = {
|
||||
{"test_sp_params", test_sp_params, TEST_CONNECTION_NEW, CLIENT_MULTI_STATEMENTS, NULL , NULL},
|
||||
{"test_sp_reset", test_sp_reset, TEST_CONNECTION_NEW, CLIENT_MULTI_STATEMENTS, NULL , NULL},
|
||||
{"test_multi_result", test_multi_result, TEST_CONNECTION_NEW, CLIENT_MULTI_STATEMENTS, NULL , NULL},
|
||||
{"test_query", test_query, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS , NULL , NULL},
|
||||
{"test_sp_params", test_sp_params, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
|
||||
{"test_sp_reset", test_sp_reset, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
|
||||
{"test_sp_reset1", test_sp_reset1, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
|
||||
{"test_sp_reset2", test_sp_reset2, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
|
||||
{"test_multi_result", test_multi_result, TEST_CONNECTION_DEFAULT, CLIENT_MULTI_STATEMENTS, NULL , NULL},
|
||||
{NULL, NULL, 0, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user