diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result index c0c67707231c4..2e6d57c68fd14 100644 --- a/mysql-test/main/subselect4.result +++ b/mysql-test/main/subselect4.result @@ -3372,5 +3372,11 @@ drop table t1,t2,t3; CREATE TABLE t(c INT); SELECT (SELECT 0 GROUP BY c HAVING (SELECT c)) FROM t GROUP BY c; (SELECT 0 GROUP BY c HAVING (SELECT c)) +# +# MDEV-31632 Unresolvable outer reference causes null pointer exception +# +SELECT 1 union select 2 UNION SELECT 1 from t JOIN t b ON +(SELECT 1 FROM dual WHERE AAA); +ERROR 42S22: Unknown column 'AAA' in 'WHERE' DROP TABLE t; # End of 10.11 tests diff --git a/mysql-test/main/subselect4.test b/mysql-test/main/subselect4.test index 083da1647b27c..f3d68aae1739f 100644 --- a/mysql-test/main/subselect4.test +++ b/mysql-test/main/subselect4.test @@ -2693,6 +2693,15 @@ drop table t1,t2,t3; CREATE TABLE t(c INT); SELECT (SELECT 0 GROUP BY c HAVING (SELECT c)) FROM t GROUP BY c; + +--echo # +--echo # MDEV-31632 Unresolvable outer reference causes null pointer exception +--echo # + +--error ER_BAD_FIELD_ERROR +SELECT 1 union select 2 UNION SELECT 1 from t JOIN t b ON + (SELECT 1 FROM dual WHERE AAA); + DROP TABLE t; --echo # End of 10.11 tests diff --git a/sql/item.cc b/sql/item.cc index da3219d7545e4..b584df6912133 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5922,10 +5922,19 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) select= outer_context->select_lex; Item_subselect *prev_subselect_item= last_checked_context->select_lex->master_unit()->item; + /* + We have merged to the top select and this field is no longer outer, + or we have reached the outermost select without resolution + */ + bool at_top= !prev_subselect_item; last_checked_context= outer_context; upward_lookup= TRUE; - place= prev_subselect_item->parsing_place; + if (!at_top) + place= prev_subselect_item->parsing_place; + else + place= NO_MATTER; + /* If outer_field is set, field was already found by first call to find_field_in_tables(). Only need to find appropriate context. @@ -5980,8 +5989,11 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) } if (*from_field != view_ref_found) { - prev_subselect_item->used_tables_cache|= (*from_field)->table->map; - prev_subselect_item->const_item_cache= 0; + if (!at_top) + { + prev_subselect_item->used_tables_cache|= (*from_field)->table->map; + prev_subselect_item->const_item_cache= 0; + } set_field(*from_field); if (!last_checked_context->select_lex->having_fix_field && select->group_list.elements && @@ -6030,7 +6042,8 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) else { Item::Type ref_type= (*reference)->type(); - prev_subselect_item->used_tables_and_const_cache_join(*reference); + if (!at_top) + prev_subselect_item->used_tables_and_const_cache_join(*reference); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, this, ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? @@ -6064,7 +6077,8 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) if (ref != not_found_item) { DBUG_ASSERT(*ref && (*ref)->fixed()); - prev_subselect_item->used_tables_and_const_cache_join(*ref); + if (!at_top) + prev_subselect_item->used_tables_and_const_cache_join(*ref); break; } } @@ -6074,8 +6088,11 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) outer select (or we just trying to find wrong identifier, in this case it does not matter which used tables bits we set) */ - prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; - prev_subselect_item->const_item_cache= 0; + if (!at_top) + { + prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_subselect_item->const_item_cache= 0; + } } DBUG_ASSERT(ref != 0);