summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/view_grant.result24
-rw-r--r--mysql-test/t/view_grant.test36
-rw-r--r--sql/sql_acl.cc12
-rw-r--r--sql/table.h23
4 files changed, 91 insertions, 4 deletions
diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result
index e7a50451cec..c9b31b00f69 100644
--- a/mysql-test/r/view_grant.result
+++ b/mysql-test/r/view_grant.result
@@ -945,4 +945,28 @@ 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.
diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test
index ff17cde5184..0a8456afec2 100644
--- a/mysql-test/t/view_grant.test
+++ b/mysql-test/t/view_grant.test
@@ -1232,6 +1232,42 @@ DROP TABLE db1.t1;
DROP DATABASE db1;
connection default;
+
+--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.
# Wait till we reached the initial number of concurrent sessions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index ab4e518d5dd..a411101fcfd 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3650,11 +3650,14 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
continue; // ok
if (!(~table->grant.privilege & want_access) ||
- table->derived || table->schema_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)
{
@@ -3667,9 +3670,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
}
continue;
}
+
if (!(grant_table= table_hash_search(sctx->host, sctx->ip,
- table->db, sctx->priv_user,
- table->table_name,0)))
+ table->get_db_name(), sctx->priv_user,
+ table->get_table_name(), 0)))
{
want_access &= ~table->grant.privilege;
goto err; // No grants
diff --git a/sql/table.h b/sql/table.h
index db996d45320..ce9364fad4d 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -771,6 +771,29 @@ struct TABLE_LIST
void reinit_before_use(THD *thd);
Item_subselect *containing_subselect();
+ /**
+ @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.
+ */
+ char *get_db_name() { return view != NULL ? view_db.str : db; }
+
+ /**
+ @brief Returns the name of the table that this TABLE_LIST represents.
+
+ @details The unqualified table name or view name for a table or view,
+ respectively.
+ */
+ char *get_table_name() { return view != NULL ? view_name.str : table_name; }
+
private:
bool prep_check_option(THD *thd, uint8 check_opt_type);
bool prep_where(THD *thd, Item **conds, bool no_where_clause);