diff options
author | konstantin@mysql.com <> | 2004-05-25 02:03:49 +0400 |
---|---|---|
committer | konstantin@mysql.com <> | 2004-05-25 02:03:49 +0400 |
commit | f207b33a7b85f03221fcec1afb662ede70b5e438 (patch) | |
tree | 39de3845fc8340f9a27f30803b9104e416c7ab62 /libmysql | |
parent | 1b61cb6d0f5dbea8c3901f509b2f99b4d8c618f4 (diff) | |
download | mariadb-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.c | 109 |
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); |