Commit 545fd08b authored by unknown's avatar unknown

Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0

into sanja.is.com.ua:/home/bell/mysql/bk/work-5.0
parents 842bf0b1 f157f01e
...@@ -32,10 +32,10 @@ c ...@@ -32,10 +32,10 @@ c
11 11
show create table v1; show create table v1;
Table Create Table 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; show create view v1;
Table Create Table 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; show create view t1;
ERROR HY000: 'test.t1' is not VIEW ERROR HY000: 'test.t1' is not VIEW
drop table t1; drop table t1;
...@@ -55,7 +55,7 @@ Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`v1` ...@@ -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; create algorithm=temptable view v2 (c) as select b+1 from t1;
show create table v2; show create table v2;
Table Create Table 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; select c from v2;
c c
3 3
...@@ -306,14 +306,14 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -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 1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
show create table mysqltest.v1; show create table mysqltest.v1;
Table Create Table 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; explain select c from mysqltest.v2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found 1 PRIMARY <derived2> 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 2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
show create table mysqltest.v2; show create table mysqltest.v2;
Table Create Table 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; explain select c from mysqltest.v3;
ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
show create table mysqltest.v3; show create table mysqltest.v3;
...@@ -328,27 +328,27 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -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 1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
show create table mysqltest.v1; show create table mysqltest.v1;
Table Create Table 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; explain select c from mysqltest.v2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found 1 PRIMARY <derived2> 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 2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
show create table mysqltest.v2; show create table mysqltest.v2;
Table Create Table 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; explain select c from mysqltest.v3;
id select_type table type possible_keys key key_len ref rows Extra 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 1 PRIMARY t2 system NULL NULL NULL NULL 0 const row not found
show create table mysqltest.v3; show create table mysqltest.v3;
Table Create Table 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; explain select c from mysqltest.v4;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found 1 PRIMARY <derived2> 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 2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
show create table mysqltest.v4; show create table mysqltest.v4;
Table Create Table 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; revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
drop database mysqltest; drop database mysqltest;
...@@ -830,7 +830,7 @@ a b c ...@@ -830,7 +830,7 @@ a b c
30 4 -60 30 4 -60
50 6 -100 50 6 -100
40 5 NULL 40 5 NULL
drop table t1; drop table t1, t2;
drop view v1,v2,v3,v4,v5; drop view v1,v2,v3,v4,v5;
create database mysqltest; create database mysqltest;
create table mysqltest.t1 (a int, b int, primary key(a)); create table mysqltest.t1 (a int, b int, primary key(a));
...@@ -946,7 +946,7 @@ create table t1 ("a*b" int); ...@@ -946,7 +946,7 @@ create table t1 ("a*b" int);
create view v1 as select "a*b" from t1; create view v1 as select "a*b" from t1;
show create view v1; show create view v1;
Table Create Table 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 view v1;
drop table t1; drop table t1;
set sql_mode=default; set sql_mode=default;
...@@ -1040,10 +1040,60 @@ CREATE VIEW v02 AS SELECT * FROM DUAL; ...@@ -1040,10 +1040,60 @@ CREATE VIEW v02 AS SELECT * FROM DUAL;
ERROR HY000: No tables used ERROR HY000: No tables used
SHOW TABLES; SHOW TABLES;
Tables_in_test table_type Tables_in_test table_type
t2 BASE TABLE
v4 VIEW v4 VIEW
CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2); CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2);
select * from v1; select * from v1;
EXISTS (SELECT 1 UNION SELECT 2) EXISTS (SELECT 1 UNION SELECT 2)
1 1
drop view v1; 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`;
...@@ -693,7 +693,7 @@ insert into v1 select c, b, a from t2; ...@@ -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 v1 (z,y,x) select a+20,b+2,-100 from t2;
insert into v2 select b+1, a+10 from t2; insert into v2 select b+1, a+10 from t2;
select * from t1; select * from t1;
drop table t1; drop table t1, t2;
drop view v1,v2,v3,v4,v5; drop view v1,v2,v3,v4,v5;
# #
...@@ -987,3 +987,61 @@ SHOW TABLES; ...@@ -987,3 +987,61 @@ SHOW TABLES;
CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2); CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2);
select * from v1; select * from v1;
drop view 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`;
...@@ -669,6 +669,17 @@ class Item_int :public Item_num ...@@ -669,6 +669,17 @@ class Item_int :public Item_num
}; };
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 class Item_uint :public Item_int
{ {
public: public:
...@@ -724,6 +735,18 @@ class Item_real :public Item_num ...@@ -724,6 +735,18 @@ class Item_real :public Item_num
}; };
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 class Item_float :public Item_real
{ {
public: public:
...@@ -803,6 +826,20 @@ class Item_string :public Item ...@@ -803,6 +826,20 @@ class Item_string :public Item
void cleanup() {} 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 */ /* for show tables */
class Item_datetime :public Item_string class Item_datetime :public Item_string
......
...@@ -73,12 +73,13 @@ Item *create_func_connection_id(void) ...@@ -73,12 +73,13 @@ Item *create_func_connection_id(void)
{ {
THD *thd=current_thd; THD *thd=current_thd;
thd->lex->safe_to_cache_query= 0; thd->lex->safe_to_cache_query= 0;
return new Item_int(NullS,(longlong) return new Item_static_int_func("connection_id()",
((thd->slave_thread) ? (longlong)
thd->variables.pseudo_thread_id : ((thd->slave_thread) ?
thd->thread_id), thd->variables.pseudo_thread_id :
10); thd->thread_id),
} 10);
}
Item *create_func_conv(Item* a, Item *b, Item *c) Item *create_func_conv(Item* a, Item *b, Item *c)
{ {
...@@ -293,7 +294,7 @@ Item *create_func_period_diff(Item* a, Item *b) ...@@ -293,7 +294,7 @@ Item *create_func_period_diff(Item* a, Item *b)
Item *create_func_pi(void) 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) Item *create_func_pow(Item* a, Item *b)
...@@ -309,8 +310,9 @@ Item *create_func_current_user() ...@@ -309,8 +310,9 @@ Item *create_func_current_user()
length= (uint) (strxmov(buff, thd->priv_user, "@", thd->priv_host, NullS) - length= (uint) (strxmov(buff, thd->priv_user, "@", thd->priv_host, NullS) -
buff); buff);
return new Item_string(NullS, thd->memdup(buff, length), length, return new Item_static_string_func("current_user()",
system_charset_info); thd->memdup(buff, length), length,
system_charset_info);
} }
Item *create_func_radians(Item *a) Item *create_func_radians(Item *a)
...@@ -434,7 +436,7 @@ Item *create_func_uuid(void) ...@@ -434,7 +436,7 @@ Item *create_func_uuid(void)
Item *create_func_version(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), (uint) strlen(server_version),
system_charset_info, DERIVATION_IMPLICIT); system_charset_info, DERIVATION_IMPLICIT);
} }
......
...@@ -38,6 +38,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, ...@@ -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 free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void); static void mysql_rm_tmp_tables(void);
static my_bool open_new_frm(const char *path, const char *alias, 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 db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam, uint ha_open_flags, TABLE *outparam,
TABLE_LIST *table_desc, MEM_ROOT *mem_root); TABLE_LIST *table_desc, MEM_ROOT *mem_root);
...@@ -1379,8 +1380,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, ...@@ -1379,8 +1380,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
int error; 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; uint discover_retry_count= 0;
DBUG_ENTER("open_unireg_entry"); DBUG_ENTER("open_unireg_entry");
...@@ -1388,12 +1387,12 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, ...@@ -1388,12 +1387,12 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
while ((error= openfrm(path, alias, while ((error= openfrm(path, alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
HA_GET_INDEX | HA_TRY_READ_ONLY | HA_GET_INDEX | HA_TRY_READ_ONLY |
new_frm_flag), NO_ERR_ON_NEW_FRM),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
thd->open_options, entry)) && thd->open_options, entry)) &&
(error != 5 || (error != 5 ||
fn_format(path, path, 0, reg_ext, MY_UNPACK_FILENAME), 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 | (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
HA_GET_INDEX | HA_TRY_READ_ONLY), HA_GET_INDEX | HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
...@@ -1679,6 +1678,8 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) ...@@ -1679,6 +1678,8 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
thd->proc_info="Opening table"; thd->proc_info="Opening table";
thd->current_tablenr= 0; 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) ; while (!(table= open_table(thd, table_list, 0, &refresh)) && refresh) ;
if (table) if (table)
...@@ -3209,6 +3210,8 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) ...@@ -3209,6 +3210,8 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
open_new_frm() open_new_frm()
path path to .frm path path to .frm
alias alias for table alias alias for table
db database
table_name name of table
db_stat open flags (for example HA_OPEN_KEYFILE|HA_OPEN_RNDFILE..) db_stat open flags (for example HA_OPEN_KEYFILE|HA_OPEN_RNDFILE..)
can be 0 (example in ha_example_table) can be 0 (example in ha_example_table)
prgflag READ_ALL etc.. prgflag READ_ALL etc..
...@@ -3218,7 +3221,9 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) ...@@ -3218,7 +3221,9 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
mem_root temporary MEM_ROOT for parsing mem_root temporary MEM_ROOT for parsing
*/ */
static my_bool 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, uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc,
MEM_ROOT *mem_root) MEM_ROOT *mem_root)
{ {
...@@ -3226,28 +3231,36 @@ open_new_frm(const char *path, const char *alias, uint db_stat, uint prgflag, ...@@ -3226,28 +3231,36 @@ open_new_frm(const char *path, const char *alias, uint db_stat, uint prgflag,
LEX_STRING pathstr; LEX_STRING pathstr;
pathstr.str= (char *)path; pathstr.str= (char *)path;
pathstr.length= strlen(path); pathstr.length= strlen(path);
if (!mem_root)
mem_root= &current_thd->mem_root;
File_parser *parser= sql_parse_prepare(&pathstr, mem_root, 1); File_parser *parser= sql_parse_prepare(&pathstr, mem_root, 1);
if (parser) if (parser)
{ {
if (!strncmp("VIEW", parser->type()->str, parser->type()->length)) 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 my_error(ER_WRONG_OBJECT, MYF(0), db, table_name, "BASE TABLE");
DBUG_RETURN(1); goto err;
} }
if (mysql_make_view(parser, table_desc))
goto err;
} }
else else
{ {
/* only VIEWs are supported now */ /* only VIEWs are supported now */
my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), path, parser->type()->str); my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), path, parser->type()->str);
bzero(outparam, sizeof(outparam)); // do not run repair goto err;
DBUG_RETURN(1);
} }
} }
else else
{ goto err;
DBUG_RETURN(1);
}
DBUG_RETURN(0); DBUG_RETURN(0);
err:
bzero(outparam, sizeof(TABLE)); // do not run repair
DBUG_RETURN(1);
} }
...@@ -1546,7 +1546,7 @@ bool st_lex::can_be_merged() ...@@ -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 SYNOPSIS
st_lex::can_use_merged() st_lex::can_use_merged()
...@@ -1576,6 +1576,29 @@ bool 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 Detect that we need only table structure of derived table/view
......
...@@ -749,6 +749,7 @@ typedef struct st_lex ...@@ -749,6 +749,7 @@ typedef struct st_lex
bool can_be_merged(); bool can_be_merged();
bool can_use_merged(); bool can_use_merged();
bool can_not_use_merged();
bool only_view_structure(); bool only_view_structure();
} LEX; } LEX;
......
...@@ -1575,9 +1575,9 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) ...@@ -1575,9 +1575,9 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
buff->append("MERGE ", 6); buff->append("MERGE ", 6);
} }
buff->append("VIEW ", 5); 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('.');
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(" AS ", 4);
buff->append(table->query.str, table->query.length); buff->append(table->query.str, table->query.length);
return 0; return 0;
......
...@@ -54,7 +54,7 @@ int mysql_create_view(THD *thd, ...@@ -54,7 +54,7 @@ int mysql_create_view(THD *thd,
TABLE_LIST *view= lex->unlink_first_table(&link_to_local); TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
TABLE_LIST *tables= lex->query_tables; TABLE_LIST *tables= lex->query_tables;
TABLE_LIST *tbl; TABLE_LIST *tbl;
SELECT_LEX *select_lex= &lex->select_lex; SELECT_LEX *select_lex= &lex->select_lex, *sl;
SELECT_LEX_UNIT *unit= &lex->unit; SELECT_LEX_UNIT *unit= &lex->unit;
int res= 0; int res= 0;
DBUG_ENTER("mysql_create_view"); DBUG_ENTER("mysql_create_view");
...@@ -74,56 +74,59 @@ int mysql_create_view(THD *thd, ...@@ -74,56 +74,59 @@ int mysql_create_view(THD *thd,
0, 0) || 0, 0) ||
grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0))
DBUG_RETURN(1); DBUG_RETURN(1);
for (tbl= tables; tbl; tbl= tbl->next_local) for (sl= select_lex; sl; sl= sl->next_select())
{ {
/* for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local)
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), Ensure that we have some privilage on this table, more strict check
MYF(0), will be done on column level after preparation,
"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;
/* SELECT_ACL will be checked for sure for all fields because it is
We need to check only SELECT_ACL for all normal fields, fields listed first (if we have not rights to SELECT from whole table this
where we need any privilege will be pmarked later right will be written as tbl->grant.want_privilege and will be checked
*/ later (except fields which need any privilege and can be updated).
tbl->grant.want_privilege= SELECT_ACL; */
/* if ((check_access(thd, SELECT_ACL, tbl->db,
Make sure that all rights are loaded to table 'grant' field. &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;
tbl->real_name will be correct name of table because VIEWs are /*
not opened yet. We need to check only SELECT_ACL for all normal fields, fields
*/ where we need any privilege will be pmarked later
fill_effective_table_privileges(thd, &tbl->grant, tbl->db, */
tbl->real_name); 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) if (&lex->select_lex != lex->all_selects_list)
...@@ -145,12 +148,10 @@ int mysql_create_view(THD *thd, ...@@ -145,12 +148,10 @@ int mysql_create_view(THD *thd,
} }
/* /*
Mark fields for special privilege check (any privilege) 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<Item> it(lex->select_lex.item_list); List_iterator_fast<Item> it(sl->item_list);
Item *item; Item *item;
while ((item= it++)) while ((item= it++))
{ {
...@@ -235,9 +236,10 @@ int mysql_create_view(THD *thd, ...@@ -235,9 +236,10 @@ int mysql_create_view(THD *thd,
/* /*
Compare/check grants on view with grants of underlaying tables 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; char *db= view->db ? view->db : thd->db;
List_iterator_fast<Item> it(select_lex->item_list); List_iterator_fast<Item> it(sl->item_list);
Item *item; Item *item;
fill_effective_table_privileges(thd, &view->grant, db, fill_effective_table_privileges(thd, &view->grant, db,
view->real_name); view->real_name);
...@@ -657,7 +659,8 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) ...@@ -657,7 +659,8 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
if (table->algorithm != VIEW_ALGORITHM_TMEPTABLE && if (table->algorithm != VIEW_ALGORITHM_TMEPTABLE &&
lex->can_be_merged() && lex->can_be_merged() &&
(table->select_lex->master_unit() != &old_lex->unit || (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 TODO: support multi tables substitutions
...@@ -670,6 +673,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) ...@@ -670,6 +673,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
DBUG_ASSERT(view_table != 0); DBUG_ASSERT(view_table != 0);
table->effective_algorithm= VIEW_ALGORITHM_MERGE; table->effective_algorithm= VIEW_ALGORITHM_MERGE;
DBUG_PRINT("info", ("algorithm: MERGE"));
table->updatable= (table->updatable_view != 0); table->updatable= (table->updatable_view != 0);
if (old_next) if (old_next)
...@@ -699,6 +703,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) ...@@ -699,6 +703,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
} }
table->effective_algorithm= VIEW_ALGORITHM_TMEPTABLE; table->effective_algorithm= VIEW_ALGORITHM_TMEPTABLE;
DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE"));
lex->select_lex.linkage= DERIVED_TABLE_TYPE; lex->select_lex.linkage= DERIVED_TABLE_TYPE;
table->updatable= 0; table->updatable= 0;
......
...@@ -27,13 +27,6 @@ bool check_key_in_view(THD *thd, TABLE_LIST * view); ...@@ -27,13 +27,6 @@ bool check_key_in_view(THD *thd, TABLE_LIST * view);
void insert_view_fields(List<Item> *list, TABLE_LIST *view); void insert_view_fields(List<Item> *list, TABLE_LIST *view);
enum frm_type_enum
{
FRMTYPE_ERROR,
FRMTYPE_TABLE,
FRMTYPE_VIEW
};
frm_type_enum mysql_frm_type(char *path); frm_type_enum mysql_frm_type(char *path);
extern TYPELIB sql_updatable_view_key_typelib; extern TYPELIB sql_updatable_view_key_typelib;
......
...@@ -1506,6 +1506,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) ...@@ -1506,6 +1506,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
uint i= 0; uint i= 0;
bool save_set_query_id= thd->set_query_id; bool save_set_query_id= thd->set_query_id;
bool save_wrapper= thd->lex->select_lex.no_wrap_view_item; 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"); DBUG_ENTER("st_table_list::setup_ancestor");
if (ancestor->ancestor && if (ancestor->ancestor &&
...@@ -1525,6 +1526,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) ...@@ -1525,6 +1526,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
uint want_privilege= ancestor->table->grant.want_privilege; uint want_privilege= ancestor->table->grant.want_privilege;
/* real rights will be checked in VIEW field */ /* real rights will be checked in VIEW field */
ancestor->table->grant.want_privilege= 0; ancestor->table->grant.want_privilege= 0;
/* aggregate function are allowed */
thd->allow_sum_func= 1;
if (!(*i)->fixed && (*i)->fix_fields(thd, ancestor, i)) if (!(*i)->fixed && (*i)->fix_fields(thd, ancestor, i))
goto err; goto err;
ancestor->table->grant.want_privilege= want_privilege; ancestor->table->grant.want_privilege= want_privilege;
...@@ -1558,6 +1561,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) ...@@ -1558,6 +1561,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
uint want_privilege= ancestor->table->grant.want_privilege; uint want_privilege= ancestor->table->grant.want_privilege;
/* real rights will be checked in VIEW field */ /* real rights will be checked in VIEW field */
ancestor->table->grant.want_privilege= 0; ancestor->table->grant.want_privilege= 0;
/* aggregate function are allowed */
thd->allow_sum_func= 1;
if (!item->fixed && item->fix_fields(thd, ancestor, &item)) if (!item->fixed && item->fix_fields(thd, ancestor, &item))
{ {
goto err; goto err;
...@@ -1602,6 +1607,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) ...@@ -1602,6 +1607,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
thd->lex->select_lex.no_wrap_view_item= save_wrapper; thd->lex->select_lex.no_wrap_view_item= save_wrapper;
thd->lex->current_select= current_select_save; thd->lex->current_select= current_select_save;
thd->set_query_id= save_set_query_id; thd->set_query_id= save_set_query_id;
thd->allow_sum_func= save_allow_sum_func;
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
...@@ -1614,6 +1620,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) ...@@ -1614,6 +1620,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
thd->lex->select_lex.no_wrap_view_item= save_wrapper; thd->lex->select_lex.no_wrap_view_item= save_wrapper;
thd->lex->current_select= current_select_save; thd->lex->current_select= current_select_save;
thd->set_query_id= save_set_query_id; thd->set_query_id= save_set_query_id;
thd->allow_sum_func= save_allow_sum_func;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
......
...@@ -47,6 +47,13 @@ typedef struct st_grant_info ...@@ -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 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 typedef struct st_filesort_info
{ {
IO_CACHE *io_cache; /* If sorted through filebyte */ IO_CACHE *io_cache; /* If sorted through filebyte */
...@@ -241,6 +248,8 @@ typedef struct st_table_list ...@@ -241,6 +248,8 @@ typedef struct st_table_list
bool setup_is_done; /* setup_tables() is done */ bool setup_is_done; /* setup_tables() is done */
/* do view contain auto_increment field */ /* do view contain auto_increment field */
bool contain_auto_increment; 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) */ char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
void calc_md5(char *buffer); void calc_md5(char *buffer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment