Commit 9968b41d authored by unknown's avatar unknown

Fixes for condition pushdown to storage engine based on comments from code review


mysql-test/r/ndb_condition_pushdown.result:
  Added more tests  for condition pushdown to storage engine based on comments from code review
mysql-test/t/ndb_condition_pushdown.test:
  Added more tests  for condition pushdown to storage engine based on comments from code review
parent a2bb52c7
DROP TABLE IF EXISTS t1,t2; DROP TABLE IF EXISTS t1,t2;
CREATE TABLE t1 ( CREATE TABLE t1 (
auto int(5) unsigned NOT NULL auto_increment, auto int(5) unsigned NOT NULL auto_increment,
string char(10) default "hello", string char(10),
vstring varchar(10) default "hello", vstring varchar(10),
bin binary(7) default "hello", bin binary(7),
vbin varbinary(7) default "hello", vbin varbinary(7),
tiny tinyint(4) DEFAULT '0' NOT NULL , tiny tinyint(4) DEFAULT '0' NOT NULL ,
short smallint(6) DEFAULT '1' NOT NULL , short smallint(6) DEFAULT '1' NOT NULL ,
medium mediumint(8) DEFAULT '0' NOT NULL, medium mediumint(8) DEFAULT '0' NOT NULL,
...@@ -233,17 +233,41 @@ auto ...@@ -233,17 +233,41 @@ auto
2 2
3 3
4 4
select auto from t1 where
string like "b%" and
vstring like "b%" and
bin like "b%" and
vbin like "b%"
order by auto;
auto
2
select auto from t1 where
string not like "b%" and
vstring not like "b%" and
bin not like "b%" and
vbin not like "b%"
order by auto;
auto
1
3
4
select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1; select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3
2 2 NULL NULL 2 2 NULL NULL
3 3 3 d 3 3 3 d
select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
pk1 attr1 attr2 attr3
3 3 3 d
4 4 4 e
5 5 5 f
select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1; select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 attr4
2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c
4 4 9223372036854775806 4 e 4 4 9223372036854775806 4 e
5 5 9223372036854775807 5 f 5 5 9223372036854775807 5 f
select * from t2,t3 where t2.attr1 > 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1; select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3 attr4
0 0 0 a 0 0 0 0 a
select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1; select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 attr4
2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c
...@@ -257,8 +281,8 @@ set engine_condition_pushdown = on; ...@@ -257,8 +281,8 @@ set engine_condition_pushdown = on;
select auto from t1 where select auto from t1 where
string = "aaaa" and string = "aaaa" and
vstring = "aaaa" and vstring = "aaaa" and
bin = "aaaa" and /* bin = "aaaa" and
vbin = "aaaa" and vbin = "aaaa" and */
tiny = -1 and tiny = -1 and
short = -1 and short = -1 and
medium = -1 and medium = -1 and
...@@ -285,8 +309,8 @@ auto ...@@ -285,8 +309,8 @@ auto
select auto from t1 where select auto from t1 where
string != "aaaa" and string != "aaaa" and
vstring != "aaaa" and vstring != "aaaa" and
bin != "aaaa" and /* bin != "aaaa" and
vbin != "aaaa" and vbin != "aaaa" and */
tiny != -1 and tiny != -1 and
short != -1 and short != -1 and
medium != -1 and medium != -1 and
...@@ -315,8 +339,8 @@ auto ...@@ -315,8 +339,8 @@ auto
select auto from t1 where select auto from t1 where
string > "aaaa" and string > "aaaa" and
vstring > "aaaa" and vstring > "aaaa" and
bin > "aaaa" and /* bin > "aaaa" and
vbin > "aaaa" and vbin > "aaaa" and */
tiny < -1 and tiny < -1 and
short < -1 and short < -1 and
medium < -1 and medium < -1 and
...@@ -345,8 +369,8 @@ auto ...@@ -345,8 +369,8 @@ auto
select auto from t1 where select auto from t1 where
string >= "aaaa" and string >= "aaaa" and
vstring >= "aaaa" and vstring >= "aaaa" and
bin >= "aaaa" and /* bin >= "aaaa" and
vbin >= "aaaa" and vbin >= "aaaa" and */
tiny <= -1 and tiny <= -1 and
short <= -1 and short <= -1 and
medium <= -1 and medium <= -1 and
...@@ -376,8 +400,8 @@ auto ...@@ -376,8 +400,8 @@ auto
select auto from t1 where select auto from t1 where
string < "dddd" and string < "dddd" and
vstring < "dddd" and vstring < "dddd" and
bin < "dddd" and /* bin < "dddd" and
vbin < "dddd" and vbin < "dddd" and */
tiny > -4 and tiny > -4 and
short > -4 and short > -4 and
medium > -4 and medium > -4 and
...@@ -406,8 +430,8 @@ auto ...@@ -406,8 +430,8 @@ auto
select auto from t1 where select auto from t1 where
string <= "dddd" and string <= "dddd" and
vstring <= "dddd" and vstring <= "dddd" and
bin <= "dddd" and /* bin <= "dddd" and
vbin <= "dddd" and vbin <= "dddd" and */
tiny >= -4 and tiny >= -4 and
short >= -4 and short >= -4 and
medium >= -4 and medium >= -4 and
...@@ -438,8 +462,8 @@ create index medium_index on t1(medium); ...@@ -438,8 +462,8 @@ create index medium_index on t1(medium);
select auto from t1 where select auto from t1 where
string = "aaaa" and string = "aaaa" and
vstring = "aaaa" and vstring = "aaaa" and
bin = "aaaa" and /* bin = "aaaa" and
vbin = "aaaa" and vbin = "aaaa" and */
tiny = -1 and tiny = -1 and
short = -1 and short = -1 and
medium = -1 and medium = -1 and
...@@ -466,8 +490,8 @@ auto ...@@ -466,8 +490,8 @@ auto
select auto from t1 where select auto from t1 where
string != "aaaa" and string != "aaaa" and
vstring != "aaaa" and vstring != "aaaa" and
bin != "aaaa" and /* bin != "aaaa" and
vbin != "aaaa" and vbin != "aaaa" and */
tiny != -1 and tiny != -1 and
short != -1 and short != -1 and
medium != -1 and medium != -1 and
...@@ -496,8 +520,8 @@ auto ...@@ -496,8 +520,8 @@ auto
select auto from t1 where select auto from t1 where
string > "aaaa" and string > "aaaa" and
vstring > "aaaa" and vstring > "aaaa" and
bin > "aaaa" and /* bin > "aaaa" and
vbin > "aaaa" and vbin > "aaaa" and */
tiny < -1 and tiny < -1 and
short < -1 and short < -1 and
medium < -1 and medium < -1 and
...@@ -526,8 +550,8 @@ auto ...@@ -526,8 +550,8 @@ auto
select auto from t1 where select auto from t1 where
string >= "aaaa" and string >= "aaaa" and
vstring >= "aaaa" and vstring >= "aaaa" and
bin >= "aaaa" and /* bin >= "aaaa" and
vbin >= "aaaa" and vbin >= "aaaa" and */
tiny <= -1 and tiny <= -1 and
short <= -1 and short <= -1 and
medium <= -1 and medium <= -1 and
...@@ -557,8 +581,8 @@ auto ...@@ -557,8 +581,8 @@ auto
select auto from t1 where select auto from t1 where
string < "dddd" and string < "dddd" and
vstring < "dddd" and vstring < "dddd" and
bin < "dddd" and /* bin < "dddd" and
vbin < "dddd" and vbin < "dddd" and */
tiny > -4 and tiny > -4 and
short > -4 and short > -4 and
medium > -4 and medium > -4 and
...@@ -587,8 +611,8 @@ auto ...@@ -587,8 +611,8 @@ auto
select auto from t1 where select auto from t1 where
string <= "dddd" and string <= "dddd" and
vstring <= "dddd" and vstring <= "dddd" and
bin <= "dddd" and /* bin <= "dddd" and
vbin <= "dddd" and vbin <= "dddd" and */
tiny >= -4 and tiny >= -4 and
short >= -4 and short >= -4 and
medium >= -4 and medium >= -4 and
...@@ -615,17 +639,41 @@ auto ...@@ -615,17 +639,41 @@ auto
2 2
3 3
4 4
select auto from t1 where
string like "b%" and
vstring like "b%" /* and
bin like "b%" and
vbin like "b%" */
order by auto;
auto
2
select auto from t1 where
string not like "b%" and
vstring not like "b%"/* and
bin not like "b%" and
vbin not like "b%" */
order by auto;
auto
1
3
4
select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1; select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3
2 2 NULL NULL 2 2 NULL NULL
3 3 3 d 3 3 3 d
select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
pk1 attr1 attr2 attr3
3 3 3 d
4 4 4 e
5 5 5 f
select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1; select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 attr4
2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c
4 4 9223372036854775806 4 e 4 4 9223372036854775806 4 e
5 5 9223372036854775807 5 f 5 5 9223372036854775807 5 f
select * from t2,t3 where t2.attr1 > 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1; select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 pk1 attr1 attr2 attr3 attr4
0 0 0 a 0 0 0 0 a
select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1; select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 attr4
2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c
...@@ -635,5 +683,15 @@ pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 attr4 ...@@ -635,5 +683,15 @@ pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 attr4
2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c
3 3 9223372036854775805 3 d 3 3 9223372036854775805 3 d 3 3 9223372036854775805 3 d 3 3 9223372036854775805 3 d
4 4 9223372036854775806 4 e 4 4 9223372036854775806 4 e 4 4 9223372036854775806 4 e 4 4 9223372036854775806 4 e
select auto from t1 where string = "aaaa" collate latin1_general_ci order by auto;
auto
1
select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1;
pk1 attr1 attr2 attr3
0 0 0 a
1 1 1 b
3 3 3 d
4 4 4 e
5 5 5 f
set engine_condition_pushdown = @old_ecpd; set engine_condition_pushdown = @old_ecpd;
DROP TABLE t1,t2,t3,t4; DROP TABLE t1,t2,t3,t4;
...@@ -9,10 +9,10 @@ DROP TABLE IF EXISTS t1,t2; ...@@ -9,10 +9,10 @@ DROP TABLE IF EXISTS t1,t2;
# #
CREATE TABLE t1 ( CREATE TABLE t1 (
auto int(5) unsigned NOT NULL auto_increment, auto int(5) unsigned NOT NULL auto_increment,
string char(10) default "hello", string char(10),
vstring varchar(10) default "hello", vstring varchar(10),
bin binary(7) default "hello", bin binary(7),
vbin varbinary(7) default "hello", vbin varbinary(7),
tiny tinyint(4) DEFAULT '0' NOT NULL , tiny tinyint(4) DEFAULT '0' NOT NULL ,
short smallint(6) DEFAULT '1' NOT NULL , short smallint(6) DEFAULT '1' NOT NULL ,
medium mediumint(8) DEFAULT '0' NOT NULL, medium mediumint(8) DEFAULT '0' NOT NULL,
...@@ -233,10 +233,26 @@ time_field <= '04:04:04' and ...@@ -233,10 +233,26 @@ time_field <= '04:04:04' and
date_time <= '1904-04-04 04:04:04' date_time <= '1904-04-04 04:04:04'
order by auto; order by auto;
# Test LIKE/NOT LIKE
select auto from t1 where
string like "b%" and
vstring like "b%" and
bin like "b%" and
vbin like "b%"
order by auto;
select auto from t1 where
string not like "b%" and
vstring not like "b%" and
bin not like "b%" and
vbin not like "b%"
order by auto;
# Various tests # Various tests
select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1; select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1; select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
select * from t2,t3 where t2.attr1 > 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1; select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1; select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1; select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1;
...@@ -246,8 +262,8 @@ set engine_condition_pushdown = on; ...@@ -246,8 +262,8 @@ set engine_condition_pushdown = on;
select auto from t1 where select auto from t1 where
string = "aaaa" and string = "aaaa" and
vstring = "aaaa" and vstring = "aaaa" and
bin = "aaaa" and /* bin = "aaaa" and
vbin = "aaaa" and vbin = "aaaa" and */
tiny = -1 and tiny = -1 and
short = -1 and short = -1 and
medium = -1 and medium = -1 and
...@@ -273,8 +289,8 @@ order by auto; ...@@ -273,8 +289,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string != "aaaa" and string != "aaaa" and
vstring != "aaaa" and vstring != "aaaa" and
bin != "aaaa" and /* bin != "aaaa" and
vbin != "aaaa" and vbin != "aaaa" and */
tiny != -1 and tiny != -1 and
short != -1 and short != -1 and
medium != -1 and medium != -1 and
...@@ -300,8 +316,8 @@ order by auto; ...@@ -300,8 +316,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string > "aaaa" and string > "aaaa" and
vstring > "aaaa" and vstring > "aaaa" and
bin > "aaaa" and /* bin > "aaaa" and
vbin > "aaaa" and vbin > "aaaa" and */
tiny < -1 and tiny < -1 and
short < -1 and short < -1 and
medium < -1 and medium < -1 and
...@@ -327,8 +343,8 @@ order by auto; ...@@ -327,8 +343,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string >= "aaaa" and string >= "aaaa" and
vstring >= "aaaa" and vstring >= "aaaa" and
bin >= "aaaa" and /* bin >= "aaaa" and
vbin >= "aaaa" and vbin >= "aaaa" and */
tiny <= -1 and tiny <= -1 and
short <= -1 and short <= -1 and
medium <= -1 and medium <= -1 and
...@@ -354,8 +370,8 @@ order by auto; ...@@ -354,8 +370,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string < "dddd" and string < "dddd" and
vstring < "dddd" and vstring < "dddd" and
bin < "dddd" and /* bin < "dddd" and
vbin < "dddd" and vbin < "dddd" and */
tiny > -4 and tiny > -4 and
short > -4 and short > -4 and
medium > -4 and medium > -4 and
...@@ -381,8 +397,8 @@ order by auto; ...@@ -381,8 +397,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string <= "dddd" and string <= "dddd" and
vstring <= "dddd" and vstring <= "dddd" and
bin <= "dddd" and /* bin <= "dddd" and
vbin <= "dddd" and vbin <= "dddd" and */
tiny >= -4 and tiny >= -4 and
short >= -4 and short >= -4 and
medium >= -4 and medium >= -4 and
...@@ -412,8 +428,8 @@ create index medium_index on t1(medium); ...@@ -412,8 +428,8 @@ create index medium_index on t1(medium);
select auto from t1 where select auto from t1 where
string = "aaaa" and string = "aaaa" and
vstring = "aaaa" and vstring = "aaaa" and
bin = "aaaa" and /* bin = "aaaa" and
vbin = "aaaa" and vbin = "aaaa" and */
tiny = -1 and tiny = -1 and
short = -1 and short = -1 and
medium = -1 and medium = -1 and
...@@ -439,8 +455,8 @@ order by auto; ...@@ -439,8 +455,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string != "aaaa" and string != "aaaa" and
vstring != "aaaa" and vstring != "aaaa" and
bin != "aaaa" and /* bin != "aaaa" and
vbin != "aaaa" and vbin != "aaaa" and */
tiny != -1 and tiny != -1 and
short != -1 and short != -1 and
medium != -1 and medium != -1 and
...@@ -466,8 +482,8 @@ order by auto; ...@@ -466,8 +482,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string > "aaaa" and string > "aaaa" and
vstring > "aaaa" and vstring > "aaaa" and
bin > "aaaa" and /* bin > "aaaa" and
vbin > "aaaa" and vbin > "aaaa" and */
tiny < -1 and tiny < -1 and
short < -1 and short < -1 and
medium < -1 and medium < -1 and
...@@ -493,8 +509,8 @@ order by auto; ...@@ -493,8 +509,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string >= "aaaa" and string >= "aaaa" and
vstring >= "aaaa" and vstring >= "aaaa" and
bin >= "aaaa" and /* bin >= "aaaa" and
vbin >= "aaaa" and vbin >= "aaaa" and */
tiny <= -1 and tiny <= -1 and
short <= -1 and short <= -1 and
medium <= -1 and medium <= -1 and
...@@ -520,8 +536,8 @@ order by auto; ...@@ -520,8 +536,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string < "dddd" and string < "dddd" and
vstring < "dddd" and vstring < "dddd" and
bin < "dddd" and /* bin < "dddd" and
vbin < "dddd" and vbin < "dddd" and */
tiny > -4 and tiny > -4 and
short > -4 and short > -4 and
medium > -4 and medium > -4 and
...@@ -547,8 +563,8 @@ order by auto; ...@@ -547,8 +563,8 @@ order by auto;
select auto from t1 where select auto from t1 where
string <= "dddd" and string <= "dddd" and
vstring <= "dddd" and vstring <= "dddd" and
bin <= "dddd" and /* bin <= "dddd" and
vbin <= "dddd" and vbin <= "dddd" and */
tiny >= -4 and tiny >= -4 and
short >= -4 and short >= -4 and
medium >= -4 and medium >= -4 and
...@@ -571,11 +587,32 @@ time_field <= '04:04:04' and ...@@ -571,11 +587,32 @@ time_field <= '04:04:04' and
date_time <= '1904-04-04 04:04:04' date_time <= '1904-04-04 04:04:04'
order by auto; order by auto;
# Test LIKE/NOT LIKE
select auto from t1 where
string like "b%" and
vstring like "b%" /* and
bin like "b%" and
vbin like "b%" */
order by auto;
select auto from t1 where
string not like "b%" and
vstring not like "b%"/* and
bin not like "b%" and
vbin not like "b%" */
order by auto;
# Various tests # Various tests
select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1; select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1; select * from t3 where attr2 > 9223372036854775803 and attr3 != 3 order by pk1;
select * from t2,t3 where t2.attr1 > 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1; select * from t2,t3 where t2.attr1 < 1 and t2.attr2 = t3.attr2 and t3.attr1 < 5 order by t2.pk1;
select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1; select * from t4 where attr1 < 5 and attr2 > 9223372036854775803 and attr3 != 3 order by t4.pk1;
select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1; select * from t3,t4 where t4.attr1 > 1 and t4.attr2 = t3.attr2 and t4.attr3 < 5 order by t4.pk1;
# Some tests that are currently not supported and should not push condition
select auto from t1 where string = "aaaa" collate latin1_general_ci order by auto;
select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1;
set engine_condition_pushdown = @old_ecpd; set engine_condition_pushdown = @old_ecpd;
DROP TABLE t1,t2,t3,t4; DROP TABLE t1,t2,t3,t4;
...@@ -5930,6 +5930,7 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -5930,6 +5930,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
// Expect char string or binary string // Expect char string or binary string
context->expect_only(Item::STRING_ITEM); context->expect_only(Item::STRING_ITEM);
context->expect(Item::VARBIN_ITEM); context->expect(Item::VARBIN_ITEM);
context->expect_collation(field_item->collation.collation);
break; break;
case(REAL_RESULT): case(REAL_RESULT):
context->expect_only(Item::REAL_ITEM); context->expect_only(Item::REAL_ITEM);
...@@ -5945,7 +5946,22 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -5945,7 +5946,22 @@ void ndb_serialize_cond(const Item *item, void *arg)
break; break;
default: default:
break; break;
} }
}
else
{
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
// Check that field and string constant collations are the same
if ((field->result_type() == STRING_RESULT) &&
!context->expecting_collation(item->collation.collation))
{
DBUG_PRINT("info", ("Found non-matching collations %s and %s",
item->collation.collation->name,
context->collation->name));
context->supported= FALSE;
}
} }
break; break;
} }
...@@ -5957,12 +5973,22 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -5957,12 +5973,22 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item::FUNC_ITEM): { case(Item::FUNC_ITEM): {
Item_func *func_item= (Item_func *) item; Item_func *func_item= (Item_func *) item;
// Check that we expect a function or functional expression here
if (context->expecting(Item::FUNC_ITEM) ||
func_item->functype() == Item_func::UNKNOWN_FUNC)
context->expect_nothing();
else
{
// Did not expect function here
context->supported= FALSE;
break;
}
context->expect_nothing();
switch(func_item->functype()) { switch(func_item->functype()) {
case(Item_func::EQ_FUNC): { case(Item_func::EQ_FUNC): {
DBUG_PRINT("info", ("EQ_FUNC")); DBUG_PRINT("info", ("EQ_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::STRING_ITEM); context->expect(Item::STRING_ITEM);
context->expect(Item::INT_ITEM); context->expect(Item::INT_ITEM);
context->expect(Item::REAL_ITEM); context->expect(Item::REAL_ITEM);
...@@ -5977,7 +6003,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -5977,7 +6003,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::NE_FUNC): { case(Item_func::NE_FUNC): {
DBUG_PRINT("info", ("NE_FUNC")); DBUG_PRINT("info", ("NE_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::STRING_ITEM); context->expect(Item::STRING_ITEM);
context->expect(Item::INT_ITEM); context->expect(Item::INT_ITEM);
context->expect(Item::REAL_ITEM); context->expect(Item::REAL_ITEM);
...@@ -5992,7 +6019,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -5992,7 +6019,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::LT_FUNC): { case(Item_func::LT_FUNC): {
DBUG_PRINT("info", ("LT_FUNC")); DBUG_PRINT("info", ("LT_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::STRING_ITEM); context->expect(Item::STRING_ITEM);
context->expect(Item::INT_ITEM); context->expect(Item::INT_ITEM);
context->expect(Item::REAL_ITEM); context->expect(Item::REAL_ITEM);
...@@ -6007,7 +6035,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6007,7 +6035,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::LE_FUNC): { case(Item_func::LE_FUNC): {
DBUG_PRINT("info", ("LE_FUNC")); DBUG_PRINT("info", ("LE_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::STRING_ITEM); context->expect(Item::STRING_ITEM);
context->expect(Item::INT_ITEM); context->expect(Item::INT_ITEM);
context->expect(Item::REAL_ITEM); context->expect(Item::REAL_ITEM);
...@@ -6022,7 +6051,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6022,7 +6051,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::GE_FUNC): { case(Item_func::GE_FUNC): {
DBUG_PRINT("info", ("GE_FUNC")); DBUG_PRINT("info", ("GE_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::STRING_ITEM); context->expect(Item::STRING_ITEM);
context->expect(Item::INT_ITEM); context->expect(Item::INT_ITEM);
context->expect(Item::REAL_ITEM); context->expect(Item::REAL_ITEM);
...@@ -6037,7 +6067,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6037,7 +6067,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::GT_FUNC): { case(Item_func::GT_FUNC): {
DBUG_PRINT("info", ("GT_FUNC")); DBUG_PRINT("info", ("GT_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::STRING_ITEM); context->expect(Item::STRING_ITEM);
context->expect(Item::REAL_ITEM); context->expect(Item::REAL_ITEM);
context->expect(Item::DECIMAL_ITEM); context->expect(Item::DECIMAL_ITEM);
...@@ -6052,7 +6083,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6052,7 +6083,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::LIKE_FUNC): { case(Item_func::LIKE_FUNC): {
DBUG_PRINT("info", ("LIKE_FUNC")); DBUG_PRINT("info", ("LIKE_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::STRING_ITEM); context->expect(Item::STRING_ITEM);
context->expect(Item::FIELD_ITEM); context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT); context->expect_field_result(STRING_RESULT);
...@@ -6060,7 +6092,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6060,7 +6092,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::NOTLIKE_FUNC): { case(Item_func::NOTLIKE_FUNC): {
DBUG_PRINT("info", ("NOTLIKE_FUNC")); DBUG_PRINT("info", ("NOTLIKE_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::STRING_ITEM); context->expect(Item::STRING_ITEM);
context->expect(Item::FIELD_ITEM); context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT); context->expect_field_result(STRING_RESULT);
...@@ -6068,7 +6101,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6068,7 +6101,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::ISNULL_FUNC): { case(Item_func::ISNULL_FUNC): {
DBUG_PRINT("info", ("ISNULL_FUNC")); DBUG_PRINT("info", ("ISNULL_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::FIELD_ITEM); context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT); context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT); context->expect_field_result(REAL_RESULT);
...@@ -6078,7 +6112,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6078,7 +6112,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::ISNOTNULL_FUNC): { case(Item_func::ISNOTNULL_FUNC): {
DBUG_PRINT("info", ("ISNOTNULL_FUNC")); DBUG_PRINT("info", ("ISNOTNULL_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::FIELD_ITEM); context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT); context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT); context->expect_field_result(REAL_RESULT);
...@@ -6088,7 +6123,8 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6088,7 +6123,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
} }
case(Item_func::NOT_FUNC): { case(Item_func::NOT_FUNC): {
DBUG_PRINT("info", ("NOT_FUNC")); DBUG_PRINT("info", ("NOT_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype()); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::FUNC_ITEM); context->expect(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM); context->expect(Item::COND_ITEM);
break; break;
...@@ -6102,16 +6138,28 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6102,16 +6138,28 @@ void ndb_serialize_cond(const Item *item, void *arg)
case(STRING_RESULT): { case(STRING_RESULT): {
NDB_ITEM_QUALIFICATION q; NDB_ITEM_QUALIFICATION q;
q.value_type= Item::STRING_ITEM; q.value_type= Item::STRING_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
if (context->expect_field_result_mask) if (context->expect_field_result_mask)
{ {
// We have not seen the field argument yet // We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM); context->expect_only(Item::FIELD_ITEM);
context->expect_only_field_result(STRING_RESULT); context->expect_only_field_result(STRING_RESULT);
context->expect_collation(func_item->collation.collation);
} }
else else
context->expect_nothing(); {
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
// Check that string result have correct collation
if (!context->expecting_collation(item->collation.collation))
{
DBUG_PRINT("info", ("Found non-matching collations %s and %s",
item->collation.collation->name,
context->collation->name));
context->supported= FALSE;
}
}
// Skip any arguments since we will evaluate function instead // Skip any arguments since we will evaluate function instead
DBUG_PRINT("info", ("Skip until end of arguments marker")); DBUG_PRINT("info", ("Skip until end of arguments marker"));
context->skip= func_item->argument_count(); context->skip= func_item->argument_count();
...@@ -6128,7 +6176,11 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6128,7 +6176,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->expect_only_field_result(REAL_RESULT); context->expect_only_field_result(REAL_RESULT);
} }
else else
context->expect_nothing(); {
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
// Skip any arguments since we will evaluate function instead // Skip any arguments since we will evaluate function instead
DBUG_PRINT("info", ("Skip until end of arguments marker")); DBUG_PRINT("info", ("Skip until end of arguments marker"));
...@@ -6146,7 +6198,11 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6146,7 +6198,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->expect_only_field_result(INT_RESULT); context->expect_only_field_result(INT_RESULT);
} }
else else
context->expect_nothing(); {
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
// Skip any arguments since we will evaluate function instead // Skip any arguments since we will evaluate function instead
DBUG_PRINT("info", ("Skip until end of arguments marker")); DBUG_PRINT("info", ("Skip until end of arguments marker"));
...@@ -6164,8 +6220,11 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6164,8 +6220,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->expect_only_field_result(DECIMAL_RESULT); context->expect_only_field_result(DECIMAL_RESULT);
} }
else else
context->expect_nothing(); {
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
// Skip any arguments since we will evaluate function instead // Skip any arguments since we will evaluate function instead
DBUG_PRINT("info", ("Skip until end of arguments marker")); DBUG_PRINT("info", ("Skip until end of arguments marker"));
context->skip= func_item->argument_count(); context->skip= func_item->argument_count();
...@@ -6207,9 +6266,22 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6207,9 +6266,22 @@ void ndb_serialize_cond(const Item *item, void *arg)
// We have not seen the field argument yet // We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM); context->expect_only(Item::FIELD_ITEM);
context->expect_only_field_result(STRING_RESULT); context->expect_only_field_result(STRING_RESULT);
context->expect_collation(item->collation.collation);
} }
else else
context->expect_nothing(); {
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
// Check that we are comparing with a field with same collation
if (!context->expecting_collation(item->collation.collation))
{
DBUG_PRINT("info", ("Found non-matching collations %s and %s",
item->collation.collation->name,
context->collation->name));
context->supported= FALSE;
}
}
} }
else else
context->supported= FALSE; context->supported= FALSE;
...@@ -6230,7 +6302,11 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6230,7 +6302,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->expect_only_field_result(INT_RESULT); context->expect_only_field_result(INT_RESULT);
} }
else else
context->expect_nothing(); {
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
} }
else else
context->supported= FALSE; context->supported= FALSE;
...@@ -6251,7 +6327,11 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6251,7 +6327,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->expect_only_field_result(REAL_RESULT); context->expect_only_field_result(REAL_RESULT);
} }
else else
context->expect_nothing(); {
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
} }
else else
context->supported= FALSE; context->supported= FALSE;
...@@ -6278,7 +6358,11 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6278,7 +6358,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->expect_only_field_result(STRING_RESULT); context->expect_only_field_result(STRING_RESULT);
} }
else else
context->expect_nothing(); {
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
} }
else else
context->supported= FALSE; context->supported= FALSE;
...@@ -6300,27 +6384,38 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6300,27 +6384,38 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->expect_field_result(DECIMAL_RESULT); context->expect_field_result(DECIMAL_RESULT);
} }
else else
context->expect_nothing(); {
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
} }
else else
context->supported= FALSE; context->supported= FALSE;
break; break;
case(Item::COND_ITEM): { case(Item::COND_ITEM): {
Item_cond *cond_item= (Item_cond *) item; Item_cond *cond_item= (Item_cond *) item;
switch(cond_item->functype()) {
case(Item_func::COND_AND_FUNC): if (context->expecting(Item::COND_ITEM))
DBUG_PRINT("info", ("COND_AND_FUNC")); switch(cond_item->functype()) {
curr_cond->ndb_item= new Ndb_item(cond_item->functype()); case(Item_func::COND_AND_FUNC):
break; DBUG_PRINT("info", ("COND_AND_FUNC"));
case(Item_func::COND_OR_FUNC): curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
DBUG_PRINT("info", ("COND_OR_FUNC")); cond_item);
curr_cond->ndb_item= new Ndb_item(cond_item->functype()); break;
break; case(Item_func::COND_OR_FUNC):
default: DBUG_PRINT("info", ("COND_OR_FUNC"));
DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype())); curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
context->supported= FALSE; cond_item);
break; break;
} default:
DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype()));
context->supported= FALSE;
break;
}
else
// Did not expect condition
context->supported= FALSE;
break; break;
} }
default: { default: {
...@@ -6339,6 +6434,9 @@ ha_ndbcluster::serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond) ...@@ -6339,6 +6434,9 @@ ha_ndbcluster::serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond)
DBUG_ENTER("serialize_cond"); DBUG_ENTER("serialize_cond");
Item *item= (Item *) cond; Item *item= (Item *) cond;
Ndb_cond_traverse_context context(table, (void *)m_table, ndb_cond); Ndb_cond_traverse_context context(table, (void *)m_table, ndb_cond);
// Expect a logical expression
context.expect(Item::FUNC_ITEM);
context.expect(Item::COND_ITEM);
item->traverse_cond(&ndb_serialize_cond, (void *) &context, Item::PREFIX); item->traverse_cond(&ndb_serialize_cond, (void *) &context, Item::PREFIX);
DBUG_PRINT("info", ("The pushed condition is %ssupported", (context.supported)?"":"not ")); DBUG_PRINT("info", ("The pushed condition is %ssupported", (context.supported)?"":"not "));
...@@ -6356,22 +6454,33 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6356,22 +6454,33 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
if (!cond->next) if (!cond->next)
break; break;
Ndb_item *a= cond->next->ndb_item; Ndb_item *a= cond->next->ndb_item;
switch((negated) ? Ndb_item *b, *field, *value= NULL;
Ndb_item::negate(cond->ndb_item->qualification.function_type) switch(cond->ndb_item->argument_count()) {
: cond->ndb_item->qualification.function_type) case(1):
{ field=
case(Item_func::EQ_FUNC): { (a->type == NDB_FIELD)? a : NULL;
break;
case(2):
if (!cond->next->next) if (!cond->next->next)
break; break;
Ndb_item *b= cond->next->next->ndb_item; b= cond->next->next->ndb_item;
Ndb_item *value= value=
(a->type == NDB_VALUE)? a (a->type == NDB_VALUE)? a
: (b->type == NDB_VALUE)? b : (b->type == NDB_VALUE)? b
: NULL; : NULL;
Ndb_item *field= field=
(a->type == NDB_FIELD)? a (a->type == NDB_FIELD)? a
: (b->type == NDB_FIELD)? b : (b->type == NDB_FIELD)? b
: NULL; : NULL;
break;
deafult:
break;
}
switch((negated) ?
Ndb_item::negate(cond->ndb_item->qualification.function_type)
: cond->ndb_item->qualification.function_type)
{
case(Item_func::EQ_FUNC): {
if (!value || !field) break; if (!value || !field) break;
// Save value in right format for the field type // Save value in right format for the field type
value->save_in_field(field); value->save_in_field(field);
...@@ -6385,17 +6494,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6385,17 +6494,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
case(Item_func::NE_FUNC): { case(Item_func::NE_FUNC): {
if (!cond->next->next)
break;
Ndb_item *b= cond->next->next->ndb_item;
Ndb_item *value=
(a->type == NDB_VALUE)? a
: (b->type == NDB_VALUE)? b
: NULL;
Ndb_item *field=
(a->type == NDB_FIELD)? a
: (b->type == NDB_FIELD)? b
: NULL;
if (!value || !field) break; if (!value || !field) break;
// Save value in right format for the field type // Save value in right format for the field type
value->save_in_field(field); value->save_in_field(field);
...@@ -6409,17 +6507,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6409,17 +6507,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
case(Item_func::LT_FUNC): { case(Item_func::LT_FUNC): {
if (!cond->next->next)
break;
Ndb_item *b= cond->next->next->ndb_item;
Ndb_item *value=
(a->type == NDB_VALUE)? a
: (b->type == NDB_VALUE)? b
: NULL;
Ndb_item *field=
(a->type == NDB_FIELD)? a
: (b->type == NDB_FIELD)? b
: NULL;
if (!value || !field) break; if (!value || !field) break;
// Save value in right format for the field type // Save value in right format for the field type
value->save_in_field(field); value->save_in_field(field);
...@@ -6445,17 +6532,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6445,17 +6532,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
case(Item_func::LE_FUNC): { case(Item_func::LE_FUNC): {
if (!cond->next->next)
break;
Ndb_item *b= cond->next->next->ndb_item;
Ndb_item *value=
(a->type == NDB_VALUE)? a
: (b->type == NDB_VALUE)? b
: NULL;
Ndb_item *field=
(a->type == NDB_FIELD)? a
: (b->type == NDB_FIELD)? b
: NULL;
if (!value || !field) break; if (!value || !field) break;
// Save value in right format for the field type // Save value in right format for the field type
value->save_in_field(field); value->save_in_field(field);
...@@ -6481,17 +6557,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6481,17 +6557,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
case(Item_func::GE_FUNC): { case(Item_func::GE_FUNC): {
if (!cond->next->next)
break;
Ndb_item *b= cond->next->next->ndb_item;
Ndb_item *value=
(a->type == NDB_VALUE)? a
: (b->type == NDB_VALUE)? b
: NULL;
Ndb_item *field=
(a->type == NDB_FIELD)? a
: (b->type == NDB_FIELD)? b
: NULL;
if (!value || !field) break; if (!value || !field) break;
// Save value in right format for the field type // Save value in right format for the field type
value->save_in_field(field); value->save_in_field(field);
...@@ -6517,17 +6582,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6517,17 +6582,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
case(Item_func::GT_FUNC): { case(Item_func::GT_FUNC): {
if (!cond->next->next)
break;
Ndb_item *b= cond->next->next->ndb_item;
Ndb_item *value=
(a->type == NDB_VALUE)? a
: (b->type == NDB_VALUE)? b
: NULL;
Ndb_item *field=
(a->type == NDB_FIELD)? a
: (b->type == NDB_FIELD)? b
: NULL;
if (!value || !field) break; if (!value || !field) break;
// Save value in right format for the field type // Save value in right format for the field type
value->save_in_field(field); value->save_in_field(field);
...@@ -6553,17 +6607,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6553,17 +6607,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
case(Item_func::LIKE_FUNC): { case(Item_func::LIKE_FUNC): {
if (!cond->next->next)
break;
Ndb_item *b= cond->next->next->ndb_item;
Ndb_item *value=
(a->type == NDB_VALUE)? a
: (b->type == NDB_VALUE)? b
: NULL;
Ndb_item *field=
(a->type == NDB_FIELD)? a
: (b->type == NDB_FIELD)? b
: NULL;
if (!value || !field) break; if (!value || !field) break;
if (value->qualification.value_type != Item::STRING_ITEM) break; if (value->qualification.value_type != Item::STRING_ITEM) break;
// Save value in right format for the field type // Save value in right format for the field type
...@@ -6573,24 +6616,13 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6573,24 +6616,13 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
value->pack_length())); value->pack_length()));
if (filter->cmp(NdbScanFilter::COND_LIKE, if (filter->cmp(NdbScanFilter::COND_LIKE,
field->get_field_no(), field->get_field_no(),
field->get_val(), value->get_val(),
field->pack_length()) == -1) value->pack_length()) == -1)
DBUG_RETURN(1); DBUG_RETURN(1);
cond= cond->next->next->next; cond= cond->next->next->next;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
case(Item_func::NOTLIKE_FUNC): { case(Item_func::NOTLIKE_FUNC): {
if (!cond->next->next)
break;
Ndb_item *b= cond->next->next->ndb_item;
Ndb_item *value=
(a->type == NDB_VALUE)? a
: (b->type == NDB_VALUE)? b
: NULL;
Ndb_item *field=
(a->type == NDB_FIELD)? a
: (b->type == NDB_FIELD)? b
: NULL;
if (!value || !field) break; if (!value || !field) break;
if (value->qualification.value_type != Item::STRING_ITEM) break; if (value->qualification.value_type != Item::STRING_ITEM) break;
// Save value in right format for the field type // Save value in right format for the field type
...@@ -6600,28 +6632,26 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6600,28 +6632,26 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
value->pack_length())); value->pack_length()));
if (filter->cmp(NdbScanFilter::COND_NOT_LIKE, if (filter->cmp(NdbScanFilter::COND_NOT_LIKE,
field->get_field_no(), field->get_field_no(),
field->get_val(), value->get_val(),
field->pack_length()) == -1) value->pack_length()) == -1)
DBUG_RETURN(1); DBUG_RETURN(1);
cond= cond->next->next->next; cond= cond->next->next->next;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
case(Item_func::ISNULL_FUNC): case(Item_func::ISNULL_FUNC):
if (a->type == NDB_FIELD) if (!field)
{ break;
DBUG_PRINT("info", ("Generating ISNULL filter")); DBUG_PRINT("info", ("Generating ISNULL filter"));
if (filter->isnull(a->get_field_no()) == -1) if (filter->isnull(field->get_field_no()) == -1)
DBUG_RETURN(1); DBUG_RETURN(1);
}
cond= cond->next->next; cond= cond->next->next;
DBUG_RETURN(0); DBUG_RETURN(0);
case(Item_func::ISNOTNULL_FUNC): { case(Item_func::ISNOTNULL_FUNC): {
if (a->type == NDB_FIELD) if (!field)
{ break;
DBUG_PRINT("info", ("Generating ISNOTNULL filter")); DBUG_PRINT("info", ("Generating ISNOTNULL filter"));
if (filter->isnotnull(a->get_field_no()) == -1) if (filter->isnotnull(field->get_field_no()) == -1)
DBUG_RETURN(1); DBUG_RETURN(1);
}
cond= cond->next->next; cond= cond->next->next;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -6638,62 +6668,64 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, ...@@ -6638,62 +6668,64 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
} }
int int
ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter, ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter)
bool negated)
{ {
uint level=0;
bool negated= false;
DBUG_ENTER("build_scan_filter_group"); DBUG_ENTER("build_scan_filter_group");
if (!cond) DBUG_RETURN(1); do
switch(cond->ndb_item->type) { {
case(NDB_FUNCTION): if (!cond) DBUG_RETURN(1);
switch(cond->ndb_item->qualification.function_type) { switch(cond->ndb_item->type) {
case(Item_func::COND_AND_FUNC): { case(NDB_FUNCTION):
DBUG_PRINT("info", ("Generating %s group", (negated)?"NAND":"AND")); switch(cond->ndb_item->qualification.function_type) {
if ((negated) ? filter->begin(NdbScanFilter::NAND) case(Item_func::COND_AND_FUNC): {
: filter->begin(NdbScanFilter::AND) == -1) level++;
DBUG_RETURN(1); DBUG_PRINT("info", ("Generating %s group %u", (negated)?"NAND":"AND",
cond= cond->next; level));
do if ((negated) ? filter->begin(NdbScanFilter::NAND)
{ : filter->begin(NdbScanFilter::AND) == -1)
if (build_scan_filter_group(cond, filter))
DBUG_RETURN(1); DBUG_RETURN(1);
} while (cond && cond->ndb_item->type != NDB_END_COND); negated= false;
if (cond) cond= cond->next; cond= cond->next;
if (filter->end() == -1) break;
DBUG_RETURN(1); }
DBUG_PRINT("info", ("End of %s group", (negated)?"NAND":"AND")); case(Item_func::COND_OR_FUNC): {
break; level++;
} DBUG_PRINT("info", ("Generating %s group %u", (negated)?"NOR":"OR",
case(Item_func::COND_OR_FUNC): { level));
DBUG_PRINT("info", ("Generating % group", (negated)?"NOR":"OR")); if ((negated) ? filter->begin(NdbScanFilter::NOR)
if ((negated) ? filter->begin(NdbScanFilter::NOR) : filter->begin(NdbScanFilter::OR) == -1)
: filter->begin(NdbScanFilter::OR) == -1) DBUG_RETURN(1);
DBUG_RETURN(1); negated= false;
cond= cond->next; cond= cond->next;
do break;
{ }
if (build_scan_filter_group(cond, filter)) case(Item_func::NOT_FUNC): {
cond= cond->next;
negated= true;
break;
}
default:
if (build_scan_filter_predicate(cond, filter, negated))
DBUG_RETURN(1); DBUG_RETURN(1);
} while (cond && cond->ndb_item->type != NDB_END_COND); negated= false;
break;
}
break;
case(NDB_END_COND):
DBUG_PRINT("info", ("End of group %u", level));
level--;
if (cond) cond= cond->next; if (cond) cond= cond->next;
if (filter->end() == -1) if (filter->end() == -1)
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_PRINT("info", ("End of %s group", (negated)?"NOR":"OR"));
break; break;
default: {
DBUG_PRINT("info", ("Illegal scan filter"));
} }
case(Item_func::NOT_FUNC): {
cond= cond->next;
build_scan_filter_group(cond, filter, true);
break;
} }
default: } while (level > 0);
if (build_scan_filter_predicate(cond, filter, negated))
DBUG_RETURN(1);
}
break;
default: {
DBUG_PRINT("info", ("Illegal scan filter"));
}
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -6706,8 +6738,6 @@ ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter) ...@@ -6706,8 +6738,6 @@ ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter)
switch(cond->ndb_item->type) { switch(cond->ndb_item->type) {
case(Item_func::COND_AND_FUNC): case(Item_func::COND_AND_FUNC):
simple_cond= FALSE;
break;
case(Item_func::COND_OR_FUNC): case(Item_func::COND_OR_FUNC):
simple_cond= FALSE; simple_cond= FALSE;
break; break;
......
...@@ -109,10 +109,18 @@ static const negated_function_mapping neg_map[]= ...@@ -109,10 +109,18 @@ static const negated_function_mapping neg_map[]=
}; };
/* /*
This class is used for serialization of the Item tree for This class is the construction element for serialization of Item tree
condition pushdown. It is stored in a linked list implemented in condition pushdown.
by Ndb_cond class. An instance of Ndb_Item represents a constant, table field reference,
*/ unary or binary comparison predicate, and start/end of AND/OR.
Instances of Ndb_Item are stored in a linked list implemented by Ndb_cond
class.
The order of elements produced by Ndb_cond::next corresponds to
depth-first traversal of the Item (i.e. expression) tree in prefix order.
AND and OR have arbitrary arity, so the end of AND/OR group is marked with
Ndb_item with type == NDB_END_COND.
NOT items represent negated conditions and generate NAND/NOR groups.
*/
class Ndb_item { class Ndb_item {
public: public:
Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {}; Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {};
...@@ -134,6 +142,8 @@ class Ndb_item { ...@@ -134,6 +142,8 @@ class Ndb_item {
break; break;
} }
case(NDB_FUNCTION): case(NDB_FUNCTION):
value.item= item_value;
break;
case(NDB_END_COND): case(NDB_END_COND):
break; break;
} }
...@@ -146,9 +156,11 @@ class Ndb_item { ...@@ -146,9 +156,11 @@ class Ndb_item {
field_value->column_no= column_no; field_value->column_no= column_no;
value.field_value= field_value; value.field_value= field_value;
}; };
Ndb_item(Item_func::Functype func_type) : type(NDB_FUNCTION) Ndb_item(Item_func::Functype func_type, const Item *item_value)
: type(NDB_FUNCTION)
{ {
qualification.function_type= func_type; qualification.function_type= func_type;
value.item= item_value;
}; };
~Ndb_item() ~Ndb_item()
{ {
...@@ -179,6 +191,11 @@ class Ndb_item { ...@@ -179,6 +191,11 @@ class Ndb_item {
int get_field_no() { return value.field_value->column_no; }; int get_field_no() { return value.field_value->column_no; };
int argument_count()
{
return ((Item_func *) value.item)->argument_count();
};
const char* get_val() const char* get_val()
{ {
switch(type) { switch(type) {
...@@ -274,7 +291,7 @@ class Ndb_cond_traverse_context ...@@ -274,7 +291,7 @@ class Ndb_cond_traverse_context
Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack) Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack)
: table(tab), ndb_table(ndb_tab), : table(tab), ndb_table(ndb_tab),
supported(TRUE), stack_ptr(stack), cond_ptr(NULL), supported(TRUE), stack_ptr(stack), cond_ptr(NULL),
expect_mask(0), expect_field_result_mask(0), skip(0) expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL)
{ {
if (stack) if (stack)
cond_ptr= stack->ndb_cond; cond_ptr= stack->ndb_cond;
...@@ -318,6 +335,17 @@ class Ndb_cond_traverse_context ...@@ -318,6 +335,17 @@ class Ndb_cond_traverse_context
expect_field_result_mask= 0; expect_field_result_mask= 0;
expect_field_result(result); expect_field_result(result);
}; };
void expect_collation(CHARSET_INFO* col)
{
collation= col;
};
bool expecting_collation(CHARSET_INFO* col)
{
bool matching= (!collation) ? true : (collation == col);
collation= NULL;
return matching;
};
TABLE* table; TABLE* table;
void* ndb_table; void* ndb_table;
...@@ -327,6 +355,8 @@ class Ndb_cond_traverse_context ...@@ -327,6 +355,8 @@ class Ndb_cond_traverse_context
uint expect_mask; uint expect_mask;
uint expect_field_result_mask; uint expect_field_result_mask;
uint skip; uint skip;
CHARSET_INFO* collation;
}; };
/* /*
...@@ -428,27 +458,40 @@ class ha_ndbcluster: public handler ...@@ -428,27 +458,40 @@ class ha_ndbcluster: public handler
/* /*
Condition pushdown Condition pushdown
*/ */
/*
Push a condition to ndbcluster storage engine for evaluation /*
during table and index scans. The conditions will be stored on a stack Push condition down to the table handler.
for possibly storing several conditions. The stack can be popped SYNOPSIS
by calling cond_pop, handler::extra(HA_EXTRA_RESET) (handler::reset()) cond_push()
will clear the stack. cond Condition to be pushed. The condition tree must not be
The current implementation supports arbitrary AND/OR nested conditions modified by the by the caller.
with comparisons between columns and constants (including constant RETURN
expressions and function calls) and the following comparison operators: The 'remainder' condition that caller must use to filter out records.
=, !=, >, >=, <, <=, "is null", and "is not null". NULL means the handler will not return rows that do not match the
passed condition.
RETURN NOTES
NULL The condition was supported and will be evaluated for each The pushed conditions form a stack (from which one can remove the
row found during the scan last pushed condition using cond_pop).
cond The condition was not supported and all rows will be returned from The table handler filters out rows using (pushed_cond1 AND pushed_cond2
the scan for evaluation (and thus not saved on stack) AND ... AND pushed_condN)
*/ or less restrictive condition, depending on handler's capabilities.
handler->extra(HA_EXTRA_RESET) call empties the condition stack.
Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the
condition stack.
The current implementation supports arbitrary AND/OR nested conditions
with comparisons between columns and constants (including constant
expressions and function calls) and the following comparison operators:
=, !=, >, >=, <, <=, like, "not like", "is null", and "is not null".
Negated conditions are supported by NOT which generate NAND/NOR groups.
*/
const COND *cond_push(const COND *cond); const COND *cond_push(const COND *cond);
/* /*
Pop the top condition from the condition stack of the handler instance. Pop the top condition from the condition stack of the handler instance.
*/ SYNOPSIS
cond_pop()
Pops the top if condition stack, if stack is not empty
*/
void cond_pop(); void cond_pop();
uint8 table_cache_type(); uint8 table_cache_type();
...@@ -536,8 +579,7 @@ private: ...@@ -536,8 +579,7 @@ private:
NdbScanFilter* filter, NdbScanFilter* filter,
bool negated= false); bool negated= false);
int build_scan_filter_group(Ndb_cond* &cond, int build_scan_filter_group(Ndb_cond* &cond,
NdbScanFilter* filter, NdbScanFilter* filter);
bool negated= false);
int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter); int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
int generate_scan_filter(Ndb_cond_stack* cond_stack, int generate_scan_filter(Ndb_cond_stack* cond_stack,
NdbScanOperation* op); NdbScanOperation* op);
......
...@@ -451,7 +451,7 @@ public: ...@@ -451,7 +451,7 @@ public:
enum {NONE=0, INDEX, RND} inited; enum {NONE=0, INDEX, RND} inited;
bool auto_increment_column_changed; bool auto_increment_column_changed;
bool implicit_emptied; /* Can be !=0 only if HEAP */ bool implicit_emptied; /* Can be !=0 only if HEAP */
const COND *pushed_cond;
handler(TABLE *table_arg) :table(table_arg), handler(TABLE *table_arg) :table(table_arg),
ref(0), data_file_length(0), max_data_file_length(0), index_file_length(0), ref(0), data_file_length(0), max_data_file_length(0), index_file_length(0),
...@@ -460,7 +460,8 @@ public: ...@@ -460,7 +460,8 @@ public:
create_time(0), check_time(0), update_time(0), create_time(0), check_time(0), update_time(0),
key_used_on_scan(MAX_KEY), active_index(MAX_KEY), key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
ref_length(sizeof(my_off_t)), block_size(0), ref_length(sizeof(my_off_t)), block_size(0),
raid_type(0), ft_handler(0), inited(NONE), implicit_emptied(0) raid_type(0), ft_handler(0), inited(NONE), implicit_emptied(0),
pushed_cond(NULL)
{} {}
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
int ha_open(const char *name, int mode, int test_if_locked); int ha_open(const char *name, int mode, int test_if_locked);
...@@ -724,23 +725,34 @@ public: ...@@ -724,23 +725,34 @@ public:
Condition pushdown to storage engines Condition pushdown to storage engines
*/ */
/* /*
Push a condition to storage engine for evaluation during table Push condition down to the table handler.
and index scans. The conditions should be stored on a stack SYNOPSIS
for possibly storing several conditions. The stack can be popped cond_push()
by calling cond_pop, handler::extra(HA_EXTRA_RESET) (handler::reset()) cond Condition to be pushed. The condition tree must not be
should clear the stack. modified by the by the caller.
The condition can be traversed using Item::traverse_cond RETURN
RETURN The 'remainder' condition that caller must use to filter out records.
NULL The condition was supported by the handler and will be evaluated NULL means the handler will not return rows that do not match the
for each row found during the scan passed condition.
cond The condition was not supported and all rows will be returned from NOTES
the scan for evaluation (and thus not saved on stack) The pushed conditions form a stack (from which one can remove the
*/ last pushed condition using cond_pop).
The table handler filters out rows using (pushed_cond1 AND pushed_cond2
AND ... AND pushed_condN)
or less restrictive condition, depending on handler's capabilities.
handler->extra(HA_EXTRA_RESET) call empties the condition stack.
Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the
condition stack.
*/
virtual const COND *cond_push(const COND *cond) { return cond; }; virtual const COND *cond_push(const COND *cond) { return cond; };
/* /*
Pop the top condition from the condition stack of the handler instance. Pop the top condition from the condition stack of the handler instance.
*/ SYNOPSIS
cond_pop()
Pops the top if condition stack, if stack is not empty
*/
virtual void cond_pop() { return; }; virtual void cond_pop() { return; };
}; };
......
...@@ -5305,7 +5305,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -5305,7 +5305,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
DBUG_RETURN(1); DBUG_RETURN(1);
tab->select_cond=sel->cond=tmp; tab->select_cond=sel->cond=tmp;
if (current_thd->variables.engine_condition_pushdown) if (current_thd->variables.engine_condition_pushdown)
tab->table->file->cond_push(tmp); // Push condition to handler {
tab->table->file->pushed_cond= NULL;
/* Push condition to handler */
if (!tab->table->file->cond_push(tmp))
tab->table->file->pushed_cond= tmp;
}
} }
else else
tab->select_cond= sel->cond= NULL; tab->select_cond= sel->cond= NULL;
...@@ -5428,8 +5433,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -5428,8 +5433,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
tab->cache.select->cond=tmp; tab->cache.select->cond=tmp;
tab->cache.select->read_tables=join->const_table_map; tab->cache.select->read_tables=join->const_table_map;
if (current_thd->variables.engine_condition_pushdown && if (current_thd->variables.engine_condition_pushdown &&
(tmp != tab->select_cond)) (!tab->table->file->pushed_cond))
tab->table->file->cond_push(tmp); // Push condition to handler {
/* Push condition to handler */
if (!tab->table->file->cond_push(tmp))
tab->table->file->pushed_cond= tmp;
}
} }
} }
} }
......
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