diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index 0ecc462fb70..49722d5b0ab 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -39,10 +39,10 @@ t2 CREATE TABLE `t2` ( `Field_name` varbinary(255) NOT NULL default '', `Min_value` varbinary(255) default NULL, `Max_value` varbinary(255) default NULL, - `Min_length` int(11) NOT NULL default '0', - `Max_length` int(11) NOT NULL default '0', - `Empties_or_zeros` int(11) NOT NULL default '0', - `Nulls` int(11) NOT NULL default '0', + `Min_length` bigint(11) NOT NULL default '0', + `Max_length` bigint(11) NOT NULL default '0', + `Empties_or_zeros` bigint(11) NOT NULL default '0', + `Nulls` bigint(11) NOT NULL default '0', `Avg_value_or_avg_length` varbinary(255) NOT NULL default '', `Std` varbinary(255) default NULL, `Optimal_fieldtype` varbinary(64) NOT NULL default '' @@ -58,10 +58,10 @@ t2 CREATE TABLE `t2` ( `Field_name` varbinary(255) NOT NULL default '', `Min_value` varbinary(255) default NULL, `Max_value` varbinary(255) default NULL, - `Min_length` int(11) NOT NULL default '0', - `Max_length` int(11) NOT NULL default '0', - `Empties_or_zeros` int(11) NOT NULL default '0', - `Nulls` int(11) NOT NULL default '0', + `Min_length` bigint(11) NOT NULL default '0', + `Max_length` bigint(11) NOT NULL default '0', + `Empties_or_zeros` bigint(11) NOT NULL default '0', + `Nulls` bigint(11) NOT NULL default '0', `Avg_value_or_avg_length` varbinary(255) NOT NULL default '', `Std` varbinary(255) default NULL, `Optimal_fieldtype` varbinary(64) NOT NULL default '' @@ -81,10 +81,10 @@ t2 CREATE TABLE `t2` ( `Field_name` varbinary(255) NOT NULL default '', `Min_value` varbinary(255) default NULL, `Max_value` varbinary(255) default NULL, - `Min_length` int(11) NOT NULL default '0', - `Max_length` int(11) NOT NULL default '0', - `Empties_or_zeros` int(11) NOT NULL default '0', - `Nulls` int(11) NOT NULL default '0', + `Min_length` bigint(11) NOT NULL default '0', + `Max_length` bigint(11) NOT NULL default '0', + `Empties_or_zeros` bigint(11) NOT NULL default '0', + `Nulls` bigint(11) NOT NULL default '0', `Avg_value_or_avg_length` varbinary(255) NOT NULL default '', `Std` varbinary(255) default NULL, `Optimal_fieldtype` varbinary(64) NOT NULL default '' diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result index d0058118e4c..90ba00e1019 100644 --- a/mysql-test/r/auto_increment.result +++ b/mysql-test/r/auto_increment.result @@ -232,7 +232,7 @@ a b delete from t1 where a=0; update t1 set a=NULL where b=6; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 4 +Warning 1048 Column 'a' cannot be null update t1 set a=300 where b=7; SET SQL_MODE=''; insert into t1(a,b)values(NULL,8); @@ -274,7 +274,7 @@ a b delete from t1 where a=0; update t1 set a=NULL where b=13; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 9 +Warning 1048 Column 'a' cannot be null update t1 set a=500 where b=14; select * from t1 order by b; a b diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index e1262c7d2c2..c1f72ce317c 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -13,7 +13,7 @@ Warnings: Note 1050 Table 't1' already exists insert into t1 values (""),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 2 +Warning 1048 Column 'b' cannot be null select * from t1; b diff --git a/mysql-test/r/func_date_add.result b/mysql-test/r/func_date_add.result index ac5709260fd..a7f2383848d 100644 --- a/mysql-test/r/func_date_add.result +++ b/mysql-test/r/func_date_add.result @@ -84,4 +84,15 @@ CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK; CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK 2006-10-03 +create table t1 (a int, b varchar(10)); +insert into t1 values (1, '2001-01-01'),(2, '2002-02-02'); +select '2007-01-01' + interval a day from t1; +'2007-01-01' + interval a day +2007-01-02 +2007-01-03 +select b + interval a day from t1; +b + interval a day +2001-01-02 +2002-02-04 +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index fa6e23d09f9..8a0a3ba848c 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -63,7 +63,7 @@ insert into t1 values(NULL); ERROR 23000: Column 'id' cannot be null insert into t1 values (1), (NULL), (2); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'id' at row 2 +Warning 1048 Column 'id' cannot be null select * from t1; id 1 diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index a96add7eb9a..08a865e0b94 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -606,8 +606,8 @@ NULL 2 100 create table t2(No int not null, Field int not null, Count int not null); insert into t2 Select null, Field, Count From t1 Where Month=20030901 and Type=2; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'No' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'No' at row 2 +Warning 1048 Column 'No' cannot be null +Warning 1048 Column 'No' cannot be null select * from t2; No Field Count 0 1 100 diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 375961292a3..b3bca7517f3 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -378,7 +378,7 @@ id c1 cnt INSERT IGNORE INTO t1 (id,c1) SELECT 1,NULL ON DUPLICATE KEY UPDATE c1=NULL, cnt=cnt+1; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c1' at row 1 +Warning 1048 Column 'c1' cannot be null Error 1048 Column 'c1' cannot be null SELECT * FROM t1; id c1 cnt @@ -386,7 +386,7 @@ id c1 cnt INSERT IGNORE INTO t1 (id,c1) SELECT * FROM t2 ON DUPLICATE KEY UPDATE c1=NULL, cnt=cnt+1; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c1' at row 1 +Warning 1048 Column 'c1' cannot be null Error 1048 Column 'c1' cannot be null SELECT * FROM t1; id c1 cnt diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 3abc95ec3bf..5a707770ab8 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -159,8 +159,8 @@ CREATE TABLE t1 (c CHAR(10) NOT NULL,i INT NOT NULL AUTO_INCREMENT, UNIQUE (c,i)); INSERT INTO t1 (c) VALUES (NULL),(NULL); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c' at row 2 +Warning 1048 Column 'c' cannot be null +Warning 1048 Column 'c' cannot be null SELECT * FROM t1; c i 1 diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index 4bc04c6de3c..a4966d9d5ec 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -123,3 +123,5 @@ release_lock("lock27563") drop table t1, t2; drop function bug27563; drop procedure proc27563; +PREPARE stmt FROM 'EXPLAIN SELECT * FROM t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40 WHERE a1=a2 AND a2=a3 AND a3=a4 AND a4=a5 AND a5=a6 AND a6=a7 AND a7=a8 AND a8=a9 AND a9=a10 AND a10=a11 AND a11=a12 AND a12=a13 AND a13=a14 AND a14=a15 AND a15=a16 AND a16=a17 AND a17=a18 AND a18=a19 AND a19=a20 AND a20=a21 AND a21=a22 AND a22=a23 AND a23=a24 AND a24=a25 AND a25=a26 AND a26=a27 AND a27=a28 AND a28=a29 AND a29=a30 AND a30=a31 AND a31=a32 AND a32=a33 AND a33=a34 AND a34=a35 AND a35=a36 AND a36=a37 AND a37=a38 AND a38=a39 AND a39=a40 '; +EXECUTE stmt; diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result index 34e961395c4..d33fb038b79 100644 --- a/mysql-test/r/metadata.result +++ b/mysql-test/r/metadata.result @@ -130,3 +130,14 @@ def v3 renamed 8 12 0 Y 32896 0 63 renamed drop table t1; drop view v1,v2,v3; +select a.* from (select 2147483648 as v_large) a; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def a v_large v_large 8 10 10 N 32769 0 63 +v_large +2147483648 +select a.* from (select 214748364 as v_small) a; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def a v_small v_small 3 9 9 N 32769 0 63 +v_small +214748364 +End of 5.0 tests diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index daedfa50b80..c33adee76b2 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -97,39 +97,39 @@ Warnings: Warning 1265 Data truncated for column 'd' at row 1 UPDATE t1 SET d=NULL; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'd' at row 1 +Warning 1048 Column 'd' cannot be null INSERT INTO t1 (a) values (null); ERROR 23000: Column 'a' cannot be null INSERT INTO t1 (a) values (1/null); ERROR 23000: Column 'a' cannot be null INSERT INTO t1 (a) values (null),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 2 +Warning 1048 Column 'a' cannot be null +Warning 1048 Column 'a' cannot be null INSERT INTO t1 (b) values (null); ERROR 23000: Column 'b' cannot be null INSERT INTO t1 (b) values (1/null); ERROR 23000: Column 'b' cannot be null INSERT INTO t1 (b) values (null),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 2 +Warning 1048 Column 'b' cannot be null +Warning 1048 Column 'b' cannot be null INSERT INTO t1 (c) values (null); ERROR 23000: Column 'c' cannot be null INSERT INTO t1 (c) values (1/null); ERROR 23000: Column 'c' cannot be null INSERT INTO t1 (c) values (null),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c' at row 2 +Warning 1048 Column 'c' cannot be null +Warning 1048 Column 'c' cannot be null INSERT INTO t1 (d) values (null); ERROR 23000: Column 'd' cannot be null INSERT INTO t1 (d) values (1/null); ERROR 23000: Column 'd' cannot be null INSERT INTO t1 (d) values (null),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'd' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'd' at row 2 +Warning 1048 Column 'd' cannot be null +Warning 1048 Column 'd' cannot be null select * from t1; a b c d 0 0000-00-00 00:00:00 0 diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 0b4ed15f659..8a440284c53 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -342,7 +342,7 @@ index (id2) ); insert into t1 values(null,null),(1,1); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'id2' at row 1 +Warning 1048 Column 'id2' cannot be null select * from t1; id id2 NULL 0 diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index b1c29a5aadb..4a54b17316d 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -696,8 +696,8 @@ CREATE VIEW v1 AS SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; DESC v1; Field Type Null Key Default Extra -a int(11) YES 0 -LENGTH(a) int(10) YES NULL +a bigint(11) YES NULL +LENGTH(a) bigint(10) YES NULL COUNT(*) bigint(21) NO 0 SELECT * FROM v1; a LENGTH(a) COUNT(*) diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 32ed34e1d52..06941cf6497 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1304,7 +1304,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index c53056cfa0e..235660cbbaf 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1287,7 +1287,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 2951ce28fa5..bf77ec7acf2 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1288,7 +1288,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 56ec1e04901..f6aa716d932 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1330,7 +1330,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two @@ -4351,7 +4351,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index ed774b202b2..2c8b40e8818 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1287,7 +1287,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index ff5ecbb2e9b..a0bbeed34ee 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1287,7 +1287,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/rpl_view.result b/mysql-test/r/rpl_view.result index be03f3f080a..be7ed6e8c2a 100644 --- a/mysql-test/r/rpl_view.result +++ b/mysql-test/r/rpl_view.result @@ -106,4 +106,10 @@ a b 1 6 drop table t1; drop view v1; +CREATE TABLE t1(a INT); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE VIEW v1 AS SELECT * FROM t1; +ERROR 42S01: Table 'v1' already exists +DROP VIEW v1; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index b5b79af031e..8aea5b4e6ff 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4909,7 +4909,7 @@ create table t3 as select * from v1| show create table t3| Table Create Table t3 CREATE TABLE `t3` ( - `j` int(11) default NULL + `j` bigint(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t3| j @@ -6152,3 +6152,14 @@ count(*) 3 drop table t1,t2; drop function bug27354; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE FUNCTION metered(a INT) RETURNS INT RETURN 12; +CREATE VIEW v1 AS SELECT test.metered(a) as metered FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `test`.`metered`(`t1`.`a`) AS `metered` from `t1` +DROP VIEW v1; +DROP FUNCTION metered; +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index a3ebd5c86fd..34869862a63 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -993,16 +993,16 @@ ERROR 23000: Column 'col2' cannot be null INSERT INTO t1 VALUES (103,'',NULL); ERROR 23000: Column 'col3' cannot be null UPDATE t1 SET col1=NULL WHERE col1 =100; -ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'col1' at row 1 +ERROR 23000: Column 'col1' cannot be null UPDATE t1 SET col2 =NULL WHERE col2 ='hello'; -ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 +ERROR 23000: Column 'col2' cannot be null UPDATE t1 SET col2 =NULL where col3 IS NOT NULL; -ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 +ERROR 23000: Column 'col2' cannot be null INSERT IGNORE INTO t1 values (NULL,NULL,NULL); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col1' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col3' at row 1 +Warning 1048 Column 'col1' cannot be null +Warning 1048 Column 'col2' cannot be null +Warning 1048 Column 'col3' cannot be null SELECT * FROM t1; col1 col2 col3 100 hello 2004-08-20 @@ -1027,11 +1027,11 @@ ERROR HY000: Field 'col2' doesn't have a default value INSERT INTO t1 (col1) SELECT 1; ERROR HY000: Field 'col2' doesn't have a default value INSERT INTO t1 SELECT 1,NULL; -ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 +ERROR 23000: Column 'col2' cannot be null INSERT IGNORE INTO t1 values (NULL,NULL); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col1' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 +Warning 1048 Column 'col1' cannot be null +Warning 1048 Column 'col2' cannot be null INSERT IGNORE INTO t1 (col1) values (3); Warnings: Warning 1364 Field 'col2' doesn't have a default value diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result index 2683201e25e..0b420c42cc7 100644 --- a/mysql-test/r/type_enum.result +++ b/mysql-test/r/type_enum.result @@ -1779,3 +1779,10 @@ create table t1(exhausting_charset enum('ABCDEFGHIJKLMNOPQRSTUVWXYZ','  !"','#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~','xx\','yy\','zz')); ERROR 42000: Field separator argument is not what is expected; check the manual End of 4.1 tests +create table t1(f1 set('a','b'), index(f1)); +insert into t1 values(''),(''),('a'),('b'); +select * from t1 where f1=''; +f1 + + +drop table t1; diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 753c982155c..b9f58b60d9b 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -317,3 +317,10 @@ SHOW COUNT(*) WARNINGS; SHOW COUNT(*) ERRORS; @@session.error_count 1 +create table t1(f1 int); +insert into t1 values(1),(1),(2); +select @a:=f1, count(f1) from t1 group by 1; +@a:=f1 count(f1) +1 2 +2 1 +drop table t1; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 13239af41ad..43e147724c8 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1497,7 +1497,7 @@ insert into v3(b) values (10); insert into v3(a) select a from t2; insert into v3(b) select b from t2; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 2 +Warning 1048 Column 'a' cannot be null insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a); select * from t1; a b @@ -2779,7 +2779,7 @@ CREATE TABLE t1 (i int, j int); CREATE VIEW v1 AS SELECT COALESCE(i,j) FROM t1; DESCRIBE v1; Field Type Null Key Default Extra -COALESCE(i,j) int(11) YES NULL +COALESCE(i,j) bigint(11) YES NULL CREATE TABLE t2 SELECT COALESCE(i,j) FROM t1; DESCRIBE t2; Field Type Null Key Default Extra @@ -3367,6 +3367,23 @@ SHOW CREATE VIEW v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(1.23456789 as decimal(8,0)) AS `col` DROP VIEW v1; +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT, c INT DEFAULT 0); +INSERT INTO t1 (a) VALUES (1), (2); +INSERT INTO t2 (b) VALUES (1), (2); +CREATE VIEW v1 AS SELECT t2.b,t2.c FROM t1, t2 +WHERE t1.a=t2.b AND t2.b < 3 WITH CHECK OPTION; +SELECT * FROM v1; +b c +1 0 +2 0 +UPDATE v1 SET c=1 WHERE b=1; +SELECT * FROM v1; +b c +1 1 +2 0 +DROP VIEW v1; +DROP TABLE t1,t2; CREATE TABLE t1 (id int); CREATE TABLE t2 (id int, c int DEFAULT 0); INSERT INTO t1 (id) VALUES (1); @@ -3377,4 +3394,65 @@ WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; UPDATE v1 SET c=1; DROP VIEW v1; DROP TABLE t1,t2; +CREATE TABLE t1 (a1 INT, c INT DEFAULT 0); +CREATE TABLE t2 (a2 INT); +CREATE TABLE t3 (a3 INT); +CREATE TABLE t4 (a4 INT); +INSERT INTO t1 (a1) VALUES (1),(2); +INSERT INTO t2 (a2) VALUES (1),(2); +INSERT INTO t3 (a3) VALUES (1),(2); +INSERT INTO t4 (a4) VALUES (1),(2); +CREATE VIEW v1 AS +SELECT t1.a1, t1.c FROM t1 JOIN t2 ON t1.a1=t2.a2 AND t1.c < 3 +WITH CHECK OPTION; +SELECT * FROM v1; +a1 c +1 0 +2 0 +UPDATE v1 SET c=3; +ERROR HY000: CHECK OPTION failed 'test.v1' +PREPARE t FROM 'UPDATE v1 SET c=3'; +EXECUTE t; +ERROR HY000: CHECK OPTION failed 'test.v1' +EXECUTE t; +ERROR HY000: CHECK OPTION failed 'test.v1' +INSERT INTO v1(a1, c) VALUES (3, 3); +ERROR HY000: CHECK OPTION failed 'test.v1' +UPDATE v1 SET c=1 WHERE a1=1; +SELECT * FROM v1; +a1 c +1 1 +2 0 +SELECT * FROM t1; +a1 c +1 1 +2 0 +CREATE VIEW v2 AS SELECT t1.a1, t1.c +FROM (t1 JOIN t2 ON t1.a1=t2.a2 AND t1.c < 3) +JOIN (t3 JOIN t4 ON t3.a3=t4.a4) +ON t2.a2=t3.a3 WITH CHECK OPTION; +SELECT * FROM v2; +a1 c +1 1 +2 0 +UPDATE v2 SET c=3; +ERROR HY000: CHECK OPTION failed 'test.v2' +PREPARE t FROM 'UPDATE v2 SET c=3'; +EXECUTE t; +ERROR HY000: CHECK OPTION failed 'test.v2' +EXECUTE t; +ERROR HY000: CHECK OPTION failed 'test.v2' +INSERT INTO v2(a1, c) VALUES (3, 3); +ERROR HY000: CHECK OPTION failed 'test.v2' +UPDATE v2 SET c=2 WHERE a1=1; +SELECT * FROM v2; +a1 c +1 2 +2 0 +SELECT * FROM t1; +a1 c +1 2 +2 0 +DROP VIEW v1,v2; +DROP TABLE t1,t2,t3,t4; End of 5.0 tests. diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index d0ad4ca6648..9ce1f9c825d 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -86,7 +86,7 @@ drop table t1; create table t1(a tinyint NOT NULL, b tinyint unsigned, c char(5)); insert into t1 values(NULL,100,'mysql'),(10,-1,'mysql ab'),(500,256,'open source'),(20,NULL,'test'); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null Warning 1264 Out of range value adjusted for column 'b' at row 2 Warning 1265 Data truncated for column 'c' at row 2 Warning 1264 Out of range value adjusted for column 'a' at row 3 @@ -99,7 +99,7 @@ Warning 1265 Data truncated for column 'c' at row 2 alter table t1 add d char(2); update t1 set a=NULL where a=10; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 2 +Warning 1048 Column 'a' cannot be null update t1 set c='mysql ab' where c='test'; Warnings: Warning 1265 Data truncated for column 'c' at row 4 @@ -115,7 +115,7 @@ Warnings: Warning 1265 Data truncated for column 'b' at row 1 Warning 1265 Data truncated for column 'b' at row 2 Warning 1265 Data truncated for column 'b' at row 3 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 4 +Warning 1048 Column 'a' cannot be null Warning 1265 Data truncated for column 'b' at row 4 insert into t2(b) values('mysqlab'); Warnings: diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 004ef69182d..b665eb86656 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -10,7 +10,13 @@ select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; select ~5, cast(~5 as signed); explain extended select ~5, cast(~5 as signed); select cast(5 as unsigned) -6.0; -select cast(NULL as signed), cast(1/0 as signed); +select cast(NULL as signed), cast(1/0 as signed); +# +# Bug #28250: Run-Time Check Failure #3 - The variable 'value' is being used +# without being def +# +# The following line causes Run-Time Check Failure on +# binaries built with Visual C++ 2005 select cast(NULL as unsigned), cast(1/0 as unsigned); select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A"; select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME); diff --git a/mysql-test/t/func_date_add.test b/mysql-test/t/func_date_add.test index b575eeececa..fc5a5cb2823 100644 --- a/mysql-test/t/func_date_add.test +++ b/mysql-test/t/func_date_add.test @@ -77,4 +77,14 @@ SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH; SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR; SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK; +# +# Bug#28450: The Item_date_add_interval in select list may fail the field +# type assertion. +# +create table t1 (a int, b varchar(10)); +insert into t1 values (1, '2001-01-01'),(2, '2002-02-02'); +select '2007-01-01' + interval a day from t1; +select b + interval a day from t1; +drop table t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 83194e214fb..5f6bae00254 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -249,3 +249,56 @@ select release_lock("lock27563"); drop table t1, t2; drop function bug27563; drop procedure proc27563; + +# +# Bug#28598: mysqld crash when killing a long-running explain query. +# +--disable_query_log +connection con1; +let $ID= `select connection_id()`; +let $tab_count= 40; + +let $i= $tab_count; +while ($i) +{ + eval CREATE TABLE t$i (a$i int, KEY(a$i)); + eval INSERT INTO t$i VALUES (1),(2),(3),(4),(5),(6),(7); + dec $i ; +} +set session optimizer_search_depth=0; + +let $i=$tab_count; +while ($i) +{ + let $a= a$i; + let $t= t$i; + dec $i; + if ($i) + { + let $comma=,; + let $from=$comma$t$from; + let $where=a$i=$a $and $where; + } + if (!$i) + { + let $from=FROM $t$from; + let $where=WHERE $where; + } + let $and=AND; +} + +--enable_query_log +eval PREPARE stmt FROM 'EXPLAIN SELECT * $from $where'; +send EXECUTE stmt; +--disable_query_log + +connection con2; +real_sleep 2; +eval kill query $ID; +let $i= $tab_count; +while ($i) +{ + eval DROP TABLE t$i; + dec $i ; +} +--enable_query_log diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test index a6ebfdc14c1..df4acec2021 100644 --- a/mysql-test/t/metadata.test +++ b/mysql-test/t/metadata.test @@ -81,3 +81,14 @@ drop view v1,v2,v3; --disable_metadata # End of 4.1 tests + +# +# Bug #28492: subselect returns LONG in >5.0.24a and LONGLONG in <=5.0.24a +# +--enable_metadata +select a.* from (select 2147483648 as v_large) a; +select a.* from (select 214748364 as v_small) a; +--disable_metadata + + +--echo End of 5.0 tests diff --git a/mysql-test/t/rpl_view.test b/mysql-test/t/rpl_view.test index 812e5d44d58..21748586130 100644 --- a/mysql-test/t/rpl_view.test +++ b/mysql-test/t/rpl_view.test @@ -149,4 +149,16 @@ drop view v1; sync_slave_with_master; +# +# BUG#28244 CREATE VIEW breaks replication when view exists +# +connection master; +CREATE TABLE t1(a INT); +CREATE VIEW v1 AS SELECT * FROM t1; +--error ER_TABLE_EXISTS_ERROR +CREATE VIEW v1 AS SELECT * FROM t1; +DROP VIEW v1; +DROP TABLE t1; +sync_slave_with_master; + --echo End of 5.0 tests diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ff203a85ef7..88b8a46c48f 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7112,3 +7112,23 @@ select count(*) from t1 /* must be 3 */; drop table t1,t2; drop function bug27354; + +# +# Bug #28605: SHOW CREATE VIEW with views using stored_procedures no longer +# showing SP names. +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); + +CREATE FUNCTION metered(a INT) RETURNS INT RETURN 12; + +CREATE VIEW v1 AS SELECT test.metered(a) as metered FROM t1; + +SHOW CREATE VIEW v1; + +DROP VIEW v1; +DROP FUNCTION metered; +DROP TABLE t1; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index fc663853174..bf49a6a906c 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -890,11 +890,11 @@ INSERT INTO t1 (col1,col2,col3) VALUES (NULL, '', '2004-01-01'); INSERT INTO t1 (col1,col2,col3) VALUES (102, NULL, '2004-01-01'); --error 1048 INSERT INTO t1 VALUES (103,'',NULL); ---error 1263 +--error 1048 UPDATE t1 SET col1=NULL WHERE col1 =100; ---error 1263 +--error 1048 UPDATE t1 SET col2 =NULL WHERE col2 ='hello'; ---error 1263 +--error 1048 UPDATE t1 SET col2 =NULL where col3 IS NOT NULL; INSERT IGNORE INTO t1 values (NULL,NULL,NULL); SELECT * FROM t1; @@ -914,7 +914,7 @@ INSERT INTO t1 (col1) VALUES (2); INSERT INTO t1 VALUES(default(col1),default(col2)); --error 1364 INSERT INTO t1 (col1) SELECT 1; ---error 1263 +--error 1048 INSERT INTO t1 SELECT 1,NULL; INSERT IGNORE INTO t1 values (NULL,NULL); INSERT IGNORE INTO t1 (col1) values (3); diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test index 4b3429d9ea0..45da469cf2d 100644 --- a/mysql-test/t/type_enum.test +++ b/mysql-test/t/type_enum.test @@ -157,3 +157,11 @@ create table t1(exhausting_charset enum('ABCDEFGHIJKLMNOPQRSTUVWXYZ','  !"','#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~','xx\','yy\','zz')); --echo End of 4.1 tests + +# +# Bug#28729: Field_enum wrongly reported an error while storing an empty string. +# +create table t1(f1 set('a','b'), index(f1)); +insert into t1 values(''),(''),('a'),('b'); +select * from t1 where f1=''; +drop table t1; diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 70f57fdf283..7919b663a73 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -222,3 +222,11 @@ drop table t1,t2; insert into city 'blah'; SHOW COUNT(*) WARNINGS; SHOW COUNT(*) ERRORS; + +# +# Bug#28494: Grouping by Item_func_set_user_var produces incorrect result. +# +create table t1(f1 int); +insert into t1 values(1),(1),(2); +select @a:=f1, count(f1) from t1 group by 1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 1f6bee8b142..f574451af08 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3233,6 +3233,22 @@ CREATE VIEW v1 AS SELECT CAST(1.23456789 AS DECIMAL(8,0)) AS col; SHOW CREATE VIEW v1; DROP VIEW v1; +# +# Bug #28716: CHECK OPTION expression is evaluated over expired record buffers +# when VIEW is updated via temporary tables +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT, c INT DEFAULT 0); +INSERT INTO t1 (a) VALUES (1), (2); +INSERT INTO t2 (b) VALUES (1), (2); +CREATE VIEW v1 AS SELECT t2.b,t2.c FROM t1, t2 + WHERE t1.a=t2.b AND t2.b < 3 WITH CHECK OPTION; +SELECT * FROM v1; +UPDATE v1 SET c=1 WHERE b=1; +SELECT * FROM v1; +DROP VIEW v1; +DROP TABLE t1,t2; + # # Bug #28561: update on multi-table view with CHECK OPTION and # a subquery in WHERE condition @@ -3252,4 +3268,56 @@ UPDATE v1 SET c=1; DROP VIEW v1; DROP TABLE t1,t2; +# +# Bug #27827: CHECK OPTION ignores ON conditions when updating +# a multi-table view with CHECK OPTION. +# + +CREATE TABLE t1 (a1 INT, c INT DEFAULT 0); +CREATE TABLE t2 (a2 INT); +CREATE TABLE t3 (a3 INT); +CREATE TABLE t4 (a4 INT); +INSERT INTO t1 (a1) VALUES (1),(2); +INSERT INTO t2 (a2) VALUES (1),(2); +INSERT INTO t3 (a3) VALUES (1),(2); +INSERT INTO t4 (a4) VALUES (1),(2); + +CREATE VIEW v1 AS + SELECT t1.a1, t1.c FROM t1 JOIN t2 ON t1.a1=t2.a2 AND t1.c < 3 + WITH CHECK OPTION; +SELECT * FROM v1; +--error 1369 +UPDATE v1 SET c=3; +PREPARE t FROM 'UPDATE v1 SET c=3'; +--error 1369 +EXECUTE t; +--error 1369 +EXECUTE t; +--error 1369 +INSERT INTO v1(a1, c) VALUES (3, 3); +UPDATE v1 SET c=1 WHERE a1=1; +SELECT * FROM v1; +SELECT * FROM t1; + +CREATE VIEW v2 AS SELECT t1.a1, t1.c + FROM (t1 JOIN t2 ON t1.a1=t2.a2 AND t1.c < 3) + JOIN (t3 JOIN t4 ON t3.a3=t4.a4) + ON t2.a2=t3.a3 WITH CHECK OPTION; +SELECT * FROM v2; +--error 1369 +UPDATE v2 SET c=3; +PREPARE t FROM 'UPDATE v2 SET c=3'; +--error 1369 +EXECUTE t; +--error 1369 +EXECUTE t; +--error 1369 +INSERT INTO v2(a1, c) VALUES (3, 3); +UPDATE v2 SET c=2 WHERE a1=1; +SELECT * FROM v2; +SELECT * FROM t1; + +DROP VIEW v1,v2; +DROP TABLE t1,t2,t3,t4; + --echo End of 5.0 tests. diff --git a/sql/field.cc b/sql/field.cc index 8186659ae89..8ff615ee798 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7643,6 +7643,8 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) tmp=0; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); } + if (!table->in_use->count_cuted_fields) + err= 0; } else set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); diff --git a/sql/field.h b/sql/field.h index 997ae1f2cd4..37ce6b88453 100644 --- a/sql/field.h +++ b/sql/field.h @@ -675,7 +675,7 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return 4; } void sql_type(String &str) const; - uint32 max_display_length() { return 11; } + uint32 max_display_length() { return MY_INT32_NUM_DECIMAL_DIGITS; } }; diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 5c74ea9e49f..410db357510 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -177,8 +177,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions) } if (current_thd->count_cuted_fields == CHECK_FIELD_WARN) { - field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARN_NULL_TO_NOTNULL, 1); + field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1); return 0; } if (!current_thd->no_errors) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 0de9ef3e9ad..06c825334c2 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -766,7 +766,12 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, { value= item->val_int(); *is_null= item->null_value; - if (item->field_type() == MYSQL_TYPE_DATE) + /* + Item_date_add_interval may return MYSQL_TYPE_STRING as the result + field type. To detect that the DATE value has been returned we + compare it with 1000000L - any DATE value should be less than it. + */ + if (item->field_type() == MYSQL_TYPE_DATE || value < 100000000L) value*= 1000000L; } else diff --git a/sql/item_func.cc b/sql/item_func.cc index 34f3c2c6add..95ff432ca5a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -996,6 +996,8 @@ longlong Item_func_unsigned::val_int() my_decimal tmp, *dec= args[0]->val_decimal(&tmp); if (!(null_value= args[0]->null_value)) my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value); + else + value= 0; return value; } else if (args[0]->cast_to_int_type() != STRING_RESULT || @@ -4288,9 +4290,11 @@ void Item_func_set_user_var::make_field(Send_field *tmp_field) TRUE Error */ -int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions) +int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions, + bool can_use_result_field) { - bool use_result_field= (result_field && result_field != field); + bool use_result_field= (!can_use_result_field ? 0 : + (result_field && result_field != field)); int error; /* Update the value of the user variable */ @@ -5213,10 +5217,11 @@ Item_func_sp::func_name() const { THD *thd= current_thd; /* Calculate length to avoid reallocation of string for sure */ - uint len= ((m_name->m_explicit_name ? m_name->m_db.length : 0 + + uint len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) + m_name->m_name.length)*2 + //characters*quoting 2 + // ` and ` - 1 + // . + (m_name->m_explicit_name ? + 3 : 0) + // '`', '`' and '.' for the db 1 + // end of string ALIGN_SIZE(1)); // to avoid String reallocation String qname((char *)alloc_root(thd->mem_root, len), len, diff --git a/sql/item_func.h b/sql/item_func.h index 1cffe9a934e..18cd87d2de4 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1220,7 +1220,13 @@ public: void print(String *str); void print_as_stmt(String *str); const char *func_name() const { return "set_user_var"; } - int save_in_field(Field *field, bool no_conversions); + int save_in_field(Field *field, bool no_conversions, + bool can_use_result_field); + int save_in_field(Field *field, bool no_conversions) + { + return save_in_field(field, no_conversions, 1); + } + void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); } }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index f5895369a55..9aabd068d25 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2180,27 +2180,6 @@ bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, uint fuzzy_date) default: goto null_date; } - - /* Adjust cached_field_type according to the detected type. */ - if (cached_field_type == MYSQL_TYPE_STRING) - { - switch (ltime->time_type) - { - case MYSQL_TIMESTAMP_DATE: - cached_field_type= MYSQL_TYPE_DATE; - break; - case MYSQL_TIMESTAMP_DATETIME: - cached_field_type= MYSQL_TYPE_DATETIME; - break; - case MYSQL_TIMESTAMP_TIME: - cached_field_type= MYSQL_TYPE_TIME; - break; - default: - /* Shouldn't get here. */ - DBUG_ASSERT(0); - break; - } - } return 0; // Ok invalid_date: diff --git a/sql/sql_class.h b/sql/sql_class.h index bef679806d0..90c959a1922 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2283,6 +2283,11 @@ class multi_update :public select_result_interceptor List *fields, *values; List **fields_for_table, **values_for_table; uint table_count; + /* + List of tables referenced in the CHECK OPTION condition of + the updated view excluding the updated table. + */ + List unupdated_check_opt_tables; Copy_field *copy_field; enum enum_duplicates handle_duplicates; bool do_update, trans_safe; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 57dff4b23a5..78d213a45c4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -49,15 +49,15 @@ static int sort_keyuse(KEYUSE *a,KEYUSE *b); static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key); static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, table_map used_tables); -static void choose_plan(JOIN *join,table_map join_tables); +static bool choose_plan(JOIN *join,table_map join_tables); static void best_access_path(JOIN *join, JOIN_TAB *s, THD *thd, table_map remaining_tables, uint idx, double record_count, double read_time); static void optimize_straight_join(JOIN *join, table_map join_tables); -static void greedy_search(JOIN *join, table_map remaining_tables, +static bool greedy_search(JOIN *join, table_map remaining_tables, uint depth, uint prune_level); -static void best_extension_by_limited_search(JOIN *join, +static bool best_extension_by_limited_search(JOIN *join, table_map remaining_tables, uint idx, double record_count, double read_time, uint depth, @@ -69,7 +69,7 @@ static int join_tab_cmp_straight(const void* ptr1, const void* ptr2); TODO: 'find_best' is here only temporarily until 'greedy_search' is tested and approved. */ -static void find_best(JOIN *join,table_map rest_tables,uint index, +static bool find_best(JOIN *join,table_map rest_tables,uint index, double record_count,double read_time); static uint cache_record_length(JOIN *join,uint index); static double prev_record_reads(JOIN *join,table_map found_ref); @@ -2717,7 +2717,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if (join->const_tables != join->tables) { optimize_keyuse(join, keyuse_array); - choose_plan(join, all_table_map & ~join->const_table_map); + if (choose_plan(join, all_table_map & ~join->const_table_map)) + DBUG_RETURN(TRUE); } else { @@ -4307,11 +4308,12 @@ best_access_path(JOIN *join, the array 'join->best_positions', and the cost of the plan in 'join->best_read'. - RETURN - None + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool choose_plan(JOIN *join, table_map join_tables) { uint search_depth= join->thd->variables.optimizer_search_depth; @@ -4344,14 +4346,16 @@ choose_plan(JOIN *join, table_map join_tables) the greedy version. Will be removed when greedy_search is approved. */ join->best_read= DBL_MAX; - find_best(join, join_tables, join->const_tables, 1.0, 0.0); + if (find_best(join, join_tables, join->const_tables, 1.0, 0.0)) + DBUG_RETURN(TRUE); } else { if (search_depth == 0) /* Automatically determine a reasonable value for 'search_depth' */ search_depth= determine_search_depth(join); - greedy_search(join, join_tables, search_depth, prune_level); + if (greedy_search(join, join_tables, search_depth, prune_level)) + DBUG_RETURN(TRUE); } } @@ -4361,7 +4365,7 @@ choose_plan(JOIN *join, table_map join_tables) */ if (join->thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS) join->thd->status_var.last_query_cost= join->best_read; - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -4589,11 +4593,12 @@ optimize_straight_join(JOIN *join, table_map join_tables) In the future, 'greedy_search' might be extended to support other implementations of 'best_extension', e.g. some simpler quadratic procedure. - RETURN - None + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool greedy_search(JOIN *join, table_map remaining_tables, uint search_depth, @@ -4615,8 +4620,9 @@ greedy_search(JOIN *join, do { /* Find the extension of the current QEP with the lowest cost */ join->best_read= DBL_MAX; - best_extension_by_limited_search(join, remaining_tables, idx, record_count, - read_time, search_depth, prune_level); + if (best_extension_by_limited_search(join, remaining_tables, idx, record_count, + read_time, search_depth, prune_level)) + DBUG_RETURN(TRUE); if (size_remain <= search_depth) { @@ -4627,7 +4633,7 @@ greedy_search(JOIN *join, DBUG_EXECUTE("opt", print_plan(join, join->tables, record_count, read_time, read_time, "optimal");); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } /* select the first table in the optimal extension as most promising */ @@ -4772,11 +4778,12 @@ greedy_search(JOIN *join, The parameter 'search_depth' provides control over the recursion depth, and thus the size of the resulting optimal plan. - RETURN - None + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool best_extension_by_limited_search(JOIN *join, table_map remaining_tables, uint idx, @@ -4785,11 +4792,11 @@ best_extension_by_limited_search(JOIN *join, uint search_depth, uint prune_level) { + DBUG_ENTER("best_extension_by_limited_search"); + THD *thd= join->thd; if (thd->killed) // Abort - return; - - DBUG_ENTER("best_extension_by_limited_search"); + DBUG_RETURN(TRUE); /* 'join' is a partial plan with lower cost than the best plan so far, @@ -4869,15 +4876,14 @@ best_extension_by_limited_search(JOIN *join, if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) ) { /* Recursively expand the current partial plan */ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); - best_extension_by_limited_search(join, - remaining_tables & ~real_table_bit, - idx + 1, - current_record_count, - current_read_time, - search_depth - 1, - prune_level); - if (thd->killed) - DBUG_VOID_RETURN; + if (best_extension_by_limited_search(join, + remaining_tables & ~real_table_bit, + idx + 1, + current_record_count, + current_read_time, + search_depth - 1, + prune_level)) + DBUG_RETURN(TRUE); swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); } else @@ -4906,19 +4912,26 @@ best_extension_by_limited_search(JOIN *join, restore_prev_nj_state(s); } } - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } /* TODO: this function is here only temporarily until 'greedy_search' is tested and accepted. + + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, double read_time) { + DBUG_ENTER("find_best"); THD *thd= join->thd; + if (thd->killed) + DBUG_RETURN(TRUE); if (!rest_tables) { DBUG_PRINT("best",("read_time: %g record_count: %g",read_time, @@ -4935,10 +4948,10 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, sizeof(POSITION)*idx); join->best_read= read_time - 0.001; } - return; + DBUG_RETURN(FALSE); } if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read) - return; /* Found better before */ + DBUG_RETURN(FALSE); /* Found better before */ JOIN_TAB *s; double best_record_count=DBL_MAX,best_read_time=DBL_MAX; @@ -4971,10 +4984,9 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, best_read_time=current_read_time; } swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); - find_best(join,rest_tables & ~real_table_bit,idx+1, - current_record_count,current_read_time); - if (thd->killed) - return; + if (find_best(join,rest_tables & ~real_table_bit,idx+1, + current_record_count,current_read_time)) + DBUG_RETURN(TRUE); swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); } restore_prev_nj_state(s); @@ -4982,6 +4994,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, break; // Don't test all combinations } } + DBUG_RETURN(FALSE); } @@ -8869,8 +8882,13 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, item->name, table, item->decimals, TRUE); break; case INT_RESULT: - /* Select an integer type with the minimal fit precision */ - if (item->max_length > MY_INT32_NUM_DECIMAL_DIGITS) + /* + Select an integer type with the minimal fit precision. + MY_INT32_NUM_DECIMAL_DIGITS is sign inclusive, don't consider the sign. + Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into + Field_long : make them Field_longlong. + */ + if (item->max_length >= (MY_INT32_NUM_DECIMAL_DIGITS - 1)) new_field=new Field_longlong(item->max_length, maybe_null, item->name, table, item->unsigned_flag); else diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 222e33345cc..314f67c79c5 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -970,6 +970,7 @@ int multi_update::prepare(List ¬_used_values, List_iterator_fast field_it(*fields); List_iterator_fast value_it(*values); uint i, max_fields; + uint leaf_table_count= 0; DBUG_ENTER("multi_update::prepare"); thd->count_cuted_fields= CHECK_FIELD_WARN; @@ -1003,6 +1004,7 @@ int multi_update::prepare(List ¬_used_values, { /* TODO: add support of view of join support */ TABLE *table=table_ref->table; + leaf_table_count++; if (tables_to_update & table->map) { TABLE_LIST *tl= (TABLE_LIST*) thd->memdup((char*) table_ref, @@ -1067,7 +1069,7 @@ int multi_update::prepare(List ¬_used_values, /* Allocate copy fields */ max_fields=0; for (i=0 ; i < table_count ; i++) - set_if_bigger(max_fields, fields_for_table[i]->elements); + set_if_bigger(max_fields, fields_for_table[i]->elements + leaf_table_count); copy_field= new Copy_field[max_fields]; DBUG_RETURN(thd->is_fatal_error != 0); } @@ -1160,13 +1162,22 @@ multi_update::initialize_tables(JOIN *join) trans_safe= transactional_tables= main_table->file->has_transactions(); table_to_update= 0; + /* Any update has at least one pair (field, value) */ + DBUG_ASSERT(fields->elements); + /* + Only one table may be modified by UPDATE of an updatable view. + For an updatable view first_table_for_update indicates this + table. + For a regular multi-update it refers to some updated table. + */ + TABLE *first_table_for_update= ((Item_field *) fields->head())->field->table; + /* Create a temporary table for keys to all tables, except main table */ for (table_ref= update_tables; table_ref; table_ref= table_ref->next_local) { TABLE *table=table_ref->table; uint cnt= table_ref->shared; - Item_field *ifield; - List temp_fields= *fields_for_table[cnt]; + List temp_fields; ORDER group; if (ignore) @@ -1174,34 +1185,63 @@ multi_update::initialize_tables(JOIN *join) if (table == main_table) // First table in join { if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables, - &temp_fields)) + fields_for_table[cnt])) { table_to_update= main_table; // Update table on the fly continue; } } + if (table == first_table_for_update && table_ref->check_option) + { + table_map unupdated_tables= table_ref->check_option->used_tables() & + ~first_table_for_update->map; + for (TABLE_LIST *tbl_ref =leaves; + unupdated_tables && tbl_ref; + tbl_ref= tbl_ref->next_leaf) + { + if (unupdated_tables & tbl_ref->table->map) + unupdated_tables&= ~tbl_ref->table->map; + else + continue; + if (unupdated_check_opt_tables.push_back(tbl_ref->table)) + DBUG_RETURN(1); + } + } + TMP_TABLE_PARAM *tmp_param= tmp_table_param+cnt; /* Create a temporary table to store all fields that are changed for this table. The first field in the temporary table is a pointer to the - original row so that we can find and update it + original row so that we can find and update it. For the updatable + VIEW a few following fields are rowids of tables used in the CHECK + OPTION condition. */ - /* ok to be on stack as this is not referenced outside of this func */ - Field_string offset(table->file->ref_length, 0, "offset", - table, &my_charset_bin); - /* - The field will be converted to varstring when creating tmp table if - table to be updated was created by mysql 4.1. Deny this. - */ - offset.can_alter_field_type= 0; - if (!(ifield= new Item_field(((Field *) &offset)))) - DBUG_RETURN(1); - ifield->maybe_null= 0; - if (temp_fields.push_front(ifield)) - DBUG_RETURN(1); + List_iterator_fast
tbl_it(unupdated_check_opt_tables); + TABLE *tbl= table; + do + { + Field_string *field= new Field_string(tbl->file->ref_length, 0, + tbl->alias, + tbl, &my_charset_bin); + if (!field) + DBUG_RETURN(1); + /* + The field will be converted to varstring when creating tmp table if + table to be updated was created by mysql 4.1. Deny this. + */ + field->can_alter_field_type= 0; + Item_field *ifield= new Item_field((Field *) field); + if (!ifield) + DBUG_RETURN(1); + ifield->maybe_null= 0; + if (temp_fields.push_back(ifield)) + DBUG_RETURN(1); + } while ((tbl= tbl_it++)); + + temp_fields.concat(fields_for_table[cnt]); /* Make an unique key over the first field to avoid duplicated updates */ bzero((char*) &group, sizeof(group)); @@ -1350,10 +1390,26 @@ bool multi_update::send_data(List ¬_used_values) { int error; TABLE *tmp_table= tmp_tables[offset]; - fill_record(thd, tmp_table->field+1, *values_for_table[offset], 1); - /* Store pointer to row */ - memcpy((char*) tmp_table->field[0]->ptr, - (char*) table->file->ref, table->file->ref_length); + /* Store regular updated fields in the row. */ + fill_record(thd, + tmp_table->field + 1 + unupdated_check_opt_tables.elements, + *values_for_table[offset], 1); + /* + For updatable VIEW store rowid of the updated table and + rowids of tables used in the CHECK OPTION condition. + */ + uint field_num= 0; + List_iterator_fast
tbl_it(unupdated_check_opt_tables); + TABLE *tbl= table; + do + { + if (tbl != table) + tbl->file->position(tbl->record[0]); + memcpy((char*) tmp_table->field[field_num]->ptr, + (char*) tbl->file->ref, tbl->file->ref_length); + field_num++; + } while ((tbl= tbl_it++)); + /* Write row, ignoring duplicated updates to a row */ error= tmp_table->file->write_row(tmp_table->record[0]); if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE) @@ -1403,9 +1459,10 @@ void multi_update::send_error(uint errcode,const char *err) int multi_update::do_updates(bool from_send_error) { TABLE_LIST *cur_table; - int local_error; + int local_error= 0; ha_rows org_updated; TABLE *table, *tmp_table; + List_iterator_fast
check_opt_it(unupdated_check_opt_tables); DBUG_ENTER("do_updates"); do_update= 0; // Don't retry this function @@ -1413,8 +1470,8 @@ int multi_update::do_updates(bool from_send_error) DBUG_RETURN(0); for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local) { - byte *ref_pos; bool can_compare_record; + uint offset= cur_table->shared; table = cur_table->table; if (table == table_to_update) @@ -1425,11 +1482,20 @@ int multi_update::do_updates(bool from_send_error) (void) table->file->ha_rnd_init(0); table->file->extra(HA_EXTRA_NO_CACHE); + check_opt_it.rewind(); + while(TABLE *tbl= check_opt_it++) + { + if (tbl->file->ha_rnd_init(1)) + goto err; + tbl->file->extra(HA_EXTRA_CACHE); + } + /* Setup copy functions to copy fields from temporary table */ - List_iterator_fast field_it(*fields_for_table[cur_table->shared]); - Field **field= tmp_table->field+1; // Skip row pointer + List_iterator_fast field_it(*fields_for_table[offset]); + Field **field= tmp_table->field + + 1 + unupdated_check_opt_tables.elements; // Skip row pointers Copy_field *copy_field_ptr= copy_field, *copy_field_end; for ( ; *field ; field++) { @@ -1444,7 +1510,6 @@ int multi_update::do_updates(bool from_send_error) can_compare_record= !(table->file->table_flags() & HA_PARTIAL_COLUMN_READ); - ref_pos= (byte*) tmp_table->field[0]->ptr; for (;;) { if (thd->killed && trans_safe) @@ -1457,8 +1522,20 @@ int multi_update::do_updates(bool from_send_error) continue; // May happen on dup key goto err; } - if ((local_error= table->file->rnd_pos(table->record[0], ref_pos))) - goto err; + + /* call rnd_pos() using rowids from temporary table */ + check_opt_it.rewind(); + TABLE *tbl= table; + uint field_num= 0; + do + { + if((local_error= + tbl->file->rnd_pos(tbl->record[0], + (byte *) tmp_table->field[field_num]->ptr))) + goto err; + field_num++; + } while((tbl= check_opt_it++)); + table->status|= STATUS_UPDATED; store_record(table,record[1]); @@ -1508,6 +1585,10 @@ int multi_update::do_updates(bool from_send_error) } (void) table->file->ha_rnd_end(); (void) tmp_table->file->ha_rnd_end(); + check_opt_it.rewind(); + while (TABLE *tbl= check_opt_it++) + tbl->file->ha_rnd_end(); + } DBUG_RETURN(0); @@ -1521,6 +1602,9 @@ err: err2: (void) table->file->ha_rnd_end(); (void) tmp_table->file->ha_rnd_end(); + check_opt_it.rewind(); + while (TABLE *tbl= check_opt_it++) + tbl->file->ha_rnd_end(); if (updated != org_updated) { diff --git a/sql/sql_view.cc b/sql/sql_view.cc index ba367040b36..0fb4d3aaea8 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -692,6 +692,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, bool can_be_merged; char dir_buff[FN_REFLEN], file_buff[FN_REFLEN]; LEX_STRING dir, file; + int error= 0; DBUG_ENTER("mysql_register_view"); /* print query */ @@ -702,80 +703,16 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, lex->unit.print(&str); thd->variables.sql_mode|= sql_mode; } - str.append('\0'); DBUG_PRINT("info", ("View: %s", str.ptr())); - /* print file name */ - (void) my_snprintf(dir_buff, FN_REFLEN, "%s/%s/", - mysql_data_home, view->db); - unpack_filename(dir_buff, dir_buff); - dir.str= dir_buff; - dir.length= strlen(dir_buff); - - file.str= file_buff; - file.length= (strxnmov(file_buff, FN_REFLEN, view->table_name, reg_ext, - NullS) - file_buff); - /* init timestamp */ - if (!view->timestamp.str) - view->timestamp.str= view->timestamp_buffer; - - /* check old .frm */ - { - char path_buff[FN_REFLEN]; - LEX_STRING path; - File_parser *parser; - - path.str= path_buff; - fn_format(path_buff, file.str, dir.str, 0, MY_UNPACK_FILENAME); - path.length= strlen(path_buff); - - if (!access(path.str, F_OK)) - { - if (mode == VIEW_CREATE_NEW) - { - my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias); - DBUG_RETURN(-1); - } - - if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0))) - DBUG_RETURN(1); - - if (!parser->ok() || !is_equal(&view_type, parser->type())) - { - my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW"); - DBUG_RETURN(-1); - } - - /* - read revision number - - TODO: read dependence list, too, to process cascade/restrict - TODO: special cascade/restrict procedure for alter? - */ - if (parser->parse((gptr)view, thd->mem_root, - view_parameters + revision_number_position, 1, - &file_parser_dummy_hook)) - { - DBUG_RETURN(thd->net.report_error? -1 : 0); - } - } - else - { - if (mode == VIEW_ALTER) - { - my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias); - DBUG_RETURN(-1); - } - } - } /* fill structure */ - view->query.str= (char*)str.ptr(); - view->query.length= str.length()-1; // we do not need last \0 + view->query.str= str.c_ptr_safe(); + view->query.length= str.length(); view->source.str= thd->query + thd->lex->create_view_select_start; - view->source.length= (char *)skip_rear_comments((char *)view->source.str, - (char *)thd->query + - thd->query_length) - - view->source.str; + view->source.length= skip_rear_comments((char *)view->source.str, + (char *)thd->query + + thd->query_length) - + view->source.str; view->file_version= 1; view->calc_md5(md5); view->md5.str= md5; @@ -817,6 +754,76 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, } } loop_out: + /* print file name */ + (void) my_snprintf(dir_buff, FN_REFLEN, "%s/%s/", + mysql_data_home, view->db); + unpack_filename(dir_buff, dir_buff); + dir.str= dir_buff; + dir.length= strlen(dir_buff); + + file.str= file_buff; + file.length= (strxnmov(file_buff, FN_REFLEN, view->table_name, reg_ext, + NullS) - file_buff); + /* init timestamp */ + if (!view->timestamp.str) + view->timestamp.str= view->timestamp_buffer; + + /* check old .frm */ + { + char path_buff[FN_REFLEN]; + LEX_STRING path; + File_parser *parser; + + path.str= path_buff; + fn_format(path_buff, file.str, dir.str, 0, MY_UNPACK_FILENAME); + path.length= strlen(path_buff); + + if (!access(path.str, F_OK)) + { + if (mode == VIEW_CREATE_NEW) + { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias); + error= -1; + goto err; + } + + if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0))) + { + error= 1; + goto err; + } + + if (!parser->ok() || !is_equal(&view_type, parser->type())) + { + my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW"); + error= -1; + goto err; + } + + /* + read revision number + + TODO: read dependence list, too, to process cascade/restrict + TODO: special cascade/restrict procedure for alter? + */ + if (parser->parse((gptr)view, thd->mem_root, + view_parameters + revision_number_position, 1, + &file_parser_dummy_hook)) + { + error= thd->net.report_error? -1 : 0; + goto err; + } + } + else + { + if (mode == VIEW_ALTER) + { + my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias); + error= -1; + goto err; + } + } + } /* Check that table of main select do not used in subqueries. @@ -841,15 +848,23 @@ loop_out: !view->updatable_view) { my_error(ER_VIEW_NONUPD_CHECK, MYF(0), view->db, view->table_name); - DBUG_RETURN(-1); + error= -1; + goto err; } if (sql_create_definition_file(&dir, &file, view_file_type, (gptr)view, view_parameters, num_view_backups)) { - DBUG_RETURN(thd->net.report_error? -1 : 1); + error= thd->net.report_error? -1 : 1; + goto err; } DBUG_RETURN(0); +err: + view->query.str= NULL; + view->query.length= 0; + view->md5.str= NULL; + view->md5.length= 0; + DBUG_RETURN(error); } diff --git a/sql/table.cc b/sql/table.cc index fb2012a79d1..9868aa9b9c1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1985,6 +1985,47 @@ bool st_table_list::prep_where(THD *thd, Item **conds, } +/* + Merge ON expressions for a view + + SYNOPSIS + merge_on_conds() + thd thread handle + table table for the VIEW + is_cascaded TRUE <=> merge ON expressions from underlying views + + DESCRIPTION + This function returns the result of ANDing the ON expressions + of the given view and all underlying views. The ON expressions + of the underlying views are added only if is_cascaded is TRUE. + + RETURN + Pointer to the built expression if there is any. + Otherwise and in the case of a failure NULL is returned. +*/ + +static Item * +merge_on_conds(THD *thd, TABLE_LIST *table, bool is_cascaded) +{ + DBUG_ENTER("merge_on_conds"); + + Item *cond= NULL; + DBUG_PRINT("info", ("alias: %s", table->alias)); + if (table->on_expr) + cond= table->on_expr->copy_andor_structure(thd); + if (!table->nested_join) + DBUG_RETURN(cond); + List_iterator li(table->nested_join->join_list); + while (TABLE_LIST *tbl= li++) + { + if (tbl->view && !is_cascaded) + continue; + cond= and_conds(cond, merge_on_conds(thd, tbl, is_cascaded)); + } + DBUG_RETURN(cond); +} + + /* Prepare check option expression of table @@ -2001,8 +2042,8 @@ bool st_table_list::prep_where(THD *thd, Item **conds, VIEW_CHECK_LOCAL option. NOTE - This method build check options for every call - (usual execution or every SP/PS call) + This method builds check option condition to use it later on + every call (usual execution or every SP/PS call). This method have to be called after WHERE preparation (st_table_list::prep_where) @@ -2014,38 +2055,42 @@ bool st_table_list::prep_where(THD *thd, Item **conds, bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type) { DBUG_ENTER("st_table_list::prep_check_option"); + bool is_cascaded= check_opt_type == VIEW_CHECK_CASCADED; for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { /* see comment of check_opt_type parameter */ - if (tbl->view && - tbl->prep_check_option(thd, - ((check_opt_type == VIEW_CHECK_CASCADED) ? - VIEW_CHECK_CASCADED : - VIEW_CHECK_NONE))) - { + if (tbl->view && tbl->prep_check_option(thd, (is_cascaded ? + VIEW_CHECK_CASCADED : + VIEW_CHECK_NONE))) DBUG_RETURN(TRUE); - } } - if (check_opt_type) + if (check_opt_type && !check_option_processed) { - Item *item= 0; + Query_arena *arena= thd->stmt_arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test + if (where) { DBUG_ASSERT(where->fixed); - item= where->copy_andor_structure(thd); + check_option= where->copy_andor_structure(thd); } - if (check_opt_type == VIEW_CHECK_CASCADED) + if (is_cascaded) { for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { if (tbl->check_option) - item= and_conds(item, tbl->check_option); + check_option= and_conds(check_option, tbl->check_option); } } - if (item) - thd->change_item_tree(&check_option, item); + check_option= and_conds(check_option, + merge_on_conds(thd, this, is_cascaded)); + + if (arena) + thd->restore_active_arena(arena, &backup); + check_option_processed= TRUE; + } if (check_option) @@ -2150,7 +2195,7 @@ void st_table_list::cleanup_items() check CHECK OPTION condition SYNOPSIS - check_option() + st_table_list::view_check_option() ignore_failure ignore check option fail RETURN diff --git a/sql/table.h b/sql/table.h index 952b575c00e..d4dc3e8c0b8 100644 --- a/sql/table.h +++ b/sql/table.h @@ -685,6 +685,8 @@ typedef struct st_table_list bool compact_view_format; /* Use compact format for SHOW CREATE VIEW */ /* view where processed */ bool where_processed; + /* TRUE <=> VIEW CHECK OPTION expression has been processed */ + bool check_option_processed; /* FRMTYPE_ERROR if any type is acceptable */ enum frm_type_enum required_type; char timestamp_buffer[20]; /* buffer for timestamp (19+1) */