Skip to content

Commit b75c003

Browse files
author
Alexander Barkov
committed
MDEV-8816 Equal field propagation is not applied for WHERE varbinary_column>=_utf8'a' COLLATE utf8_general_ci AND varbinary_column='A';
1. Removing the legacy code that disabled equal field propagation in cases when comparison is done as VARBINARY. This is now correctly handled by the new propagation code in Item_xxx::propagate_equal_fields() and Field_str::can_be_substituted_to_equal_item (the bug fix). 2. Also, removing legacy (pre-MySQL-4.1) Arg_comparator methods compare_binary_string() and compare_e_binary_string(), as VARBINARY comparison is correcty handled in compare_string() and compare_e_string() by the corresponding VARBINARY collation handler implemented in my_charset_bin. (not really a part of the bug fix)
1 parent da3ec3d commit b75c003

File tree

6 files changed

+31
-95
lines changed

6 files changed

+31
-95
lines changed

mysql-test/r/ctype_utf8.result

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10198,5 +10198,20 @@ Warnings:
1019810198
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = '1ë1') and (`test`.`t1`.`a` in (1,2,'x')))
1019910199
DROP TABLE IF EXISTS t1;
1020010200
#
10201+
# MDEV-8816 Equal field propagation is not applied for WHERE varbinary_column>=_utf8'a' COLLATE utf8_swedish_ci AND varbinary_column='A';
10202+
#
10203+
CREATE TABLE t1 (c VARBINARY(10));
10204+
INSERT INTO t1 VALUES ('a'),('A');
10205+
SELECT * FROM t1 WHERE c>=_utf8'a' COLLATE utf8_general_ci AND c='A';
10206+
c
10207+
A
10208+
EXPLAIN EXTENDED
10209+
SELECT * FROM t1 WHERE c>=_utf8'a' COLLATE utf8_general_ci AND c='A';
10210+
id select_type table type possible_keys key key_len ref rows filtered Extra
10211+
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
10212+
Warnings:
10213+
Note 1003 select `test`.`t1`.`c` AS `c` from `test`.`t1` where (`test`.`t1`.`c` = 'A')
10214+
DROP TABLE t1;
10215+
#
1020110216
# End of 10.1 tests
1020210217
#

mysql-test/t/ctype_utf8.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,6 +1833,17 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a IN (1,2,'x') AND a='1ë1';
18331833
DROP TABLE IF EXISTS t1;
18341834

18351835

1836+
--echo #
1837+
--echo # MDEV-8816 Equal field propagation is not applied for WHERE varbinary_column>=_utf8'a' COLLATE utf8_swedish_ci AND varbinary_column='A';
1838+
--echo #
1839+
CREATE TABLE t1 (c VARBINARY(10));
1840+
INSERT INTO t1 VALUES ('a'),('A');
1841+
SELECT * FROM t1 WHERE c>=_utf8'a' COLLATE utf8_general_ci AND c='A';
1842+
EXPLAIN EXTENDED
1843+
SELECT * FROM t1 WHERE c>=_utf8'a' COLLATE utf8_general_ci AND c='A';
1844+
DROP TABLE t1;
1845+
1846+
18361847
--echo #
18371848
--echo # End of 10.1 tests
18381849
--echo #

