diff options
author | unknown <joerg@trift2.> | 2008-03-05 10:24:28 +0100 |
---|---|---|
committer | unknown <joerg@trift2.> | 2008-03-05 10:24:28 +0100 |
commit | 1cddfc2f42afe1767388f1591648a45b211e778e (patch) | |
tree | 7fcfc29cff4d76a37a95e3c9bb529becc0d19b1e | |
parent | 61caf4635d07d83b6aa0cddf9661c32dc0bee61a (diff) | |
parent | 4d09306dd19820a742b003417d83f76f5d3633f3 (diff) | |
download | mariadb-git-1cddfc2f42afe1767388f1591648a45b211e778e.tar.gz |
Merge trift2.:/MySQL/M50/mysql-5.0
into trift2.:/MySQL/M50/push-5.0
configure.in:
Auto merged
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | mysql-test/r/limit.result | 9 | ||||
-rw-r--r-- | mysql-test/r/ps.result | 182 | ||||
-rw-r--r-- | mysql-test/r/rpl_user_variables.result | 16 | ||||
-rw-r--r-- | mysql-test/r/view.result | 21 | ||||
-rw-r--r-- | mysql-test/r/view_grant.result | 1 | ||||
-rw-r--r-- | mysql-test/t/limit.test | 17 | ||||
-rw-r--r-- | mysql-test/t/ps.test | 142 | ||||
-rw-r--r-- | mysql-test/t/rpl_user_variables.test | 17 | ||||
-rw-r--r-- | mysql-test/t/view.test | 36 | ||||
-rw-r--r-- | mysql-test/t/view_grant.test | 1 | ||||
-rw-r--r-- | sql/item.cc | 13 | ||||
-rw-r--r-- | sql/item.h | 52 | ||||
-rw-r--r-- | sql/item_func.cc | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/sql_cursor.cc | 98 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 39 | ||||
-rw-r--r-- | sql/sql_view.cc | 242 | ||||
-rw-r--r-- | sql/sql_view.h | 3 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 2 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 169 |
21 files changed, 879 insertions, 189 deletions
diff --git a/configure.in b/configure.in index 73bbbc2161b..fdec3bb3a6c 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.58) +AM_INIT_AUTOMAKE(mysql, 5.0.60) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=58 +NDB_VERSION_BUILD=60 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result index 01d7d7ca218..2acf74162a4 100644 --- a/mysql-test/r/limit.result +++ b/mysql-test/r/limit.result @@ -94,6 +94,9 @@ drop table t1; prepare s from "select 1 limit ?"; set @a='qwe'; execute s using @a; +1 +set @a=-1; +execute s using @a; ERROR HY000: Incorrect arguments to EXECUTE prepare s from "select 1 limit 1, ?"; execute s using @a; @@ -101,4 +104,10 @@ ERROR HY000: Incorrect arguments to EXECUTE prepare s from "select 1 limit ?, ?"; execute s using @a, @a; ERROR HY000: Incorrect arguments to EXECUTE +set @a=14632475938453979136; +execute s using @a, @a; +1 +set @a=-14632475938453979136; +execute s using @a, @a; +ERROR HY000: Incorrect arguments to EXECUTE End of 5.0 tests diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 8845f011971..9aef58d5702 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1709,4 +1709,186 @@ a b 9999999999999999 14632475938453979136 deallocate prepare stmt; 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 +prepare stmt from "select ?"; +set @arg= 123456789.987654321; +select @arg; +@arg +123456789.987654321 +execute stmt using @arg; +? +123456789.987654321 +set @arg= "string"; +select @arg; +@arg +string +execute stmt using @arg; +? +string +set @arg= 123456; +select @arg; +@arg +123456 +execute stmt using @arg; +? +123456 +set @arg= cast(-12345.54321 as decimal(20, 10)); +select @arg; +@arg +-12345.5432100000 +execute stmt using @arg; +? +-12345.5432100000 +deallocate prepare stmt; End of 5.0 tests. diff --git a/mysql-test/r/rpl_user_variables.result b/mysql-test/r/rpl_user_variables.result index 26ac2b26aaa..b8032a9c362 100644 --- a/mysql-test/r/rpl_user_variables.result +++ b/mysql-test/r/rpl_user_variables.result @@ -290,6 +290,22 @@ select * from t1; a b 2 1 drop table t1; +create table t1(a int); +insert into t1 values (1),(2); +prepare s1 from 'insert into t1 select a from t1 limit ?'; +set @x='1.1'; +execute s1 using @x; +select * from t1; +a +1 +2 +1 +select * from t1; +a +1 +2 +1 +drop table t1; End of 5.0 tests. DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index fb36304e562..633278a9781 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3618,4 +3618,23 @@ ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default val set @@sql_mode=@old_mode; drop view v1; 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. +# ----------------------------------------------------------------- diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index eef61c65fb8..53ad8642ba4 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -467,6 +467,7 @@ use test; REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; drop database mysqltest; drop view if exists v1; +drop table if exists t1; create table t1 as select * from mysql.user where user=''; delete from mysql.user where user=''; flush privileges; diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index 286c04785ff..9cccca1adc3 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -76,15 +76,22 @@ drop table t1; # Bug #28464: a string argument to 'limit ?' PS # -prepare s from "select 1 limit ?"; -set @a='qwe'; ---error 1210 +prepare s from "select 1 limit ?"; +set @a='qwe'; +execute s using @a; +set @a=-1; +--error ER_WRONG_ARGUMENTS execute s using @a; prepare s from "select 1 limit 1, ?"; ---error 1210 +--error ER_WRONG_ARGUMENTS execute s using @a; prepare s from "select 1 limit ?, ?"; ---error 1210 +--error ER_WRONG_ARGUMENTS +execute s using @a, @a; +set @a=14632475938453979136; +execute s using @a, @a; +set @a=-14632475938453979136; +--error ER_WRONG_ARGUMENTS execute s using @a, @a; --echo End of 5.0 tests diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 3f4b37f13f4..6c3f98f6a1a 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1824,4 +1824,146 @@ select * from t1 where a = @a and b = @b; deallocate prepare stmt; 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`"; + +# +# Bug#33851: Passing UNSIGNED param to EXECUTE returns ERROR 1210 +# + +prepare stmt from "select ?"; +set @arg= 123456789.987654321; +select @arg; +execute stmt using @arg; +set @arg= "string"; +select @arg; +execute stmt using @arg; +set @arg= 123456; +select @arg; +execute stmt using @arg; +set @arg= cast(-12345.54321 as decimal(20, 10)); +select @arg; +execute stmt using @arg; +deallocate prepare stmt; + --echo End of 5.0 tests. diff --git a/mysql-test/t/rpl_user_variables.test b/mysql-test/t/rpl_user_variables.test index 8f8f0accbd1..70b708be258 100644 --- a/mysql-test/t/rpl_user_variables.test +++ b/mysql-test/t/rpl_user_variables.test @@ -337,6 +337,23 @@ select * from t1; connection master; drop table t1; +# +# Bug#33851: Passing UNSIGNED param to EXECUTE returns ERROR 1210 +# + +connection master; +create table t1(a int); +insert into t1 values (1),(2); +prepare s1 from 'insert into t1 select a from t1 limit ?'; +set @x='1.1'; +execute s1 using @x; +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +drop table t1; + --echo End of 5.0 tests. # This test uses a stored function that uses user-defined variables to return data diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 340a34db5a1..5a87128f69e 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3470,5 +3470,39 @@ insert into v1 values(1); set @@sql_mode=@old_mode; drop view v1; 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 # ----------------------------------------------------------------- diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 7f9eb4e1cff..be9daacec4f 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -608,6 +608,7 @@ drop database mysqltest; # --disable_warnings drop view if exists v1; +drop table if exists t1; --enable_warnings # Backup anonymous users and remove them. (They get in the way of diff --git a/sql/item.cc b/sql/item.cc index ffb18054750..a9e99c65580 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2385,14 +2385,14 @@ default_set_param_func(Item_param *param, Item_param::Item_param(unsigned pos_in_query_arg) : - strict_type(FALSE), state(NO_VALUE), item_result_type(STRING_RESULT), /* Don't pretend to be a literal unless value for this item is set. */ item_type(PARAM_ITEM), param_type(MYSQL_TYPE_VARCHAR), pos_in_query(pos_in_query_arg), - set_param_func(default_set_param_func) + set_param_func(default_set_param_func), + limit_clause_param(FALSE) { name= (char*) "?"; /* @@ -2581,8 +2581,13 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) { item_result_type= entry->type; unsigned_flag= entry->unsigned_flag; - if (strict_type && required_result_type != item_result_type) - DBUG_RETURN(1); + if (limit_clause_param) + { + my_bool unused; + set_int(entry->val_int(&unused), MY_INT64_NUM_DECIMAL_DIGITS); + item_type= Item::INT_ITEM; + DBUG_RETURN(!unsigned_flag && value.integer < 0 ? 1 : 0); + } switch (item_result_type) { case REAL_RESULT: set_double(*(double*)entry->value); diff --git a/sql/item.h b/sql/item.h index 5f511557f47..7dc9ed4ec10 100644 --- a/sql/item.h +++ b/sql/item.h @@ -879,6 +879,23 @@ public: 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 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); -class Item_num: public Item +class Item_num: public Item_basic_constant { public: Item_num() {} /* Remove gcc warning */ @@ -1352,7 +1369,7 @@ public: friend class st_select_lex_unit; }; -class Item_null :public Item +class Item_null :public Item_basic_constant { public: Item_null(char *name_par=0) @@ -1374,8 +1391,6 @@ public: bool send(Protocol *protocol, String *str); enum Item_result result_type () const { return STRING_RESULT; } 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; } Item *clone_item() { return new Item_null(name); } bool is_null() { return 1; } @@ -1402,8 +1417,6 @@ class Item_param :public Item char cnvbuf[MAX_FIELD_WIDTH]; String cnvstr; Item *cnvitem; - bool strict_type; - enum Item_result required_result_type; public: enum enum_item_param_state @@ -1533,11 +1546,8 @@ public: Otherwise return FALSE. */ bool eq(const Item *item, bool binary_cmp) const; - void set_strict_type(enum Item_result result_type_arg) - { - strict_type= TRUE; - required_result_type= result_type_arg; - } + /** Item is a argument to a limit clause. */ + bool limit_clause_param; }; @@ -1567,8 +1577,6 @@ public: int save_in_field(Field *field, bool no_conversions); bool basic_const_item() const { return 1; } 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); Item_num *neg() { value= -value; return this; } uint decimal_precision() const @@ -1621,8 +1629,6 @@ public: { 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); Item_num *neg() { @@ -1673,8 +1679,6 @@ public: String *val_str(String*); my_decimal *val_decimal(my_decimal *); bool basic_const_item() const { return 1; } - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} Item *clone_item() { return new Item_float(name, value, decimals, max_length); } Item_num *neg() { value= -value; return this; } @@ -1696,7 +1700,7 @@ public: }; -class Item_string :public Item +class Item_string :public Item_basic_constant { public: Item_string(const char *str,uint length, @@ -1780,8 +1784,6 @@ public: max_length= str_value.numchars() * collation.collation->mbmaxlen; } void print(String *str); - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} }; @@ -1839,10 +1841,10 @@ public: }; -class Item_hex_string: public Item +class Item_hex_string: public Item_basic_constant { public: - Item_hex_string(): Item() {} + Item_hex_string() {} Item_hex_string(const char *str,uint str_length); enum Type type() const { return VARBIN_ITEM; } double val_real() @@ -1858,8 +1860,6 @@ public: enum Item_result result_type () const { return STRING_RESULT; } enum Item_result cast_to_int_type() const { return INT_RESULT; } 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); bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); @@ -2449,7 +2449,7 @@ private: }; -class Item_cache: public Item +class Item_cache: public Item_basic_constant { protected: Item *example; @@ -2486,8 +2486,6 @@ public: static Item_cache* get_cache(const Item *item); table_map used_tables() const { return used_table_map; } virtual void keep_array() {} - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} void print(String *str); bool eq_def(Field *field) { diff --git a/sql/item_func.cc b/sql/item_func.cc index 639e069d24e..84dd3e3ebc6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3985,7 +3985,7 @@ double user_var_entry::val_real(my_bool *null_value) /* Get the value of a variable as an integer */ -longlong user_var_entry::val_int(my_bool *null_value) +longlong user_var_entry::val_int(my_bool *null_value) const { if ((*null_value= (value == 0))) return LL(0); diff --git a/sql/sql_class.h b/sql/sql_class.h index 97f2d07b1d3..4ca8947de30 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2329,7 +2329,7 @@ class user_var_entry bool unsigned_flag; double val_real(my_bool *null_value); - longlong val_int(my_bool *null_value); + longlong val_int(my_bool *null_value) const; String *val_str(my_bool *null_value, String *str, uint decimals); my_decimal *val_decimal(my_bool *null_value, my_decimal *result); DTCollation collation; diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index 2e98da42be1..c2345f1f2cd 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -88,6 +88,7 @@ class Materialized_cursor: public Server_side_cursor public: 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 int open(JOIN *join __attribute__((unused))); 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) */ public: + Materialized_cursor *materialized_cursor; Select_materialize(select_result *result_arg) :result(result_arg) {} 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))) { - delete result; + delete result_materialize; return 1; } @@ -174,13 +176,13 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, /* Possible options here: - 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 - result_materialize->table is not NULL - - an error occured during materializaton. - result_materialize->table is not NULL, but rc != 0 + result_materialize->materialized is not NULL + - an error occurred during materialization. + result_materialize->materialized_cursor is not NULL, but rc != 0 - 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. This is possible if some command writes directly to the 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()) { - DBUG_ASSERT(!result_materialize->table); + DBUG_ASSERT(!result_materialize->materialized_cursor); /* It's safer if we grab THD state after mysql_execute_command 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; goto end; } - else if (result_materialize->table) + else if (result_materialize->materialized_cursor) { - Materialized_cursor *materialized_cursor; - TABLE *table= result_materialize->table; - MEM_ROOT *mem_root= &table->mem_root; - - if (!(materialized_cursor= new (mem_root) - Materialized_cursor(result, table))) - { - rc= 1; - goto err_open; - } + Materialized_cursor *materialized_cursor= + result_materialize->materialized_cursor; if ((rc= materialized_cursor->open(0))) { @@ -229,8 +223,6 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, err_open: DBUG_ASSERT(! (sensitive_cursor && sensitive_cursor->is_open())); delete sensitive_cursor; - if (result_materialize->table) - free_tmp_table(thd, result_materialize->table); end: delete result_materialize; 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))) { 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); /* Create a list of fields and start sequential scan */ - rc= (table->fill_item_list(&item_list) || - result->prepare(item_list, &fake_unit) || + rc= (result->prepare(item_list, &fake_unit) || table->file->ha_rnd_init(TRUE)); thd->restore_active_arena(this, &backup_arena); 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(), FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, "")) 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; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 74cbd2c5505..18cfd8d7dfc 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -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. @@ -1730,6 +1768,7 @@ static bool check_prepared_statement(Prepared_statement *stmt, my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0)); goto error; } + res= mysql_test_create_view(stmt); break; case SQLCOM_DO: res= mysql_test_do_fields(stmt, tables, lex->insert_list); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index dd0b92a06f8..4c8e6e80c41 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -182,10 +182,33 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) TABLE_LIST decoy; 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; } @@ -204,104 +227,31 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) return FALSE; } +#ifndef NO_EMBEDDED_ACCESS_CHECKS /** - @brief Creating/altering VIEW procedure + @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 - @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) +bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, + 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; + bool res= TRUE; + DBUG_ENTER("create_view_precheck"); - 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: - user has CREATE VIEW privilege on view table @@ -323,10 +273,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, (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) @@ -340,7 +288,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, 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; } /* @@ -376,10 +323,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, 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; - } } } } @@ -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 + + if ((res= create_view_precheck(thd, tables, view, mode))) + goto err; + if (open_and_lock_tables(thd, tables)) { res= TRUE; diff --git a/sql/sql_view.h b/sql/sql_view.h index ab0920e0bf2..1d45283352b 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -15,6 +15,9 @@ 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, enum_view_create_mode mode); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a7c1060025d..04285fea227 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6320,7 +6320,7 @@ limit_options: limit_option: param_marker { - ((Item_param *) $1)->set_strict_type(INT_RESULT); + ((Item_param *) $1)->limit_clause_param= TRUE; } | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); } | LONG_NUM { $$= new Item_uint($1.str, $1.length); } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9cc2af25529..260e7b1e7a7 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -8702,8 +8702,8 @@ static void test_sqlmode() strmov(c1, "My"); strmov(c2, "SQL"); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); - mysql_stmt_close(stmt); + verify_col_data("test_piping", "name", "MySQL"); rc= mysql_query(mysql, "DELETE FROM test_piping"); @@ -12993,7 +12993,7 @@ from t2);"); static void test_bug8378() { #if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY) - MYSQL *old_mysql=mysql; + MYSQL *lmysql; char out[9]; /* strlen(TEST_BUG8378)*2+1 */ char buf[256]; int len, rc; @@ -13002,17 +13002,17 @@ static void test_bug8378() if (!opt_silent) fprintf(stdout, "\n Establishing a test connection ..."); - if (!(mysql= mysql_init(NULL))) + if (!(lmysql= mysql_init(NULL))) { myerror("mysql_init() failed"); exit(1); } - if (mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "gbk")) + if (mysql_options(lmysql, MYSQL_SET_CHARSET_NAME, "gbk")) { myerror("mysql_options() failed"); 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_unix_socket, 0))) { @@ -13022,19 +13022,17 @@ static void test_bug8378() if (!opt_silent) 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. */ DIE_UNLESS(memcmp(out, TEST_BUG8378_OUT, len) == 0); sprintf(buf, "SELECT '%s'", out); - rc=mysql_real_query(mysql, buf, strlen(buf)); + rc=mysql_real_query(lmysql, buf, strlen(buf)); myquery(rc); - mysql_close(mysql); - - mysql=old_mysql; + mysql_close(lmysql); #endif } @@ -14869,7 +14867,7 @@ static void test_opt_reconnect() if (mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true)) { myerror("mysql_options failed: unknown option MYSQL_OPT_RECONNECT\n"); - exit(1); + DIE_UNLESS(0); } /* reconnect should be 1 */ @@ -14882,7 +14880,7 @@ static void test_opt_reconnect() opt_unix_socket, 0))) { myerror("connection failed"); - exit(1); + DIE_UNLESS(0); } /* reconnect should still be 1 */ @@ -14896,7 +14894,7 @@ static void test_opt_reconnect() if (!(lmysql= mysql_init(NULL))) { myerror("mysql_init() failed"); - exit(1); + DIE_UNLESS(0); } if (!opt_silent) @@ -14908,7 +14906,7 @@ static void test_opt_reconnect() opt_unix_socket, 0))) { myerror("connection failed"); - exit(1); + DIE_UNLESS(0); } /* reconnect should still be 0 */ @@ -14926,32 +14924,32 @@ static void test_opt_reconnect() static void test_bug12744() { MYSQL_STMT *prep_stmt = NULL; + MYSQL *lmysql; int rc; myheader("test_bug12744"); - prep_stmt= mysql_stmt_init(mysql); - rc= mysql_stmt_prepare(prep_stmt, "SELECT 1", 8); - DIE_UNLESS(rc==0); - - mysql_close(mysql); + lmysql= mysql_init(NULL); + DIE_UNLESS(lmysql); - if ((rc= mysql_stmt_execute(prep_stmt))) - { - if ((rc= mysql_stmt_reset(prep_stmt))) - printf("OK!\n"); - else - { - printf("Error!"); - DIE_UNLESS(1==0); - } - } - else + if (!mysql_real_connect(lmysql, opt_host, opt_user, opt_password, + current_db, opt_port, opt_unix_socket, 0)) { - fprintf(stderr, "expected error but no error occured\n"); - DIE_UNLESS(1==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); + 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); - client_connect(0); + DIE_UNLESS(rc == 0); } #endif /* EMBEDDED_LIBRARY */ @@ -15217,6 +15215,10 @@ static void test_bug14169() Test that mysql_insert_id() behaves as documented in our manual */ +#if 0 + + Commented out because of Bug#34889. + static void test_mysql_insert_id() { my_ulonglong res; @@ -15392,6 +15394,7 @@ static void test_mysql_insert_id() rc= mysql_query(mysql, "drop table t1,t2"); myquery(rc); } +#endif /* @@ -15759,6 +15762,7 @@ static void test_bug24179() mysql_stmt_error(stmt)); } DIE_UNLESS(mysql_stmt_errno(stmt) == 1323); + mysql_stmt_close(stmt); DBUG_VOID_RETURN; } @@ -15801,6 +15805,7 @@ static void test_bug27876() myquery(rc); result= mysql_store_result(mysql); mytest(result); + mysql_free_result(result); sprintf(query, "DROP FUNCTION IF EXISTS %s", utf8_func); rc= mysql_query(mysql, query); @@ -15817,6 +15822,7 @@ static void test_bug27876() myquery(rc); result= mysql_store_result(mysql); mytest(result); + mysql_free_result(result); sprintf(query, "DROP FUNCTION %s", utf8_func); rc= mysql_query(mysql, query); @@ -15965,6 +15971,7 @@ static void test_bug29948() exit(1); } + bzero(&bind, sizeof(bind)); bind.buffer_type= MYSQL_TYPE_LONG; bind.buffer= (char *)&buf; bind.is_null= &is_null; @@ -16152,6 +16159,99 @@ static void test_bug31669() 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 */ @@ -16432,7 +16532,7 @@ static struct my_tests_st my_tests[]= { { "test_bug17667", test_bug17667 }, { "test_bug19671", test_bug19671 }, { "test_bug15752", test_bug15752 }, - { "test_mysql_insert_id", test_mysql_insert_id }, + /* { "test_mysql_insert_id", test_mysql_insert_id }, Bug#34889 */ { "test_bug21206", test_bug21206 }, { "test_bug21726", test_bug21726 }, { "test_bug15518", test_bug15518 }, @@ -16446,6 +16546,7 @@ static struct my_tests_st my_tests[]= { { "test_bug29948", test_bug29948 }, { "test_bug29306", test_bug29306 }, { "test_bug31669", test_bug31669 }, + { "test_bug32265", test_bug32265 }, { 0, 0 } }; |