mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Fixes for condition pushdown to storage engine based on comments from code review
This commit is contained in:
parent
b3d3f73753
commit
fcc37a0787
6 changed files with 489 additions and 301 deletions
|
@ -1,10 +1,10 @@
|
|||
DROP TABLE IF EXISTS t1,t2;
|
||||
CREATE TABLE t1 (
|
||||
auto int(5) unsigned NOT NULL auto_increment,
|
||||
string char(10) default "hello",
|
||||
vstring varchar(10) default "hello",
|
||||
bin binary(7) default "hello",
|
||||
vbin varbinary(7) default "hello",
|
||||
string char(10),
|
||||
vstring varchar(10),
|
||||
bin binary(7),
|
||||
vbin varbinary(7),
|
||||
tiny tinyint(4) DEFAULT '0' NOT NULL ,
|
||||
short smallint(6) DEFAULT '1' NOT NULL ,
|
||||
medium mediumint(8) DEFAULT '0' NOT NULL,
|
||||
|
@ -233,17 +233,41 @@ auto
|
|||
2
|
||||
3
|
||||
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;
|
||||
pk1 attr1 attr2 attr3
|
||||
2 2 NULL NULL
|
||||
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;
|
||||
pk1 attr1 attr2 attr3 attr4
|
||||
2 2 9223372036854775804 2 c
|
||||
4 4 9223372036854775806 4 e
|
||||
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
|
||||
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;
|
||||
pk1 attr1 attr2 attr3 attr4
|
||||
2 2 9223372036854775804 2 c
|
||||
|
@ -257,8 +281,8 @@ set engine_condition_pushdown = on;
|
|||
select auto from t1 where
|
||||
string = "aaaa" and
|
||||
vstring = "aaaa" and
|
||||
bin = "aaaa" and
|
||||
vbin = "aaaa" and
|
||||
/* bin = "aaaa" and
|
||||
vbin = "aaaa" and */
|
||||
tiny = -1 and
|
||||
short = -1 and
|
||||
medium = -1 and
|
||||
|
@ -285,8 +309,8 @@ auto
|
|||
select auto from t1 where
|
||||
string != "aaaa" and
|
||||
vstring != "aaaa" and
|
||||
bin != "aaaa" and
|
||||
vbin != "aaaa" and
|
||||
/* bin != "aaaa" and
|
||||
vbin != "aaaa" and */
|
||||
tiny != -1 and
|
||||
short != -1 and
|
||||
medium != -1 and
|
||||
|
@ -315,8 +339,8 @@ auto
|
|||
select auto from t1 where
|
||||
string > "aaaa" and
|
||||
vstring > "aaaa" and
|
||||
bin > "aaaa" and
|
||||
vbin > "aaaa" and
|
||||
/* bin > "aaaa" and
|
||||
vbin > "aaaa" and */
|
||||
tiny < -1 and
|
||||
short < -1 and
|
||||
medium < -1 and
|
||||
|
@ -345,8 +369,8 @@ auto
|
|||
select auto from t1 where
|
||||
string >= "aaaa" and
|
||||
vstring >= "aaaa" and
|
||||
bin >= "aaaa" and
|
||||
vbin >= "aaaa" and
|
||||
/* bin >= "aaaa" and
|
||||
vbin >= "aaaa" and */
|
||||
tiny <= -1 and
|
||||
short <= -1 and
|
||||
medium <= -1 and
|
||||
|
@ -376,8 +400,8 @@ auto
|
|||
select auto from t1 where
|
||||
string < "dddd" and
|
||||
vstring < "dddd" and
|
||||
bin < "dddd" and
|
||||
vbin < "dddd" and
|
||||
/* bin < "dddd" and
|
||||
vbin < "dddd" and */
|
||||
tiny > -4 and
|
||||
short > -4 and
|
||||
medium > -4 and
|
||||
|
@ -406,8 +430,8 @@ auto
|
|||
select auto from t1 where
|
||||
string <= "dddd" and
|
||||
vstring <= "dddd" and
|
||||
bin <= "dddd" and
|
||||
vbin <= "dddd" and
|
||||
/* bin <= "dddd" and
|
||||
vbin <= "dddd" and */
|
||||
tiny >= -4 and
|
||||
short >= -4 and
|
||||
medium >= -4 and
|
||||
|
@ -438,8 +462,8 @@ create index medium_index on t1(medium);
|
|||
select auto from t1 where
|
||||
string = "aaaa" and
|
||||
vstring = "aaaa" and
|
||||
bin = "aaaa" and
|
||||
vbin = "aaaa" and
|
||||
/* bin = "aaaa" and
|
||||
vbin = "aaaa" and */
|
||||
tiny = -1 and
|
||||
short = -1 and
|
||||
medium = -1 and
|
||||
|
@ -466,8 +490,8 @@ auto
|
|||
select auto from t1 where
|
||||
string != "aaaa" and
|
||||
vstring != "aaaa" and
|
||||
bin != "aaaa" and
|
||||
vbin != "aaaa" and
|
||||
/* bin != "aaaa" and
|
||||
vbin != "aaaa" and */
|
||||
tiny != -1 and
|
||||
short != -1 and
|
||||
medium != -1 and
|
||||
|
@ -496,8 +520,8 @@ auto
|
|||
select auto from t1 where
|
||||
string > "aaaa" and
|
||||
vstring > "aaaa" and
|
||||
bin > "aaaa" and
|
||||
vbin > "aaaa" and
|
||||
/* bin > "aaaa" and
|
||||
vbin > "aaaa" and */
|
||||
tiny < -1 and
|
||||
short < -1 and
|
||||
medium < -1 and
|
||||
|
@ -526,8 +550,8 @@ auto
|
|||
select auto from t1 where
|
||||
string >= "aaaa" and
|
||||
vstring >= "aaaa" and
|
||||
bin >= "aaaa" and
|
||||
vbin >= "aaaa" and
|
||||
/* bin >= "aaaa" and
|
||||
vbin >= "aaaa" and */
|
||||
tiny <= -1 and
|
||||
short <= -1 and
|
||||
medium <= -1 and
|
||||
|
@ -557,8 +581,8 @@ auto
|
|||
select auto from t1 where
|
||||
string < "dddd" and
|
||||
vstring < "dddd" and
|
||||
bin < "dddd" and
|
||||
vbin < "dddd" and
|
||||
/* bin < "dddd" and
|
||||
vbin < "dddd" and */
|
||||
tiny > -4 and
|
||||
short > -4 and
|
||||
medium > -4 and
|
||||
|
@ -587,8 +611,8 @@ auto
|
|||
select auto from t1 where
|
||||
string <= "dddd" and
|
||||
vstring <= "dddd" and
|
||||
bin <= "dddd" and
|
||||
vbin <= "dddd" and
|
||||
/* bin <= "dddd" and
|
||||
vbin <= "dddd" and */
|
||||
tiny >= -4 and
|
||||
short >= -4 and
|
||||
medium >= -4 and
|
||||
|
@ -615,17 +639,41 @@ auto
|
|||
2
|
||||
3
|
||||
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;
|
||||
pk1 attr1 attr2 attr3
|
||||
2 2 NULL NULL
|
||||
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;
|
||||
pk1 attr1 attr2 attr3 attr4
|
||||
2 2 9223372036854775804 2 c
|
||||
4 4 9223372036854775806 4 e
|
||||
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
|
||||
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;
|
||||
pk1 attr1 attr2 attr3 attr4
|
||||
2 2 9223372036854775804 2 c
|
||||
|
@ -635,5 +683,15 @@ pk1 attr1 attr2 attr3 attr4 pk1 attr1 attr2 attr3 attr4
|
|||
2 2 9223372036854775804 2 c 2 2 9223372036854775804 2 c
|
||||
3 3 9223372036854775805 3 d 3 3 9223372036854775805 3 d
|
||||
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;
|
||||
DROP TABLE t1,t2,t3,t4;
|
||||
|
|
|
@ -9,10 +9,10 @@ DROP TABLE IF EXISTS t1,t2;
|
|||
#
|
||||
CREATE TABLE t1 (
|
||||
auto int(5) unsigned NOT NULL auto_increment,
|
||||
string char(10) default "hello",
|
||||
vstring varchar(10) default "hello",
|
||||
bin binary(7) default "hello",
|
||||
vbin varbinary(7) default "hello",
|
||||
string char(10),
|
||||
vstring varchar(10),
|
||||
bin binary(7),
|
||||
vbin varbinary(7),
|
||||
tiny tinyint(4) DEFAULT '0' NOT NULL ,
|
||||
short smallint(6) DEFAULT '1' NOT NULL ,
|
||||
medium mediumint(8) DEFAULT '0' NOT NULL,
|
||||
|
@ -233,10 +233,26 @@ time_field <= '04:04:04' and
|
|||
date_time <= '1904-04-04 04:04:04'
|
||||
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
|
||||
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 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 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;
|
|||
select auto from t1 where
|
||||
string = "aaaa" and
|
||||
vstring = "aaaa" and
|
||||
bin = "aaaa" and
|
||||
vbin = "aaaa" and
|
||||
/* bin = "aaaa" and
|
||||
vbin = "aaaa" and */
|
||||
tiny = -1 and
|
||||
short = -1 and
|
||||
medium = -1 and
|
||||
|
@ -273,8 +289,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string != "aaaa" and
|
||||
vstring != "aaaa" and
|
||||
bin != "aaaa" and
|
||||
vbin != "aaaa" and
|
||||
/* bin != "aaaa" and
|
||||
vbin != "aaaa" and */
|
||||
tiny != -1 and
|
||||
short != -1 and
|
||||
medium != -1 and
|
||||
|
@ -300,8 +316,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string > "aaaa" and
|
||||
vstring > "aaaa" and
|
||||
bin > "aaaa" and
|
||||
vbin > "aaaa" and
|
||||
/* bin > "aaaa" and
|
||||
vbin > "aaaa" and */
|
||||
tiny < -1 and
|
||||
short < -1 and
|
||||
medium < -1 and
|
||||
|
@ -327,8 +343,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string >= "aaaa" and
|
||||
vstring >= "aaaa" and
|
||||
bin >= "aaaa" and
|
||||
vbin >= "aaaa" and
|
||||
/* bin >= "aaaa" and
|
||||
vbin >= "aaaa" and */
|
||||
tiny <= -1 and
|
||||
short <= -1 and
|
||||
medium <= -1 and
|
||||
|
@ -354,8 +370,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string < "dddd" and
|
||||
vstring < "dddd" and
|
||||
bin < "dddd" and
|
||||
vbin < "dddd" and
|
||||
/* bin < "dddd" and
|
||||
vbin < "dddd" and */
|
||||
tiny > -4 and
|
||||
short > -4 and
|
||||
medium > -4 and
|
||||
|
@ -381,8 +397,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string <= "dddd" and
|
||||
vstring <= "dddd" and
|
||||
bin <= "dddd" and
|
||||
vbin <= "dddd" and
|
||||
/* bin <= "dddd" and
|
||||
vbin <= "dddd" and */
|
||||
tiny >= -4 and
|
||||
short >= -4 and
|
||||
medium >= -4 and
|
||||
|
@ -412,8 +428,8 @@ create index medium_index on t1(medium);
|
|||
select auto from t1 where
|
||||
string = "aaaa" and
|
||||
vstring = "aaaa" and
|
||||
bin = "aaaa" and
|
||||
vbin = "aaaa" and
|
||||
/* bin = "aaaa" and
|
||||
vbin = "aaaa" and */
|
||||
tiny = -1 and
|
||||
short = -1 and
|
||||
medium = -1 and
|
||||
|
@ -439,8 +455,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string != "aaaa" and
|
||||
vstring != "aaaa" and
|
||||
bin != "aaaa" and
|
||||
vbin != "aaaa" and
|
||||
/* bin != "aaaa" and
|
||||
vbin != "aaaa" and */
|
||||
tiny != -1 and
|
||||
short != -1 and
|
||||
medium != -1 and
|
||||
|
@ -466,8 +482,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string > "aaaa" and
|
||||
vstring > "aaaa" and
|
||||
bin > "aaaa" and
|
||||
vbin > "aaaa" and
|
||||
/* bin > "aaaa" and
|
||||
vbin > "aaaa" and */
|
||||
tiny < -1 and
|
||||
short < -1 and
|
||||
medium < -1 and
|
||||
|
@ -493,8 +509,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string >= "aaaa" and
|
||||
vstring >= "aaaa" and
|
||||
bin >= "aaaa" and
|
||||
vbin >= "aaaa" and
|
||||
/* bin >= "aaaa" and
|
||||
vbin >= "aaaa" and */
|
||||
tiny <= -1 and
|
||||
short <= -1 and
|
||||
medium <= -1 and
|
||||
|
@ -520,8 +536,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string < "dddd" and
|
||||
vstring < "dddd" and
|
||||
bin < "dddd" and
|
||||
vbin < "dddd" and
|
||||
/* bin < "dddd" and
|
||||
vbin < "dddd" and */
|
||||
tiny > -4 and
|
||||
short > -4 and
|
||||
medium > -4 and
|
||||
|
@ -547,8 +563,8 @@ order by auto;
|
|||
select auto from t1 where
|
||||
string <= "dddd" and
|
||||
vstring <= "dddd" and
|
||||
bin <= "dddd" and
|
||||
vbin <= "dddd" and
|
||||
/* bin <= "dddd" and
|
||||
vbin <= "dddd" and */
|
||||
tiny >= -4 and
|
||||
short >= -4 and
|
||||
medium >= -4 and
|
||||
|
@ -571,11 +587,32 @@ time_field <= '04:04:04' and
|
|||
date_time <= '1904-04-04 04:04:04'
|
||||
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
|
||||
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 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 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;
|
||||
DROP TABLE t1,t2,t3,t4;
|
||||
|
|
|
@ -5930,6 +5930,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
// Expect char string or binary string
|
||||
context->expect_only(Item::STRING_ITEM);
|
||||
context->expect(Item::VARBIN_ITEM);
|
||||
context->expect_collation(field_item->collation.collation);
|
||||
break;
|
||||
case(REAL_RESULT):
|
||||
context->expect_only(Item::REAL_ITEM);
|
||||
|
@ -5945,7 +5946,22 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
break;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
@ -5957,12 +5973,22 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(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()) {
|
||||
case(Item_func::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::INT_ITEM);
|
||||
context->expect(Item::REAL_ITEM);
|
||||
|
@ -5977,7 +6003,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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::INT_ITEM);
|
||||
context->expect(Item::REAL_ITEM);
|
||||
|
@ -5992,7 +6019,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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::INT_ITEM);
|
||||
context->expect(Item::REAL_ITEM);
|
||||
|
@ -6007,7 +6035,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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::INT_ITEM);
|
||||
context->expect(Item::REAL_ITEM);
|
||||
|
@ -6022,7 +6051,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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::INT_ITEM);
|
||||
context->expect(Item::REAL_ITEM);
|
||||
|
@ -6037,7 +6067,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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::REAL_ITEM);
|
||||
context->expect(Item::DECIMAL_ITEM);
|
||||
|
@ -6052,7 +6083,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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::FIELD_ITEM);
|
||||
context->expect_field_result(STRING_RESULT);
|
||||
|
@ -6060,7 +6092,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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::FIELD_ITEM);
|
||||
context->expect_field_result(STRING_RESULT);
|
||||
|
@ -6068,7 +6101,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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_field_result(STRING_RESULT);
|
||||
context->expect_field_result(REAL_RESULT);
|
||||
|
@ -6078,7 +6112,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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_field_result(STRING_RESULT);
|
||||
context->expect_field_result(REAL_RESULT);
|
||||
|
@ -6088,7 +6123,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
}
|
||||
case(Item_func::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::COND_ITEM);
|
||||
break;
|
||||
|
@ -6102,16 +6138,28 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
case(STRING_RESULT): {
|
||||
NDB_ITEM_QUALIFICATION q;
|
||||
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)
|
||||
{
|
||||
// We have not seen the field argument yet
|
||||
context->expect_only(Item::FIELD_ITEM);
|
||||
context->expect_only_field_result(STRING_RESULT);
|
||||
context->expect_collation(func_item->collation.collation);
|
||||
}
|
||||
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
|
||||
DBUG_PRINT("info", ("Skip until end of arguments marker"));
|
||||
context->skip= func_item->argument_count();
|
||||
|
@ -6128,7 +6176,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
context->expect_only_field_result(REAL_RESULT);
|
||||
}
|
||||
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
|
||||
DBUG_PRINT("info", ("Skip until end of arguments marker"));
|
||||
|
@ -6146,7 +6198,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
context->expect_only_field_result(INT_RESULT);
|
||||
}
|
||||
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
|
||||
DBUG_PRINT("info", ("Skip until end of arguments marker"));
|
||||
|
@ -6164,8 +6220,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
context->expect_only_field_result(DECIMAL_RESULT);
|
||||
}
|
||||
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
|
||||
DBUG_PRINT("info", ("Skip until end of arguments marker"));
|
||||
context->skip= func_item->argument_count();
|
||||
|
@ -6207,9 +6266,22 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
// We have not seen the field argument yet
|
||||
context->expect_only(Item::FIELD_ITEM);
|
||||
context->expect_only_field_result(STRING_RESULT);
|
||||
context->expect_collation(item->collation.collation);
|
||||
}
|
||||
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
|
||||
context->supported= FALSE;
|
||||
|
@ -6230,7 +6302,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
context->expect_only_field_result(INT_RESULT);
|
||||
}
|
||||
else
|
||||
context->expect_nothing();
|
||||
{
|
||||
// Expect another logical expression
|
||||
context->expect_only(Item::FUNC_ITEM);
|
||||
context->expect(Item::COND_ITEM);
|
||||
}
|
||||
}
|
||||
else
|
||||
context->supported= FALSE;
|
||||
|
@ -6251,7 +6327,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
context->expect_only_field_result(REAL_RESULT);
|
||||
}
|
||||
else
|
||||
context->expect_nothing();
|
||||
{
|
||||
// Expect another logical expression
|
||||
context->expect_only(Item::FUNC_ITEM);
|
||||
context->expect(Item::COND_ITEM);
|
||||
}
|
||||
}
|
||||
else
|
||||
context->supported= FALSE;
|
||||
|
@ -6278,7 +6358,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
context->expect_only_field_result(STRING_RESULT);
|
||||
}
|
||||
else
|
||||
context->expect_nothing();
|
||||
{
|
||||
// Expect another logical expression
|
||||
context->expect_only(Item::FUNC_ITEM);
|
||||
context->expect(Item::COND_ITEM);
|
||||
}
|
||||
}
|
||||
else
|
||||
context->supported= FALSE;
|
||||
|
@ -6300,27 +6384,38 @@ void ndb_serialize_cond(const Item *item, void *arg)
|
|||
context->expect_field_result(DECIMAL_RESULT);
|
||||
}
|
||||
else
|
||||
context->expect_nothing();
|
||||
{
|
||||
// Expect another logical expression
|
||||
context->expect_only(Item::FUNC_ITEM);
|
||||
context->expect(Item::COND_ITEM);
|
||||
}
|
||||
}
|
||||
else
|
||||
context->supported= FALSE;
|
||||
break;
|
||||
case(Item::COND_ITEM): {
|
||||
Item_cond *cond_item= (Item_cond *) item;
|
||||
switch(cond_item->functype()) {
|
||||
case(Item_func::COND_AND_FUNC):
|
||||
DBUG_PRINT("info", ("COND_AND_FUNC"));
|
||||
curr_cond->ndb_item= new Ndb_item(cond_item->functype());
|
||||
break;
|
||||
case(Item_func::COND_OR_FUNC):
|
||||
DBUG_PRINT("info", ("COND_OR_FUNC"));
|
||||
curr_cond->ndb_item= new Ndb_item(cond_item->functype());
|
||||
break;
|
||||
default:
|
||||
DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype()));
|
||||
context->supported= FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (context->expecting(Item::COND_ITEM))
|
||||
switch(cond_item->functype()) {
|
||||
case(Item_func::COND_AND_FUNC):
|
||||
DBUG_PRINT("info", ("COND_AND_FUNC"));
|
||||
curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
|
||||
cond_item);
|
||||
break;
|
||||
case(Item_func::COND_OR_FUNC):
|
||||
DBUG_PRINT("info", ("COND_OR_FUNC"));
|
||||
curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
|
||||
cond_item);
|
||||
break;
|
||||
default:
|
||||
DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype()));
|
||||
context->supported= FALSE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
// Did not expect condition
|
||||
context->supported= FALSE;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -6339,6 +6434,9 @@ ha_ndbcluster::serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond)
|
|||
DBUG_ENTER("serialize_cond");
|
||||
Item *item= (Item *) 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);
|
||||
DBUG_PRINT("info", ("The pushed condition is %ssupported", (context.supported)?"":"not "));
|
||||
|
||||
|
@ -6356,22 +6454,33 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
if (!cond->next)
|
||||
break;
|
||||
Ndb_item *a= cond->next->ndb_item;
|
||||
Ndb_item *b, *field, *value= NULL;
|
||||
switch(cond->ndb_item->argument_count()) {
|
||||
case(1):
|
||||
field=
|
||||
(a->type == NDB_FIELD)? a : NULL;
|
||||
break;
|
||||
case(2):
|
||||
if (!cond->next->next)
|
||||
break;
|
||||
b= cond->next->next->ndb_item;
|
||||
value=
|
||||
(a->type == NDB_VALUE)? a
|
||||
: (b->type == NDB_VALUE)? b
|
||||
: NULL;
|
||||
field=
|
||||
(a->type == NDB_FIELD)? a
|
||||
: (b->type == NDB_FIELD)? b
|
||||
: 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 (!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;
|
||||
// Save value in right format for the field type
|
||||
value->save_in_field(field);
|
||||
|
@ -6385,17 +6494,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
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;
|
||||
// Save value in right format for the field type
|
||||
value->save_in_field(field);
|
||||
|
@ -6409,17 +6507,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
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;
|
||||
// Save value in right format for the field type
|
||||
value->save_in_field(field);
|
||||
|
@ -6445,17 +6532,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
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;
|
||||
// Save value in right format for the field type
|
||||
value->save_in_field(field);
|
||||
|
@ -6481,17 +6557,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
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;
|
||||
// Save value in right format for the field type
|
||||
value->save_in_field(field);
|
||||
|
@ -6517,17 +6582,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
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;
|
||||
// Save value in right format for the field type
|
||||
value->save_in_field(field);
|
||||
|
@ -6553,17 +6607,6 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
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->qualification.value_type != Item::STRING_ITEM) break;
|
||||
// Save value in right format for the field type
|
||||
|
@ -6573,24 +6616,13 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
value->pack_length()));
|
||||
if (filter->cmp(NdbScanFilter::COND_LIKE,
|
||||
field->get_field_no(),
|
||||
field->get_val(),
|
||||
field->pack_length()) == -1)
|
||||
value->get_val(),
|
||||
value->pack_length()) == -1)
|
||||
DBUG_RETURN(1);
|
||||
cond= cond->next->next->next;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
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->qualification.value_type != Item::STRING_ITEM) break;
|
||||
// Save value in right format for the field type
|
||||
|
@ -6600,28 +6632,26 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
value->pack_length()));
|
||||
if (filter->cmp(NdbScanFilter::COND_NOT_LIKE,
|
||||
field->get_field_no(),
|
||||
field->get_val(),
|
||||
field->pack_length()) == -1)
|
||||
value->get_val(),
|
||||
value->pack_length()) == -1)
|
||||
DBUG_RETURN(1);
|
||||
cond= cond->next->next->next;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
case(Item_func::ISNULL_FUNC):
|
||||
if (a->type == NDB_FIELD)
|
||||
{
|
||||
DBUG_PRINT("info", ("Generating ISNULL filter"));
|
||||
if (filter->isnull(a->get_field_no()) == -1)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (!field)
|
||||
break;
|
||||
DBUG_PRINT("info", ("Generating ISNULL filter"));
|
||||
if (filter->isnull(field->get_field_no()) == -1)
|
||||
DBUG_RETURN(1);
|
||||
cond= cond->next->next;
|
||||
DBUG_RETURN(0);
|
||||
case(Item_func::ISNOTNULL_FUNC): {
|
||||
if (a->type == NDB_FIELD)
|
||||
{
|
||||
DBUG_PRINT("info", ("Generating ISNOTNULL filter"));
|
||||
if (filter->isnotnull(a->get_field_no()) == -1)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (!field)
|
||||
break;
|
||||
DBUG_PRINT("info", ("Generating ISNOTNULL filter"));
|
||||
if (filter->isnotnull(field->get_field_no()) == -1)
|
||||
DBUG_RETURN(1);
|
||||
cond= cond->next->next;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
@ -6638,62 +6668,64 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond,
|
|||
}
|
||||
|
||||
int
|
||||
ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter,
|
||||
bool negated)
|
||||
ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter)
|
||||
{
|
||||
uint level=0;
|
||||
bool negated= false;
|
||||
|
||||
DBUG_ENTER("build_scan_filter_group");
|
||||
if (!cond) DBUG_RETURN(1);
|
||||
switch(cond->ndb_item->type) {
|
||||
case(NDB_FUNCTION):
|
||||
switch(cond->ndb_item->qualification.function_type) {
|
||||
case(Item_func::COND_AND_FUNC): {
|
||||
DBUG_PRINT("info", ("Generating %s group", (negated)?"NAND":"AND"));
|
||||
if ((negated) ? filter->begin(NdbScanFilter::NAND)
|
||||
: filter->begin(NdbScanFilter::AND) == -1)
|
||||
DBUG_RETURN(1);
|
||||
cond= cond->next;
|
||||
do
|
||||
{
|
||||
if (build_scan_filter_group(cond, filter))
|
||||
do
|
||||
{
|
||||
if (!cond) DBUG_RETURN(1);
|
||||
switch(cond->ndb_item->type) {
|
||||
case(NDB_FUNCTION):
|
||||
switch(cond->ndb_item->qualification.function_type) {
|
||||
case(Item_func::COND_AND_FUNC): {
|
||||
level++;
|
||||
DBUG_PRINT("info", ("Generating %s group %u", (negated)?"NAND":"AND",
|
||||
level));
|
||||
if ((negated) ? filter->begin(NdbScanFilter::NAND)
|
||||
: filter->begin(NdbScanFilter::AND) == -1)
|
||||
DBUG_RETURN(1);
|
||||
} while (cond && cond->ndb_item->type != NDB_END_COND);
|
||||
negated= false;
|
||||
cond= cond->next;
|
||||
break;
|
||||
}
|
||||
case(Item_func::COND_OR_FUNC): {
|
||||
level++;
|
||||
DBUG_PRINT("info", ("Generating %s group %u", (negated)?"NOR":"OR",
|
||||
level));
|
||||
if ((negated) ? filter->begin(NdbScanFilter::NOR)
|
||||
: filter->begin(NdbScanFilter::OR) == -1)
|
||||
DBUG_RETURN(1);
|
||||
negated= false;
|
||||
cond= cond->next;
|
||||
break;
|
||||
}
|
||||
case(Item_func::NOT_FUNC): {
|
||||
cond= cond->next;
|
||||
negated= true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (build_scan_filter_predicate(cond, filter, negated))
|
||||
DBUG_RETURN(1);
|
||||
negated= false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case(NDB_END_COND):
|
||||
DBUG_PRINT("info", ("End of group %u", level));
|
||||
level--;
|
||||
if (cond) cond= cond->next;
|
||||
if (filter->end() == -1)
|
||||
DBUG_RETURN(1);
|
||||
DBUG_PRINT("info", ("End of %s group", (negated)?"NAND":"AND"));
|
||||
break;
|
||||
default: {
|
||||
DBUG_PRINT("info", ("Illegal scan filter"));
|
||||
}
|
||||
case(Item_func::COND_OR_FUNC): {
|
||||
DBUG_PRINT("info", ("Generating % group", (negated)?"NOR":"OR"));
|
||||
if ((negated) ? filter->begin(NdbScanFilter::NOR)
|
||||
: filter->begin(NdbScanFilter::OR) == -1)
|
||||
DBUG_RETURN(1);
|
||||
cond= cond->next;
|
||||
do
|
||||
{
|
||||
if (build_scan_filter_group(cond, filter))
|
||||
DBUG_RETURN(1);
|
||||
} while (cond && cond->ndb_item->type != NDB_END_COND);
|
||||
if (cond) cond= cond->next;
|
||||
if (filter->end() == -1)
|
||||
DBUG_RETURN(1);
|
||||
DBUG_PRINT("info", ("End of %s group", (negated)?"NOR":"OR"));
|
||||
break;
|
||||
}
|
||||
case(Item_func::NOT_FUNC): {
|
||||
cond= cond->next;
|
||||
build_scan_filter_group(cond, filter, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (build_scan_filter_predicate(cond, filter, negated))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
DBUG_PRINT("info", ("Illegal scan filter"));
|
||||
}
|
||||
}
|
||||
} while (level > 0);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
@ -6706,8 +6738,6 @@ ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter)
|
|||
|
||||
switch(cond->ndb_item->type) {
|
||||
case(Item_func::COND_AND_FUNC):
|
||||
simple_cond= FALSE;
|
||||
break;
|
||||
case(Item_func::COND_OR_FUNC):
|
||||
simple_cond= FALSE;
|
||||
break;
|
||||
|
|
|
@ -109,10 +109,18 @@ static const negated_function_mapping neg_map[]=
|
|||
};
|
||||
|
||||
/*
|
||||
This class is used for serialization of the Item tree for
|
||||
condition pushdown. It is stored in a linked list implemented
|
||||
by Ndb_cond class.
|
||||
*/
|
||||
This class is the construction element for serialization of Item tree
|
||||
in condition pushdown.
|
||||
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 {
|
||||
public:
|
||||
Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {};
|
||||
|
@ -134,6 +142,8 @@ class Ndb_item {
|
|||
break;
|
||||
}
|
||||
case(NDB_FUNCTION):
|
||||
value.item= item_value;
|
||||
break;
|
||||
case(NDB_END_COND):
|
||||
break;
|
||||
}
|
||||
|
@ -146,9 +156,11 @@ class Ndb_item {
|
|||
field_value->column_no= column_no;
|
||||
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;
|
||||
value.item= item_value;
|
||||
};
|
||||
~Ndb_item()
|
||||
{
|
||||
|
@ -179,6 +191,11 @@ class Ndb_item {
|
|||
|
||||
int get_field_no() { return value.field_value->column_no; };
|
||||
|
||||
int argument_count()
|
||||
{
|
||||
return ((Item_func *) value.item)->argument_count();
|
||||
};
|
||||
|
||||
const char* get_val()
|
||||
{
|
||||
switch(type) {
|
||||
|
@ -274,7 +291,7 @@ class Ndb_cond_traverse_context
|
|||
Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack)
|
||||
: table(tab), ndb_table(ndb_tab),
|
||||
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)
|
||||
cond_ptr= stack->ndb_cond;
|
||||
|
@ -318,6 +335,17 @@ class Ndb_cond_traverse_context
|
|||
expect_field_result_mask= 0;
|
||||
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;
|
||||
void* ndb_table;
|
||||
|
@ -327,6 +355,8 @@ class Ndb_cond_traverse_context
|
|||
uint expect_mask;
|
||||
uint expect_field_result_mask;
|
||||
uint skip;
|
||||
CHARSET_INFO* collation;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -428,27 +458,40 @@ class ha_ndbcluster: public handler
|
|||
/*
|
||||
Condition pushdown
|
||||
*/
|
||||
/*
|
||||
Push a condition to ndbcluster storage engine for evaluation
|
||||
during table and index scans. The conditions will be stored on a stack
|
||||
for possibly storing several conditions. The stack can be popped
|
||||
by calling cond_pop, handler::extra(HA_EXTRA_RESET) (handler::reset())
|
||||
will clear the 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:
|
||||
=, !=, >, >=, <, <=, "is null", and "is not null".
|
||||
|
||||
RETURN
|
||||
NULL The condition was supported and will be evaluated for each
|
||||
row found during the scan
|
||||
cond The condition was not supported and all rows will be returned from
|
||||
the scan for evaluation (and thus not saved on stack)
|
||||
*/
|
||||
|
||||
/*
|
||||
Push condition down to the table handler.
|
||||
SYNOPSIS
|
||||
cond_push()
|
||||
cond Condition to be pushed. The condition tree must not be
|
||||
modified by the by the caller.
|
||||
RETURN
|
||||
The 'remainder' condition that caller must use to filter out records.
|
||||
NULL means the handler will not return rows that do not match the
|
||||
passed condition.
|
||||
NOTES
|
||||
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.
|
||||
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);
|
||||
/*
|
||||
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();
|
||||
|
||||
uint8 table_cache_type();
|
||||
|
@ -536,8 +579,7 @@ private:
|
|||
NdbScanFilter* filter,
|
||||
bool negated= false);
|
||||
int build_scan_filter_group(Ndb_cond* &cond,
|
||||
NdbScanFilter* filter,
|
||||
bool negated= false);
|
||||
NdbScanFilter* filter);
|
||||
int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
|
||||
int generate_scan_filter(Ndb_cond_stack* cond_stack,
|
||||
NdbScanOperation* op);
|
||||
|
|
|
@ -451,7 +451,7 @@ public:
|
|||
enum {NONE=0, INDEX, RND} inited;
|
||||
bool auto_increment_column_changed;
|
||||
bool implicit_emptied; /* Can be !=0 only if HEAP */
|
||||
|
||||
const COND *pushed_cond;
|
||||
|
||||
handler(TABLE *table_arg) :table(table_arg),
|
||||
ref(0), data_file_length(0), max_data_file_length(0), index_file_length(0),
|
||||
|
@ -460,7 +460,8 @@ public:
|
|||
create_time(0), check_time(0), update_time(0),
|
||||
key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
|
||||
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); */ }
|
||||
int ha_open(const char *name, int mode, int test_if_locked);
|
||||
|
@ -724,23 +725,34 @@ public:
|
|||
Condition pushdown to storage engines
|
||||
*/
|
||||
|
||||
/*
|
||||
Push a condition to storage engine for evaluation during table
|
||||
and index scans. The conditions should be stored on a stack
|
||||
for possibly storing several conditions. The stack can be popped
|
||||
by calling cond_pop, handler::extra(HA_EXTRA_RESET) (handler::reset())
|
||||
should clear the stack.
|
||||
The condition can be traversed using Item::traverse_cond
|
||||
RETURN
|
||||
NULL The condition was supported by the handler and will be evaluated
|
||||
for each row found during the scan
|
||||
cond The condition was not supported and all rows will be returned from
|
||||
the scan for evaluation (and thus not saved on stack)
|
||||
*/
|
||||
/*
|
||||
Push condition down to the table handler.
|
||||
SYNOPSIS
|
||||
cond_push()
|
||||
cond Condition to be pushed. The condition tree must not be
|
||||
modified by the by the caller.
|
||||
RETURN
|
||||
The 'remainder' condition that caller must use to filter out records.
|
||||
NULL means the handler will not return rows that do not match the
|
||||
passed condition.
|
||||
NOTES
|
||||
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; };
|
||||
/*
|
||||
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; };
|
||||
};
|
||||
|
||||
|
|
|
@ -5305,7 +5305,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
|||
DBUG_RETURN(1);
|
||||
tab->select_cond=sel->cond=tmp;
|
||||
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
|
||||
tab->select_cond= sel->cond= NULL;
|
||||
|
@ -5428,8 +5433,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
|||
tab->cache.select->cond=tmp;
|
||||
tab->cache.select->read_tables=join->const_table_map;
|
||||
if (current_thd->variables.engine_condition_pushdown &&
|
||||
(tmp != tab->select_cond))
|
||||
tab->table->file->cond_push(tmp); // Push condition to handler
|
||||
(!tab->table->file->pushed_cond))
|
||||
{
|
||||
/* Push condition to handler */
|
||||
if (!tab->table->file->cond_push(tmp))
|
||||
tab->table->file->pushed_cond= tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue