Skip to content

Commit c4a8b7a

Browse files
committed
Bug#32824429 - SIGNAL 11 / VIRTUAL LONGLONG ITEM_FUNC_IN::VAL_INT():
ASSERTION `IN_ITEM' Problem: Floating point literal in query was identified as real number, then converted to zerofilled string to compare with zerofilled float column. Due to being identified as a real number the comparison was attempted in a real context, even after the value was converted to string. Solution: Convert zerofill numbers to zerofilled Item_string only when used in a string context, eg. concat or comparing with a string constant. (cherry picked from commit ce4d1d1b605535db3f00bedc810bce93e7b7ccc0) Change-Id: Id1e3ddcb917471258ca5e003e075fcb0b4a09b21
1 parent ee22af8 commit c4a8b7a

File tree

8 files changed

+77
-78
lines changed

8 files changed

+77
-78
lines changed

mysql-test/r/myisam_icp.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ id select_type table partitions type possible_keys key key_len ref rows filtered
599599
3 SUBQUERY t3 NULL system NULL NULL NULL NULL 1 100.00 NULL
600600
Warnings:
601601
Note 1276 Field or reference 'test.t1.c1' of SELECT #2 was resolved in SELECT #1
602-
Note 1003 /* select#1 */ select '2' AS `i1` from dual where exists(/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` where ((`test`.`t2`.`c1` = 'v') and (`test`.`t2`.`c2` = (/* select#3 */ select min('v') from dual))))
602+
Note 1003 /* select#1 */ select '2' AS `i1` from dual where exists(/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` where ((`test`.`t2`.`c1` = 'v') and (`test`.`t2`.`c2` = (/* select#3 */ select min('v') from dual)) and ((/* select#3 */ select min('v') from dual) <> 'w')))
603603
SELECT i1
604604
FROM t1
605605
WHERE EXISTS (SELECT t2.c1

mysql-test/r/myisam_icp_all.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ id select_type table partitions type possible_keys key key_len ref rows filtered
599599
3 SUBQUERY t3 NULL system NULL NULL NULL NULL 1 100.00 NULL
600600
Warnings:
601601
Note 1276 Field or reference 'test.t1.c1' of SELECT #2 was resolved in SELECT #1
602-
Note 1003 /* select#1 */ select '2' AS `i1` from dual where exists(/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` where ((`test`.`t2`.`c1` = 'v') and (`test`.`t2`.`c2` = (/* select#3 */ select min('v') from dual))))
602+
Note 1003 /* select#1 */ select '2' AS `i1` from dual where exists(/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` where ((`test`.`t2`.`c1` = 'v') and (`test`.`t2`.`c2` = (/* select#3 */ select min('v') from dual)) and ((/* select#3 */ select min('v') from dual) <> 'w')))
603603
SELECT i1
604604
FROM t1
605605
WHERE EXISTS (SELECT t2.c1

mysql-test/r/myisam_icp_none.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ id select_type table partitions type possible_keys key key_len ref rows filtered
598598
3 SUBQUERY t3 NULL system NULL NULL NULL NULL 1 100.00 NULL
599599
Warnings:
600600
Note 1276 Field or reference 'test.t1.c1' of SELECT #2 was resolved in SELECT #1
601-
Note 1003 /* select#1 */ select '2' AS `i1` from dual where exists(/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` where ((`test`.`t2`.`c1` = 'v') and (`test`.`t2`.`c2` = (/* select#3 */ select min('v') from dual))))
601+
Note 1003 /* select#1 */ select '2' AS `i1` from dual where exists(/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` where ((`test`.`t2`.`c1` = 'v') and (`test`.`t2`.`c2` = (/* select#3 */ select min('v') from dual)) and ((/* select#3 */ select min('v') from dual) <> 'w')))
602602
SELECT i1
603603
FROM t1
604604
WHERE EXISTS (SELECT t2.c1

mysql-test/suite/opt_trace/r/subquery_no_prot.result

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,18 @@ t1.a= (SELECT a FROM t2 LIMIT 1) {
431431
"steps": [
432432
{
433433
"transformation": "equality_propagation",
434+
"subselect_evaluation": [
435+
] /* subselect_evaluation */,
436+
"resulting_condition": "(((/* select#2 */ select `t2`.`b` from `t2` limit 1) <> (/* select#3 */ select `t2`.`a` from `t2` limit 1)) and multiple equal((/* select#2 */ select `t2`.`b` from `t2` limit 1), `t1`.`a`))"
437+
},
438+
{
439+
"transformation": "constant_propagation",
440+
"subselect_evaluation": [
441+
] /* subselect_evaluation */,
442+
"resulting_condition": "(((/* select#2 */ select `t2`.`b` from `t2` limit 1) <> (/* select#3 */ select `t2`.`a` from `t2` limit 1)) and multiple equal((/* select#2 */ select `t2`.`b` from `t2` limit 1), `t1`.`a`))"
443+
},
444+
{
445+
"transformation": "trivial_condition_removal",
434446
"subselect_evaluation": [
435447
{
436448
"subselect_execution": {
@@ -477,27 +489,8 @@ t1.a= (SELECT a FROM t2 LIMIT 1) {
477489
}
478490
] /* steps */
479491
} /* subselect_execution */
480-
},
481-
{
482-
"subselect_execution": {
483-
"select#": 2,
484-
"steps": [
485-
] /* steps */
486-
} /* subselect_execution */
487492
}
488493
] /* subselect_evaluation */,
489-
"resulting_condition": "((NULL <> (/* select#3 */ select `t2`.`a` from `t2` limit 1)) and multiple equal((/* select#2 */ select NULL from `t2` limit 1), `t1`.`a`))"
490-
},
491-
{
492-
"transformation": "constant_propagation",
493-
"subselect_evaluation": [
494-
] /* subselect_evaluation */,
495-
"resulting_condition": "((NULL <> (/* select#3 */ select `t2`.`a` from `t2` limit 1)) and multiple equal((/* select#2 */ select NULL from `t2` limit 1), `t1`.`a`))"
496-
},
497-
{
498-
"transformation": "trivial_condition_removal",
499-
"subselect_evaluation": [
500-
] /* subselect_evaluation */,
501494
"resulting_condition": null
502495
}
503496
] /* steps */

mysql-test/suite/opt_trace/r/subquery_ps_prot.result

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,18 @@ t1.a= (SELECT a FROM t2 LIMIT 1) {
431431
"steps": [
432432
{
433433
"transformation": "equality_propagation",
434+
"subselect_evaluation": [
435+
] /* subselect_evaluation */,
436+
"resulting_condition": "(((/* select#2 */ select `t2`.`b` from `t2` limit 1) <> (/* select#3 */ select `t2`.`a` from `t2` limit 1)) and multiple equal((/* select#2 */ select `t2`.`b` from `t2` limit 1), `t1`.`a`))"
437+
},
438+
{
439+
"transformation": "constant_propagation",
440+
"subselect_evaluation": [
441+
] /* subselect_evaluation */,
442+
"resulting_condition": "(((/* select#2 */ select `t2`.`b` from `t2` limit 1) <> (/* select#3 */ select `t2`.`a` from `t2` limit 1)) and multiple equal((/* select#2 */ select `t2`.`b` from `t2` limit 1), `t1`.`a`))"
443+
},
444+
{
445+
"transformation": "trivial_condition_removal",
434446
"subselect_evaluation": [
435447
{
436448
"subselect_execution": {
@@ -486,18 +498,6 @@ t1.a= (SELECT a FROM t2 LIMIT 1) {
486498
} /* subselect_execution */
487499
}
488500
] /* subselect_evaluation */,
489-
"resulting_condition": "((NULL <> (/* select#3 */ select `t2`.`a` from `t2` limit 1)) and multiple equal((/* select#2 */ select NULL from `t2` limit 1), `t1`.`a`))"
490-
},
491-
{
492-
"transformation": "constant_propagation",
493-
"subselect_evaluation": [
494-
] /* subselect_evaluation */,
495-
"resulting_condition": "((NULL <> (/* select#3 */ select `t2`.`a` from `t2` limit 1)) and multiple equal((/* select#2 */ select NULL from `t2` limit 1), `t1`.`a`))"
496-
},
497-
{
498-
"transformation": "trivial_condition_removal",
499-
"subselect_evaluation": [
500-
] /* subselect_evaluation */,
501501
"resulting_condition": null
502502
}
503503
] /* steps */

sql/item.cc

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6187,16 +6187,15 @@ static void convert_zerofill_number_to_string(Item **item, Field_num *field)
61876187

61886188

61896189
/**
6190-
Set a pointer to the multiple equality the field reference belongs to
6191-
(if any).
6190+
If field matches a multiple equality, set a pointer to that object in the
6191+
field. Also return a pointer to a constant value that can be substituted for
6192+
a field (if any).
61926193
6193-
The function looks for a multiple equality containing the field item
6194-
among those referenced by arg.
6195-
In the case such equality exists the function does the following.
6196-
If the found multiple equality contains a constant, then the field
6197-
reference is substituted for this constant, otherwise it sets a pointer
6198-
to the multiple equality in the field item.
6194+
A constant value is returned only if certain conditions are met (see
6195+
implementation).
61996196
6197+
In addition, a numeric field with a zerofill attribute can be substituted
6198+
with a zerofilled value if it is to be used in a character string context.
62006199
62016200
@param arg reference to list of multiple equalities where
62026201
the field (this object) is to be looked for
@@ -6210,37 +6209,35 @@ static void convert_zerofill_number_to_string(Item **item, Field_num *field)
62106209
- pointer to the field item, otherwise.
62116210
*/
62126211

6213-
Item *Item_field::equal_fields_propagator(uchar *arg)
6214-
{
6215-
if (no_const_subst)
6216-
return this;
6212+
Item *Item_field::equal_fields_propagator(uchar *arg) {
6213+
if (no_const_subst) return this;
62176214
item_equal= find_item_equal((COND_EQUAL *) arg);
62186215
Item *item= 0;
6219-
if (item_equal)
6220-
item= item_equal->get_const();
6216+
if (item_equal) item = item_equal->get_const();
62216217
/*
6222-
Disable const propagation for items used in different comparison contexts.
6223-
This must be done because, for example, Item_hex_string->val_int() is not
6224-
the same as (Item_hex_string->val_str() in BINARY column)->val_int().
6225-
We cannot simply disable the replacement in a particular context (
6226-
e.g. <bin_col> = <int_col> AND <bin_col> = <hex_string>) since
6227-
Items don't know the context they are in and there are functions like
6228-
IF (<hex_string>, 'yes', 'no').
6218+
Disable const propagation if the constant is nullable and this item is not.
6219+
If propagation was allowed in this case, it would also be necessary to
6220+
propagate the new nullability up to the parents of this item.
62296221
*/
6230-
if (!item || !has_compatible_context(item))
6231-
item= this;
6232-
else if (field && (field->flags & ZEROFILL_FLAG) && IS_NUM(field->type()))
6233-
{
6222+
if (!item || (item->maybe_null && !maybe_null)) {
6223+
return this;
6224+
}
6225+
if ((field->flags & ZEROFILL_FLAG) && cmp_context == STRING_RESULT &&
6226+
IS_NUM(field->type())) {
62346227
/*
6235-
We don't need to zero-fill timestamp columns here because they will be
6236-
first converted to a string (in date/time format) and compared as such if
6237-
compared with another string.
6228+
Convert numeric constant to a zero-filled string if the field has
6229+
the zerofill property and is wanted in a string context.
62386230
*/
6239-
if (item && field->type() != FIELD_TYPE_TIMESTAMP && cmp_context != INT_RESULT
6240-
&& item->real_item()->type() != Item::REAL_ITEM)
6241-
convert_zerofill_number_to_string(&item, (Field_num *)field);
6242-
else
6243-
item= this;
6231+
convert_zerofill_number_to_string(&item, down_cast<Field_num *>(field));
6232+
return item;
6233+
}
6234+
if (!has_compatible_context(item)) {
6235+
/*
6236+
If the field does not have the zerofill property, the items must have
6237+
compatible comparison contexts, otherwise the resolved metadata for
6238+
the items and the referencing objects might become invalid.
6239+
*/
6240+
return this;
62446241
}
62456242
return item;
62466243
}

sql/item.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2181,18 +2181,24 @@ class Item : public Parse_tree_node
21812181
compared as DATETIME values by the Arg_comparator.
21822182
FALSE otherwise.
21832183
*/
2184-
inline bool has_compatible_context(Item *item) const
2185-
{
2186-
/* Same context. */
2187-
if (cmp_context == (Item_result)-1 || item->cmp_context == cmp_context)
2184+
inline bool has_compatible_context(Item *item) const {
2185+
// If no explicit context has been set, assume the same type as the item
2186+
const Item_result this_context =
2187+
cmp_context == (Item_result)-1 ? result_type() : cmp_context;
2188+
const Item_result other_context = item->cmp_context == (Item_result)-1
2189+
? item->result_type()
2190+
: item->cmp_context;
2191+
2192+
// Check if both items have the same context
2193+
if (this_context == other_context) {
21882194
return TRUE;
2195+
}
21892196
/* DATETIME comparison context. */
21902197
if (is_temporal_with_date())
2191-
return item->is_temporal_with_date() ||
2192-
item->cmp_context == STRING_RESULT;
2198+
return item->is_temporal_with_date() || other_context == STRING_RESULT;
21932199
if (item->is_temporal_with_date())
2194-
return is_temporal_with_date() || cmp_context == STRING_RESULT;
2195-
return FALSE;
2200+
return is_temporal_with_date() || this_context == STRING_RESULT;
2201+
return false;
21962202
}
21972203
virtual Field::geometry_type get_geometry_type() const
21982204
{ return Field::GEOM_GEOMETRY; };

sql/item_strfunc.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -967,9 +967,10 @@ void Item_func_concat::fix_length_and_dec()
967967
if (agg_arg_charsets_for_string_result(collation, args, arg_count))
968968
return;
969969

970-
for (uint i=0 ; i < arg_count ; i++)
970+
for (uint i=0 ; i < arg_count ; i++) {
971+
args[i]->cmp_context = STRING_RESULT;
971972
char_length+= args[i]->max_char_length();
972-
973+
}
973974
fix_char_length_ulonglong(char_length);
974975
}
975976

@@ -1233,8 +1234,10 @@ void Item_func_concat_ws::fix_length_and_dec()
12331234
so, (arg_count - 2) is safe here.
12341235
*/
12351236
char_length= (ulonglong) args[0]->max_char_length() * (arg_count - 2);
1236-
for (uint i=1 ; i < arg_count ; i++)
1237+
for (uint i=1 ; i < arg_count ; i++) {
1238+
args[i]->cmp_context = STRING_RESULT;
12371239
char_length+= args[i]->max_char_length();
1240+
}
12381241

12391242
fix_char_length_ulonglong(char_length);
12401243
}

0 commit comments

Comments
 (0)