Commit a587ded2 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-24346 valgrind error in main.precedence

in queries like

  create view v1 as select 2 like 1 escape (3 in (select 0 union select 1));
  select 2 union select * from v1;

Item_func_like::escape was left uninitialized, because
Item_in_optimizer is const_during_execution()
but not actually const_item() during execution.

It's not, because const subquery evaluation was disabled for derived.
Practically it only needs to be disabled for multi-update
that runs fix_fields() before all tables are locked.
parent 5785de72
...@@ -81,4 +81,5 @@ CREATE TABLE t1(f1 INT) ENGINE=INNODB; ...@@ -81,4 +81,5 @@ CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1);
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1; UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
ERROR 21000: Operand should contain 1 column(s) ERROR 21000: Operand should contain 1 column(s)
UPDATE (SELECT ((SELECT 1 FROM t1),1) = (1,1) FROM t1 WHERE (SELECT 1 FROM t1)) x, t1 AS d SET d.f1 = 1;
DROP TABLE t1; DROP TABLE t1;
...@@ -35,4 +35,5 @@ CREATE TABLE t1(f1 INT) ENGINE=INNODB; ...@@ -35,4 +35,5 @@ CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1);
--error ER_OPERAND_COLUMNS --error ER_OPERAND_COLUMNS
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1; UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
UPDATE (SELECT ((SELECT 1 FROM t1),1) = (1,1) FROM t1 WHERE (SELECT 1 FROM t1)) x, t1 AS d SET d.f1 = 1;
DROP TABLE t1; DROP TABLE t1;
...@@ -5261,6 +5261,7 @@ void Item_func_like::print(String *str, enum_query_type query_type) ...@@ -5261,6 +5261,7 @@ void Item_func_like::print(String *str, enum_query_type query_type)
longlong Item_func_like::val_int() longlong Item_func_like::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
DBUG_ASSERT(escape != -1);
String* res= args[0]->val_str(&cmp_value1); String* res= args[0]->val_str(&cmp_value1);
if (args[0]->null_value) if (args[0]->null_value)
{ {
...@@ -5352,10 +5353,13 @@ bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str, ...@@ -5352,10 +5353,13 @@ bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str,
my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE"); my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
return TRUE; return TRUE;
} }
IF_DBUG(*escape= -1,);
if (escape_item->const_item()) if (escape_item->const_item())
{ {
/* If we are on execution stage */ /* If we are on execution stage */
/* XXX is it safe to evaluate is_expensive() items here? */
String *escape_str= escape_item->val_str(tmp_str); String *escape_str= escape_item->val_str(tmp_str);
if (escape_str) if (escape_str)
{ {
......
...@@ -738,14 +738,12 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) ...@@ -738,14 +738,12 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
!(derived->derived_result= new (thd->mem_root) select_union(thd))) !(derived->derived_result= new (thd->mem_root) select_union(thd)))
DBUG_RETURN(TRUE); // out of memory DBUG_RETURN(TRUE); // out of memory
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
// st_select_lex_unit::prepare correctly work for single select // st_select_lex_unit::prepare correctly work for single select
if ((res= unit->prepare(thd, derived->derived_result, 0))) if ((res= unit->prepare(thd, derived->derived_result, 0)))
goto exit; goto exit;
if (derived->with && if (derived->with &&
(res= derived->with->rename_columns_of_derived_unit(thd, unit))) (res= derived->with->rename_columns_of_derived_unit(thd, unit)))
goto exit; goto exit;
lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
if ((res= check_duplicate_names(thd, unit->types, 0))) if ((res= check_duplicate_names(thd, unit->types, 0)))
goto exit; goto exit;
......
...@@ -1534,7 +1534,11 @@ int mysql_multi_update_prepare(THD *thd) ...@@ -1534,7 +1534,11 @@ int mysql_multi_update_prepare(THD *thd)
During prepare phase acquire only S metadata locks instead of SW locks to During prepare phase acquire only S metadata locks instead of SW locks to
keep prepare of multi-UPDATE compatible with concurrent LOCK TABLES WRITE keep prepare of multi-UPDATE compatible with concurrent LOCK TABLES WRITE
and global read lock. and global read lock.
Don't evaluate any subqueries even if constant, because
tables aren't locked yet.
*/ */
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI) if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI)
{ {
if (open_tables(thd, &table_list, &table_count, if (open_tables(thd, &table_list, &table_count,
...@@ -1557,6 +1561,9 @@ int mysql_multi_update_prepare(THD *thd) ...@@ -1557,6 +1561,9 @@ int mysql_multi_update_prepare(THD *thd)
{ {
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
(void) read_statistics_for_tables_if_needed(thd, table_list); (void) read_statistics_for_tables_if_needed(thd, table_list);
/* @todo: downgrade the metadata locks here. */ /* @todo: downgrade the metadata locks here. */
......
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