diff options
-rw-r--r-- | mysql-test/r/derived.result | 53 | ||||
-rw-r--r-- | mysql-test/t/derived.test | 51 | ||||
-rw-r--r-- | sql/sql_base.cc | 2 | ||||
-rw-r--r-- | sql/table.cc | 24 |
4 files changed, 127 insertions, 3 deletions
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 2106ba504a9..5085feaaedc 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -1204,5 +1204,58 @@ REPLACE INTO v2 ( SELECT * FROM v4 ) UNION ( SELECT f FROM v2 ); drop view v1,v2,v3,v4; drop table t1,t2,t3; # +# MDEV-20325: Assertion `outer_context || !*from_field || *from_field == not_found_field' failed in Item_field::fix_outer_field | `!derived->is_excluded()' failed in TABLE_LIST::set_check_materialized | SIGEGV in st_select_lex::mark_as_dependent (optimized builds) +# +CREATE TABLE t1 (a INT); +# Check that re-execution of a stored routine containing +# a query with subquery in the FROM clause doesn't result in +# assert failure in case the 'derived_merge' optimizer option +# has been turned on/off +CREATE PROCEDURE sp() SELECT * FROM (SELECT a FROM t1) tb; +CALL sp(); +a +SET optimizer_switch='derived_merge=off'; +# Without the patch the following statement would result in assert +# failure +CALL sp(); +a +# Check the same test case for Prepared Statement +SET optimizer_switch='derived_merge=on'; +PREPARE stmt FROM "SELECT * FROM (SELECT a FROM t1) tb"; +EXECUTE stmt; +a +SET optimizer_switch='derived_merge=off'; +# Without the patch the following statement would result in assert +# failure +EXECUTE stmt; +a +DEALLOCATE PREPARE stmt; +# Here check the reverse test case - first turn off the 'derived_merge' +# optimizer option, run the stored routine containing a query with +# subquery in the FROM clause, then turn on the 'derived_merge' +# optimizer option and re-execute the same stored routine to check that +# the routine is finished successfully. +CREATE PROCEDURE sp1() SELECT * FROM (SELECT a FROM t1) tb; +SET optimizer_switch='derived_merge=off'; +CALL sp1(); +a +SET optimizer_switch='derived_merge=on'; +CALL sp1(); +a +# Check the same test case for Prepared Statement +SET optimizer_switch='derived_merge=off'; +PREPARE stmt FROM "SELECT * FROM (SELECT a FROM t1) tb"; +EXECUTE stmt; +a +SET optimizer_switch='derived_merge=on'; +# Without the patch the following statement would result in assert +# failure +EXECUTE stmt; +a +DEALLOCATE PREPARE stmt; +DROP PROCEDURE sp; +DROP PROCEDURE sp1; +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 6d9d5e23cf9..c8e6681e80b 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -1037,5 +1037,56 @@ drop view v1,v2,v3,v4; drop table t1,t2,t3; --echo # +--echo # MDEV-20325: Assertion `outer_context || !*from_field || *from_field == not_found_field' failed in Item_field::fix_outer_field | `!derived->is_excluded()' failed in TABLE_LIST::set_check_materialized | SIGEGV in st_select_lex::mark_as_dependent (optimized builds) +--echo # +CREATE TABLE t1 (a INT); + +--echo # Check that re-execution of a stored routine containing +--echo # a query with subquery in the FROM clause doesn't result in +--echo # assert failure in case the 'derived_merge' optimizer option +--echo # has been turned on/off +CREATE PROCEDURE sp() SELECT * FROM (SELECT a FROM t1) tb; +CALL sp(); +SET optimizer_switch='derived_merge=off'; +--echo # Without the patch the following statement would result in assert +--echo # failure +CALL sp(); + +--echo # Check the same test case for Prepared Statement +SET optimizer_switch='derived_merge=on'; +PREPARE stmt FROM "SELECT * FROM (SELECT a FROM t1) tb"; +EXECUTE stmt; +SET optimizer_switch='derived_merge=off'; +--echo # Without the patch the following statement would result in assert +--echo # failure +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +--echo # Here check the reverse test case - first turn off the 'derived_merge' +--echo # optimizer option, run the stored routine containing a query with +--echo # subquery in the FROM clause, then turn on the 'derived_merge' +--echo # optimizer option and re-execute the same stored routine to check that +--echo # the routine is finished successfully. +CREATE PROCEDURE sp1() SELECT * FROM (SELECT a FROM t1) tb; +SET optimizer_switch='derived_merge=off'; +CALL sp1(); +SET optimizer_switch='derived_merge=on'; +CALL sp1(); + +--echo # Check the same test case for Prepared Statement +SET optimizer_switch='derived_merge=off'; +PREPARE stmt FROM "SELECT * FROM (SELECT a FROM t1) tb"; +EXECUTE stmt; +SET optimizer_switch='derived_merge=on'; +--echo # Without the patch the following statement would result in assert +--echo # failure +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +DROP PROCEDURE sp; +DROP PROCEDURE sp1; +DROP TABLE t1; + +--echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9a66b27a454..5345fdbecd0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5980,7 +5980,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TRUE, &(item->cached_field_index)); #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check if there are sufficient access rights to the found field. */ - if (found && check_privileges && + if (found && check_privileges && !is_temporary_table(table_ref) && check_column_grant_in_table_ref(thd, table_ref, name, length)) found= WRONG_GRANT; #endif diff --git a/sql/table.cc b/sql/table.cc index d4f8170e0af..ca6ce02e4f2 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8232,6 +8232,24 @@ void TABLE_LIST::wrap_into_nested_join(List<TABLE_LIST> &join_list) /** + Check whether optimization has been performed and a derived table either + been merged to upper select level or materialized. + + @param table a TABLE_LIST object containing a derived table + + @return true in case the derived table has been merged to surrounding select, + false otherwise +*/ + +static inline bool derived_table_optimization_done(TABLE_LIST *table) +{ + return table->derived && + (table->derived->is_excluded() || + table->is_materialized_derived()); +} + + +/** @brief Initialize this derived table/view @@ -8267,13 +8285,15 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) set_multitable(); unit->derived= this; - if (init_view && !view) + if (init_view && !view && + !derived_table_optimization_done(this)) { /* This is all what we can do for a derived table for now. */ set_derived(); } - if (!is_view()) + if (!is_view() && + !derived_table_optimization_done(this)) { /* A subquery might be forced to be materialized due to a side-effect. */ if (!is_materialized_derived() && first_select->is_mergeable() && |