Commit c61667bc authored by anozdrin/alik@quad's avatar anozdrin/alik@quad

Merge quad.:/mnt/raid/alik/MySQL/devel/5.0

into  quad.:/mnt/raid/alik/MySQL/devel/5.0-rt-merged
parents a5e90661 74addb78
...@@ -1709,4 +1709,156 @@ a b ...@@ -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 ...@@ -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; ...@@ -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; ...@@ -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); ...@@ -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; ...@@ -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
......
...@@ -879,6 +879,23 @@ public: ...@@ -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, ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 ...@@ -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 ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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))) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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);
......
...@@ -182,10 +182,33 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) ...@@ -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, &not_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, &not_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,104 +227,31 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) ...@@ -204,104 +227,31 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
return FALSE; return FALSE;
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/** /**
@brief Creating/altering VIEW procedure @brief CREATE VIEW privileges pre-check.
@param thd thread handler @param thd thread handler
@param tables tables used in the view
@param views views to create @param views views to create
@param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
@note This function handles both create and alter view commands.
@retval FALSE Operation was a success. @retval FALSE Operation was a success.
@retval TRUE An error occured. @retval TRUE An error occured.
*/ */
bool mysql_create_view(THD *thd, TABLE_LIST *views, bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
enum_view_create_mode mode) enum_view_create_mode mode)
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
bool link_to_local;
/* first table in list is target VIEW name => cut off it */ /* first table in list is target VIEW name => cut off it */
TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
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;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
SELECT_LEX *sl; SELECT_LEX *sl;
#endif bool res= TRUE;
SELECT_LEX_UNIT *unit= &lex->unit; DBUG_ENTER("create_view_precheck");
bool res= FALSE;
DBUG_ENTER("mysql_create_view");
/* This is ensured in the parser. */
DBUG_ASSERT(!lex->proc_list.first && !lex->result &&
!lex->param_list.elements && !lex->derived_tables);
if (mode != VIEW_CREATE_NEW)
{
if (mode == VIEW_ALTER &&
fill_defined_view_parts(thd, view))
{
res= TRUE;
goto err;
}
sp_cache_invalidate();
}
if (!lex->definer)
{
/*
DEFINER-clause is missing; we have to create default definer in
persistent arena to be PS/SP friendly.
If this is an ALTER VIEW then the current user should be set as
the definer.
*/
Query_arena original_arena;
Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
if (!(lex->definer= create_default_definer(thd)))
res= TRUE;
if (ps_arena)
thd->restore_active_arena(ps_arena, &original_arena);
if (res)
goto err;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
check definer of view:
- same as current user
- current user has SUPER_ACL
*/
if (lex->definer &&
(strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 ||
my_strcasecmp(system_charset_info,
lex->definer->host.str,
thd->security_ctx->priv_host) != 0))
{
if (!(thd->security_ctx->master_access & SUPER_ACL))
{
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
res= TRUE;
goto err;
}
else
{
if (!is_acl_user(lex->definer->host.str,
lex->definer->user.str))
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_NO_SUCH_USER,
ER(ER_NO_SUCH_USER),
lex->definer->user.str,
lex->definer->host.str);
}
}
}
/* /*
Privilege check for view creation: Privilege check for view creation:
- user has CREATE VIEW privilege on view table - user has CREATE VIEW privilege on view table
...@@ -323,10 +273,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, ...@@ -323,10 +273,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
(check_access(thd, DROP_ACL, view->db, &view->grant.privilege, (check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
0, 0, is_schema_db(view->db)) || 0, 0, is_schema_db(view->db)) ||
grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0)))) grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0))))
{
res= TRUE;
goto err; goto err;
}
for (sl= select_lex; sl; sl= sl->next_select()) for (sl= select_lex; sl; sl= sl->next_select())
{ {
for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local) for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local)
...@@ -340,7 +288,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, ...@@ -340,7 +288,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
"ANY", thd->security_ctx->priv_user, "ANY", thd->security_ctx->priv_user,
thd->security_ctx->priv_host, tbl->table_name); thd->security_ctx->priv_host, tbl->table_name);
res= TRUE;
goto err; goto err;
} }
/* /*
...@@ -376,13 +323,10 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, ...@@ -376,13 +323,10 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
if (check_access(thd, SELECT_ACL, tbl->db, if (check_access(thd, SELECT_ACL, tbl->db,
&tbl->grant.privilege, 0, 0, test(tbl->schema_table)) || &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) ||
grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0)) grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0))
{
res= TRUE;
goto err; goto err;
} }
} }
} }
}
/* /*
Mark fields for special privilege check ("any" privilege) Mark fields for special privilege check ("any" privilege)
*/ */
...@@ -403,8 +347,126 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, ...@@ -403,8 +347,126 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
} }
} }
} }
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
@param thd thread handler
@param views views to create
@param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
@note This function handles both create and alter view commands.
@retval FALSE Operation was a success.
@retval TRUE An error occured.
*/
bool mysql_create_view(THD *thd, TABLE_LIST *views,
enum_view_create_mode mode)
{
LEX *lex= thd->lex;
bool link_to_local;
/* first table in list is target VIEW name => cut off it */
TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
TABLE_LIST *tables= lex->query_tables;
TABLE_LIST *tbl;
SELECT_LEX *select_lex= &lex->select_lex;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
SELECT_LEX *sl;
#endif
SELECT_LEX_UNIT *unit= &lex->unit;
bool res= FALSE;
DBUG_ENTER("mysql_create_view");
/* This is ensured in the parser. */
DBUG_ASSERT(!lex->proc_list.first && !lex->result &&
!lex->param_list.elements && !lex->derived_tables);
if (mode != VIEW_CREATE_NEW)
{
if (mode == VIEW_ALTER &&
fill_defined_view_parts(thd, view))
{
res= TRUE;
goto err;
}
sp_cache_invalidate();
}
if (!lex->definer)
{
/*
DEFINER-clause is missing; we have to create default definer in
persistent arena to be PS/SP friendly.
If this is an ALTER VIEW then the current user should be set as
the definer.
*/
Query_arena original_arena;
Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
if (!(lex->definer= create_default_definer(thd)))
res= TRUE;
if (ps_arena)
thd->restore_active_arena(ps_arena, &original_arena);
if (res)
goto err;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
check definer of view:
- same as current user
- current user has SUPER_ACL
*/
if (lex->definer &&
(strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 ||
my_strcasecmp(system_charset_info,
lex->definer->host.str,
thd->security_ctx->priv_host) != 0))
{
if (!(thd->security_ctx->master_access & SUPER_ACL))
{
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
res= TRUE;
goto err;
}
else
{
if (!is_acl_user(lex->definer->host.str,
lex->definer->user.str))
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_NO_SUCH_USER,
ER(ER_NO_SUCH_USER),
lex->definer->user.str,
lex->definer->host.str);
}
}
}
#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 @@ ...@@ -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() ...@@ -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);"); ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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);
rc= mysql_stmt_prepare(prep_stmt, "SELECT 1", 8); DIE_UNLESS(lmysql);
DIE_UNLESS(rc==0);
mysql_close(mysql);
if ((rc= mysql_stmt_execute(prep_stmt))) if (!mysql_real_connect(lmysql, opt_host, opt_user, opt_password,
{ current_db, opt_port, opt_unix_socket, 0))
if ((rc= mysql_stmt_reset(prep_stmt)))
printf("OK!\n");
else
{
printf("Error!");
DIE_UNLESS(1==0);
}
}
else
{ {
fprintf(stderr, "expected error but no error occured\n"); fprintf(stderr, "Failed to connect to the database\n");
DIE_UNLESS(1==0); DIE_UNLESS(0);
} }
prep_stmt= mysql_stmt_init(lmysql);
rc= mysql_stmt_prepare(prep_stmt, "SELECT 1", 8);
DIE_UNLESS(rc == 0);
mysql_close(lmysql);
rc= mysql_stmt_execute(prep_stmt);
DIE_UNLESS(rc);
rc= mysql_stmt_reset(prep_stmt);
DIE_UNLESS(rc);
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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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[]= { ...@@ -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 }
}; };
......
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