Merge quad.:/mnt/raid/alik/MySQL/devel/5.0
into quad.:/mnt/raid/alik/MySQL/devel/5.0-rt-merged
This commit is contained in:
commit
c61667bca8
@ -1709,4 +1709,156 @@ a b
|
|||||||
9999999999999999 14632475938453979136
|
9999999999999999 14632475938453979136
|
||||||
deallocate prepare stmt;
|
deallocate prepare stmt;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
drop view if exists v1;
|
||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (a int, b int);
|
||||||
|
insert into t1 values (1,1), (2,2), (3,3);
|
||||||
|
insert into t1 values (3,1), (1,2), (2,3);
|
||||||
|
prepare stmt from "create view v1 as select * from t1";
|
||||||
|
execute stmt;
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int, b int);
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1`
|
||||||
|
drop view v1;
|
||||||
|
prepare stmt from "create view v1 (c,d) as select a,b from t1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d` from `t1`
|
||||||
|
select * from v1;
|
||||||
|
c d
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d` from `t1`
|
||||||
|
select * from v1;
|
||||||
|
c d
|
||||||
|
drop view v1;
|
||||||
|
prepare stmt from "create view v1 (c) as select b+1 from t1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1`
|
||||||
|
select * from v1;
|
||||||
|
c
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1`
|
||||||
|
select * from v1;
|
||||||
|
c
|
||||||
|
drop view v1;
|
||||||
|
prepare stmt from "create view v1 (c,d,e,f) as select a,b,a in (select a+2 from t1), a = all (select a from t1) from t1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d`,`t1`.`a` in (select (`t1`.`a` + 2) AS `a+2` from `t1`) AS `e`,`t1`.`a` = all (select `t1`.`a` AS `a` from `t1`) AS `f` from `t1`
|
||||||
|
select * from v1;
|
||||||
|
c d e f
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d`,`t1`.`a` in (select (`t1`.`a` + 2) AS `a+2` from `t1`) AS `e`,`t1`.`a` = all (select `t1`.`a` AS `a` from `t1`) AS `f` from `t1`
|
||||||
|
select * from v1;
|
||||||
|
c d e f
|
||||||
|
drop view v1;
|
||||||
|
prepare stmt from "create or replace view v1 as select 1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`
|
||||||
|
select * from v1;
|
||||||
|
1
|
||||||
|
1
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`
|
||||||
|
select * from v1;
|
||||||
|
1
|
||||||
|
1
|
||||||
|
drop view v1;
|
||||||
|
prepare stmt from "create view v1 as select 1, 1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`,1 AS `My_exp_1`
|
||||||
|
select * from v1;
|
||||||
|
1 My_exp_1
|
||||||
|
1 1
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`,1 AS `My_exp_1`
|
||||||
|
select * from v1;
|
||||||
|
1 My_exp_1
|
||||||
|
1 1
|
||||||
|
drop view v1;
|
||||||
|
prepare stmt from "create view v1 (x) as select a from t1 where a > 1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `x` from `t1` where (`t1`.`a` > 1)
|
||||||
|
select * from v1;
|
||||||
|
x
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `x` from `t1` where (`t1`.`a` > 1)
|
||||||
|
select * from v1;
|
||||||
|
x
|
||||||
|
drop view v1;
|
||||||
|
prepare stmt from "create view v1 as select * from `t1` `b`";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `b`.`a` AS `a`,`b`.`b` AS `b` from `t1` `b`
|
||||||
|
select * from v1;
|
||||||
|
a b
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
View Create View
|
||||||
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `b`.`a` AS `a`,`b`.`b` AS `b` from `t1` `b`
|
||||||
|
select * from v1;
|
||||||
|
a b
|
||||||
|
drop view v1;
|
||||||
|
prepare stmt from "create view v1 (a,b,c) as select * from t1";
|
||||||
|
execute stmt;
|
||||||
|
ERROR HY000: View's SELECT and view's field list have different column counts
|
||||||
|
execute stmt;
|
||||||
|
ERROR HY000: View's SELECT and view's field list have different column counts
|
||||||
|
deallocate prepare stmt;
|
||||||
|
drop table t1;
|
||||||
|
create temporary table t1 (a int, b int);
|
||||||
|
prepare stmt from "create view v1 as select * from t1";
|
||||||
|
execute stmt;
|
||||||
|
ERROR HY000: View's SELECT refers to a temporary table 't1'
|
||||||
|
execute stmt;
|
||||||
|
ERROR HY000: View's SELECT refers to a temporary table 't1'
|
||||||
|
deallocate prepare stmt;
|
||||||
|
drop table t1;
|
||||||
|
prepare stmt from "create view v1 as select * from t1";
|
||||||
|
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||||
|
prepare stmt from "create view v1 as select * from `t1` `b`";
|
||||||
|
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||||
End of 5.0 tests.
|
End of 5.0 tests.
|
||||||
|
@ -3618,4 +3618,23 @@ ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default val
|
|||||||
set @@sql_mode=@old_mode;
|
set @@sql_mode=@old_mode;
|
||||||
drop view v1;
|
drop view v1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
End of 5.0 tests.
|
# -----------------------------------------------------------------
|
||||||
|
# -- Bug#34337: Server crash when Altering a view using a table name.
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1(c1 INT);
|
||||||
|
|
||||||
|
SELECT * FROM t1;
|
||||||
|
c1
|
||||||
|
ALTER ALGORITHM=TEMPTABLE SQL SECURITY INVOKER VIEW t1 (c2) AS SELECT (1);
|
||||||
|
ERROR HY000: 'test.t1' is not VIEW
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# -- End of test case for Bug#34337.
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
# -- End of 5.0 tests.
|
||||||
|
# -----------------------------------------------------------------
|
||||||
|
@ -467,6 +467,7 @@ use test;
|
|||||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
|
REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
|
||||||
drop database mysqltest;
|
drop database mysqltest;
|
||||||
drop view if exists v1;
|
drop view if exists v1;
|
||||||
|
drop table if exists t1;
|
||||||
create table t1 as select * from mysql.user where user='';
|
create table t1 as select * from mysql.user where user='';
|
||||||
delete from mysql.user where user='';
|
delete from mysql.user where user='';
|
||||||
flush privileges;
|
flush privileges;
|
||||||
|
@ -1824,4 +1824,127 @@ select * from t1 where a = @a and b = @b;
|
|||||||
deallocate prepare stmt;
|
deallocate prepare stmt;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#32890 Crash after repeated create and drop of tables and views
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop view if exists v1;
|
||||||
|
drop table if exists t1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
create table t1 (a int, b int);
|
||||||
|
insert into t1 values (1,1), (2,2), (3,3);
|
||||||
|
insert into t1 values (3,1), (1,2), (2,3);
|
||||||
|
|
||||||
|
prepare stmt from "create view v1 as select * from t1";
|
||||||
|
execute stmt;
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int, b int);
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
drop view v1;
|
||||||
|
|
||||||
|
prepare stmt from "create view v1 (c,d) as select a,b from t1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
|
||||||
|
prepare stmt from "create view v1 (c) as select b+1 from t1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
|
||||||
|
prepare stmt from "create view v1 (c,d,e,f) as select a,b,a in (select a+2 from t1), a = all (select a from t1) from t1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
|
||||||
|
prepare stmt from "create or replace view v1 as select 1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
|
||||||
|
prepare stmt from "create view v1 as select 1, 1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
|
||||||
|
prepare stmt from "create view v1 (x) as select a from t1 where a > 1";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
|
||||||
|
prepare stmt from "create view v1 as select * from `t1` `b`";
|
||||||
|
execute stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
show create view v1;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
|
||||||
|
prepare stmt from "create view v1 (a,b,c) as select * from t1";
|
||||||
|
--error ER_VIEW_WRONG_LIST
|
||||||
|
execute stmt;
|
||||||
|
--error ER_VIEW_WRONG_LIST
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
|
||||||
|
drop table t1;
|
||||||
|
create temporary table t1 (a int, b int);
|
||||||
|
|
||||||
|
prepare stmt from "create view v1 as select * from t1";
|
||||||
|
--error ER_VIEW_SELECT_TMPTABLE
|
||||||
|
execute stmt;
|
||||||
|
--error ER_VIEW_SELECT_TMPTABLE
|
||||||
|
execute stmt;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
prepare stmt from "create view v1 as select * from t1";
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
|
prepare stmt from "create view v1 as select * from `t1` `b`";
|
||||||
|
|
||||||
--echo End of 5.0 tests.
|
--echo End of 5.0 tests.
|
||||||
|
@ -3470,5 +3470,39 @@ insert into v1 values(1);
|
|||||||
set @@sql_mode=@old_mode;
|
set @@sql_mode=@old_mode;
|
||||||
drop view v1;
|
drop view v1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
--echo End of 5.0 tests.
|
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
--echo # -----------------------------------------------------------------
|
||||||
|
--echo # -- Bug#34337: Server crash when Altering a view using a table name.
|
||||||
|
--echo # -----------------------------------------------------------------
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE TABLE t1(c1 INT);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
--error ER_WRONG_OBJECT
|
||||||
|
ALTER ALGORITHM=TEMPTABLE SQL SECURITY INVOKER VIEW t1 (c2) AS SELECT (1);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
--echo # -- End of test case for Bug#34337.
|
||||||
|
--echo
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
--echo # -----------------------------------------------------------------
|
||||||
|
--echo # -- End of 5.0 tests.
|
||||||
|
--echo # -----------------------------------------------------------------
|
||||||
|
@ -608,6 +608,7 @@ drop database mysqltest;
|
|||||||
#
|
#
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
drop view if exists v1;
|
drop view if exists v1;
|
||||||
|
drop table if exists t1;
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
# Backup anonymous users and remove them. (They get in the way of
|
# Backup anonymous users and remove them. (They get in the way of
|
||||||
|
43
sql/item.h
43
sql/item.h
@ -879,6 +879,23 @@ public:
|
|||||||
class sp_head;
|
class sp_head;
|
||||||
|
|
||||||
|
|
||||||
|
class Item_basic_constant :public Item
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* to prevent drop fixed flag (no need parent cleanup call) */
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Restore the original field name as it might not have been allocated
|
||||||
|
in the statement memory. If the name is auto generated, it must be
|
||||||
|
done again between subsequent executions of a prepared statement.
|
||||||
|
*/
|
||||||
|
if (orig_name)
|
||||||
|
name= orig_name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
The class is a base class for representation of stored routine variables in
|
The class is a base class for representation of stored routine variables in
|
||||||
the Item-hierarchy. There are the following kinds of SP-vars:
|
the Item-hierarchy. There are the following kinds of SP-vars:
|
||||||
@ -1161,7 +1178,7 @@ bool agg_item_charsets(DTCollation &c, const char *name,
|
|||||||
Item **items, uint nitems, uint flags, int item_sep);
|
Item **items, uint nitems, uint flags, int item_sep);
|
||||||
|
|
||||||
|
|
||||||
class Item_num: public Item
|
class Item_num: public Item_basic_constant
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_num() {} /* Remove gcc warning */
|
Item_num() {} /* Remove gcc warning */
|
||||||
@ -1352,7 +1369,7 @@ public:
|
|||||||
friend class st_select_lex_unit;
|
friend class st_select_lex_unit;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_null :public Item
|
class Item_null :public Item_basic_constant
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_null(char *name_par=0)
|
Item_null(char *name_par=0)
|
||||||
@ -1374,8 +1391,6 @@ public:
|
|||||||
bool send(Protocol *protocol, String *str);
|
bool send(Protocol *protocol, String *str);
|
||||||
enum Item_result result_type () const { return STRING_RESULT; }
|
enum Item_result result_type () const { return STRING_RESULT; }
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
|
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
|
||||||
/* to prevent drop fixed flag (no need parent cleanup call) */
|
|
||||||
void cleanup() {}
|
|
||||||
bool basic_const_item() const { return 1; }
|
bool basic_const_item() const { return 1; }
|
||||||
Item *clone_item() { return new Item_null(name); }
|
Item *clone_item() { return new Item_null(name); }
|
||||||
bool is_null() { return 1; }
|
bool is_null() { return 1; }
|
||||||
@ -1567,8 +1582,6 @@ public:
|
|||||||
int save_in_field(Field *field, bool no_conversions);
|
int save_in_field(Field *field, bool no_conversions);
|
||||||
bool basic_const_item() const { return 1; }
|
bool basic_const_item() const { return 1; }
|
||||||
Item *clone_item() { return new Item_int(name,value,max_length); }
|
Item *clone_item() { return new Item_int(name,value,max_length); }
|
||||||
// to prevent drop fixed flag (no need parent cleanup call)
|
|
||||||
void cleanup() {}
|
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
Item_num *neg() { value= -value; return this; }
|
Item_num *neg() { value= -value; return this; }
|
||||||
uint decimal_precision() const
|
uint decimal_precision() const
|
||||||
@ -1621,8 +1634,6 @@ public:
|
|||||||
{
|
{
|
||||||
return new Item_decimal(name, &decimal_value, decimals, max_length);
|
return new Item_decimal(name, &decimal_value, decimals, max_length);
|
||||||
}
|
}
|
||||||
// to prevent drop fixed flag (no need parent cleanup call)
|
|
||||||
void cleanup() {}
|
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
Item_num *neg()
|
Item_num *neg()
|
||||||
{
|
{
|
||||||
@ -1673,8 +1684,6 @@ public:
|
|||||||
String *val_str(String*);
|
String *val_str(String*);
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
bool basic_const_item() const { return 1; }
|
bool basic_const_item() const { return 1; }
|
||||||
// to prevent drop fixed flag (no need parent cleanup call)
|
|
||||||
void cleanup() {}
|
|
||||||
Item *clone_item()
|
Item *clone_item()
|
||||||
{ return new Item_float(name, value, decimals, max_length); }
|
{ return new Item_float(name, value, decimals, max_length); }
|
||||||
Item_num *neg() { value= -value; return this; }
|
Item_num *neg() { value= -value; return this; }
|
||||||
@ -1696,7 +1705,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_string :public Item
|
class Item_string :public Item_basic_constant
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_string(const char *str,uint length,
|
Item_string(const char *str,uint length,
|
||||||
@ -1780,8 +1789,6 @@ public:
|
|||||||
max_length= str_value.numchars() * collation.collation->mbmaxlen;
|
max_length= str_value.numchars() * collation.collation->mbmaxlen;
|
||||||
}
|
}
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
// to prevent drop fixed flag (no need parent cleanup call)
|
|
||||||
void cleanup() {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1839,10 +1846,10 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_hex_string: public Item
|
class Item_hex_string: public Item_basic_constant
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_hex_string(): Item() {}
|
Item_hex_string() {}
|
||||||
Item_hex_string(const char *str,uint str_length);
|
Item_hex_string(const char *str,uint str_length);
|
||||||
enum Type type() const { return VARBIN_ITEM; }
|
enum Type type() const { return VARBIN_ITEM; }
|
||||||
double val_real()
|
double val_real()
|
||||||
@ -1858,8 +1865,6 @@ public:
|
|||||||
enum Item_result result_type () const { return STRING_RESULT; }
|
enum Item_result result_type () const { return STRING_RESULT; }
|
||||||
enum Item_result cast_to_int_type() const { return INT_RESULT; }
|
enum Item_result cast_to_int_type() const { return INT_RESULT; }
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
||||||
// to prevent drop fixed flag (no need parent cleanup call)
|
|
||||||
void cleanup() {}
|
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
bool eq(const Item *item, bool binary_cmp) const;
|
bool eq(const Item *item, bool binary_cmp) const;
|
||||||
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
|
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
|
||||||
@ -2449,7 +2454,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_cache: public Item
|
class Item_cache: public Item_basic_constant
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
Item *example;
|
Item *example;
|
||||||
@ -2486,8 +2491,6 @@ public:
|
|||||||
static Item_cache* get_cache(const Item *item);
|
static Item_cache* get_cache(const Item *item);
|
||||||
table_map used_tables() const { return used_table_map; }
|
table_map used_tables() const { return used_table_map; }
|
||||||
virtual void keep_array() {}
|
virtual void keep_array() {}
|
||||||
// to prevent drop fixed flag (no need parent cleanup call)
|
|
||||||
void cleanup() {}
|
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
bool eq_def(Field *field)
|
bool eq_def(Field *field)
|
||||||
{
|
{
|
||||||
|
@ -88,6 +88,7 @@ class Materialized_cursor: public Server_side_cursor
|
|||||||
public:
|
public:
|
||||||
Materialized_cursor(select_result *result, TABLE *table);
|
Materialized_cursor(select_result *result, TABLE *table);
|
||||||
|
|
||||||
|
int fill_item_list(THD *thd, List<Item> &send_fields);
|
||||||
virtual bool is_open() const { return table != 0; }
|
virtual bool is_open() const { return table != 0; }
|
||||||
virtual int open(JOIN *join __attribute__((unused)));
|
virtual int open(JOIN *join __attribute__((unused)));
|
||||||
virtual void fetch(ulong num_rows);
|
virtual void fetch(ulong num_rows);
|
||||||
@ -109,6 +110,7 @@ class Select_materialize: public select_union
|
|||||||
{
|
{
|
||||||
select_result *result; /* the result object of the caller (PS or SP) */
|
select_result *result; /* the result object of the caller (PS or SP) */
|
||||||
public:
|
public:
|
||||||
|
Materialized_cursor *materialized_cursor;
|
||||||
Select_materialize(select_result *result_arg) :result(result_arg) {}
|
Select_materialize(select_result *result_arg) :result(result_arg) {}
|
||||||
virtual bool send_fields(List<Item> &list, uint flags);
|
virtual bool send_fields(List<Item> &list, uint flags);
|
||||||
};
|
};
|
||||||
@ -152,7 +154,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
|
|||||||
|
|
||||||
if (! (sensitive_cursor= new (thd->mem_root) Sensitive_cursor(thd, result)))
|
if (! (sensitive_cursor= new (thd->mem_root) Sensitive_cursor(thd, result)))
|
||||||
{
|
{
|
||||||
delete result;
|
delete result_materialize;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,13 +176,13 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
|
|||||||
/*
|
/*
|
||||||
Possible options here:
|
Possible options here:
|
||||||
- a sensitive cursor is open. In this case rc is 0 and
|
- a sensitive cursor is open. In this case rc is 0 and
|
||||||
result_materialize->table is NULL, or
|
result_materialize->materialized_cursor is NULL, or
|
||||||
- a materialized cursor is open. In this case rc is 0 and
|
- a materialized cursor is open. In this case rc is 0 and
|
||||||
result_materialize->table is not NULL
|
result_materialize->materialized is not NULL
|
||||||
- an error occured during materializaton.
|
- an error occurred during materialization.
|
||||||
result_materialize->table is not NULL, but rc != 0
|
result_materialize->materialized_cursor is not NULL, but rc != 0
|
||||||
- successful completion of mysql_execute_command without
|
- successful completion of mysql_execute_command without
|
||||||
a cursor: rc is 0, result_materialize->table is NULL,
|
a cursor: rc is 0, result_materialize->materialized_cursor is NULL,
|
||||||
sensitive_cursor is not open.
|
sensitive_cursor is not open.
|
||||||
This is possible if some command writes directly to the
|
This is possible if some command writes directly to the
|
||||||
network, bypassing select_result mechanism. An example of
|
network, bypassing select_result mechanism. An example of
|
||||||
@ -191,7 +193,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
|
|||||||
|
|
||||||
if (sensitive_cursor->is_open())
|
if (sensitive_cursor->is_open())
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(!result_materialize->table);
|
DBUG_ASSERT(!result_materialize->materialized_cursor);
|
||||||
/*
|
/*
|
||||||
It's safer if we grab THD state after mysql_execute_command
|
It's safer if we grab THD state after mysql_execute_command
|
||||||
is finished and not in Sensitive_cursor::open(), because
|
is finished and not in Sensitive_cursor::open(), because
|
||||||
@ -202,18 +204,10 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
|
|||||||
*pcursor= sensitive_cursor;
|
*pcursor= sensitive_cursor;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
else if (result_materialize->table)
|
else if (result_materialize->materialized_cursor)
|
||||||
{
|
{
|
||||||
Materialized_cursor *materialized_cursor;
|
Materialized_cursor *materialized_cursor=
|
||||||
TABLE *table= result_materialize->table;
|
result_materialize->materialized_cursor;
|
||||||
MEM_ROOT *mem_root= &table->mem_root;
|
|
||||||
|
|
||||||
if (!(materialized_cursor= new (mem_root)
|
|
||||||
Materialized_cursor(result, table)))
|
|
||||||
{
|
|
||||||
rc= 1;
|
|
||||||
goto err_open;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rc= materialized_cursor->open(0)))
|
if ((rc= materialized_cursor->open(0)))
|
||||||
{
|
{
|
||||||
@ -229,8 +223,6 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
|
|||||||
err_open:
|
err_open:
|
||||||
DBUG_ASSERT(! (sensitive_cursor && sensitive_cursor->is_open()));
|
DBUG_ASSERT(! (sensitive_cursor && sensitive_cursor->is_open()));
|
||||||
delete sensitive_cursor;
|
delete sensitive_cursor;
|
||||||
if (result_materialize->table)
|
|
||||||
free_tmp_table(thd, result_materialize->table);
|
|
||||||
end:
|
end:
|
||||||
delete result_materialize;
|
delete result_materialize;
|
||||||
return rc;
|
return rc;
|
||||||
@ -544,6 +536,51 @@ Materialized_cursor::Materialized_cursor(select_result *result_arg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Preserve the original metadata that would be sent to the client.
|
||||||
|
|
||||||
|
@param thd Thread identifier.
|
||||||
|
@param send_fields List of fields that would be sent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Materialized_cursor::fill_item_list(THD *thd, List<Item> &send_fields)
|
||||||
|
{
|
||||||
|
Query_arena backup_arena;
|
||||||
|
int rc;
|
||||||
|
List_iterator_fast<Item> it_org(send_fields);
|
||||||
|
List_iterator_fast<Item> it_dst(item_list);
|
||||||
|
Item *item_org;
|
||||||
|
Item *item_dst;
|
||||||
|
|
||||||
|
thd->set_n_backup_active_arena(this, &backup_arena);
|
||||||
|
|
||||||
|
if ((rc= table->fill_item_list(&item_list)))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
DBUG_ASSERT(send_fields.elements == item_list.elements);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Unless we preserve the original metadata, it will be lost,
|
||||||
|
since new fields describe columns of the temporary table.
|
||||||
|
Allocate a copy of the name for safety only. Currently
|
||||||
|
items with original names are always kept in memory,
|
||||||
|
but in case this changes a memory leak may be hard to notice.
|
||||||
|
*/
|
||||||
|
while ((item_dst= it_dst++, item_org= it_org++))
|
||||||
|
{
|
||||||
|
Send_field send_field;
|
||||||
|
Item_ident *ident= static_cast<Item_ident *>(item_dst);
|
||||||
|
item_org->make_field(&send_field);
|
||||||
|
|
||||||
|
ident->db_name= thd->strdup(send_field.db_name);
|
||||||
|
ident->table_name= thd->strdup(send_field.table_name);
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
thd->restore_active_arena(this, &backup_arena);
|
||||||
|
/* Check for thd->is_error() in case of OOM */
|
||||||
|
return rc || thd->net.report_error;
|
||||||
|
}
|
||||||
|
|
||||||
int Materialized_cursor::open(JOIN *join __attribute__((unused)))
|
int Materialized_cursor::open(JOIN *join __attribute__((unused)))
|
||||||
{
|
{
|
||||||
THD *thd= fake_unit.thd;
|
THD *thd= fake_unit.thd;
|
||||||
@ -552,8 +589,7 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused)))
|
|||||||
|
|
||||||
thd->set_n_backup_active_arena(this, &backup_arena);
|
thd->set_n_backup_active_arena(this, &backup_arena);
|
||||||
/* Create a list of fields and start sequential scan */
|
/* Create a list of fields and start sequential scan */
|
||||||
rc= (table->fill_item_list(&item_list) ||
|
rc= (result->prepare(item_list, &fake_unit) ||
|
||||||
result->prepare(item_list, &fake_unit) ||
|
|
||||||
table->file->ha_rnd_init(TRUE));
|
table->file->ha_rnd_init(TRUE));
|
||||||
thd->restore_active_arena(this, &backup_arena);
|
thd->restore_active_arena(this, &backup_arena);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
@ -664,6 +700,24 @@ bool Select_materialize::send_fields(List<Item> &list, uint flags)
|
|||||||
if (create_result_table(unit->thd, unit->get_unit_column_types(),
|
if (create_result_table(unit->thd, unit->get_unit_column_types(),
|
||||||
FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, ""))
|
FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, ""))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
materialized_cursor= new (&table->mem_root)
|
||||||
|
Materialized_cursor(result, table);
|
||||||
|
|
||||||
|
if (! materialized_cursor)
|
||||||
|
{
|
||||||
|
free_tmp_table(table->in_use, table);
|
||||||
|
table= 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (materialized_cursor->fill_item_list(unit->thd, list))
|
||||||
|
{
|
||||||
|
delete materialized_cursor;
|
||||||
|
table= 0;
|
||||||
|
materialized_cursor= 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1512,6 +1512,44 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Validate and prepare for execution CREATE VIEW statement
|
||||||
|
|
||||||
|
@param stmt prepared statement
|
||||||
|
|
||||||
|
@note This function handles create view commands.
|
||||||
|
|
||||||
|
@retval FALSE Operation was a success.
|
||||||
|
@retval TRUE An error occured.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool mysql_test_create_view(Prepared_statement *stmt)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("mysql_test_create_view");
|
||||||
|
THD *thd= stmt->thd;
|
||||||
|
LEX *lex= stmt->lex;
|
||||||
|
bool res= TRUE;
|
||||||
|
/* Skip first table, which is the view we are creating */
|
||||||
|
bool link_to_local;
|
||||||
|
TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
|
||||||
|
TABLE_LIST *tables= lex->query_tables;
|
||||||
|
|
||||||
|
if (create_view_precheck(thd, tables, view, lex->create_view_mode))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (open_normal_and_derived_tables(thd, tables, 0))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
lex->view_prepare_mode= 1;
|
||||||
|
res= select_like_stmt_test(stmt, 0, 0);
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* put view back for PS rexecuting */
|
||||||
|
lex->link_first_table_back(view, link_to_local);
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Validate and prepare for execution a multi update statement.
|
Validate and prepare for execution a multi update statement.
|
||||||
|
|
||||||
@ -1730,6 +1768,7 @@ static bool check_prepared_statement(Prepared_statement *stmt,
|
|||||||
my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0));
|
my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
res= mysql_test_create_view(stmt);
|
||||||
break;
|
break;
|
||||||
case SQLCOM_DO:
|
case SQLCOM_DO:
|
||||||
res= mysql_test_do_fields(stmt, tables, lex->insert_list);
|
res= mysql_test_do_fields(stmt, tables, lex->insert_list);
|
||||||
|
270
sql/sql_view.cc
270
sql/sql_view.cc
@ -182,10 +182,33 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
|
|||||||
TABLE_LIST decoy;
|
TABLE_LIST decoy;
|
||||||
|
|
||||||
memcpy (&decoy, view, sizeof (TABLE_LIST));
|
memcpy (&decoy, view, sizeof (TABLE_LIST));
|
||||||
if (!open_table(thd, &decoy, thd->mem_root, ¬_used, OPEN_VIEW_NO_PARSE) &&
|
|
||||||
!decoy.view)
|
/*
|
||||||
|
Let's reset decoy.view before calling open_table(): when we start
|
||||||
|
supporting ALTER VIEW in PS/SP that may save us from a crash.
|
||||||
|
*/
|
||||||
|
|
||||||
|
decoy.view= NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
open_table() will return NULL if 'decoy' is idenitifying a view *and*
|
||||||
|
there is no TABLE object for that view in the table cache. However,
|
||||||
|
decoy.view will be set to 1.
|
||||||
|
|
||||||
|
If there is a TABLE-instance for the oject identified by 'decoy',
|
||||||
|
open_table() will return that instance no matter if it is a table or
|
||||||
|
a view.
|
||||||
|
|
||||||
|
Thus, there is no need to check for the return value of open_table(),
|
||||||
|
since the return value itself does not mean anything.
|
||||||
|
*/
|
||||||
|
|
||||||
|
open_table(thd, &decoy, thd->mem_root, ¬_used, OPEN_VIEW_NO_PARSE);
|
||||||
|
|
||||||
|
if (!decoy.view)
|
||||||
{
|
{
|
||||||
/* It's a table */
|
/* It's a table. */
|
||||||
|
my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,6 +227,143 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CREATE VIEW privileges pre-check.
|
||||||
|
|
||||||
|
@param thd thread handler
|
||||||
|
@param tables tables used in the view
|
||||||
|
@param views views to create
|
||||||
|
@param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
|
||||||
|
|
||||||
|
@retval FALSE Operation was a success.
|
||||||
|
@retval TRUE An error occured.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
|
||||||
|
enum_view_create_mode mode)
|
||||||
|
{
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
/* first table in list is target VIEW name => cut off it */
|
||||||
|
TABLE_LIST *tbl;
|
||||||
|
SELECT_LEX *select_lex= &lex->select_lex;
|
||||||
|
SELECT_LEX *sl;
|
||||||
|
bool res= TRUE;
|
||||||
|
DBUG_ENTER("create_view_precheck");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Privilege check for view creation:
|
||||||
|
- user has CREATE VIEW privilege on view table
|
||||||
|
- user has DROP privilege in case of ALTER VIEW or CREATE OR REPLACE
|
||||||
|
VIEW
|
||||||
|
- user has some (SELECT/UPDATE/INSERT/DELETE) privileges on columns of
|
||||||
|
underlying tables used on top of SELECT list (because it can be
|
||||||
|
(theoretically) updated, so it is enough to have UPDATE privilege on
|
||||||
|
them, for example)
|
||||||
|
- user has SELECT privilege on columns used in expressions of VIEW select
|
||||||
|
- for columns of underly tables used on top of SELECT list also will be
|
||||||
|
checked that we have not more privileges on correspondent column of view
|
||||||
|
table (i.e. user will not get some privileges by view creation)
|
||||||
|
*/
|
||||||
|
if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege,
|
||||||
|
0, 0, is_schema_db(view->db)) ||
|
||||||
|
grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) ||
|
||||||
|
(mode != VIEW_CREATE_NEW &&
|
||||||
|
(check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
|
||||||
|
0, 0, is_schema_db(view->db)) ||
|
||||||
|
grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0))))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
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 privileges on this table, more strict check
|
||||||
|
will be done on column level after preparation,
|
||||||
|
*/
|
||||||
|
if (check_some_access(thd, VIEW_ANY_ACL, tbl))
|
||||||
|
{
|
||||||
|
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
|
||||||
|
"ANY", thd->security_ctx->priv_user,
|
||||||
|
thd->security_ctx->priv_host, tbl->table_name);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Mark this table as a table which will be checked after the prepare
|
||||||
|
phase
|
||||||
|
*/
|
||||||
|
tbl->table_in_first_from_clause= 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We need to check only SELECT_ACL for all normal fields, fields for
|
||||||
|
which we need "any" (SELECT/UPDATE/INSERT/DELETE) privilege will be
|
||||||
|
checked later
|
||||||
|
*/
|
||||||
|
tbl->grant.want_privilege= SELECT_ACL;
|
||||||
|
/*
|
||||||
|
Make sure that all rights are loaded to the TABLE::grant field.
|
||||||
|
|
||||||
|
tbl->table_name will be correct name of table because VIEWs are
|
||||||
|
not opened yet.
|
||||||
|
*/
|
||||||
|
fill_effective_table_privileges(thd, &tbl->grant, tbl->db,
|
||||||
|
tbl->table_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&lex->select_lex != lex->all_selects_list)
|
||||||
|
{
|
||||||
|
/* check tables of subqueries */
|
||||||
|
for (tbl= tables; tbl; tbl= tbl->next_global)
|
||||||
|
{
|
||||||
|
if (!tbl->table_in_first_from_clause)
|
||||||
|
{
|
||||||
|
if (check_access(thd, SELECT_ACL, tbl->db,
|
||||||
|
&tbl->grant.privilege, 0, 0, test(tbl->schema_table)) ||
|
||||||
|
grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Mark fields for special privilege check ("any" privilege)
|
||||||
|
*/
|
||||||
|
for (sl= select_lex; sl; sl= sl->next_select())
|
||||||
|
{
|
||||||
|
List_iterator_fast<Item> it(sl->item_list);
|
||||||
|
Item *item;
|
||||||
|
while ((item= it++))
|
||||||
|
{
|
||||||
|
Item_field *field;
|
||||||
|
if ((field= item->filed_for_view_update()))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
any_privileges may be reset later by the Item_field::set_field
|
||||||
|
method in case of a system temporary table.
|
||||||
|
*/
|
||||||
|
field->any_privileges= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res= FALSE;
|
||||||
|
|
||||||
|
err:
|
||||||
|
DBUG_RETURN(res || thd->net.report_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
|
||||||
|
enum_view_create_mode mode)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Creating/altering VIEW procedure
|
@brief Creating/altering VIEW procedure
|
||||||
@ -302,109 +462,11 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Privilege check for view creation:
|
|
||||||
- user has CREATE VIEW privilege on view table
|
|
||||||
- user has DROP privilege in case of ALTER VIEW or CREATE OR REPLACE
|
|
||||||
VIEW
|
|
||||||
- user has some (SELECT/UPDATE/INSERT/DELETE) privileges on columns of
|
|
||||||
underlying tables used on top of SELECT list (because it can be
|
|
||||||
(theoretically) updated, so it is enough to have UPDATE privilege on
|
|
||||||
them, for example)
|
|
||||||
- user has SELECT privilege on columns used in expressions of VIEW select
|
|
||||||
- for columns of underly tables used on top of SELECT list also will be
|
|
||||||
checked that we have not more privileges on correspondent column of view
|
|
||||||
table (i.e. user will not get some privileges by view creation)
|
|
||||||
*/
|
|
||||||
if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege,
|
|
||||||
0, 0, is_schema_db(view->db)) ||
|
|
||||||
grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) ||
|
|
||||||
(mode != VIEW_CREATE_NEW &&
|
|
||||||
(check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
|
|
||||||
0, 0, is_schema_db(view->db)) ||
|
|
||||||
grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0))))
|
|
||||||
{
|
|
||||||
res= TRUE;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
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 privileges on this table, more strict check
|
|
||||||
will be done on column level after preparation,
|
|
||||||
*/
|
|
||||||
if (check_some_access(thd, VIEW_ANY_ACL, tbl))
|
|
||||||
{
|
|
||||||
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
|
|
||||||
"ANY", thd->security_ctx->priv_user,
|
|
||||||
thd->security_ctx->priv_host, tbl->table_name);
|
|
||||||
res= TRUE;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Mark this table as a table which will be checked after the prepare
|
|
||||||
phase
|
|
||||||
*/
|
|
||||||
tbl->table_in_first_from_clause= 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
We need to check only SELECT_ACL for all normal fields, fields for
|
|
||||||
which we need "any" (SELECT/UPDATE/INSERT/DELETE) privilege will be
|
|
||||||
checked later
|
|
||||||
*/
|
|
||||||
tbl->grant.want_privilege= SELECT_ACL;
|
|
||||||
/*
|
|
||||||
Make sure that all rights are loaded to the TABLE::grant field.
|
|
||||||
|
|
||||||
tbl->table_name will be correct name of table because VIEWs are
|
|
||||||
not opened yet.
|
|
||||||
*/
|
|
||||||
fill_effective_table_privileges(thd, &tbl->grant, tbl->db,
|
|
||||||
tbl->table_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (&lex->select_lex != lex->all_selects_list)
|
|
||||||
{
|
|
||||||
/* check tables of subqueries */
|
|
||||||
for (tbl= tables; tbl; tbl= tbl->next_global)
|
|
||||||
{
|
|
||||||
if (!tbl->table_in_first_from_clause)
|
|
||||||
{
|
|
||||||
if (check_access(thd, SELECT_ACL, tbl->db,
|
|
||||||
&tbl->grant.privilege, 0, 0, test(tbl->schema_table)) ||
|
|
||||||
grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0))
|
|
||||||
{
|
|
||||||
res= TRUE;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Mark fields for special privilege check ("any" privilege)
|
|
||||||
*/
|
|
||||||
for (sl= select_lex; sl; sl= sl->next_select())
|
|
||||||
{
|
|
||||||
List_iterator_fast<Item> it(sl->item_list);
|
|
||||||
Item *item;
|
|
||||||
while ((item= it++))
|
|
||||||
{
|
|
||||||
Item_field *field;
|
|
||||||
if ((field= item->filed_for_view_update()))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
any_privileges may be reset later by the Item_field::set_field
|
|
||||||
method in case of a system temporary table.
|
|
||||||
*/
|
|
||||||
field->any_privileges= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if ((res= create_view_precheck(thd, tables, view, mode)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (open_and_lock_tables(thd, tables))
|
if (open_and_lock_tables(thd, tables))
|
||||||
{
|
{
|
||||||
res= TRUE;
|
res= TRUE;
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
|
||||||
|
enum_view_create_mode mode);
|
||||||
|
|
||||||
bool mysql_create_view(THD *thd, TABLE_LIST *view,
|
bool mysql_create_view(THD *thd, TABLE_LIST *view,
|
||||||
enum_view_create_mode mode);
|
enum_view_create_mode mode);
|
||||||
|
|
||||||
|
@ -8702,8 +8702,8 @@ static void test_sqlmode()
|
|||||||
strmov(c1, "My"); strmov(c2, "SQL");
|
strmov(c1, "My"); strmov(c2, "SQL");
|
||||||
rc= mysql_stmt_execute(stmt);
|
rc= mysql_stmt_execute(stmt);
|
||||||
check_execute(stmt, rc);
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
mysql_stmt_close(stmt);
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
verify_col_data("test_piping", "name", "MySQL");
|
verify_col_data("test_piping", "name", "MySQL");
|
||||||
|
|
||||||
rc= mysql_query(mysql, "DELETE FROM test_piping");
|
rc= mysql_query(mysql, "DELETE FROM test_piping");
|
||||||
@ -12993,7 +12993,7 @@ from t2);");
|
|||||||
static void test_bug8378()
|
static void test_bug8378()
|
||||||
{
|
{
|
||||||
#if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY)
|
#if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY)
|
||||||
MYSQL *old_mysql=mysql;
|
MYSQL *lmysql;
|
||||||
char out[9]; /* strlen(TEST_BUG8378)*2+1 */
|
char out[9]; /* strlen(TEST_BUG8378)*2+1 */
|
||||||
char buf[256];
|
char buf[256];
|
||||||
int len, rc;
|
int len, rc;
|
||||||
@ -13002,17 +13002,17 @@ static void test_bug8378()
|
|||||||
|
|
||||||
if (!opt_silent)
|
if (!opt_silent)
|
||||||
fprintf(stdout, "\n Establishing a test connection ...");
|
fprintf(stdout, "\n Establishing a test connection ...");
|
||||||
if (!(mysql= mysql_init(NULL)))
|
if (!(lmysql= mysql_init(NULL)))
|
||||||
{
|
{
|
||||||
myerror("mysql_init() failed");
|
myerror("mysql_init() failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "gbk"))
|
if (mysql_options(lmysql, MYSQL_SET_CHARSET_NAME, "gbk"))
|
||||||
{
|
{
|
||||||
myerror("mysql_options() failed");
|
myerror("mysql_options() failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (!(mysql_real_connect(mysql, opt_host, opt_user,
|
if (!(mysql_real_connect(lmysql, opt_host, opt_user,
|
||||||
opt_password, current_db, opt_port,
|
opt_password, current_db, opt_port,
|
||||||
opt_unix_socket, 0)))
|
opt_unix_socket, 0)))
|
||||||
{
|
{
|
||||||
@ -13022,19 +13022,17 @@ static void test_bug8378()
|
|||||||
if (!opt_silent)
|
if (!opt_silent)
|
||||||
fprintf(stdout, " OK");
|
fprintf(stdout, " OK");
|
||||||
|
|
||||||
len= mysql_real_escape_string(mysql, out, TEST_BUG8378_IN, 4);
|
len= mysql_real_escape_string(lmysql, out, TEST_BUG8378_IN, 4);
|
||||||
|
|
||||||
/* No escaping should have actually happened. */
|
/* No escaping should have actually happened. */
|
||||||
DIE_UNLESS(memcmp(out, TEST_BUG8378_OUT, len) == 0);
|
DIE_UNLESS(memcmp(out, TEST_BUG8378_OUT, len) == 0);
|
||||||
|
|
||||||
sprintf(buf, "SELECT '%s'", out);
|
sprintf(buf, "SELECT '%s'", out);
|
||||||
|
|
||||||
rc=mysql_real_query(mysql, buf, strlen(buf));
|
rc=mysql_real_query(lmysql, buf, strlen(buf));
|
||||||
myquery(rc);
|
myquery(rc);
|
||||||
|
|
||||||
mysql_close(mysql);
|
mysql_close(lmysql);
|
||||||
|
|
||||||
mysql=old_mysql;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14869,7 +14867,7 @@ static void test_opt_reconnect()
|
|||||||
if (mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true))
|
if (mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true))
|
||||||
{
|
{
|
||||||
myerror("mysql_options failed: unknown option MYSQL_OPT_RECONNECT\n");
|
myerror("mysql_options failed: unknown option MYSQL_OPT_RECONNECT\n");
|
||||||
exit(1);
|
DIE_UNLESS(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reconnect should be 1 */
|
/* reconnect should be 1 */
|
||||||
@ -14882,7 +14880,7 @@ static void test_opt_reconnect()
|
|||||||
opt_unix_socket, 0)))
|
opt_unix_socket, 0)))
|
||||||
{
|
{
|
||||||
myerror("connection failed");
|
myerror("connection failed");
|
||||||
exit(1);
|
DIE_UNLESS(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reconnect should still be 1 */
|
/* reconnect should still be 1 */
|
||||||
@ -14896,7 +14894,7 @@ static void test_opt_reconnect()
|
|||||||
if (!(lmysql= mysql_init(NULL)))
|
if (!(lmysql= mysql_init(NULL)))
|
||||||
{
|
{
|
||||||
myerror("mysql_init() failed");
|
myerror("mysql_init() failed");
|
||||||
exit(1);
|
DIE_UNLESS(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opt_silent)
|
if (!opt_silent)
|
||||||
@ -14908,7 +14906,7 @@ static void test_opt_reconnect()
|
|||||||
opt_unix_socket, 0)))
|
opt_unix_socket, 0)))
|
||||||
{
|
{
|
||||||
myerror("connection failed");
|
myerror("connection failed");
|
||||||
exit(1);
|
DIE_UNLESS(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reconnect should still be 0 */
|
/* reconnect should still be 0 */
|
||||||
@ -14926,32 +14924,32 @@ static void test_opt_reconnect()
|
|||||||
static void test_bug12744()
|
static void test_bug12744()
|
||||||
{
|
{
|
||||||
MYSQL_STMT *prep_stmt = NULL;
|
MYSQL_STMT *prep_stmt = NULL;
|
||||||
|
MYSQL *lmysql;
|
||||||
int rc;
|
int rc;
|
||||||
myheader("test_bug12744");
|
myheader("test_bug12744");
|
||||||
|
|
||||||
prep_stmt= mysql_stmt_init(mysql);
|
lmysql= mysql_init(NULL);
|
||||||
|
DIE_UNLESS(lmysql);
|
||||||
|
|
||||||
|
if (!mysql_real_connect(lmysql, opt_host, opt_user, opt_password,
|
||||||
|
current_db, opt_port, opt_unix_socket, 0))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to connect to the database\n");
|
||||||
|
DIE_UNLESS(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
prep_stmt= mysql_stmt_init(lmysql);
|
||||||
rc= mysql_stmt_prepare(prep_stmt, "SELECT 1", 8);
|
rc= mysql_stmt_prepare(prep_stmt, "SELECT 1", 8);
|
||||||
DIE_UNLESS(rc==0);
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
mysql_close(mysql);
|
mysql_close(lmysql);
|
||||||
|
|
||||||
if ((rc= mysql_stmt_execute(prep_stmt)))
|
rc= mysql_stmt_execute(prep_stmt);
|
||||||
{
|
DIE_UNLESS(rc);
|
||||||
if ((rc= mysql_stmt_reset(prep_stmt)))
|
rc= mysql_stmt_reset(prep_stmt);
|
||||||
printf("OK!\n");
|
DIE_UNLESS(rc);
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Error!");
|
|
||||||
DIE_UNLESS(1==0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, "expected error but no error occured\n");
|
|
||||||
DIE_UNLESS(1==0);
|
|
||||||
}
|
|
||||||
rc= mysql_stmt_close(prep_stmt);
|
rc= mysql_stmt_close(prep_stmt);
|
||||||
client_connect(0);
|
DIE_UNLESS(rc == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* EMBEDDED_LIBRARY */
|
#endif /* EMBEDDED_LIBRARY */
|
||||||
@ -15759,6 +15757,7 @@ static void test_bug24179()
|
|||||||
mysql_stmt_error(stmt));
|
mysql_stmt_error(stmt));
|
||||||
}
|
}
|
||||||
DIE_UNLESS(mysql_stmt_errno(stmt) == 1323);
|
DIE_UNLESS(mysql_stmt_errno(stmt) == 1323);
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -15801,6 +15800,7 @@ static void test_bug27876()
|
|||||||
myquery(rc);
|
myquery(rc);
|
||||||
result= mysql_store_result(mysql);
|
result= mysql_store_result(mysql);
|
||||||
mytest(result);
|
mytest(result);
|
||||||
|
mysql_free_result(result);
|
||||||
|
|
||||||
sprintf(query, "DROP FUNCTION IF EXISTS %s", utf8_func);
|
sprintf(query, "DROP FUNCTION IF EXISTS %s", utf8_func);
|
||||||
rc= mysql_query(mysql, query);
|
rc= mysql_query(mysql, query);
|
||||||
@ -15817,6 +15817,7 @@ static void test_bug27876()
|
|||||||
myquery(rc);
|
myquery(rc);
|
||||||
result= mysql_store_result(mysql);
|
result= mysql_store_result(mysql);
|
||||||
mytest(result);
|
mytest(result);
|
||||||
|
mysql_free_result(result);
|
||||||
|
|
||||||
sprintf(query, "DROP FUNCTION %s", utf8_func);
|
sprintf(query, "DROP FUNCTION %s", utf8_func);
|
||||||
rc= mysql_query(mysql, query);
|
rc= mysql_query(mysql, query);
|
||||||
@ -15965,6 +15966,7 @@ static void test_bug29948()
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bzero(&bind, sizeof(bind));
|
||||||
bind.buffer_type= MYSQL_TYPE_LONG;
|
bind.buffer_type= MYSQL_TYPE_LONG;
|
||||||
bind.buffer= (char *)&buf;
|
bind.buffer= (char *)&buf;
|
||||||
bind.is_null= &is_null;
|
bind.is_null= &is_null;
|
||||||
@ -16152,6 +16154,99 @@ static void test_bug31669()
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Bug#32265 Server returns different metadata if prepared statement is used
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void test_bug32265()
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
MYSQL_FIELD *field;
|
||||||
|
MYSQL_RES *metadata;
|
||||||
|
|
||||||
|
DBUG_ENTER("test_bug32265");
|
||||||
|
myheader("test_bug32265");
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "CREATE TABLE t1 (a INTEGER)");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "CREATE VIEW v1 AS SELECT * FROM t1");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
stmt= open_cursor("SELECT * FROM t1");
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
metadata= mysql_stmt_result_metadata(stmt);
|
||||||
|
field= mysql_fetch_field(metadata);
|
||||||
|
DIE_UNLESS(field);
|
||||||
|
DIE_UNLESS(strcmp(field->table, "t1") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->org_table, "t1") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
|
||||||
|
mysql_free_result(metadata);
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
stmt= open_cursor("SELECT a '' FROM t1 ``");
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
metadata= mysql_stmt_result_metadata(stmt);
|
||||||
|
field= mysql_fetch_field(metadata);
|
||||||
|
DIE_UNLESS(strcmp(field->table, "") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->org_table, "t1") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
|
||||||
|
mysql_free_result(metadata);
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
stmt= open_cursor("SELECT a '' FROM t1 ``");
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
metadata= mysql_stmt_result_metadata(stmt);
|
||||||
|
field= mysql_fetch_field(metadata);
|
||||||
|
DIE_UNLESS(strcmp(field->table, "") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->org_table, "t1") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
|
||||||
|
mysql_free_result(metadata);
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
stmt= open_cursor("SELECT * FROM v1");
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
metadata= mysql_stmt_result_metadata(stmt);
|
||||||
|
field= mysql_fetch_field(metadata);
|
||||||
|
DIE_UNLESS(strcmp(field->table, "v1") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->org_table, "t1") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
|
||||||
|
mysql_free_result(metadata);
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
stmt= open_cursor("SELECT * FROM v1 /* SIC */ GROUP BY 1");
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
metadata= mysql_stmt_result_metadata(stmt);
|
||||||
|
field= mysql_fetch_field(metadata);
|
||||||
|
DIE_UNLESS(strcmp(field->table, "v1") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->org_table, "t1") == 0);
|
||||||
|
DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
|
||||||
|
mysql_free_result(metadata);
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP VIEW v1");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE t1");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read and parse arguments and MySQL options from my.cnf
|
Read and parse arguments and MySQL options from my.cnf
|
||||||
*/
|
*/
|
||||||
@ -16446,6 +16541,7 @@ static struct my_tests_st my_tests[]= {
|
|||||||
{ "test_bug29948", test_bug29948 },
|
{ "test_bug29948", test_bug29948 },
|
||||||
{ "test_bug29306", test_bug29306 },
|
{ "test_bug29306", test_bug29306 },
|
||||||
{ "test_bug31669", test_bug31669 },
|
{ "test_bug31669", test_bug31669 },
|
||||||
|
{ "test_bug32265", test_bug32265 },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user