sql/item.cc

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,8 +2140,6 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname,
21402140
res= TRUE;
21412141
break; // we cannot return here, we need to restore "arena".
21422142
}
2143-
if ((*arg)->type() == Item::FIELD_ITEM)
2144-
((Item_field *)(*arg))->no_const_subst= 1;
21452143
/*
21462144
If in statement prepare, then we create a converter for two
21472145
constant items, do it once and then reuse it.
@@ -2226,7 +2224,7 @@ void Item_ident_for_show::make_field(Send_field *tmp_field)
22262224

22272225
Item_field::Item_field(THD *thd, Field *f)
22282226
:Item_ident(thd, 0, NullS, *f->table_name, f->field_name),
2229-
item_equal(0), no_const_subst(0),
2227+
item_equal(0),
22302228
have_privileges(0), any_privileges(0)
22312229
{
22322230
set_field(f);
@@ -2249,7 +2247,7 @@ Item_field::Item_field(THD *thd, Field *f)
22492247
Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
22502248
Field *f)
22512249
:Item_ident(thd, context_arg, f->table->s->db.str, *f->table_name, f->field_name),
2252-
item_equal(0), no_const_subst(0),
2250+
item_equal(0),
22532251
have_privileges(0), any_privileges(0)
22542252
{
22552253
/*
@@ -2292,7 +2290,7 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
22922290
const char *db_arg,const char *table_name_arg,
22932291
const char *field_name_arg)
22942292
:Item_ident(thd, context_arg, db_arg, table_name_arg, field_name_arg),
2295-
field(0), item_equal(0), no_const_subst(0),
2293+
field(0), item_equal(0),
22962294
have_privileges(0), any_privileges(0)
22972295
{
22982296
SELECT_LEX *select= thd->lex->current_select;
@@ -2310,7 +2308,6 @@ Item_field::Item_field(THD *thd, Item_field *item)
23102308
:Item_ident(thd, item),
23112309
field(item->field),
23122310
item_equal(item->item_equal),
2313-
no_const_subst(item->no_const_subst),
23142311
have_privileges(item->have_privileges),
23152312
any_privileges(item->any_privileges)
23162313
{
@@ -5335,7 +5332,7 @@ Item *Item_field::propagate_equal_fields(THD *thd,
53355332
const Context &ctx,
53365333
COND_EQUAL *arg)
53375334
{
5338-
if (no_const_subst || !(item_equal= find_item_equal(arg)))
5335+
if (!(item_equal= find_item_equal(arg)))
53395336
return this;
53405337
if (!field->can_be_substituted_to_equal_item(ctx, item_equal))
53415338
{
@@ -5372,20 +5369,6 @@ Item *Item_field::propagate_equal_fields(THD *thd,
53725369
}
53735370

53745371

5375-
/**
5376-
Mark the item to not be part of substitution if it's not a binary item.
5377-
5378-
See comments in Arg_comparator::set_compare_func() for details.
5379-
*/
5380-
5381-
bool Item_field::set_no_const_sub(uchar *arg)
5382-
{
5383-
if (field->charset() != &my_charset_bin)
5384-
no_const_subst=1;
5385-
return FALSE;
5386-
}
5387-
5388-
53895372
/**
53905373
Replace an Item_field for an equal Item_field that evaluated earlier
53915374
(if any).

sql/item.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,7 +1520,6 @@ class Item: public Value_source, public Type_std_attributes
15201520
return trace_unsupported_by_check_vcol_func_processor(full_name());
15211521
}
15221522

1523-
virtual bool set_no_const_sub(uchar *arg) { return FALSE; }
15241523
/* arg points to REPLACE_EQUAL_FIELD_ARG object */
15251524
virtual Item *replace_equal_field(THD *thd, uchar *arg) { return this; }
15261525
/*
@@ -2333,7 +2332,6 @@ class Item_field :public Item_ident
23332332
public:
23342333
Field *field;
23352334
Item_equal *item_equal;
2336-
bool no_const_subst;
23372335
/*
23382336
if any_privileges set to TRUE then here real effective privileges will
23392337
be stored
@@ -2465,7 +2463,6 @@ class Item_field :public Item_ident
24652463
void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; }
24662464
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
24672465
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
2468-
bool set_no_const_sub(uchar *arg);
24692466
Item *replace_equal_field(THD *thd, uchar *arg);
24702467
inline uint32 max_disp_length() { return field->max_display_length(); }
24712468
Item_field *field_for_view_update() { return this; }

sql/item_cmpfunc.cc

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -554,32 +554,6 @@ int Arg_comparator::set_compare_func(Item_func_or_sum *item, Item_result type)
554554
}
555555
break;
556556
}
557-
case STRING_RESULT:
558-
{
559-
if (cmp_collation.collation == &my_charset_bin)
560-
{
561-
/*
562-
We are using BLOB/BINARY/VARBINARY, change to compare byte by byte,
563-
without removing end space
564-
*/
565-
if (func == &Arg_comparator::compare_string)
566-
func= &Arg_comparator::compare_binary_string;
567-
else if (func == &Arg_comparator::compare_e_string)
568-
func= &Arg_comparator::compare_e_binary_string;
569-
570-
/*
571-
As this is binary compassion, mark all fields that they can't be
572-
transformed. Otherwise we would get into trouble with comparisons
573-
like:
574-
WHERE col= 'j' AND col LIKE BINARY 'j'
575-
which would be transformed to:
576-
WHERE col= 'j'
577-
*/
578-
(*a)->walk(&Item::set_no_const_sub, FALSE, (uchar*) 0);
579-
(*b)->walk(&Item::set_no_const_sub, FALSE, (uchar*) 0);
580-
}
581-
break;
582-
}
583557
case INT_RESULT:
584558
{
585559
if (func == &Arg_comparator::compare_int_signed)
@@ -598,6 +572,7 @@ int Arg_comparator::set_compare_func(Item_func_or_sum *item, Item_result type)
598572
}
599573
break;
600574
}
575+
case STRING_RESULT:
601576
case DECIMAL_RESULT:
602577
break;
603578
case REAL_RESULT:
@@ -943,38 +918,6 @@ int Arg_comparator::compare_string()
943918
}
944919

