summaryrefslogtreecommitdiff
path: root/libmysql
diff options
context:
space:
mode:
authorkonstantin@mysql.com <>2004-05-25 02:03:49 +0400
committerkonstantin@mysql.com <>2004-05-25 02:03:49 +0400
commitf207b33a7b85f03221fcec1afb662ede70b5e438 (patch)
tree39de3845fc8340f9a27f30803b9104e416c7ab62 /libmysql
parent1b61cb6d0f5dbea8c3901f509b2f99b4d8c618f4 (diff)
downloadmariadb-git-f207b33a7b85f03221fcec1afb662ede70b5e438.tar.gz
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.
Diffstat (limited to 'libmysql')
-rw-r--r--libmysql/libmysql.c109
1 files changed, 27 insertions, 82 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 2214ca68c81..b8ede73a0c5 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -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);