Commit f1f318e6 authored by unknown's avatar unknown

Merge mysql.com:/home/jimw/my/mysql-5.0-10214

into  mysql.com:/home/jimw/my/mysql-5.0-clean


include/my_sys.h:
  Auto merged
include/mysql_com.h:
  Auto merged
libmysql/libmysql.c:
  Auto merged
sql/set_var.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
tests/mysql_client_test.c:
  Clean up merge of new tests
parents 2d7d15ab 86eb6f70
...@@ -866,6 +866,9 @@ extern void add_compiled_collation(CHARSET_INFO *cs); ...@@ -866,6 +866,9 @@ extern void add_compiled_collation(CHARSET_INFO *cs);
extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
char *to, ulong to_length, char *to, ulong to_length,
const char *from, ulong length); const char *from, ulong length);
extern ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info,
char *to, ulong to_length,
const char *from, ulong length);
extern void thd_increment_bytes_sent(ulong length); extern void thd_increment_bytes_sent(ulong length);
extern void thd_increment_bytes_received(ulong length); extern void thd_increment_bytes_received(ulong length);
......
...@@ -148,6 +148,7 @@ enum enum_server_command ...@@ -148,6 +148,7 @@ enum enum_server_command
*/ */
#define SERVER_STATUS_LAST_ROW_SENT 128 #define SERVER_STATUS_LAST_ROW_SENT 128
#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */ #define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */
#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512
#define MYSQL_ERRMSG_SIZE 512 #define MYSQL_ERRMSG_SIZE 512
#define NET_READ_TIMEOUT 30 /* Timeout on read */ #define NET_READ_TIMEOUT 30 /* Timeout on read */
......
...@@ -1616,7 +1616,14 @@ ulong STDCALL ...@@ -1616,7 +1616,14 @@ ulong STDCALL
mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
ulong length) ulong length)
{ {
return escape_string_for_mysql(mysql->charset, to, 0, from, length); if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
{
return escape_quotes_for_mysql(mysql->charset, to, 0, from, length);
}
else
{
return escape_string_for_mysql(mysql->charset, to, 0, from, length);
}
} }
......
...@@ -561,11 +561,30 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, ...@@ -561,11 +561,30 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_RETURN(cs); DBUG_RETURN(cs);
} }
/* /*
Escape string with backslashes (\)
SYNOPSIS
escape_string_for_mysql()
charset_info Charset of the strings
to Buffer for escaped string
to_length Length of destination buffer, or 0
from The string to escape
length The length of the string to escape
DESCRIPTION
This escapes the contents of a string by adding backslashes before special
characters, and turning others into specific escape sequences, such as
turning newlines into \n and null bytes into \0.
NOTE NOTE
to keep old C API, to_length may be 0 to mean "big enough" To maintain compatibility with the old C API, to_length may be 0 to mean
RETURN "big enough"
the length of the escaped string or ~0 if it did not fit.
RETURN VALUES
~0 The escaped string did not fit in the to buffer
>=0 The length of the escaped string
*/ */
ulong escape_string_for_mysql(CHARSET_INFO *charset_info, ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
char *to, ulong to_length, char *to, ulong to_length,
...@@ -573,20 +592,20 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, ...@@ -573,20 +592,20 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
{ {
const char *to_start= to; const char *to_start= to;
const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
my_bool overflow=0; my_bool overflow= FALSE;
#ifdef USE_MB #ifdef USE_MB
my_bool use_mb_flag= use_mb(charset_info); my_bool use_mb_flag= use_mb(charset_info);
#endif #endif
for (end= from + length; from < end; from++) for (end= from + length; from < end; from++)
{ {
char escape=0; char escape= 0;
#ifdef USE_MB #ifdef USE_MB
int tmp_length; int tmp_length;
if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
{ {
if (to + tmp_length > to_end) if (to + tmp_length > to_end)
{ {
overflow=1; overflow= TRUE;
break; break;
} }
while (tmp_length--) while (tmp_length--)
...@@ -636,7 +655,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, ...@@ -636,7 +655,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
{ {
if (to + 2 > to_end) if (to + 2 > to_end)
{ {
overflow=1; overflow= TRUE;
break; break;
} }
*to++= '\\'; *to++= '\\';
...@@ -646,7 +665,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, ...@@ -646,7 +665,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
{ {
if (to + 1 > to_end) if (to + 1 > to_end)
{ {
overflow=1; overflow= TRUE;
break; break;
} }
*to++= *from; *to++= *from;
...@@ -656,3 +675,84 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, ...@@ -656,3 +675,84 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
return overflow ? (ulong)~0 : (ulong) (to - to_start); return overflow ? (ulong)~0 : (ulong) (to - to_start);
} }
/*
Escape apostrophes by doubling them up
SYNOPSIS
escape_quotes_for_mysql()
charset_info Charset of the strings
to Buffer for escaped string
to_length Length of destination buffer, or 0
from The string to escape
length The length of the string to escape
DESCRIPTION
This escapes the contents of a string by doubling up any apostrophes that
it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in
effect on the server.
NOTE
To be consistent with escape_string_for_mysql(), to_length may be 0 to
mean "big enough"
RETURN VALUES
~0 The escaped string did not fit in the to buffer
>=0 The length of the escaped string
*/
ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info,
char *to, ulong to_length,
const char *from, ulong length)
{
const char *to_start= to;
const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
my_bool overflow= FALSE;
#ifdef USE_MB
my_bool use_mb_flag= use_mb(charset_info);
#endif
for (end= from + length; from < end; from++)
{
char escape= 0;
#ifdef USE_MB
int tmp_length;
if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
{
if (to + tmp_length > to_end)
{
overflow= TRUE;
break;
}
while (tmp_length--)
*to++= *from++;
from--;
continue;
}
/*
We don't have the same issue here with a non-multi-byte character being
turned into a multi-byte character by the addition of an escaping
character, because we are only escaping the ' character with itself.
*/
#endif
if (*from == '\'')
{
if (to + 2 > to_end)
{
overflow= TRUE;
break;
}
*to++= '\'';
*to++= '\'';
}
else
{
if (to + 1 > to_end)
{
overflow= TRUE;
break;
}
*to++= *from;
}
}
*to= 0;
return overflow ? (ulong)~0 : (ulong) (to - to_start);
}
...@@ -3238,7 +3238,16 @@ void fix_sql_mode_var(THD *thd, enum_var_type type) ...@@ -3238,7 +3238,16 @@ void fix_sql_mode_var(THD *thd, enum_var_type type)
global_system_variables.sql_mode= global_system_variables.sql_mode=
fix_sql_mode(global_system_variables.sql_mode); fix_sql_mode(global_system_variables.sql_mode);
else else
{
thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode); thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode);
/*
Update thd->server_status
*/
if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
else
thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES;
}
} }
/* Map database specific bits to function bits */ /* Map database specific bits to function bits */
......
...@@ -282,6 +282,8 @@ void THD::init(void) ...@@ -282,6 +282,8 @@ void THD::init(void)
#endif #endif
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
server_status= SERVER_STATUS_AUTOCOMMIT; server_status= SERVER_STATUS_AUTOCOMMIT;
if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
options= thd_startup_options; options= thd_startup_options;
open_options=ha_open_options; open_options=ha_open_options;
update_lock_default= (variables.low_priority_updates ? update_lock_default= (variables.low_priority_updates ?
......
...@@ -13332,7 +13332,6 @@ static void test_bug9992() ...@@ -13332,7 +13332,6 @@ static void test_bug9992()
mysql_close(mysql1); mysql_close(mysql1);
} }
/* Bug#10736: cursors and subqueries, memroot management */ /* Bug#10736: cursors and subqueries, memroot management */
static void test_bug10736() static void test_bug10736()
...@@ -13600,6 +13599,34 @@ static void test_bug11656() ...@@ -13600,6 +13599,34 @@ static void test_bug11656()
} }
/*
Check that the server signals when NO_BACKSLASH_ESCAPES mode is in effect,
and mysql_real_escape_string() does the right thing as a result.
*/
static void test_bug10214()
{
MYSQL_RES* res ;
int len;
char out[8];
myheader("test_bug10214");
DIE_UNLESS(!(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES));
len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
DIE_UNLESS(memcmp(out, "a\\'b\\\\c", len) == 0);
mysql_query(mysql, "set sql_mode='NO_BACKSLASH_ESCAPES'");
DIE_UNLESS(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES);
len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
DIE_UNLESS(memcmp(out, "a''b\\c", len) == 0);
mysql_query(mysql, "set sql_mode=''");
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -13839,6 +13866,7 @@ static struct my_tests_st my_tests[]= { ...@@ -13839,6 +13866,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug10794", test_bug10794 }, { "test_bug10794", test_bug10794 },
{ "test_bug11172", test_bug11172 }, { "test_bug11172", test_bug11172 },
{ "test_bug11656", test_bug11656 }, { "test_bug11656", test_bug11656 },
{ "test_bug10214", test_bug10214 },
{ 0, 0 } { 0, 0 }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment