mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Merge mysql.com:/home/pz/mysql/mysql-4.1-root
into mysql.com:/home/pz/mysql/mysql-4.1
This commit is contained in:
commit
d2aa1fb8e7
47 changed files with 1258 additions and 987 deletions
|
@ -57,6 +57,9 @@ typedef int my_socket;
|
|||
#include "mysql_com.h"
|
||||
#include "mysql_version.h"
|
||||
#include "typelib.h"
|
||||
#ifndef DBUG_OFF
|
||||
#define CHECK_EXTRA_ARGUMENTS
|
||||
#endif
|
||||
|
||||
extern unsigned int mysql_port;
|
||||
extern char *mysql_unix_port;
|
||||
|
@ -424,7 +427,7 @@ int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con,
|
|||
*/
|
||||
|
||||
/* statement state */
|
||||
enum MY_STMT_STATE { MY_ST_UNKNOWN, MY_ST_PREPARE, MY_ST_EXECUTE };
|
||||
enum PREP_STMT_STATE { MY_ST_UNKNOWN, MY_ST_PREPARE, MY_ST_EXECUTE };
|
||||
|
||||
/* bind structure */
|
||||
typedef struct st_mysql_bind
|
||||
|
@ -442,7 +445,7 @@ typedef struct st_mysql_bind
|
|||
my_bool long_ended; /* All data supplied for long */
|
||||
unsigned int param_number; /* For null count and error messages */
|
||||
void (*store_param_func)(NET *net, struct st_mysql_bind *param);
|
||||
char *(*fetch_result)(struct st_mysql_bind *, const char *row);
|
||||
void (*fetch_result)(struct st_mysql_bind *, unsigned char **row);
|
||||
} MYSQL_BIND;
|
||||
|
||||
|
||||
|
@ -462,10 +465,12 @@ typedef struct st_mysql_stmt
|
|||
unsigned long long_length; /* long buffer alloced length */
|
||||
unsigned long stmt_id; /* Id for prepared statement */
|
||||
unsigned int last_errno; /* error code */
|
||||
enum MY_STMT_STATE state; /* statement state */
|
||||
enum PREP_STMT_STATE state; /* statement state */
|
||||
char last_error[MYSQL_ERRMSG_SIZE]; /* error message */
|
||||
my_bool long_alloced; /* flag to indicate long alloced */
|
||||
my_bool types_supplied; /* to indicate types supply */
|
||||
my_bool send_types_to_server; /* to indicate types supply to server */
|
||||
my_bool param_buffers; /* to indicate the param bound buffers */
|
||||
my_bool res_buffers; /* to indicate the result bound buffers */
|
||||
} MYSQL_STMT;
|
||||
|
||||
|
||||
|
|
|
@ -312,6 +312,7 @@ void my_thread_end(void);
|
|||
#endif
|
||||
|
||||
#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
|
||||
#define MYSQL_STMT_HEADER 4
|
||||
#define MYSQL_LONG_DATA_HEADER 8
|
||||
|
||||
#endif
|
||||
|
|
|
@ -261,4 +261,5 @@
|
|||
#define ER_CORRUPT_HELP_DB 1242
|
||||
#define ER_CYCLIC_REFERENCE 1243
|
||||
#define ER_AUTO_CONVERT 1244
|
||||
#define ER_ERROR_MESSAGES 245
|
||||
#define ER_ILLEGAL_REFERENCE 1245
|
||||
#define ER_ERROR_MESSAGES 246
|
||||
|
|
|
@ -59,7 +59,7 @@ const char *client_errors[]=
|
|||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
"Can't send long data for non string or binary data types (parameter: %d)",
|
||||
"Using not supported parameter type: %d (parameter: %d)"
|
||||
"Using un supported parameter type: %d (parameter: %d)"
|
||||
"Shared memory (%lu)",
|
||||
"Can't open shared memory. Request event don't create (%lu)",
|
||||
"Can't open shared memory. Answer event don't create (%lu)",
|
||||
|
@ -113,7 +113,7 @@ const char *client_errors[]=
|
|||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
"Can't send long data for non string or binary data types (parameter: %d)",
|
||||
"Using not supported parameter type: %d (parameter: %d)"
|
||||
"Using un supported parameter type: %d (parameter: %d)"
|
||||
"Shared memory (%lu)",
|
||||
"Can't open shared memory. Request event don't create (%lu)",
|
||||
"Can't open shared memory. Answer event don't create (%lu)",
|
||||
|
@ -165,7 +165,7 @@ const char *client_errors[]=
|
|||
"No parameters exists in the statement",
|
||||
"Invalid parameter number",
|
||||
"Can't send long data for non string or binary data types (parameter: %d)",
|
||||
"Using not supported parameter type: %d (parameter: %d)"
|
||||
"Using un supported parameter type: %d (parameter: %d)"
|
||||
"Shared memory (%lu)",
|
||||
"Can't open shared memory. Request event don't create (%lu)",
|
||||
"Can't open shared memory. Answer event don't create (%lu)",
|
||||
|
|
|
@ -928,7 +928,7 @@ static const char *default_options[]=
|
|||
"connect-timeout", "local-infile", "disable-local-infile",
|
||||
"replication-probe", "enable-reads-from-master", "repl-parse-query",
|
||||
"ssl-cipher","protocol", "shared_memory_base_name",
|
||||
NullS
|
||||
NullS
|
||||
};
|
||||
|
||||
static TYPELIB option_types={array_elements(default_options)-1,
|
||||
|
@ -1740,7 +1740,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
|
|||
static void
|
||||
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
|
||||
{
|
||||
#ifdef HAVE_OPENSSL
|
||||
#ifdef HAVE_OPENSLL
|
||||
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
|
||||
|
@ -1754,7 +1754,7 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
|
|||
mysql->options.ssl_cipher= 0;
|
||||
mysql->options.use_ssl = FALSE;
|
||||
mysql->connector_fd = 0;
|
||||
#endif /* HAVE_OPENSSL */
|
||||
#endif /* HAVE_OPENSLL */
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -2645,7 +2645,7 @@ get_info:
|
|||
{
|
||||
mysql->affected_rows= net_field_length_ll(&pos);
|
||||
mysql->insert_id= net_field_length_ll(&pos);
|
||||
if (mysql->server_capabilities & CLIENT_PROTOCOL_41)
|
||||
if (protocol_41(mysql))
|
||||
{
|
||||
mysql->server_status=uint2korr(pos); pos+=2;
|
||||
mysql->warning_count=uint2korr(pos); pos+=2;
|
||||
|
@ -3728,10 +3728,10 @@ MYSQL_STMT *STDCALL
|
|||
mysql_prepare(MYSQL *mysql, const char *query, ulong length)
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
DBUG_ENTER("mysql_real_prepare");
|
||||
DBUG_ENTER("mysql_prepare");
|
||||
DBUG_ASSERT(mysql != 0);
|
||||
|
||||
#ifdef EXTRA_CHECK_ARGUMENTS
|
||||
#ifdef CHECK_EXTRA_ARGUMENTS
|
||||
if (!query)
|
||||
{
|
||||
set_mysql_error(mysql, CR_NULL_POINTER);
|
||||
|
@ -3752,7 +3752,6 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length)
|
|||
mysql_stmt_close(stmt);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
stmt->state= MY_ST_PREPARE;
|
||||
|
||||
init_alloc_root(&stmt->mem_root,8192,0);
|
||||
if (read_prepare_result(mysql, stmt))
|
||||
|
@ -3760,8 +3759,8 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length)
|
|||
mysql_stmt_close(stmt);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
stmt->mysql= mysql;
|
||||
stmt->state= MY_ST_PREPARE;
|
||||
stmt->mysql= mysql;
|
||||
DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
|
||||
DBUG_RETURN(stmt);
|
||||
}
|
||||
|
@ -3897,7 +3896,7 @@ static void store_param_str(NET *net, MYSQL_BIND *param)
|
|||
ulong length= *param->length;
|
||||
char *to= (char *) net_store_length((char *) net->write_pos, length);
|
||||
memcpy(to, param->buffer, length);
|
||||
net->write_pos+= length;
|
||||
net->write_pos= to+length;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3931,17 +3930,19 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
|
|||
MYSQL *mysql= stmt->mysql;
|
||||
NET *net = &mysql->net;
|
||||
DBUG_ENTER("store_param");
|
||||
DBUG_PRINT("enter",("type : %d, buffer :%lx", param->buffer_type,
|
||||
param->buffer));
|
||||
|
||||
/* Allocate for worst case (long string) */
|
||||
if ((my_realloc_str(net, 9 + *param->length)))
|
||||
return 1;
|
||||
if (!param->buffer)
|
||||
DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %d", param->buffer_type,
|
||||
param->buffer ? param->buffer : "0", *param->length));
|
||||
|
||||
if (param->is_null || param->buffer_type == MYSQL_TYPE_NULL)
|
||||
store_param_null(net, param);
|
||||
else
|
||||
{
|
||||
/* Allocate for worst case (long string) */
|
||||
if ((my_realloc_str(net, 9 + *param->length)))
|
||||
DBUG_RETURN(1);
|
||||
(*param->store_param_func)(net, param);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3953,13 +3954,13 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
|
|||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
NET *net= &mysql->net;
|
||||
char buff[4];
|
||||
char buff[MYSQL_STMT_HEADER];
|
||||
DBUG_ENTER("execute");
|
||||
DBUG_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length));
|
||||
|
||||
mysql->last_used_con= mysql;
|
||||
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
|
||||
if (advanced_command(mysql, COM_EXECUTE, buff, sizeof(buff), packet,
|
||||
if (advanced_command(mysql, COM_EXECUTE, buff, MYSQL_STMT_HEADER, packet,
|
||||
length, 1) ||
|
||||
mysql_read_query_result(mysql))
|
||||
{
|
||||
|
@ -3967,12 +3968,14 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
|
|||
DBUG_RETURN(1);
|
||||
}
|
||||
stmt->state= MY_ST_EXECUTE;
|
||||
|
||||
if (stmt->bind)
|
||||
mysql_free_result(stmt->result);
|
||||
#if USED_IN_FETCH
|
||||
if (stmt->res_buffers) /* Result buffers exists, cache results */
|
||||
{
|
||||
mysql_free_result(stmt->result);
|
||||
stmt->result= mysql_store_result(mysql);
|
||||
}
|
||||
#endif
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -3983,8 +3986,6 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
|
|||
|
||||
int STDCALL mysql_execute(MYSQL_STMT *stmt)
|
||||
{
|
||||
ulong length;
|
||||
uint null_count;
|
||||
DBUG_ENTER("mysql_execute");
|
||||
|
||||
if (stmt->state == MY_ST_UNKNOWN)
|
||||
|
@ -3998,14 +3999,18 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt)
|
|||
NET *net= &stmt->mysql->net;
|
||||
MYSQL_BIND *param, *param_end;
|
||||
char *param_data;
|
||||
my_bool result;
|
||||
ulong length;
|
||||
uint null_count;
|
||||
my_bool result;
|
||||
|
||||
if (!stmt->params)
|
||||
#ifdef CHECK_EXTRA_ARGUMENTS
|
||||
if (!stmt->param_buffers)
|
||||
{
|
||||
/* Parameters exists, but no bound buffers */
|
||||
set_stmt_error(stmt, CR_NOT_ALL_PARAMS_BOUND);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
#endif
|
||||
net_clear(net); /* Sets net->write_pos */
|
||||
/* Reserve place for null-marker bytes */
|
||||
null_count= (stmt->param_count+7) /8;
|
||||
|
@ -4014,10 +4019,9 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt)
|
|||
param_end= stmt->params + stmt->param_count;
|
||||
|
||||
/* In case if buffers (type) altered, indicate to server */
|
||||
*(net->write_pos)++= (uchar) stmt->types_supplied;
|
||||
if (!stmt->types_supplied)
|
||||
*(net->write_pos)++= (uchar) stmt->send_types_to_server;
|
||||
if (stmt->send_types_to_server)
|
||||
{
|
||||
stmt->types_supplied=1;
|
||||
/*
|
||||
Store types of parameters in first in first package
|
||||
that is sent to the server.
|
||||
|
@ -4031,21 +4035,22 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt)
|
|||
/* Check for long data which has not been propery given/terminated */
|
||||
if (param->is_long_data)
|
||||
{
|
||||
if (!param->long_ended)
|
||||
DBUG_RETURN(MYSQL_NEED_DATA);
|
||||
if (!param->long_ended)
|
||||
DBUG_RETURN(MYSQL_NEED_DATA);
|
||||
}
|
||||
else if (store_param(stmt, param))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
length= (ulong) (net->write_pos - net->buff);
|
||||
/* TODO: Look into avoding the following memdup */
|
||||
if (!(param_data= my_memdup((byte *) net->buff, length, MYF(0))))
|
||||
if (!(param_data= my_memdup( net->buff, length, MYF(0))))
|
||||
{
|
||||
set_stmt_error(stmt, CR_OUT_OF_MEMORY);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
net->write_pos= net->buff; /* Reset for net_write() */
|
||||
result= execute(stmt, param_data, length);
|
||||
stmt->send_types_to_server=0;
|
||||
my_free(param_data, MYF(MY_WME));
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
@ -4108,15 +4113,19 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
|
|||
param->param_number);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/*
|
||||
If param->length is not given, change it to point to bind_length.
|
||||
This way we can always use *param->length to get the length of data
|
||||
*/
|
||||
if (!param->length)
|
||||
param->length= ¶m->bind_length;
|
||||
|
||||
|
||||
/* Setup data copy functions for the different supported types */
|
||||
switch (param->buffer_type) {
|
||||
case MYSQL_TYPE_NULL:
|
||||
param->is_null=1;
|
||||
break;
|
||||
case MYSQL_TYPE_TINY:
|
||||
param->bind_length= 1;
|
||||
param->store_param_func= store_param_tinyint;
|
||||
|
@ -4138,12 +4147,13 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
|
|||
param->store_param_func= store_param_float;
|
||||
break;
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
param->bind_length= 4;
|
||||
param->bind_length= 8;
|
||||
param->store_param_func= store_param_double;
|
||||
break;
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_STRING:
|
||||
param->bind_length= param->buffer_length;
|
||||
|
@ -4156,7 +4166,8 @@ my_bool STDCALL mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND * bind)
|
|||
}
|
||||
}
|
||||
/* We have to send/resendtype information to MySQL */
|
||||
stmt->types_supplied= 0;
|
||||
stmt->send_types_to_server= 1;
|
||||
stmt->param_buffers= 1;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -4230,6 +4241,73 @@ mysql_send_long_data(MYSQL_STMT *stmt, uint param_number,
|
|||
Fetch-bind related implementations
|
||||
*********************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
Functions to fetch data to application buffers
|
||||
|
||||
All functions has the following characteristics:
|
||||
|
||||
SYNOPSIS
|
||||
fetch_result_xxx()
|
||||
param MySQL bind param
|
||||
row Row value
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 Error (Can't alloc net->buffer)
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row)
|
||||
{
|
||||
*param->buffer= (uchar) **row;
|
||||
*row++;
|
||||
}
|
||||
|
||||
static void fetch_result_short(MYSQL_BIND *param, uchar **row)
|
||||
{
|
||||
short value= *(short *)row;
|
||||
int2store(param->buffer, value);
|
||||
*row+=2;
|
||||
}
|
||||
|
||||
static void fetch_result_int32(MYSQL_BIND *param, uchar **row)
|
||||
{
|
||||
int32 value= *(int32 *)row;
|
||||
int4store(param->buffer, value);
|
||||
*row+=4;
|
||||
}
|
||||
|
||||
static void fetch_result_int64(MYSQL_BIND *param, uchar **row)
|
||||
{
|
||||
longlong value= *(longlong *)row;
|
||||
int8store(param->buffer, value);
|
||||
*row+=8;
|
||||
}
|
||||
|
||||
static void fetch_result_float(MYSQL_BIND *param, uchar **row)
|
||||
{
|
||||
float value;
|
||||
float4get(value,*row);
|
||||
float4store(param->buffer, *row);
|
||||
*row+=4;
|
||||
}
|
||||
|
||||
static void fetch_result_double(MYSQL_BIND *param, uchar **row)
|
||||
{
|
||||
double value;
|
||||
float8get(value,*row);
|
||||
float8store(param->buffer, value);
|
||||
*row+=8;
|
||||
}
|
||||
|
||||
static void fetch_result_str(MYSQL_BIND *param, uchar **row)
|
||||
{
|
||||
ulong length= net_field_length(row);
|
||||
memcpy(param->buffer, (char *)*row, length);
|
||||
*param->length= length;
|
||||
*row+=length;
|
||||
}
|
||||
|
||||
/*
|
||||
Setup the bind buffers for resultset processing
|
||||
*/
|
||||
|
@ -4241,21 +4319,62 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
|||
DBUG_ENTER("mysql_bind_result");
|
||||
DBUG_ASSERT(stmt != 0);
|
||||
|
||||
#ifdef EXTRA_CHECK_ARGUMENTS
|
||||
#ifdef CHECK_EXTRA_ARGUMENTS
|
||||
if (!bind)
|
||||
{
|
||||
set_stmt_error(stmt, CR_NULL_POINTER);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
#endif
|
||||
bind_count= stmt->result->field_count;
|
||||
bind_count= stmt->field_count;
|
||||
memcpy((char*) stmt->bind, (char*) bind,
|
||||
sizeof(MYSQL_BIND)*bind_count);
|
||||
|
||||
for (param= stmt->bind, end= param+bind_count; param < end ; param++)
|
||||
{
|
||||
/* TODO: Set up convert functions like in mysql_bind_param */
|
||||
/* Setup data copy functions for the different supported types */
|
||||
switch (param->buffer_type) {
|
||||
case MYSQL_TYPE_TINY:
|
||||
param->bind_length= 1;
|
||||
param->fetch_result= fetch_result_tinyint;
|
||||
break;
|
||||
case MYSQL_TYPE_SHORT:
|
||||
param->bind_length= 2;
|
||||
param->fetch_result= fetch_result_short;
|
||||
break;
|
||||
case MYSQL_TYPE_LONG:
|
||||
param->bind_length= 4;
|
||||
param->fetch_result= fetch_result_int32;
|
||||
break;
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
param->bind_length= 8;
|
||||
param->fetch_result= fetch_result_int64;
|
||||
break;
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
param->bind_length= 4;
|
||||
param->fetch_result= fetch_result_float;
|
||||
break;
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
param->bind_length= 8;
|
||||
param->fetch_result= fetch_result_double;
|
||||
break;
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_STRING:
|
||||
param->length= ¶m->buffer_length;
|
||||
param->fetch_result= fetch_result_str;
|
||||
break;
|
||||
default:
|
||||
sprintf(stmt->last_error, ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
|
||||
param->buffer_type, param->param_number);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (!param->length)
|
||||
param->length= ¶m->bind_length;
|
||||
}
|
||||
stmt->res_buffers= 1;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -4265,16 +4384,16 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
|||
*/
|
||||
|
||||
static my_bool
|
||||
my_fetch_row(MYSQL_STMT *stmt, MYSQL_RES *result, const byte *row)
|
||||
stmt_fetch_row(MYSQL_STMT *stmt, uchar **row)
|
||||
{
|
||||
MYSQL_BIND *bind, *end;
|
||||
uchar *null_ptr= (uchar*) row, bit;
|
||||
|
||||
result->row_count++;
|
||||
row+= (result->field_count+7)/8;
|
||||
/* Copy complete row to application buffers */
|
||||
uchar *null_ptr= (uchar*) *row, bit;
|
||||
|
||||
*row+= (stmt->field_count+7)/8;
|
||||
bit=1;
|
||||
for (bind= stmt->bind, end= (MYSQL_BIND *) bind + result->field_count;
|
||||
|
||||
/* Copy complete row to application buffers */
|
||||
for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count;
|
||||
bind < end;
|
||||
bind++)
|
||||
{
|
||||
|
@ -4283,7 +4402,7 @@ my_fetch_row(MYSQL_STMT *stmt, MYSQL_RES *result, const byte *row)
|
|||
else
|
||||
{
|
||||
bind->is_null= 0;
|
||||
row= (byte*) (*bind->fetch_result)(bind, (char*) row);
|
||||
(*bind->fetch_result)(bind, row);
|
||||
}
|
||||
if (! (bit<<=1) & 255)
|
||||
{
|
||||
|
@ -4294,12 +4413,9 @@ my_fetch_row(MYSQL_STMT *stmt, MYSQL_RES *result, const byte *row)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_binary_data(MYSQL *mysql)
|
||||
{
|
||||
ulong pkt_len;
|
||||
if ((pkt_len= net_safe_read(mysql)) == packet_error)
|
||||
static int read_binary_data(MYSQL *mysql)
|
||||
{
|
||||
if (packet_error == net_safe_read(mysql))
|
||||
return -1;
|
||||
if (mysql->net.read_pos[0])
|
||||
return 1; /* End of data */
|
||||
|
@ -4313,57 +4429,30 @@ read_binary_data(MYSQL *mysql)
|
|||
|
||||
int STDCALL mysql_fetch(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
DBUG_ENTER("mysql_fetch");
|
||||
|
||||
result= stmt->result;
|
||||
if (!result)
|
||||
DBUG_RETURN(MYSQL_NO_DATA);
|
||||
|
||||
if (!result->data)
|
||||
if (stmt->res_buffers)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
if (!result->eof)
|
||||
int res;
|
||||
if (!(res= read_binary_data(mysql)))
|
||||
{
|
||||
int res;
|
||||
if (!(res= read_binary_data(result->handle)))
|
||||
DBUG_RETURN((int) my_fetch_row(stmt, result,
|
||||
(byte*) mysql->net.read_pos+1));
|
||||
DBUG_PRINT("info", ("end of data"));
|
||||
result->eof= 1;
|
||||
result->handle->status= MYSQL_STATUS_READY;
|
||||
|
||||
/* Don't clear handle in mysql_free_results */
|
||||
result->handle= 0;
|
||||
if (res < 0) /* Network error */
|
||||
{
|
||||
set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
|
||||
mysql->net.last_errno);
|
||||
DBUG_RETURN(MYSQL_STATUS_ERROR);
|
||||
}
|
||||
if (stmt->res_buffers)
|
||||
DBUG_RETURN((int) stmt_fetch_row(stmt,(uchar **) &mysql->net.read_pos+1));
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
DBUG_PRINT("info", ("end of data"));
|
||||
mysql->status= MYSQL_STATUS_READY;
|
||||
|
||||
if (res < 0) /* Network error */
|
||||
{
|
||||
set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
|
||||
mysql->net.last_errno);
|
||||
DBUG_RETURN(MYSQL_STATUS_ERROR);
|
||||
}
|
||||
DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
|
||||
}
|
||||
{
|
||||
/*
|
||||
For prepared statements, the row data is a string of binary bytes,
|
||||
not a set of string pointers as for normal statements
|
||||
It's however convenient to use the data pointer also for prepared
|
||||
statements.
|
||||
*/
|
||||
MYSQL_ROW values;
|
||||
if (!result->data_cursor)
|
||||
{
|
||||
DBUG_PRINT("info", ("end of data"));
|
||||
result->current_row= (MYSQL_ROW) NULL;
|
||||
DBUG_RETURN(MYSQL_NO_DATA);
|
||||
}
|
||||
values= result->data_cursor->data;
|
||||
result->data_cursor= result->data_cursor->next;
|
||||
|
||||
DBUG_RETURN((int) my_fetch_row(stmt,result, (byte*) values));
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(0); //?? do we need to set MYSQL_STATUS_READY ?
|
||||
}
|
||||
|
||||
|
||||
|
@ -4380,17 +4469,15 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
|
|||
my_bool error=0;
|
||||
DBUG_ENTER("mysql_stmt_close");
|
||||
|
||||
if (stmt->state)
|
||||
if (stmt->state != MY_ST_UNKNOWN)
|
||||
{
|
||||
char buff[4];
|
||||
int4store(buff, stmt->stmt_id);
|
||||
error= simple_command(stmt->mysql, COM_CLOSE_STMT, buff, 4, 0);
|
||||
}
|
||||
|
||||
mysql_free_result(stmt->result);
|
||||
free_root(&stmt->mem_root, MYF(0));
|
||||
my_free((gptr) stmt->query, MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
||||
my_free((gptr) stmt->bind, MY_ALLOW_ZERO_PTR);
|
||||
my_free((gptr) stmt->params, MY_ALLOW_ZERO_PTR);
|
||||
my_free((gptr) stmt, MYF(MY_WME));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
|
|
@ -102,8 +102,24 @@ EXPORTS
|
|||
mysql_add_slave
|
||||
mysql_warning_count
|
||||
mysql_warnings
|
||||
|
||||
|
||||
mysql_prepare
|
||||
mysql_execute
|
||||
mysql_param_count
|
||||
mysql_bind_param
|
||||
mysql_bind_result
|
||||
mysql_prepare_result
|
||||
mysql_stmt_close
|
||||
mysql_stmt_error
|
||||
mysql_stmt_errno
|
||||
mysql_fetch
|
||||
mysql_send_long_data
|
||||
mysql_multi_query
|
||||
mysql_next_result
|
||||
mysql_commit
|
||||
mysql_rollback
|
||||
mysql_autocommit
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -9,9 +9,14 @@ SELECT (SELECT (SELECT 0 UNION SELECT 0));
|
|||
(SELECT (SELECT 0 UNION SELECT 0))
|
||||
0
|
||||
SELECT (SELECT 1 FROM (SELECT 1) HAVING a=1) as a;
|
||||
Cyclic reference on subqueries
|
||||
Reference 'a' not supported (forward reference in item list)
|
||||
SELECT (SELECT 1 FROM (SELECT 1) HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) HAVING a=1) as b;
|
||||
Cyclic reference on subqueries
|
||||
Reference 'b' not supported (forward reference in item list)
|
||||
SELECT (SELECT 1),MAX(1) FROM (SELECT 1);
|
||||
(SELECT 1) MAX(1)
|
||||
1 1
|
||||
SELECT (SELECT a) as a;
|
||||
Reference 'a' not supported (forward reference in item list)
|
||||
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int, b int);
|
||||
|
@ -20,6 +25,8 @@ create table t4 (a int, b int);
|
|||
insert into t1 values (2);
|
||||
insert into t2 values (1,7),(2,7);
|
||||
insert into t4 values (4,8),(3,8),(5,9);
|
||||
select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1;
|
||||
Reference 'a1' not supported (forward reference in item list)
|
||||
select (select a from t1 where t1.a=t2.a), a from t2;
|
||||
(select a from t1 where t1.a=t2.a) a
|
||||
NULL 1
|
||||
|
@ -278,6 +285,12 @@ PRIMARY KEY (`numeropost`,`numreponse`),
|
|||
UNIQUE KEY `numreponse` (`numreponse`),
|
||||
KEY `pseudo` (`pseudo`,`numeropost`)
|
||||
) TYPE=MyISAM;
|
||||
SELECT (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=a),numreponse FROM (SELECT * FROM threadhardwarefr7) as a;
|
||||
Reference 'numreponse' not supported (forward reference in item list)
|
||||
SELECT numreponse, (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=a) FROM (SELECT * FROM threadhardwarefr7) as a;
|
||||
Unknown column 'a' in 'having clause'
|
||||
SELECT numreponse, (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=1) FROM (SELECT * FROM threadhardwarefr7) as a;
|
||||
numreponse (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=1)
|
||||
INSERT INTO threadhardwarefr7 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test');
|
||||
EXPLAIN SELECT numreponse FROM threadhardwarefr7 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM threadhardwarefr7 WHERE numeropost='1');
|
||||
Subselect returns more than 1 record
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
select (select 2);
|
||||
SELECT (SELECT 1) UNION SELECT (SELECT 2);
|
||||
SELECT (SELECT (SELECT 0 UNION SELECT 0));
|
||||
-- error 1243
|
||||
-- error 1245
|
||||
SELECT (SELECT 1 FROM (SELECT 1) HAVING a=1) as a;
|
||||
-- error 1243
|
||||
-- error 1245
|
||||
SELECT (SELECT 1 FROM (SELECT 1) HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) HAVING a=1) as b;
|
||||
SELECT (SELECT 1),MAX(1) FROM (SELECT 1);
|
||||
-- error 1245
|
||||
SELECT (SELECT a) as a;
|
||||
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int, b int);
|
||||
|
@ -13,6 +16,8 @@ create table t4 (a int, b int);
|
|||
insert into t1 values (2);
|
||||
insert into t2 values (1,7),(2,7);
|
||||
insert into t4 values (4,8),(3,8),(5,9);
|
||||
-- error 1245
|
||||
select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1;
|
||||
select (select a from t1 where t1.a=t2.a), a from t2;
|
||||
select (select a from t1 where t1.a=t2.b), a from t2;
|
||||
select (select a from t1), a from t2;
|
||||
|
@ -176,6 +181,11 @@ CREATE TABLE `threadhardwarefr7` (
|
|||
UNIQUE KEY `numreponse` (`numreponse`),
|
||||
KEY `pseudo` (`pseudo`,`numeropost`)
|
||||
) TYPE=MyISAM;
|
||||
-- error 1245
|
||||
SELECT (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=a),numreponse FROM (SELECT * FROM threadhardwarefr7) as a;
|
||||
-- error 1054
|
||||
SELECT numreponse, (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=a) FROM (SELECT * FROM threadhardwarefr7) as a;
|
||||
SELECT numreponse, (SELECT numeropost FROM threadhardwarefr7 HAVING numreponse=1) FROM (SELECT * FROM threadhardwarefr7) as a;
|
||||
INSERT INTO threadhardwarefr7 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test');
|
||||
-- error 1240
|
||||
EXPLAIN SELECT numreponse FROM threadhardwarefr7 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM threadhardwarefr7 WHERE numeropost='1');
|
||||
|
|
63
sql/item.cc
63
sql/item.cc
|
@ -34,7 +34,8 @@ void item_init(void)
|
|||
item_user_lock_init();
|
||||
}
|
||||
|
||||
Item::Item()
|
||||
Item::Item():
|
||||
fixed(0)
|
||||
{
|
||||
marker=0;
|
||||
maybe_null=null_value=with_sum_func=unsigned_flag=0;
|
||||
|
@ -139,6 +140,7 @@ CHARSET_INFO * Item::thd_charset() const
|
|||
Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
|
||||
{
|
||||
set_field(f);
|
||||
fixed= 1; // This item is not needed in fix_fields
|
||||
}
|
||||
|
||||
|
||||
|
@ -315,32 +317,27 @@ void Item_param::set_null()
|
|||
void Item_param::set_int(longlong i)
|
||||
{
|
||||
int_value=(longlong)i;
|
||||
item_result_type = INT_RESULT;
|
||||
item_type = INT_ITEM;
|
||||
}
|
||||
|
||||
void Item_param::set_double(double value)
|
||||
{
|
||||
real_value=value;
|
||||
item_result_type = REAL_RESULT;
|
||||
item_type = REAL_ITEM;
|
||||
}
|
||||
|
||||
|
||||
void Item_param::set_value(const char *str, uint length, CHARSET_INFO *cs)
|
||||
void Item_param::set_value(const char *str, uint length)
|
||||
{
|
||||
str_value.set(str,length,cs);
|
||||
item_result_type = STRING_RESULT;
|
||||
str_value.set(str,length,thd_charset());
|
||||
item_type = STRING_ITEM;
|
||||
}
|
||||
|
||||
|
||||
void Item_param::set_longdata(const char *str, ulong length, CHARSET_INFO *cs)
|
||||
{
|
||||
/* TODO: Fix this for binary handling by making use of
|
||||
buffer_type..
|
||||
*/
|
||||
str_value.append(str,length);
|
||||
void Item_param::set_longdata(const char *str, ulong length)
|
||||
{
|
||||
str_value.append(str,length);
|
||||
long_data_supplied= 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -438,6 +435,7 @@ bool Item::fix_fields(THD *thd,
|
|||
struct st_table_list *list,
|
||||
Item ** ref)
|
||||
{
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -459,23 +457,48 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
*/
|
||||
SELECT_LEX *last= 0;
|
||||
|
||||
Item **refer= (Item **)not_found_item;
|
||||
// Prevent using outer fields in subselects, that is not supported now
|
||||
if (thd->lex.current_select->linkage != DERIVED_TABLE_TYPE)
|
||||
for (SELECT_LEX *sl= thd->lex.current_select->outer_select();
|
||||
sl;
|
||||
sl= sl->outer_select())
|
||||
{
|
||||
if ((tmp= find_field_in_tables(thd, this,
|
||||
(last= sl)->get_table_list(),
|
||||
0)) != not_found_field)
|
||||
break;
|
||||
if((refer= find_item_in_list(this, (last= sl)->item_list,
|
||||
REPORT_EXCEPT_NOT_FOUND)) !=
|
||||
(Item **)not_found_item)
|
||||
break;
|
||||
|
||||
}
|
||||
if (!tmp)
|
||||
return -1;
|
||||
else if (tmp == not_found_field)
|
||||
else if (!refer)
|
||||
return 1;
|
||||
else if (tmp == not_found_field && refer == (Item **)not_found_item)
|
||||
{
|
||||
// call to return error code
|
||||
find_field_in_tables(thd, this, tables, 1);
|
||||
return -1;
|
||||
}
|
||||
else if (refer != (Item **)not_found_item)
|
||||
{
|
||||
Item_ref *r;
|
||||
*ref= r= new Item_ref((char *)db_name, (char *)table_name,
|
||||
(char *)field_name);
|
||||
if (!r)
|
||||
return 1;
|
||||
int res;
|
||||
if ((res= r->fix_fields(thd, tables, ref)))
|
||||
return res;
|
||||
r->depended_from= last;
|
||||
thd->lex.current_select->mark_as_dependent(last);
|
||||
thd->add_possible_loop(r);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
depended_from= last;
|
||||
|
@ -507,6 +530,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
return 1;
|
||||
return (*ref)->fix_fields(thd, tables, ref);
|
||||
}
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -885,6 +909,19 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
|||
maybe_null= (*ref)->maybe_null;
|
||||
decimals= (*ref)->decimals;
|
||||
}
|
||||
if (((*ref)->with_sum_func &&
|
||||
(depended_from ||
|
||||
!(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE &&
|
||||
thd->lex.current_select->select_lex()->having_fix_field))) ||
|
||||
!(*ref)->fixed)
|
||||
{
|
||||
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
|
||||
((*ref)->with_sum_func?
|
||||
"reference on group function":
|
||||
"forward reference in item list"));
|
||||
return 1;
|
||||
}
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
18
sql/item.h
18
sql/item.h
|
@ -46,6 +46,7 @@ public:
|
|||
my_bool null_value; /* if item is null */
|
||||
my_bool unsigned_flag;
|
||||
my_bool with_sum_func;
|
||||
my_bool fixed; /* If item fixed with fix_fields */
|
||||
|
||||
// alloc & destruct is done as start of select using sql_alloc
|
||||
Item();
|
||||
|
@ -186,8 +187,8 @@ public:
|
|||
Item_param(char *name_par=0)
|
||||
{
|
||||
name= name_par ? name_par : (char*) "?";
|
||||
long_data_supplied = false;
|
||||
item_type = STRING_ITEM;
|
||||
long_data_supplied= false;
|
||||
item_type= STRING_ITEM;
|
||||
item_result_type = STRING_RESULT;
|
||||
}
|
||||
enum Type type() const { return item_type; }
|
||||
|
@ -199,12 +200,13 @@ public:
|
|||
void set_null();
|
||||
void set_int(longlong i);
|
||||
void set_double(double i);
|
||||
void set_value(const char *str, uint length, CHARSET_INFO *cs);
|
||||
void set_long_str(const char *str, ulong length, CHARSET_INFO *cs);
|
||||
void set_long_binary(const char *str, ulong length, CHARSET_INFO *cs);
|
||||
void set_longdata(const char *str, ulong length, CHARSET_INFO *cs);
|
||||
void set_value(const char *str, uint length);
|
||||
void set_long_str(const char *str, ulong length);
|
||||
void set_long_binary(const char *str, ulong length);
|
||||
void set_longdata(const char *str, ulong length);
|
||||
void set_long_end();
|
||||
void reset() {}
|
||||
void (*setup_param_func)(Item_param *param, uchar **pos);
|
||||
enum Item_result result_type () const
|
||||
{ return item_result_type; }
|
||||
Item *new_item() { return new Item_param(name); }
|
||||
|
@ -401,8 +403,8 @@ public:
|
|||
:Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
|
||||
enum Type type() const { return REF_ITEM; }
|
||||
bool eq(const Item *item, bool binary_cmp) const
|
||||
{ return (*ref)->eq(item, binary_cmp); }
|
||||
~Item_ref() { if (ref) delete *ref; }
|
||||
{ return ref && (*ref)->eq(item, binary_cmp); }
|
||||
~Item_ref() { if (ref && (*ref) != this) delete *ref; }
|
||||
double val()
|
||||
{
|
||||
double tmp=(*ref)->val_result();
|
||||
|
|
|
@ -1160,6 +1160,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
if (thd)
|
||||
thd->cond_count+=list.elements;
|
||||
fix_length_and_dec();
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1485,6 +1486,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
}
|
||||
else
|
||||
maybe_null=1;
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
}
|
||||
}
|
||||
fix_length_and_dec();
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -754,6 +754,7 @@ public:
|
|||
bool res= udf.fix_fields(thd, tables, this, arg_count, args);
|
||||
used_tables_cache= udf.used_tables_cache;
|
||||
const_item_cache= udf.const_item_cache;
|
||||
fixed= 1;
|
||||
return res;
|
||||
}
|
||||
Item_result result_type () const { return udf.result_type(); }
|
||||
|
|
|
@ -2079,6 +2079,7 @@ bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables, I
|
|||
const_item_cache=args[0]->const_item();
|
||||
set_charset(conv_charset);
|
||||
fix_length_and_dec();
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2113,6 +2114,7 @@ bool Item_func_set_collation::fix_fields(THD *thd,struct st_table_list *tables,
|
|||
used_tables_cache=args[0]->used_tables();
|
||||
const_item_cache=args[0]->const_item();
|
||||
fix_length_and_dec();
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
}
|
||||
fix_length_and_dec();
|
||||
}
|
||||
fixed= 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
null_value=1;
|
||||
fix_length_and_dec();
|
||||
thd->allow_sum_func=1; // Allow group functions
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -165,6 +166,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
null_value=1;
|
||||
fix_length_and_dec();
|
||||
thd->allow_sum_func=1; // Allow group functions
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -384,6 +384,7 @@ public:
|
|||
const char *func_name() const { return udf.name(); }
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
fixed= 1;
|
||||
return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
|
||||
}
|
||||
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
|
||||
|
|
|
@ -43,5 +43,9 @@ public:
|
|||
bool add() { return 0; }
|
||||
void reset_field() {}
|
||||
void update_field(int offset) {}
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { return 0;}
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
{
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -513,7 +513,7 @@ int mysqld_show_column_types(THD *thd);
|
|||
int mysqld_help (THD *thd, const char *text);
|
||||
|
||||
/* sql_prepare.cc */
|
||||
int compare_prep_stmt(PREP_STMT *a, PREP_STMT *b, void *not_used);
|
||||
int compare_prep_stmt(void *not_used, PREP_STMT *stmt, ulong *key);
|
||||
void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used);
|
||||
bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length);
|
||||
void mysql_stmt_execute(THD *thd, char *packet);
|
||||
|
|
|
@ -254,4 +254,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -248,4 +248,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -256,4 +256,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -245,4 +245,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -250,4 +250,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -245,4 +245,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -248,4 +248,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -245,4 +245,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -247,4 +247,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -245,4 +245,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -247,4 +247,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -245,4 +245,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -247,4 +247,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -247,4 +247,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -249,4 +249,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -245,4 +245,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -250,3 +250,4 @@
|
|||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -248,4 +248,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"ãÉËÌÉÞÅÓËÁÑ ÓÓÙÌËÁ ÎÁ ÐÏÄÚÁÐÒÏÓ",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Преобразование поля '%s' из %s в %s",
|
||||
"Ссылка '%-.64s' не поддерживается (%s)",
|
||||
|
|
|
@ -241,4 +241,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -253,4 +253,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -246,4 +246,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"Cyclic reference on subqueries",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Converting column '%s' from %s to %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -245,4 +245,5 @@
|
|||
"Okänd PREPARED STATEMENT id (%ld) var given till %s",
|
||||
"Hjälp databasen finns inte eller är skadad",
|
||||
"Syklisk referens i subselect",
|
||||
"Konvertar kolumn '%s' från %s till %s"
|
||||
"Konvertar kolumn '%s' från %s till %s",
|
||||
"Reference '%-.64s' not supported (%s)",
|
||||
|
|
|
@ -250,4 +250,5 @@
|
|||
"Unknown prepared statement handler (%ld) given to %s",
|
||||
"Help database is corrupt or does not exist",
|
||||
"ãÉËÌiÞÎÅ ÐÏÓÉÌÁÎÎÑ ÎÁ ÐiÄÚÁÐÉÔ",
|
||||
"Converting column '%s' from %s to %s"
|
||||
"Перетворення стовбца '%s' з %s у %s",
|
||||
"Посилання '%-.64s' не пiдтримуется (%s)",
|
||||
|
|
|
@ -2225,8 +2225,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
|||
{
|
||||
DBUG_ENTER("setup_conds");
|
||||
thd->set_query_id=1;
|
||||
thd->cond_count=0;
|
||||
thd->allow_sum_func=0;
|
||||
|
||||
thd->cond_count= 0;
|
||||
bool save_allow_sum_func= thd->allow_sum_func;
|
||||
thd->allow_sum_func= 0;
|
||||
if (*conds)
|
||||
{
|
||||
thd->where="where clause";
|
||||
|
@ -2299,6 +2301,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
|||
table->on_expr=and_conds(table->on_expr,cond_and);
|
||||
}
|
||||
}
|
||||
thd->allow_sum_func= save_allow_sum_func;
|
||||
DBUG_RETURN(test(thd->fatal_error));
|
||||
}
|
||||
|
||||
|
|
|
@ -325,7 +325,7 @@ typedef struct st_prep_stmt
|
|||
uint param_count;
|
||||
uint last_errno;
|
||||
char last_error[MYSQL_ERRMSG_SIZE];
|
||||
bool error_in_prepare, long_data_used;
|
||||
bool error_in_prepare, long_data_used, param_inited;
|
||||
} PREP_STMT;
|
||||
|
||||
|
||||
|
@ -510,7 +510,6 @@ public:
|
|||
bool safe_to_cache_query;
|
||||
bool volatile killed;
|
||||
bool prepare_command;
|
||||
Item_param *params; // Pointer to array of params
|
||||
|
||||
/*
|
||||
If we do a purge of binary logs, log index info of the threads
|
||||
|
|
|
@ -127,7 +127,7 @@ static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
|
|||
my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
|
||||
{
|
||||
List<Item> field_list;
|
||||
DBUG_ENTER("mysqld_show_errors");
|
||||
DBUG_ENTER("mysqld_show_warnings");
|
||||
|
||||
field_list.push_back(new Item_empty_string("Level", 7));
|
||||
field_list.push_back(new Item_int("Code",0,4));
|
||||
|
|
|
@ -30,10 +30,11 @@ Prepare:
|
|||
Prepare-execute:
|
||||
|
||||
- Server gets the command 'COM_EXECUTE' to execute the
|
||||
previously prepared query.
|
||||
- If there is are any parameters, then replace the markers with the
|
||||
data supplied by client with the following format:
|
||||
[types_specified(0/1)][type][length][data] .. [type][length]..
|
||||
previously prepared query. If there is any param markers; then client
|
||||
will send the data in the following format:
|
||||
[null_bits][types_specified(0/1)][[length][data]][[length][data] .. [length][data].
|
||||
- Replace the param items with this new data. If it is a first execute
|
||||
or types altered by client; then setup the conversion routines.
|
||||
- Execute the query without re-parsing and send back the results
|
||||
to client
|
||||
|
||||
|
@ -53,33 +54,9 @@ Long data handling:
|
|||
#include <assert.h> // for DEBUG_ASSERT()
|
||||
#include <m_ctype.h> // for isspace()
|
||||
|
||||
extern int yyparse(void);
|
||||
static ulong get_param_length(uchar **packet);
|
||||
static uint get_buffer_type(uchar **packet);
|
||||
static bool param_is_null(uchar **packet);
|
||||
static bool setup_param_fields(THD *thd,List<Item> ¶ms);
|
||||
static uchar* setup_param_field(Item_param *item_param, uchar *pos,
|
||||
uint buffer_type);
|
||||
static void setup_longdata_field(Item_param *item_param, uchar *pos);
|
||||
static bool setup_longdata(THD *thd,List<Item> ¶ms);
|
||||
static bool send_prepare_results(PREP_STMT *stmt);
|
||||
static bool parse_prepare_query(PREP_STMT *stmt, char *packet, uint length);
|
||||
static bool mysql_send_insert_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
|
||||
List<Item> &fields,
|
||||
List<List_item> &values_list,
|
||||
thr_lock_type lock_type);
|
||||
static bool mysql_test_insert_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
|
||||
List<Item> &fields,
|
||||
List<List_item> &values_list,
|
||||
thr_lock_type lock_type);
|
||||
static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
|
||||
List<Item> &fields, List<Item> &values,
|
||||
COND *conds,thr_lock_type lock_type);
|
||||
static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|
||||
List<Item> &fields, List<Item> &values,
|
||||
COND *conds, ORDER *order, ORDER *group,
|
||||
Item *having,thr_lock_type lock_type);
|
||||
#define IS_PARAM_NULL(pos, param_no) pos[param_no/8] & (1 << param_no & 7)
|
||||
|
||||
extern int yyparse(void);
|
||||
|
||||
/*
|
||||
Find prepared statement in thd
|
||||
|
@ -114,9 +91,9 @@ static PREP_STMT *find_prepared_statement(THD *thd, ulong stmt_id,
|
|||
Compare two prepared statements; Used to find a prepared statement
|
||||
*/
|
||||
|
||||
int compare_prep_stmt(PREP_STMT *a, PREP_STMT *b, void *not_used)
|
||||
int compare_prep_stmt(void *not_used, PREP_STMT *stmt, ulong *key)
|
||||
{
|
||||
return (a->stmt_id < b->stmt_id) ? -1 : (a->stmt_id == b->stmt_id) ? 0 : 1;
|
||||
return (stmt->stmt_id == *key) ? 0 : (stmt->stmt_id < *key) ? -1 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -132,22 +109,23 @@ int compare_prep_stmt(PREP_STMT *a, PREP_STMT *b, void *not_used)
|
|||
*/
|
||||
|
||||
void free_prep_stmt(PREP_STMT *stmt, TREE_FREE mode, void *not_used)
|
||||
{
|
||||
free_root(&stmt->mem_root, MYF(0));
|
||||
{
|
||||
free_items(stmt->free_list);
|
||||
free_root(&stmt->mem_root, MYF(0));
|
||||
}
|
||||
|
||||
/*
|
||||
Send prepared stmt info to client after prepare
|
||||
*/
|
||||
|
||||
bool send_prep_stmt(PREP_STMT *stmt, uint columns)
|
||||
static bool send_prep_stmt(PREP_STMT *stmt, uint columns)
|
||||
{
|
||||
NET *net=&stmt->thd->net;
|
||||
char buff[8];
|
||||
int4store(buff, stmt->stmt_id);
|
||||
int2store(buff+4, columns);
|
||||
int2store(buff+6, stmt->param_count);
|
||||
return my_net_write(&stmt->thd->net, buff, sizeof(buff));
|
||||
return (my_net_write(net, buff, sizeof(buff)) || net_flush(net));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -156,43 +134,15 @@ bool send_prep_stmt(PREP_STMT *stmt, uint columns)
|
|||
TODO: Not yet ready
|
||||
*/
|
||||
|
||||
bool send_item_params(PREP_STMT *stmt)
|
||||
static bool send_item_params(PREP_STMT *stmt)
|
||||
{
|
||||
#if 0
|
||||
char buff[1];
|
||||
buff[0]=0;
|
||||
return my_net_write(&stmt->thd->net, buff, sizeof(buff));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Read the buffer type, this happens only first time
|
||||
*/
|
||||
|
||||
static uint get_buffer_type(uchar **packet)
|
||||
{
|
||||
reg1 uchar *pos= *packet;
|
||||
(*packet)+= 2;
|
||||
return (uint) uint2korr(pos);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check for NULL param data
|
||||
|
||||
RETURN VALUES
|
||||
0 Value was not NULL
|
||||
1 Value was NULL
|
||||
*/
|
||||
|
||||
static bool param_is_null(uchar **packet)
|
||||
{
|
||||
reg1 uchar *pos= *packet;
|
||||
if (*pos == 251)
|
||||
{
|
||||
(*packet)++;
|
||||
if (my_net_write(&stmt->thd->net, buff, sizeof(buff)))
|
||||
return 1;
|
||||
}
|
||||
send_eof(stmt->thd);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -222,60 +172,103 @@ static ulong get_param_length(uchar **packet)
|
|||
(*packet)+=9; // Must be 254 when here
|
||||
return (ulong) uint4korr(pos+1);
|
||||
}
|
||||
/*
|
||||
Setup param conversion routines
|
||||
|
||||
/*
|
||||
Read and return the data for parameters supplied by client
|
||||
setup_param_xx()
|
||||
param Parameter Item
|
||||
pos Input data buffer
|
||||
|
||||
All these functions reads the data from pos and sets up that data
|
||||
through 'param' and advances the buffer position to predifined
|
||||
length position.
|
||||
|
||||
Make a note that the NULL handling is examined at first execution
|
||||
(i.e. when input types altered) and for all subsequent executions
|
||||
we don't read any values for this.
|
||||
|
||||
RETURN VALUES
|
||||
|
||||
*/
|
||||
|
||||
static uchar* setup_param_field(Item_param *item_param,
|
||||
uchar *pos, uint buffer_type)
|
||||
static void setup_param_tiny(Item_param *param, uchar **pos)
|
||||
{
|
||||
if (param_is_null(&pos))
|
||||
{
|
||||
item_param->set_null();
|
||||
return(pos);
|
||||
}
|
||||
switch (buffer_type) {
|
||||
param->set_int((longlong)(**pos));
|
||||
*pos+= 1;
|
||||
}
|
||||
|
||||
static void setup_param_short(Item_param *param, uchar **pos)
|
||||
{
|
||||
param->set_int((longlong)sint2korr(*pos));
|
||||
*pos+= 2;
|
||||
}
|
||||
|
||||
static void setup_param_int32(Item_param *param, uchar **pos)
|
||||
{
|
||||
param->set_int((longlong)sint4korr(*pos));
|
||||
*pos+= 4;
|
||||
}
|
||||
|
||||
static void setup_param_int64(Item_param *param, uchar **pos)
|
||||
{
|
||||
param->set_int((longlong)sint8korr(*pos));
|
||||
*pos+= 8;
|
||||
}
|
||||
|
||||
static void setup_param_float(Item_param *param, uchar **pos)
|
||||
{
|
||||
float data;
|
||||
float4get(data,*pos);
|
||||
param->set_double((double) data);
|
||||
*pos+= 4;
|
||||
}
|
||||
|
||||
static void setup_param_double(Item_param *param, uchar **pos)
|
||||
{
|
||||
double data;
|
||||
float8get(data,*pos);
|
||||
param->set_double((double) data);
|
||||
*pos+= 8;
|
||||
}
|
||||
|
||||
static void setup_param_str(Item_param *param, uchar **pos)
|
||||
{
|
||||
ulong len=get_param_length(pos);
|
||||
param->set_value((const char *)*pos, len);
|
||||
*pos+=len;
|
||||
}
|
||||
|
||||
static void setup_param_functions(Item_param *param, uchar read_pos)
|
||||
{
|
||||
switch (read_pos) {
|
||||
case FIELD_TYPE_TINY:
|
||||
item_param->set_int((longlong)(*pos));
|
||||
pos += 1;
|
||||
param->setup_param_func= setup_param_tiny;
|
||||
param->item_result_type = INT_RESULT;
|
||||
break;
|
||||
case FIELD_TYPE_SHORT:
|
||||
item_param->set_int((longlong)sint2korr(pos));
|
||||
pos += 2;
|
||||
break;
|
||||
case FIELD_TYPE_INT24:
|
||||
item_param->set_int((longlong)sint4korr(pos));
|
||||
pos += 3;
|
||||
param->setup_param_func= setup_param_short;
|
||||
param->item_result_type = INT_RESULT;
|
||||
break;
|
||||
case FIELD_TYPE_LONG:
|
||||
item_param->set_int((longlong)sint4korr(pos));
|
||||
pos += 4;
|
||||
param->setup_param_func= setup_param_int32;
|
||||
param->item_result_type = INT_RESULT;
|
||||
break;
|
||||
case FIELD_TYPE_LONGLONG:
|
||||
item_param->set_int((longlong)sint8korr(pos));
|
||||
pos += 8;
|
||||
param->setup_param_func= setup_param_int64;
|
||||
param->item_result_type = INT_RESULT;
|
||||
break;
|
||||
case FIELD_TYPE_FLOAT:
|
||||
float data;
|
||||
float4get(data,pos);
|
||||
item_param->set_double((double) data);
|
||||
pos += 4;
|
||||
param->setup_param_func= setup_param_float;
|
||||
param->item_result_type = REAL_RESULT;
|
||||
break;
|
||||
case FIELD_TYPE_DOUBLE:
|
||||
double j;
|
||||
float8get(j,pos)
|
||||
item_param->set_double(j);
|
||||
pos += 8;
|
||||
param->setup_param_func= setup_param_double;
|
||||
param->item_result_type = REAL_RESULT;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
ulong len=get_param_length(&pos);
|
||||
item_param->set_value((const char*)pos,len,current_thd->thd_charset);
|
||||
pos+=len;
|
||||
}
|
||||
param->setup_param_func= setup_param_str;
|
||||
param->item_result_type = STRING_RESULT;
|
||||
}
|
||||
return(pos);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -283,42 +276,46 @@ static uchar* setup_param_field(Item_param *item_param,
|
|||
from client ..
|
||||
*/
|
||||
|
||||
static bool setup_param_fields(THD *thd, PREP_STMT *stmt)
|
||||
{
|
||||
DBUG_ENTER("setup_param_fields");
|
||||
#ifdef READY_TO_BE_USED
|
||||
Item_param *item_param;
|
||||
ulong param_count=0;
|
||||
uchar *pos=(uchar*) thd->net.read_pos+1;// skip command type
|
||||
static bool setup_params_data(PREP_STMT *stmt)
|
||||
{
|
||||
THD *thd= stmt->thd;
|
||||
List<Item> ¶ms= thd->lex.param_list;
|
||||
List_iterator<Item> param_iterator(params);
|
||||
Item_param *param;
|
||||
DBUG_ENTER("setup_params_data");
|
||||
|
||||
|
||||
if (*pos++) // No types supplied, read only param data
|
||||
{
|
||||
while ((item_param=(Item_param *)it++) &&
|
||||
(param_count++ < stmt->param_count))
|
||||
{
|
||||
if (item_param->long_data_supplied)
|
||||
continue;
|
||||
uchar *pos=(uchar*) thd->net.read_pos+1+MYSQL_STMT_HEADER; //skip header
|
||||
uchar *read_pos= pos+(stmt->param_count+7) / 8; //skip null bits
|
||||
ulong param_no;
|
||||
|
||||
if (!(pos=setup_param_field(item_param,pos,item_param->buffer_type)))
|
||||
DBUG_RETURN(1);
|
||||
if (*read_pos++) //types supplied / first execute
|
||||
{
|
||||
/*
|
||||
First execute or types altered by the client, setup the
|
||||
conversion routines for all parameters (one time)
|
||||
*/
|
||||
while ((param= (Item_param *)param_iterator++))
|
||||
{
|
||||
if (!param->long_data_supplied)
|
||||
{
|
||||
setup_param_functions(param,*read_pos);
|
||||
read_pos+= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Types supplied, read and store it along with param data
|
||||
param_iterator.rewind();
|
||||
}
|
||||
param_no= 0;
|
||||
while ((param= (Item_param *)param_iterator++))
|
||||
{
|
||||
while ((item_param=(Item_param *)it++) &&
|
||||
(param_count++ < thd->param_count))
|
||||
if (!param->long_data_supplied)
|
||||
{
|
||||
if (item_param->long_data_supplied)
|
||||
continue;
|
||||
|
||||
if (!(pos=setup_param_field(item_param,pos,
|
||||
item_param->buffer_type=
|
||||
(enum_field_types) get_buffer_type(&pos))))
|
||||
DBUG_RETURN(1);
|
||||
if (IS_PARAM_NULL(pos,param_no))
|
||||
param->maybe_null=param->null_value=1;
|
||||
else
|
||||
param->setup_param_func(param,&read_pos);
|
||||
}
|
||||
param_no++;
|
||||
}
|
||||
#endif
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -379,8 +376,7 @@ static int check_prepare_fields(THD *thd,TABLE *table, List<Item> &fields,
|
|||
static bool mysql_test_insert_fields(PREP_STMT *stmt,
|
||||
TABLE_LIST *table_list,
|
||||
List<Item> &fields,
|
||||
List<List_item> &values_list,
|
||||
thr_lock_type lock_type)
|
||||
List<List_item> &values_list)
|
||||
{
|
||||
THD *thd= stmt->thd;
|
||||
TABLE *table;
|
||||
|
@ -388,7 +384,7 @@ static bool mysql_test_insert_fields(PREP_STMT *stmt,
|
|||
List_item *values;
|
||||
DBUG_ENTER("mysql_test_insert_fields");
|
||||
|
||||
if (!(table = open_ltable(thd,table_list,lock_type)))
|
||||
if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if ((values= its++))
|
||||
|
@ -431,13 +427,13 @@ static bool mysql_test_insert_fields(PREP_STMT *stmt,
|
|||
|
||||
static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
|
||||
List<Item> &fields, List<Item> &values,
|
||||
COND *conds, thr_lock_type lock_type)
|
||||
COND *conds)
|
||||
{
|
||||
THD *thd= stmt->thd;
|
||||
TABLE *table;
|
||||
DBUG_ENTER("mysql_test_upd_fields");
|
||||
|
||||
if (!(table = open_ltable(thd,table_list,lock_type)))
|
||||
if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) ||
|
||||
|
@ -469,7 +465,7 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
|
|||
static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|
||||
List<Item> &fields, List<Item> &values,
|
||||
COND *conds, ORDER *order, ORDER *group,
|
||||
Item *having, thr_lock_type lock_type)
|
||||
Item *having)
|
||||
{
|
||||
TABLE *table;
|
||||
bool hidden_group_fields;
|
||||
|
@ -477,7 +473,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|
|||
List<Item> all_fields(fields);
|
||||
DBUG_ENTER("mysql_test_select_fields");
|
||||
|
||||
if (!(table = open_ltable(thd,tables,lock_type)))
|
||||
if (!(table = open_ltable(thd,tables,tables->lock_type)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
thd->used_tables=0; // Updated by setup_fields
|
||||
|
@ -550,21 +546,19 @@ static bool send_prepare_results(PREP_STMT *stmt)
|
|||
|
||||
case SQLCOM_INSERT:
|
||||
if (mysql_test_insert_fields(stmt, tables, lex->field_list,
|
||||
lex->many_values, lex->lock_option))
|
||||
lex->many_values))
|
||||
goto abort;
|
||||
break;
|
||||
|
||||
case SQLCOM_UPDATE:
|
||||
if (mysql_test_upd_fields(stmt, tables, select_lex->item_list,
|
||||
lex->value_list, select_lex->where,
|
||||
lex->lock_option))
|
||||
lex->value_list, select_lex->where))
|
||||
goto abort;
|
||||
break;
|
||||
|
||||
case SQLCOM_DELETE:
|
||||
if (mysql_test_upd_fields(stmt, tables, select_lex->item_list,
|
||||
lex->value_list, select_lex->where,
|
||||
lex->lock_option))
|
||||
lex->value_list, select_lex->where))
|
||||
goto abort;
|
||||
break;
|
||||
|
||||
|
@ -572,8 +566,7 @@ static bool send_prepare_results(PREP_STMT *stmt)
|
|||
if (mysql_test_select_fields(stmt, tables, select_lex->item_list,
|
||||
lex->value_list, select_lex->where,
|
||||
(ORDER*) select_lex->order_list.first,
|
||||
(ORDER*) select_lex->group_list.first,
|
||||
select_lex->having, lex->lock_option))
|
||||
(ORDER*) select_lex->group_list.first, select_lex->having))
|
||||
goto abort;
|
||||
break;
|
||||
|
||||
|
@ -583,6 +576,8 @@ static bool send_prepare_results(PREP_STMT *stmt)
|
|||
Rest fall through to default category, no parsing
|
||||
for non-DML statements
|
||||
*/
|
||||
if (send_prep_stmt(stmt, 0))
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
@ -597,7 +592,7 @@ abort:
|
|||
*/
|
||||
|
||||
static bool parse_prepare_query(PREP_STMT *stmt,
|
||||
char *packet, uint length)
|
||||
char *packet, uint length)
|
||||
{
|
||||
bool error= 1;
|
||||
THD *thd= stmt->thd;
|
||||
|
@ -607,6 +602,7 @@ static bool parse_prepare_query(PREP_STMT *stmt,
|
|||
mysql_init_query(thd);
|
||||
thd->prepare_command=true;
|
||||
thd->safe_to_cache_query= 0;
|
||||
thd->lex.param_count=0;
|
||||
|
||||
LEX *lex=lex_start(thd, (uchar*) packet, length);
|
||||
if (!yyparse() && !thd->fatal_error)
|
||||
|
@ -615,6 +611,25 @@ static bool parse_prepare_query(PREP_STMT *stmt,
|
|||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize parameter items in statement
|
||||
*/
|
||||
static bool init_param_items(THD *thd, PREP_STMT *stmt)
|
||||
{
|
||||
#if TO_BE_TESTED
|
||||
Item_param **to;
|
||||
if (!(to= (Item_param *)
|
||||
my_malloc(sizeof(Item_param*) * stmt->param_count, MYF(MY_WME))))
|
||||
return 1;
|
||||
List<Item> ¶ms= thd->lex.param_list;
|
||||
List_iterator<Item> param_iterator(params);
|
||||
while ((to++ = (Item_param *)param_iterator++))
|
||||
{
|
||||
DBUG_PRINT("info",("param: %lx", to));
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
Parse the query and send the total number of parameters
|
||||
|
@ -648,10 +663,15 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
|
|||
goto err;
|
||||
|
||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
|
||||
|
||||
stmt.mem_root= thd->mem_root;
|
||||
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
|
||||
#if 0
|
||||
if (init_param_items(thd, &stmt))
|
||||
goto err;
|
||||
#endif
|
||||
stmt.mem_root= thd->mem_root;
|
||||
tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0);
|
||||
thd->mem_root= thd_root; // restore main mem_root
|
||||
thd->last_prepared_stmt= &stmt;
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
|
@ -685,15 +705,13 @@ void mysql_stmt_execute(THD *thd, char *packet)
|
|||
/* Check if we got an error when sending long data */
|
||||
if (stmt->error_in_prepare)
|
||||
{
|
||||
send_error(thd);
|
||||
send_error(thd, stmt->last_errno, stmt->last_error);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
if (stmt->param_count && setup_param_fields(thd, stmt))
|
||||
if (stmt->param_count && setup_params_data(stmt))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
MEM_ROOT thd_root= thd->mem_root;
|
||||
thd->mem_root = thd->con_root;
|
||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
|
||||
|
||||
|
@ -703,12 +721,12 @@ void mysql_stmt_execute(THD *thd, char *packet)
|
|||
mysql_delete(), mysql_update() and mysql_select() to not to
|
||||
have re-check on setup_* and other things ..
|
||||
*/
|
||||
mysql_execute_command(thd);
|
||||
mysql_execute_command(stmt->thd);
|
||||
thd->last_prepared_stmt= stmt;
|
||||
|
||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
|
||||
|
||||
thd->mem_root= thd_root;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -768,8 +786,10 @@ void mysql_stmt_close(THD *thd, char *packet)
|
|||
send_error(thd);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
stmt->param= 0;
|
||||
my_free((char *)stmt->param, MYF(MY_ALLOW_ZERO_PTR));
|
||||
/* Will call free_prep_stmt() */
|
||||
tree_delete(&thd->prepared_statements, (void*) stmt, NULL);
|
||||
tree_delete(&thd->prepared_statements, (void*) &stmt, (void *)0);
|
||||
thd->last_prepared_stmt=0;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
@ -800,17 +820,16 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
|
|||
DBUG_ENTER("mysql_stmt_get_longdata");
|
||||
|
||||
/* The following should never happen */
|
||||
if (packet_length < 9)
|
||||
if (packet_length < MYSQL_LONG_DATA_HEADER+1)
|
||||
{
|
||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "get_longdata");
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
pos++; // skip command type at first position
|
||||
ulong stmt_id= uint4korr(pos);
|
||||
uint param_number= uint2korr(pos+4);
|
||||
uint param_type= uint2korr(pos+6);
|
||||
pos+=8; // Point to data
|
||||
pos+=MYSQL_LONG_DATA_HEADER; // Point to data
|
||||
|
||||
if (!(stmt=find_prepared_statement(thd, stmt_id, "get_longdata")))
|
||||
{
|
||||
|
@ -829,7 +848,8 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
|
|||
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), "get_longdata");
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
stmt->param[param_number].set_longdata(pos, packet_length-9, current_thd->thd_charset);
|
||||
stmt->param[param_number].set_longdata(pos, packet_length-9);
|
||||
stmt->long_data_used= 1;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
|
1358
tests/client_test.c
1358
tests/client_test.c
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue