Commit a858d8e8 authored by unknown's avatar unknown

Merge weblab.(none):/home/marcsql/TREE/mysql-5.0-base

into  weblab.(none):/home/marcsql/TREE/mysql-5.0-rt-merge


sql/item_cmpfunc.cc:
  Auto merged
sql/item_cmpfunc.h:
  Auto merged
sql/item_subselect.cc:
  Auto merged
sql/item_subselect.h:
  Auto merged
sql/sql_lex.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
parents 9d66be72 a475ed7c
...@@ -128,3 +128,6 @@ f1 f2 if(f1, 40.0, 5.00) ...@@ -128,3 +128,6 @@ f1 f2 if(f1, 40.0, 5.00)
0 0 5.00 0 0 5.00
1 1 40.00 1 1 40.00
drop table t1; drop table t1;
select if(0, 18446744073709551610, 18446744073709551610);
if(0, 18446744073709551610, 18446744073709551610)
18446744073709551610
...@@ -431,17 +431,17 @@ SELECT HEX(v10); ...@@ -431,17 +431,17 @@ SELECT HEX(v10);
END| END|
CALL p1(); CALL p1();
HEX(v1) HEX(v1)
01 1
HEX(v2) HEX(v2)
00 0
HEX(v3) HEX(v3)
05 5
HEX(v4) HEX(v4)
5555555555555555 5555555555555555
HEX(v5) HEX(v5)
07 7
HEX(v6) HEX(v6)
0000000000000005 5
HEX(v7) HEX(v7)
80 80
HEX(v8) HEX(v8)
...@@ -748,12 +748,60 @@ HEX(b) b = 0 b = FALSE b IS FALSE b = 1 b = TRUE b IS TRUE ...@@ -748,12 +748,60 @@ HEX(b) b = 0 b = FALSE b IS FALSE b = 1 b = TRUE b IS TRUE
1 0 0 0 1 1 1 1 0 0 0 1 1 1
call p2(); call p2();
HEX(vb) vb = 0 vb = FALSE vb IS FALSE vb = 1 vb = TRUE vb IS TRUE HEX(vb) vb = 0 vb = FALSE vb IS FALSE vb = 1 vb = TRUE vb IS TRUE
00 1 1 1 0 0 0 0 1 1 1 0 0 0
HEX(vb) vb = 0 vb = FALSE vb IS FALSE vb = 1 vb = TRUE vb IS TRUE HEX(vb) vb = 0 vb = FALSE vb IS FALSE vb = 1 vb = TRUE vb IS TRUE
01 0 0 1 1 1 0 1 0 0 0 1 1 1
DROP TABLE t1; DROP TABLE t1;
DROP PROCEDURE p1; DROP PROCEDURE p1;
DROP PROCEDURE p2; DROP PROCEDURE p2;
DROP TABLE IF EXISTS table_12976_a;
DROP TABLE IF EXISTS table_12976_b;
DROP PROCEDURE IF EXISTS proc_12976_a;
DROP PROCEDURE IF EXISTS proc_12976_b;
CREATE TABLE table_12976_a (val bit(1));
CREATE TABLE table_12976_b(
appname varchar(15),
emailperm bit not null default 1,
phoneperm bit not null default 0);
insert into table_12976_b values ('A', b'1', b'1'), ('B', b'0', b'0');
CREATE PROCEDURE proc_12976_a()
BEGIN
declare localvar bit(1);
SELECT val INTO localvar FROM table_12976_a;
SELECT coalesce(localvar, 1)+1, coalesce(val, 1)+1 FROM table_12976_a;
END||
CREATE PROCEDURE proc_12976_b(
name varchar(15),
out ep bit,
out msg varchar(10))
BEGIN
SELECT emailperm into ep FROM table_12976_b where (appname = name);
IF ep is true THEN
SET msg = 'True';
ELSE
SET msg = 'False';
END IF;
END||
INSERT table_12976_a VALUES (0);
call proc_12976_a();
coalesce(localvar, 1)+1 coalesce(val, 1)+1
1 1
UPDATE table_12976_a set val=1;
call proc_12976_a();
coalesce(localvar, 1)+1 coalesce(val, 1)+1
2 2
call proc_12976_b('A', @ep, @msg);
select @ep, @msg;
@ep @msg
1 True
call proc_12976_b('B', @ep, @msg);
select @ep, @msg;
@ep @msg
0 False
DROP TABLE table_12976_a;
DROP TABLE table_12976_b;
DROP PROCEDURE proc_12976_a;
DROP PROCEDURE proc_12976_b;
--------------------------------------------------------------- ---------------------------------------------------------------
BUG#9572 BUG#9572
......
This diff is collapsed.
...@@ -2543,7 +2543,7 @@ create table t1(f1 int, f2 int); ...@@ -2543,7 +2543,7 @@ create table t1(f1 int, f2 int);
create view v1 as select ta.f1 as a, tb.f1 as b from t1 ta, t1 tb where ta.f1=tb create view v1 as select ta.f1 as a, tb.f1 as b from t1 ta, t1 tb where ta.f1=tb
.f1 and ta.f2=tb.f2; .f1 and ta.f2=tb.f2;
insert into t1 values(1,1),(2,2); insert into t1 values(1,1),(2,2);
create view v2 as select * from v1 where a > 1 with local check option; create view v2 as select * from v1 where a > 1 with check option;
select * from v2; select * from v2;
a b a b
2 2 2 2
...@@ -3014,17 +3014,6 @@ i j ...@@ -3014,17 +3014,6 @@ i j
6 3 6 3
DROP VIEW v1, v2; DROP VIEW v1, v2;
DROP TABLE t1; DROP TABLE t1;
CREATE VIEW v AS SELECT !0 * 5 AS x FROM DUAL;
SHOW CREATE VIEW v;
View Create View
v CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` AS select ((not(0)) * 5) AS `x`
SELECT !0 * 5 AS x FROM DUAL;
x
5
SELECT * FROM v;
x
5
DROP VIEW v;
DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1;
CREATE VIEW v1 AS SELECT 'The\ZEnd'; CREATE VIEW v1 AS SELECT 'The\ZEnd';
SELECT * FROM v1; SELECT * FROM v1;
...@@ -3034,105 +3023,139 @@ SHOW CREATE VIEW v1; ...@@ -3034,105 +3023,139 @@ SHOW CREATE VIEW v1;
View Create View View Create View
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select _latin1'The\ZEnd' AS `TheEnd` v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select _latin1'The\ZEnd' AS `TheEnd`
DROP VIEW v1; DROP VIEW v1;
CREATE TABLE t1 (mydate DATETIME); DROP VIEW IF EXISTS v1;
INSERT INTO t1 VALUES SELECT * FROM (SELECT 1) AS t;
('2007-01-01'), ('2007-01-02'), ('2007-01-30'), ('2007-01-31');
CREATE VIEW v1 AS SELECT mydate from t1;
SELECT * FROM t1 WHERE mydate BETWEEN '2007-01-01' AND '2007-01-31';
mydate
2007-01-01 00:00:00
2007-01-02 00:00:00
2007-01-30 00:00:00
2007-01-31 00:00:00
SELECT * FROM v1 WHERE mydate BETWEEN '2007-01-01' AND '2007-01-31';
mydate
2007-01-01 00:00:00
2007-01-02 00:00:00
2007-01-30 00:00:00
2007-01-31 00:00:00
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1 (a int);
CREATE TABLE t2 (b int);
INSERT INTO t1 VALUES (1), (2);
INSERT INTO t2 VALUES (1), (2);
CREATE VIEW v1 AS
SELECT t2.b FROM t1,t2 WHERE t1.a = t2.b WITH CHECK OPTION;
SELECT * FROM v1;
b
1 1
2
UPDATE v1 SET b=3;
ERROR HY000: CHECK OPTION failed 'test.v1'
SELECT * FROM v1;
b
1 1
2 CREATE VIEW v1 AS SELECT * FROM (SELECT 1) AS t;
SELECT * FROM t1; ERROR HY000: View's SELECT contains a subquery in the FROM clause
a # Previously the following would fail.
SELECT * FROM (SELECT 1) AS t;
1 1
2
SELECT * FROM t2;
b
1 1
2 drop view if exists view_24532_a;
DROP VIEW v1; drop view if exists view_24532_b;
DROP TABLE t1,t2; drop table if exists table_24532;
create table t1(f1 int, f2 int); create table table_24532 (
insert into t1 values(1,2),(1,3),(1,1),(2,3),(2,1),(2,2); a int,
select * from t1; b bigint,
f1 f2 c int(4),
1 2 d bigint(48)
1 3
1 1
2 3
2 1
2 2
create view v1 as select * from t1 order by f2;
select * from v1;
f1 f2
1 1
2 1
1 2
2 2
1 3
2 3
explain extended select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using filesort
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2` from `test`.`t1` order by `test`.`t1`.`f2`
select * from v1 order by f1;
f1 f2
1 1
1 2
1 3
2 1
2 2
2 3
explain extended select * from v1 order by f1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using filesort
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2` from `test`.`t1` order by `test`.`t1`.`f1`,`test`.`t1`.`f2`
drop view v1;
drop table t1;
CREATE TABLE t1 (
id int(11) NOT NULL PRIMARY KEY,
country varchar(32),
code int(11) default NULL
); );
INSERT INTO t1 VALUES create view view_24532_a as
(1,'ITALY',100),(2,'ITALY',200),(3,'FRANCE',100), (4,'ITALY',100); select
CREATE VIEW v1 AS SELECT * FROM t1; a IS TRUE,
SELECT code, COUNT(DISTINCT country) FROM t1 GROUP BY code ORDER BY MAX(id); a IS NOT TRUE,
code COUNT(DISTINCT country) a IS FALSE,
200 1 a IS NOT FALSE,
100 2 a IS UNKNOWN,
SELECT code, COUNT(DISTINCT country) FROM v1 GROUP BY code ORDER BY MAX(id); a IS NOT UNKNOWN,
code COUNT(DISTINCT country) a is NULL,
200 1 a IS NOT NULL,
100 2 ISNULL(a),
DROP VIEW v1; b IS TRUE,
DROP TABLE t1; b IS NOT TRUE,
b IS FALSE,
b IS NOT FALSE,
b IS UNKNOWN,
b IS NOT UNKNOWN,
b is NULL,
b IS NOT NULL,
ISNULL(b),
c IS TRUE,
c IS NOT TRUE,
c IS FALSE,
c IS NOT FALSE,
c IS UNKNOWN,
c IS NOT UNKNOWN,
c is NULL,
c IS NOT NULL,
ISNULL(c),
d IS TRUE,
d IS NOT TRUE,
d IS FALSE,
d IS NOT FALSE,
d IS UNKNOWN,
d IS NOT UNKNOWN,
d is NULL,
d IS NOT NULL,
ISNULL(d)
from table_24532;
describe view_24532_a;
Field Type Null Key Default Extra
a IS TRUE int(1) NO 0
a IS NOT TRUE int(1) NO 0
a IS FALSE int(1) NO 0
a IS NOT FALSE int(1) NO 0
a IS UNKNOWN int(1) NO 0
a IS NOT UNKNOWN int(1) NO 0
a is NULL int(1) NO 0
a IS NOT NULL int(1) NO 0
ISNULL(a) int(1) NO 0
b IS TRUE int(1) NO 0
b IS NOT TRUE int(1) NO 0
b IS FALSE int(1) NO 0
b IS NOT FALSE int(1) NO 0
b IS UNKNOWN int(1) NO 0
b IS NOT UNKNOWN int(1) NO 0
b is NULL int(1) NO 0
b IS NOT NULL int(1) NO 0
ISNULL(b) int(1) NO 0
c IS TRUE int(1) NO 0
c IS NOT TRUE int(1) NO 0
c IS FALSE int(1) NO 0
c IS NOT FALSE int(1) NO 0
c IS UNKNOWN int(1) NO 0
c IS NOT UNKNOWN int(1) NO 0
c is NULL int(1) NO 0
c IS NOT NULL int(1) NO 0
ISNULL(c) int(1) NO 0
d IS TRUE int(1) NO 0
d IS NOT TRUE int(1) NO 0
d IS FALSE int(1) NO 0
d IS NOT FALSE int(1) NO 0
d IS UNKNOWN int(1) NO 0
d IS NOT UNKNOWN int(1) NO 0
d is NULL int(1) NO 0
d IS NOT NULL int(1) NO 0
ISNULL(d) int(1) NO 0
create view view_24532_b as
select
a IS TRUE,
if(ifnull(a, 0), 1, 0) as old_istrue,
a IS NOT TRUE,
if(ifnull(a, 0), 0, 1) as old_isnottrue,
a IS FALSE,
if(ifnull(a, 1), 0, 1) as old_isfalse,
a IS NOT FALSE,
if(ifnull(a, 1), 1, 0) as old_isnotfalse
from table_24532;
describe view_24532_b;
Field Type Null Key Default Extra
a IS TRUE int(1) NO 0
old_istrue int(1) NO 0
a IS NOT TRUE int(1) NO 0
old_isnottrue int(1) NO 0
a IS FALSE int(1) NO 0
old_isfalse int(1) NO 0
a IS NOT FALSE int(1) NO 0
old_isnotfalse int(1) NO 0
show create view view_24532_b;
View Create View
view_24532_b CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `view_24532_b` AS select (`table_24532`.`a` is true) AS `a IS TRUE`,if(ifnull(`table_24532`.`a`,0),1,0) AS `old_istrue`,(`table_24532`.`a` is not true) AS `a IS NOT TRUE`,if(ifnull(`table_24532`.`a`,0),0,1) AS `old_isnottrue`,(`table_24532`.`a` is false) AS `a IS FALSE`,if(ifnull(`table_24532`.`a`,1),0,1) AS `old_isfalse`,(`table_24532`.`a` is not false) AS `a IS NOT FALSE`,if(ifnull(`table_24532`.`a`,1),1,0) AS `old_isnotfalse` from `table_24532`
insert into table_24532 values (0, 0, 0, 0);
select * from view_24532_b;
a IS TRUE old_istrue a IS NOT TRUE old_isnottrue a IS FALSE old_isfalse a IS NOT FALSE old_isnotfalse
0 0 1 1 1 1 0 0
update table_24532 set a=1;
select * from view_24532_b;
a IS TRUE old_istrue a IS NOT TRUE old_isnottrue a IS FALSE old_isfalse a IS NOT FALSE old_isnotfalse
1 1 0 0 0 0 1 1
update table_24532 set a=NULL;
select * from view_24532_b;
a IS TRUE old_istrue a IS NOT TRUE old_isnottrue a IS FALSE old_isfalse a IS NOT FALSE old_isnotfalse
0 0 1 1 0 0 1 1
drop view view_24532_a;
drop view view_24532_b;
drop table table_24532;
End of 5.0 tests. End of 5.0 tests.
...@@ -97,3 +97,14 @@ create table t1 (f1 int, f2 int); ...@@ -97,3 +97,14 @@ create table t1 (f1 int, f2 int);
insert into t1 values(1,1),(0,0); insert into t1 values(1,1),(0,0);
select f1, f2, if(f1, 40.0, 5.00) from t1 group by f1 order by f2; select f1, f2, if(f1, 40.0, 5.00) from t1 group by f1 order by f2;
drop table t1; drop table t1;
#
# Bug#24532 (The return data type of IS TRUE is different from similar
# operations)
#
# IF(x, unsigned, unsigned) should be unsigned.
#
select if(0, 18446744073709551610, 18446744073709551610);
...@@ -500,8 +500,6 @@ DROP PROCEDURE p1; ...@@ -500,8 +500,6 @@ DROP PROCEDURE p1;
# #
# Test case for BUG#12976: Boolean values reversed in stored procedures? # Test case for BUG#12976: Boolean values reversed in stored procedures?
# #
# TODO: test case failed.
#
########################################################################### ###########################################################################
--echo --echo
...@@ -566,13 +564,8 @@ BEGIN ...@@ -566,13 +564,8 @@ BEGIN
END| END|
delimiter ;| delimiter ;|
# The expected and correct result.
call p1(); call p1();
# The wrong result. Note that only hex(vb) works, but is printed with two
# digits for some reason in this case.
call p2(); call p2();
# #
...@@ -583,6 +576,64 @@ DROP TABLE t1; ...@@ -583,6 +576,64 @@ DROP TABLE t1;
DROP PROCEDURE p1; DROP PROCEDURE p1;
DROP PROCEDURE p2; DROP PROCEDURE p2;
# Additional tests for Bug#12976
--disable_warnings
DROP TABLE IF EXISTS table_12976_a;
DROP TABLE IF EXISTS table_12976_b;
DROP PROCEDURE IF EXISTS proc_12976_a;
DROP PROCEDURE IF EXISTS proc_12976_b;
--enable_warnings
CREATE TABLE table_12976_a (val bit(1));
CREATE TABLE table_12976_b(
appname varchar(15),
emailperm bit not null default 1,
phoneperm bit not null default 0);
insert into table_12976_b values ('A', b'1', b'1'), ('B', b'0', b'0');
delimiter ||;
CREATE PROCEDURE proc_12976_a()
BEGIN
declare localvar bit(1);
SELECT val INTO localvar FROM table_12976_a;
SELECT coalesce(localvar, 1)+1, coalesce(val, 1)+1 FROM table_12976_a;
END||
CREATE PROCEDURE proc_12976_b(
name varchar(15),
out ep bit,
out msg varchar(10))
BEGIN
SELECT emailperm into ep FROM table_12976_b where (appname = name);
IF ep is true THEN
SET msg = 'True';
ELSE
SET msg = 'False';
END IF;
END||
delimiter ;||
INSERT table_12976_a VALUES (0);
call proc_12976_a();
UPDATE table_12976_a set val=1;
call proc_12976_a();
call proc_12976_b('A', @ep, @msg);
select @ep, @msg;
call proc_12976_b('B', @ep, @msg);
select @ep, @msg;
DROP TABLE table_12976_a;
DROP TABLE table_12976_b;
DROP PROCEDURE proc_12976_a;
DROP PROCEDURE proc_12976_b;
########################################################################### ###########################################################################
# #
# Test case for BUG#9572: Stored procedures: variable type declarations # Test case for BUG#9572: Stored procedures: variable type declarations
......
...@@ -2000,65 +2000,6 @@ SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; ...@@ -2000,65 +2000,6 @@ SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL;
EXPLAIN SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; EXPLAIN SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL;
DROP TABLE t1; DROP TABLE t1;
#
# Bug 24653: sorting by expressions containing subselects
# that return more than one row
#
CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES (2), (4), (1), (3);
CREATE TABLE t2 (b int, c int);
INSERT INTO t2 VALUES
(2,1), (1,3), (2,1), (4,4), (2,2), (1,4);
SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 2 );
--error 1242
SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 1);
SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 2), a;
--error 1242
SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 1), a;
SELECT b, MAX(c) FROM t2 GROUP BY b, (SELECT c FROM t2 WHERE b > 2);
--error 1242
SELECT b, MAX(c) FROM t2 GROUP BY b, (SELECT c FROM t2 WHERE b > 1);
SELECT a FROM t1 GROUP BY a
HAVING IFNULL((SELECT b FROM t2 WHERE b > 2),
(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)) > 3;
--error 1242
SELECT a FROM t1 GROUP BY a
HAVING IFNULL((SELECT b FROM t2 WHERE b > 1),
(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)) > 3;
SELECT a FROM t1 GROUP BY a
HAVING IFNULL((SELECT b FROM t2 WHERE b > 4),
(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)) > 3;
--error 1242
SELECT a FROM t1 GROUP BY a
HAVING IFNULL((SELECT b FROM t2 WHERE b > 4),
(SELECT c FROM t2 WHERE c=a AND b > 1 ORDER BY b)) > 3;
SELECT a FROM t1
ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 2),
(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b));
--error 1242
SELECT a FROM t1
ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 1),
(SELECT c FROM t2 WHERE c=a AND b > 1 ORDER BY b));
SELECT a FROM t1
ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 4),
(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b));
--error 1242
SELECT a FROM t1
ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 4),
(SELECT c FROM t2 WHERE c=a AND b > 1 ORDER BY b));
DROP TABLE t1,t2;
# End of 4.1 tests # End of 4.1 tests
# #
...@@ -2569,35 +2510,101 @@ SELECT SQL_NO_CACHE COUNT(*) ...@@ -2569,35 +2510,101 @@ SELECT SQL_NO_CACHE COUNT(*)
DROP TABLE t1,t2; DROP TABLE t1,t2;
# #
# Bug #25219: EXIST subquery with UNION over a mix of # Bug#21904 (parser problem when using IN with a double "(())")
# correlated and uncorrelated selects #
#
CREATE TABLE t1 (id char(4) PRIMARY KEY, c int); --disable_warnings
CREATE TABLE t2 (c int); DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
DROP TABLE IF EXISTS t1xt2;
--enable_warnings
INSERT INTO t1 VALUES ('aa', 1); CREATE TABLE t1 (
INSERT INTO t2 VALUES (1); id_1 int(5) NOT NULL,
t varchar(4) DEFAULT NULL
);
SELECT * FROM t1 CREATE TABLE t2 (
WHERE EXISTS (SELECT c FROM t2 WHERE c=1 id_2 int(5) NOT NULL,
UNION t varchar(4) DEFAULT NULL
SELECT c from t2 WHERE c=t1.c); );
INSERT INTO t1 VALUES ('bb', 2), ('cc', 3), ('dd',1); CREATE TABLE t1xt2 (
id_1 int(5) NOT NULL,
id_2 int(5) NOT NULL
);
SELECT * FROM t1 INSERT INTO t1 VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd');
WHERE EXISTS (SELECT c FROM t2 WHERE c=1
UNION
SELECT c from t2 WHERE c=t1.c);
INSERT INTO t2 VALUES (2); INSERT INTO t2 VALUES (2, 'bb'), (3, 'cc'), (4, 'dd'), (12, 'aa');
CREATE TABLE t3 (c int);
INSERT INTO t3 VALUES (1);
SELECT * FROM t1 INSERT INTO t1xt2 VALUES (2, 2), (3, 3), (4, 4);
WHERE EXISTS (SELECT t2.c FROM t2 JOIN t3 ON t2.c=t3.c WHERE t2.c=1
UNION # subselect returns 0 rows
SELECT c from t2 WHERE c=t1.c);
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1)));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1))));
insert INTO t1xt2 VALUES (1, 12);
# subselect returns 1 row
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
insert INTO t1xt2 VALUES (2, 12);
# subselect returns more than 1 row
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)));
SELECT DISTINCT t1.id_1 FROM t1 WHERE
(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))));
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t1xt2;
DROP TABLE t1,t2,t3;
...@@ -2385,7 +2385,7 @@ create table t1(f1 int, f2 int); ...@@ -2385,7 +2385,7 @@ create table t1(f1 int, f2 int);
create view v1 as select ta.f1 as a, tb.f1 as b from t1 ta, t1 tb where ta.f1=tb create view v1 as select ta.f1 as a, tb.f1 as b from t1 ta, t1 tb where ta.f1=tb
.f1 and ta.f2=tb.f2; .f1 and ta.f2=tb.f2;
insert into t1 values(1,1),(2,2); insert into t1 values(1,1),(2,2);
create view v2 as select * from v1 where a > 1 with local check option; create view v2 as select * from v1 where a > 1 with check option;
select * from v2; select * from v2;
update v2 set b=3 where a=2; update v2 set b=3 where a=2;
select * from v2; select * from v2;
...@@ -2959,17 +2959,6 @@ SELECT * FROM t1; ...@@ -2959,17 +2959,6 @@ SELECT * FROM t1;
DROP VIEW v1, v2; DROP VIEW v1, v2;
DROP TABLE t1; DROP TABLE t1;
#
# Bug #25580: !0 as an operand in a select expression of a view
#
CREATE VIEW v AS SELECT !0 * 5 AS x FROM DUAL;
SHOW CREATE VIEW v;
SELECT !0 * 5 AS x FROM DUAL;
SELECT * FROM v;
DROP VIEW v;
# #
# BUG#24293: '\Z' token is not handled correctly in views # BUG#24293: '\Z' token is not handled correctly in views
...@@ -2986,76 +2975,108 @@ SHOW CREATE VIEW v1; ...@@ -2986,76 +2975,108 @@ SHOW CREATE VIEW v1;
DROP VIEW v1; DROP VIEW v1;
#
# Bug #26124: BETWEEN over a view column of the DATETIME type
#
CREATE TABLE t1 (mydate DATETIME);
INSERT INTO t1 VALUES
('2007-01-01'), ('2007-01-02'), ('2007-01-30'), ('2007-01-31');
CREATE VIEW v1 AS SELECT mydate from t1;
SELECT * FROM t1 WHERE mydate BETWEEN '2007-01-01' AND '2007-01-31';
SELECT * FROM v1 WHERE mydate BETWEEN '2007-01-01' AND '2007-01-31';
DROP VIEW v1;
DROP TABLE t1;
# #
# Bug #25931: update of a multi-table view with check option # BUG#25897: Some queries are no longer possible after a CREATE VIEW
# fails
# #
--disable_warnings
DROP VIEW IF EXISTS v1;
--enable_warnings
CREATE TABLE t1 (a int); let $query = SELECT * FROM (SELECT 1) AS t;
CREATE TABLE t2 (b int);
INSERT INTO t1 VALUES (1), (2);
INSERT INTO t2 VALUES (1), (2);
CREATE VIEW v1 AS eval $query;
SELECT t2.b FROM t1,t2 WHERE t1.a = t2.b WITH CHECK OPTION; --error ER_VIEW_SELECT_DERIVED
eval CREATE VIEW v1 AS $query;
SELECT * FROM v1; --echo # Previously the following would fail.
--error 1369 eval $query;
UPDATE v1 SET b=3;
SELECT * FROM v1;
SELECT * FROM t1;
SELECT * FROM t2;
DROP VIEW v1;
DROP TABLE t1,t2;
# #
# Bug#12122: Views with ORDER BY can't be resolved using MERGE algorithm. # Bug#24532: The return data type of IS TRUE is different from similar
# operations
# #
create table t1(f1 int, f2 int);
insert into t1 values(1,2),(1,3),(1,1),(2,3),(2,1),(2,2);
select * from t1;
create view v1 as select * from t1 order by f2;
select * from v1;
explain extended select * from v1;
select * from v1 order by f1;
explain extended select * from v1 order by f1;
drop view v1;
drop table t1;
# --disable_warnings
# Bug#26209: queries with GROUP BY and ORDER BY using views drop view if exists view_24532_a;
# drop view if exists view_24532_b;
drop table if exists table_24532;
--enable_warnings
CREATE TABLE t1 ( create table table_24532 (
id int(11) NOT NULL PRIMARY KEY, a int,
country varchar(32), b bigint,
code int(11) default NULL c int(4),
d bigint(48)
); );
INSERT INTO t1 VALUES
(1,'ITALY',100),(2,'ITALY',200),(3,'FRANCE',100), (4,'ITALY',100);
CREATE VIEW v1 AS SELECT * FROM t1; create view view_24532_a as
select
SELECT code, COUNT(DISTINCT country) FROM t1 GROUP BY code ORDER BY MAX(id); a IS TRUE,
SELECT code, COUNT(DISTINCT country) FROM v1 GROUP BY code ORDER BY MAX(id); a IS NOT TRUE,
a IS FALSE,
DROP VIEW v1; a IS NOT FALSE,
DROP TABLE t1; a IS UNKNOWN,
a IS NOT UNKNOWN,
a is NULL,
a IS NOT NULL,
ISNULL(a),
b IS TRUE,
b IS NOT TRUE,
b IS FALSE,
b IS NOT FALSE,
b IS UNKNOWN,
b IS NOT UNKNOWN,
b is NULL,
b IS NOT NULL,
ISNULL(b),
c IS TRUE,
c IS NOT TRUE,
c IS FALSE,
c IS NOT FALSE,
c IS UNKNOWN,
c IS NOT UNKNOWN,
c is NULL,
c IS NOT NULL,
ISNULL(c),
d IS TRUE,
d IS NOT TRUE,
d IS FALSE,
d IS NOT FALSE,
d IS UNKNOWN,
d IS NOT UNKNOWN,
d is NULL,
d IS NOT NULL,
ISNULL(d)
from table_24532;
describe view_24532_a;
create view view_24532_b as
select
a IS TRUE,
if(ifnull(a, 0), 1, 0) as old_istrue,
a IS NOT TRUE,
if(ifnull(a, 0), 0, 1) as old_isnottrue,
a IS FALSE,
if(ifnull(a, 1), 0, 1) as old_isfalse,
a IS NOT FALSE,
if(ifnull(a, 1), 1, 0) as old_isnotfalse
from table_24532;
describe view_24532_b;
show create view view_24532_b;
insert into table_24532 values (0, 0, 0, 0);
select * from view_24532_b;
update table_24532 set a=1;
select * from view_24532_b;
update table_24532 set a=NULL;
select * from view_24532_b;
drop view view_24532_a;
drop view view_24532_b;
drop table table_24532;
--echo End of 5.0 tests. --echo End of 5.0 tests.
...@@ -792,6 +792,59 @@ int Arg_comparator::compare_e_row() ...@@ -792,6 +792,59 @@ int Arg_comparator::compare_e_row()
} }
void Item_func_truth::fix_length_and_dec()
{
maybe_null= 0;
null_value= 0;
decimals= 0;
max_length= 1;
}
void Item_func_truth::print(String *str)
{
str->append('(');
args[0]->print(str);
str->append(STRING_WITH_LEN(" is "));
if (! affirmative)
str->append(STRING_WITH_LEN("not "));
if (value)
str->append(STRING_WITH_LEN("true"));
else
str->append(STRING_WITH_LEN("false"));
str->append(')');
}
bool Item_func_truth::val_bool()
{
bool val= args[0]->val_bool();
if (args[0]->null_value)
{
/*
NULL val IS {TRUE, FALSE} --> FALSE
NULL val IS NOT {TRUE, FALSE} --> TRUE
*/
return (! affirmative);
}
if (affirmative)
{
/* {TRUE, FALSE} val IS {TRUE, FALSE} value */
return (val == value);
}
/* {TRUE, FALSE} val IS NOT {TRUE, FALSE} value */
return (val != value);
}
longlong Item_func_truth::val_int()
{
return (val_bool() ? 1 : 0);
}
bool Item_in_optimizer::fix_left(THD *thd, Item **ref) bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
{ {
if (!args[0]->fixed && args[0]->fix_fields(thd, args) || if (!args[0]->fixed && args[0]->fix_fields(thd, args) ||
...@@ -1527,6 +1580,7 @@ Item_func_if::fix_length_and_dec() ...@@ -1527,6 +1580,7 @@ Item_func_if::fix_length_and_dec()
{ {
maybe_null=args[1]->maybe_null || args[2]->maybe_null; maybe_null=args[1]->maybe_null || args[2]->maybe_null;
decimals= max(args[1]->decimals, args[2]->decimals); decimals= max(args[1]->decimals, args[2]->decimals);
unsigned_flag=args[1]->unsigned_flag && args[2]->unsigned_flag;
enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg1_type=args[1]->result_type();
enum Item_result arg2_type=args[2]->result_type(); enum Item_result arg2_type=args[2]->result_type();
...@@ -1556,12 +1610,20 @@ Item_func_if::fix_length_and_dec() ...@@ -1556,12 +1610,20 @@ Item_func_if::fix_length_and_dec()
collation.set(&my_charset_bin); // Number collation.set(&my_charset_bin); // Number
} }
} }
max_length=
(cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT) ? if ((cached_result_type == DECIMAL_RESULT )
(max(args[1]->max_length - args[1]->decimals, || (cached_result_type == INT_RESULT))
args[2]->max_length - args[2]->decimals) + decimals + {
(unsigned_flag ? 0 : 1) ) : int len1= args[1]->max_length - args[1]->decimals
max(args[1]->max_length, args[2]->max_length); - (args[1]->unsigned_flag ? 0 : 1);
int len2= args[2]->max_length - args[2]->decimals
- (args[2]->unsigned_flag ? 0 : 1);
max_length=max(len1, len2) + decimals + (unsigned_flag ? 0 : 1);
}
else
max_length= max(args[1]->max_length, args[2]->max_length);
} }
......
...@@ -101,6 +101,92 @@ public: ...@@ -101,6 +101,92 @@ public:
uint decimal_precision() const { return 1; } uint decimal_precision() const { return 1; }
}; };
/**
Abstract Item class, to represent <code>X IS [NOT] (TRUE | FALSE)</code>
boolean predicates.
*/
class Item_func_truth : public Item_bool_func
{
public:
virtual bool val_bool();
virtual longlong val_int();
virtual void fix_length_and_dec();
virtual void print(String *str);
protected:
Item_func_truth(Item *a, bool a_value, bool a_affirmative)
: Item_bool_func(a), value(a_value), affirmative(a_affirmative)
{}
~Item_func_truth()
{}
private:
/**
True for <code>X IS [NOT] TRUE</code>,
false for <code>X IS [NOT] FALSE</code> predicates.
*/
const bool value;
/**
True for <code>X IS Y</code>, false for <code>X IS NOT Y</code> predicates.
*/
const bool affirmative;
};
/**
This Item represents a <code>X IS TRUE</code> boolean predicate.
*/
class Item_func_istrue : public Item_func_truth
{
public:
Item_func_istrue(Item *a) : Item_func_truth(a, true, true) {}
~Item_func_istrue() {}
virtual const char* func_name() const { return "istrue"; }
};
/**
This Item represents a <code>X IS NOT TRUE</code> boolean predicate.
*/
class Item_func_isnottrue : public Item_func_truth
{
public:
Item_func_isnottrue(Item *a) : Item_func_truth(a, true, false) {}
~Item_func_isnottrue() {}
virtual const char* func_name() const { return "isnottrue"; }
};
/**
This Item represents a <code>X IS FALSE</code> boolean predicate.
*/
class Item_func_isfalse : public Item_func_truth
{
public:
Item_func_isfalse(Item *a) : Item_func_truth(a, false, true) {}
~Item_func_isfalse() {}
virtual const char* func_name() const { return "isfalse"; }
};
/**
This Item represents a <code>X IS NOT FALSE</code> boolean predicate.
*/
class Item_func_isnotfalse : public Item_func_truth
{
public:
Item_func_isnotfalse(Item *a) : Item_func_truth(a, false, false) {}
~Item_func_isnotfalse() {}
virtual const char* func_name() const { return "isnotfalse"; }
};
class Item_cache; class Item_cache;
#define UNKNOWN ((my_bool)-1) #define UNKNOWN ((my_bool)-1)
......
...@@ -51,6 +51,10 @@ Item_subselect::Item_subselect(): ...@@ -51,6 +51,10 @@ Item_subselect::Item_subselect():
void Item_subselect::init(st_select_lex *select_lex, void Item_subselect::init(st_select_lex *select_lex,
select_subselect *result) select_subselect *result)
{ {
/*
Please see Item_singlerow_subselect::invalidate_and_restore_select_lex(),
which depends on alterations to the parse tree implemented here.
*/
DBUG_ENTER("Item_subselect::init"); DBUG_ENTER("Item_subselect::init");
DBUG_PRINT("enter", ("select_lex: 0x%lx", (long) select_lex)); DBUG_PRINT("enter", ("select_lex: 0x%lx", (long) select_lex));
...@@ -91,6 +95,12 @@ void Item_subselect::init(st_select_lex *select_lex, ...@@ -91,6 +95,12 @@ void Item_subselect::init(st_select_lex *select_lex,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
st_select_lex *
Item_subselect::get_select_lex()
{
return unit->first_select();
}
void Item_subselect::cleanup() void Item_subselect::cleanup()
{ {
DBUG_ENTER("Item_subselect::cleanup"); DBUG_ENTER("Item_subselect::cleanup");
...@@ -268,6 +278,26 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) ...@@ -268,6 +278,26 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
st_select_lex *
Item_singlerow_subselect::invalidate_and_restore_select_lex()
{
DBUG_ENTER("Item_singlerow_subselect::invalidate_and_restore_select_lex");
st_select_lex *result= get_select_lex();
DBUG_ASSERT(result);
/*
This code restore the parse tree in it's state before the execution of
Item_singlerow_subselect::Item_singlerow_subselect(),
and in particular decouples this object from the SELECT_LEX,
so that the SELECT_LEX can be used with a different flavor
or Item_subselect instead, as part of query rewriting.
*/
unit->item= NULL;
DBUG_RETURN(result);
}
Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param, Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param,
Item_subselect *parent, Item_subselect *parent,
st_select_lex *select_lex, st_select_lex *select_lex,
......
...@@ -126,6 +126,12 @@ public: ...@@ -126,6 +126,12 @@ public:
virtual void reset_value_registration() {} virtual void reset_value_registration() {}
enum_parsing_place place() { return parsing_place; } enum_parsing_place place() { return parsing_place; }
/**
Get the SELECT_LEX structure associated with this Item.
@return the SELECT_LEX structure associated with this Item
*/
st_select_lex* get_select_lex();
friend class select_subselect; friend class select_subselect;
friend class Item_in_optimizer; friend class Item_in_optimizer;
friend bool Item_field::fix_fields(THD *, Item **); friend bool Item_field::fix_fields(THD *, Item **);
...@@ -169,6 +175,20 @@ public: ...@@ -169,6 +175,20 @@ public:
bool null_inside(); bool null_inside();
void bring_value(); void bring_value();
/**
This method is used to implement a special case of semantic tree
rewriting, mandated by a SQL:2003 exception in the specification.
The only caller of this method is handle_sql2003_note184_exception(),
see the code there for more details.
Note that this method breaks the object internal integrity, by
removing it's association with the corresponding SELECT_LEX,
making this object orphan from the parse tree.
No other method, beside the destructor, should be called on this
object, as it is now invalid.
@return the SELECT_LEX structure that was given in the constructor.
*/
st_select_lex* invalidate_and_restore_select_lex();
friend class select_singlerow_subselect; friend class select_singlerow_subselect;
}; };
......
...@@ -36,6 +36,7 @@ Item_result ...@@ -36,6 +36,7 @@ Item_result
sp_map_result_type(enum enum_field_types type) sp_map_result_type(enum enum_field_types type)
{ {
switch (type) { switch (type) {
case MYSQL_TYPE_BIT:
case MYSQL_TYPE_TINY: case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT: case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONG: case MYSQL_TYPE_LONG:
...@@ -58,6 +59,7 @@ Item::Type ...@@ -58,6 +59,7 @@ Item::Type
sp_map_item_type(enum enum_field_types type) sp_map_item_type(enum enum_field_types type)
{ {
switch (type) { switch (type) {
case MYSQL_TYPE_BIT:
case MYSQL_TYPE_TINY: case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT: case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONG: case MYSQL_TYPE_LONG:
......
...@@ -1765,8 +1765,18 @@ void Query_cache::free_cache() ...@@ -1765,8 +1765,18 @@ void Query_cache::free_cache()
{ {
DBUG_ENTER("Query_cache::free_cache"); DBUG_ENTER("Query_cache::free_cache");
if (query_cache_size > 0) if (query_cache_size > 0)
{
flush_cache(); flush_cache();
/*
There may be two free_cache() calls in progress, because we
release 'structure_guard_mutex' in flush_cache(). When the second
flush_cache() wakes up from the wait on 'COND_flush_finished', the
first call to free_cache() has done its job. So we have to test
'query_cache_size > 0' the second time to see if the cache wasn't
reset by other thread, or if it was reset and was re-enabled then.
If the cache was reset, then we have nothing to do here.
*/
if (query_cache_size > 0)
{
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (bins[0].free_blocks == 0) if (bins[0].free_blocks == 0)
{ {
...@@ -1808,6 +1818,12 @@ void Query_cache::free_cache() ...@@ -1808,6 +1818,12 @@ void Query_cache::free_cache()
flush_in_progress flag and releases the lock, so other threads may flush_in_progress flag and releases the lock, so other threads may
proceed skipping the cache as if it is disabled. Concurrent proceed skipping the cache as if it is disabled. Concurrent
flushes are performed in turn. flushes are performed in turn.
After flush_cache() call, the cache is flushed, all the freed
memory is accumulated in bin[0], and the 'structure_guard_mutex'
is locked. However, since we could release the mutex during
execution, the rest of the cache state could have been changed,
and should not be relied on.
*/ */
void Query_cache::flush_cache() void Query_cache::flush_cache()
......
...@@ -99,6 +99,16 @@ void lex_free(void) ...@@ -99,6 +99,16 @@ void lex_free(void)
} }
void
st_parsing_options::reset()
{
allows_variable= TRUE;
allows_select_into= TRUE;
allows_select_procedure= TRUE;
allows_derived= TRUE;
}
/* /*
This is called before every query that is to be parsed. This is called before every query that is to be parsed.
Because of this, it's critical to not do too much things here. Because of this, it's critical to not do too much things here.
...@@ -149,6 +159,7 @@ void lex_start(THD *thd, uchar *buf,uint length) ...@@ -149,6 +159,7 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->safe_to_cache_query= 1; lex->safe_to_cache_query= 1;
lex->time_zone_tables_used= 0; lex->time_zone_tables_used= 0;
lex->leaf_tables_insert= 0; lex->leaf_tables_insert= 0;
lex->parsing_options.reset();
lex->empty_field_list_on_rset= 0; lex->empty_field_list_on_rset= 0;
lex->select_lex.select_number= 1; lex->select_lex.select_number= 1;
lex->next_state=MY_LEX_START; lex->next_state=MY_LEX_START;
......
...@@ -884,10 +884,8 @@ struct st_parsing_options ...@@ -884,10 +884,8 @@ struct st_parsing_options
bool allows_select_procedure; bool allows_select_procedure;
bool allows_derived; bool allows_derived;
st_parsing_options() st_parsing_options() { reset(); }
: allows_variable(TRUE), allows_select_into(TRUE), void reset();
allows_select_procedure(TRUE), allows_derived(TRUE)
{}
}; };
......
...@@ -58,15 +58,6 @@ const LEX_STRING null_lex_str={0,0}; ...@@ -58,15 +58,6 @@ const LEX_STRING null_lex_str={0,0};
YYABORT; \ YYABORT; \
} }
/* Helper for parsing "IS [NOT] truth_value" */
inline Item *is_truth_value(Item *A, bool v1, bool v2)
{
return new Item_func_if(create_func_ifnull(A,
new Item_int((char *) (v2 ? "TRUE" : "FALSE"), v2, 1)),
new Item_int((char *) (v1 ? "TRUE" : "FALSE"), v1, 1),
new Item_int((char *) (v1 ? "FALSE" : "TRUE"),!v1, 1));
}
#ifndef DBUG_OFF #ifndef DBUG_OFF
#define YYDEBUG 1 #define YYDEBUG 1
#else #else
...@@ -276,6 +267,81 @@ void case_stmt_action_end_case(LEX *lex, bool simple) ...@@ -276,6 +267,81 @@ void case_stmt_action_end_case(LEX *lex, bool simple)
lex->sphead->do_cont_backpatch(); lex->sphead->do_cont_backpatch();
} }
/**
Helper to resolve the SQL:2003 Syntax exception 1) in <in predicate>.
See SQL:2003, Part 2, section 8.4 <in predicate>, Note 184, page 383.
This function returns the proper item for the SQL expression
<code>left [NOT] IN ( expr )</code>
@param thd the current thread
@param left the in predicand
@param equal true for IN predicates, false for NOT IN predicates
@param expr first and only expression of the in value list
@return an expression representing the IN predicate.
*/
Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
Item *expr)
{
/*
Relevant references for this issue:
- SQL:2003, Part 2, section 8.4 <in predicate>, page 383,
- SQL:2003, Part 2, section 7.2 <row value expression>, page 296,
- SQL:2003, Part 2, section 6.3 <value expression primary>, page 174,
- SQL:2003, Part 2, section 7.15 <subquery>, page 370,
- SQL:2003 Feature F561, "Full value expressions".
The exception in SQL:2003 Note 184 means:
Item_singlerow_subselect, which corresponds to a <scalar subquery>,
should be re-interpreted as an Item_in_subselect, which corresponds
to a <table subquery> when used inside an <in predicate>.
Our reading of Note 184 is reccursive, so that all:
- IN (( <subquery> ))
- IN ((( <subquery> )))
- IN '('^N <subquery> ')'^N
- etc
should be interpreted as a <table subquery>, no matter how deep in the
expression the <subquery> is.
*/
Item *result;
DBUG_ENTER("handle_sql2003_note184_exception");
if (expr->type() == Item::SUBSELECT_ITEM)
{
Item_subselect *expr2 = (Item_subselect*) expr;
if (expr2->substype() == Item_subselect::SINGLEROW_SUBS)
{
Item_singlerow_subselect *expr3 = (Item_singlerow_subselect*) expr2;
st_select_lex *subselect;
/*
Implement the mandated change, by altering the semantic tree:
left IN Item_singlerow_subselect(subselect)
is modified to
left IN (subselect)
which is represented as
Item_in_subselect(left, subselect)
*/
subselect= expr3->invalidate_and_restore_select_lex();
result= new (thd->mem_root) Item_in_subselect(left, subselect);
if (! equal)
result = negate_expression(thd, result);
DBUG_RETURN(result);
}
}
if (equal)
result= new (thd->mem_root) Item_func_eq(left, expr);
else
result= new (thd->mem_root) Item_func_ne(left, expr);
DBUG_RETURN(result);
}
%} %}
%union { %union {
int num; int num;
...@@ -4382,13 +4448,18 @@ bool_factor: ...@@ -4382,13 +4448,18 @@ bool_factor:
| bool_test ; | bool_test ;
bool_test: bool_test:
bool_pri IS TRUE_SYM { $$= is_truth_value($1,1,0); } bool_pri IS TRUE_SYM
| bool_pri IS not TRUE_SYM { $$= is_truth_value($1,0,0); } { $$= new (YYTHD->mem_root) Item_func_istrue($1); }
| bool_pri IS FALSE_SYM { $$= is_truth_value($1,0,1); } | bool_pri IS not TRUE_SYM
| bool_pri IS not FALSE_SYM { $$= is_truth_value($1,1,1); } { $$= new (YYTHD->mem_root) Item_func_isnottrue($1); }
| bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); } | bool_pri IS FALSE_SYM
| bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); } { $$= new (YYTHD->mem_root) Item_func_isfalse($1); }
| bool_pri ; | bool_pri IS not FALSE_SYM
{ $$= new (YYTHD->mem_root) Item_func_isnotfalse($1); }
| bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); }
| bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); }
| bool_pri
;
bool_pri: bool_pri:
bool_pri IS NULL_SYM { $$= new Item_func_isnull($1); } bool_pri IS NULL_SYM { $$= new Item_func_isnull($1); }
...@@ -4401,31 +4472,37 @@ bool_pri: ...@@ -4401,31 +4472,37 @@ bool_pri:
| predicate ; | predicate ;
predicate: predicate:
bit_expr IN_SYM '(' subselect ')' bit_expr IN_SYM '(' subselect ')'
{ $$= new Item_in_subselect($1, $4); } {
| bit_expr not IN_SYM '(' subselect ')' $$= new (YYTHD->mem_root) Item_in_subselect($1, $4);
{ $$= negate_expression(YYTHD, new Item_in_subselect($1, $5)); } }
| bit_expr not IN_SYM '(' subselect ')'
{
THD *thd= YYTHD;
Item *item= new (thd->mem_root) Item_in_subselect($1, $5);
$$= negate_expression(thd, item);
}
| bit_expr IN_SYM '(' expr ')' | bit_expr IN_SYM '(' expr ')'
{ {
$$= new Item_func_eq($1, $4); $$= handle_sql2003_note184_exception(YYTHD, $1, true, $4);
} }
| bit_expr IN_SYM '(' expr ',' expr_list ')' | bit_expr IN_SYM '(' expr ',' expr_list ')'
{ {
$6->push_front($4); $6->push_front($4);
$6->push_front($1); $6->push_front($1);
$$= new Item_func_in(*$6); $$= new (YYTHD->mem_root) Item_func_in(*$6);
} }
| bit_expr not IN_SYM '(' expr ')' | bit_expr not IN_SYM '(' expr ')'
{ {
$$= new Item_func_ne($1, $5); $$= handle_sql2003_note184_exception(YYTHD, $1, false, $5);
} }
| bit_expr not IN_SYM '(' expr ',' expr_list ')' | bit_expr not IN_SYM '(' expr ',' expr_list ')'
{ {
$7->push_front($5); $7->push_front($5);
$7->push_front($1); $7->push_front($1);
Item_func_in *item = new Item_func_in(*$7); Item_func_in *item = new (YYTHD->mem_root) Item_func_in(*$7);
item->negate(); item->negate();
$$= item; $$= item;
} }
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
{ $$= new Item_func_between($1,$3,$5); } { $$= new Item_func_between($1,$3,$5); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment