1
0
mirror of https://github.com/MariaDB/server.git synced 2025-06-12 01:53:02 +03:00

Support for character set conversion in binary protocol: another go

after Monty's review.
- Item_param was rewritten.
- it turns out that we can't convert string data to character set of
  connection on the fly, because they first should be written to the binary
  log.
  To support efficient conversion we need to rewrite prepared statements
  binlogging code first.
This commit is contained in:
konstantin@mysql.com
2004-05-25 02:03:49 +04:00
parent 1b61cb6d0f
commit f207b33a7b
30 changed files with 1067 additions and 536 deletions

View File

@ -88,8 +88,6 @@ my_bool net_flush(NET *net);
static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
static void append_wild(char *to,char *end,const char *wild);
sig_handler pipe_sig_handler(int sig);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
const char *from, ulong length);
static my_bool mysql_client_init= 0;
static my_bool org_my_init_done= 0;
@ -1570,73 +1568,14 @@ void my_net_local_init(NET *net)
ulong STDCALL
mysql_escape_string(char *to,const char *from,ulong length)
{
return mysql_sub_escape_string(default_charset_info,to,from,length);
return escape_string_for_mysql(default_charset_info, to, from, length);
}
ulong STDCALL
mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
ulong length)
{
return mysql_sub_escape_string(mysql->charset,to,from,length);
}
static ulong
mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
const char *from, ulong length)
{
const char *to_start=to;
const char *end;
#ifdef USE_MB
my_bool use_mb_flag=use_mb(charset_info);
#endif
for (end=from+length; from != end ; from++)
{
#ifdef USE_MB
int l;
if (use_mb_flag && (l = my_ismbchar(charset_info, from, end)))
{
while (l--)
*to++ = *from++;
from--;
continue;
}
#endif
switch (*from) {
case 0: /* Must be escaped for 'mysql' */
*to++= '\\';
*to++= '0';
break;
case '\n': /* Must be escaped for logs */
*to++= '\\';
*to++= 'n';
break;
case '\r':
*to++= '\\';
*to++= 'r';
break;
case '\\':
*to++= '\\';
*to++= '\\';
break;
case '\'':
*to++= '\\';
*to++= '\'';
break;
case '"': /* Better safe than sorry */
*to++= '\\';
*to++= '"';
break;
case '\032': /* This gives problems on Win32 */
*to++= '\\';
*to++= 'Z';
break;
default:
*to++= *from;
}
}
*to=0;
return (ulong) (to-to_start);
return escape_string_for_mysql(mysql->charset, to, from, length);
}
@ -1978,7 +1917,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
{
/* This is second prepare with another statement */
char buff[4];
char buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
mysql_stmt_free_result(stmt);
/*
@ -2353,6 +2292,14 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
stmt->insert_id= mysql->insert_id;
DBUG_RETURN(0);
}
static void store_param_type(char **pos, MYSQL_BIND *param)
{
uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0);
int2store(*pos, typecode);
*pos+= 2;
}
int cli_stmt_execute(MYSQL_STMT *stmt)
@ -2390,11 +2337,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
that is sent to the server.
*/
for (param= stmt->params; param < param_end ; param++)
{
uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0);
int2store(net->write_pos, typecode);
net->write_pos+= 2;
}
store_param_type((char**) &net->write_pos, param);
}
for (param= stmt->params; param < param_end; param++)
@ -2804,25 +2747,27 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
param->param_number);
DBUG_RETURN(1);
}
/* Mark for execute that the result is already sent */
/*
Send long data packet if there is data or we're sending long data
for the first time.
*/
if (length || param->long_data_used == 0)
{
MYSQL *mysql= stmt->mysql;
char *packet, extra_data[MYSQL_LONG_DATA_HEADER];
/* Packet header: stmt id (4 bytes), param no (2 bytes) */
char buff[MYSQL_LONG_DATA_HEADER];
int4store(buff, stmt->stmt_id);
int2store(buff + 4, param_number);
param->long_data_used= 1;
packet= extra_data;
int4store(packet, stmt->stmt_id); packet+=4;
int2store(packet, param_number); packet+=2;
/*
Note that we don't get any ok packet from the server in this case
This is intentional to save bandwidth.
*/
if ((*mysql->methods->advanced_command)(mysql, COM_LONG_DATA, extra_data,
MYSQL_LONG_DATA_HEADER, data,
length, 1))
if ((*mysql->methods->advanced_command)(mysql, COM_LONG_DATA, buff,
sizeof(buff), data, length, 1))
{
set_stmt_errmsg(stmt, mysql->net.last_error,
mysql->net.last_errno, mysql->net.sqlstate);
@ -3962,7 +3907,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
mysql->stmts= list_delete(mysql->stmts, &stmt->list);
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
{
char buff[4];
char buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
mysql->unbuffered_fetch_owner= 0;
@ -3997,7 +3942,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
{
char buff[MYSQL_STMT_HEADER];
char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
MYSQL *mysql;
MYSQL_BIND *param, *param_end;
DBUG_ENTER("mysql_stmt_reset");
@ -4010,7 +3955,7 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
mysql= stmt->mysql->last_used_con;
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff,
MYSQL_STMT_HEADER,0,0,0))
sizeof(buff), 0, 0, 0))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);