diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 7bade28f395..b84d79bc09c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -32,10 +32,10 @@ c 11 show create table v1; Table Create Table -v1 CREATE VIEW test.v1 AS select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` +v1 CREATE VIEW `test`.`v1` AS select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` show create view v1; Table Create Table -v1 CREATE VIEW test.v1 AS select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` +v1 CREATE VIEW `test`.`v1` AS select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` show create view t1; ERROR HY000: 'test.t1' is not VIEW drop table t1; @@ -55,7 +55,7 @@ Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`v1` create algorithm=temptable view v2 (c) as select b+1 from t1; show create table v2; Table Create Table -v2 CREATE ALGORITHM=TMPTABLE VIEW test.v2 AS select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` +v2 CREATE ALGORITHM=TMPTABLE VIEW `test`.`v2` AS select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` select c from v2; c 3 @@ -306,14 +306,14 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found show create table mysqltest.v1; Table Create Table -v1 CREATE VIEW mysqltest.v1 AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` +v1 CREATE VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` explain select c from mysqltest.v2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 0 const row not found 2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table show create table mysqltest.v2; Table Create Table -v2 CREATE ALGORITHM=TMPTABLE VIEW mysqltest.v2 AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` +v2 CREATE ALGORITHM=TMPTABLE VIEW `mysqltest`.`v2` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` explain select c from mysqltest.v3; ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table show create table mysqltest.v3; @@ -328,27 +328,27 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found show create table mysqltest.v1; Table Create Table -v1 CREATE VIEW mysqltest.v1 AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` +v1 CREATE VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` explain select c from mysqltest.v2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 0 const row not found 2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table show create table mysqltest.v2; Table Create Table -v2 CREATE ALGORITHM=TMPTABLE VIEW mysqltest.v2 AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` +v2 CREATE ALGORITHM=TMPTABLE VIEW `mysqltest`.`v2` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` explain select c from mysqltest.v3; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 system NULL NULL NULL NULL 0 const row not found show create table mysqltest.v3; Table Create Table -v3 CREATE VIEW mysqltest.v3 AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` +v3 CREATE VIEW `mysqltest`.`v3` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` explain select c from mysqltest.v4; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 0 const row not found 2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table show create table mysqltest.v4; Table Create Table -v4 CREATE ALGORITHM=TMPTABLE VIEW mysqltest.v4 AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` +v4 CREATE ALGORITHM=TMPTABLE VIEW `mysqltest`.`v4` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` revoke all privileges on mysqltest.* from mysqltest_1@localhost; delete from mysql.user where user='mysqltest_1'; drop database mysqltest; @@ -830,7 +830,7 @@ a b c 30 4 -60 50 6 -100 40 5 NULL -drop table t1; +drop table t1, t2; drop view v1,v2,v3,v4,v5; create database mysqltest; create table mysqltest.t1 (a int, b int, primary key(a)); @@ -946,7 +946,7 @@ create table t1 ("a*b" int); create view v1 as select "a*b" from t1; show create view v1; Table Create Table -v1 CREATE VIEW test.v1 AS select `test`.`t1`.`a*b` AS `a*b` from `test`.`t1` +v1 CREATE VIEW "test"."v1" AS select `test`.`t1`.`a*b` AS `a*b` from `test`.`t1` drop view v1; drop table t1; set sql_mode=default; @@ -1040,10 +1040,60 @@ CREATE VIEW v02 AS SELECT * FROM DUAL; ERROR HY000: No tables used SHOW TABLES; Tables_in_test table_type -t2 BASE TABLE v4 VIEW CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2); select * from v1; EXISTS (SELECT 1 UNION SELECT 2) 1 drop view v1; +create table t1 (col1 int,col2 char(22)); +create view v1 as select * from t1; +create index i1 on v1 (col1); +ERROR HY000: 'test.v1' is not BASE TABLE +drop view v1; +drop table t1; +CREATE VIEW v1 (f1,f2,f3,f4) AS SELECT connection_id(), pi(), current_user(), version(); +SHOW CREATE VIEW v1; +Table Create Table +v1 CREATE VIEW `test`.`v1` AS select sql_no_cache connection_id() AS `f1`,pi() AS `f2`,current_user() AS `f3`,version() AS `f4` +drop view v1; +create table t1 (s1 int); +create table t2 (s2 int); +insert into t1 values (1), (2); +insert into t2 values (2), (3); +create view v1 as select * from t1,t2 union all select * from t1,t2; +select * from v1; +s1 s2 +1 2 +2 2 +1 3 +2 3 +1 2 +2 2 +1 3 +2 3 +drop view v1; +drop tables t1, t2; +create table t1 (col1 int); +insert into t1 values (1); +create view v1 as select count(*) from t1; +insert into t1 values (null); +select * from v1; +count(*) +2 +drop view v1; +drop table t1; +create table t1 (a int); +create table t2 (a int); +create view v1 as select a from t1; +create view v2 as select a from t2 where a in (select a from v1); +show create view v2; +Table Create Table +v2 CREATE VIEW `test`.`v2` AS select `test`.`t2`.`a` AS `a` from `test`.`t2` where `a` in (select `v1`.`a` AS `a` from `test`.`v1`) +drop view v2, v1; +drop table t1, t2; +CREATE VIEW `v 1` AS select 5 AS `5`; +show create view `v 1`; +Table Create Table +v 1 CREATE VIEW `test`.`v 1` AS select 5 AS `5` +drop view `v 1`; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index c00489c1d1a..1c3064e864e 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -693,7 +693,7 @@ insert into v1 select c, b, a from t2; insert into v1 (z,y,x) select a+20,b+2,-100 from t2; insert into v2 select b+1, a+10 from t2; select * from t1; -drop table t1; +drop table t1, t2; drop view v1,v2,v3,v4,v5; # @@ -987,3 +987,61 @@ SHOW TABLES; CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2); select * from v1; drop view v1; + +# +# using VIEW where table is required +# +create table t1 (col1 int,col2 char(22)); +create view v1 as select * from t1; +-- error 1346 +create index i1 on v1 (col1); +drop view v1; +drop table t1; + +# +# connection_id(), pi(), current_user(), version() representation test +# +CREATE VIEW v1 (f1,f2,f3,f4) AS SELECT connection_id(), pi(), current_user(), version(); +SHOW CREATE VIEW v1; +drop view v1; + +# +# VIEW built over UNION +# +create table t1 (s1 int); +create table t2 (s2 int); +insert into t1 values (1), (2); +insert into t2 values (2), (3); +create view v1 as select * from t1,t2 union all select * from t1,t2; +select * from v1; +drop view v1; +drop tables t1, t2; + +# +# Aggregate functions in view list +# +create table t1 (col1 int); +insert into t1 values (1); +create view v1 as select count(*) from t1; +insert into t1 values (null); +select * from v1; +drop view v1; +drop table t1; + +# +# Showing VIEW with VIEWs in subquery +# +create table t1 (a int); +create table t2 (a int); +create view v1 as select a from t1; +create view v2 as select a from t2 where a in (select a from v1); +show create view v2; +drop view v2, v1; +drop table t1, t2; + +# +# SHOW VIEW view with name with spaces +# +CREATE VIEW `v 1` AS select 5 AS `5`; +show create view `v 1`; +drop view `v 1`; diff --git a/sql/item.h b/sql/item.h index afa439dff32..b3dbc0ce46f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -669,6 +669,17 @@ public: }; +class Item_static_int_func :public Item_int +{ + const char *func_name; +public: + Item_static_int_func(const char *str_arg, longlong i, uint length) + :Item_int(NullS, i, length), func_name(str_arg) + {} + void print(String *str) { str->append(func_name); } +}; + + class Item_uint :public Item_int { public: @@ -724,6 +735,18 @@ public: }; +class Item_static_real_func :public Item_real +{ + const char *func_name; +public: + Item_static_real_func(const char *str, double val_arg, uint decimal_par, + uint length) + :Item_real(NullS, val_arg, decimal_par, length), func_name(str) + {} + void print(String *str) { str->append(func_name); } +}; + + class Item_float :public Item_real { public: @@ -803,6 +826,20 @@ public: void cleanup() {} }; + +class Item_static_string_func :public Item_string +{ + const char *func_name; +public: + Item_static_string_func(const char *name_par, const char *str, uint length, + CHARSET_INFO *cs, + Derivation dv= DERIVATION_COERCIBLE) + :Item_string(NullS, str, length, cs, dv), func_name(name_par) + {} + void print(String *str) { str->append(func_name); } +}; + + /* for show tables */ class Item_datetime :public Item_string diff --git a/sql/item_create.cc b/sql/item_create.cc index e2c85af49bc..02cface827b 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -73,12 +73,13 @@ Item *create_func_connection_id(void) { THD *thd=current_thd; thd->lex->safe_to_cache_query= 0; - return new Item_int(NullS,(longlong) - ((thd->slave_thread) ? - thd->variables.pseudo_thread_id : - thd->thread_id), - 10); -} + return new Item_static_int_func("connection_id()", + (longlong) + ((thd->slave_thread) ? + thd->variables.pseudo_thread_id : + thd->thread_id), + 10); +} Item *create_func_conv(Item* a, Item *b, Item *c) { @@ -293,7 +294,7 @@ Item *create_func_period_diff(Item* a, Item *b) Item *create_func_pi(void) { - return new Item_real("pi()",M_PI,6,8); + return new Item_static_real_func("pi()", M_PI, 6, 8); } Item *create_func_pow(Item* a, Item *b) @@ -309,8 +310,9 @@ Item *create_func_current_user() length= (uint) (strxmov(buff, thd->priv_user, "@", thd->priv_host, NullS) - buff); - return new Item_string(NullS, thd->memdup(buff, length), length, - system_charset_info); + return new Item_static_string_func("current_user()", + thd->memdup(buff, length), length, + system_charset_info); } Item *create_func_radians(Item *a) @@ -434,7 +436,7 @@ Item *create_func_uuid(void) Item *create_func_version(void) { - return new Item_string(NullS,server_version, + return new Item_static_string_func("version()", server_version, (uint) strlen(server_version), system_charset_info, DERIVATION_IMPLICIT); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6ff50b32f50..b413f96ace2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -38,6 +38,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, static void free_cache_entry(TABLE *entry); static void mysql_rm_tmp_tables(void); static my_bool open_new_frm(const char *path, const char *alias, + const char *db, const char *table_name, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc, MEM_ROOT *mem_root); @@ -1379,8 +1380,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, { char path[FN_REFLEN]; int error; - // we support new format only is have all parameters for it - uint new_frm_flag= (table_desc && mem_root) ? NO_ERR_ON_NEW_FRM : 0; uint discover_retry_count= 0; DBUG_ENTER("open_unireg_entry"); @@ -1388,12 +1387,12 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, while ((error= openfrm(path, alias, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | HA_TRY_READ_ONLY | - new_frm_flag), + NO_ERR_ON_NEW_FRM), READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, thd->open_options, entry)) && (error != 5 || fn_format(path, path, 0, reg_ext, MY_UNPACK_FILENAME), - open_new_frm(path, alias, + open_new_frm(path, alias, db, name, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | HA_TRY_READ_ONLY), READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, @@ -1679,6 +1678,8 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) thd->proc_info="Opening table"; thd->current_tablenr= 0; + /* open_ltable can be used only for BASIC TABLEs */ + table_list->required_type= FRMTYPE_TABLE; while (!(table= open_table(thd, table_list, 0, &refresh)) && refresh) ; if (table) @@ -3209,6 +3210,8 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) open_new_frm() path path to .frm alias alias for table + db database + table_name name of table db_stat open flags (for example HA_OPEN_KEYFILE|HA_OPEN_RNDFILE..) can be 0 (example in ha_example_table) prgflag READ_ALL etc.. @@ -3218,7 +3221,9 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) mem_root temporary MEM_ROOT for parsing */ static my_bool -open_new_frm(const char *path, const char *alias, uint db_stat, uint prgflag, +open_new_frm(const char *path, const char *alias, + const char *db, const char *table_name, + uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc, MEM_ROOT *mem_root) { @@ -3226,28 +3231,36 @@ open_new_frm(const char *path, const char *alias, uint db_stat, uint prgflag, LEX_STRING pathstr; pathstr.str= (char *)path; pathstr.length= strlen(path); + + if (!mem_root) + mem_root= ¤t_thd->mem_root; + File_parser *parser= sql_parse_prepare(&pathstr, mem_root, 1); if (parser) { if (!strncmp("VIEW", parser->type()->str, parser->type()->length)) { - if (mysql_make_view(parser, table_desc)) + if (table_desc == 0 || table_desc->required_type == FRMTYPE_TABLE) { - bzero(outparam, sizeof(*outparam)); // do not run repair - DBUG_RETURN(1); + my_error(ER_WRONG_OBJECT, MYF(0), db, table_name, "BASE TABLE"); + goto err; } + if (mysql_make_view(parser, table_desc)) + goto err; } else { /* only VIEWs are supported now */ my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), path, parser->type()->str); - bzero(outparam, sizeof(outparam)); // do not run repair - DBUG_RETURN(1); + goto err; } } else - { - DBUG_RETURN(1); - } + goto err; + DBUG_RETURN(0); + +err: + bzero(outparam, sizeof(TABLE)); // do not run repair + DBUG_RETURN(1); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0fe0cf51041..f806bc0f123 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1546,7 +1546,7 @@ bool st_lex::can_be_merged() } /* - check if command can use VIEW with MERGE algorithm + check if command can use VIEW with MERGE algorithm (for top VIEWs) SYNOPSIS st_lex::can_use_merged() @@ -1576,6 +1576,29 @@ bool st_lex::can_use_merged() } } +/* + check if command can't use merged views in any part of command + + SYNOPSIS + st_lex::can_not_use_merged() + + RETURN + FALSE - command can't use merged VIEWs + TRUE - VIEWs with MERGE algorithms can be used +*/ + +bool st_lex::can_not_use_merged() +{ + switch (sql_command) + { + case SQLCOM_CREATE_VIEW: + case SQLCOM_SHOW_CREATE: + return TRUE; + default: + return FALSE; + } +} + /* Detect that we need only table structure of derived table/view diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d25381072a5..84b5cf3454b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -749,6 +749,7 @@ typedef struct st_lex bool can_be_merged(); bool can_use_merged(); + bool can_not_use_merged(); bool only_view_structure(); } LEX; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index c11207eac24..fa8b81f8ea2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1575,9 +1575,9 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) buff->append("MERGE ", 6); } buff->append("VIEW ", 5); - buff->append(table->view_db.str, table->view_db.length); + append_identifier(thd, buff, table->view_db.str, table->view_db.length); buff->append('.'); - buff->append(table->view_name.str, table->view_name.length); + append_identifier(thd, buff, table->view_name.str, table->view_name.length); buff->append(" AS ", 4); buff->append(table->query.str, table->query.length); return 0; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 78fcac4ddcf..3f0e0db1724 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -54,7 +54,7 @@ int mysql_create_view(THD *thd, TABLE_LIST *view= lex->unlink_first_table(&link_to_local); TABLE_LIST *tables= lex->query_tables; TABLE_LIST *tbl; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= &lex->select_lex, *sl; SELECT_LEX_UNIT *unit= &lex->unit; int res= 0; DBUG_ENTER("mysql_create_view"); @@ -74,56 +74,59 @@ int mysql_create_view(THD *thd, 0, 0) || grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) DBUG_RETURN(1); - for (tbl= tables; tbl; tbl= tbl->next_local) + for (sl= select_lex; sl; sl= sl->next_select()) { - /* - Ensure that we have some privilage on this table, more strict check - will be done on column level after preparation, - - SELECT_ACL will be checked for sure for all fields because it is - listed first (if we have not rights to SELECT from whole table this - right will be written as tbl->grant.want_privilege and will be checked - later (except fields which need any privilege and can be updated). - */ - if ((check_access(thd, SELECT_ACL, tbl->db, - &tbl->grant.privilege, 0, 1) || - grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 1)) && - (check_access(thd, INSERT_ACL, tbl->db, - &tbl->grant.privilege, 0, 1) || - grant_option && check_grant(thd, INSERT_ACL, tbl, 0, 1, 1)) && - (check_access(thd, DELETE_ACL, tbl->db, - &tbl->grant.privilege, 0, 1) || - grant_option && check_grant(thd, DELETE_ACL, tbl, 0, 1, 1)) && - (check_access(thd, UPDATE_ACL, tbl->db, - &tbl->grant.privilege, 0, 1) || - grant_option && check_grant(thd, UPDATE_ACL, tbl, 0, 1, 1)) - ) + for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local) { - my_printf_error(ER_TABLEACCESS_DENIED_ERROR, - ER(ER_TABLEACCESS_DENIED_ERROR), - MYF(0), - "ANY", - thd->priv_user, - thd->host_or_ip, - tbl->real_name); - DBUG_RETURN(-1); + /* + Ensure that we have some privilage on this table, more strict check + will be done on column level after preparation, + + SELECT_ACL will be checked for sure for all fields because it is + listed first (if we have not rights to SELECT from whole table this + right will be written as tbl->grant.want_privilege and will be checked + later (except fields which need any privilege and can be updated). + */ + if ((check_access(thd, SELECT_ACL, tbl->db, + &tbl->grant.privilege, 0, 1) || + grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 1)) && + (check_access(thd, INSERT_ACL, tbl->db, + &tbl->grant.privilege, 0, 1) || + grant_option && check_grant(thd, INSERT_ACL, tbl, 0, 1, 1)) && + (check_access(thd, DELETE_ACL, tbl->db, + &tbl->grant.privilege, 0, 1) || + grant_option && check_grant(thd, DELETE_ACL, tbl, 0, 1, 1)) && + (check_access(thd, UPDATE_ACL, tbl->db, + &tbl->grant.privilege, 0, 1) || + grant_option && check_grant(thd, UPDATE_ACL, tbl, 0, 1, 1)) + ) + { + my_printf_error(ER_TABLEACCESS_DENIED_ERROR, + ER(ER_TABLEACCESS_DENIED_ERROR), + MYF(0), + "ANY", + thd->priv_user, + thd->host_or_ip, + tbl->real_name); + DBUG_RETURN(-1); + } + /* mark this table as table which will be checked after preparation */ + tbl->table_in_first_from_clause= 1; + + /* + We need to check only SELECT_ACL for all normal fields, fields + where we need any privilege will be pmarked later + */ + tbl->grant.want_privilege= SELECT_ACL; + /* + Make sure that all rights are loaded to table 'grant' field. + + tbl->real_name will be correct name of table because VIEWs are + not opened yet. + */ + fill_effective_table_privileges(thd, &tbl->grant, tbl->db, + tbl->real_name); } - /* mark this table as table which will be checked after preparation */ - tbl->table_in_first_from_clause= 1; - - /* - We need to check only SELECT_ACL for all normal fields, fields - where we need any privilege will be pmarked later - */ - tbl->grant.want_privilege= SELECT_ACL; - /* - Make sure that all rights are loaded to table 'grant' field. - - tbl->real_name will be correct name of table because VIEWs are - not opened yet. - */ - fill_effective_table_privileges(thd, &tbl->grant, tbl->db, - tbl->real_name); } if (&lex->select_lex != lex->all_selects_list) @@ -145,12 +148,10 @@ int mysql_create_view(THD *thd, } /* Mark fields for special privilege check (any privilege) - - 'if' should be changed if we made updateable UNION. */ - if (lex->select_lex.next_select() == 0) + for (sl= select_lex; sl; sl= sl->next_select()) { - List_iterator_fast it(lex->select_lex.item_list); + List_iterator_fast it(sl->item_list); Item *item; while ((item= it++)) { @@ -235,9 +236,10 @@ int mysql_create_view(THD *thd, /* Compare/check grants on view with grants of underlaying tables */ + for (sl= select_lex; sl; sl= sl->next_select()) { char *db= view->db ? view->db : thd->db; - List_iterator_fast it(select_lex->item_list); + List_iterator_fast it(sl->item_list); Item *item; fill_effective_table_privileges(thd, &view->grant, db, view->real_name); @@ -657,7 +659,8 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) if (table->algorithm != VIEW_ALGORITHM_TMEPTABLE && lex->can_be_merged() && (table->select_lex->master_unit() != &old_lex->unit || - old_lex->can_use_merged())) + old_lex->can_use_merged()) && + !old_lex->can_not_use_merged()) { /* TODO: support multi tables substitutions @@ -670,6 +673,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) DBUG_ASSERT(view_table != 0); table->effective_algorithm= VIEW_ALGORITHM_MERGE; + DBUG_PRINT("info", ("algorithm: MERGE")); table->updatable= (table->updatable_view != 0); if (old_next) @@ -699,6 +703,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) } table->effective_algorithm= VIEW_ALGORITHM_TMEPTABLE; + DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE")); lex->select_lex.linkage= DERIVED_TABLE_TYPE; table->updatable= 0; diff --git a/sql/sql_view.h b/sql/sql_view.h index 36eae6cdcfc..431f82a5bb8 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -27,13 +27,6 @@ bool check_key_in_view(THD *thd, TABLE_LIST * view); void insert_view_fields(List *list, TABLE_LIST *view); -enum frm_type_enum -{ - FRMTYPE_ERROR, - FRMTYPE_TABLE, - FRMTYPE_VIEW -}; - frm_type_enum mysql_frm_type(char *path); extern TYPELIB sql_updatable_view_key_typelib; diff --git a/sql/table.cc b/sql/table.cc index 097dc8aabf6..a1e1faa36a6 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1506,6 +1506,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) uint i= 0; bool save_set_query_id= thd->set_query_id; bool save_wrapper= thd->lex->select_lex.no_wrap_view_item; + bool save_allow_sum_func= thd->allow_sum_func; DBUG_ENTER("st_table_list::setup_ancestor"); if (ancestor->ancestor && @@ -1525,6 +1526,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) uint want_privilege= ancestor->table->grant.want_privilege; /* real rights will be checked in VIEW field */ ancestor->table->grant.want_privilege= 0; + /* aggregate function are allowed */ + thd->allow_sum_func= 1; if (!(*i)->fixed && (*i)->fix_fields(thd, ancestor, i)) goto err; ancestor->table->grant.want_privilege= want_privilege; @@ -1558,6 +1561,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) uint want_privilege= ancestor->table->grant.want_privilege; /* real rights will be checked in VIEW field */ ancestor->table->grant.want_privilege= 0; + /* aggregate function are allowed */ + thd->allow_sum_func= 1; if (!item->fixed && item->fix_fields(thd, ancestor, &item)) { goto err; @@ -1602,6 +1607,7 @@ ok: thd->lex->select_lex.no_wrap_view_item= save_wrapper; thd->lex->current_select= current_select_save; thd->set_query_id= save_set_query_id; + thd->allow_sum_func= save_allow_sum_func; DBUG_RETURN(0); err: @@ -1614,6 +1620,7 @@ err: thd->lex->select_lex.no_wrap_view_item= save_wrapper; thd->lex->current_select= current_select_save; thd->set_query_id= save_set_query_id; + thd->allow_sum_func= save_allow_sum_func; DBUG_RETURN(1); } diff --git a/sql/table.h b/sql/table.h index 75d54d9d069..dd41ab79b7b 100644 --- a/sql/table.h +++ b/sql/table.h @@ -47,6 +47,13 @@ typedef struct st_grant_info enum tmp_table_type {NO_TMP_TABLE=0, TMP_TABLE=1, TRANSACTIONAL_TMP_TABLE=2}; +enum frm_type_enum +{ + FRMTYPE_ERROR= 0, + FRMTYPE_TABLE, + FRMTYPE_VIEW +}; + typedef struct st_filesort_info { IO_CACHE *io_cache; /* If sorted through filebyte */ @@ -241,6 +248,8 @@ typedef struct st_table_list bool setup_is_done; /* setup_tables() is done */ /* do view contain auto_increment field */ bool contain_auto_increment; + /* FRMTYPE_ERROR if any type is acceptable */ + enum frm_type_enum required_type; char timestamp_buffer[20]; /* buffer for timestamp (19+1) */ void calc_md5(char *buffer);