From 46a0c8a7df4ef7cc53bbade3ffcbff4b4a046fd8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Aug 2004 15:37:51 +0300 Subject: [PATCH 1/7] sending right error message where VIEW is not expected (BUG#4606) mysql-test/r/view.result: using VIEW where table is required mysql-test/t/view.test: using VIEW where table is required sql/sql_base.cc: sending right error message where VIEW is not expected sql/sql_view.h: frm_type_enum moved to table.h becuae used in TABLE_LIST sql/table.h: frm_type_enum moved to table.h becuae used in TABLE_LIST --- mysql-test/r/view.result | 6 ++++++ mysql-test/t/view.test | 10 ++++++++++ sql/sql_base.cc | 39 ++++++++++++++++++++++++++------------- sql/sql_view.h | 7 ------- sql/table.h | 9 +++++++++ 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 7bade28f395..f2a4648bdc4 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1047,3 +1047,9 @@ 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 BASIC TABLE +drop view v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index c00489c1d1a..d9d9d0ba765 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -987,3 +987,13 @@ 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; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6ff50b32f50..8a8c0ece0a7 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, "BASIC 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_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.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); From c688b7b882e9eda4e19c8db0715184a802446756 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Aug 2004 18:46:27 +0300 Subject: [PATCH 2/7] items for functions which is converted to constants internally to support its correct printing added (BUG#4663) mysql-test/r/view.result: test of functions in VIEW which is converted to constants internally mysql-test/t/view.test: test of functions in VIEW which is converted to constants internally sql/item.h: items for functions which is converted to constants internally to support its correct printing sql/item_create.cc: items for functions which is converted to constants internally to support its correct printing --- mysql-test/r/view.result | 5 +++++ mysql-test/t/view.test | 7 +++++++ sql/item.h | 37 +++++++++++++++++++++++++++++++++++++ sql/item_create.cc | 22 ++++++++++++---------- 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f2a4648bdc4..ac19dbe4ffa 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1053,3 +1053,8 @@ create index i1 on v1 (col1); ERROR HY000: 'test.v1' is not BASIC 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; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index d9d9d0ba765..dc92d7936eb 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -997,3 +997,10 @@ create view v1 as select * from t1; 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; 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); } From 964955b1c0c85c460efa4bbd757848d5e042b37d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Aug 2004 19:50:16 +0300 Subject: [PATCH 3/7] Fixed UNION support in view creation (BUG#4664) mysql-test/r/view.result: added removing of table t2 test of view built over union mysql-test/t/view.test: added removing of table t2 test of view built over union sql/sql_view.cc: Fixed UNION support in view creation --- mysql-test/r/view.result | 20 +++++++- mysql-test/t/view.test | 14 ++++- sql/sql_view.cc | 108 ++++++++++++++++++++------------------- 3 files changed, 86 insertions(+), 56 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index ac19dbe4ffa..059b8d4cf70 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -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)); @@ -1040,7 +1040,6 @@ 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; @@ -1058,3 +1057,20 @@ 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; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index dc92d7936eb..805d033c525 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; # @@ -1004,3 +1004,15 @@ drop table t1; 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; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 78fcac4ddcf..f531f2c94f5 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); From 52b735a1a2ddd54ec265844c54690ea846dbcaa8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Aug 2004 20:29:44 +0300 Subject: [PATCH 4/7] fixed aggregate function processing in VIEWs (BUG#4665) mysql-test/r/view.result: Aggregate functions in view list mysql-test/t/view.test: Aggregate functions in view list sql/table.cc: fixed aggregate function processing in VIEWs --- mysql-test/r/view.result | 9 +++++++++ mysql-test/t/view.test | 11 +++++++++++ sql/table.cc | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 059b8d4cf70..87d64a69e49 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1074,3 +1074,12 @@ s1 s2 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; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 805d033c525..0cc403c5dfd 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1016,3 +1016,14 @@ 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; 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); } From b8785595b9ce92e7d555bf6eb27371c9b7e541a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Aug 2004 22:51:23 +0300 Subject: [PATCH 5/7] new method to detect commands where all VIEWs should be temporary tables (BUG#4803) mysql-test/r/view.result: Showing VIEW with VIEWs in subquery mysql-test/t/view.test: Showing VIEW with VIEWs in subquery sql/sql_lex.cc: new method to detect commands where all VIEWs should be temporary tables sql/sql_lex.h: new method to detect commands where all VIEWs should be temporary tables sql/sql_view.cc: new method to detect commands where all VIEWs should be temporary tables debug output added --- mysql-test/r/view.result | 9 +++++++++ mysql-test/t/view.test | 11 +++++++++++ sql/sql_lex.cc | 25 ++++++++++++++++++++++++- sql/sql_lex.h | 1 + sql/sql_view.cc | 5 ++++- 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 87d64a69e49..d99743c9a03 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1083,3 +1083,12 @@ 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; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 0cc403c5dfd..82f6f46d80c 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1027,3 +1027,14 @@ 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; 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_view.cc b/sql/sql_view.cc index f531f2c94f5..3f0e0db1724 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -659,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 @@ -672,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) @@ -701,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; From d8f599bcdcf7248c872dc8f0d5117e744a6bc119 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Aug 2004 23:07:34 +0300 Subject: [PATCH 6/7] fixes name outout for SHOW CREATE VIEW command (BUG#5162) mysql-test/r/view.result: SHOW CREATE VIEW output changed test of SHOW CREATE VIEW for view with spaces in the name mysql-test/t/view.test: test of SHOW CREATE VIEW for view with spaces in the name sql/sql_show.cc: fixes name outout for SHOW CREATE VIEW command --- mysql-test/r/view.result | 29 +++++++++++++++++------------ mysql-test/t/view.test | 7 +++++++ sql/sql_show.cc | 4 ++-- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index d99743c9a03..ddad7395cec 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; @@ -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; @@ -1055,7 +1055,7 @@ 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` +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); @@ -1089,6 +1089,11 @@ 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`) +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 82f6f46d80c..1c3064e864e 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1038,3 +1038,10 @@ 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/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; From 367d882bb36b34197cdd7437f264706cf6b35a62 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Aug 2004 08:56:46 +0300 Subject: [PATCH 7/7] wording changed (postreview fix) mysql-test/r/view.result: wording changed sql/sql_base.cc: wording changed --- mysql-test/r/view.result | 2 +- sql/sql_base.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index ddad7395cec..b84d79bc09c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1049,7 +1049,7 @@ 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 BASIC TABLE +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(); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8a8c0ece0a7..b413f96ace2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3242,7 +3242,7 @@ open_new_frm(const char *path, const char *alias, { if (table_desc == 0 || table_desc->required_type == FRMTYPE_TABLE) { - my_error(ER_WRONG_OBJECT, MYF(0), db, table_name, "BASIC TABLE"); + my_error(ER_WRONG_OBJECT, MYF(0), db, table_name, "BASE TABLE"); goto err; } if (mysql_make_view(parser, table_desc))