summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/analyse.result6
-rw-r--r--mysql-test/t/analyse.test4
-rw-r--r--sql/sql_analyse.cc59
3 files changed, 68 insertions, 1 deletions
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index b51afab5b54..8013bc516bb 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -96,3 +96,9 @@ select * from t2;
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
test.t1.a 1 2 1 1 0 0 1.5000 0.5000 ENUM('1','2') NOT NULL
drop table t1,t2;
+create table t1 (v varchar(128));
+insert into t1 values ('abc'),('abc\'def\\hij\"klm\0opq'),('\''),('\"'),('\\'),('a\0'),('b\''),('c\"'),('d\\'),('\'b'),('\"c'),('\\d'),('a\0\0\0b'),('a\'\'\'\'b'),('a\"\"\"\"b'),('a\\\\\\\\b'),('\'\0\\\"'),('\'\''),('\"\"'),('\\\\'),('The\ZEnd');
+select * from t1 procedure analyse();
+Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
+test.t1.v " \\ 1 19 0 0 3.7619 NULL ENUM('"','""','"c','\'\0\\"','\'','\'\'','\'b','a\0\0\0b','a\0','a""""b','a\'\'\'\'b','abc','abc\'def\\hij"klm\0opq','a\\\\\\\\b','b\'','c"','d\\','The\ZEnd','\\','\\d','\\\\') NOT NULL
+drop table t1;
diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test
index 47f3473584b..34343c2b7bf 100644
--- a/mysql-test/t/analyse.test
+++ b/mysql-test/t/analyse.test
@@ -38,3 +38,7 @@ select * from t2;
insert into t2 select * from t1 procedure analyse();
select * from t2;
drop table t1,t2;
+create table t1 (v varchar(128));
+insert into t1 values ('abc'),('abc\'def\\hij\"klm\0opq'),('\''),('\"'),('\\'),('a\0'),('b\''),('c\"'),('d\\'),('\'b'),('\"c'),('\\d'),('a\0\0\0b'),('a\'\'\'\'b'),('a\"\"\"\"b'),('a\\\\\\\\b'),('\'\0\\\"'),('\'\''),('\"\"'),('\\\\'),('The\ZEnd');
+select * from t1 procedure analyse();
+drop table t1;
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 1e0aebbc1ec..5265857f3b1 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -59,6 +59,7 @@ int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
return compare_ulonglong(s,t);
}
+static bool append_escaped(String *to_str, String *from_str);
Procedure *
proc_analyse_init(THD *thd, ORDER *param, select_result *result,
@@ -890,7 +891,8 @@ int collect_string(String *element,
else
info->found = 1;
info->str->append('\'');
- info->str->append(*element);
+ if (append_escaped(info->str, element))
+ return 1;
info->str->append('\'');
return 0;
} // collect_string
@@ -1025,3 +1027,58 @@ uint check_ulonglong(const char *str, uint length)
while (*cmp && *cmp++ == *str++) ;
return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
} /* check_ulonlong */
+
+
+
+/*
+ FUNCTION: append_escaped()
+
+ DESCRIPTION
+ append_escaped() takes a String type variable, where it appends
+ escaped the second argument. Only characters that require escaping
+ will be escaped.
+
+ ARGUMENTS
+ A pointer to a String variable, where results will be appended
+ A pointer to a String variable, which is appended to the result
+ String, escaping those characters that require it.
+
+ RETURN VALUES
+ 0 Success
+ 1 Out of memory
+*/
+
+static bool append_escaped(String *to_str, String *from_str)
+{
+ char *from, *end, c;
+
+ if (to_str->realloc(to_str->length() + from_str->length()))
+ return 1;
+
+ from= (char*) from_str->ptr();
+ end= from + from_str->length();
+ for (; from < end; from++)
+ {
+ c= *from;
+ switch (c) {
+ case '\0':
+ c= '0';
+ break;
+ case '\032':
+ c= 'Z';
+ break;
+ case '\\':
+ case '\'':
+ break;
+ default:
+ goto normal_character;
+ }
+ if (to_str->append('\\'))
+ return 1;
+
+ normal_character:
+ if (to_str->append(c))
+ return 1;
+ }
+ return 0;
+}