945920

946-
/**
947-
Compare strings byte by byte. End spaces are also compared.
948-
949-
@retval
950-
<0 *a < *b
951-
@retval
952-
0 *b == *b
953-
@retval
954-
>0 *a > *b
955-
*/
956-
957-
int Arg_comparator::compare_binary_string()
958-
{
959-
String *res1,*res2;
960-
if ((res1= (*a)->val_str(&value1)))
961-
{
962-
if ((res2= (*b)->val_str(&value2)))
963-
{
964-
if (set_null)
965-
owner->null_value= 0;
966-
uint res1_length= res1->length();
967-
uint res2_length= res2->length();
968-
int cmp= memcmp(res1->ptr(), res2->ptr(), MY_MIN(res1_length,res2_length));
969-
return cmp ? cmp : (int) (res1_length - res2_length);
970-
}
971-
}
972-
if (set_null)
973-
owner->null_value= 1;
974-
return -1;
975-
}
976-
977-
978921
/**
979922
Compare strings, but take into account that NULL == NULL.
980923
*/
@@ -991,17 +934,6 @@ int Arg_comparator::compare_e_string()
991934
}
992935

993936

994-
int Arg_comparator::compare_e_binary_string()
995-
{
996-
String *res1,*res2;
997-
res1= (*a)->val_str(&value1);
998-
res2= (*b)->val_str(&value2);
999-
if (!res1 || !res2)
1000-
return MY_TEST(res1 == res2);
1001-
return MY_TEST(stringcmp(res1, res2) == 0);
1002-
}
1003-
1004-
1005937
int Arg_comparator::compare_real()
1006938
{
1007939
/*

sql/item_cmpfunc.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ class Arg_comparator: public Sql_alloc
8686
inline int compare() { return (this->*func)(); }
8787

8888
int compare_string(); // compare args[0] & args[1]
89-
int compare_binary_string(); // compare args[0] & args[1]
9089
int compare_real(); // compare args[0] & args[1]
9190
int compare_decimal(); // compare args[0] & args[1]
9291
int compare_int_signed(); // compare args[0] & args[1]
@@ -95,7 +94,6 @@ class Arg_comparator: public Sql_alloc
9594
int compare_int_unsigned();
9695
int compare_row(); // compare args[0] & args[1]
9796
int compare_e_string(); // compare args[0] & args[1]
98-
int compare_e_binary_string(); // compare args[0] & args[1]
9997
int compare_e_real(); // compare args[0] & args[1]
10098
int compare_e_decimal(); // compare args[0] & args[1]
10199
int compare_e_int(); // compare args[0] & args[1]

0 commit comments

Comments
 (0)