diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 7e280fa2fe5d738343fcdd2f1aa0354db51d99e2..6d1d872c3b70e5a03985a8d3064f1ef40e3a2105 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -947,6 +947,30 @@ DROP USER foo; DROP VIEW db1.v1; DROP TABLE db1.t1; DROP DATABASE db1; +# +# Bug #46019: ERROR 1356 When selecting from within another +# view that has Group By +# +CREATE DATABASE db1; +USE db1; +CREATE TABLE t1 (a INT); +CREATE SQL SECURITY INVOKER VIEW v1 AS +SELECT a FROM t1 GROUP BY a; +CREATE SQL SECURITY INVOKER VIEW v2 AS +SELECT a FROM v1; +CREATE USER u1; +GRANT SELECT ON TABLE t1 TO u1; +GRANT SELECT, SHOW VIEW ON TABLE v1 TO u1; +GRANT SELECT, SHOW VIEW ON TABLE v2 TO u1; +SELECT a FROM v1; +a +SELECT a FROM v2; +a +DROP USER u1; +DROP VIEW v1,v2; +DROP TABLE t1; +USE test; +DROP DATABASE db1; End of 5.0 tests. DROP VIEW IF EXISTS v1; DROP TABLE IF EXISTS t1; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 824c67d867e74762515d543d73bba89b4eecab1d..78b4a078683fbe110b94aa7694d60fed6de1cd42 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1237,6 +1237,41 @@ DROP VIEW db1.v1; DROP TABLE db1.t1; DROP DATABASE db1; +--echo # +--echo # Bug #46019: ERROR 1356 When selecting from within another +--echo # view that has Group By +--echo # + +CREATE DATABASE db1; +USE db1; + +CREATE TABLE t1 (a INT); + +CREATE SQL SECURITY INVOKER VIEW v1 AS + SELECT a FROM t1 GROUP BY a; + +CREATE SQL SECURITY INVOKER VIEW v2 AS + SELECT a FROM v1; + +CREATE USER u1; + +GRANT SELECT ON TABLE t1 TO u1; +GRANT SELECT, SHOW VIEW ON TABLE v1 TO u1; +GRANT SELECT, SHOW VIEW ON TABLE v2 TO u1; + +CONNECT (u1, localhost, u1,,db1); +CONNECTION u1; + +SELECT a FROM v1; +SELECT a FROM v2; + +CONNECTION default; +DISCONNECT u1; +DROP USER u1; +DROP VIEW v1,v2; +DROP TABLE t1; +USE test; +DROP DATABASE db1; --echo End of 5.0 tests. diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ab18a2d1d04ced0cde0f597fef5980f989c6ca8f..de132d169f228294883d99fa0cad05573e7c2694 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3905,11 +3905,15 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, continue; // ok if (!(~table->grant.privilege & want_access) || - table->is_anonymous_derived_table() || table->schema_table) + (table->is_anonymous_derived_table() && + table->is_non_materialized_derived_table()) || table->schema_table) { /* It is subquery in the FROM clause. VIEW set table->derived after - table opening, but this function always called before table opening. + table opening, but this function is mostly called before table opening. + When it's called after table opening e.g. for nested views with + materialization we shoud check the materialized table for access as + any other table. */ if (!table->referencing_view) { @@ -3922,6 +3926,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, } continue; } + if (!(grant_table= table_hash_search(sctx->host, sctx->ip, table->get_db_name(), sctx->priv_user, table->get_table_name(), FALSE))) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index fb5d58b63c4d3387be2669332a8f48bcb3acc75f..de5f2838eddb736d42b5bf9614b759743fb8d098 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5058,7 +5058,8 @@ bool check_single_table_access(THD *thd, ulong privilege, if (!(all_tables->belong_to_view && (thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) && !(all_tables->view && - all_tables->effective_algorithm == VIEW_ALGORITHM_TMPTABLE) && + all_tables->effective_algorithm == VIEW_ALGORITHM_TMPTABLE && + all_tables->is_non_materialized_derived_table()) && check_grant(thd, privilege, all_tables, 0, 1, no_errors)) goto deny; diff --git a/sql/table.h b/sql/table.h index 40372fa91cf9785327fae22452ca18decbfea24c..1beea8ac1a12279dec95dafa3e5d1c0126382412 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1465,6 +1465,15 @@ struct TABLE_LIST */ bool is_anonymous_derived_table() const { return derived && !view; } + /** + @brief True if this TABLE_LIST represents an not yet materialized + derived table, i.e. the result of a subquery or view execution. + */ + bool is_non_materialized_derived_table() const + { + return derived && !derived_result; + } + /** @brief Returns the name of the database that the referenced table belongs to.