#At file:///data0/martin/bzr/6.0bt-privilege-bugs/
2666 Martin Hansson 2008-06-27
Bug#36086: SELECT * from views don't check column grants
This patch also fixes bugs 36963 and 35600.
- In many place a view was confused with an anonymous derived table,
i.e. access checking was skipped. Fixed by introducing a predicate
to tell the difference between named and anonymous derived tables.
- When inserting fields for "SELECT * ", there was no distinction made
between base tables and views when it should have. View privileges are
checked elsewhere.
- Privileges for TEMPTABLE views should not be checked in check_grant().
modified:
mysql-test/include/grant_cache.inc
mysql-test/r/grant2.result
mysql-test/r/grant_cache_no_prot.result
mysql-test/r/grant_cache_ps_prot.result
mysql-test/r/view_grant.result
mysql-test/t/grant2.test
mysql-test/t/view_grant.test
sql/sql_acl.cc
sql/sql_base.cc
sql/sql_derived.cc
sql/sql_parse.cc
sql/table.cc
sql/table.h
per-file messages:
mysql-test/include/grant_cache.inc
Bug#36086: Changed test case.
mysql-test/r/grant2.result
Bug#36086: Changed test result.
mysql-test/r/grant_cache_no_prot.result
Bug#36086: Changed test result.
mysql-test/r/grant_cache_ps_prot.result
Bug#36086: Changed test result.
mysql-test/r/view_grant.result
Bug#36086: Test result
mysql-test/t/grant2.test
Bug#36086: Changed test case.
mysql-test/t/view_grant.test
Bug#36086: Test case.
sql/sql_acl.cc
Bug no 35600: In check_grant:
- Changed the requirement table->derived != null to
check all anonymous derived tables.
- Use the access methods for getting object and database
names.
Bug#36086: In check_grant_all_columns:
- Updated comment. This function is now called for views
as well.
- The error message should not disclose any column names
unless the user has privilege to see all column names.
sql/sql_base.cc
Bug no 36963: insert_fields()
- We should call check_grant_all_columns() for views in
this case.
- We should not disclose column names in the error message
when the user has no approprate privilege.
sql/sql_derived.cc
Bug#36086: commenting only. Updated and doxygenated
comment for mysql_derived_prepare().
sql/sql_parse.cc
Bug no 35600:
- In check_table_access():
- replaced table->derived
- replaced ->db with ->get_database_name() (see
table.h)
sql/table.cc
Bug#36086: TABLE_LIST::set_underlying_merge():
Commenting only. Doxygenated, corrected spelling,
added.
sql/table.h
Bug#36086:
- Commented GRANT_INFO.
- Added a predicate is_anonymous_derived_table to
TABLE_LIST.
- Added get_object_name() and get_database_name() to
TABLE_LIST in order to hide the disparate
representation of these properties.
=== modified file 'mysql-test/include/grant_cache.inc'
--- a/mysql-test/include/grant_cache.inc 2007-05-24 20:13:49 +0000
+++ b/mysql-test/include/grant_cache.inc 2008-06-27 07:40:53 +0000
@@ -136,7 +136,7 @@ connect (user3,localhost,mysqltest_3,,my
connection user3;
select "user3";
--replace_result 127.0.0.1 localhost
---error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_TABLEACCESS_DENIED_ERROR
select * from t1;
select a from t1;
--replace_result 127.0.0.1 localhost
=== modified file 'mysql-test/r/grant2.result'
--- a/mysql-test/r/grant2.result 2008-03-18 10:54:37 +0000
+++ b/mysql-test/r/grant2.result 2008-06-27 07:40:53 +0000
@@ -434,7 +434,7 @@ USE db1;
SELECT c FROM t2;
ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2'
SELECT * FROM t2;
-ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2'
+ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for table 't2'
SELECT * FROM t1 JOIN t2 USING (b);
ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2'
DROP TABLE db1.t1, db1.t2;
=== modified file 'mysql-test/r/grant_cache_no_prot.result'
--- a/mysql-test/r/grant_cache_no_prot.result 2007-05-24 20:13:49 +0000
+++ b/mysql-test/r/grant_cache_no_prot.result 2008-06-27 07:40:53 +0000
@@ -155,7 +155,7 @@ select "user3";
user3
user3
select * from t1;
-ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'b' in table 't1'
+ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 't1'
select a from t1;
a
1
=== modified file 'mysql-test/r/grant_cache_ps_prot.result'
--- a/mysql-test/r/grant_cache_ps_prot.result 2007-05-24 20:13:49 +0000
+++ b/mysql-test/r/grant_cache_ps_prot.result 2008-06-27 07:40:53 +0000
@@ -155,7 +155,7 @@ select "user3";
user3
user3
select * from t1;
-ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for column 'b' in table 't1'
+ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 't1'
select a from t1;
a
1
=== modified file 'mysql-test/r/view_grant.result'
--- a/mysql-test/r/view_grant.result 2008-03-22 08:02:24 +0000
+++ b/mysql-test/r/view_grant.result 2008-06-27 07:40:53 +0000
@@ -948,3 +948,35 @@ Warning 1356 View 'test.v1' references i
DROP VIEW v1;
DROP TABLE t1;
End of 5.1 tests.
+CREATE USER mysqluser1@localhost;
+CREATE DATABASE mysqltest1;
+USE mysqltest1;
+CREATE TABLE t1 ( a INT, b INT );
+CREATE TABLE t2 ( a INT, b INT );
+CREATE VIEW v1 AS SELECT a, b FROM t1;
+GRANT SELECT( a ) ON v1 TO mysqluser1@localhost;
+GRANT UPDATE( b ) ON t2 TO mysqluser1@localhost;
+SELECT * FROM mysqltest1.v1;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 'v1'
+CREATE VIEW v1 AS SELECT * FROM mysqltest1.t2;
+ERROR 42000: ANY command denied to user 'mysqluser1'@'localhost' for table 't2'
+DROP TABLE t1, t2;
+DROP VIEW v1;
+DROP DATABASE mysqltest1;
+DROP USER mysqluser1@localhost;
+CREATE USER mysqluser1@localhost;
+CREATE DATABASE mysqltest1;
+USE mysqltest1;
+CREATE VIEW v1 AS SELECT * FROM information_schema.tables LIMIT 1;
+CREATE ALGORITHM = TEMPTABLE VIEW v2 AS SELECT 1 AS A;
+GRANT SELECT ON mysqltest1.* to mysqluser1@localhost;
+PREPARE stmt_v1 FROM "SELECT * FROM mysqltest1.v1";
+PREPARE stmt_v2 FROM "SELECT * FROM mysqltest1.v2";
+REVOKE SELECT ON mysqltest1.* FROM mysqluser1@localhost;
+EXECUTE stmt_v1;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 'v1'
+EXECUTE stmt_v2;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 'v2'
+DROP VIEW v1, v2;
+DROP DATABASE mysqltest1;
+DROP USER mysqluser1@localhost;
=== modified file 'mysql-test/t/grant2.test'
--- a/mysql-test/t/grant2.test 2007-09-27 09:32:59 +0000
+++ b/mysql-test/t/grant2.test 2008-06-27 07:40:53 +0000
@@ -605,7 +605,7 @@ connection conn1;
USE db1;
--error ER_COLUMNACCESS_DENIED_ERROR
SELECT c FROM t2;
---error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_TABLEACCESS_DENIED_ERROR
SELECT * FROM t2;
--error ER_COLUMNACCESS_DENIED_ERROR
SELECT * FROM t1 JOIN t2 USING (b);
=== modified file 'mysql-test/t/view_grant.test'
--- a/mysql-test/t/view_grant.test 2008-03-04 17:35:42 +0000
+++ b/mysql-test/t/view_grant.test 2008-06-27 07:40:53 +0000
@@ -1216,3 +1216,71 @@ DROP VIEW v1;
DROP TABLE t1;
--echo End of 5.1 tests.
+
+#
+# Bug#36086: SELECT * from views don't check column grants
+#
+CREATE USER mysqluser1@localhost;
+CREATE DATABASE mysqltest1;
+
+USE mysqltest1;
+
+CREATE TABLE t1 ( a INT, b INT );
+CREATE TABLE t2 ( a INT, b INT );
+
+CREATE VIEW v1 AS SELECT a, b FROM t1;
+
+GRANT SELECT( a ) ON v1 TO mysqluser1@localhost;
+GRANT UPDATE( b ) ON t2 TO mysqluser1@localhost;
+
+--connect (connection1, localhost, mysqluser1, , test)
+
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT * FROM mysqltest1.v1;
+
+--error ER_TABLEACCESS_DENIED_ERROR
+CREATE VIEW v1 AS SELECT * FROM mysqltest1.t2;
+
+--disconnect connection1
+
+--connection default
+
+DROP TABLE t1, t2;
+DROP VIEW v1;
+DROP DATABASE mysqltest1;
+DROP USER mysqluser1@localhost;
+
+#
+# Bug#35600: Security breach via view, I_S table and prepared
+# statement/stored procedure
+#
+CREATE USER mysqluser1@localhost;
+CREATE DATABASE mysqltest1;
+
+USE mysqltest1;
+
+CREATE VIEW v1 AS SELECT * FROM information_schema.tables LIMIT 1;
+CREATE ALGORITHM = TEMPTABLE VIEW v2 AS SELECT 1 AS A;
+
+--connection default
+GRANT SELECT ON mysqltest1.* to mysqluser1@localhost;
+
+--connect (connection1, localhost, mysqluser1, , test)
+PREPARE stmt_v1 FROM "SELECT * FROM mysqltest1.v1";
+PREPARE stmt_v2 FROM "SELECT * FROM mysqltest1.v2";
+
+--connection default
+REVOKE SELECT ON mysqltest1.* FROM mysqluser1@localhost;
+
+--connection connection1
+
+--error ER_TABLEACCESS_DENIED_ERROR
+EXECUTE stmt_v1;
+--error ER_TABLEACCESS_DENIED_ERROR
+EXECUTE stmt_v2;
+
+--disconnect connection1
+--connection default
+DROP VIEW v1, v2;
+DROP DATABASE mysqltest1;
+DROP USER mysqluser1@localhost;
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2008-05-21 10:17:29 +0000
+++ b/sql/sql_acl.cc 2008-06-27 07:40:53 +0000
@@ -3919,8 +3919,8 @@ bool check_grant(THD *thd, ulong want_ac
if (!want_access)
continue; // ok
- if (!(~table->grant.privilege & want_access) ||
- table->derived || table->schema_table)
+ if (!(~table->grant.privilege & want_access) ||
+ table->is_anonymous_derived_table() || table->schema_table)
{
/*
It is subquery in the FROM clause. VIEW set table->derived after
@@ -3938,8 +3938,8 @@ bool check_grant(THD *thd, ulong want_ac
continue;
}
if (!(grant_table= table_hash_search(sctx->host, sctx->ip,
- table->db, sctx->priv_user,
- table->table_name,0)))
+ table->get_database_name(), sctx->priv_user,
+ table->get_object_name(), FALSE)))
{
want_access &= ~table->grant.privilege;
goto err; // No grants
@@ -3980,7 +3980,7 @@ err:
command,
sctx->priv_user,
sctx->host_or_ip,
- table ? table->table_name : "unknown");
+ table ? table->get_object_name() : "unknown");
}
DBUG_RETURN(TRUE);
}
@@ -4224,7 +4224,7 @@ bool check_column_grant_in_table_ref(THD
@retval 1 Falure
@details This function walks over the columns of a table reference
The columns may originate from different tables, depending on the kind of
- table reference, e.g. join.
+ table reference, e.g. join, view.
For each table it will retrieve the grant information and will use it
to check the required access privileges for the fields requested from it.
*/
@@ -4239,6 +4239,7 @@ bool check_grant_all_columns(THD *thd, u
GRANT_INFO *grant;
/* Initialized only to make gcc happy */
GRANT_TABLE *grant_table= NULL;
+ bool missing_column_privilege= FALSE;
rw_rdlock(&LOCK_grant);
@@ -4275,6 +4276,8 @@ bool check_grant_all_columns(THD *thd, u
GRANT_COLUMN *grant_column=
column_hash_search(grant_table, field_name,
(uint) strlen(field_name));
+ if (grant_column)
+ missing_column_privilege= TRUE;
if (!grant_column || (~grant_column->rights & want_access))
goto err;
}
@@ -4287,12 +4290,17 @@ err:
char command[128];
get_privilege_desc(command, sizeof(command), want_access);
- my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
- command,
- sctx->priv_user,
- sctx->host_or_ip,
- fields->name(),
- table_name);
+ if (missing_column_privilege)
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ command, sctx->priv_user,
+ sctx->host_or_ip, table_name);
+ else
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ command,
+ sctx->priv_user,
+ sctx->host_or_ip,
+ fields->name(),
+ table_name);
return 1;
}
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2008-05-21 10:17:29 +0000
+++ b/sql/sql_base.cc 2008-06-27 07:40:53 +0000
@@ -7634,8 +7634,8 @@ insert_fields(THD *thd, Name_resolution_
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Ensure that we have access rights to all fields to be inserted. */
- if (!((table && (table->grant.privilege & SELECT_ACL) ||
- tables->view && (tables->grant.privilege & SELECT_ACL))) &&
+ if (!(table && !tables->view && (table->grant.privilege & SELECT_ACL) ||
+ tables->view && (tables->grant.privilege & SELECT_ACL)) &&
!any_privileges)
{
field_iterator.set(tables);
@@ -7698,10 +7698,10 @@ insert_fields(THD *thd, Name_resolution_
field_table_name, fld->field_name) &
VIEW_ANY_ACL)))
{
- my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "ANY",
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY",
thd->security_ctx->priv_user,
thd->security_ctx->host_or_ip,
- fld->field_name, field_table_name);
+ field_table_name);
DBUG_RETURN(TRUE);
}
}
=== modified file 'sql/sql_derived.cc'
--- a/sql/sql_derived.cc 2007-12-12 15:44:48 +0000
+++ b/sql/sql_derived.cc 2008-06-27 07:40:53 +0000
@@ -73,29 +73,59 @@ out:
}
-/*
- Create temporary table structure (but do not fill it)
-
- SYNOPSIS
- mysql_derived_prepare()
- thd Thread handle
- lex LEX for this thread
- orig_table_list TABLE_LIST for the upper SELECT
-
- IMPLEMENTATION
- Derived table is resolved with temporary table.
-
- After table creation, the above TABLE_LIST is updated with a new table.
-
- This function is called before any command containing derived table
- is executed.
-
- Derived tables is stored in thd->derived_tables and freed in
- close_thread_tables()
+/**
+ @brief Create temporary table structure (but do not fill it).
- RETURN
- FALSE OK
- TRUE Error
+ @param thd Thread handle
+ @param lex LEX for this thread
+ @param orig_table_list TABLE_LIST for the upper SELECT
+
+ @details
+
+ This function is called before any command containing derived tables is
+ executed. Currently the function is used for derived tables, i.e.
+
+ - Anonymous derived tables, or
+ - Named derived tables (aka views) with the @c TEMPTABLE algorithm.
+
+ The table reference, contained in @c orig_table_list, is updated with the
+ fields of a new temporary table.
+
+ Derived tables are stored in @c thd->derived_tables and closed by
+ close_thread_tables().
+
+ This function is part of the procedure that starts in
+ open_and_lock_tables(), a procedure that - among other things - introduces
+ new table and table reference objects (to represent derived tables) that
+ don't exist in the privilege database. This means that normal privilege
+ checking cannot handle them. Hence this function does some extra tricks in
+ order to bypass normal privilege checking, by exploiting the fact that the
+ current state of privilege verification is attached as GRANT_INFO structures
+ on the relevant TABLE and TABLE_REF objects.
+
+ For table references, the current state of accrued access is stored inside
+ TABLE_LIST::grant. Hence this function must update the state of fulfilled
+ privileges for the new TABLE_LIST, an operation which is normally performed
+ exclusively by the table and database access checking functions,
+ check_access() and check_grant(), respectively. This modification is done
+ for both views and anonymous derived tables: The @c SELECT privilege is set
+ as fulfilled by the user. However, if a view is referenced and the table
+ reference is queried against directly (see TABLE_LIST::referencing_view),
+ the state of privilege checking (GRANT_INFO struct) is copied as-is to the
+ temporary table.
+
+ This function implements a signature called "derived table processor", and
+ is passed as a function pointer to mysql_handle_derived().
+
+ @note This function sets @c SELECT_ACL for @c TEMPTABLE views as well as
+ anonymous derived tables, but this is ok since later access checking will
+ distinguish between them.
+
+ @see mysql_handle_derived(), mysql_derived_filling(), GRANT_INFO
+
+ @return
+ false OK
+ true Error
*/
bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-05-21 10:17:29 +0000
+++ b/sql/sql_parse.cc 2008-06-27 07:40:53 +0000
@@ -5267,15 +5267,15 @@ check_table_access(THD *thd, ulong requi
continue;
}
- if (tables->derived ||
+ if (tables->is_anonymous_derived_table() ||
(tables->table && tables->table->s && (int)tables->table->s->tmp_table))
continue;
thd->security_ctx= sctx;
if ((sctx->master_access & want_access) ==
want_access && thd->db)
tables->grant.privilege= want_access;
- else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
- 0, no_errors, 0))
+ else if (check_access(thd, want_access, tables->get_database_name(),
+ &tables->grant.privilege, 0, no_errors, 0))
goto deny;
}
thd->security_ctx= backup_ctx;
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2008-05-08 16:01:15 +0000
+++ b/sql/table.cc 2008-06-27 07:40:53 +0000
@@ -3080,16 +3080,27 @@ void TABLE_LIST::calc_md5(char *buffer)
}
-/*
- set underlying TABLE for table place holder of VIEW
+/**
+ @brief Set underlying table for table place holder of view.
- DESCRIPTION
- Replace all views that only uses one table with the table itself.
- This allows us to treat the view as a simple table and even update
- it (it is a kind of optimisation)
+ @details
- SYNOPSIS
- TABLE_LIST::set_underlying_merge()
+ Replace all views that only use one table with the table itself. This
+ allows us to treat the view as a simple table and even update it (it is a
+ kind of optimization).
+
+ @note
+
+ This optimization is potentially dangerous at it makes views
+ masquerade as base tables: Views don't have the pointer TABLE_LIST::table
+ set to non-@c NULL.
+
+ We may have the case where a view accesses tables not normally accessible
+ in the current Security_context (only in the definer's
+ Security_context). According to the table's GRANT_INFO (TABLE::grant),
+ access is fulfilled, but this is implicitly meant in the definer's security
+ context. Hence we must never look at only a TABLE's GRANT_INFO without
+ looking at the one of the referring TABLE_LIST.
*/
void TABLE_LIST::set_underlying_merge()
=== modified file 'sql/table.h'
--- a/sql/table.h 2008-05-21 10:17:29 +0000
+++ b/sql/table.h 2008-06-27 07:40:53 +0000
@@ -66,13 +66,61 @@ typedef struct st_order {
table_map used, depend_map;
} ORDER;
+/**
+ @brief The current state of the privilege checking process for the current
+ user, SQL statement and SQL object.
+
+ @details The privilege checking process is divided into phases depending on
+ the level of the privilege to be checked and the type of object to be
+ accessed. Due to the distributed nature of privilege checking, it is
+ necessary to keep track of the state of the process. This information is
+ stored in privilege, want_privilege, and orig_want_privilege.
+
+ A GRANT_INFO also serves as a local repository of the privilege
+ database. Relevant members are grant_table and version.
+ */
typedef struct st_grant_info
{
+ /**
+ @brief A copy of the privilege information regarding the current host,
+ database, object and user.
+
+ @details The version of this copy is found in GRANT_INFO::version.
+ */
GRANT_TABLE *grant_table;
+ /**
+ @brief Used for cache invalidation when caching privile information.
+
+ @details The privilege information is stored on disk, with dedicated
+ caches residing in memory: table-level and column-level privileges,
+ respectively, have their own dedicated caches.
+
+ The GRANT_INFO works as a level 1 cache with this member updated to the
+ current value of the global variable grant_version (@c static in
+ sql_acl.cc). It is updated Whenever the GRANT_INFO is refreshed from the
+ second level caches.
+
+ @see grant_version
+ */
uint version;
+ /**
+ @brief The set of privileges that the current user has fulfilled for a
+ certain host, database, and object.
+
+ @details This field is continually updated throughout the access checking
+ process. In each step the "wanted privilege" is checked against the
+ fulfilled privileges. When/if the intersection of these sets is empty,
+ access is granted.
+
+ The set is implemented as a bitmap, with the bits defined in sql_acl.h.
+ */
ulong privilege;
+ /**
+ @brief the set of privileges that the current user needs to fulfil in
+ order to carry out the requested operation.
+ */
ulong want_privilege;
- /*
+ /**
Stores the requested access acl of top level tables list. Is used to
check access rights to the underlying tables of a view.
*/
@@ -1122,6 +1170,27 @@ struct TABLE_LIST
can see this lists can't be merged)
*/
TABLE_LIST *correspondent_table;
+ /**
+ @brief Normally, this field is non-null for anonymous derived tables only.
+
+ @details This field is set to non-null for
+
+ - Anonymous derived tables, In this case it points to the SELECT_LEX_UNIT
+ representing the derived table. E.g. for a query
+
+ @verbatim SELECT * FROM (SELECT a FROM t1) b @endverbatim
+
+ For the @c TABLE_LIST representing the derived table @c b, @c derived
+ points to the SELECT_LEX_UNIT representing the result of the query within
+ parenteses.
+
+ - Views. This is set for views with @verbatim ALGORITHM = TEMPTABLE
+ @endverbatim by mysql_make_view().
+
+ @note Inside views, a subquery in the @c FROM clause is not allowed.
+ @note Do not use this field to separate views/base tables/anonymous
+ derived tables. Use TABLE_LIST::is_anonymous_derived_table().
+ */
st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
ST_SCHEMA_TABLE *schema_table; /* Information_schema table */
st_select_lex *schema_select_lex;
@@ -1187,7 +1256,15 @@ struct TABLE_LIST
ulonglong file_version; /* version of file's field set */
ulonglong updatable_view; /* VIEW can be updated */
ulonglong revision; /* revision control number */
- ulonglong algorithm; /* 0 any, 1 tmp tables , 2 merging */
+ /**
+ @brief The declared algorithm, if this is a view.
+ @details One of
+ - VIEW_ALGORITHM_UNDEFINED
+ - VIEW_ALGORITHM_TMPTABLE
+ - VIEW_ALGORITHM_MERGE
+ @to do Replace with an enum
+ */
+ ulonglong algorithm;
ulonglong view_suid; /* view is suid (TRUE dy default) */
ulonglong with_check; /* WITH CHECK OPTION */
/*
@@ -1195,7 +1272,15 @@ struct TABLE_LIST
algorithm)
*/
uint8 effective_with_check;
- uint8 effective_algorithm; /* which algorithm was really used */
+ /**
+ @brief The view algorithm that is actually used, if this is a view.
+ @details One of
+ - VIEW_ALGORITHM_UNDEFINED
+ - VIEW_ALGORITHM_TMPTABLE
+ - VIEW_ALGORITHM_MERGE
+ @to do Replace with an enum
+ */
+ uint8 effective_algorithm;
GRANT_INFO grant;
/* data need by some engines in query cache*/
ulonglong engine_data;
@@ -1393,6 +1478,27 @@ struct TABLE_LIST
m_table_ref_version= s->get_table_ref_version();
}
+ /**
+ @brief True if this TABLE_LIST represents an anonymous derived table,
+ i.e. the result of a subquery.
+ */
+ bool is_anonymous_derived_table() const { return derived && !view; }
+
+ /**
+ @brief Returns the name of the database that the referenced object
+ belongs to.
+ */
+ char *get_database_name() { return view != NULL ? view_db.str : db; }
+
+ /**
+ @brief Returns the name of the SQL object that this TABLE_LIST
+ represents.
+
+ @details The object name would be the unqualified table name or view name
+ for a table or view, respectively.
+ */
+ char *get_object_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);
| Thread |
|---|
| • bzr commit into mysql-6.0 branch (mhansson:2666) Bug#36086 | Martin Hansson | 27 Jun |