Commit 991b6f14 authored by andrey@lmy004's avatar andrey@lmy004

fix for bug #12595 (ESCAPE must be exactly 1 character long)

ESCAPE has length of 1 if specified and sql_mode is NO_BACKSLASH_ESCAPES
or has length of 0 or 1 in every other situation.
(approved patch applied on a up-to-date tree re-commit) 
parent 70c816c8
......@@ -2965,6 +2965,63 @@ NULL
SELECT IFNULL(NULL, NULL);
IFNULL(NULL, NULL)
NULL
SET @OLD_SQL_MODE12595=@@SQL_MODE, @@SQL_MODE='';
SHOW LOCAL VARIABLES LIKE 'SQL_MODE';
Variable_name Value
sql_mode
CREATE TABLE BUG_12595(a varchar(100));
INSERT INTO BUG_12595 VALUES ('hakan%'), ('hakank'), ("ha%an");
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%';
a
hakan%
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan*%' ESCAPE '*';
a
hakan%
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan**%' ESCAPE '**';
ERROR HY000: Incorrect arguments to ESCAPE
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan%' ESCAPE '';
a
hakan%
hakank
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%' ESCAPE '';
a
SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE 0x5c;
a
ha%an
SELECT * FROM BUG_12595 WHERE a LIKE 'ha%%an' ESCAPE '%';
a
ha%an
SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE '\\';
a
ha%an
SELECT * FROM BUG_12595 WHERE a LIKE 'ha|%an' ESCAPE '|';
a
ha%an
SET @@SQL_MODE='NO_BACKSLASH_ESCAPES';
SHOW LOCAL VARIABLES LIKE 'SQL_MODE';
Variable_name Value
sql_mode NO_BACKSLASH_ESCAPES
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%';
a
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan*%' ESCAPE '*';
a
hakan%
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan**%' ESCAPE '**';
ERROR HY000: Incorrect arguments to ESCAPE
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%' ESCAPE '\\';
ERROR HY000: Incorrect arguments to ESCAPE
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan%' ESCAPE '';
ERROR HY000: Incorrect arguments to ESCAPE
SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE 0x5c;
a
ha%an
SELECT * FROM BUG_12595 WHERE a LIKE 'ha|%an' ESCAPE '|';
a
ha%an
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\n%' ESCAPE '\n';
ERROR HY000: Incorrect arguments to ESCAPE
SET @@SQL_MODE=@OLD_SQL_MODE12595;
DROP TABLE BUG_12595;
create table t1 (a char(1));
create table t2 (a char(1));
insert into t1 values ('a'),('b'),('c');
......
......@@ -2517,6 +2517,45 @@ SELECT CAST(IFNULL(NULL, NULL) AS DECIMAL);
SELECT ABS(IFNULL(NULL, NULL));
SELECT IFNULL(NULL, NULL);
#
# BUG #12595 (ESCAPE must be exactly one)
#
SET @OLD_SQL_MODE12595=@@SQL_MODE, @@SQL_MODE='';
SHOW LOCAL VARIABLES LIKE 'SQL_MODE';
CREATE TABLE BUG_12595(a varchar(100));
INSERT INTO BUG_12595 VALUES ('hakan%'), ('hakank'), ("ha%an");
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%';
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan*%' ESCAPE '*';
-- error 1210
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan**%' ESCAPE '**';
# this should work when sql_mode is not NO_BACKSLASH_ESCAPES
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan%' ESCAPE '';
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%' ESCAPE '';
SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE 0x5c;
SELECT * FROM BUG_12595 WHERE a LIKE 'ha%%an' ESCAPE '%';
SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE '\\';
SELECT * FROM BUG_12595 WHERE a LIKE 'ha|%an' ESCAPE '|';
SET @@SQL_MODE='NO_BACKSLASH_ESCAPES';
SHOW LOCAL VARIABLES LIKE 'SQL_MODE';
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%';
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan*%' ESCAPE '*';
-- error 1210
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan**%' ESCAPE '**';
-- error 1210
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\%' ESCAPE '\\';
#this gives an error when NO_BACKSLASH_ESCAPES is set
-- error 1210
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan%' ESCAPE '';
SELECT * FROM BUG_12595 WHERE a LIKE 'ha\%an' ESCAPE 0x5c;
SELECT * FROM BUG_12595 WHERE a LIKE 'ha|%an' ESCAPE '|';
-- error 1210
SELECT * FROM BUG_12595 WHERE a LIKE 'hakan\n%' ESCAPE '\n';
SET @@SQL_MODE=@OLD_SQL_MODE12595;
DROP TABLE BUG_12595;
#
# Bug #6495 Illogical requirement for column qualification in NATURAL join
#
......
......@@ -2958,6 +2958,15 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
String *escape_str= escape_item->val_str(&tmp_value1);
if (escape_str)
{
if (escape_used_in_parsing && (
(((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
escape_str->numchars() != 1) ||
escape_str->numchars() > 1)))
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
return TRUE;
}
if (use_mb(cmp.cmp_collation.collation))
{
CHARSET_INFO *cs= escape_str->charset();
......
......@@ -986,12 +986,15 @@ class Item_func_like :public Item_bool_func2
Item *escape_item;
bool escape_used_in_parsing;
public:
int escape;
Item_func_like(Item *a,Item *b, Item *escape_arg)
Item_func_like(Item *a,Item *b, Item *escape_arg, bool escape_used)
:Item_bool_func2(a,b), canDoTurboBM(FALSE), pattern(0), pattern_len(0),
bmGs(0), bmBc(0), escape_item(escape_arg) {}
bmGs(0), bmBc(0), escape_item(escape_arg),
escape_used_in_parsing(escape_used) {}
longlong val_int();
enum Functype functype() const { return LIKE_FUNC; }
optimize_type select_optimize() const;
......
......@@ -599,7 +599,8 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
{
Item *cond= new Item_func_like(new Item_field(pfname),
new Item_string(mask,mlen,pfname->charset()),
new Item_string("\\",1,&my_charset_latin1));
new Item_string("\\",1,&my_charset_latin1),
FALSE);
if (thd->is_fatal_error)
return 0; // OOM
return prepare_simple_select(thd, cond, table, error);
......
......@@ -175,6 +175,7 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->spcont= NULL;
lex->proc_list.first= 0;
lex->query_tables_own_last= 0;
lex->escape_used= FALSE;
if (lex->sroutines.records)
my_hash_reset(&lex->sroutines);
......
......@@ -895,6 +895,8 @@ typedef struct st_lex
*/
uchar *fname_start, *fname_end;
bool escape_used;
st_lex();
virtual ~st_lex()
......
......@@ -4314,9 +4314,9 @@ predicate:
{ $$= new Item_func_eq(new Item_func_soundex($1),
new Item_func_soundex($4)); }
| bit_expr LIKE simple_expr opt_escape
{ $$= new Item_func_like($1,$3,$4); }
{ $$= new Item_func_like($1,$3,$4,Lex->escape_used); }
| bit_expr not LIKE simple_expr opt_escape
{ $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
{ $$= new Item_func_not(new Item_func_like($1,$4,$5, Lex->escape_used)); }
| bit_expr REGEXP bit_expr { $$= new Item_func_regex($1,$3); }
| bit_expr not REGEXP bit_expr
{ $$= negate_expression(YYTHD, new Item_func_regex($1,$4)); }
......@@ -5678,10 +5678,14 @@ having_clause:
;
opt_escape:
ESCAPE_SYM simple_expr { $$= $2; }
ESCAPE_SYM simple_expr
{
Lex->escape_used= TRUE;
$$= $2;
}
| /* empty */
{
Lex->escape_used= FALSE;
$$= ((YYTHD->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ?
new Item_string("", 0, &my_charset_latin1) :
new Item_string("\\", 1, &my_charset_latin1));
......
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