summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <jimw@mysql.com>2005-07-05 09:47:20 -0700
committerunknown <jimw@mysql.com>2005-07-05 09:47:20 -0700
commit63c5a72b314bcf4ad68e120fa2e16caa861bb822 (patch)
treeb9559572d9068a65f3ebaa464b35ff27d369fa20
parent7450eef89a7aac5be282d7be7b22b0c636b5ea74 (diff)
parent390bc0d6195a2042d0534fcfbdeee336f8b394fe (diff)
downloadmariadb-git-63c5a72b314bcf4ad68e120fa2e16caa861bb822.tar.gz
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
-rw-r--r--include/my_sys.h3
-rw-r--r--include/mysql_com.h1
-rw-r--r--libmysql/libmysql.c9
-rw-r--r--mysys/charset.c116
-rw-r--r--sql/set_var.cc9
-rw-r--r--sql/sql_class.cc2
-rw-r--r--tests/mysql_client_test.c30
7 files changed, 160 insertions, 10 deletions
diff --git a/include/my_sys.h b/include/my_sys.h
index a3d6f6827d3..e31659c0652 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -866,6 +866,9 @@ extern void add_compiled_collation(CHARSET_INFO *cs);
extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
char *to, ulong to_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_received(ulong length);
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 88a614bc4a3..969fba4a433 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -148,6 +148,7 @@ enum enum_server_command
*/
#define SERVER_STATUS_LAST_ROW_SENT 128
#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */
+#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512
#define MYSQL_ERRMSG_SIZE 512
#define NET_READ_TIMEOUT 30 /* Timeout on read */
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index e33fd470582..2a4bc5151c1 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1616,7 +1616,14 @@ ulong STDCALL
mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
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);
+ }
}
diff --git a/mysys/charset.c b/mysys/charset.c
index cbd9ba16b4c..4920e7806a2 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -561,11 +561,30 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
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
- to keep old C API, to_length may be 0 to mean "big enough"
- RETURN
- the length of the escaped string or ~0 if it did not fit.
+ To maintain compatibility with the old C API, 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_string_for_mysql(CHARSET_INFO *charset_info,
char *to, ulong to_length,
@@ -573,20 +592,20 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
{
const char *to_start= to;
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
my_bool use_mb_flag= use_mb(charset_info);
#endif
for (end= from + length; from < end; from++)
{
- char escape=0;
+ 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=1;
+ overflow= TRUE;
break;
}
while (tmp_length--)
@@ -636,7 +655,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
{
if (to + 2 > to_end)
{
- overflow=1;
+ overflow= TRUE;
break;
}
*to++= '\\';
@@ -646,7 +665,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
{
if (to + 1 > to_end)
{
- overflow=1;
+ overflow= TRUE;
break;
}
*to++= *from;
@@ -656,3 +675,84 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
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);
+}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 3f991713eb7..ae7e4bd844b 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -3238,7 +3238,16 @@ void fix_sql_mode_var(THD *thd, enum_var_type type)
global_system_variables.sql_mode=
fix_sql_mode(global_system_variables.sql_mode);
else
+ {
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 */
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index a941ba11943..bf6f41d00ed 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -282,6 +282,8 @@ void THD::init(void)
#endif
pthread_mutex_unlock(&LOCK_global_system_variables);
server_status= SERVER_STATUS_AUTOCOMMIT;
+ if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
+ server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
options= thd_startup_options;
open_options=ha_open_options;
update_lock_default= (variables.low_priority_updates ?
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index a80d5e1d1be..0c79925c3eb 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -13332,7 +13332,6 @@ static void test_bug9992()
mysql_close(mysql1);
}
-
/* Bug#10736: cursors and subqueries, memroot management */
static void test_bug10736()
@@ -13601,6 +13600,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
*/
@@ -13839,6 +13866,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug10794", test_bug10794 },
{ "test_bug11172", test_bug11172 },
{ "test_bug11656", test_bug11656 },
+ { "test_bug10214", test_bug10214 },
{ 0, 0 }
};