Commit c9fd2749 authored by unknown's avatar unknown

Merge sinisa@work.mysql.com:/home/bk/mysql-4.1

into sinisa.nasamreza.org:/mnt/work/mysql-4.1


sql/sql_select.cc:
  Auto merged
sql/sql_union.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
parents 2b29b55c 19f6ad06
...@@ -90,6 +90,7 @@ tonu@x153.internalnet ...@@ -90,6 +90,7 @@ tonu@x153.internalnet
tonu@x3.internalnet tonu@x3.internalnet
venu@myvenu.com venu@myvenu.com
venu@work.mysql.com venu@work.mysql.com
vva@eagle.mysql.r18.ru
vva@genie.(none) vva@genie.(none)
walrus@mysql.com walrus@mysql.com
wax@mysql.com wax@mysql.com
......
...@@ -32040,6 +32040,10 @@ a single backslash to be matched). ...@@ -32040,6 +32040,10 @@ a single backslash to be matched).
@item expr NOT LIKE pat [ESCAPE 'escape-char'] @item expr NOT LIKE pat [ESCAPE 'escape-char']
Same as @code{NOT (expr LIKE pat [ESCAPE 'escape-char'])}. Same as @code{NOT (expr LIKE pat [ESCAPE 'escape-char'])}.
@findex SOUNDS LIKE
@item expr SOUNDS LIKE expr
Same as @code{SOUNDEX(expr)=SOUNDEX(expr)}.
@cindex mSQL compatibility @cindex mSQL compatibility
@cindex compatibility, with mSQL @cindex compatibility, with mSQL
@findex REGEXP @findex REGEXP
...@@ -42,21 +42,21 @@ insert into t1 values (null,null,''); ...@@ -42,21 +42,21 @@ insert into t1 values (null,null,'');
select count(distinct a),count(distinct grp) from t1; select count(distinct a),count(distinct grp) from t1;
count(distinct a) count(distinct grp) count(distinct a) count(distinct grp)
6 3 6 3
select sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1; select sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1;
sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c) sum(a) count(a) avg(a) std(a) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
21 6 3.5000 1.7078 7 0 1 6 E 21 6 3.5000 1.7078 2.9167 7 0 1 6 E
select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp; select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c) grp sum(a) count(a) avg(a) std(a) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
NULL 0 0 NULL NULL 0 0 NULL NULL NULL 0 0 NULL NULL NULL 0 0 NULL NULL
1 1 1 1.0000 0.0000 1 1 1 1 a a 1 1 1 1.0000 0.0000 0.0000 1 1 1 1 a a
2 5 2 2.5000 0.5000 3 2 2 3 b c 2 5 2 2.5000 0.5000 0.2500 3 2 2 3 b c
3 15 3 5.0000 0.8165 7 4 4 6 C E 3 15 3 5.0000 0.8165 0.6667 7 4 4 6 C E
select grp, sum(a)+count(a)+avg(a)+std(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp; select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
grp sum grp sum
NULL NULL NULL NULL
1 7 1 7
2 20 2 20.25
3 44.816496580928 3 45.483163247594
create table t2 (grp int, a bigint unsigned, c char(10)); create table t2 (grp int, a bigint unsigned, c char(10));
insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp; insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
replace into t2 select grp, a, c from t1 limit 2,1; replace into t2 select grp, a, c from t1 limit 2,1;
...@@ -72,14 +72,14 @@ CREATE TABLE t1 (id int(11),value1 float(10,2)); ...@@ -72,14 +72,14 @@ CREATE TABLE t1 (id int(11),value1 float(10,2));
INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00); INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00);
CREATE TABLE t2 (id int(11),name char(20)); CREATE TABLE t2 (id int(11),name char(20));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two'); INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
select id, avg(value1), std(value1) from t1 group by id; select id, avg(value1), std(value1), variance(value1) from t1 group by id;
id avg(value1) std(value1) id avg(value1) std(value1) variance(value1)
1 1.000000 0.816497 1 1.000000 0.816497 0.666667
2 11.000000 0.816497 2 11.000000 0.816497 0.666667
select name, avg(value1), std(value1) from t1, t2 where t1.id = t2.id group by t1.id; select name, avg(value1), std(value1), variance(value1) from t1, t2 where t1.id = t2.id group by t1.id;
name avg(value1) std(value1) name avg(value1) std(value1) variance(value1)
Set One 1.000000 0.816497 Set One 1.000000 0.816497 0.666667
Set Two 11.000000 0.816497 Set Two 11.000000 0.816497 0.666667
drop table t1,t2; drop table t1,t2;
create table t1 (id int not null); create table t1 (id int not null);
create table t2 (id int not null,rating int null); create table t2 (id int not null,rating int null);
......
select 1 in (1,2,3);
1 in (1,2,3)
1
select 10 in (1,2,3);
10 in (1,2,3)
0
select NULL in (1,2,3);
NULL in (1,2,3)
NULL
select 1 in (1,NULL,3);
1 in (1,NULL,3)
1
select 3 in (1,NULL,3);
3 in (1,NULL,3)
1
select 10 in (1,NULL,3);
10 in (1,NULL,3)
NULL
select 1.5 in (1.5,2.5,3.5);
1.5 in (1.5,2.5,3.5)
1
select 10.5 in (1.5,2.5,3.5);
10.5 in (1.5,2.5,3.5)
0
select NULL in (1.5,2.5,3.5);
NULL in (1.5,2.5,3.5)
NULL
select 1.5 in (1.5,NULL,3.5);
1.5 in (1.5,NULL,3.5)
1
select 3.5 in (1.5,NULL,3.5);
3.5 in (1.5,NULL,3.5)
1
select 10.5 in (1.5,NULL,3.5);
10.5 in (1.5,NULL,3.5)
NULL
drop table if exists t1; drop table if exists t1;
CREATE TABLE t1 (a int, b int, c int);
insert into t1 values (1,2,3), (1,NULL,3);
select 1 in (a,b,c) from t1;
1 in (a,b,c)
1
1
select 3 in (a,b,c) from t1;
3 in (a,b,c)
1
1
select 10 in (a,b,c) from t1;
10 in (a,b,c)
0
NULL
select NULL in (a,b,c) from t1;
NULL in (a,b,c)
NULL
NULL
drop table t1;
CREATE TABLE t1 (a float, b float, c float);
insert into t1 values (1.5,2.5,3.5), (1.5,NULL,3.5);
select 1.5 in (a,b,c) from t1;
1.5 in (a,b,c)
1
1
select 3.5 in (a,b,c) from t1;
3.5 in (a,b,c)
1
1
select 10.5 in (a,b,c) from t1;
10.5 in (a,b,c)
0
NULL
drop table t1;
CREATE TABLE t1 (a varchar(10), b varchar(10), c varchar(10));
insert into t1 values ('A','BC','EFD'), ('A',NULL,'EFD');
select 'A' in (a,b,c) from t1;
'A' in (a,b,c)
1
1
select 'EFD' in (a,b,c) from t1;
'EFD' in (a,b,c)
1
1
select 'XSFGGHF' in (a,b,c) from t1;
'XSFGGHF' in (a,b,c)
0
NULL
drop table t1;
CREATE TABLE t1 (field char(1)); CREATE TABLE t1 (field char(1));
INSERT INTO t1 VALUES ('A'),(NULL); INSERT INTO t1 VALUES ('A'),(NULL);
SELECT * from t1 WHERE field IN (NULL); SELECT * from t1 WHERE field IN (NULL);
field field
SELECT * from t1 WHERE field NOT IN (NULL); SELECT * from t1 WHERE field NOT IN (NULL);
field field
A
SELECT * from t1 where field = field; SELECT * from t1 where field = field;
field field
A A
...@@ -16,6 +100,7 @@ NULL ...@@ -16,6 +100,7 @@ NULL
DELETE FROM t1 WHERE field NOT IN (NULL); DELETE FROM t1 WHERE field NOT IN (NULL);
SELECT * FROM t1; SELECT * FROM t1;
field field
A
NULL NULL
drop table t1; drop table t1;
create table t1 (id int(10) primary key); create table t1 (id int(10) primary key);
......
...@@ -80,6 +80,21 @@ this is a REAL test ...@@ -80,6 +80,21 @@ this is a REAL test
select soundex(''),soundex('he'),soundex('hello all folks'); select soundex(''),soundex('he'),soundex('hello all folks');
soundex('') soundex('he') soundex('hello all folks') soundex('') soundex('he') soundex('hello all folks')
H000 H4142 H000 H4142
select 'mood' sounds like 'mud';
'mood' sounds like 'mud'
1
select 'Glazgo' sounds like 'Liverpool';
'Glazgo' sounds like 'Liverpool'
0
select null sounds like 'null';
null sounds like 'null'
NULL
select 'null' sounds like null;
'null' sounds like null
NULL
select null sounds like null;
null sounds like null
NULL
select md5('hello'); select md5('hello');
md5('hello') md5('hello')
5d41402abc4b2a76b9719d911017c592 5d41402abc4b2a76b9719d911017c592
......
...@@ -62,4 +62,8 @@ select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null; ...@@ -62,4 +62,8 @@ select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null;
Fld1 max(Fld2) Fld1 max(Fld2)
1 20 1 20
3 50 3 50
select Fld1, max(Fld2) from t1 group by Fld1 having variance(Fld2) is not null;
Fld1 max(Fld2)
1 20
3 50
drop table t1; drop table t1;
select row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3))
1
select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3))
0
select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3))
1
select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3))
0
select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'));
row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'))
1
select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3))
1
select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3));
row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3))
1
select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3))
1
select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3))
0
select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3));
row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3))
NULL
select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3));
row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3))
0
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4)));
row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4)))
1
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4));
Cardinality error (more/less than 2 columns)
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)));
row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)))
NULL
SELECT ROW(1,2,3)=ROW(1,2,3); SELECT ROW(1,2,3)=ROW(1,2,3);
ROW(1,2,3)=ROW(1,2,3) ROW(1,2,3)=ROW(1,2,3)
1 1
...@@ -36,9 +77,20 @@ ROW('test',2,3.33)=ROW('test',2,3.33) ...@@ -36,9 +77,20 @@ ROW('test',2,3.33)=ROW('test',2,3.33)
1 1
SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4); SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
Cardinality error (more/less than 3 columns) Cardinality error (more/less than 3 columns)
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33));
ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33))
1
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3));
ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3))
0
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL));
ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL))
NULL
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,4);
Cardinality error (more/less than 2 columns)
drop table if exists t1; drop table if exists t1;
create table t1 ( a int, b int, c int); create table t1 ( a int, b int, c int);
insert into t1 values (1,2,3), (2,3,1), (3,2,1); insert into t1 values (1,2,3), (2,3,1), (3,2,1), (1,2,NULL);
select * from t1 where ROW(1,2,3)=ROW(a,b,c); select * from t1 where ROW(1,2,3)=ROW(a,b,c);
a b c a b c
1 2 3 1 2 3
...@@ -48,6 +100,30 @@ select * from t1 where ROW(1,2,3)<ROW(a,b,c); ...@@ -48,6 +100,30 @@ select * from t1 where ROW(1,2,3)<ROW(a,b,c);
a b c a b c
2 3 1 2 3 1
3 2 1 3 2 1
select ROW(a,2,3) IN(row(1,b,c), row(2,3,1)) from t1;
ROW(a,2,3) IN(row(1,b,c), row(2,3,1))
1
0
0
NULL
select ROW(c,2,3) IN(row(1,b,a), row(2,3,1)) from t1;
ROW(c,2,3) IN(row(1,b,a), row(2,3,1))
0
0
1
NULL
select ROW(a,b,c) IN(row(1,2,3), row(3,2,1)) from t1;
ROW(a,b,c) IN(row(1,2,3), row(3,2,1))
1
0
1
NULL
select ROW(1,2,3) IN(row(a,b,c), row(1,2,3)) from t1;
ROW(1,2,3) IN(row(a,b,c), row(1,2,3))
1
1
1
1
drop table t1; drop table t1;
select ROW(1,1); select ROW(1,1);
Cardinality error (more/less than 1 columns) Cardinality error (more/less than 1 columns)
......
...@@ -2656,14 +2656,14 @@ companynr count(*) ...@@ -2656,14 +2656,14 @@ companynr count(*)
58 23 58 23
53 4 53 4
50 11 50 11
select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 where companynr = 34 and fld4<>""; select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
70 absentee vest 17788966 254128.0857 3272.5940 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 group by companynr limit 3; select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
00 82 Anthony windmills 10355753 126289.6707 115550.9757 00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087
29 95 abut wetness 14473298 152350.5053 8368.5480 29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026
34 70 absentee vest 17788966 254128.0857 3272.5940 34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
companynr t2nr count(price) sum(price) min(price) max(price) avg(price) companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
37 1 1 5987435 5987435 5987435 5987435.0000 37 1 1 5987435 5987435 5987435 5987435.0000
......
...@@ -598,3 +598,105 @@ INSERT INTO t1 values (1),(1); ...@@ -598,3 +598,105 @@ INSERT INTO t1 values (1),(1);
UPDATE t SET id=(SELECT * FROM t1); UPDATE t SET id=(SELECT * FROM t1);
Subselect returns more than 1 record Subselect returns more than 1 record
drop table t; drop table t;
create table t (a int);
insert into t values (1),(2),(3);
select 1 IN (SELECT * from t);
1 IN (SELECT * from t)
1
select 10 IN (SELECT * from t);
10 IN (SELECT * from t)
0
select NULL IN (SELECT * from t);
NULL IN (SELECT * from t)
NULL
update t set a=NULL where a=2;
select 1 IN (SELECT * from t);
1 IN (SELECT * from t)
1
select 3 IN (SELECT * from t);
3 IN (SELECT * from t)
1
select 10 IN (SELECT * from t);
10 IN (SELECT * from t)
NULL
select 1 > ALL (SELECT * from t);
1 > ALL (SELECT * from t)
0
select 10 > ALL (SELECT * from t);
10 > ALL (SELECT * from t)
NULL
select 1 > ANY (SELECT * from t);
1 > ANY (SELECT * from t)
NULL
select 10 > ANY (SELECT * from t);
10 > ANY (SELECT * from t)
1
drop table t;
create table t (a varchar(20));
insert into t values ('A'),('BC'),('DEF');
select 'A' IN (SELECT * from t);
'A' IN (SELECT * from t)
1
select 'XYZS' IN (SELECT * from t);
'XYZS' IN (SELECT * from t)
0
select NULL IN (SELECT * from t);
NULL IN (SELECT * from t)
NULL
update t set a=NULL where a='BC';
select 'A' IN (SELECT * from t);
'A' IN (SELECT * from t)
1
select 'DEF' IN (SELECT * from t);
'DEF' IN (SELECT * from t)
1
select 'XYZS' IN (SELECT * from t);
'XYZS' IN (SELECT * from t)
NULL
select 'A' > ALL (SELECT * from t);
'A' > ALL (SELECT * from t)
0
select 'XYZS' > ALL (SELECT * from t);
'XYZS' > ALL (SELECT * from t)
NULL
select 'A' > ANY (SELECT * from t);
'A' > ANY (SELECT * from t)
NULL
select 'XYZS' > ANY (SELECT * from t);
'XYZS' > ANY (SELECT * from t)
1
drop table t;
create table t (a float);
insert into t values (1.5),(2.5),(3.5);
select 1.5 IN (SELECT * from t);
1.5 IN (SELECT * from t)
1
select 10.5 IN (SELECT * from t);
10.5 IN (SELECT * from t)
0
select NULL IN (SELECT * from t);
NULL IN (SELECT * from t)
NULL
update t set a=NULL where a=2.5;
select 1.5 IN (SELECT * from t);
1.5 IN (SELECT * from t)
1
select 3.5 IN (SELECT * from t);
3.5 IN (SELECT * from t)
1
select 10.5 IN (SELECT * from t);
10.5 IN (SELECT * from t)
NULL
select 1.5 > ALL (SELECT * from t);
1.5 > ALL (SELECT * from t)
0
select 10.5 > ALL (SELECT * from t);
10.5 > ALL (SELECT * from t)
NULL
select 1.5 > ANY (SELECT * from t);
1.5 > ANY (SELECT * from t)
NULL
select 10.5 > ANY (SELECT * from t);
10.5 > ANY (SELECT * from t)
1
drop table t;
...@@ -21,9 +21,9 @@ select count(distinct a),count(distinct grp) from t1; ...@@ -21,9 +21,9 @@ select count(distinct a),count(distinct grp) from t1;
insert into t1 values (null,null,''); insert into t1 values (null,null,'');
select count(distinct a),count(distinct grp) from t1; select count(distinct a),count(distinct grp) from t1;
select sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1; select sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1;
select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp; select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
select grp, sum(a)+count(a)+avg(a)+std(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp; select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
create table t2 (grp int, a bigint unsigned, c char(10)); create table t2 (grp int, a bigint unsigned, c char(10));
insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp; insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
...@@ -40,8 +40,8 @@ CREATE TABLE t1 (id int(11),value1 float(10,2)); ...@@ -40,8 +40,8 @@ CREATE TABLE t1 (id int(11),value1 float(10,2));
INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00); INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00);
CREATE TABLE t2 (id int(11),name char(20)); CREATE TABLE t2 (id int(11),name char(20));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two'); INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
select id, avg(value1), std(value1) from t1 group by id; select id, avg(value1), std(value1), variance(value1) from t1 group by id;
select name, avg(value1), std(value1) from t1, t2 where t1.id = t2.id group by t1.id; select name, avg(value1), std(value1), variance(value1) from t1, t2 where t1.id = t2.id group by t1.id;
drop table t1,t2; drop table t1,t2;
# #
......
...@@ -2,7 +2,39 @@ ...@@ -2,7 +2,39 @@
# test of IN (NULL) # test of IN (NULL)
# #
select 1 in (1,2,3);
select 10 in (1,2,3);
select NULL in (1,2,3);
select 1 in (1,NULL,3);
select 3 in (1,NULL,3);
select 10 in (1,NULL,3);
select 1.5 in (1.5,2.5,3.5);
select 10.5 in (1.5,2.5,3.5);
select NULL in (1.5,2.5,3.5);
select 1.5 in (1.5,NULL,3.5);
select 3.5 in (1.5,NULL,3.5);
select 10.5 in (1.5,NULL,3.5);
drop table if exists t1; drop table if exists t1;
CREATE TABLE t1 (a int, b int, c int);
insert into t1 values (1,2,3), (1,NULL,3);
select 1 in (a,b,c) from t1;
select 3 in (a,b,c) from t1;
select 10 in (a,b,c) from t1;
select NULL in (a,b,c) from t1;
drop table t1;
CREATE TABLE t1 (a float, b float, c float);
insert into t1 values (1.5,2.5,3.5), (1.5,NULL,3.5);
select 1.5 in (a,b,c) from t1;
select 3.5 in (a,b,c) from t1;
select 10.5 in (a,b,c) from t1;
drop table t1;
CREATE TABLE t1 (a varchar(10), b varchar(10), c varchar(10));
insert into t1 values ('A','BC','EFD'), ('A',NULL,'EFD');
select 'A' in (a,b,c) from t1;
select 'EFD' in (a,b,c) from t1;
select 'XSFGGHF' in (a,b,c) from t1;
drop table t1;
CREATE TABLE t1 (field char(1)); CREATE TABLE t1 (field char(1));
INSERT INTO t1 VALUES ('A'),(NULL); INSERT INTO t1 VALUES ('A'),(NULL);
SELECT * from t1 WHERE field IN (NULL); SELECT * from t1 WHERE field IN (NULL);
......
...@@ -36,6 +36,11 @@ select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); ...@@ -36,6 +36,11 @@ select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c'); select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c');
select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ; select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ;
select soundex(''),soundex('he'),soundex('hello all folks'); select soundex(''),soundex('he'),soundex('hello all folks');
select 'mood' sounds like 'mud';
select 'Glazgo' sounds like 'Liverpool';
select null sounds like 'null';
select 'null' sounds like null;
select null sounds like null;
select md5('hello'); select md5('hello');
select sha('abc'); select sha('abc');
select sha1('abc'); select sha1('abc');
......
...@@ -59,4 +59,5 @@ select Fld1, max(Fld2) as q from t1 group by Fld1 having q is not null; ...@@ -59,4 +59,5 @@ select Fld1, max(Fld2) as q from t1 group by Fld1 having q is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having max(Fld2) is not null; select Fld1, max(Fld2) from t1 group by Fld1 having max(Fld2) is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having avg(Fld2) is not null; select Fld1, max(Fld2) from t1 group by Fld1 having avg(Fld2) is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null; select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having variance(Fld2) is not null;
drop table t1; drop table t1;
select row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'));
select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3));
select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3));
select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3));
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4)));
-- error 1239
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4));
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)));
SELECT ROW(1,2,3)=ROW(1,2,3); SELECT ROW(1,2,3)=ROW(1,2,3);
SELECT ROW(2,2,3)=ROW(1+1,2,3); SELECT ROW(2,2,3)=ROW(1+1,2,3);
SELECT ROW(1,2,3)=ROW(1+1,2,3); SELECT ROW(1,2,3)=ROW(1+1,2,3);
...@@ -12,12 +28,21 @@ SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5)); ...@@ -12,12 +28,21 @@ SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5));
SELECT ROW('test',2,3.33)=ROW('test',2,3.33); SELECT ROW('test',2,3.33)=ROW('test',2,3.33);
-- error 1239 -- error 1239
SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4); SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33));
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3));
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL));
-- error 1239
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,4);
drop table if exists t1; drop table if exists t1;
create table t1 ( a int, b int, c int); create table t1 ( a int, b int, c int);
insert into t1 values (1,2,3), (2,3,1), (3,2,1); insert into t1 values (1,2,3), (2,3,1), (3,2,1), (1,2,NULL);
select * from t1 where ROW(1,2,3)=ROW(a,b,c); select * from t1 where ROW(1,2,3)=ROW(a,b,c);
select * from t1 where ROW(0,2,3)=ROW(a,b,c); select * from t1 where ROW(0,2,3)=ROW(a,b,c);
select * from t1 where ROW(1,2,3)<ROW(a,b,c); select * from t1 where ROW(1,2,3)<ROW(a,b,c);
select ROW(a,2,3) IN(row(1,b,c), row(2,3,1)) from t1;
select ROW(c,2,3) IN(row(1,b,a), row(2,3,1)) from t1;
select ROW(a,b,c) IN(row(1,2,3), row(3,2,1)) from t1;
select ROW(1,2,3) IN(row(a,b,c), row(1,2,3)) from t1;
drop table t1; drop table t1;
-- error 1239 -- error 1239
......
...@@ -1577,8 +1577,8 @@ select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld ...@@ -1577,8 +1577,8 @@ select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld
select count(*) from t1; select count(*) from t1;
select companynr,count(*),sum(fld1) from t2 group by companynr; select companynr,count(*),sum(fld1) from t2 group by companynr;
select companynr,count(*) from t2 group by companynr order by companynr desc limit 5; select companynr,count(*) from t2 group by companynr order by companynr desc limit 5;
select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 where companynr = 34 and fld4<>""; select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 group by companynr limit 3; select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ; select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ;
......
...@@ -362,3 +362,48 @@ INSERT INTO t1 values (1),(1); ...@@ -362,3 +362,48 @@ INSERT INTO t1 values (1),(1);
-- error 1240 -- error 1240
UPDATE t SET id=(SELECT * FROM t1); UPDATE t SET id=(SELECT * FROM t1);
drop table t; drop table t;
#NULL test
create table t (a int);
insert into t values (1),(2),(3);
select 1 IN (SELECT * from t);
select 10 IN (SELECT * from t);
select NULL IN (SELECT * from t);
update t set a=NULL where a=2;
select 1 IN (SELECT * from t);
select 3 IN (SELECT * from t);
select 10 IN (SELECT * from t);
select 1 > ALL (SELECT * from t);
select 10 > ALL (SELECT * from t);
select 1 > ANY (SELECT * from t);
select 10 > ANY (SELECT * from t);
drop table t;
create table t (a varchar(20));
insert into t values ('A'),('BC'),('DEF');
select 'A' IN (SELECT * from t);
select 'XYZS' IN (SELECT * from t);
select NULL IN (SELECT * from t);
update t set a=NULL where a='BC';
select 'A' IN (SELECT * from t);
select 'DEF' IN (SELECT * from t);
select 'XYZS' IN (SELECT * from t);
select 'A' > ALL (SELECT * from t);
select 'XYZS' > ALL (SELECT * from t);
select 'A' > ANY (SELECT * from t);
select 'XYZS' > ANY (SELECT * from t);
drop table t;
create table t (a float);
insert into t values (1.5),(2.5),(3.5);
select 1.5 IN (SELECT * from t);
select 10.5 IN (SELECT * from t);
select NULL IN (SELECT * from t);
update t set a=NULL where a=2.5;
select 1.5 IN (SELECT * from t);
select 3.5 IN (SELECT * from t);
select 10.5 IN (SELECT * from t);
select 1.5 > ALL (SELECT * from t);
select 10.5 > ALL (SELECT * from t);
select 1.5 > ANY (SELECT * from t);
select 10.5 > ANY (SELECT * from t);
drop table t;
...@@ -46,6 +46,12 @@ Item::Item(): ...@@ -46,6 +46,12 @@ Item::Item():
loop_id= 0; loop_id= 0;
} }
Item_ref_in_optimizer::Item_ref_in_optimizer(Item_in_optimizer *master,
char *table_name_par,
char *field_name_par):
Item_ref(master->args, table_name_par, field_name_par), owner(master) {}
bool Item::check_loop(uint id) bool Item::check_loop(uint id)
{ {
DBUG_ENTER("Item::check_loop"); DBUG_ENTER("Item::check_loop");
...@@ -436,6 +442,20 @@ String *Item_copy_string::val_str(String *str) ...@@ -436,6 +442,20 @@ String *Item_copy_string::val_str(String *str)
return &str_value; return &str_value;
} }
double Item_ref_in_optimizer::val()
{
return owner->get_cache();
}
longlong Item_ref_in_optimizer::val_int()
{
return owner->get_cache_int();
}
String* Item_ref_in_optimizer::val_str(String* s)
{
return owner->get_cache_str(s);
}
/* /*
Functions to convert item to field (for send_fields) Functions to convert item to field (for send_fields)
*/ */
...@@ -511,10 +531,31 @@ bool Item_asterisk_remover::fix_fields(THD *thd, ...@@ -511,10 +531,31 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
res= item->fix_fields(thd, list, &item); res= item->fix_fields(thd, list, &item);
else else
thd->fatal_error= 1; // no item given => out of memory thd->fatal_error= 1; // no item given => out of memory
*ref= item;
DBUG_RETURN(res); DBUG_RETURN(res);
} }
double Item_ref_null_helper::val()
{
double tmp= (*ref)->val_result();
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
longlong Item_ref_null_helper::val_int()
{
longlong tmp= (*ref)->val_int_result();
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
String* Item_ref_null_helper::val_str(String* s)
{
String* tmp= (*ref)->str_result(s);
owner->was_null|= null_value= (*ref)->null_value;
return tmp;
}
bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate)
{
return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate));
}
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
...@@ -686,7 +727,7 @@ void Item_avg_field::make_field(Send_field *tmp_field) ...@@ -686,7 +727,7 @@ void Item_avg_field::make_field(Send_field *tmp_field)
init_make_field(tmp_field,FIELD_TYPE_DOUBLE); init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
} }
void Item_std_field::make_field(Send_field *tmp_field) void Item_variance_field::make_field(Send_field *tmp_field)
{ {
init_make_field(tmp_field,FIELD_TYPE_DOUBLE); init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
} }
......
...@@ -33,7 +33,8 @@ class Item { ...@@ -33,7 +33,8 @@ class Item {
enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM, enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM,
INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM, INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM,
COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM, COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM,
PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, CONST_ITEM, PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM,CONST_ITEM,
SUBSELECT_ITEM, ROW_ITEM}; SUBSELECT_ITEM, ROW_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
...@@ -72,7 +73,6 @@ class Item { ...@@ -72,7 +73,6 @@ class Item {
virtual double val_result() { return val(); } virtual double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); } virtual longlong val_int_result() { return val_int(); }
virtual String *str_result(String* tmp) { return val_str(tmp); } virtual String *str_result(String* tmp) { return val_str(tmp); }
virtual bool is_null_result() { return is_null(); }
virtual table_map used_tables() const { return (table_map) 0L; } virtual table_map used_tables() const { return (table_map) 0L; }
virtual bool basic_const_item() const { return 0; } virtual bool basic_const_item() const { return 0; }
virtual Item *new_item() { return 0; } /* Only for const items */ virtual Item *new_item() { return 0; } /* Only for const items */
...@@ -100,6 +100,8 @@ class Item { ...@@ -100,6 +100,8 @@ class Item {
virtual Item* el(uint i) { return this; } virtual Item* el(uint i) { return this; }
virtual Item** addr(uint i) { return 0; } virtual Item** addr(uint i) { return 0; }
virtual bool check_cols(uint c); virtual bool check_cols(uint c);
// It is not row => null inside is impossible
virtual bool null_inside() { return 0; };
}; };
...@@ -122,6 +124,25 @@ class Item_wrapper :public Item ...@@ -122,6 +124,25 @@ class Item_wrapper :public Item
String* val_str(String* s) { return item->val_str(s); } String* val_str(String* s) { return item->val_str(s); }
void make_field(Send_field* f) { item->make_field(f); } void make_field(Send_field* f) { item->make_field(f); }
bool check_cols(uint col) { return item->check_cols(col); } bool check_cols(uint col) { return item->check_cols(col); }
bool eq(const Item *item, bool binary_cmp) const
{ return item->eq(item, binary_cmp); }
bool is_null()
{
item->val_int();
return item->null_value;
}
bool get_date(TIME *ltime, bool fuzzydate)
{
return (null_value=item->get_date(ltime, fuzzydate));
}
bool send(THD *thd, String *tmp) { return item->send(thd, tmp); }
int save_in_field(Field *field, bool no_conversions)
{
return item->save_in_field(field, no_conversions);
}
void save_org_in_field(Field *field) { item->save_org_in_field(field); }
enum Item_result result_type () const { return item->result_type(); }
table_map used_tables() const { return item->used_tables(); }
}; };
...@@ -138,19 +159,6 @@ class Item_outer_select_context_saver :public Item_wrapper ...@@ -138,19 +159,6 @@ class Item_outer_select_context_saver :public Item_wrapper
bool fix_fields(THD *, struct st_table_list *, Item ** ref); bool fix_fields(THD *, struct st_table_list *, Item ** ref);
}; };
/*
To resolve '*' field moved to condition
*/
class Item_asterisk_remover :public Item_wrapper
{
public:
Item_asterisk_remover(Item *it)
{
item= it;
}
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
};
class st_select_lex; class st_select_lex;
class Item_ident :public Item class Item_ident :public Item
{ {
...@@ -188,7 +196,6 @@ class Item_field :public Item_ident ...@@ -188,7 +196,6 @@ class Item_field :public Item_ident
double val_result(); double val_result();
longlong val_int_result(); longlong val_int_result();
String *str_result(String* tmp); String *str_result(String* tmp);
bool is_null_result() { return result_field->is_null(); }
bool send(THD *thd, String *str_arg) bool send(THD *thd, String *str_arg)
{ {
return result_field->send(thd,str_arg); return result_field->send(thd,str_arg);
...@@ -384,9 +391,13 @@ class Item_string :public Item ...@@ -384,9 +391,13 @@ class Item_string :public Item
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
bool basic_const_item() const { return 1; } bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
Item *new_item() { return new Item_string(name,str_value.ptr(),max_length,default_charset_info); } Item *new_item()
{
return new Item_string(name, str_value.ptr(), max_length,
default_charset_info);
}
String *const_string() { return &str_value; } String *const_string() { return &str_value; }
inline void append(char *str,uint length) { str_value.append(str,length); } inline void append(char *str, uint length) { str_value.append(str, length); }
void print(String *str); void print(String *str);
}; };
...@@ -470,25 +481,25 @@ class Item_ref :public Item_ident ...@@ -470,25 +481,25 @@ class Item_ref :public Item_ident
double val() double val()
{ {
double tmp=(*ref)->val_result(); double tmp=(*ref)->val_result();
null_value=(*ref)->is_null_result(); null_value=(*ref)->null_value;
return tmp; return tmp;
} }
longlong val_int() longlong val_int()
{ {
longlong tmp=(*ref)->val_int_result(); longlong tmp=(*ref)->val_int_result();
null_value=(*ref)->is_null_result(); null_value=(*ref)->null_value;
return tmp; return tmp;
} }
String *val_str(String* tmp) String *val_str(String* tmp)
{ {
tmp=(*ref)->str_result(tmp); tmp=(*ref)->str_result(tmp);
null_value=(*ref)->is_null_result(); null_value=(*ref)->null_value;
return tmp; return tmp;
} }
bool is_null() bool is_null()
{ {
(void) (*ref)->val_int_result(); (void) (*ref)->val_int_result();
return (*ref)->is_null_result(); return (*ref)->null_value;
} }
bool get_date(TIME *ltime,bool fuzzydate) bool get_date(TIME *ltime,bool fuzzydate)
{ {
...@@ -505,6 +516,54 @@ class Item_ref :public Item_ident ...@@ -505,6 +516,54 @@ class Item_ref :public Item_ident
bool check_loop(uint id); bool check_loop(uint id);
}; };
class Item_in_subselect;
class Item_ref_null_helper: public Item_ref
{
protected:
Item_in_subselect* owner;
public:
Item_ref_null_helper(Item_in_subselect* master, Item **item,
char *table_name_par,char *field_name_par):
Item_ref(item, table_name_par, field_name_par), owner(master) {}
double val();
longlong val_int();
String* val_str(String* s);
bool get_date(TIME *ltime, bool fuzzydate);
};
/*
To resolve '*' field moved to condition
and register NULL values
*/
class Item_asterisk_remover :public Item_ref_null_helper
{
Item *item;
public:
Item_asterisk_remover(Item_in_subselect *master, Item *it,
char *table, char *field):
Item_ref_null_helper(master, &item, table, field),
item(it)
{}
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
};
class Item_in_optimizer;
class Item_ref_in_optimizer: public Item_ref
{
protected:
Item_in_optimizer* owner;
public:
Item_ref_in_optimizer(Item_in_optimizer* master,
char *table_name_par,char *field_name_par);
double val();
longlong val_int();
String* val_str(String* s);
bool fix_fields(THD *, struct st_table_list *, Item ** ref)
{
fixed= 1;
return 0;
}
};
/* /*
The following class is used to optimize comparing of date columns The following class is used to optimize comparing of date columns
......
This diff is collapsed.
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
/* compare and test functions */ /* compare and test functions */
#include "assert.h"
#ifdef __GNUC__ #ifdef __GNUC__
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
...@@ -38,16 +40,12 @@ class Arg_comparator: public Sql_alloc ...@@ -38,16 +40,12 @@ class Arg_comparator: public Sql_alloc
Arg_comparator() {}; Arg_comparator() {};
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {};
inline void seta(Item **item) { a= item; }
inline void setb(Item **item) { b= item; }
int set_compare_func(Item_bool_func2 *owner, Item_result type); int set_compare_func(Item_bool_func2 *owner, Item_result type);
inline int set_compare_func(Item_bool_func2 *owner) inline int set_compare_func(Item_bool_func2 *owner)
{ {
return set_compare_func(owner, item_cmp_type((*a)->result_type(), return set_compare_func(owner, item_cmp_type((*a)->result_type(),
(*b)->result_type())); (*b)->result_type()));
} }
inline int set_cmp_func(Item_bool_func2 *owner, inline int set_cmp_func(Item_bool_func2 *owner,
Item **a1, Item **a2, Item **a1, Item **a2,
Item_result type) Item_result type)
...@@ -87,6 +85,27 @@ class Item_bool_func :public Item_int_func ...@@ -87,6 +85,27 @@ class Item_bool_func :public Item_int_func
void fix_length_and_dec() { decimals=0; max_length=1; } void fix_length_and_dec() { decimals=0; max_length=1; }
}; };
class Item_in_optimizer: public Item_bool_func
{
protected:
char buffer[80];
longlong int_cache;
double flt_cache;
String *str_cache;
bool int_cache_ok, flt_cache_ok, str_cache_ok;
public:
Item_in_optimizer(Item *a,Item *b):
Item_bool_func(a,b), int_cache_ok(0), flt_cache_ok(0), str_cache_ok(0) {}
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
longlong val_int();
double get_cache();
longlong get_cache_int();
String *get_cache_str(String *s);
friend class Item_ref_in_optimizer;
};
class Item_bool_func2 :public Item_int_func class Item_bool_func2 :public Item_int_func
{ /* Bool with 2 string args */ { /* Bool with 2 string args */
protected: protected:
...@@ -358,6 +377,7 @@ class in_vector :public Sql_alloc ...@@ -358,6 +377,7 @@ class in_vector :public Sql_alloc
uint count; uint count;
public: public:
uint used_count; uint used_count;
in_vector() {}
in_vector(uint elements,uint element_length,qsort_cmp cmp_func) in_vector(uint elements,uint element_length,qsort_cmp cmp_func)
:base((char*) sql_calloc(elements*element_length)), :base((char*) sql_calloc(elements*element_length)),
size(element_length), compare(cmp_func), count(elements), size(element_length), compare(cmp_func), count(elements),
...@@ -372,7 +392,6 @@ class in_vector :public Sql_alloc ...@@ -372,7 +392,6 @@ class in_vector :public Sql_alloc
int find(Item *item); int find(Item *item);
}; };
class in_string :public in_vector class in_string :public in_vector
{ {
char buff[80]; char buff[80];
...@@ -384,7 +403,6 @@ class in_string :public in_vector ...@@ -384,7 +403,6 @@ class in_string :public in_vector
byte *get_value(Item *item); byte *get_value(Item *item);
}; };
class in_longlong :public in_vector class in_longlong :public in_vector
{ {
longlong tmp; longlong tmp;
...@@ -394,7 +412,6 @@ class in_longlong :public in_vector ...@@ -394,7 +412,6 @@ class in_longlong :public in_vector
byte *get_value(Item *item); byte *get_value(Item *item);
}; };
class in_double :public in_vector class in_double :public in_vector
{ {
double tmp; double tmp;
...@@ -404,7 +421,6 @@ class in_double :public in_vector ...@@ -404,7 +421,6 @@ class in_double :public in_vector
byte *get_value(Item *item); byte *get_value(Item *item);
}; };
/* /*
** Classes for easy comparing of non const items ** Classes for easy comparing of non const items
*/ */
...@@ -414,88 +430,201 @@ class cmp_item :public Sql_alloc ...@@ -414,88 +430,201 @@ class cmp_item :public Sql_alloc
public: public:
cmp_item() {} cmp_item() {}
virtual ~cmp_item() {} virtual ~cmp_item() {}
virtual void store_value(Item *item)=0; virtual void store_value(Item *item)= 0;
virtual int cmp(Item *item)=0; virtual int cmp(Item *item)= 0;
// for optimized IN with row
virtual int compare(cmp_item *item)= 0;
static cmp_item* get_comparator(Item *);
virtual cmp_item *make_same()= 0;
virtual void store_value_by_template(cmp_item *tmpl, Item *item)
{
store_value(item);
}
}; };
typedef int (*str_cmp_func_pointer)(const String *, const String *);
class cmp_item_string :public cmp_item
{
protected:
str_cmp_func_pointer str_cmp_func;
String *value_res;
public:
cmp_item_string (str_cmp_func_pointer cmp): str_cmp_func(cmp) {}
friend class cmp_item_sort_string;
friend class cmp_item_binary_string;
friend class cmp_item_sort_string_in_static;
friend class cmp_item_binary_string_in_static;
};
class cmp_item_sort_string :public cmp_item { class cmp_item_sort_string :public cmp_item_string
protected: {
protected:
char value_buff[80]; char value_buff[80];
String value,*value_res; String value;
public: public:
cmp_item_sort_string() :value(value_buff,sizeof(value_buff),default_charset_info) {} cmp_item_sort_string(str_cmp_func_pointer cmp):
cmp_item_string(cmp),
value(value_buff, sizeof(value_buff), default_charset_info) {}
cmp_item_sort_string():
cmp_item_string(&sortcmp),
value(value_buff, sizeof(value_buff), default_charset_info) {}
void store_value(Item *item) void store_value(Item *item)
{ {
value_res=item->val_str(&value); value_res= item->val_str(&value);
} }
int cmp(Item *arg) int cmp(Item *arg)
{ {
char buff[80]; char buff[80];
String tmp(buff,sizeof(buff),default_charset_info),*res; String tmp(buff, sizeof(buff), default_charset_info), *res;
if (!(res=arg->val_str(&tmp))) if (!(res= arg->val_str(&tmp)))
return 1; /* Can't be right */ return 1; /* Can't be right */
return sortcmp(value_res,res); return (*str_cmp_func)(value_res, res);
} }
int compare(cmp_item *c)
{
cmp_item_string *cmp= (cmp_item_string *)c;
return (*str_cmp_func)(value_res, cmp->value_res);
}
cmp_item *make_same();
}; };
class cmp_item_binary_string :public cmp_item_sort_string { class cmp_item_binary_string :public cmp_item_sort_string {
public: public:
cmp_item_binary_string() {} cmp_item_binary_string(): cmp_item_sort_string(&stringcmp) {}
int cmp(Item *arg) cmp_item *make_same();
{
char buff[80];
String tmp(buff,sizeof(buff),default_charset_info),*res;
if (!(res=arg->val_str(&tmp)))
return 1; /* Can't be right */
return stringcmp(value_res,res);
}
}; };
class cmp_item_int :public cmp_item class cmp_item_int :public cmp_item
{ {
longlong value; longlong value;
public: public:
void store_value(Item *item) void store_value(Item *item)
{ {
value=item->val_int(); value= item->val_int();
} }
int cmp(Item *arg) int cmp(Item *arg)
{ {
return value != arg->val_int(); return value != arg->val_int();
} }
int compare(cmp_item *c)
{
cmp_item_int *cmp= (cmp_item_int *)c;
return (value < cmp->value) ? -1 : ((value == cmp->value) ? 0 : 1);
}
cmp_item *make_same();
}; };
class cmp_item_real :public cmp_item class cmp_item_real :public cmp_item
{ {
double value; double value;
public: public:
void store_value(Item *item) void store_value(Item *item)
{ {
value= item->val(); value= item->val();
} }
int cmp(Item *arg) int cmp(Item *arg)
{ {
return value != arg->val(); return value != arg->val();
} }
int compare(cmp_item *c)
{
cmp_item_real *cmp= (cmp_item_real *)c;
return (value < cmp->value)? -1 : ((value == cmp->value) ? 0 : 1);
}
cmp_item *make_same();
};
class cmp_item_row :public cmp_item
{
cmp_item **comparators;
uint n;
public:
cmp_item_row(): comparators(0), n(0) {}
~cmp_item_row()
{
if(comparators)
for(uint i= 0; i < n; i++)
if (comparators[i])
delete comparators[i];
}
void store_value(Item *item);
int cmp(Item *arg);
int compare(cmp_item *arg);
cmp_item *make_same();
void store_value_by_template(cmp_item *tmpl, Item *);
};
class in_row :public in_vector
{
cmp_item_row tmp;
public:
in_row(uint elements, Item *);
void set(uint pos,Item *item);
byte *get_value(Item *item);
}; };
/*
cmp_item for optimized IN with row (right part string, which never
be changed)
*/
class cmp_item_sort_string_in_static :public cmp_item_string
{
protected:
String value;
public:
cmp_item_sort_string_in_static(str_cmp_func_pointer cmp):
cmp_item_string(cmp) {}
cmp_item_sort_string_in_static(): cmp_item_string(&sortcmp) {}
void store_value(Item *item)
{
value_res= item->val_str(&value);
}
int cmp(Item *item)
{
// Should never be called
DBUG_ASSERT(0);
return 1;
}
int compare(cmp_item *c)
{
cmp_item_string *cmp= (cmp_item_string *)c;
return (*str_cmp_func)(value_res, cmp->value_res);
}
cmp_item * make_same()
{
return new cmp_item_sort_string_in_static();
}
};
class cmp_item_binary_string_in_static :public cmp_item_sort_string_in_static {
public:
cmp_item_binary_string_in_static():
cmp_item_sort_string_in_static(&stringcmp) {}
cmp_item * make_same()
{
return new cmp_item_binary_string_in_static();
}
};
class Item_func_in :public Item_int_func class Item_func_in :public Item_int_func
{ {
Item *item; Item *item;
in_vector *array; in_vector *array;
cmp_item *in_item; cmp_item *in_item;
bool have_null;
public: public:
Item_func_in(Item *a,List<Item> &list) Item_func_in(Item *a,List<Item> &list)
:Item_int_func(list),item(a),array(0),in_item(0) {} :Item_int_func(list), item(a), array(0), in_item(0), have_null(0)
{
allowed_arg_cols= item->cols();
}
longlong val_int(); longlong val_int();
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{ {
bool res=(item->check_cols(1) || // We do not check item->cols(), because allowed_arg_cols assigned from it
item->fix_fields(thd, tlist, &item) || bool res=(item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref)); Item_func::fix_fields(thd, tlist, ref));
with_sum_func= with_sum_func || item->with_sum_func; with_sum_func= with_sum_func || item->with_sum_func;
return res; return res;
...@@ -517,10 +646,9 @@ class Item_func_in :public Item_int_func ...@@ -517,10 +646,9 @@ class Item_func_in :public Item_int_func
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id)); DBUG_RETURN(item->check_loop(id));
} }
bool nulls_in_row();
}; };
/* Functions used by where clause */ /* Functions used by where clause */
class Item_func_isnull :public Item_bool_func class Item_func_isnull :public Item_bool_func
......
...@@ -18,8 +18,10 @@ ...@@ -18,8 +18,10 @@
#include "assert.h" #include "assert.h"
Item_row::Item_row(List<Item> &arg): Item_row::Item_row(List<Item> &arg):
Item(), array_holder(1) Item(), array_holder(1), used_tables_cache(0), const_item_cache(1)
{ {
//TODO: think placing 2-3 component items in item (as it done for function)
if ((arg_count= arg.elements)) if ((arg_count= arg.elements))
items= (Item**) sql_alloc(sizeof(Item*)*arg_count); items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
else else
...@@ -45,16 +47,31 @@ void Item_row::illegal_method_call(const char *method) ...@@ -45,16 +47,31 @@ void Item_row::illegal_method_call(const char *method)
bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref) bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
{ {
tables= 0; null_value= 0;
maybe_null= 0;
for (uint i= 0; i < arg_count; i++) for (uint i= 0; i < arg_count; i++)
{ {
if (items[i]->fix_fields(thd, tabl, items+i)) if (items[i]->fix_fields(thd, tabl, items+i))
return 1; return 1;
tables |= items[i]->used_tables(); used_tables_cache |= items[i]->used_tables();
const_item_cache&= items[i]->const_item();
maybe_null|= items[i]->maybe_null;
} }
return 0; return 0;
} }
void Item_row::update_used_tables()
{
used_tables_cache= 0;
const_item_cache= 1;
for (uint i= 0; i < arg_count; i++)
{
items[i]->update_used_tables();
used_tables_cache|= items[i]->used_tables();
const_item_cache&= items[i]->const_item();
}
}
bool Item_row::check_cols(uint c) bool Item_row::check_cols(uint c)
{ {
if (c != arg_count) if (c != arg_count)
...@@ -64,3 +81,22 @@ bool Item_row::check_cols(uint c) ...@@ -64,3 +81,22 @@ bool Item_row::check_cols(uint c)
} }
return 0; return 0;
} }
bool Item_row::null_inside()
{
for (uint i= 0; i < arg_count; i++)
{
if (items[i]->cols() > 1)
{
if (items[i]->null_inside())
return 1;
}
else
{
items[i]->val_int();
if (items[i]->null_value)
return 1;
}
}
return 0;
}
...@@ -17,13 +17,17 @@ ...@@ -17,13 +17,17 @@
class Item_row: public Item class Item_row: public Item
{ {
bool array_holder; bool array_holder;
table_map tables; table_map used_tables_cache;
bool const_item_cache;
uint arg_count; uint arg_count;
Item **items; Item **items;
public: public:
Item_row(List<Item> &); Item_row(List<Item> &);
Item_row(Item_row *item): Item_row(Item_row *item):
Item(), array_holder(0), tables(item->tables), arg_count(item->arg_count), Item(), array_holder(0),
used_tables_cache(item->used_tables_cache),
const_item_cache(item->const_item_cache),
arg_count(item->arg_count),
items(item->items) items(item->items)
{} {}
...@@ -56,11 +60,14 @@ class Item_row: public Item ...@@ -56,11 +60,14 @@ class Item_row: public Item
return 0; return 0;
}; };
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
table_map used_tables() const { return tables; }; table_map used_tables() const { return used_tables_cache; };
bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; } enum Item_result result_type() const { return ROW_RESULT; }
void update_used_tables();
virtual uint cols() { return arg_count; } uint cols() { return arg_count; }
virtual Item* el(uint i) { return items[i]; } Item* el(uint i) { return items[i]; }
virtual Item** addr(uint i) { return items + i; } Item** addr(uint i) { return items + i; }
virtual bool check_cols(uint c); bool check_cols(uint c);
bool null_inside();
}; };
...@@ -33,9 +33,10 @@ SUBSELECT TODO: ...@@ -33,9 +33,10 @@ SUBSELECT TODO:
#include "sql_select.h" #include "sql_select.h"
Item_subselect::Item_subselect(): Item_subselect::Item_subselect():
Item_result_field(), engine_owner(1), value_assigned(0), substitution(0) Item_result_field(), engine_owner(1), value_assigned(0), substitution(0),
have_to_be_excluded(0)
{ {
assign_null(); reset();
/* /*
item value is NULL if select_subselect not changed this value item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned) (i.e. some rows will be found returned)
...@@ -93,8 +94,10 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -93,8 +94,10 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
(*ref)= substitution; (*ref)= substitution;
substitution->name= name; substitution->name= name;
engine->exclude(); if (have_to_be_excluded)
return substitution->fix_fields(thd, tables, ref); engine->exclude();
substitution= 0;
return (*ref)->fix_fields(thd, tables, ref);
} }
char const *save_where= thd->where; char const *save_where= thd->where;
...@@ -159,7 +162,7 @@ double Item_singleval_subselect::val () ...@@ -159,7 +162,7 @@ double Item_singleval_subselect::val ()
{ {
if (engine->exec()) if (engine->exec())
{ {
assign_null(); reset();
return 0; return 0;
} }
return real_value; return real_value;
...@@ -169,7 +172,7 @@ longlong Item_singleval_subselect::val_int () ...@@ -169,7 +172,7 @@ longlong Item_singleval_subselect::val_int ()
{ {
if (engine->exec()) if (engine->exec())
{ {
assign_null(); reset();
return 0; return 0;
} }
return int_value; return int_value;
...@@ -179,7 +182,7 @@ String *Item_singleval_subselect::val_str (String *str) ...@@ -179,7 +182,7 @@ String *Item_singleval_subselect::val_str (String *str)
{ {
if (engine->exec() || null_value) if (engine->exec() || null_value)
{ {
assign_null(); reset();
return 0; return 0;
} }
return &string_value; return &string_value;
...@@ -208,9 +211,8 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp, ...@@ -208,9 +211,8 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
left_expr= left_exp; left_expr= left_exp;
init(thd, select_lex, new select_exists_subselect(this)); init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX; max_columns= UINT_MAX;
null_value= 0; //can't be NULL maybe_null= 1;
maybe_null= 0; //can't be NULL reset();
value= 0;
// We need only 1 row to determinate existence // We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1; select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -226,9 +228,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp, ...@@ -226,9 +228,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
func= f; func= f;
init(thd, select_lex, new select_exists_subselect(this)); init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX; max_columns= UINT_MAX;
null_value= 0; //can't be NULL reset();
maybe_null= 0; //can't be NULL
value= 0;
// We need only 1 row to determinate existence // We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1; select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -237,14 +237,15 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp, ...@@ -237,14 +237,15 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
void Item_exists_subselect::fix_length_and_dec() void Item_exists_subselect::fix_length_and_dec()
{ {
max_length= 1; decimals=0;
max_length= 1;
} }
double Item_exists_subselect::val () double Item_exists_subselect::val ()
{ {
if (engine->exec()) if (engine->exec())
{ {
assign_null(); reset();
return 0; return 0;
} }
return (double) value; return (double) value;
...@@ -254,7 +255,7 @@ longlong Item_exists_subselect::val_int () ...@@ -254,7 +255,7 @@ longlong Item_exists_subselect::val_int ()
{ {
if (engine->exec()) if (engine->exec())
{ {
assign_null(); reset();
return 0; return 0;
} }
return value; return value;
...@@ -264,7 +265,50 @@ String *Item_exists_subselect::val_str(String *str) ...@@ -264,7 +265,50 @@ String *Item_exists_subselect::val_str(String *str)
{ {
if (engine->exec()) if (engine->exec())
{ {
assign_null(); reset();
return 0;
}
str->set(value,thd_charset());
return str;
}
double Item_in_subselect::val ()
{
if (engine->exec())
{
reset();
null_value= 1;
return 0;
}
if (was_null && !value)
null_value= 1;
return (double) value;
}
longlong Item_in_subselect::val_int ()
{
if (engine->exec())
{
reset();
null_value= 1;
return 0;
}
if (was_null && !value)
null_value= 1;
return value;
}
String *Item_in_subselect::val_str(String *str)
{
if (engine->exec())
{
reset();
null_value= 1;
return 0;
}
if (was_null && !value)
{
null_value= 1;
return 0; return 0;
} }
str->set(value,thd_charset()); str->set(value,thd_charset());
...@@ -288,8 +332,23 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -288,8 +332,23 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
compare_func_creator func) compare_func_creator func)
{ {
DBUG_ENTER("Item_in_subselect::single_value_transformer"); DBUG_ENTER("Item_in_subselect::single_value_transformer");
Item_in_optimizer *optimizer;
substitution= optimizer= new Item_in_optimizer(left_expr, this);
if (!optimizer)
{
current_thd->fatal_error= 1;
DBUG_VOID_RETURN;
}
/*
As far as Item_ref_in_optimizer do not substitude itself on fix_fields
we can use same item for all selects.
*/
Item *expr= new Item_ref_in_optimizer(optimizer, (char *)"<no matter>",
(char*)"<left expr>");
select_lex->master_unit()->dependent= 1;
for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select()) for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select())
{ {
select_lex->dependent= 1;
Item *item; Item *item;
if (sl->item_list.elements > 1) if (sl->item_list.elements > 1)
{ {
...@@ -299,14 +358,14 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -299,14 +358,14 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
else else
item= (Item*) sl->item_list.pop(); item= (Item*) sl->item_list.pop();
Item *expr= new Item_outer_select_context_saver(left_expr);
if (sl->having || sl->with_sum_func || sl->group_list.first || if (sl->having || sl->with_sum_func || sl->group_list.first ||
sl->order_list.first) sl->order_list.first)
{ {
sl->item_list.push_back(item); sl->item_list.push_back(item);
item= (*func)(expr, new Item_ref(sl->item_list.head_ref(), item= (*func)(expr, new Item_ref_null_helper(this,
0, (char*)"<result>")); sl->item_list.head_ref(),
(char *)"<no matter>",
(char*)"<result>"));
if (sl->having || sl->with_sum_func || sl->group_list.first) if (sl->having || sl->with_sum_func || sl->group_list.first)
if (sl->having) if (sl->having)
sl->having= new Item_cond_and(sl->having, item); sl->having= new Item_cond_and(sl->having, item);
...@@ -324,7 +383,9 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -324,7 +383,9 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
sl->item_list.push_back(new Item_int(1)); sl->item_list.push_back(new Item_int(1));
if (sl->table_list.elements) if (sl->table_list.elements)
{ {
item= (*func)(expr, new Item_asterisk_remover(item)); item= (*func)(expr, new Item_asterisk_remover(this, item,
(char *)"<no matter>",
(char*)"<result>"));
if (sl->where) if (sl->where)
sl->where= new Item_cond_and(sl->where, item); sl->where= new Item_cond_and(sl->where, item);
else else
...@@ -340,14 +401,21 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -340,14 +401,21 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
} }
if (select_lex->next_select()) if (select_lex->next_select())
{ {
// it is in union => we should perform it /*
sl->having= (*func)(expr, item); It is in union => we should perform it.
Item_asterisk_remover used only as wrapper to receine NULL value
*/
sl->having= (*func)(expr,
new Item_asterisk_remover(this, item,
(char *)"<no matter>",
(char*)"<result>"));
} }
else else
{ {
// it is single select without tables => possible optimization // it is single select without tables => possible optimization
item= (*func)(left_expr, item); item= (*func)(left_expr, item);
substitution= item; substitution= item;
have_to_be_excluded= 1;
THD *thd= current_thd; THD *thd= current_thd;
if (thd->lex.describe) if (thd->lex.describe)
{ {
...@@ -489,7 +557,7 @@ int subselect_single_select_engine::exec() ...@@ -489,7 +557,7 @@ int subselect_single_select_engine::exec()
join->thd->where= save_where; join->thd->where= save_where;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
item->assign_null(); item->reset();
item->assigned((executed= 0)); item->assigned((executed= 0));
} }
if (!executed) if (!executed)
......
...@@ -42,6 +42,8 @@ class Item_subselect :public Item_result_field ...@@ -42,6 +42,8 @@ class Item_subselect :public Item_result_field
subselect_engine *engine; subselect_engine *engine;
/* allowed number of columns (1 for single value subqueries) */ /* allowed number of columns (1 for single value subqueries) */
uint max_columns; uint max_columns;
/* work with 'substitution' */
bool have_to_be_excluded;
public: public:
Item_subselect(); Item_subselect();
...@@ -65,7 +67,7 @@ class Item_subselect :public Item_result_field ...@@ -65,7 +67,7 @@ class Item_subselect :public Item_result_field
select_subselect *result); select_subselect *result);
~Item_subselect(); ~Item_subselect();
virtual void assign_null() virtual void reset()
{ {
null_value= 1; null_value= 1;
} }
...@@ -110,7 +112,7 @@ class Item_singleval_subselect :public Item_subselect ...@@ -110,7 +112,7 @@ class Item_singleval_subselect :public Item_subselect
decimals= item->decimals; decimals= item->decimals;
res_type= item->res_type; res_type= item->res_type;
} }
virtual void assign_null() virtual void reset()
{ {
null_value= 1; null_value= 1;
int_value= 0; int_value= 0;
...@@ -144,7 +146,7 @@ class Item_exists_subselect :public Item_subselect ...@@ -144,7 +146,7 @@ class Item_exists_subselect :public Item_subselect
} }
Item_exists_subselect(): Item_subselect() {} Item_exists_subselect(): Item_subselect() {}
virtual void assign_null() virtual void reset()
{ {
value= 0; value= 0;
} }
...@@ -155,6 +157,7 @@ class Item_exists_subselect :public Item_subselect ...@@ -155,6 +157,7 @@ class Item_exists_subselect :public Item_subselect
double val(); double val();
String *val_str(String*); String *val_str(String*);
void fix_length_and_dec(); void fix_length_and_dec();
friend class select_exists_subselect; friend class select_exists_subselect;
}; };
...@@ -164,14 +167,26 @@ class Item_in_subselect :public Item_exists_subselect ...@@ -164,14 +167,26 @@ class Item_in_subselect :public Item_exists_subselect
{ {
protected: protected:
Item * left_expr; Item * left_expr;
bool was_null;
public: public:
Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex); Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex);
Item_in_subselect(Item_in_subselect *item); Item_in_subselect(Item_in_subselect *item);
Item_in_subselect(): Item_exists_subselect() {} Item_in_subselect(): Item_exists_subselect() {}
void reset()
{
value= 0;
null_value= 0;
was_null= 0;
}
virtual void select_transformer(st_select_lex *select_lex); virtual void select_transformer(st_select_lex *select_lex);
void single_value_transformer(st_select_lex *select_lex, void single_value_transformer(st_select_lex *select_lex,
Item *left_expr, compare_func_creator func); Item *left_expr, compare_func_creator func);
longlong val_int();
double val();
String *val_str(String*);
friend class Item_asterisk_remover;
friend class Item_ref_null_helper;
}; };
/* ALL/ANY/SOME subselect */ /* ALL/ANY/SOME subselect */
......
...@@ -253,12 +253,24 @@ double Item_sum_avg::val() ...@@ -253,12 +253,24 @@ double Item_sum_avg::val()
** Standard deviation ** Standard deviation
*/ */
void Item_sum_std::reset() double Item_sum_std::val()
{ {
sum=sum_sqr=0.0; count=0; (void) Item_sum_std::add(); double tmp= Item_sum_variance::val();
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
} }
bool Item_sum_std::add() /*
** variance
*/
void Item_sum_variance::reset()
{
sum=sum_sqr=0.0;
count=0;
(void) Item_sum_variance::add();
}
bool Item_sum_variance::add()
{ {
double nr=args[0]->val(); double nr=args[0]->val();
if (!args[0]->null_value) if (!args[0]->null_value)
...@@ -270,7 +282,7 @@ bool Item_sum_std::add() ...@@ -270,7 +282,7 @@ bool Item_sum_std::add()
return 0; return 0;
} }
double Item_sum_std::val() double Item_sum_variance::val()
{ {
if (!count) if (!count)
{ {
...@@ -281,11 +293,10 @@ double Item_sum_std::val() ...@@ -281,11 +293,10 @@ double Item_sum_std::val()
/* Avoid problems when the precision isn't good enough */ /* Avoid problems when the precision isn't good enough */
double tmp=ulonglong2double(count); double tmp=ulonglong2double(count);
double tmp2=(sum_sqr - sum*sum/tmp)/tmp; double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2); return tmp2 <= 0.0 ? 0.0 : tmp2;
} }
void Item_sum_variance::reset_field()
void Item_sum_std::reset_field()
{ {
double nr=args[0]->val(); double nr=args[0]->val();
char *res=result_field->ptr; char *res=result_field->ptr;
...@@ -302,7 +313,7 @@ void Item_sum_std::reset_field() ...@@ -302,7 +313,7 @@ void Item_sum_std::reset_field()
} }
} }
void Item_sum_std::update_field(int offset) void Item_sum_variance::update_field(int offset)
{ {
double nr,old_nr,old_sqr; double nr,old_nr,old_sqr;
longlong field_count; longlong field_count;
...@@ -836,6 +847,17 @@ String *Item_avg_field::val_str(String *str) ...@@ -836,6 +847,17 @@ String *Item_avg_field::val_str(String *str)
} }
Item_std_field::Item_std_field(Item_sum_std *item) Item_std_field::Item_std_field(Item_sum_std *item)
: Item_variance_field(item)
{
}
double Item_std_field::val()
{
double tmp= Item_variance_field::val();
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
Item_variance_field::Item_variance_field(Item_sum_variance *item)
{ {
name=item->name; name=item->name;
decimals=item->decimals; decimals=item->decimals;
...@@ -844,7 +866,7 @@ Item_std_field::Item_std_field(Item_sum_std *item) ...@@ -844,7 +866,7 @@ Item_std_field::Item_std_field(Item_sum_std *item)
maybe_null=1; maybe_null=1;
} }
double Item_std_field::val() double Item_variance_field::val()
{ {
double sum,sum_sqr; double sum,sum_sqr;
longlong count; longlong count;
...@@ -860,10 +882,10 @@ double Item_std_field::val() ...@@ -860,10 +882,10 @@ double Item_std_field::val()
null_value=0; null_value=0;
double tmp= (double) count; double tmp= (double) count;
double tmp2=(sum_sqr - sum*sum/tmp)/tmp; double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2); return tmp2 <= 0.0 ? 0.0 : tmp2;
} }
String *Item_std_field::val_str(String *str) String *Item_variance_field::val_str(String *str)
{ {
double nr=val(); double nr=val();
if (null_value) if (null_value)
......
...@@ -27,7 +27,7 @@ class Item_sum :public Item_result_field ...@@ -27,7 +27,7 @@ class Item_sum :public Item_result_field
{ {
public: public:
enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC, enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC,
MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,SUM_BIT_FUNC, MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
UDF_SUM_FUNC }; UDF_SUM_FUNC };
Item **args,*tmp_args[2]; Item **args,*tmp_args[2];
...@@ -235,14 +235,14 @@ class Item_sum_avg :public Item_sum_num ...@@ -235,14 +235,14 @@ class Item_sum_avg :public Item_sum_num
const char *func_name() const { return "avg"; } const char *func_name() const { return "avg"; }
}; };
class Item_sum_std; class Item_sum_variance;
class Item_std_field :public Item_result_field class Item_variance_field :public Item_result_field
{ {
public: public:
Field *field; Field *field;
Item_std_field(Item_sum_std *item); Item_variance_field(Item_sum_variance *item);
enum Type type() const { return FIELD_STD_ITEM; } enum Type type() const {return FIELD_VARIANCE_ITEM; }
double val(); double val();
longlong val_int() { return (longlong) val(); } longlong val_int() { return (longlong) val(); }
String *val_str(String*); String *val_str(String*);
...@@ -251,26 +251,63 @@ class Item_std_field :public Item_result_field ...@@ -251,26 +251,63 @@ class Item_std_field :public Item_result_field
void fix_length_and_dec() {} void fix_length_and_dec() {}
}; };
class Item_sum_std :public Item_sum_num /*
variance(a) =
= sum (ai - avg(a))^2 / count(a) )
= sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a)
= (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) =
= (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) =
= (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) =
= (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) =
= (sum(ai^2) - sum(a)^2/count(a))/count(a)
*/
class Item_sum_variance : public Item_sum_num
{ {
double sum; double sum, sum_sqr;
double sum_sqr;
ulonglong count; ulonglong count;
void fix_length_and_dec() { decimals+=4; maybe_null=1; } void fix_length_and_dec() { decimals+=4; maybe_null=1; }
public: public:
Item_sum_std(Item *item_par) :Item_sum_num(item_par),count(0) {} Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {}
enum Sumfunctype sum_func () const { return STD_FUNC; } enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void reset(); void reset();
bool add(); bool add();
double val(); double val();
void reset_field(); void reset_field();
void update_field(int offset); void update_field(int offset);
Item *result_item(Field *field) Item *result_item(Field *field)
{ return new Item_std_field(this); } { return new Item_variance_field(this); }
const char *func_name() const { return "std"; } const char *func_name() const { return "variance"; }
}; };
class Item_sum_std;
class Item_std_field :public Item_variance_field
{
public:
Item_std_field(Item_sum_std *item);
enum Type type() const { return FIELD_STD_ITEM; }
double val();
};
/*
standard_deviation(a) = sqrt(variance(a))
*/
class Item_sum_std :public Item_sum_variance
{
public:
Item_sum_std(Item *item_par) :Item_sum_variance(item_par){}
enum Sumfunctype sum_func () const { return STD_FUNC; }
double val();
Item *result_item(Field *field)
{ return new Item_std_field(this); }
const char *func_name() const { return "std"; }
};
// This class is a string or number function depending on num_func // This class is a string or number function depending on num_func
......
...@@ -344,6 +344,7 @@ static SYMBOL symbols[] = { ...@@ -344,6 +344,7 @@ static SYMBOL symbols[] = {
{ "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0}, { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0}, { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0},
{ "SQL_THREAD", SYM(SQL_THREAD),0,0}, { "SQL_THREAD", SYM(SQL_THREAD),0,0},
{ "SOUNDS", SYM(SOUNDS_SYM),0,0},
{ "SSL", SYM(SSL_SYM),0,0}, { "SSL", SYM(SSL_SYM),0,0},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0}, { "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0},
{ "START", SYM(START_SYM),0,0}, { "START", SYM(START_SYM),0,0},
...@@ -584,6 +585,7 @@ static SYMBOL sql_functions[] = { ...@@ -584,6 +585,7 @@ static SYMBOL sql_functions[] = {
{ "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP),0,0}, { "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP),0,0},
{ "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, { "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "USER", SYM(USER),0,0}, { "USER", SYM(USER),0,0},
{ "VARIANCE", SYM(VARIANCE_SYM),0,0},
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)}, { "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0}, { "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)}, { "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
......
...@@ -184,7 +184,6 @@ static uint handler_count; ...@@ -184,7 +184,6 @@ static uint handler_count;
static bool opt_enable_named_pipe = 0; static bool opt_enable_named_pipe = 0;
#endif #endif
#ifdef __WIN__ #ifdef __WIN__
static bool opt_console=0,start_mode=0;
static pthread_cond_t COND_handler_count; static pthread_cond_t COND_handler_count;
static uint handler_count; static uint handler_count;
static bool opt_console=0, start_mode=0, use_opt_args; static bool opt_console=0, start_mode=0, use_opt_args;
...@@ -2160,7 +2159,7 @@ The server will not act as a slave."); ...@@ -2160,7 +2159,7 @@ The server will not act as a slave.");
(void) thr_setconcurrency(concurrency); // 10 by default (void) thr_setconcurrency(concurrency); // 10 by default
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY) //IRENA #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY) //IRENA
{ {
hEventShutdown=CreateEvent(0, FALSE, FALSE, event_name); hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
pthread_t hThread; pthread_t hThread;
if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0)) if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
sql_print_error("Warning: Can't create thread to handle shutdown requests"); sql_print_error("Warning: Can't create thread to handle shutdown requests");
......
...@@ -933,9 +933,9 @@ bool select_singleval_subselect::send_data(List<Item> &items) ...@@ -933,9 +933,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
calculate value on it & determinate "is it NULL?". calculate value on it & determinate "is it NULL?".
*/ */
it->real_value= val_item->val_result(); it->real_value= val_item->val_result();
if ((it->null_value= val_item->is_null_result())) if ((it->null_value= val_item->null_value))
{ {
it->assign_null(); it->reset();
} }
else else
{ {
......
...@@ -25,8 +25,16 @@ ...@@ -25,8 +25,16 @@
class Sql_alloc class Sql_alloc
{ {
public: public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } static void *operator new(size_t size)
{
return (void*) sql_alloc((uint) size);
}
static void *operator new[](size_t size)
{
return (void*) sql_alloc((uint) size);
}
static void operator delete(void *ptr, size_t size) {} /*lint -e715 */ static void operator delete(void *ptr, size_t size) {} /*lint -e715 */
static void operator delete[](void *ptr, size_t size) {}
#ifdef HAVE_purify #ifdef HAVE_purify
bool dummy; bool dummy;
inline Sql_alloc() :dummy(0) {} inline Sql_alloc() :dummy(0) {}
......
...@@ -793,6 +793,16 @@ JOIN::exec() ...@@ -793,6 +793,16 @@ JOIN::exec()
HA_POS_ERROR))) HA_POS_ERROR)))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
/*
We don't have to store rows in temp table that doesn't match HAVING if:
- we are sorting the table and writing complete group rows to the
temp table.
- We are using DISTINCT without resolving the distinct as a GROUP BY
on all columns.
If having is not handled here, it will be checked before the row
is sent to the client.
*/
if (having_list && if (having_list &&
(sort_and_group || (exec_tmp_table->distinct && !group_list))) (sort_and_group || (exec_tmp_table->distinct && !group_list)))
having=having_list; having=having_list;
...@@ -3775,13 +3785,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -3775,13 +3785,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
else else
return new Field_double(item_sum->max_length,maybe_null, return new Field_double(item_sum->max_length,maybe_null,
item->name, table, item_sum->decimals); item->name, table, item_sum->decimals);
case Item_sum::STD_FUNC: /* Place for sum & count */ case Item_sum::VARIANCE_FUNC: /* Place for sum & count */
case Item_sum::STD_FUNC:
if (group) if (group)
return new Field_string(sizeof(double)*2+sizeof(longlong), return new Field_string(sizeof(double)*2+sizeof(longlong),
maybe_null, item->name,table,my_charset_bin); maybe_null, item->name,table,my_charset_bin);
else else
return new Field_double(item_sum->max_length, maybe_null, return new Field_double(item_sum->max_length, maybe_null,
item->name,table,item_sum->decimals); item->name,table,item_sum->decimals);
case Item_sum::UNIQUE_USERS_FUNC: case Item_sum::UNIQUE_USERS_FUNC:
return new Field_long(9,maybe_null,item->name,table,1); return new Field_long(9,maybe_null,item->name,table,1);
default: default:
......
...@@ -216,7 +216,7 @@ int st_select_lex_unit::exec() ...@@ -216,7 +216,7 @@ int st_select_lex_unit::exec()
if (optimized && item && item->assigned()) if (optimized && item && item->assigned())
{ {
item->assigned(0); // We will reinit & rexecute unit item->assigned(0); // We will reinit & rexecute unit
item->assign_null(); item->reset();
table->file->delete_all_rows(); table->file->delete_all_rows();
} }
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
......
...@@ -100,6 +100,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -100,6 +100,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DIV_SYM %token DIV_SYM
%token EQ %token EQ
%token EQUAL_SYM %token EQUAL_SYM
%token SOUNDS_SYM
%token GE %token GE
%token GT_SYM %token GT_SYM
%token LE %token LE
...@@ -158,6 +159,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -158,6 +159,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SQL_THREAD %token SQL_THREAD
%token START_SYM %token START_SYM
%token STD_SYM %token STD_SYM
%token VARIANCE_SYM
%token STOP_SYM %token STOP_SYM
%token SUM_SYM %token SUM_SYM
%token SUPER_SYM %token SUPER_SYM
...@@ -1833,6 +1835,7 @@ expr_expr: ...@@ -1833,6 +1835,7 @@ expr_expr:
| expr OR expr { $$= new Item_cond_or($1,$3); } | expr OR expr { $$= new Item_cond_or($1,$3); }
| expr XOR expr { $$= new Item_cond_xor($1,$3); } | expr XOR expr { $$= new Item_cond_xor($1,$3); }
| expr AND expr { $$= new Item_cond_and($1,$3); } | expr AND expr { $$= new Item_cond_and($1,$3); }
| expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); } | expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5));} | expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5));}
| expr REGEXP expr { $$= new Item_func_regex($1,$3); } | expr REGEXP expr { $$= new Item_func_regex($1,$3); }
...@@ -1879,6 +1882,7 @@ no_in_expr: ...@@ -1879,6 +1882,7 @@ no_in_expr:
| no_in_expr OR expr { $$= new Item_cond_or($1,$3); } | no_in_expr OR expr { $$= new Item_cond_or($1,$3); }
| no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); } | no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_in_expr AND expr { $$= new Item_cond_and($1,$3); } | no_in_expr AND expr { $$= new Item_cond_and($1,$3); }
| no_in_expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| no_in_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); } | no_in_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_in_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); } | no_in_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); } | no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
...@@ -1933,6 +1937,7 @@ no_and_expr: ...@@ -1933,6 +1937,7 @@ no_and_expr:
| no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); } | no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_and_expr OR expr { $$= new Item_cond_or($1,$3); } | no_and_expr OR expr { $$= new Item_cond_or($1,$3); }
| no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); } | no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_and_expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| no_and_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); } | no_and_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_and_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); } | no_and_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); } | no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
...@@ -2335,6 +2340,8 @@ sum_expr: ...@@ -2335,6 +2340,8 @@ sum_expr:
{ $$=new Item_sum_max($3); } { $$=new Item_sum_max($3); }
| STD_SYM '(' in_sum_expr ')' | STD_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_std($3); } { $$=new Item_sum_std($3); }
| VARIANCE_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_variance($3); }
| SUM_SYM '(' in_sum_expr ')' | SUM_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_sum($3); }; { $$=new Item_sum_sum($3); };
...@@ -3870,6 +3877,7 @@ keyword: ...@@ -3870,6 +3877,7 @@ keyword:
| VALUE_SYM {} | VALUE_SYM {}
| WORK_SYM {} | WORK_SYM {}
| YEAR_SYM {} | YEAR_SYM {}
| SOUNDS_SYM {}
; ;
/* Option functions */ /* Option functions */
......
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