1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Manually merged, requirees more merging

This commit is contained in:
sergefp@mysql.com
2004-05-25 08:15:50 +04:00
30 changed files with 1066 additions and 534 deletions

View File

@ -76,8 +76,6 @@ Long data handling:
#include <mysql.h>
#endif
const String my_null_string("NULL", 4, default_charset_info);
/******************************************************************************
Prepared_statement: statement which can contain placeholders
******************************************************************************/
@ -91,7 +89,6 @@ public:
uint last_errno;
char last_error[MYSQL_ERRMSG_SIZE];
bool get_longdata_error;
bool log_full_query;
#ifndef EMBEDDED_LIBRARY
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
uchar *read_pos, String *expanded_query);
@ -245,7 +242,7 @@ static ulong get_param_length(uchar **packet, ulong len)
none
*/
void set_param_tiny(Item_param *param, uchar **pos, ulong len)
static void set_param_tiny(Item_param *param, uchar **pos, ulong len)
{
#ifndef EMBEDDED_LIBRARY
if (len < 1)
@ -253,55 +250,55 @@ void set_param_tiny(Item_param *param, uchar **pos, ulong len)
#endif
int8 value= (int8) **pos;
param->set_int(param->unsigned_flag ? (longlong) ((uint8) value) :
(longlong) value);
(longlong) value, 4);
*pos+= 1;
}
void set_param_short(Item_param *param, uchar **pos, ulong len)
static void set_param_short(Item_param *param, uchar **pos, ulong len)
{
int16 value;
#ifndef EMBEDDED_LIBRARY
if (len < 2)
return;
int16 value= sint2korr(*pos);
value= sint2korr(*pos);
#else
int16 value;
shortget(value, *pos);
#endif
param->set_int(param->unsigned_flag ? (longlong) ((uint16) value) :
(longlong) value);
(longlong) value, 6);
*pos+= 2;
}
void set_param_int32(Item_param *param, uchar **pos, ulong len)
static void set_param_int32(Item_param *param, uchar **pos, ulong len)
{
int32 value;
#ifndef EMBEDDED_LIBRARY
if (len < 4)
return;
int32 value= sint4korr(*pos);
value= sint4korr(*pos);
#else
int32 value;
longget(value, *pos);
#endif
param->set_int(param->unsigned_flag ? (longlong) ((uint32) value) :
(longlong) value);
(longlong) value, 11);
*pos+= 4;
}
void set_param_int64(Item_param *param, uchar **pos, ulong len)
static void set_param_int64(Item_param *param, uchar **pos, ulong len)
{
longlong value;
#ifndef EMBEDDED_LIBRARY
if (len < 8)
return;
param->set_int((longlong)sint8korr(*pos));
*pos+= 8;
value= (longlong) sint8korr(*pos);
#else
longlong value;
longlongget(value, *pos);
param->set_int(value);
#endif
param->set_int(value, 21);
*pos+= 8;
}
void set_param_float(Item_param *param, uchar **pos, ulong len)
static void set_param_float(Item_param *param, uchar **pos, ulong len)
{
#ifndef EMBEDDED_LIBRARY
if (len < 4)
@ -313,7 +310,7 @@ void set_param_float(Item_param *param, uchar **pos, ulong len)
*pos+= 4;
}
void set_param_double(Item_param *param, uchar **pos, ulong len)
static void set_param_double(Item_param *param, uchar **pos, ulong len)
{
#ifndef EMBEDDED_LIBRARY
if (len < 8)
@ -326,9 +323,10 @@ void set_param_double(Item_param *param, uchar **pos, ulong len)
}
#ifndef EMBEDDED_LIBRARY
void set_param_time(Item_param *param, uchar **pos, ulong len)
static void set_param_time(Item_param *param, uchar **pos, ulong len)
{
ulong length;
uint day;
if ((length= get_param_length(pos, len)) >= 8)
{
@ -338,20 +336,33 @@ void set_param_time(Item_param *param, uchar **pos, ulong len)
/* TODO: why length is compared with 8 here? */
tm.second_part= (length > 8 ) ? (ulong) sint4korr(to+7): 0;
tm.day= (ulong) sint4korr(to+1);
tm.hour= (uint) to[5];
/*
Note, that though ranges of hour, minute and second are not checked
here we rely on them being < 256: otherwise
we'll get buffer overflow in make_{date,time} functions,
which are called when time value is converted to string.
*/
day= (uint) sint4korr(to+1);
tm.hour= (uint) to[5] + day * 24;
tm.minute= (uint) to[6];
tm.second= (uint) to[7];
tm.year= tm.month= 0;
if (tm.hour > 838)
{
/* TODO: add warning 'Data truncated' here */
tm.hour= 838;
tm.minute= 59;
tm.second= 59;
}
tm.day= tm.year= tm.month= 0;
tm.neg= (bool)to[0];
param->set_time(&tm, TIMESTAMP_TIME);
param->set_time(&tm, TIMESTAMP_TIME,
MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
*pos+= length;
}
void set_param_datetime(Item_param *param, uchar **pos, ulong len)
static void set_param_datetime(Item_param *param, uchar **pos, ulong len)
{
uint length;
@ -362,6 +373,11 @@ void set_param_datetime(Item_param *param, uchar **pos, ulong len)
tm.second_part= (length > 7 ) ? (ulong) sint4korr(to+7): 0;
/*
Note, that though ranges of hour, minute and second are not checked
here we rely on them being < 256: otherwise
we'll get buffer overflow in make_{date,time} functions.
*/
if (length > 4)
{
tm.hour= (uint) to[4];
@ -376,12 +392,13 @@ void set_param_datetime(Item_param *param, uchar **pos, ulong len)
tm.day= (uint) to[3];
tm.neg= 0;
param->set_time(&tm, TIMESTAMP_DATETIME);
param->set_time(&tm, TIMESTAMP_DATETIME,
MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
*pos+= length;
}
void set_param_date(Item_param *param, uchar **pos, ulong len)
static void set_param_date(Item_param *param, uchar **pos, ulong len)
{
ulong length;
@ -389,7 +406,11 @@ void set_param_date(Item_param *param, uchar **pos, ulong len)
{
uchar *to= *pos;
TIME tm;
/*
Note, that though ranges of hour, minute and second are not checked
here we rely on them being < 256: otherwise
we'll get buffer overflow in make_{date,time} functions.
*/
tm.year= (uint) sint2korr(to);
tm.month= (uint) to[2];
tm.day= (uint) to[3];
@ -398,7 +419,8 @@ void set_param_date(Item_param *param, uchar **pos, ulong len)
tm.second_part= 0;
tm.neg= 0;
param->set_time(&tm, TIMESTAMP_DATE);
param->set_time(&tm, TIMESTAMP_DATE,
MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
*pos+= length;
}
@ -418,8 +440,9 @@ void set_param_time(Item_param *param, uchar **pos, ulong len)
tm.year= tm.month= 0;
tm.neg= to->neg;
param->set_time(&tm, TIMESTAMP_TIME,
MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
param->set_time(&tm, TIMESTAMP_TIME);
}
void set_param_datetime(Item_param *param, uchar **pos, ulong len)
@ -437,7 +460,8 @@ void set_param_datetime(Item_param *param, uchar **pos, ulong len)
tm.month= to->month;
tm.neg= 0;
param->set_time(&tm, TIMESTAMP_DATETIME);
param->set_time(&tm, TIMESTAMP_DATETIME,
MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
void set_param_date(Item_param *param, uchar **pos, ulong len)
@ -455,60 +479,111 @@ void set_param_date(Item_param *param, uchar **pos, ulong len)
tm.second_part= 0;
tm.neg= 0;
param->set_time(&tm, TIMESTAMP_DATE);
param->set_time(&tm, TIMESTAMP_DATE,
MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
#endif /*!EMBEDDED_LIBRARY*/
void set_param_str(Item_param *param, uchar **pos, ulong len)
static void set_param_str(Item_param *param, uchar **pos, ulong len)
{
ulong length= get_param_length(pos, len);
param->set_value((const char *)*pos, length, Item::default_charset());
param->set_str((const char *)*pos, length);
*pos+= length;
}
static void setup_one_conversion_function(Item_param *param, uchar param_type)
#undef get_param_length
static void setup_one_conversion_function(THD *thd, Item_param *param,
uchar param_type)
{
switch (param_type) {
case FIELD_TYPE_TINY:
case MYSQL_TYPE_TINY:
param->set_param_func= set_param_tiny;
param->item_type= Item::INT_ITEM;
param->item_result_type= INT_RESULT;
break;
case FIELD_TYPE_SHORT:
case MYSQL_TYPE_SHORT:
param->set_param_func= set_param_short;
param->item_type= Item::INT_ITEM;
param->item_result_type= INT_RESULT;
break;
case FIELD_TYPE_LONG:
case MYSQL_TYPE_LONG:
param->set_param_func= set_param_int32;
param->item_type= Item::INT_ITEM;
param->item_result_type= INT_RESULT;
break;
case FIELD_TYPE_LONGLONG:
case MYSQL_TYPE_LONGLONG:
param->set_param_func= set_param_int64;
param->item_type= Item::INT_ITEM;
param->item_result_type= INT_RESULT;
break;
case FIELD_TYPE_FLOAT:
case MYSQL_TYPE_FLOAT:
param->set_param_func= set_param_float;
param->item_type= Item::REAL_ITEM;
param->item_result_type= REAL_RESULT;
break;
case FIELD_TYPE_DOUBLE:
case MYSQL_TYPE_DOUBLE:
param->set_param_func= set_param_double;
param->item_type= Item::REAL_ITEM;
param->item_result_type= REAL_RESULT;
break;
case FIELD_TYPE_TIME:
case MYSQL_TYPE_TIME:
param->set_param_func= set_param_time;
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
break;
case FIELD_TYPE_DATE:
case MYSQL_TYPE_DATE:
param->set_param_func= set_param_date;
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
param->set_param_func= set_param_datetime;
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
break;
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
param->set_param_func= set_param_str;
param->value.cs_info.character_set_client= &my_charset_bin;
param->value.cs_info.final_character_set_of_str_value= &my_charset_bin;
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
break;
default:
param->set_param_func= set_param_str;
param->item_result_type= STRING_RESULT;
/*
The client library ensures that we won't get any other typecodes
except typecodes above and typecodes for string types. Marking
label as 'default' lets us to handle malformed packets as well.
*/
{
CHARSET_INFO *fromcs= thd->variables.character_set_client;
CHARSET_INFO *tocs= thd->variables.collation_connection;
uint32 dummy_offset;
param->value.cs_info.character_set_client= fromcs;
/*
Setup source and destination character sets so that they
are different only if conversion is necessary: this will
make later checks easier.
*/
param->value.cs_info.final_character_set_of_str_value=
String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
tocs : fromcs;
param->set_param_func= set_param_str;
/*
Exact value of max_length is not known unless data is converted to
charset of connection, so we have to set it later.
*/
param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT;
}
}
}
@ -538,23 +613,21 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
for (Item_param **it= begin; it < end; ++it)
{
Item_param *param= *it;
if (param->long_data_supplied)
res= param->query_val_str(&str);
else
if (param->state != Item_param::LONG_DATA_VALUE)
{
if (is_param_null(null_array, it - begin))
{
param->set_null();
res= &my_null_string;
}
else
{
if (read_pos >= data_end)
DBUG_RETURN(1);
param->set_param_func(param, &read_pos, data_end - read_pos);
res= param->query_val_str(&str);
}
}
res= param->query_val_str(&str);
if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */
if (query->replace(param->pos_in_query+length, 1, *res))
DBUG_RETURN(1);
@ -576,7 +649,7 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
for (Item_param **it= begin; it < end; ++it)
{
Item_param *param= *it;
if (!param->long_data_supplied)
if (param->state != Item_param::LONG_DATA_VALUE)
{
if (is_param_null(null_array, it - begin))
param->set_null();
@ -587,6 +660,8 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
param->set_param_func(param, &read_pos, data_end - read_pos);
}
}
if (param->convert_str_value(stmt->thd))
DBUG_RETURN(1); /* out of memory */
}
DBUG_RETURN(0);
}
@ -608,6 +683,7 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
*/
Item_param **it= stmt->param_array;
Item_param **end= it + stmt->param_count;
THD *thd= stmt->thd;
for (; it < end; ++it)
{
ushort typecode;
@ -619,7 +695,7 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
typecode= sint2korr(read_pos);
read_pos+= 2;
(**it).unsigned_flag= test(typecode & signed_bit);
setup_one_conversion_function(*it, (uchar) (typecode & ~signed_bit));
setup_one_conversion_function(thd, *it, (uchar) (typecode & ~signed_bit));
}
}
*data= read_pos;
@ -630,6 +706,7 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query)
{
THD *thd= stmt->thd;
Item_param **it= stmt->param_array;
Item_param **end= it + stmt->param_count;
MYSQL_BIND *client_param= stmt->thd->client_params;
@ -639,21 +716,22 @@ static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query)
for (; it < end; ++it, ++client_param)
{
Item_param *param= *it;
setup_one_conversion_function(param, client_param->buffer_type);
param->unsigned_flag= client_param->is_unsigned;
if (!param->long_data_supplied)
setup_one_conversion_function(thd, param, client_param->buffer_type);
if (param->state != Item_param::LONG_DATA_VALUE)
{
if (*client_param->is_null)
param->set_null();
else
{
uchar *buff= (uchar*)client_param->buffer;
uchar *buff= (uchar*) client_param->buffer;
param->set_param_func(param, &buff,
client_param->length ?
*client_param->length :
client_param->buffer_length);
}
}
if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */
}
DBUG_RETURN(0);
}
@ -678,25 +756,22 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query)
for (; it < end; ++it, ++client_param)
{
Item_param *param= *it;
setup_one_conversion_function(param, client_param->buffer_type);
if (param->long_data_supplied)
res= param->query_val_str(&str);
else
setup_one_conversion_function(thd, param, client_param->buffer_type);
if (param->state != Item_param::LONG_DATA_VALUE)
{
if (*client_param->is_null)
{
param->set_null();
res= &my_null_string;
}
else
{
uchar *buff= (uchar*)client_param->buffer;
uchar *buff= (uchar*)client_param->buffer;
param->set_param_func(param, &buff,
client_param->length ?
*client_param->length :
client_param->buffer_length);
res= param->query_val_str(&str);
}
res= param->query_val_str(&str);
if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */
}
if (query->replace(param->pos_in_query+length, 1, *res))
DBUG_RETURN(1);
@ -859,7 +934,7 @@ static int mysql_test_insert(Prepared_statement *stmt,
TABLE_LIST *insert_table_list=
(TABLE_LIST*) lex->select_lex.table_list.first;
my_bool update= (lex->value_list.elements ? UPDATE_ACL : 0);
DBUG_ENTER("mysql_test_insert_fields");
DBUG_ENTER("mysql_test_insert");
if ((res= insert_precheck(thd, table_list, update)))
DBUG_RETURN(res);
@ -915,7 +990,7 @@ error:
Validate UPDATE statement
SYNOPSIS
mysql_test_delete()
mysql_test_update()
stmt prepared statemen handler
tables list of tables queries
@ -1230,7 +1305,7 @@ end:
/*
Validate and prepare for execution CRETE TABLE statement
Validate and prepare for execution CREATE TABLE statement
SYNOPSIS
mysql_test_create_table()
@ -1267,7 +1342,7 @@ static int mysql_test_create_table(Prepared_statement *stmt,
/*
Validate and prepare for execution multy update statement
Validate and prepare for execution multi update statement
SYNOPSIS
mysql_test_multiupdate()
@ -1290,7 +1365,7 @@ static int mysql_test_multiupdate(Prepared_statement *stmt,
/*
Validate and prepare for execution multy delete statement
Validate and prepare for execution multi delete statement
SYNOPSIS
mysql_test_multidelete()
@ -1462,8 +1537,8 @@ error:
}
/*
Initialize array of parametes in statement from LEX.
(We need to have quick access to items by number in mysql_send_longdata).
Initialize array of parameters in statement from LEX.
(We need to have quick access to items by number in mysql_stmt_get_longdata).
This is to avoid using malloc/realloc in the parser.
*/
@ -1705,7 +1780,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
packet+= 9; /* stmt_id + 5 bytes of flags */
if (!(stmt= find_prepared_statement(thd, stmt_id, "execute", SEND_ERROR)))
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute",
SEND_ERROR)))
DBUG_VOID_RETURN;
DBUG_PRINT("exec_query:", ("%s", stmt->query));
@ -1743,7 +1819,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
set_params_data_err:
reset_stmt_params(stmt);
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_execute");
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_execute");
send_error(thd);
DBUG_VOID_RETURN;
}
@ -1864,7 +1940,8 @@ void mysql_stmt_reset(THD *thd, char *packet)
DBUG_ENTER("mysql_stmt_reset");
if (!(stmt= find_prepared_statement(thd, stmt_id, "reset", SEND_ERROR)))
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset",
SEND_ERROR)))
DBUG_VOID_RETURN;
stmt->get_longdata_error= 0;
@ -1894,7 +1971,8 @@ void mysql_stmt_free(THD *thd, char *packet)
DBUG_ENTER("mysql_stmt_free");
if (!(stmt= find_prepared_statement(thd, stmt_id, "close", DONT_SEND_ERROR)))
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close",
DONT_SEND_ERROR)))
DBUG_VOID_RETURN;
/* Statement map deletes statement on erase */
@ -1922,43 +2000,50 @@ void mysql_stmt_free(THD *thd, char *packet)
to the server. (No checking that we get a 'end of column' in the server)
*/
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length)
void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
{
ulong stmt_id;
uint param_number;
Prepared_statement *stmt;
Item_param *param;
char *packet_end= packet + packet_length - 1;
DBUG_ENTER("mysql_stmt_get_longdata");
#ifndef EMBEDDED_LIBRARY
/* The following should never happen */
if (packet_length < MYSQL_LONG_DATA_HEADER+1)
/* Minimal size of long data packet is 6 bytes */
if ((ulong) (packet_end - packet) < MYSQL_LONG_DATA_HEADER)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "get_longdata");
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_send_long_data");
DBUG_VOID_RETURN;
}
#endif
ulong stmt_id= uint4korr(pos);
uint param_number= uint2korr(pos+4);
stmt_id= uint4korr(packet);
packet+= 4;
if (!(stmt=find_prepared_statement(thd, stmt_id, "get_longdata",
if (!(stmt=find_prepared_statement(thd, stmt_id, "mysql_stmt_send_long_data",
DONT_SEND_ERROR)))
DBUG_VOID_RETURN;
param_number= uint2korr(packet);
packet+= 2;
#ifndef EMBEDDED_LIBRARY
if (param_number >= stmt->param_count)
{
/* Error will be sent in execute call */
stmt->get_longdata_error= 1;
stmt->last_errno= ER_WRONG_ARGUMENTS;
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), "get_longdata");
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
"mysql_stmt_send_long_data");
DBUG_VOID_RETURN;
}
pos+= MYSQL_LONG_DATA_HEADER; // Point to data
#endif
Item_param *param= stmt->param_array[param_number];
param= stmt->param_array[param_number];
#ifndef EMBEDDED_LIBRARY
param->set_longdata(pos, packet_length-MYSQL_LONG_DATA_HEADER-1);
param->set_longdata(packet, (ulong) (packet_end - packet));
#else
param->set_longdata(thd->extra_data, thd->extra_length);
#endif
@ -1972,13 +2057,11 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
param_array(0),
param_count(0),
last_errno(0),
get_longdata_error(0),
log_full_query(0)
get_longdata_error(0)
{
*last_error= '\0';
if (mysql_bin_log.is_open())
{
log_full_query= 1;
set_params_from_vars= insert_params_from_vars_with_log;
#ifndef EMBEDDED_LIBRARY
set_params= insert_params_withlog;