summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authordlenev@brandersnatch.localdomain <>2004-06-22 19:27:16 +0400
committerdlenev@brandersnatch.localdomain <>2004-06-22 19:27:16 +0400
commiteea19e52352e739cda7ea7b137710356809d04ec (patch)
treed0e1e3af3a439cdd96e7e95fea25e1dc8d02a760 /sql
parent6b45c24d398e23a758917e3d03c9644c17d60bb3 (diff)
downloadmariadb-git-eea19e52352e739cda7ea7b137710356809d04ec.tar.gz
Fix for Bug# 4200 "Parse error on LIKE ESCAPE with parameter binding"
Now ESCAPE in LIKE will accept not only string literal but constant delimited expression.
Diffstat (limited to 'sql')
-rw-r--r--sql/item_cmpfunc.cc87
-rw-r--r--sql/item_cmpfunc.h6
-rw-r--r--sql/sql_help.cc2
-rw-r--r--sql/sql_yacc.yy12
4 files changed, 63 insertions, 44 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 446d72ac143..0c86b5f7d52 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2151,49 +2151,62 @@ Item_func::optimize_type Item_func_like::select_optimize() const
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
DBUG_ASSERT(fixed == 0);
- if (Item_bool_func2::fix_fields(thd, tlist, ref))
+ if (Item_bool_func2::fix_fields(thd, tlist, ref) ||
+ escape_item->fix_fields(thd, tlist, &escape_item))
return 1;
- /*
- We could also do boyer-more for non-const items, but as we would have to
- recompute the tables for each row it's not worth it.
- */
- if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
- !(specialflag & SPECIAL_NO_NEW_FUNC))
+ if (!escape_item->const_during_execution())
{
- String* res2 = args[1]->val_str(&tmp_value2);
- if (!res2)
- return 0; // Null argument
-
- const size_t len = res2->length();
- const char* first = res2->ptr();
- const char* last = first + len - 1;
+ my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
+ return 1;
+ }
+
+ if (escape_item->const_item())
+ {
+ /* If we are on execution stage */
+ String *escape_str= escape_item->val_str(&tmp_value1);
+ escape= escape_str ? *(escape_str->ptr()) : '\\';
+
/*
- len must be > 2 ('%pattern%')
- heuristic: only do TurboBM for pattern_len > 2
+ We could also do boyer-more for non-const items, but as we would have to
+ recompute the tables for each row it's not worth it.
*/
-
- if (len > MIN_TURBOBM_PATTERN_LEN + 2 &&
- *first == wild_many &&
- *last == wild_many)
- {
- const char* tmp = first + 1;
- for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
- canDoTurboBM = (tmp == last) && !use_mb(args[0]->collation.collation);
- }
-
- if (canDoTurboBM)
+ if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
+ !(specialflag & SPECIAL_NO_NEW_FUNC))
{
- pattern = first + 1;
- pattern_len = len - 2;
- DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
- int *suff = (int*) thd->alloc(sizeof(int)*((pattern_len + 1)*2+
- alphabet_size));
- bmGs = suff + pattern_len + 1;
- bmBc = bmGs + pattern_len + 1;
- turboBM_compute_good_suffix_shifts(suff);
- turboBM_compute_bad_character_shifts();
- DBUG_PRINT("info",("done"));
+ String* res2 = args[1]->val_str(&tmp_value2);
+ if (!res2)
+ return 0; // Null argument
+
+ const size_t len = res2->length();
+ const char* first = res2->ptr();
+ const char* last = first + len - 1;
+ /*
+ len must be > 2 ('%pattern%')
+ heuristic: only do TurboBM for pattern_len > 2
+ */
+
+ if (len > MIN_TURBOBM_PATTERN_LEN + 2 &&
+ *first == wild_many &&
+ *last == wild_many)
+ {
+ const char* tmp = first + 1;
+ for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
+ canDoTurboBM = (tmp == last) && !use_mb(args[0]->collation.collation);
+ }
+ if (canDoTurboBM)
+ {
+ pattern = first + 1;
+ pattern_len = len - 2;
+ DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
+ int *suff = (int*) thd->alloc(sizeof(int)*((pattern_len + 1)*2+
+ alphabet_size));
+ bmGs = suff + pattern_len + 1;
+ bmBc = bmGs + pattern_len + 1;
+ turboBM_compute_good_suffix_shifts(suff);
+ turboBM_compute_bad_character_shifts();
+ DBUG_PRINT("info",("done"));
+ }
}
}
return 0;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index ef80c060c03..4a7e7e06f10 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -841,12 +841,14 @@ class Item_func_like :public Item_bool_func2
bool turboBM_matches(const char* text, int text_len) const;
enum { alphabet_size = 256 };
+ Item *escape_item;
+
public:
char escape;
- Item_func_like(Item *a,Item *b, char* escape_arg)
+ Item_func_like(Item *a,Item *b, Item *escape_arg)
:Item_bool_func2(a,b), canDoTurboBM(false), pattern(0), pattern_len(0),
- bmGs(0), bmBc(0), escape(*escape_arg) {}
+ bmGs(0), bmBc(0), escape_item(escape_arg) {}
longlong val_int();
enum Functype functype() const { return LIKE_FUNC; }
optimize_type select_optimize() const;
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 44293b8214f..c5a49cab3b5 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -626,7 +626,7 @@ 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()),
- (char*) "\\");
+ new Item_string("\\",1,&my_charset_latin1));
if (thd->is_fatal_error)
return 0; // OOM
return prepare_simple_select(thd,cond,tables,table,error);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 89915852b9b..f4c249c2676 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -606,7 +606,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <simple_string>
remember_name remember_end opt_ident opt_db text_or_password
- opt_escape opt_constraint constraint
+ opt_constraint constraint
%type <string>
text_string opt_gconcat_separator
@@ -634,7 +634,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
using_list expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init geometry_function
- signed_literal now_or_signed_literal
+ signed_literal now_or_signed_literal opt_escape
%type <item_num>
NUM_literal
@@ -3570,8 +3570,12 @@ having_clause:
;
opt_escape:
- ESCAPE_SYM TEXT_STRING_literal { $$= $2.str; }
- | /* empty */ { $$= (char*) "\\"; };
+ ESCAPE_SYM simple_expr { $$= $2; }
+ | /* empty */
+ {
+ $$= new Item_string("\\", 1, &my_charset_latin1);
+ }
+ ;
/*