Commit fc4a865f 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/ha_ndbcluster.h:
  Auto merged
sql/sql_select.cc:
  Auto merged
parents 9c9e64d5 267c5d79
......@@ -251,6 +251,108 @@ auto
1
3
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;
pk1 attr1 attr2 attr3
2 2 NULL NULL
......@@ -1023,6 +1125,212 @@ auto
1
3
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
set medium = 17
where
......@@ -1138,6 +1446,11 @@ id select_type table type possible_keys key key_len ref rows Extra
explain
select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1;
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;
DROP TABLE t1,t2,t3,t4;
......@@ -249,6 +249,104 @@ bin not like concat(0xBB, '%') and
vbin not like concat(0xBB, '%')
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
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;
......@@ -955,6 +1053,204 @@ bin not like concat(0xBB, '%') and
vbin not like concat(0xBB, '%')
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 t1
set medium = 17
......@@ -1044,6 +1340,8 @@ explain
select auto from t1 where string = "aaaa" collate latin1_general_ci order by auto;
explain
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;
DROP TABLE t1,t2,t3,t4;
......@@ -6184,572 +6184,784 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->supported= FALSE;
break;
}
DBUG_VOID_RETURN;
}
if (context->supported)
{
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 for end of AND/OR expression
if (!item)
Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
const Item_func *func_item;
// Check if we are rewriting some unsupported function call
if (rewrite_context &&
(func_item= rewrite_context->func_item) &&
rewrite_context->count++ == 0)
{
// 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();
switch(func_item->functype()) {
case(Item_func::BETWEEN):
/*
Check that the field is part of the table of the handler
instance and that we expect a field with of this result type.
Rewrite
<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)
{
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)
case(Item_func::IN_FUNC): {
/*
Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..)
to <field>|<const> = <const1>|<field1> OR
<field> = <const2>|<field2> ...
or actually in prefix format
BEGIN(OR) EQ(<field>|<const>, <const1><field1>),
EQ(<field>|<const>, <const2>|<field2>), ... END()
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
*/
if (context->expecting(item->type()))
{
// This is the <field>|<const> item, save it in the rewrite context
rewrite_context->left_hand_item= item;
if (item->type() == Item::FUNC_ITEM)
{
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)
Item_func *func_item= (Item_func *) item;
if (func_item->functype() == Item_func::UNKNOWN_FUNC &&
func_item->const_item())
{
// We have not seen second argument yet
if (type == MYSQL_TYPE_TIME ||
type == MYSQL_TYPE_DATE ||
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;
}
// Skip any arguments since we will evaluate function instead
DBUG_PRINT("info", ("Skip until end of arguments marker"));
context->skip= func_item->argument_count();
}
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 collation %s",
item->collation.collation->name));
context->supported= FALSE;
}
DBUG_PRINT("info", ("Found unsupported functional expression in BETWEEN|IN"));
context->supported= FALSE;
DBUG_VOID_RETURN;
}
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
{
// 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;
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()) {
case(Item_func::EQ_FUNC): {
DBUG_PRINT("info", ("EQ_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::NE_FUNC): {
DBUG_PRINT("info", ("NE_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::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);
case(Item_func::BETWEEN): {
/*
Rewrite
<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 (rewrite_context->count == 2)
{
// Lower limit of BETWEEN
DBUG_PRINT("info", ("GE_FUNC"));
curr_cond->ndb_item= new Ndb_item(Item_func::GE_FUNC, 2);
}
else if (rewrite_context->count == 3)
{
// Upper limit of BETWEEN
DBUG_PRINT("info", ("LE_FUNC"));
curr_cond->ndb_item= new Ndb_item(Item_func::LE_FUNC, 2);
}
else
{
// Illegal BETWEEN expression
DBUG_PRINT("info", ("Illegal BETWEEN expression"));
context->supported= FALSE;
DBUG_VOID_RETURN;
}
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);
case(Item_func::IN_FUNC): {
/*
Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..)
to <field>|<const> = <const1>|<field1> OR
<field> = <const2>|<field2> ...
or actually in prefix format
BEGIN(OR) EQ(<field>|<const>, <const1><field1>),
EQ(<field>|<const>, <const2>|<field2>), ... END()
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;
}
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);
break;
default:
context->supported= FALSE;
}
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)
// Handle left hand <field>|<const>
context->rewrite_stack= NULL; // Disable rewrite mode
context->expect_only(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::INT_ITEM);
context->expect(Item::STRING_ITEM);
context->expect(Item::VARBIN_ITEM);
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
context->expect_only(Item::FIELD_ITEM);
context->expect_only_field_result(STRING_RESULT);
context->expect_collation(func_item->collation.collation);
// We have not seen second argument yet
if (type == MYSQL_TYPE_TIME ||
type == MYSQL_TYPE_DATE ||
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
{
// 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))
// Check that field and string constant collations are the same
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",
item->collation.collation->name));
context->supported= FALSE;
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
{
DBUG_PRINT("info", ("Was not expecting field of type %u",
field->result_type()));
context->supported= FALSE;
}
}
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;
}
break;
}
default: {
DBUG_PRINT("info", ("Found func_item of type %d",
func_item->functype()));
context->supported= FALSE;
}
}
break;
}
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)
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
{
// 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);
// Did not expect function here
context->supported= FALSE;
break;
}
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;
}
switch(func_item->functype()) {
case(Item_func::EQ_FUNC): {
DBUG_PRINT("info", ("EQ_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;
}
}
else
context->supported= FALSE;
break;
case(Item::INT_ITEM):
DBUG_PRINT("info", ("INT_ITEM"));
if (context->expecting(Item::INT_ITEM))
{
Item_int *int_item= (Item_int *) item;
DBUG_PRINT("info", ("value %d", int_item->value));
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);
case(Item_func::NE_FUNC): {
DBUG_PRINT("info", ("NE_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;
}
else
{
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
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);
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);
break;
}
}
else
context->supported= FALSE;
break;
case(Item::REAL_ITEM):
DBUG_PRINT("info", ("REAL_ITEM %s"));
if (context->expecting(Item::REAL_ITEM))
{
Item_float *float_item= (Item_float *) item;
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
case(Item_func::BETWEEN) : {
DBUG_PRINT("info", ("BETWEEN, rewriting using AND"));
Ndb_rewrite_context *rewrite_context=
new Ndb_rewrite_context(func_item);
rewrite_context->next= context->rewrite_stack;
context->rewrite_stack= rewrite_context;
DBUG_PRINT("info", ("COND_AND_FUNC"));
curr_cond->ndb_item= new Ndb_item(Item_func::COND_AND_FUNC,
func_item->argument_count() - 1);
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
{
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
case(Item_func::IN_FUNC) : {
DBUG_PRINT("info", ("IN_FUNC, rewriting using OR"));
Ndb_rewrite_context *rewrite_context=
new Ndb_rewrite_context(func_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
context->supported= FALSE;
break;
case(Item::VARBIN_ITEM):
DBUG_PRINT("info", ("VARBIN_ITEM"));
if (context->expecting(Item::VARBIN_ITEM))
{
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_hex_string *varbin_item= (Item_hex_string *) item;
DBUG_PRINT("info", ("value \"%s\"",
varbin_item->val_str(&str)->ptr()));
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::VARBIN_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
if (context->expect_field_result_mask)
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(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
context->expect_only(Item::FIELD_ITEM);
context->expect_only_field_result(STRING_RESULT);
Item_int *int_item= (Item_int *) item;
DBUG_PRINT("info", ("value %d", int_item->value));
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
context->supported= FALSE;
break;
case(Item::REAL_ITEM):
DBUG_PRINT("info", ("REAL_ITEM %s"));
if (context->expecting(Item::REAL_ITEM))
{
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
Item_float *float_item= (Item_float *) item;
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_field_result(REAL_RESULT);
}
else
{
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
}
}
else
context->supported= FALSE;
break;
case(Item::DECIMAL_ITEM):
DBUG_PRINT("info", ("DECIMAL_ITEM %s"));
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)
else
context->supported= FALSE;
break;
case(Item::VARBIN_ITEM):
DBUG_PRINT("info", ("VARBIN_ITEM"));
if (context->expecting(Item::VARBIN_ITEM))
{
// 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);
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::VARBIN_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);
}
else
{
// Expect another logical expression
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_ITEM);
}
}
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
context->expect_only(Item::FUNC_ITEM);
context->expect(Item::COND_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
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;
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;
}
default: {
DBUG_PRINT("info", ("Found item of type %d", item->type()));
context->supported= FALSE;
}
}
}
if (context->supported && context->rewrite_stack)
{
Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
if (rewrite_context->count ==
rewrite_context->func_item->argument_count())
{
// Rewrite is done, wrap an END() at the en
DBUG_PRINT("info", ("End of condition group"));
prev_cond= curr_cond;
curr_cond= context->cond_ptr= new Ndb_cond();
prev_cond->next= curr_cond;
curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
// Pop rewrite stack
context->rewrite_stack= context->rewrite_stack->next;
}
}
}
}
DBUG_VOID_RETURN;
}
......@@ -7065,14 +7277,20 @@ ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter)
bool simple_cond= TRUE;
DBUG_ENTER("build_scan_filter");
switch(cond->ndb_item->type) {
case(Item_func::COND_AND_FUNC):
case(Item_func::COND_OR_FUNC):
simple_cond= FALSE;
break;
default:
break;
}
switch(cond->ndb_item->type) {
case(NDB_FUNCTION):
switch(cond->ndb_item->qualification.function_type) {
case(Item_func::COND_AND_FUNC):
case(Item_func::COND_OR_FUNC):
simple_cond= FALSE;
break;
default:
break;
}
break;
default:
break;
}
if (simple_cond && filter->begin() == -1)
DBUG_RETURN(1);
if (build_scan_filter_group(cond, filter))
......
......@@ -86,6 +86,7 @@ typedef struct ndb_item_field_value {
typedef union ndb_item_value {
const Item *item;
NDB_ITEM_FIELD_VALUE *field_value;
uint arg_count;
} NDB_ITEM_VALUE;
struct negated_function_mapping
......@@ -144,6 +145,7 @@ class Ndb_item {
}
case(NDB_FUNCTION):
value.item= item_value;
value.arg_count= ((Item_func *) item_value)->argument_count();
break;
case(NDB_END_COND):
break;
......@@ -162,6 +164,13 @@ class Ndb_item {
{
qualification.function_type= func_type;
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()
{
......@@ -194,7 +203,7 @@ class Ndb_item {
int argument_count()
{
return ((Item_func *) value.item)->argument_count();
return value.arg_count;
};
const char* get_val()
......@@ -273,12 +282,28 @@ class Ndb_cond_stack
{
if (ndb_cond) delete ndb_cond;
ndb_cond= NULL;
if (next) delete next;
next= NULL;
};
Ndb_cond *ndb_cond;
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
the Item tree. It stores a reference to the table the condition
......@@ -292,11 +317,16 @@ 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), collation(NULL)
expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL),
rewrite_stack(NULL)
{
if (stack)
cond_ptr= stack->ndb_cond;
};
~Ndb_cond_traverse_context()
{
if (rewrite_stack) delete rewrite_stack;
}
void expect(Item::Type type)
{
expect_mask|= (1 << type);
......@@ -357,7 +387,7 @@ class Ndb_cond_traverse_context
uint expect_field_result_mask;
uint skip;
CHARSET_INFO* collation;
Ndb_rewrite_context *rewrite_stack;
};
/*
......
......@@ -5401,10 +5401,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0)))
DBUG_RETURN(1);
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)
{
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;
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