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
tonu@x3.internalnet
venu@myvenu.com
venu@work.mysql.com
vva@eagle.mysql.r18.ru
vva@genie.(none)
walrus@mysql.com
wax@mysql.com
......
......@@ -32040,6 +32040,10 @@ a single backslash to be matched).
@item expr NOT 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 compatibility, with mSQL
@findex REGEXP
......@@ -42,21 +42,21 @@ insert into t1 values (null,null,'');
select count(distinct a),count(distinct grp) from t1;
count(distinct a) count(distinct grp)
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;
sum(a) count(a) avg(a) std(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
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;
grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
NULL 0 0 NULL NULL 0 0 NULL NULL
1 1 1 1.0000 0.0000 1 1 1 1 a a
2 5 2 2.5000 0.5000 3 2 2 3 b c
3 15 3 5.0000 0.8165 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 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) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
21 6 3.5000 1.7078 2.9167 7 0 1 6 E
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) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
NULL 0 0 NULL NULL NULL 0 0 NULL NULL
1 1 1 1.0000 0.0000 0.0000 1 1 1 1 a a
2 5 2 2.5000 0.5000 0.2500 3 2 2 3 b c
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)+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
NULL NULL
1 7
2 20
3 44.816496580928
2 20.25
3 45.483163247594
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;
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));
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));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
select id, avg(value1), std(value1) from t1 group by id;
id avg(value1) std(value1)
1 1.000000 0.816497
2 11.000000 0.816497
select name, avg(value1), std(value1) from t1, t2 where t1.id = t2.id group by t1.id;
name avg(value1) std(value1)
Set One 1.000000 0.816497
Set Two 11.000000 0.816497
select id, avg(value1), std(value1), variance(value1) from t1 group by id;
id avg(value1) std(value1) variance(value1)
1 1.000000 0.816497 0.666667
2 11.000000 0.816497 0.666667
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) variance(value1)
Set One 1.000000 0.816497 0.666667
Set Two 11.000000 0.816497 0.666667
drop table t1,t2;
create table t1 (id int not 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;
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));
INSERT INTO t1 VALUES ('A'),(NULL);
SELECT * from t1 WHERE field IN (NULL);
field
SELECT * from t1 WHERE field NOT IN (NULL);
field
A
SELECT * from t1 where field = field;
field
A
......@@ -16,6 +100,7 @@ NULL
DELETE FROM t1 WHERE field NOT IN (NULL);
SELECT * FROM t1;
field
A
NULL
drop table t1;
create table t1 (id int(10) primary key);
......
......@@ -80,6 +80,21 @@ this is a REAL test
select soundex(''),soundex('he'),soundex('hello all folks');
soundex('') soundex('he') soundex('hello all folks')
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');
md5('hello')
5d41402abc4b2a76b9719d911017c592
......
......@@ -62,4 +62,8 @@ select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null;
Fld1 max(Fld2)
1 20
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;
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);
ROW(1,2,3)=ROW(1,2,3)
1
......@@ -36,9 +77,20 @@ ROW('test',2,3.33)=ROW('test',2,3.33)
1
SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
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;
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);
a b c
1 2 3
......@@ -48,6 +100,30 @@ select * from t1 where ROW(1,2,3)<ROW(a,b,c);
a b c
2 3 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;
select ROW(1,1);
Cardinality error (more/less than 1 columns)
......
......@@ -2656,14 +2656,14 @@ companynr count(*)
58 23
53 4
50 11
select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 where companynr = 34 and fld4<>"";
count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1)
70 absentee vest 17788966 254128.0857 3272.5940
select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 group by companynr limit 3;
companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1)
00 82 Anthony windmills 10355753 126289.6707 115550.9757
29 95 abut wetness 14473298 152350.5053 8368.5480
34 70 absentee vest 17788966 254128.0857 3272.5940
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) variance(fld1)
70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
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) variance(fld1)
00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087
29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026
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;
companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
37 1 1 5987435 5987435 5987435 5987435.0000
......
......@@ -598,3 +598,105 @@ INSERT INTO t1 values (1),(1);
UPDATE t SET id=(SELECT * FROM t1);
Subselect returns more than 1 record
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;
insert into t1 values (null,null,'');
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 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)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
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),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)+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));
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));
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));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
select id, avg(value1), std(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 id, avg(value1), std(value1), variance(value1) from t1 group by 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;
#
......
......@@ -2,7 +2,39 @@
# 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;
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));
INSERT INTO t1 VALUES ('A'),(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');
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 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 sha('abc');
select sha1('abc');
......
......@@ -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 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 variance(Fld2) is not null;
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(2,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));
SELECT ROW('test',2,3.33)=ROW('test',2,3.33);
-- error 1239
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;
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(0,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;
-- error 1239
......
......@@ -1577,8 +1577,8 @@ select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld
select count(*) from t1;
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 count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(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 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),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 /*! 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 ;
......
......@@ -362,3 +362,48 @@ INSERT INTO t1 values (1),(1);
-- error 1240
UPDATE t SET id=(SELECT * FROM t1);
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():
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)
{
DBUG_ENTER("Item::check_loop");
......@@ -436,6 +442,20 @@ String *Item_copy_string::val_str(String *str)
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)
*/
......@@ -511,10 +531,31 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
res= item->fix_fields(thd, list, &item);
else
thd->fatal_error= 1; // no item given => out of memory
*ref= item;
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)
{
......@@ -686,7 +727,7 @@ void Item_avg_field::make_field(Send_field *tmp_field)
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);
}
......
......@@ -33,7 +33,8 @@ class Item {
enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM,
INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_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};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
......@@ -72,7 +73,6 @@ class Item {
virtual double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); }
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 bool basic_const_item() const { return 0; }
virtual Item *new_item() { return 0; } /* Only for const items */
......@@ -100,6 +100,8 @@ class Item {
virtual Item* el(uint i) { return this; }
virtual Item** addr(uint i) { return 0; }
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
String* val_str(String* s) { return item->val_str(s); }
void make_field(Send_field* f) { item->make_field(f); }
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
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 Item_ident :public Item
{
......@@ -188,7 +196,6 @@ class Item_field :public Item_ident
double val_result();
longlong val_int_result();
String *str_result(String* tmp);
bool is_null_result() { return result_field->is_null(); }
bool send(THD *thd, String *str_arg)
{
return result_field->send(thd,str_arg);
......@@ -384,9 +391,13 @@ class Item_string :public Item
enum Item_result result_type () const { return STRING_RESULT; }
bool basic_const_item() const { return 1; }
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; }
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);
};
......@@ -470,25 +481,25 @@ class Item_ref :public Item_ident
double val()
{
double tmp=(*ref)->val_result();
null_value=(*ref)->is_null_result();
null_value=(*ref)->null_value;
return tmp;
}
longlong val_int()
{
longlong tmp=(*ref)->val_int_result();
null_value=(*ref)->is_null_result();
null_value=(*ref)->null_value;
return tmp;
}
String *val_str(String* tmp)
{
tmp=(*ref)->str_result(tmp);
null_value=(*ref)->is_null_result();
null_value=(*ref)->null_value;
return tmp;
}
bool is_null()
{
(void) (*ref)->val_int_result();
return (*ref)->is_null_result();
return (*ref)->null_value;
}
bool get_date(TIME *ltime,bool fuzzydate)
{
......@@ -505,6 +516,54 @@ class Item_ref :public Item_ident
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
......
This diff is collapsed.
......@@ -17,6 +17,8 @@
/* compare and test functions */
#include "assert.h"
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
......@@ -38,16 +40,12 @@ class Arg_comparator: public Sql_alloc
Arg_comparator() {};
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);
inline int set_compare_func(Item_bool_func2 *owner)
{
return set_compare_func(owner, item_cmp_type((*a)->result_type(),
(*b)->result_type()));
}
inline int set_cmp_func(Item_bool_func2 *owner,
Item **a1, Item **a2,
Item_result type)
......@@ -87,6 +85,27 @@ class Item_bool_func :public Item_int_func
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
{ /* Bool with 2 string args */
protected:
......@@ -358,6 +377,7 @@ class in_vector :public Sql_alloc
uint count;
public:
uint used_count;
in_vector() {}
in_vector(uint elements,uint element_length,qsort_cmp cmp_func)
:base((char*) sql_calloc(elements*element_length)),
size(element_length), compare(cmp_func), count(elements),
......@@ -372,7 +392,6 @@ class in_vector :public Sql_alloc
int find(Item *item);
};
class in_string :public in_vector
{
char buff[80];
......@@ -384,7 +403,6 @@ class in_string :public in_vector
byte *get_value(Item *item);
};
class in_longlong :public in_vector
{
longlong tmp;
......@@ -394,7 +412,6 @@ class in_longlong :public in_vector
byte *get_value(Item *item);
};
class in_double :public in_vector
{
double tmp;
......@@ -404,7 +421,6 @@ class in_double :public in_vector
byte *get_value(Item *item);
};
/*
** Classes for easy comparing of non const items
*/
......@@ -414,60 +430,90 @@ class cmp_item :public Sql_alloc
public:
cmp_item() {}
virtual ~cmp_item() {}
virtual void store_value(Item *item)=0;
virtual int cmp(Item *item)=0;
virtual void store_value(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 {
protected:
class cmp_item_sort_string :public cmp_item_string
{
protected:
char value_buff[80];
String value,*value_res;
public:
cmp_item_sort_string() :value(value_buff,sizeof(value_buff),default_charset_info) {}
String value;
public:
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)
{
value_res=item->val_str(&value);
value_res= item->val_str(&value);
}
int cmp(Item *arg)
{
char buff[80];
String tmp(buff,sizeof(buff),default_charset_info),*res;
if (!(res=arg->val_str(&tmp)))
String tmp(buff, sizeof(buff), default_charset_info), *res;
if (!(res= arg->val_str(&tmp)))
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 {
public:
cmp_item_binary_string() {}
int cmp(Item *arg)
{
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);
}
cmp_item_binary_string(): cmp_item_sort_string(&stringcmp) {}
cmp_item *make_same();
};
class cmp_item_int :public cmp_item
{
longlong value;
public:
void store_value(Item *item)
{
value=item->val_int();
value= item->val_int();
}
int cmp(Item *arg)
{
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
{
double value;
......@@ -480,22 +526,105 @@ class cmp_item_real :public cmp_item
{
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
{
Item *item;
in_vector *array;
cmp_item *in_item;
bool have_null;
public:
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();
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{
bool res=(item->check_cols(1) ||
item->fix_fields(thd, tlist, &item) ||
// We do not check item->cols(), because allowed_arg_cols assigned from it
bool res=(item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
with_sum_func= with_sum_func || item->with_sum_func;
return res;
......@@ -517,10 +646,9 @@ class Item_func_in :public Item_int_func
DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id));
}
bool nulls_in_row();
};
/* Functions used by where clause */
class Item_func_isnull :public Item_bool_func
......
......@@ -18,8 +18,10 @@
#include "assert.h"
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))
items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
else
......@@ -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)
{
tables= 0;
null_value= 0;
maybe_null= 0;
for (uint i= 0; i < arg_count; i++)
{
if (items[i]->fix_fields(thd, tabl, items+i))
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;
}
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)
{
if (c != arg_count)
......@@ -64,3 +81,22 @@ bool Item_row::check_cols(uint c)
}
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 @@
class Item_row: public Item
{
bool array_holder;
table_map tables;
table_map used_tables_cache;
bool const_item_cache;
uint arg_count;
Item **items;
public:
Item_row(List<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)
{}
......@@ -56,11 +60,14 @@ class Item_row: public Item
return 0;
};
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; }
void update_used_tables();
virtual uint cols() { return arg_count; }
virtual Item* el(uint i) { return items[i]; }
virtual Item** addr(uint i) { return items + i; }
virtual bool check_cols(uint c);
uint cols() { return arg_count; }
Item* el(uint i) { return items[i]; }
Item** addr(uint i) { return items + i; }
bool check_cols(uint c);
bool null_inside();
};
......@@ -33,9 +33,10 @@ SUBSELECT TODO:
#include "sql_select.h"
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
(i.e. some rows will be found returned)
......@@ -93,8 +94,10 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
(*ref)= substitution;
substitution->name= name;
if (have_to_be_excluded)
engine->exclude();
return substitution->fix_fields(thd, tables, ref);
substitution= 0;
return (*ref)->fix_fields(thd, tables, ref);
}
char const *save_where= thd->where;
......@@ -159,7 +162,7 @@ double Item_singleval_subselect::val ()
{
if (engine->exec())
{
assign_null();
reset();
return 0;
}
return real_value;
......@@ -169,7 +172,7 @@ longlong Item_singleval_subselect::val_int ()
{
if (engine->exec())
{
assign_null();
reset();
return 0;
}
return int_value;
......@@ -179,7 +182,7 @@ String *Item_singleval_subselect::val_str (String *str)
{
if (engine->exec() || null_value)
{
assign_null();
reset();
return 0;
}
return &string_value;
......@@ -208,9 +211,8 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
left_expr= left_exp;
init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL
value= 0;
maybe_null= 1;
reset();
// We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN;
......@@ -226,9 +228,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
func= f;
init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL
value= 0;
reset();
// We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN;
......@@ -237,6 +237,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
void Item_exists_subselect::fix_length_and_dec()
{
decimals=0;
max_length= 1;
}
......@@ -244,7 +245,7 @@ double Item_exists_subselect::val ()
{
if (engine->exec())
{
assign_null();
reset();
return 0;
}
return (double) value;
......@@ -254,7 +255,7 @@ longlong Item_exists_subselect::val_int ()
{
if (engine->exec())
{
assign_null();
reset();
return 0;
}
return value;
......@@ -264,7 +265,50 @@ String *Item_exists_subselect::val_str(String *str)
{
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;
}
str->set(value,thd_charset());
......@@ -288,8 +332,23 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
compare_func_creator func)
{
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())
{
select_lex->dependent= 1;
Item *item;
if (sl->item_list.elements > 1)
{
......@@ -299,14 +358,14 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
else
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 ||
sl->order_list.first)
{
sl->item_list.push_back(item);
item= (*func)(expr, new Item_ref(sl->item_list.head_ref(),
0, (char*)"<result>"));
item= (*func)(expr, new Item_ref_null_helper(this,
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->having= new Item_cond_and(sl->having, item);
......@@ -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));
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)
sl->where= new Item_cond_and(sl->where, item);
else
......@@ -340,14 +401,21 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
}
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
{
// it is single select without tables => possible optimization
item= (*func)(left_expr, item);
substitution= item;
have_to_be_excluded= 1;
THD *thd= current_thd;
if (thd->lex.describe)
{
......@@ -489,7 +557,7 @@ int subselect_single_select_engine::exec()
join->thd->where= save_where;
DBUG_RETURN(1);
}
item->assign_null();
item->reset();
item->assigned((executed= 0));
}
if (!executed)
......
......@@ -42,6 +42,8 @@ class Item_subselect :public Item_result_field
subselect_engine *engine;
/* allowed number of columns (1 for single value subqueries) */
uint max_columns;
/* work with 'substitution' */
bool have_to_be_excluded;
public:
Item_subselect();
......@@ -65,7 +67,7 @@ class Item_subselect :public Item_result_field
select_subselect *result);
~Item_subselect();
virtual void assign_null()
virtual void reset()
{
null_value= 1;
}
......@@ -110,7 +112,7 @@ class Item_singleval_subselect :public Item_subselect
decimals= item->decimals;
res_type= item->res_type;
}
virtual void assign_null()
virtual void reset()
{
null_value= 1;
int_value= 0;
......@@ -144,7 +146,7 @@ class Item_exists_subselect :public Item_subselect
}
Item_exists_subselect(): Item_subselect() {}
virtual void assign_null()
virtual void reset()
{
value= 0;
}
......@@ -155,6 +157,7 @@ class Item_exists_subselect :public Item_subselect
double val();
String *val_str(String*);
void fix_length_and_dec();
friend class select_exists_subselect;
};
......@@ -164,14 +167,26 @@ class Item_in_subselect :public Item_exists_subselect
{
protected:
Item * left_expr;
bool was_null;
public:
Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex);
Item_in_subselect(Item_in_subselect *item);
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);
void single_value_transformer(st_select_lex *select_lex,
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 */
......
......@@ -253,12 +253,24 @@ double Item_sum_avg::val()
** 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();
if (!args[0]->null_value)
......@@ -270,7 +282,7 @@ bool Item_sum_std::add()
return 0;
}
double Item_sum_std::val()
double Item_sum_variance::val()
{
if (!count)
{
......@@ -281,11 +293,10 @@ double Item_sum_std::val()
/* Avoid problems when the precision isn't good enough */
double tmp=ulonglong2double(count);
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_std::reset_field()
void Item_sum_variance::reset_field()
{
double nr=args[0]->val();
char *res=result_field->ptr;
......@@ -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;
longlong field_count;
......@@ -836,6 +847,17 @@ String *Item_avg_field::val_str(String *str)
}
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;
decimals=item->decimals;
......@@ -844,7 +866,7 @@ Item_std_field::Item_std_field(Item_sum_std *item)
maybe_null=1;
}
double Item_std_field::val()
double Item_variance_field::val()
{
double sum,sum_sqr;
longlong count;
......@@ -860,10 +882,10 @@ double Item_std_field::val()
null_value=0;
double tmp= (double) count;
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();
if (null_value)
......
......@@ -27,7 +27,7 @@ class Item_sum :public Item_result_field
{
public:
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 };
Item **args,*tmp_args[2];
......@@ -235,14 +235,14 @@ class Item_sum_avg :public Item_sum_num
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:
Field *field;
Item_std_field(Item_sum_std *item);
enum Type type() const { return FIELD_STD_ITEM; }
Item_variance_field(Item_sum_variance *item);
enum Type type() const {return FIELD_VARIANCE_ITEM; }
double val();
longlong val_int() { return (longlong) val(); }
String *val_str(String*);
......@@ -251,27 +251,64 @@ class Item_std_field :public Item_result_field
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_sqr;
double sum, sum_sqr;
ulonglong count;
void fix_length_and_dec() { decimals+=4; maybe_null=1; }
public:
Item_sum_std(Item *item_par) :Item_sum_num(item_par),count(0) {}
enum Sumfunctype sum_func () const { return STD_FUNC; }
Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {}
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void reset();
bool add();
double val();
void reset_field();
void update_field(int offset);
Item *result_item(Field *field)
{ return new Item_variance_field(this); }
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
class Item_sum_hybrid :public Item_sum
......
......@@ -344,6 +344,7 @@ static SYMBOL symbols[] = {
{ "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0},
{ "SQL_THREAD", SYM(SQL_THREAD),0,0},
{ "SOUNDS", SYM(SOUNDS_SYM),0,0},
{ "SSL", SYM(SSL_SYM),0,0},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0},
{ "START", SYM(START_SYM),0,0},
......@@ -584,6 +585,7 @@ static SYMBOL sql_functions[] = {
{ "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP),0,0},
{ "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "USER", SYM(USER),0,0},
{ "VARIANCE", SYM(VARIANCE_SYM),0,0},
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
......
......@@ -184,7 +184,6 @@ static uint handler_count;
static bool opt_enable_named_pipe = 0;
#endif
#ifdef __WIN__
static bool opt_console=0,start_mode=0;
static pthread_cond_t COND_handler_count;
static uint handler_count;
static bool opt_console=0, start_mode=0, use_opt_args;
......@@ -2160,7 +2159,7 @@ The server will not act as a slave.");
(void) thr_setconcurrency(concurrency); // 10 by default
#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;
if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
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)
calculate value on it & determinate "is it NULL?".
*/
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
{
......
......@@ -25,8 +25,16 @@
class Sql_alloc
{
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) {}
#ifdef HAVE_purify
bool dummy;
inline Sql_alloc() :dummy(0) {}
......
......@@ -793,6 +793,16 @@ JOIN::exec()
HA_POS_ERROR)))
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 &&
(sort_and_group || (exec_tmp_table->distinct && !group_list)))
having=having_list;
......@@ -3775,7 +3785,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
else
return new Field_double(item_sum->max_length,maybe_null,
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)
return new Field_string(sizeof(double)*2+sizeof(longlong),
maybe_null, item->name,table,my_charset_bin);
......
......@@ -216,7 +216,7 @@ int st_select_lex_unit::exec()
if (optimized && item && item->assigned())
{
item->assigned(0); // We will reinit & rexecute unit
item->assign_null();
item->reset();
table->file->delete_all_rows();
}
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
......
......@@ -100,6 +100,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DIV_SYM
%token EQ
%token EQUAL_SYM
%token SOUNDS_SYM
%token GE
%token GT_SYM
%token LE
......@@ -158,6 +159,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SQL_THREAD
%token START_SYM
%token STD_SYM
%token VARIANCE_SYM
%token STOP_SYM
%token SUM_SYM
%token SUPER_SYM
......@@ -1833,6 +1835,7 @@ expr_expr:
| expr OR expr { $$= new Item_cond_or($1,$3); }
| expr XOR expr { $$= new Item_cond_xor($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 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); }
......@@ -1879,6 +1882,7 @@ no_in_expr:
| 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 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 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); }
......@@ -1933,6 +1937,7 @@ no_and_expr:
| 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 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 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); }
......@@ -2335,6 +2340,8 @@ sum_expr:
{ $$=new Item_sum_max($3); }
| STD_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_std($3); }
| VARIANCE_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_variance($3); }
| SUM_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_sum($3); };
......@@ -3870,6 +3877,7 @@ keyword:
| VALUE_SYM {}
| WORK_SYM {}
| YEAR_SYM {}
| SOUNDS_SYM {}
;
/* 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