Commit 87b965f2 authored by unknown's avatar unknown

Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.0

into mysql.com:/usr/local/home/marty/MySQL/mysql-5.0


sql/ha_ndbcluster.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
parents 982bd00d fc4a865f
...@@ -251,6 +251,108 @@ auto ...@@ -251,6 +251,108 @@ auto
1 1
3 3
4 4
select auto from t1 where
(string between "aaaa" and "cccc") and
(vstring between "aaaa" and "cccc") and
(bin between 0xAAAA and 0xCCCC) and
(vbin between 0xAAAA and 0xCCCC) and
(tiny between -3 and -1) and
(short between -3 and -1) and
(medium between -3 and -1) and
(long_int between -3 and -1) and
(longlong between -3 and -1) and
(utiny between 1 and 3) and
(ushort between 1 and 3) and
(umedium between 1 and 3) and
(ulong between 1 and 3) and
(ulonglong between 1 and 3) and
(bits between b'001' and b'011') and
(options between 'one' and 'three') and
(flags between 'one' and 'one,two,three') and
(date_field between '1901-01-01' and '1903-03-03') and
(year_field between '1901' and '1903') and
(time_field between '01:01:01' and '03:03:03') and
(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
order by auto;
auto
1
3
select auto from t1 where
("aaaa" between string and string) and
("aaaa" between vstring and vstring) and
(0xAAAA between bin and bin) and
(0xAAAA between vbin and vbin) and
(-1 between tiny and tiny) and
(-1 between short and short) and
(-1 between medium and medium) and
(-1 between long_int and long_int) and
(-1 between longlong and longlong) and
(1 between utiny and utiny) and
(1 between ushort and ushort) and
(1 between umedium and umedium) and
(1 between ulong and ulong) and
(1 between ulonglong and ulonglong) and
(b'001' between bits and bits) and
('one' between options and options) and
('one' between flags and flags) and
('1901-01-01' between date_field and date_field) and
('1901' between year_field and year_field) and
('01:01:01' between time_field and time_field) and
('1901-01-01 01:01:01' between date_time and date_time)
order by auto;
auto
1
select auto from t1 where
string in("aaaa","cccc") and
vstring in("aaaa","cccc") and
bin in(0xAAAA,0xCCCC) and
vbin in(0xAAAA,0xCCCC) and
tiny in(-1,-3) and
short in(-1,-3) and
medium in(-1,-3) and
long_int in(-1,-3) and
longlong in(-1,-3) and
utiny in(1,3) and
ushort in(1,3) and
umedium in(1,3) and
ulong in(1,3) and
ulonglong in(1,3) and
bits in(b'001',b'011') and
options in('one','three') and
flags in('one','one,two,three') and
date_field in('1901-01-01','1903-03-03') and
year_field in('1901','1903') and
time_field in('01:01:01','03:03:03') and
date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
order by auto;
auto
1
3
select auto from t1 where
"aaaa" in(string) and
"aaaa" in(vstring) and
0xAAAA in(bin) and
0xAAAA in(vbin) and
/* -1 in(tiny) and */
/* -1 in (short) and */
/* -1 in(medium) and */
/* -1 in(long_int) and */
/* -1 in(longlong) and */
1 in(utiny) and
1 in(ushort) and
1 in(umedium) and
1 in(ulong) and
1 in(ulonglong) and
b'001' in(bits) and
'one' in(options) and
'one' in(flags) and
'1901-01-01' in(date_field) and
'1901' in(year_field) and
'01:01:01' in(time_field) and
'1901-01-01 01:01:01' in(date_time)
order by auto;
auto
1
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
...@@ -1023,6 +1125,212 @@ auto ...@@ -1023,6 +1125,212 @@ auto
1 1
3 3
4 4
explain
select auto from t1 where
(string between "aaaa" and "cccc") and
(vstring between "aaaa" and "cccc") and
(bin between 0xAAAA and 0xCCCC) and
(vbin between 0xAAAA and 0xCCCC) and
(tiny between -3 and -1) and
(short between -3 and -1) and
(medium between -3 and -1) and
(long_int between -3 and -1) and
(longlong between -3 and -1) and
(utiny between 1 and 3) and
(ushort between 1 and 3) and
(umedium between 1 and 3) and
(ulong between 1 and 3) and
(ulonglong between 1 and 3) and
/* (bits between b'001' and b'011') and */
(options between 'one' and 'three') and
(flags between 'one' and 'one,two,three') and
(date_field between '1901-01-01' and '1903-03-03') and
(year_field between '1901' and '1903') and
(time_field between '01:01:01' and '03:03:03') and
(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
order by auto;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range medium_index medium_index 3 NULL 10 Using where with pushed condition; Using filesort
select auto from t1 where
(string between "aaaa" and "cccc") and
(vstring between "aaaa" and "cccc") and
(bin between 0xAAAA and 0xCCCC) and
(vbin between 0xAAAA and 0xCCCC) and
(tiny between -3 and -1) and
(short between -3 and -1) and
(medium between -3 and -1) and
(long_int between -3 and -1) and
(longlong between -3 and -1) and
(utiny between 1 and 3) and
(ushort between 1 and 3) and
(umedium between 1 and 3) and
(ulong between 1 and 3) and
(ulonglong between 1 and 3) and
/* (bits between b'001' and b'011') and */
(options between 'one' and 'three') and
(flags between 'one' and 'one,two,three') and
(date_field between '1901-01-01' and '1903-03-03') and
(year_field between '1901' and '1903') and
(time_field between '01:01:01' and '03:03:03') and
(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
order by auto;
auto
1
3
explain
select auto from t1 where
("aaaa" between string and string) and
("aaaa" between vstring and vstring) and
(0xAAAA between bin and bin) and
(0xAAAA between vbin and vbin) and
(-1 between tiny and tiny) and
(-1 between short and short) and
(-1 between medium and medium) and
(-1 between long_int and long_int) and
(-1 between longlong and longlong) and
(1 between utiny and utiny) and
(1 between ushort and ushort) and
(1 between umedium and umedium) and
(1 between ulong and ulong) and
(1 between ulonglong and ulonglong) and
/* (b'001' between bits and bits) and */
('one' between options and options) and
('one' between flags and flags) and
('1901-01-01' between date_field and date_field) and
('1901' between year_field and year_field) and
('01:01:01' between time_field and time_field) and
('1901-01-01 01:01:01' between date_time and date_time)
order by auto;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
select auto from t1 where
("aaaa" between string and string) and
("aaaa" between vstring and vstring) and
(0xAAAA between bin and bin) and
(0xAAAA between vbin and vbin) and
(-1 between tiny and tiny) and
(-1 between short and short) and
(-1 between medium and medium) and
(-1 between long_int and long_int) and
(-1 between longlong and longlong) and
(1 between utiny and utiny) and
(1 between ushort and ushort) and
(1 between umedium and umedium) and
(1 between ulong and ulong) and
(1 between ulonglong and ulonglong) and
/* (b'001' between bits and bits) and */
('one' between options and options) and
('one' between flags and flags) and
('1901-01-01' between date_field and date_field) and
('1901' between year_field and year_field) and
('01:01:01' between time_field and time_field) and
('1901-01-01 01:01:01' between date_time and date_time)
order by auto;
auto
1
explain
select auto from t1 where
string in("aaaa","cccc") and
vstring in("aaaa","cccc") and
bin in(0xAAAA,0xCCCC) and
vbin in(0xAAAA,0xCCCC) and
tiny in(-1,-3) and
short in(-1,-3) and
medium in(-1,-3) and
long_int in(-1,-3) and
longlong in(-1,-3) and
utiny in(1,3) and
ushort in(1,3) and
umedium in(1,3) and
ulong in(1,3) and
ulonglong in(1,3) and
/* bits in(b'001',b'011') and */
options in('one','three') and
flags in('one','one,two,three') and
date_field in('1901-01-01','1903-03-03') and
year_field in('1901','1903') and
time_field in('01:01:01','03:03:03') and
date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
order by auto;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range medium_index medium_index 3 NULL 20 Using where with pushed condition; Using filesort
select auto from t1 where
string in("aaaa","cccc") and
vstring in("aaaa","cccc") and
bin in(0xAAAA,0xCCCC) and
vbin in(0xAAAA,0xCCCC) and
tiny in(-1,-3) and
short in(-1,-3) and
medium in(-1,-3) and
long_int in(-1,-3) and
longlong in(-1,-3) and
utiny in(1,3) and
ushort in(1,3) and
umedium in(1,3) and
ulong in(1,3) and
ulonglong in(1,3) and
/* bits in(b'001',b'011') and */
options in('one','three') and
flags in('one','one,two,three') and
date_field in('1901-01-01','1903-03-03') and
year_field in('1901','1903') and
time_field in('01:01:01','03:03:03') and
date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
order by auto;
auto
1
3
explain
select auto from t1 where
"aaaa" in(string) and
"aaaa" in(vstring) and
0xAAAA in(bin) and
0xAAAA in(vbin) and
/* -1 in(tiny) and */
/* -1 in (short) and */
/* -1 in(medium) and */
/* -1 in(long_int) and */
/* -1 in(longlong) and */
1 in(utiny) and
1 in(ushort) and
1 in(umedium) and
1 in(ulong) and
1 in(ulonglong) and
/* b'001' in(bits) and */
'one' in(options) and
'one' in(flags) and
'1901-01-01' in(date_field) and
'1901' in(year_field) and
'01:01:01' in(time_field) and
'1901-01-01 01:01:01' in(date_time)
order by auto;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where with pushed condition; Using filesort
select auto from t1 where
"aaaa" in(string) and
"aaaa" in(vstring) and
0xAAAA in(bin) and
0xAAAA in(vbin) and
/* -1 in(tiny) and */
/* -1 in (short) and */
/* -1 in(medium) and */
/* -1 in(long_int) and */
/* -1 in(longlong) and */
1 in(utiny) and
1 in(ushort) and
1 in(umedium) and
1 in(ulong) and
1 in(ulonglong) and
/* b'001' in(bits) and */
'one' in(options) and
'one' in(flags) and
'1901-01-01' in(date_field) and
'1901' in(year_field) and
'01:01:01' in(time_field) and
'1901-01-01 01:01:01' in(date_time)
order by auto;
auto
1
update t1 update t1
set medium = 17 set medium = 17
where where
...@@ -1138,6 +1446,11 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1138,6 +1446,11 @@ id select_type table type possible_keys key key_len ref rows Extra
explain explain
select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1; select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where; Using filesort 1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where with pushed condition; Using filesort
explain
select * from t3 left join t4 on t4.attr2 = t3.attr2 where t4.attr1 > 1 and t4.attr3 < 5 or t4.attr1 is null order by t4.pk1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
1 SIMPLE t4 ALL NULL NULL NULL NULL 6 Using where
set engine_condition_pushdown = @old_ecpd; set engine_condition_pushdown = @old_ecpd;
DROP TABLE t1,t2,t3,t4; DROP TABLE t1,t2,t3,t4;
...@@ -249,6 +249,104 @@ bin not like concat(0xBB, '%') and ...@@ -249,6 +249,104 @@ bin not like concat(0xBB, '%') and
vbin not like concat(0xBB, '%') vbin not like concat(0xBB, '%')
order by auto; order by auto;
# BETWEEN
select auto from t1 where
(string between "aaaa" and "cccc") and
(vstring between "aaaa" and "cccc") and
(bin between 0xAAAA and 0xCCCC) and
(vbin between 0xAAAA and 0xCCCC) and
(tiny between -3 and -1) and
(short between -3 and -1) and
(medium between -3 and -1) and
(long_int between -3 and -1) and
(longlong between -3 and -1) and
(utiny between 1 and 3) and
(ushort between 1 and 3) and
(umedium between 1 and 3) and
(ulong between 1 and 3) and
(ulonglong between 1 and 3) and
(bits between b'001' and b'011') and
(options between 'one' and 'three') and
(flags between 'one' and 'one,two,three') and
(date_field between '1901-01-01' and '1903-03-03') and
(year_field between '1901' and '1903') and
(time_field between '01:01:01' and '03:03:03') and
(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
order by auto;
select auto from t1 where
("aaaa" between string and string) and
("aaaa" between vstring and vstring) and
(0xAAAA between bin and bin) and
(0xAAAA between vbin and vbin) and
(-1 between tiny and tiny) and
(-1 between short and short) and
(-1 between medium and medium) and
(-1 between long_int and long_int) and
(-1 between longlong and longlong) and
(1 between utiny and utiny) and
(1 between ushort and ushort) and
(1 between umedium and umedium) and
(1 between ulong and ulong) and
(1 between ulonglong and ulonglong) and
(b'001' between bits and bits) and
('one' between options and options) and
('one' between flags and flags) and
('1901-01-01' between date_field and date_field) and
('1901' between year_field and year_field) and
('01:01:01' between time_field and time_field) and
('1901-01-01 01:01:01' between date_time and date_time)
order by auto;
# IN
select auto from t1 where
string in("aaaa","cccc") and
vstring in("aaaa","cccc") and
bin in(0xAAAA,0xCCCC) and
vbin in(0xAAAA,0xCCCC) and
tiny in(-1,-3) and
short in(-1,-3) and
medium in(-1,-3) and
long_int in(-1,-3) and
longlong in(-1,-3) and
utiny in(1,3) and
ushort in(1,3) and
umedium in(1,3) and
ulong in(1,3) and
ulonglong in(1,3) and
bits in(b'001',b'011') and
options in('one','three') and
flags in('one','one,two,three') and
date_field in('1901-01-01','1903-03-03') and
year_field in('1901','1903') and
time_field in('01:01:01','03:03:03') and
date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
order by auto;
select auto from t1 where
"aaaa" in(string) and
"aaaa" in(vstring) and
0xAAAA in(bin) and
0xAAAA in(vbin) and
/* -1 in(tiny) and */
/* -1 in (short) and */
/* -1 in(medium) and */
/* -1 in(long_int) and */
/* -1 in(longlong) and */
1 in(utiny) and
1 in(ushort) and
1 in(umedium) and
1 in(ulong) and
1 in(ulonglong) and
b'001' in(bits) and
'one' in(options) and
'one' in(flags) and
'1901-01-01' in(date_field) and
'1901' in(year_field) and
'01:01:01' in(time_field) and
'1901-01-01 01:01:01' in(date_time)
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 t2 where attr3 is not null and attr1 > 2 order by pk1;
...@@ -955,6 +1053,204 @@ bin not like concat(0xBB, '%') and ...@@ -955,6 +1053,204 @@ bin not like concat(0xBB, '%') and
vbin not like concat(0xBB, '%') vbin not like concat(0xBB, '%')
order by auto; order by auto;
# BETWEEN
explain
select auto from t1 where
(string between "aaaa" and "cccc") and
(vstring between "aaaa" and "cccc") and
(bin between 0xAAAA and 0xCCCC) and
(vbin between 0xAAAA and 0xCCCC) and
(tiny between -3 and -1) and
(short between -3 and -1) and
(medium between -3 and -1) and
(long_int between -3 and -1) and
(longlong between -3 and -1) and
(utiny between 1 and 3) and
(ushort between 1 and 3) and
(umedium between 1 and 3) and
(ulong between 1 and 3) and
(ulonglong between 1 and 3) and
/* (bits between b'001' and b'011') and */
(options between 'one' and 'three') and
(flags between 'one' and 'one,two,three') and
(date_field between '1901-01-01' and '1903-03-03') and
(year_field between '1901' and '1903') and
(time_field between '01:01:01' and '03:03:03') and
(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
order by auto;
select auto from t1 where
(string between "aaaa" and "cccc") and
(vstring between "aaaa" and "cccc") and
(bin between 0xAAAA and 0xCCCC) and
(vbin between 0xAAAA and 0xCCCC) and
(tiny between -3 and -1) and
(short between -3 and -1) and
(medium between -3 and -1) and
(long_int between -3 and -1) and
(longlong between -3 and -1) and
(utiny between 1 and 3) and
(ushort between 1 and 3) and
(umedium between 1 and 3) and
(ulong between 1 and 3) and
(ulonglong between 1 and 3) and
/* (bits between b'001' and b'011') and */
(options between 'one' and 'three') and
(flags between 'one' and 'one,two,three') and
(date_field between '1901-01-01' and '1903-03-03') and
(year_field between '1901' and '1903') and
(time_field between '01:01:01' and '03:03:03') and
(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03')
order by auto;
explain
select auto from t1 where
("aaaa" between string and string) and
("aaaa" between vstring and vstring) and
(0xAAAA between bin and bin) and
(0xAAAA between vbin and vbin) and
(-1 between tiny and tiny) and
(-1 between short and short) and
(-1 between medium and medium) and
(-1 between long_int and long_int) and
(-1 between longlong and longlong) and
(1 between utiny and utiny) and
(1 between ushort and ushort) and
(1 between umedium and umedium) and
(1 between ulong and ulong) and
(1 between ulonglong and ulonglong) and
/* (b'001' between bits and bits) and */
('one' between options and options) and
('one' between flags and flags) and
('1901-01-01' between date_field and date_field) and
('1901' between year_field and year_field) and
('01:01:01' between time_field and time_field) and
('1901-01-01 01:01:01' between date_time and date_time)
order by auto;
select auto from t1 where
("aaaa" between string and string) and
("aaaa" between vstring and vstring) and
(0xAAAA between bin and bin) and
(0xAAAA between vbin and vbin) and
(-1 between tiny and tiny) and
(-1 between short and short) and
(-1 between medium and medium) and
(-1 between long_int and long_int) and
(-1 between longlong and longlong) and
(1 between utiny and utiny) and
(1 between ushort and ushort) and
(1 between umedium and umedium) and
(1 between ulong and ulong) and
(1 between ulonglong and ulonglong) and
/* (b'001' between bits and bits) and */
('one' between options and options) and
('one' between flags and flags) and
('1901-01-01' between date_field and date_field) and
('1901' between year_field and year_field) and
('01:01:01' between time_field and time_field) and
('1901-01-01 01:01:01' between date_time and date_time)
order by auto;
# IN
explain
select auto from t1 where
string in("aaaa","cccc") and
vstring in("aaaa","cccc") and
bin in(0xAAAA,0xCCCC) and
vbin in(0xAAAA,0xCCCC) and
tiny in(-1,-3) and
short in(-1,-3) and
medium in(-1,-3) and
long_int in(-1,-3) and
longlong in(-1,-3) and
utiny in(1,3) and
ushort in(1,3) and
umedium in(1,3) and
ulong in(1,3) and
ulonglong in(1,3) and
/* bits in(b'001',b'011') and */
options in('one','three') and
flags in('one','one,two,three') and
date_field in('1901-01-01','1903-03-03') and
year_field in('1901','1903') and
time_field in('01:01:01','03:03:03') and
date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
order by auto;
select auto from t1 where
string in("aaaa","cccc") and
vstring in("aaaa","cccc") and
bin in(0xAAAA,0xCCCC) and
vbin in(0xAAAA,0xCCCC) and
tiny in(-1,-3) and
short in(-1,-3) and
medium in(-1,-3) and
long_int in(-1,-3) and
longlong in(-1,-3) and
utiny in(1,3) and
ushort in(1,3) and
umedium in(1,3) and
ulong in(1,3) and
ulonglong in(1,3) and
/* bits in(b'001',b'011') and */
options in('one','three') and
flags in('one','one,two,three') and
date_field in('1901-01-01','1903-03-03') and
year_field in('1901','1903') and
time_field in('01:01:01','03:03:03') and
date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03')
order by auto;
explain
select auto from t1 where
"aaaa" in(string) and
"aaaa" in(vstring) and
0xAAAA in(bin) and
0xAAAA in(vbin) and
/* -1 in(tiny) and */
/* -1 in (short) and */
/* -1 in(medium) and */
/* -1 in(long_int) and */
/* -1 in(longlong) and */
1 in(utiny) and
1 in(ushort) and
1 in(umedium) and
1 in(ulong) and
1 in(ulonglong) and
/* b'001' in(bits) and */
'one' in(options) and
'one' in(flags) and
'1901-01-01' in(date_field) and
'1901' in(year_field) and
'01:01:01' in(time_field) and
'1901-01-01 01:01:01' in(date_time)
order by auto;
select auto from t1 where
"aaaa" in(string) and
"aaaa" in(vstring) and
0xAAAA in(bin) and
0xAAAA in(vbin) and
/* -1 in(tiny) and */
/* -1 in (short) and */
/* -1 in(medium) and */
/* -1 in(long_int) and */
/* -1 in(longlong) and */
1 in(utiny) and
1 in(ushort) and
1 in(umedium) and
1 in(ulong) and
1 in(ulonglong) and
/* b'001' in(bits) and */
'one' in(options) and
'one' in(flags) and
'1901-01-01' in(date_field) and
'1901' in(year_field) and
'01:01:01' in(time_field) and
'1901-01-01 01:01:01' in(date_time)
order by auto;
# Update test # Update test
update t1 update t1
set medium = 17 set medium = 17
...@@ -1044,6 +1340,8 @@ explain ...@@ -1044,6 +1340,8 @@ explain
select auto from t1 where string = "aaaa" collate latin1_general_ci order by auto; select auto from t1 where string = "aaaa" collate latin1_general_ci order by auto;
explain explain
select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1; select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1;
explain
select * from t3 left join t4 on t4.attr2 = t3.attr2 where t4.attr1 > 1 and t4.attr3 < 5 or t4.attr1 is null order by t4.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;
...@@ -6172,572 +6172,784 @@ void ndb_serialize_cond(const Item *item, void *arg) ...@@ -6172,572 +6172,784 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->supported= FALSE; context->supported= FALSE;
break; break;
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
if (context->supported) if (context->supported)
{ {
Ndb_cond_stack *ndb_stack= context->stack_ptr; Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
Ndb_cond *prev_cond= context->cond_ptr; const Item_func *func_item;
Ndb_cond *curr_cond= context->cond_ptr= new Ndb_cond(); // Check if we are rewriting some unsupported function call
if (!ndb_stack->ndb_cond) if (rewrite_context &&
ndb_stack->ndb_cond= curr_cond; (func_item= rewrite_context->func_item) &&
curr_cond->prev= prev_cond; rewrite_context->count++ == 0)
if (prev_cond) prev_cond->next= curr_cond;
// Check for end of AND/OR expression
if (!item)
{ {
// End marker for condition group switch(func_item->functype()) {
DBUG_PRINT("info", ("End of condition group")); case(Item_func::BETWEEN):
curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
}
else
switch(item->type()) {
case(Item::FIELD_ITEM): {
Item_field *field_item= (Item_field *) item;
Field *field= field_item->field;
enum_field_types type= field->type();
/* /*
Check that the field is part of the table of the handler Rewrite
instance and that we expect a field with of this result type. <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2>
to <field>|<const> > <const1>|<field1> AND
<field>|<const> < <const2>|<field2>
or actually in prefix format
BEGIN(AND) GT(<field>|<const>, <const1>|<field1>),
LT(<field>|<const>, <const2>|<field2>), END()
*/ */
if (context->table == field->table) case(Item_func::IN_FUNC): {
{ /*
const NDBTAB *tab= (const NDBTAB *) context->ndb_table; Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..)
DBUG_PRINT("info", ("FIELD_ITEM")); to <field>|<const> = <const1>|<field1> OR
DBUG_PRINT("info", ("table %s", tab->getName())); <field> = <const2>|<field2> ...
DBUG_PRINT("info", ("column %s", field->field_name)); or actually in prefix format
DBUG_PRINT("info", ("result type %d", field->result_type())); BEGIN(OR) EQ(<field>|<const>, <const1><field1>),
EQ(<field>|<const>, <const2>|<field2>), ... END()
// Check that we are expecting a field and with the correct Each part of the disjunction is added for each call
// result type to ndb_serialize_cond and end of rewrite statement
if(context->expecting(Item::FIELD_ITEM) && is wrapped in end of ndb_serialize_cond
(context->expecting_field_result(field->result_type()) || */
// Date and year can be written as strings if (context->expecting(item->type()))
(type == MYSQL_TYPE_TIME || {
type == MYSQL_TYPE_DATE || // This is the <field>|<const> item, save it in the rewrite context
type == MYSQL_TYPE_YEAR || rewrite_context->left_hand_item= item;
type == MYSQL_TYPE_DATETIME) if (item->type() == Item::FUNC_ITEM)
? context->expecting_field_result(STRING_RESULT) : true)
// Bit fields no yet supported in scan filter
&& type != MYSQL_TYPE_BIT)
{ {
const NDBCOL *col= tab->getColumn(field->field_name); Item_func *func_item= (Item_func *) item;
DBUG_ASSERT(col); if (func_item->functype() == Item_func::UNKNOWN_FUNC &&
curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo()); func_item->const_item())
context->dont_expect(Item::FIELD_ITEM);
context->expect_no_field_result();
if (context->expect_mask)
{ {
// We have not seen second argument yet // Skip any arguments since we will evaluate function instead
if (type == MYSQL_TYPE_TIME || DBUG_PRINT("info", ("Skip until end of arguments marker"));
type == MYSQL_TYPE_DATE || context->skip= func_item->argument_count();
type == MYSQL_TYPE_YEAR ||
type == MYSQL_TYPE_DATETIME)
{
context->expect_only(Item::STRING_ITEM);
context->expect(Item::INT_ITEM);
}
else
switch(field->result_type()) {
case(STRING_RESULT):
// 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);
context->expect(Item::DECIMAL_ITEM);
break;
case(INT_RESULT):
context->expect_only(Item::INT_ITEM);
context->expect(Item::VARBIN_ITEM);
break;
case(DECIMAL_RESULT):
context->expect_only(Item::DECIMAL_ITEM);
context->expect(Item::REAL_ITEM);
break;
default:
break;
}
} }
else else
{ {
// Expect another logical expression DBUG_PRINT("info", ("Found unsupported functional expression in BETWEEN|IN"));
context->expect_only(Item::FUNC_ITEM); context->supported= FALSE;
context->expect(Item::COND_ITEM); DBUG_VOID_RETURN;
// 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 collation %s",
item->collation.collation->name));
context->supported= FALSE;
}
} }
break;
} }
} }
DBUG_PRINT("info", ("Was not expecting field of type %u",
field->result_type()));
context->supported= FALSE;
break;
}
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 else
{ {
// Did not expect function here // Non-supported BETWEEN|IN expression
DBUG_PRINT("info", ("Found unexpected item of type %u in BETWEEN|IN",
item->type()));
context->supported= FALSE; context->supported= FALSE;
break; DBUG_VOID_RETURN;
} }
break;
}
default:
context->supported= FALSE;
break;
}
DBUG_VOID_RETURN;
}
else
{
Ndb_cond_stack *ndb_stack= context->stack_ptr;
Ndb_cond *prev_cond= context->cond_ptr;
Ndb_cond *curr_cond= context->cond_ptr= new Ndb_cond();
if (!ndb_stack->ndb_cond)
ndb_stack->ndb_cond= curr_cond;
curr_cond->prev= prev_cond;
if (prev_cond) prev_cond->next= curr_cond;
// Check if we are rewriting some unsupported function call
if (context->rewrite_stack)
{
Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
const Item_func *func_item= rewrite_context->func_item;
switch(func_item->functype()) { switch(func_item->functype()) {
case(Item_func::EQ_FUNC): { case(Item_func::BETWEEN): {
DBUG_PRINT("info", ("EQ_FUNC")); /*
curr_cond->ndb_item= new Ndb_item(func_item->functype(), Rewrite
func_item); <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2>
context->expect(Item::STRING_ITEM); to <field>|<const> > <const1>|<field1> AND
context->expect(Item::INT_ITEM); <field>|<const> < <const2>|<field2>
context->expect(Item::REAL_ITEM); or actually in prefix format
context->expect(Item::DECIMAL_ITEM); BEGIN(AND) GT(<field>|<const>, <const1>|<field1>),
context->expect(Item::VARBIN_ITEM); LT(<field>|<const>, <const2>|<field2>), END()
context->expect(Item::FIELD_ITEM); */
context->expect_field_result(STRING_RESULT); if (rewrite_context->count == 2)
context->expect_field_result(REAL_RESULT); {
context->expect_field_result(INT_RESULT); // Lower limit of BETWEEN
context->expect_field_result(DECIMAL_RESULT); DBUG_PRINT("info", ("GE_FUNC"));
break; curr_cond->ndb_item= new Ndb_item(Item_func::GE_FUNC, 2);
} }
case(Item_func::NE_FUNC): { else if (rewrite_context->count == 3)
DBUG_PRINT("info", ("NE_FUNC")); {
curr_cond->ndb_item= new Ndb_item(func_item->functype(), // Upper limit of BETWEEN
func_item); DBUG_PRINT("info", ("LE_FUNC"));
context->expect(Item::STRING_ITEM); curr_cond->ndb_item= new Ndb_item(Item_func::LE_FUNC, 2);
context->expect(Item::INT_ITEM); }
context->expect(Item::REAL_ITEM); else
context->expect(Item::DECIMAL_ITEM); {
context->expect(Item::VARBIN_ITEM); // Illegal BETWEEN expression
context->expect(Item::FIELD_ITEM); DBUG_PRINT("info", ("Illegal BETWEEN expression"));
context->expect_field_result(STRING_RESULT); context->supported= FALSE;
context->expect_field_result(REAL_RESULT); DBUG_VOID_RETURN;
context->expect_field_result(INT_RESULT); }
context->expect_field_result(DECIMAL_RESULT);
break;
}
case(Item_func::LT_FUNC): {
DBUG_PRINT("info", ("LT_FUNC"));
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);
context->expect(Item::DECIMAL_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
break;
}
case(Item_func::LE_FUNC): {
DBUG_PRINT("info", ("LE_FUNC"));
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);
context->expect(Item::DECIMAL_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
break;
}
case(Item_func::GE_FUNC): {
DBUG_PRINT("info", ("GE_FUNC"));
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);
context->expect(Item::DECIMAL_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
break;
}
case(Item_func::GT_FUNC): {
DBUG_PRINT("info", ("GT_FUNC"));
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);
context->expect(Item::INT_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
break;
}
case(Item_func::LIKE_FUNC): {
DBUG_PRINT("info", ("LIKE_FUNC"));
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);
break;
}
case(Item_func::NOTLIKE_FUNC): {
DBUG_PRINT("info", ("NOTLIKE_FUNC"));
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);
break;
}
case(Item_func::ISNULL_FUNC): {
DBUG_PRINT("info", ("ISNULL_FUNC"));
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);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
break; break;
} }
case(Item_func::ISNOTNULL_FUNC): { case(Item_func::IN_FUNC): {
DBUG_PRINT("info", ("ISNOTNULL_FUNC")); /*
curr_cond->ndb_item= new Ndb_item(func_item->functype(), Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..)
func_item); to <field>|<const> = <const1>|<field1> OR
context->expect(Item::FIELD_ITEM); <field> = <const2>|<field2> ...
context->expect_field_result(STRING_RESULT); or actually in prefix format
context->expect_field_result(REAL_RESULT); BEGIN(OR) EQ(<field>|<const>, <const1><field1>),
context->expect_field_result(INT_RESULT); EQ(<field>|<const>, <const2>|<field2>), ... END()
context->expect_field_result(DECIMAL_RESULT); Each part of the disjunction is added for each call
to ndb_serialize_cond and end of rewrite statement
is wrapped in end of ndb_serialize_cond
*/
DBUG_PRINT("info", ("EQ_FUNC"));
curr_cond->ndb_item= new Ndb_item(Item_func::EQ_FUNC, 2);
break; break;
} }
case(Item_func::NOT_FUNC): { default:
DBUG_PRINT("info", ("NOT_FUNC")); context->supported= FALSE;
curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
break;
} }
case(Item_func::UNKNOWN_FUNC): { // Handle left hand <field>|<const>
DBUG_PRINT("info", ("UNKNOWN_FUNC %s", context->rewrite_stack= NULL; // Disable rewrite mode
func_item->const_item()?"const":"")); context->expect_only(Item::FIELD_ITEM);
DBUG_PRINT("info", ("result type %d", func_item->result_type())); context->expect_field_result(STRING_RESULT);
if (func_item->const_item()) context->expect_field_result(REAL_RESULT);
switch(func_item->result_type()) { context->expect_field_result(INT_RESULT);
case(STRING_RESULT): { context->expect_field_result(DECIMAL_RESULT);
NDB_ITEM_QUALIFICATION q; context->expect(Item::INT_ITEM);
q.value_type= Item::STRING_ITEM; context->expect(Item::STRING_ITEM);
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); context->expect(Item::VARBIN_ITEM);
if (context->expect_field_result_mask) context->expect(Item::FUNC_ITEM);
ndb_serialize_cond(rewrite_context->left_hand_item, arg);
context->skip= 0; // Any FUNC_ITEM expression has already been parsed
context->rewrite_stack= rewrite_context; // Enable rewrite mode
if (!context->supported)
DBUG_VOID_RETURN;
prev_cond= context->cond_ptr;
curr_cond= context->cond_ptr= new Ndb_cond();
prev_cond->next= curr_cond;
}
// Check for end of AND/OR expression
if (!item)
{
// End marker for condition group
DBUG_PRINT("info", ("End of condition group"));
curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
}
else
switch(item->type()) {
case(Item::FIELD_ITEM): {
Item_field *field_item= (Item_field *) item;
Field *field= field_item->field;
enum_field_types type= field->type();
/*
Check that the field is part of the table of the handler
instance and that we expect a field with of this result type.
*/
if (context->table == field->table)
{
const NDBTAB *tab= (const NDBTAB *) context->ndb_table;
DBUG_PRINT("info", ("FIELD_ITEM"));
DBUG_PRINT("info", ("table %s", tab->getName()));
DBUG_PRINT("info", ("column %s", field->field_name));
DBUG_PRINT("info", ("result type %d", field->result_type()));
// Check that we are expecting a field and with the correct
// result type
if (context->expecting(Item::FIELD_ITEM) &&
(context->expecting_field_result(field->result_type()) ||
// Date and year can be written as strings
((type == MYSQL_TYPE_TIME ||
type == MYSQL_TYPE_DATE ||
type == MYSQL_TYPE_YEAR ||
type == MYSQL_TYPE_DATETIME)
? context->expecting_field_result(STRING_RESULT) : true)) &&
// Bit fields no yet supported in scan filter
type != MYSQL_TYPE_BIT)
{
const NDBCOL *col= tab->getColumn(field->field_name);
DBUG_ASSERT(col);
curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo());
context->dont_expect(Item::FIELD_ITEM);
context->expect_no_field_result();
if (context->expect_mask)
{ {
// We have not seen the field argument yet // We have not seen second argument yet
context->expect_only(Item::FIELD_ITEM); if (type == MYSQL_TYPE_TIME ||
context->expect_only_field_result(STRING_RESULT); type == MYSQL_TYPE_DATE ||
context->expect_collation(func_item->collation.collation); type == MYSQL_TYPE_YEAR ||
type == MYSQL_TYPE_DATETIME)
{
context->expect_only(Item::STRING_ITEM);
context->expect(Item::INT_ITEM);
}
else
switch(field->result_type()) {
case(STRING_RESULT):
// 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);
context->expect(Item::DECIMAL_ITEM);
break;
case(INT_RESULT):
context->expect_only(Item::INT_ITEM);
context->expect(Item::VARBIN_ITEM);
break;
case(DECIMAL_RESULT):
context->expect_only(Item::DECIMAL_ITEM);
context->expect(Item::REAL_ITEM);
break;
default:
break;
}
} }
else else
{ {
// Expect another logical expression // Expect another logical expression
context->expect_only(Item::FUNC_ITEM); context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM); context->expect(Item::COND_ITEM);
// Check that string result have correct collation // Check that field and string constant collations are the same
if (!context->expecting_collation(item->collation.collation)) if ((field->result_type() == STRING_RESULT) &&
!context->expecting_collation(item->collation.collation)
&& type != MYSQL_TYPE_TIME
&& type != MYSQL_TYPE_DATE
&& type != MYSQL_TYPE_YEAR
&& type != MYSQL_TYPE_DATETIME)
{ {
DBUG_PRINT("info", ("Found non-matching collation %s", DBUG_PRINT("info", ("Found non-matching collation %s",
item->collation.collation->name)); item->collation.collation->name));
context->supported= FALSE; 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();
break; break;
} }
case(REAL_RESULT): { else
NDB_ITEM_QUALIFICATION q; {
q.value_type= Item::REAL_ITEM; DBUG_PRINT("info", ("Was not expecting field of type %u",
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); field->result_type()));
if (context->expect_field_result_mask) context->supported= FALSE;
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
context->expect_only_field_result(REAL_RESULT);
}
else
{
// 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();
break;
}
case(INT_RESULT): {
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::INT_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(INT_RESULT);
}
else
{
// 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();
break;
}
case(DECIMAL_RESULT): {
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::DECIMAL_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(DECIMAL_RESULT);
}
else
{
// 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();
break;
}
default:
break;
} }
}
else else
// Function does not return constant expression {
DBUG_PRINT("info", ("Was not expecting field from table %s(%s)",
context->table->s->table_name,
field->table->s->table_name));
context->supported= FALSE; context->supported= FALSE;
}
break; break;
} }
default: { case(Item::FUNC_ITEM): {
DBUG_PRINT("info", ("Found func_item of type %d", Item_func *func_item= (Item_func *) item;
func_item->functype())); // Check that we expect a function or functional expression here
context->supported= FALSE; if (context->expecting(Item::FUNC_ITEM) ||
} func_item->functype() == Item_func::UNKNOWN_FUNC)
} context->expect_nothing();
break; else
}
case(Item::STRING_ITEM):
DBUG_PRINT("info", ("STRING_ITEM"));
if (context->expecting(Item::STRING_ITEM))
{
#ifndef DBUG_OFF
char buff[256];
String str(buff,(uint32) sizeof(buff), system_charset_info);
str.length(0);
Item_string *string_item= (Item_string *) item;
DBUG_PRINT("info", ("value \"%s\"",
string_item->val_str(&str)->ptr()));
#endif
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::STRING_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 // Did not expect function here
context->expect_only(Item::FIELD_ITEM); context->supported= FALSE;
context->expect_only_field_result(STRING_RESULT); break;
context->expect_collation(item->collation.collation);
} }
else
{ switch(func_item->functype()) {
// Expect another logical expression case(Item_func::EQ_FUNC): {
context->expect_only(Item::FUNC_ITEM); DBUG_PRINT("info", ("EQ_FUNC"));
context->expect(Item::COND_ITEM); curr_cond->ndb_item= new Ndb_item(func_item->functype(),
// Check that we are comparing with a field with same collation func_item);
if (!context->expecting_collation(item->collation.collation)) context->expect(Item::STRING_ITEM);
{ context->expect(Item::INT_ITEM);
DBUG_PRINT("info", ("Found non-matching collation %s", context->expect(Item::REAL_ITEM);
item->collation.collation->name)); context->expect(Item::DECIMAL_ITEM);
context->supported= FALSE; context->expect(Item::VARBIN_ITEM);
} context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
context->expect(Item::FUNC_ITEM);
break;
} }
} case(Item_func::NE_FUNC): {
else DBUG_PRINT("info", ("NE_FUNC"));
context->supported= FALSE; curr_cond->ndb_item= new Ndb_item(func_item->functype(),
break; func_item);
case(Item::INT_ITEM): context->expect(Item::STRING_ITEM);
DBUG_PRINT("info", ("INT_ITEM")); context->expect(Item::INT_ITEM);
if (context->expecting(Item::INT_ITEM)) context->expect(Item::REAL_ITEM);
{ context->expect(Item::DECIMAL_ITEM);
Item_int *int_item= (Item_int *) item; context->expect(Item::VARBIN_ITEM);
DBUG_PRINT("info", ("value %d", int_item->value)); context->expect(Item::FIELD_ITEM);
NDB_ITEM_QUALIFICATION q; context->expect_field_result(STRING_RESULT);
q.value_type= Item::INT_ITEM; context->expect_field_result(REAL_RESULT);
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); context->expect_field_result(INT_RESULT);
if (context->expect_field_result_mask) context->expect_field_result(DECIMAL_RESULT);
{ context->expect(Item::FUNC_ITEM);
// We have not seen the field argument yet break;
context->expect_only(Item::FIELD_ITEM);
context->expect_only_field_result(INT_RESULT);
} }
else case(Item_func::LT_FUNC): {
{ DBUG_PRINT("info", ("LT_FUNC"));
// Expect another logical expression curr_cond->ndb_item= new Ndb_item(func_item->functype(),
context->expect_only(Item::FUNC_ITEM); func_item);
context->expect(Item::STRING_ITEM);
context->expect(Item::INT_ITEM);
context->expect(Item::REAL_ITEM);
context->expect(Item::DECIMAL_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
context->expect(Item::FUNC_ITEM);
break;
}
case(Item_func::LE_FUNC): {
DBUG_PRINT("info", ("LE_FUNC"));
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);
context->expect(Item::DECIMAL_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
context->expect(Item::FUNC_ITEM);
break;
}
case(Item_func::GE_FUNC): {
DBUG_PRINT("info", ("GE_FUNC"));
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);
context->expect(Item::DECIMAL_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
context->expect(Item::FUNC_ITEM);
break;
}
case(Item_func::GT_FUNC): {
DBUG_PRINT("info", ("GT_FUNC"));
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);
context->expect(Item::INT_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FIELD_ITEM);
context->expect_field_result(STRING_RESULT);
context->expect_field_result(REAL_RESULT);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
context->expect(Item::FUNC_ITEM);
break;
}
case(Item_func::LIKE_FUNC): {
DBUG_PRINT("info", ("LIKE_FUNC"));
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);
context->expect(Item::FUNC_ITEM);
break;
}
case(Item_func::NOTLIKE_FUNC): {
DBUG_PRINT("info", ("NOTLIKE_FUNC"));
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);
context->expect(Item::FUNC_ITEM);
break;
}
case(Item_func::ISNULL_FUNC): {
DBUG_PRINT("info", ("ISNULL_FUNC"));
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);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
break;
}
case(Item_func::ISNOTNULL_FUNC): {
DBUG_PRINT("info", ("ISNOTNULL_FUNC"));
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);
context->expect_field_result(INT_RESULT);
context->expect_field_result(DECIMAL_RESULT);
break;
}
case(Item_func::NOT_FUNC): {
DBUG_PRINT("info", ("NOT_FUNC"));
curr_cond->ndb_item= new Ndb_item(func_item->functype(),
func_item);
context->expect(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM); context->expect(Item::COND_ITEM);
break;
} }
} case(Item_func::BETWEEN) : {
else DBUG_PRINT("info", ("BETWEEN, rewriting using AND"));
context->supported= FALSE; Ndb_rewrite_context *rewrite_context=
break; new Ndb_rewrite_context(func_item);
case(Item::REAL_ITEM): rewrite_context->next= context->rewrite_stack;
DBUG_PRINT("info", ("REAL_ITEM %s")); context->rewrite_stack= rewrite_context;
if (context->expecting(Item::REAL_ITEM)) DBUG_PRINT("info", ("COND_AND_FUNC"));
{ curr_cond->ndb_item= new Ndb_item(Item_func::COND_AND_FUNC,
Item_float *float_item= (Item_float *) item; func_item->argument_count() - 1);
DBUG_PRINT("info", ("value %f", float_item->value));
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::REAL_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(Item::FIELD_ITEM);
context->expect_only_field_result(REAL_RESULT); context->expect(Item::INT_ITEM);
context->expect(Item::STRING_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FUNC_ITEM);
break;
} }
else case(Item_func::IN_FUNC) : {
{ DBUG_PRINT("info", ("IN_FUNC, rewriting using OR"));
// Expect another logical expression Ndb_rewrite_context *rewrite_context=
context->expect_only(Item::FUNC_ITEM); new Ndb_rewrite_context(func_item);
context->expect(Item::COND_ITEM); rewrite_context->next= context->rewrite_stack;
context->rewrite_stack= rewrite_context;
DBUG_PRINT("info", ("COND_OR_FUNC"));
curr_cond->ndb_item= new Ndb_item(Item_func::COND_OR_FUNC,
func_item->argument_count() - 1);
context->expect_only(Item::FIELD_ITEM);
context->expect(Item::INT_ITEM);
context->expect(Item::STRING_ITEM);
context->expect(Item::VARBIN_ITEM);
context->expect(Item::FUNC_ITEM);
break;
}
case(Item_func::UNKNOWN_FUNC): {
DBUG_PRINT("info", ("UNKNOWN_FUNC %s",
func_item->const_item()?"const":""));
DBUG_PRINT("info", ("result type %d", func_item->result_type()));
if (func_item->const_item())
switch(func_item->result_type()) {
case(STRING_RESULT): {
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::STRING_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
{
// 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 collation %s",
item->collation.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();
break;
}
case(REAL_RESULT): {
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::REAL_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(REAL_RESULT);
}
else
{
// 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();
break;
}
case(INT_RESULT): {
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::INT_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(INT_RESULT);
}
else
{
// 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();
break;
}
case(DECIMAL_RESULT): {
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::DECIMAL_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(DECIMAL_RESULT);
}
else
{
// 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();
break;
}
default:
break;
}
else
// Function does not return constant expression
context->supported= FALSE;
break;
}
default: {
DBUG_PRINT("info", ("Found func_item of type %d",
func_item->functype()));
context->supported= FALSE;
} }
}
break;
} }
else case(Item::STRING_ITEM):
context->supported= FALSE; DBUG_PRINT("info", ("STRING_ITEM"));
break; if (context->expecting(Item::STRING_ITEM))
case(Item::VARBIN_ITEM): {
DBUG_PRINT("info", ("VARBIN_ITEM"));
if (context->expecting(Item::VARBIN_ITEM))
{
#ifndef DBUG_OFF #ifndef DBUG_OFF
char buff[256]; char buff[256];
String str(buff,(uint32) sizeof(buff), system_charset_info); String str(buff,(uint32) sizeof(buff), system_charset_info);
str.length(0); str.length(0);
Item_hex_string *varbin_item= (Item_hex_string *) item; Item_string *string_item= (Item_string *) item;
DBUG_PRINT("info", ("value \"%s\"", DBUG_PRINT("info", ("value \"%s\"",
varbin_item->val_str(&str)->ptr())); string_item->val_str(&str)->ptr()));
#endif #endif
NDB_ITEM_QUALIFICATION q; NDB_ITEM_QUALIFICATION q;
q.value_type= Item::VARBIN_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
context->expect_only(Item::FIELD_ITEM);
context->expect_only_field_result(STRING_RESULT);
context->expect_collation(item->collation.collation);
}
else
{
// 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 collation %s",
item->collation.collation->name));
context->supported= FALSE;
}
}
}
else
context->supported= FALSE;
break;
case(Item::INT_ITEM):
DBUG_PRINT("info", ("INT_ITEM"));
if (context->expecting(Item::INT_ITEM))
{ {
// We have not seen the field argument yet Item_int *int_item= (Item_int *) item;
context->expect_only(Item::FIELD_ITEM); DBUG_PRINT("info", ("value %d", int_item->value));
context->expect_only_field_result(STRING_RESULT); NDB_ITEM_QUALIFICATION q;
q.value_type= Item::INT_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(INT_RESULT);
}
else
{
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
} }
else else
context->supported= FALSE;
break;
case(Item::REAL_ITEM):
DBUG_PRINT("info", ("REAL_ITEM %s"));
if (context->expecting(Item::REAL_ITEM))
{ {
// Expect another logical expression Item_float *float_item= (Item_float *) item;
context->expect_only(Item::FUNC_ITEM); DBUG_PRINT("info", ("value %f", float_item->value));
context->expect(Item::COND_ITEM); NDB_ITEM_QUALIFICATION q;
q.value_type= Item::REAL_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(REAL_RESULT);
}
else
{
// 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::VARBIN_ITEM):
case(Item::DECIMAL_ITEM): DBUG_PRINT("info", ("VARBIN_ITEM"));
DBUG_PRINT("info", ("DECIMAL_ITEM %s")); if (context->expecting(Item::VARBIN_ITEM))
if (context->expecting(Item::DECIMAL_ITEM))
{
Item_decimal *decimal_item= (Item_decimal *) item;
DBUG_PRINT("info", ("value %f", decimal_item->val_real()));
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::DECIMAL_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 NDB_ITEM_QUALIFICATION q;
context->expect_only(Item::FIELD_ITEM); q.value_type= Item::VARBIN_ITEM;
context->expect_only_field_result(REAL_RESULT); curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
context->expect_field_result(DECIMAL_RESULT); 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);
}
else
{
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
} }
else else
context->supported= FALSE;
break;
case(Item::DECIMAL_ITEM):
DBUG_PRINT("info", ("DECIMAL_ITEM %s"));
if (context->expecting(Item::DECIMAL_ITEM))
{ {
// Expect another logical expression Item_decimal *decimal_item= (Item_decimal *) item;
context->expect_only(Item::FUNC_ITEM); DBUG_PRINT("info", ("value %f", decimal_item->val_real()));
context->expect(Item::COND_ITEM); NDB_ITEM_QUALIFICATION q;
q.value_type= Item::DECIMAL_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(REAL_RESULT);
context->expect_field_result(DECIMAL_RESULT);
}
else
{
// 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;
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;
} }
else default: {
DBUG_PRINT("info", ("Found item of type %d", item->type()));
context->supported= FALSE; context->supported= FALSE;
break; }
case(Item::COND_ITEM): { }
Item_cond *cond_item= (Item_cond *) item;
if (context->supported && context->rewrite_stack)
if (context->expecting(Item::COND_ITEM)) {
switch(cond_item->functype()) { Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
case(Item_func::COND_AND_FUNC): if (rewrite_context->count ==
DBUG_PRINT("info", ("COND_AND_FUNC")); rewrite_context->func_item->argument_count())
curr_cond->ndb_item= new Ndb_item(cond_item->functype(), {
cond_item); // Rewrite is done, wrap an END() at the en
break; DBUG_PRINT("info", ("End of condition group"));
case(Item_func::COND_OR_FUNC): prev_cond= curr_cond;
DBUG_PRINT("info", ("COND_OR_FUNC")); curr_cond= context->cond_ptr= new Ndb_cond();
curr_cond->ndb_item= new Ndb_item(cond_item->functype(), prev_cond->next= curr_cond;
cond_item); curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
break; // Pop rewrite stack
default: context->rewrite_stack= context->rewrite_stack->next;
DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype())); }
context->supported= FALSE;
break;
}
else
// Did not expect condition
context->supported= FALSE;
break;
}
default: {
DBUG_PRINT("info", ("Found item of type %d", item->type()));
context->supported= FALSE;
}
} }
}
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -7053,14 +7265,20 @@ ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter) ...@@ -7053,14 +7265,20 @@ ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter)
bool simple_cond= TRUE; bool simple_cond= TRUE;
DBUG_ENTER("build_scan_filter"); DBUG_ENTER("build_scan_filter");
switch(cond->ndb_item->type) { switch(cond->ndb_item->type) {
case(Item_func::COND_AND_FUNC): case(NDB_FUNCTION):
case(Item_func::COND_OR_FUNC): switch(cond->ndb_item->qualification.function_type) {
simple_cond= FALSE; case(Item_func::COND_AND_FUNC):
break; case(Item_func::COND_OR_FUNC):
default: simple_cond= FALSE;
break; break;
} default:
break;
}
break;
default:
break;
}
if (simple_cond && filter->begin() == -1) if (simple_cond && filter->begin() == -1)
DBUG_RETURN(1); DBUG_RETURN(1);
if (build_scan_filter_group(cond, filter)) if (build_scan_filter_group(cond, filter))
......
...@@ -86,6 +86,7 @@ typedef struct ndb_item_field_value { ...@@ -86,6 +86,7 @@ typedef struct ndb_item_field_value {
typedef union ndb_item_value { typedef union ndb_item_value {
const Item *item; const Item *item;
NDB_ITEM_FIELD_VALUE *field_value; NDB_ITEM_FIELD_VALUE *field_value;
uint arg_count;
} NDB_ITEM_VALUE; } NDB_ITEM_VALUE;
struct negated_function_mapping struct negated_function_mapping
...@@ -144,6 +145,7 @@ class Ndb_item { ...@@ -144,6 +145,7 @@ class Ndb_item {
} }
case(NDB_FUNCTION): case(NDB_FUNCTION):
value.item= item_value; value.item= item_value;
value.arg_count= ((Item_func *) item_value)->argument_count();
break; break;
case(NDB_END_COND): case(NDB_END_COND):
break; break;
...@@ -162,6 +164,13 @@ class Ndb_item { ...@@ -162,6 +164,13 @@ class Ndb_item {
{ {
qualification.function_type= func_type; qualification.function_type= func_type;
value.item= item_value; value.item= item_value;
value.arg_count= ((Item_func *) item_value)->argument_count();
};
Ndb_item(Item_func::Functype func_type, uint no_args)
: type(NDB_FUNCTION)
{
qualification.function_type= func_type;
value.arg_count= no_args;
}; };
~Ndb_item() ~Ndb_item()
{ {
...@@ -194,7 +203,7 @@ class Ndb_item { ...@@ -194,7 +203,7 @@ class Ndb_item {
int argument_count() int argument_count()
{ {
return ((Item_func *) value.item)->argument_count(); return value.arg_count;
}; };
const char* get_val() const char* get_val()
...@@ -273,12 +282,28 @@ class Ndb_cond_stack ...@@ -273,12 +282,28 @@ class Ndb_cond_stack
{ {
if (ndb_cond) delete ndb_cond; if (ndb_cond) delete ndb_cond;
ndb_cond= NULL; ndb_cond= NULL;
if (next) delete next;
next= NULL; next= NULL;
}; };
Ndb_cond *ndb_cond; Ndb_cond *ndb_cond;
Ndb_cond_stack *next; Ndb_cond_stack *next;
}; };
class Ndb_rewrite_context
{
public:
Ndb_rewrite_context(Item_func *func)
: func_item(func), left_hand_item(NULL), count(0) {};
~Ndb_rewrite_context()
{
if (next) delete next;
}
const Item_func *func_item;
const Item *left_hand_item;
uint count;
Ndb_rewrite_context *next;
};
/* /*
This class is used for storing the context when traversing This class is used for storing the context when traversing
the Item tree. It stores a reference to the table the condition the Item tree. It stores a reference to the table the condition
...@@ -292,11 +317,16 @@ class Ndb_cond_traverse_context ...@@ -292,11 +317,16 @@ 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), collation(NULL) expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL),
rewrite_stack(NULL)
{ {
if (stack) if (stack)
cond_ptr= stack->ndb_cond; cond_ptr= stack->ndb_cond;
}; };
~Ndb_cond_traverse_context()
{
if (rewrite_stack) delete rewrite_stack;
}
void expect(Item::Type type) void expect(Item::Type type)
{ {
expect_mask|= (1 << type); expect_mask|= (1 << type);
...@@ -357,7 +387,7 @@ class Ndb_cond_traverse_context ...@@ -357,7 +387,7 @@ class Ndb_cond_traverse_context
uint expect_field_result_mask; uint expect_field_result_mask;
uint skip; uint skip;
CHARSET_INFO* collation; CHARSET_INFO* collation;
Ndb_rewrite_context *rewrite_stack;
}; };
/* /*
......
...@@ -5461,10 +5461,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -5461,10 +5461,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0))) if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0)))
DBUG_RETURN(1); DBUG_RETURN(1);
tab->select_cond=sel->cond=tmp; tab->select_cond=sel->cond=tmp;
/* Push condition to storage engine if this is enabled
and the condition is not guarded */
if (thd->variables.engine_condition_pushdown) if (thd->variables.engine_condition_pushdown)
{ {
COND *push_cond= COND *push_cond=
make_cond_for_table(cond,current_map,current_map); make_cond_for_table(tmp,current_map,current_map);
tab->table->file->pushed_cond= NULL; tab->table->file->pushed_cond= NULL;
if (push_cond) if (push_cond)
{ {
......
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