From 9e04ebfa99c12ffef5f03846c3696ba650986f4b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 May 2005 18:56:29 +0200 Subject: [PATCH 01/29] Fix for Bug #9246 Condition pushdown and left join, wrong result --- mysql-test/r/ndb_condition_pushdown.result | 5 +++++ mysql-test/t/ndb_condition_pushdown.test | 2 ++ sql/sql_select.cc | 4 +++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result index 7f769154212..4ddfa5817d8 100644 --- a/mysql-test/r/ndb_condition_pushdown.result +++ b/mysql-test/r/ndb_condition_pushdown.result @@ -1139,5 +1139,10 @@ 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 +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; diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test index 1d201a94c95..c6f3f67a65f 100644 --- a/mysql-test/t/ndb_condition_pushdown.test +++ b/mysql-test/t/ndb_condition_pushdown.test @@ -1044,6 +1044,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; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 47c7de6eba7..72fc407692b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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) { From 267c5d7986dcb0415d02ddb6317b8976e362b55d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 May 2005 14:32:05 +0200 Subject: [PATCH 02/29] Added support for BETWEEN and IN in condition pushdown to ndbcluster by rewriting them as AND and OR expressions --- mysql-test/r/ndb_condition_pushdown.result | 310 ++++- mysql-test/t/ndb_condition_pushdown.test | 296 +++++ sql/ha_ndbcluster.cc | 1286 ++++++++++++-------- sql/ha_ndbcluster.h | 36 +- 4 files changed, 1390 insertions(+), 538 deletions(-) diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result index 4ddfa5817d8..e62c8bb5704 100644 --- a/mysql-test/r/ndb_condition_pushdown.result +++ b/mysql-test/r/ndb_condition_pushdown.result @@ -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,7 +1446,7 @@ 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 diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test index c6f3f67a65f..f0a8e7754dd 100644 --- a/mysql-test/t/ndb_condition_pushdown.test +++ b/mysql-test/t/ndb_condition_pushdown.test @@ -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 diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 372a178b59a..74aff359483 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -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); + switch(func_item->functype()) { + case(Item_func::BETWEEN): + /* + Rewrite + | BETWEEN | AND | + to | > | AND + | < | + or actually in prefix format + BEGIN(AND) GT(|, |), + LT(|, |), END() + */ + case(Item_func::IN_FUNC): { + /* + Rewrite | IN(|, |,..) + to | = | OR + = | ... + or actually in prefix format + BEGIN(OR) EQ(|, ), + EQ(|, |), ... 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 | item, save it in the rewrite context + rewrite_context->left_hand_item= item; + if (item->type() == Item::FUNC_ITEM) + { + Item_func *func_item= (Item_func *) item; + if (func_item->functype() == Item_func::UNKNOWN_FUNC && + func_item->const_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(); + } + else + { + DBUG_PRINT("info", ("Found unsupported functional expression in BETWEEN|IN")); + context->supported= FALSE; + DBUG_VOID_RETURN; + + } + } + } + else + { + // Non-supported BETWEEN|IN expression + DBUG_PRINT("info", ("Found unexpected item of type %u in BETWEEN|IN", + item->type())); + context->supported= FALSE; + DBUG_VOID_RETURN; + } + break; + } + default: + context->supported= FALSE; + break; + } + DBUG_VOID_RETURN; } 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(); + { + 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::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 + | BETWEEN | AND | + to | > | AND + | < | + or actually in prefix format + BEGIN(AND) GT(|, |), + LT(|, |), 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) + if (rewrite_context->count == 2) { - 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) + // 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::IN_FUNC): { + /* + Rewrite | IN(|, |,..) + to | = | OR + = | ... + or actually in prefix format + BEGIN(OR) EQ(|, ), + EQ(|, |), ... 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; + } + default: + context->supported= FALSE; + } + // Handle left hand | + 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) { - // We have not seen second argument yet - if (type == MYSQL_TYPE_TIME || - type == MYSQL_TYPE_DATE || - type == MYSQL_TYPE_YEAR || - type == MYSQL_TYPE_DATETIME) + 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) { - context->expect_only(Item::STRING_ITEM); - context->expect(Item::INT_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; + } } 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; - } + { + // 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) + && 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; + } + } + break; + } + else + { + DBUG_PRINT("info", ("Was not expecting field of type %u", + field->result_type())); + context->supported= FALSE; + } + } + else + { + 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; + } + case(Item::FUNC_ITEM): { + Item_func *func_item= (Item_func *) item; + // Check that we expect a function or functional expression here + if (context->expecting(Item::FUNC_ITEM) || + func_item->functype() == Item_func::UNKNOWN_FUNC) + context->expect_nothing(); + else + { + // Did not expect function here + context->supported= FALSE; + break; + } + + 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; + } + 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; + } + 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; + } + 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(Item::INT_ITEM); + context->expect(Item::STRING_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FUNC_ITEM); + break; + } + 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; + } + 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 + 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)) + { + 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); - // 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 - { - // Did not expect function here - context->supported= FALSE; + else + context->supported= FALSE; break; - } - - 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); - 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; - } - 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(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 + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(REAL_RESULT); } - 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; + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); } - 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; + } + else + context->supported= FALSE; + break; + case(Item::VARBIN_ITEM): + DBUG_PRINT("info", ("VARBIN_ITEM")); + if (context->expecting(Item::VARBIN_ITEM)) + { + 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); } - 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; + 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) + { + // 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 - // Function does not return constant expression - context->supported= FALSE; + // Did not expect condition + context->supported= FALSE; break; } default: { - DBUG_PRINT("info", ("Found func_item of type %d", - func_item->functype())); + DBUG_PRINT("info", ("Found item of type %d", item->type())); 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) - { - // 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)) - { - 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)) - { - 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::VARBIN_ITEM): - DBUG_PRINT("info", ("VARBIN_ITEM")); - if (context->expecting(Item::VARBIN_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())); -#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) - { - // 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)) - { - 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; - } - 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)) diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 81b2873d9dd..47ac7986e59 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -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; }; /* From af8cbbaec5cab3b3bbce3a0af423d9725c33f3f0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 May 2005 16:41:53 -0700 Subject: [PATCH 03/29] Fix '%h', '%I', and '%l' format specifiers in TIME_FORMAT() to handle large time values as documented. (Bug #10590) mysql-test/r/func_time.result: Add new results mysql-test/t/func_time.test: Add new regression test sql/item_timefunc.cc: Fix handling of '%h', '%I', and '%l' format specifiers for TIME_FORMAT() to handle large time values correctly. --- mysql-test/r/func_time.result | 3 +++ mysql-test/t/func_time.test | 6 ++++++ sql/item_timefunc.cc | 7 ++----- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 4293ef5bd85..239fca65b67 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -688,3 +688,6 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 select timestamp_diff(WEEK,_latin1'2001-02-01',_latin1'2001-05-01') AS `a1`,timestamp_diff(SECOND_FRAC,_latin1'2001-02-01 12:59:59.120000',_latin1'2001-05-01 12:58:58.119999') AS `a2` +select time_format('100:00:00', '%H %k %h %I %l'); +time_format('100:00:00', '%H %k %h %I %l') +100 100 04 04 4 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 80ddb205110..34da2ae1435 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -336,3 +336,9 @@ DROP TABLE t1; explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1, timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2; + +# +# Bug #10590: %h, %I, and %l format specifies should all return results in +# the 0-11 range +# +select time_format('100:00:00', '%H %k %h %I %l'); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 7a9c7898856..a99297180e5 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -497,7 +497,6 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, timestamp_type type, String *str) { char intbuff[15]; - uint days_i; uint hours_i; uint weekday; ulong length; @@ -600,8 +599,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, break; case 'h': case 'I': - days_i= l_time->hour/24; - hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i; + hours_i= (l_time->hour%24 + 11)%12+1; length= int10_to_str(hours_i, intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 2, '0'); break; @@ -622,8 +620,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, str->append_with_prefill(intbuff, length, 1, '0'); break; case 'l': - days_i= l_time->hour/24; - hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i; + hours_i= (l_time->hour%24 + 11)%12+1; length= int10_to_str(hours_i, intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 1, '0'); break; From 51d8161d564ad6d78cfc34dbb316db7593e626c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Jun 2005 09:32:05 +0200 Subject: [PATCH 04/29] FIELD_TYPE_NEWDECIMAL is numeric too --- include/mysql.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index b2b2e239758..84284fa0661 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -74,14 +74,14 @@ extern char *mysql_unix_port; #define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG) #define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG) #define IS_BLOB(n) ((n) & BLOB_FLAG) -#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR) +#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR || (t) == FIELD_TYPE_NEWDECIMAL) #define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG) #define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR) typedef struct st_mysql_field { char *name; /* Name of column */ - char *org_name; /* Original column name, if an alias */ + char *org_name; /* Original column name, if an alias */ char *table; /* Table of column if column was a field */ char *org_table; /* Org table name, if table was an alias */ char *db; /* Database for table */ From 9f50c2ffacfdeba18bfc85c8c2410d59c8528c39 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Jun 2005 11:56:47 +0200 Subject: [PATCH 05/29] Fixed handling of condition pushdown to storage engine of NO BETWEEN and NOT IN --- mysql-test/r/ndb_condition_pushdown.result | 344 ++++++++++++++++++++- mysql-test/t/ndb_condition_pushdown.test | 326 ++++++++++++++++++- sql/ha_ndbcluster.cc | 9 +- 3 files changed, 647 insertions(+), 32 deletions(-) diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result index e62c8bb5704..2465c4272cb 100644 --- a/mysql-test/r/ndb_condition_pushdown.result +++ b/mysql-test/r/ndb_condition_pushdown.result @@ -303,6 +303,58 @@ order by auto; auto 1 select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +(bits not between b'001' and b'011') and +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; +auto +4 +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +(b'001' not between bits and bits) and +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; +auto +2 +3 +4 +select auto from t1 where string in("aaaa","cccc") and vstring in("aaaa","cccc") and bin in(0xAAAA,0xCCCC) and @@ -333,11 +385,11 @@ select auto from t1 where "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(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 @@ -353,6 +405,59 @@ b'001' in(bits) and order by auto; auto 1 +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +bits not in(b'001',b'011') and +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; +auto +2 +4 +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +b'001' not in(bits) and +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; +auto +2 +3 +4 select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1; pk1 attr1 attr2 attr3 2 2 NULL NULL @@ -1228,6 +1333,110 @@ select auto from t1 where order by auto; auto 1 +explain +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +/* (bits not between b'001' and b'011') and */ +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not 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 20 Using where with pushed condition; Using filesort +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +/* (bits not between b'001' and b'011') and */ +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; +auto +4 +explain +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +/* (b'001' not between bits and bits) and */ +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not 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" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +/* (b'001' not between bits and bits) and */ +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; +auto +2 +3 +4 explain select auto from t1 where string in("aaaa","cccc") and @@ -1286,11 +1495,11 @@ select auto from t1 where "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(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 @@ -1311,11 +1520,11 @@ select auto from t1 where "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(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 @@ -1331,6 +1540,111 @@ select auto from t1 where order by auto; auto 1 +explain +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +/* bits not in(b'001',b'011') and */ +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not 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 30 Using where with pushed condition; Using filesort +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +/* bits not in(b'001',b'011') and */ +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; +auto +2 +4 +explain +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +/* b'001' not in(bits) and */ +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not 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" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +/* b'001' not in(bits) and */ +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; +auto +2 +3 +4 update t1 set medium = 17 where diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test index f0a8e7754dd..d090d12e81b 100644 --- a/mysql-test/t/ndb_condition_pushdown.test +++ b/mysql-test/t/ndb_condition_pushdown.test @@ -298,6 +298,55 @@ select auto from t1 where ('1901-01-01 01:01:01' between date_time and date_time) order by auto; +# NOT BETWEEN +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +(bits not between b'001' and b'011') and +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +(b'001' not between bits and bits) and +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; + # IN select auto from t1 where string in("aaaa","cccc") and @@ -328,11 +377,11 @@ select auto from t1 where "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(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 @@ -347,6 +396,55 @@ b'001' in(bits) and '1901-01-01 01:01:01' in(date_time) order by auto; +# NOT IN +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +bits not in(b'001',b'011') and +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +b'001' not in(bits) and +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not 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; @@ -1152,6 +1250,105 @@ select auto from t1 where ('1901-01-01 01:01:01' between date_time and date_time) order by auto; +# NOT BETWEEN +explain +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +/* (bits not between b'001' and b'011') and */ +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +(string not between "aaaa" and "cccc") and +(vstring not between "aaaa" and "cccc") and +(bin not between 0xAAAA and 0xCCCC) and +(vbin not between 0xAAAA and 0xCCCC) and +(tiny not between -3 and -1) and +(short not between -3 and -1) and +(medium not between -3 and -1) and +(long_int not between -3 and -1) and +(longlong not between -3 and -1) and +(utiny not between 1 and 3) and +(ushort not between 1 and 3) and +(umedium not between 1 and 3) and +(ulong not between 1 and 3) and +(ulonglong not between 1 and 3) and +/* (bits not between b'001' and b'011') and */ +(options not between 'one' and 'three') and +(flags not between 'one' and 'one,two,three') and +(date_field not between '1901-01-01' and '1903-03-03') and +(year_field not between '1901' and '1903') and +(time_field not between '01:01:01' and '03:03:03') and +(date_time not between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') +order by auto; + +explain +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +/* (b'001' not between bits and bits) and */ +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; + +select auto from t1 where +("aaaa" not between string and string) and +("aaaa" not between vstring and vstring) and +(0xAAAA not between bin and bin) and +(0xAAAA not between vbin and vbin) and +(-1 not between tiny and tiny) and +(-1 not between short and short) and +(-1 not between medium and medium) and +(-1 not between long_int and long_int) and +(-1 not between longlong and longlong) and +(1 not between utiny and utiny) and +(1 not between ushort and ushort) and +(1 not between umedium and umedium) and +(1 not between ulong and ulong) and +(1 not between ulonglong and ulonglong) and +/* (b'001' not between bits and bits) and */ +('one' not between options and options) and +('one' not between flags and flags) and +('1901-01-01' not between date_field and date_field) and +('1901' not between year_field and year_field) and +('01:01:01' not between time_field and time_field) and +('1901-01-01 01:01:01' not between date_time and date_time) +order by auto; + # IN explain select auto from t1 where @@ -1208,11 +1405,11 @@ select auto from t1 where "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(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 @@ -1232,11 +1429,11 @@ select auto from t1 where "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(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 @@ -1251,6 +1448,105 @@ select auto from t1 where '1901-01-01 01:01:01' in(date_time) order by auto; +# NOT IN +explain +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +/* bits not in(b'001',b'011') and */ +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; + +select auto from t1 where +string not in("aaaa","cccc") and +vstring not in("aaaa","cccc") and +bin not in(0xAAAA,0xCCCC) and +vbin not in(0xAAAA,0xCCCC) and +tiny not in(-1,-3) and +short not in(-1,-3) and +medium not in(-1,-3) and +long_int not in(-1,-3) and +longlong not in(-1,-3) and +utiny not in(1,3) and +ushort not in(1,3) and +umedium not in(1,3) and +ulong not in(1,3) and +ulonglong not in(1,3) and +/* bits not in(b'001',b'011') and */ +options not in('one','three') and +flags not in('one','one,two,three') and +date_field not in('1901-01-01','1903-03-03') and +year_field not in('1901','1903') and +time_field not in('01:01:01','03:03:03') and +date_time not in('1901-01-01 01:01:01','1903-03-03 03:03:03') +order by auto; + +explain +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +/* b'001' not in(bits) and */ +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; + +select auto from t1 where +"aaaa" not in(string) and +"aaaa" not in(vstring) and +0xAAAA not in(bin) and +0xAAAA not in(vbin) and +(-1 not in(tiny)) and +(-1 not in(short)) and +(-1 not in(medium)) and +(-1 not in(long_int)) and +(-1 not in(longlong)) and +1 not in(utiny) and +1 not in(ushort) and +1 not in(umedium) and +1 not in(ulong) and +1 not in(ulonglong) and +/* b'001' not in(bits) and */ +'one' not in(options) and +'one' not in(flags) and +'1901-01-01' not in(date_field) and +'1901' not in(year_field) and +'01:01:01' not in(time_field) and +'1901-01-01 01:01:01' not in(date_time) +order by auto; + # Update test update t1 set medium = 17 diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 8b9706bb81f..0b6a8e34e93 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -7232,8 +7232,10 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) break; } case(Item_func::NOT_FUNC): { + DBUG_PRINT("info", ("Generating negated query")); cond= cond->next; negated= TRUE; + break; } default: @@ -7249,12 +7251,14 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) if (cond) cond= cond->next; if (filter->end() == -1) DBUG_RETURN(1); - break; + if (!negated) + break; + // else fall through (NOT END is an illegal condition) default: { DBUG_PRINT("info", ("Illegal scan filter")); } } - } while (level > 0); + } while (level > 0 || negated); DBUG_RETURN(0); } @@ -7296,6 +7300,7 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack, DBUG_ENTER("generate_scan_filter"); if (ndb_cond_stack) { + DBUG_PRINT("info", ("Generating scan filter")); NdbScanFilter filter(op); bool multiple_cond= FALSE; // Wrap an AND group around multiple conditions From 6d397aae1a3f82868f21a82fb41b767ca58156d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Jun 2005 14:20:16 +0200 Subject: [PATCH 06/29] Bug#10602 - LOAD INDEX INTO CACHE deadlocks Fixed two deadlocks. Made minor changes. mysys/mf_keycache.c: Bug#10602 - LOAD INDEX INTO CACHE deadlocks Fixed two deadlocks. Made keycache traces line buffered. Removed unused macro and function. Added comments and trace messages. Fixed two compiler warnings. Fixed some coding style issues. --- mysys/mf_keycache.c | 121 +++++++++++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 30 deletions(-) diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index cee1b7eb4e9..f14af44dbb9 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -184,10 +184,18 @@ static void test_key_cache(KEY_CACHE *keycache, static FILE *keycache_debug_log=NULL; static void keycache_debug_print _VARARGS((const char *fmt,...)); #define KEYCACHE_DEBUG_OPEN \ - if (!keycache_debug_log) keycache_debug_log=fopen(KEYCACHE_DEBUG_LOG, "w") + if (!keycache_debug_log) \ + { \ + keycache_debug_log= fopen(KEYCACHE_DEBUG_LOG, "w"); \ + (void) setvbuf(keycache_debug_log, NULL, _IOLBF, BUFSIZ); \ + } #define KEYCACHE_DEBUG_CLOSE \ - if (keycache_debug_log) { fclose(keycache_debug_log); keycache_debug_log=0; } + if (keycache_debug_log) \ + { \ + fclose(keycache_debug_log); \ + keycache_debug_log= 0; \ + } #else #define KEYCACHE_DEBUG_OPEN #define KEYCACHE_DEBUG_CLOSE @@ -213,7 +221,7 @@ static long keycache_thread_id; #define KEYCACHE_THREAD_TRACE_BEGIN(l) \ { struct st_my_thread_var *thread_var= my_thread_var; \ - keycache_thread_id= my_thread_var->id; \ + keycache_thread_id= thread_var->id; \ KEYCACHE_DBUG_PRINT(l,("[thread %ld",keycache_thread_id)) } #define KEYCACHE_THREAD_TRACE_END(l) \ @@ -240,12 +248,10 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond, static int keycache_pthread_mutex_lock(pthread_mutex_t *mutex); static void keycache_pthread_mutex_unlock(pthread_mutex_t *mutex); static int keycache_pthread_cond_signal(pthread_cond_t *cond); -static int keycache_pthread_cond_broadcast(pthread_cond_t *cond); #else #define keycache_pthread_mutex_lock pthread_mutex_lock #define keycache_pthread_mutex_unlock pthread_mutex_unlock #define keycache_pthread_cond_signal pthread_cond_signal -#define keycache_pthread_cond_broadcast pthread_cond_broadcast #endif /* defined(KEYCACHE_DEBUG) */ static uint next_power(uint value) @@ -508,6 +514,8 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, keycache->can_be_used= 0; while (keycache->cnt_for_resize_op) { + KEYCACHE_DBUG_PRINT("resize_key_cache: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -520,7 +528,11 @@ finish: unlink_from_queue(wqueue, thread); /* Signal for the next resize request to proceeed if any */ if (wqueue->last_thread) + { + KEYCACHE_DBUG_PRINT("resize_key_cache: signal", + ("thread %ld", wqueue->last_thread->next->id)); keycache_pthread_cond_signal(&wqueue->last_thread->next->suspend); + } keycache_pthread_mutex_unlock(&keycache->cache_lock); return blocks; } @@ -544,7 +556,11 @@ static inline void dec_counter_for_resize_op(KEY_CACHE *keycache) struct st_my_thread_var *last_thread; if (!--keycache->cnt_for_resize_op && (last_thread= keycache->resize_queue.last_thread)) + { + KEYCACHE_DBUG_PRINT("dec_counter_for_resize_op: signal", + ("thread %ld", last_thread->next->id)); keycache_pthread_cond_signal(&last_thread->next->suspend); + } } /* @@ -761,8 +777,8 @@ static void release_queue(KEYCACHE_WQUEUE *wqueue) do { thread=next; - keycache_pthread_cond_signal(&thread->suspend); KEYCACHE_DBUG_PRINT("release_queue: signal", ("thread %ld", thread->id)); + keycache_pthread_cond_signal(&thread->suspend); next=thread->next; thread->next= NULL; } @@ -876,7 +892,8 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, BLOCK_LINK **pins; KEYCACHE_DBUG_ASSERT(! (block->hash_link && block->hash_link->requests)); - if (!hot && keycache->waiting_for_block.last_thread) { + if (!hot && keycache->waiting_for_block.last_thread) + { /* Signal that in the LRU warm sub-chain an available block has appeared */ struct st_my_thread_var *last_thread= keycache->waiting_for_block.last_thread; @@ -894,6 +911,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, */ if ((HASH_LINK *) thread->opt_info == hash_link) { + KEYCACHE_DBUG_PRINT("link_block: signal", ("thread %ld", thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_block, thread); block->requests++; @@ -1000,11 +1018,10 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count) linking it to the LRU chain if it's the last request SYNOPSIS - - unreg_block() - keycache pointer to a key cache data structure - block pointer to the block to link to the LRU chain - at_end <-> to link the block at the end of the LRU chain + unreg_request() + keycache pointer to a key cache data structure + block pointer to the block to link to the LRU chain + at_end <-> to link the block at the end of the LRU chain RETURN VALUE none @@ -1086,6 +1103,9 @@ static inline void wait_for_readers(KEY_CACHE *keycache, BLOCK_LINK *block) struct st_my_thread_var *thread= my_thread_var; while (block->hash_link->requests) { + KEYCACHE_DBUG_PRINT("wait_for_readers: wait", + ("suspend thread %ld block %u", + thread->id, BLOCK_NUMBER(block))); block->condvar= &thread->suspend; keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); block->condvar= NULL; @@ -1143,6 +1163,7 @@ static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link) */ if (page->file == hash_link->file && page->filepos == hash_link->diskpos) { + KEYCACHE_DBUG_PRINT("unlink_hash: signal", ("thread %ld", thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_hash_link, thread); } @@ -1225,6 +1246,8 @@ restart: page.filepos= filepos; thread->opt_info= (void *) &page; link_into_queue(&keycache->waiting_for_hash_link, thread); + KEYCACHE_DBUG_PRINT("get_hash_link: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); thread->opt_info= NULL; @@ -1343,6 +1366,8 @@ restart: add_to_queue(&block->wqueue[COND_FOR_SAVED], thread); do { + KEYCACHE_DBUG_PRINT("find_key_block: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -1360,7 +1385,9 @@ restart: /* This is a request for a page to be removed from cache */ KEYCACHE_DBUG_PRINT("find_key_block", - ("request for old page in block %u",BLOCK_NUMBER(block))); + ("request for old page in block %u " + "wrmode: %d block->status: %d", + BLOCK_NUMBER(block), wrmode, block->status)); /* Only reading requests can proceed until the old dirty page is flushed, all others are to be suspended, then resubmitted @@ -1379,6 +1406,8 @@ restart: /* Wait until the request can be resubmitted */ do { + KEYCACHE_DBUG_PRINT("find_key_block: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -1448,6 +1477,8 @@ restart: link_into_queue(&keycache->waiting_for_block, thread); do { + KEYCACHE_DBUG_PRINT("find_key_block: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -1528,9 +1559,13 @@ restart: else { /* This is for secondary requests for a new page only */ - page_status= block->hash_link == hash_link && - (block->status & BLOCK_READ) ? - PAGE_READ : PAGE_WAIT_TO_BE_READ; + KEYCACHE_DBUG_PRINT("find_key_block", + ("block->hash_link: %p hash_link: %p " + "block->status: %u", block->hash_link, + hash_link, block->status )); + page_status= (((block->hash_link == hash_link) && + (block->status & BLOCK_READ)) ? + PAGE_READ : PAGE_WAIT_TO_BE_READ); } } keycache->global_cache_read++; @@ -1538,17 +1573,22 @@ restart: else { reg_requests(keycache, block, 1); - page_status = block->hash_link == hash_link && - (block->status & BLOCK_READ) ? - PAGE_READ : PAGE_WAIT_TO_BE_READ; + KEYCACHE_DBUG_PRINT("find_key_block", + ("block->hash_link: %p hash_link: %p " + "block->status: %u", block->hash_link, + hash_link, block->status )); + page_status= (((block->hash_link == hash_link) && + (block->status & BLOCK_READ)) ? + PAGE_READ : PAGE_WAIT_TO_BE_READ); } } KEYCACHE_DBUG_ASSERT(page_status != -1); *page_st=page_status; KEYCACHE_DBUG_PRINT("find_key_block", - ("fd: %u pos %lu page_status %lu", - (uint) file,(ulong) filepos,(uint) page_status)); + ("fd: %u pos %lu block->status %u page_status %lu", + (uint) file, (ulong) filepos, block->status, + (uint) page_status)); #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) DBUG_EXECUTE("check_keycache2", @@ -1604,6 +1644,10 @@ static void read_block(KEY_CACHE *keycache, /* Page is not in buffer yet, is to be read from disk */ keycache_pthread_mutex_unlock(&keycache->cache_lock); + /* + Here other threads may step in and register as secondary readers. + They will register in block->wqueue[COND_FOR_REQUESTED]. + */ got_length= my_pread(block->hash_link->file, block->buffer, read_length, block->hash_link->diskpos, MYF(0)); keycache_pthread_mutex_lock(&keycache->cache_lock); @@ -1634,6 +1678,8 @@ static void read_block(KEY_CACHE *keycache, add_to_queue(&block->wqueue[COND_FOR_REQUESTED], thread); do { + KEYCACHE_DBUG_PRINT("read_block: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -1855,6 +1901,10 @@ int key_cache_insert(KEY_CACHE *keycache, /* The requested page is to be read into the block buffer */ #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_unlock(&keycache->cache_lock); + /* + Here other threads may step in and register as secondary readers. + They will register in block->wqueue[COND_FOR_REQUESTED]. + */ #endif /* Copy data from buff */ @@ -1865,9 +1915,15 @@ int key_cache_insert(KEY_CACHE *keycache, #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_lock(&keycache->cache_lock); + /* Here we are alone again. */ #endif block->status= BLOCK_READ; block->length= read_length+offset; + KEYCACHE_DBUG_PRINT("key_cache_insert", + ("primary request: new page in cache")); + /* Signal that all pending requests for this now can be processed. */ + if (block->wqueue[COND_FOR_REQUESTED].last_thread) + release_queue(&block->wqueue[COND_FOR_REQUESTED]); } remove_reader(block); @@ -2074,9 +2130,16 @@ static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block) { KEYCACHE_THREAD_TRACE("free block"); KEYCACHE_DBUG_PRINT("free_block", - ("block %u to be freed",BLOCK_NUMBER(block))); + ("block %u to be freed, hash_link %p", + BLOCK_NUMBER(block), block->hash_link)); if (block->hash_link) { + /* + While waiting for readers to finish, new readers might request the + block. But since we set block->status|= BLOCK_REASSIGNED, they + will wait on block->wqueue[COND_FOR_SAVED]. They must be signalled + later. + */ block->status|= BLOCK_REASSIGNED; wait_for_readers(keycache, block); unlink_hash(keycache, block->hash_link); @@ -2102,6 +2165,10 @@ static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block) keycache->free_block_list= block; /* Keep track of the number of currently unused blocks. */ keycache->blocks_unused++; + + /* All pending requests for this page must be resubmitted. */ + if (block->wqueue[COND_FOR_SAVED].last_thread) + release_queue(&block->wqueue[COND_FOR_SAVED]); } @@ -2334,6 +2401,8 @@ restart: add_to_queue(&block->wqueue[COND_FOR_SAVED], thread); do { + KEYCACHE_DBUG_PRINT("flush_key_blocks_int: wait", + ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -2685,14 +2754,6 @@ static int keycache_pthread_cond_signal(pthread_cond_t *cond) } -static int keycache_pthread_cond_broadcast(pthread_cond_t *cond) -{ - int rc; - KEYCACHE_THREAD_TRACE("signal"); - rc= pthread_cond_broadcast(cond); - return rc; -} - #if defined(KEYCACHE_DEBUG_LOG) From 04ed9f0204c1d21d4ebac0ad612f9b5aaf27effa Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Jun 2005 18:33:16 +0200 Subject: [PATCH 07/29] more than 64 indexes per table. bugfixes. bug#10995 --- sql/sql_bitmap.h | 23 +++++++++++------------ sql/sql_select.cc | 1 + tests/mysql_client_test.c | 16 ++++++++++------ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h index 2fd603d9381..958268fc314 100644 --- a/sql/sql_bitmap.h +++ b/sql/sql_bitmap.h @@ -28,7 +28,7 @@ template class Bitmap uchar buffer[(default_width+7)/8]; public: Bitmap() { init(); } - Bitmap(Bitmap& from) { *this=from; } + Bitmap(const Bitmap& from) { *this=from; } explicit Bitmap(uint prefix_to_set) { init(prefix_to_set); } void init() { bitmap_init(&map, buffer, default_width, 0); } void init(uint prefix_to_set) { init(); set_prefix(prefix_to_set); } @@ -61,18 +61,17 @@ public: my_bool operator==(const Bitmap& map2) const { return bitmap_cmp(&map, &map2.map); } char *print(char *buf) const { - char *s=buf; int i; - for (i=sizeof(buffer)-1; i>=0 ; i--) + char *s=buf; + const uchar *e=buffer, *b=e+sizeof(buffer)-1; + while (!*b && b>e) + b--; + if ((*s=_dig_vec_upper[*b >> 4]) != '0') + s++; + *s++=_dig_vec_upper[*b & 15]; + while (--b>=e) { - if ((*s=_dig_vec_upper[buffer[i] >> 4]) != '0') - break; - if ((*s=_dig_vec_upper[buffer[i] & 15]) != '0') - break; - } - for (s++, i-- ; i>=0 ; i--) - { - *s++=_dig_vec_upper[buffer[i] >> 4]; - *s++=_dig_vec_upper[buffer[i] & 15]; + *s++=_dig_vec_upper[*b >> 4]; + *s++=_dig_vec_upper[*b & 15]; } *s=0; return buf; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e23d32cca84..4d8145d8df2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5792,6 +5792,7 @@ make_join_readinfo(JOIN *join, uint options) if (!table->no_keyread) { if (tab->select && tab->select->quick && + tab->select->quick->index != MAX_KEY && //not index_merge table->used_keys.is_set(tab->select->quick->index)) { table->key_read=1; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9a8ee44c54c..002076afd90 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -7455,12 +7455,16 @@ static void test_explain_bug() verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_LEN, 0); - verify_prepare_field(result, 6, "key_len", "", - (mysql_get_server_version(mysql) <= 50000 ? - MYSQL_TYPE_LONGLONG : MYSQL_TYPE_VAR_STRING), - "", "", "", - (mysql_get_server_version(mysql) <= 50000 ? 3 : 4096), - 0); + if (mysql_get_server_version(mysql) <= 50000) + { + verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_LONGLONG, "", + "", "", 3, 0); + } + else + { + verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "", + "", "", NAME_LEN*MAX_KEY, 0); + } verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_LEN*16, 0); From 17678a7b885beb59fa808b7ace5cee4a0e21667d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 16:17:44 +0500 Subject: [PATCH 08/29] item_func.cc: set_var.cc: variables.result variables.test Bug #10904 Illegal mix of collations between a system variable and a constant Changing coercibility of system variables to SYSCONST, to be the same with USER(), DATABASE(), etc. sql/item_func.cc: Bug #10904 Illegal mix of collations between a system variable and a constant Changing coercibility of system variables to SYSCONST To be the same with USER(), DATABASE(), etc. --- mysql-test/r/variables.result | 6 ++++++ mysql-test/t/variables.test | 7 +++++++ sql/item_func.cc | 2 +- sql/set_var.cc | 3 ++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 6d4f9055e4e..602750d5033 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -210,6 +210,12 @@ query_prealloc_size 8192 range_alloc_block_size 2048 transaction_alloc_block_size 8192 transaction_prealloc_size 4096 +SELECT @@version LIKE 'non-existent'; +@@version LIKE 'non-existent' +0 +SELECT @@version_compile_os LIKE 'non-existent'; +@@version_compile_os LIKE 'non-existent' +0 set big_tables=OFFF; ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF' set big_tables="OFFF"; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 50bcc1c038c..e45218a9ed7 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -115,6 +115,13 @@ set @@query_alloc_block_size=default, @@query_prealloc_size=default; set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; show variables like '%alloc%'; +# +# Bug #10904 Illegal mix of collations between +# a system variable and a constant +# +SELECT @@version LIKE 'non-existent'; +SELECT @@version_compile_os LIKE 'non-existent'; + # The following should give errors --error 1231 diff --git a/sql/item_func.cc b/sql/item_func.cc index 598439c60c1..ad8479c7b0b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3369,7 +3369,7 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name, !my_strcasecmp(system_charset_info, name.str, "VERSION")) return new Item_string("@@VERSION", server_version, (uint) strlen(server_version), - system_charset_info); + system_charset_info, DERIVATION_SYSCONST); Item *item; sys_var *var; diff --git a/sql/set_var.cc b/sql/set_var.cc index b006dde2b4b..5564ba096ac 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1606,7 +1606,8 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) Item_string *tmp; pthread_mutex_lock(&LOCK_global_system_variables); char *str= (char*) value_ptr(thd, var_type, base); - tmp= new Item_string(str, strlen(str), system_charset_info); + tmp= new Item_string(str, strlen(str), + system_charset_info, DERIVATION_SYSCONST); pthread_mutex_unlock(&LOCK_global_system_variables); return tmp; } From b8c37b95025acf0d028dff6a1d22dc9b2d7530cc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 14:46:58 +0200 Subject: [PATCH 09/29] Removed bug introduced when implementing support for IN and BETWEEN --- mysql-test/r/ndb_condition_pushdown.result | 2 +- sql/ha_ndbcluster.cc | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result index 2465c4272cb..14cd4666528 100644 --- a/mysql-test/r/ndb_condition_pushdown.result +++ b/mysql-test/r/ndb_condition_pushdown.result @@ -1760,7 +1760,7 @@ 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 with pushed condition; Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where; 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 diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 0b6a8e34e93..65e16dcb539 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -6476,7 +6476,6 @@ void ndb_serialize_cond(const Item *item, void *arg) 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): { @@ -6493,7 +6492,6 @@ void ndb_serialize_cond(const Item *item, void *arg) 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::LT_FUNC): { @@ -6510,7 +6508,6 @@ void ndb_serialize_cond(const Item *item, void *arg) 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): { @@ -6527,7 +6524,6 @@ void ndb_serialize_cond(const Item *item, void *arg) 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): { @@ -6544,7 +6540,6 @@ void ndb_serialize_cond(const Item *item, void *arg) 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): { @@ -6561,7 +6556,6 @@ void ndb_serialize_cond(const Item *item, void *arg) 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): { From 2d008198d29509c69677c44985af8b086ac063fe Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 14:48:19 +0200 Subject: [PATCH 10/29] Modified handling of guarded predicates at condition pushdown to storage engine, to make valgrind happy --- sql/sql_select.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7bd2d6f4fd2..d0038561d5e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5454,6 +5454,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) */ if (cond) { + COND *unguarded= tmp; /* Because of QUICK_GROUP_MIN_MAX_SELECT there may be a select without a cond, so neutralize the hack above. @@ -5463,11 +5464,12 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) 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) + tab->table->file->pushed_cond= NULL; + if (thd->variables.engine_condition_pushdown && + unguarded == tmp) { COND *push_cond= - make_cond_for_table(tmp,current_map,current_map); - tab->table->file->pushed_cond= NULL; + make_cond_for_table(cond, current_map, current_map); if (push_cond) { /* Push condition to handler */ From c8e797b5b6d921803746d82b81c5e9e35d7c03a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 17:00:07 +0400 Subject: [PATCH 11/29] Fix bug #9669 Ordering on IF function with FROM_UNIXTIME function fails Integer overflow results in wrong field sortlength. sql/item_cmpfunc.cc: Fix bug #9669 Ordering on IF function with FROM_UNIXTIME function fails. mysql-test/t/func_if.test: Test for bug #9669 Ordering on IF function with FROM_UNIXTIME function fails. mysql-test/r/func_if.result: Test for bug #9669 Ordering on IF function with FROM_UNIXTIME function fails. --- mysql-test/r/func_if.result | 17 +++++++++++++++++ mysql-test/t/func_if.test | 14 ++++++++++++++ sql/item_cmpfunc.cc | 9 ++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index 4db31121756..3e72fb45a14 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -91,3 +91,20 @@ drop table t1; SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL; NULLIF(5,5) IS NULL NULLIF(5,5) IS NOT NULL 1 0 +CREATE TABLE `t1` ( +`id` int(11) NOT NULL , +`date` int(10) default NULL, +`text` varchar(32) NOT NULL +); +INSERT INTO t1 VALUES (1,1110000000,'Day 1'),(2,1111000000,'Day 2'),(3,1112000000,'Day 3'); +SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord ASC; +id date_ord text +1 05-03-2005 Day 1 +2 16-03-2005 Day 2 +3 28-03-2005 Day 3 +SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord DESC; +id date_ord text +3 28-03-2005 Day 3 +2 16-03-2005 Day 2 +1 05-03-2005 Day 1 +DROP TABLE t1; diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index a2ea26390ca..37556984f68 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -61,3 +61,17 @@ drop table t1; # Bug #5595 NULLIF() IS NULL returns false if NULLIF() returns NULL # SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL; + +# +# Bug #9669 Ordering on IF function with FROM_UNIXTIME function fails +# +CREATE TABLE `t1` ( + `id` int(11) NOT NULL , + `date` int(10) default NULL, + `text` varchar(32) NOT NULL +); +INSERT INTO t1 VALUES (1,1110000000,'Day 1'),(2,1111000000,'Day 2'),(3,1112000000,'Day 3'); +SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord ASC; +SELECT id, IF(date IS NULL, '-', FROM_UNIXTIME(date, '%d-%m-%Y')) AS date_ord, text FROM t1 ORDER BY date_ord DESC; +DROP TABLE t1; + diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a7abb5f9be8..eb0dddd3e28 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1227,9 +1227,16 @@ Item_func_if::fix_length_and_dec() { maybe_null=args[1]->maybe_null || args[2]->maybe_null; decimals= max(args[1]->decimals, args[2]->decimals); - max_length= (max(args[1]->max_length - args[1]->decimals, + if (decimals == NOT_FIXED_DEC) + { + max_length= max(args[1]->max_length, args[2]->max_length); + } + else + { + max_length= (max(args[1]->max_length - args[1]->decimals, args[2]->max_length - args[2]->decimals) + decimals); + } enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg2_type=args[2]->result_type(); bool null1=args[1]->const_item() && args[1]->null_value; From 1dd50e466d7ad4c2cb39be6393840abf5cbb9fbf Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 15:32:02 +0200 Subject: [PATCH 12/29] misc. fixes for windoze builds VC++Files/client/mysql.dsp: added missing mysys.lib VC++Files/client/mysqladmin.dsp: added missing mysys.lib VC++Files/client/mysqlimport.dsp: added missing mysys.lib VC++Files/client/mysqlshow.dsp: added missing mysys.lib VC++Files/libmysql/libmysql.dsp: added missing mysys.lib VC++Files/mysql.dsw: added dependencies on mysys include/config-win.h: added missing constant sql/sql_base.cc: pulled declaration of table_list out of for-scope --- VC++Files/client/mysql.dsp | 8 ++++---- VC++Files/client/mysqladmin.dsp | 6 +++--- VC++Files/client/mysqlimport.dsp | 8 ++++---- VC++Files/client/mysqlshow.dsp | 8 ++++---- VC++Files/libmysql/libmysql.dsp | 4 ++-- VC++Files/mysql.dsw | 12 ++++++++++++ include/config-win.h | 1 + sql/sql_base.cc | 5 +++-- 8 files changed, 33 insertions(+), 19 deletions(-) diff --git a/VC++Files/client/mysql.dsp b/VC++Files/client/mysql.dsp index 8298e62d8ad..e9e79a49d0a 100644 --- a/VC++Files/client/mysql.dsp +++ b/VC++Files/client/mysql.dsp @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\" # SUBTRACT LINK32 /incremental:yes !ELSEIF "$(CFG)" == "mysql - Win32 Debug" @@ -78,7 +78,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysql.exe" /pdbtype:sept /libpath:"..\lib_debug\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysql.exe" /pdbtype:sept /libpath:"..\lib_debug\\" !ELSEIF "$(CFG)" == "mysql - Win32 classic" @@ -104,9 +104,9 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=xilink6.exe -# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\" +# ADD BASE LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_release/mysql.exe" /libpath:"..\lib_release\\" # SUBTRACT BASE LINK32 /incremental:yes -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_classic/mysql.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client_classic/mysql.exe" /libpath:"..\lib_release\\" # SUBTRACT LINK32 /incremental:yes !ENDIF diff --git a/VC++Files/client/mysqladmin.dsp b/VC++Files/client/mysqladmin.dsp index b473d104a76..d713325b4e7 100644 --- a/VC++Files/client/mysqladmin.dsp +++ b/VC++Files/client/mysqladmin.dsp @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\" !ELSEIF "$(CFG)" == "mysqladmin - Win32 Debug" @@ -77,7 +77,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqladmin.exe" /pdbtype:sept /libpath:"..\lib_debug\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqladmin.exe" /pdbtype:sept /libpath:"..\lib_debug\\" !ELSEIF "$(CFG)" == "mysqladmin - Win32 classic" @@ -104,7 +104,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqladmin.exe" /libpath:"..\lib_release\\" -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqladmin.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqladmin.exe" /libpath:"..\lib_release\\" !ENDIF diff --git a/VC++Files/client/mysqlimport.dsp b/VC++Files/client/mysqlimport.dsp index 1a9b64a0383..1b650dab731 100644 --- a/VC++Files/client/mysqlimport.dsp +++ b/VC++Files/client/mysqlimport.dsp @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\" # SUBTRACT LINK32 /incremental:yes !ELSEIF "$(CFG)" == "mysqlimport - Win32 Debug" @@ -78,7 +78,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlimport.exe" /pdbtype:sept /libpath:"..\lib_debug\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib setargv.obj /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlimport.exe" /pdbtype:sept /libpath:"..\lib_debug\\" !ELSEIF "$(CFG)" == "mysqlimport - Win32 classic" @@ -104,9 +104,9 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=xilink6.exe -# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\" +# ADD BASE LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlimport.exe" /libpath:"..\lib_release\\" # SUBTRACT BASE LINK32 /incremental:yes -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlimport.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlimport.exe" /libpath:"..\lib_release\\" # SUBTRACT LINK32 /incremental:yes !ENDIF diff --git a/VC++Files/client/mysqlshow.dsp b/VC++Files/client/mysqlshow.dsp index 855c2dcdf34..f9377763c49 100644 --- a/VC++Files/client/mysqlshow.dsp +++ b/VC++Files/client/mysqlshow.dsp @@ -52,7 +52,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\" !ELSEIF "$(CFG)" == "mysqlshow - Win32 Debug" @@ -77,7 +77,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlshow.exe" /pdbtype:sept /libpath:"..\lib_debug\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqlshow.exe" /pdbtype:sept /libpath:"..\lib_debug\\" !ELSEIF "$(CFG)" == "mysqlshow - Win32 classic" @@ -103,8 +103,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=xilink6.exe -# ADD BASE LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\" -# ADD LINK32 mysqlclient.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlshow.exe" /libpath:"..\lib_release\\" +# ADD BASE LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../client_release/mysqlshow.exe" /libpath:"..\lib_release\\" +# ADD LINK32 mysqlclient.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib /nologo /subsystem:console /machine:I386 /out:"../client_classic/mysqlshow.exe" /libpath:"..\lib_release\\" !ENDIF diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp index 473aa60d8af..4f93ac93c40 100644 --- a/VC++Files/libmysql/libmysql.dsp +++ b/VC++Files/libmysql/libmysql.dsp @@ -54,7 +54,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 -# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release" +# ADD LINK32 mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release" # SUBTRACT LINK32 /pdb:none # Begin Special Build Tool SOURCE="$(InputPath)" @@ -87,7 +87,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 zlib.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug" +# ADD LINK32 zlib.lib mysys.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug" # SUBTRACT LINK32 /pdb:none # Begin Special Build Tool SOURCE="$(InputPath)" diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw index 25bcab8338b..6ebda999c35 100644 --- a/VC++Files/mysql.dsw +++ b/VC++Files/mysql.dsw @@ -80,6 +80,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name zlib End Project Dependency + Begin Project Dependency + Project_Dep_Name mysys + End Project Dependency }}} ############################################################################### @@ -320,6 +323,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name zlib End Project Dependency + Begin Project Dependency + Project_Dep_Name mysys + End Project Dependency }}} ############################################################################### @@ -476,6 +482,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name mysqlclient End Project Dependency + Begin Project Dependency + Project_Dep_Name mysys + End Project Dependency }}} ############################################################################### @@ -533,6 +542,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name mysqlclient End Project Dependency + Begin Project Dependency + Project_Dep_Name mysys + End Project Dependency }}} ############################################################################### diff --git a/include/config-win.h b/include/config-win.h index bc14d3d3e53..b17e4df4e26 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -76,6 +76,7 @@ functions */ #define F_EXCLUSIVE 1 /* We have only exclusive locking */ #define F_TO_EOF (INT_MAX32/2) /* size for lock of all file */ #define F_OK 0 /* parameter to access() */ +#define W_OK 2 #define S_IROTH S_IREAD /* for my_lib */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5719f77e3ef..036a838b6fc 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3222,7 +3222,8 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, if (!(*leaves)) make_leaves_list(leaves, tables); - for (TABLE_LIST *table_list= *leaves; + TABLE_LIST *table_list; + for (table_list= *leaves; table_list; table_list= table_list->next_leaf, tablenr++) { @@ -3261,7 +3262,7 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES); DBUG_RETURN(1); } - for (TABLE_LIST *table_list= tables; + for (table_list= tables; table_list; table_list= table_list->next_local) { From 1ea49fecddde8e2d81438ee8d0eefff1a5fd8527 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 15:45:20 +0200 Subject: [PATCH 13/29] cleanup extra/yassl/src/ssl.cpp: unresolved __cxa_pure_virtual sql/item_func.cc: don't call arg[0]->val_xxx() twice --- extra/yassl/src/ssl.cpp | 2 +- sql/item_func.cc | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 466884f3cd9..84ffb9b5829 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -36,7 +36,7 @@ #include "handshake.hpp" #include "yassl_int.hpp" #include - +#include "runtime.hpp" namespace yaSSL { diff --git a/sql/item_func.cc b/sql/item_func.cc index 3767844e200..6e630fd389b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2325,9 +2325,6 @@ longlong Item_func_field::val_int() { DBUG_ASSERT(fixed == 1); - if (args[0]->is_null()) - return 0; - if (cmp_type == STRING_RESULT) { String *field; @@ -2343,6 +2340,8 @@ longlong Item_func_field::val_int() else if (cmp_type == INT_RESULT) { longlong val= args[0]->val_int(); + if (args[0]->null_value) + return 0; for (uint i=1; i < arg_count ; i++) { if (!args[i]->is_null() && val == args[i]->val_int()) @@ -2353,6 +2352,8 @@ longlong Item_func_field::val_int() { my_decimal dec_arg_buf, *dec_arg, dec_buf, *dec= args[0]->val_decimal(&dec_buf); + if (args[0]->null_value) + return 0; for (uint i=1; i < arg_count; i++) { dec_arg= args[i]->val_decimal(&dec_arg_buf); @@ -2363,6 +2364,8 @@ longlong Item_func_field::val_int() else { double val= args[0]->val_real(); + if (args[0]->null_value) + return 0; for (uint i=1; i < arg_count ; i++) { if (!args[i]->is_null() && val == args[i]->val_real()) From 21989e7d4e281b67f060d61fdd0dd4fa2b4eba54 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 07:27:02 -0700 Subject: [PATCH 14/29] item_func.h: Fixed bug #9939: a wrong conversion of arguments for functions COALESCE and IFNULL. The str_op virtual method was added into Item_func_numhybrid. item_func.cc: Fixed bug #9939: a wrong conversion of arguments for functions COALESCE and IFNULL. The str_op virtual method was added into Item_func_numhybrid. item_cmpfunc.h, item_cmpfunc.cc: Fixed bug #9939: a wrong conversion of arguments for functions COALESCE and IFNULL. Item_func_coalesce and Item_func_ifnull now inherit from a modified Item_func_numhybrid. case.test, case.result: Added test cases for bug #9939. mysql-test/r/case.result: Added test cases for bug #9939. mysql-test/t/case.test: Added test cases for bug #9939. sql/item_cmpfunc.cc: Fixed bug #9939: a wrong conversion of arguments for functions COALESCE and IFNULL. Item_func_coalesce and Item_func_ifnull now inherit from a modified Item_func_numhybrid. sql/item_cmpfunc.h: Fixed bug #9939: a wrong conversion of arguments for functions COALESCE and IFNULL. Item_func_coalesce and Item_func_ifnull now inherit from a modified Item_func_numhybrid. sql/item_func.cc: Fixed bug #9939: a wrong conversion of arguments for functions COALESCE and IFNULL. The str_op virtual method was added into Item_func_numhybrid. sql/item_func.h: Fixed bug #9939: a wrong conversion of arguments for functions COALESCE and IFNULL. he str_op virtual method was added into Item_func_numhybrid. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + mysql-test/r/case.result | 17 +++++++++++++++++ mysql-test/t/case.test | 19 +++++++++++++++++++ sql/item_cmpfunc.cc | 24 ++++++++++++------------ sql/item_cmpfunc.h | 30 +++++++++++++----------------- sql/item_func.cc | 25 +++++++++++++++++++++++++ sql/item_func.h | 6 ++++++ 7 files changed, 93 insertions(+), 29 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 3230f3c119f..5b842d47fdc 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -87,6 +87,7 @@ hf@deer.mysql.r18.ru hf@genie.(none) holyfoot@mysql.com igor@hundin.mysql.fi +igor@igor-inspiron.creware.com igor@linux.local igor@rurik.mysql.com ingo@mysql.com diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index 5fb21004469..a854cf4c7b0 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -160,3 +160,20 @@ t1 CREATE TABLE `t1` ( `COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; +CREATE TABLE t1 (EMPNUM INT); +INSERT INTO t1 VALUES (0), (2); +CREATE TABLE t2 (EMPNUM DECIMAL (4, 2)); +INSERT INTO t2 VALUES (0.0), (9.0); +SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, +t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2 +FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; +CEMPNUM EMPMUM1 EMPNUM2 +0.00 0 0.00 +2.00 2 NULL +SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, +t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2 +FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; +CEMPNUM EMPMUM1 EMPNUM2 +0.00 0 0.00 +2.00 2 NULL +DROP TABLE t1,t2; diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index fed3ff07a13..f2cfce9085d 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -110,3 +110,22 @@ explain extended SELECT COALESCE('a' COLLATE latin1_bin,'b'); SHOW CREATE TABLE t1; DROP TABLE t1; + +# +# Tests for bug #9939: conversion of the arguments for COALESCE and IFNULL +# + +CREATE TABLE t1 (EMPNUM INT); +INSERT INTO t1 VALUES (0), (2); +CREATE TABLE t2 (EMPNUM DECIMAL (4, 2)); +INSERT INTO t2 VALUES (0.0), (9.0); + +SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, + t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2 + FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; + +SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, + t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2 + FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; + +DROP TABLE t1,t2; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 66f0bf9c395..d64f1df78ab 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1114,8 +1114,8 @@ Item_func_ifnull::fix_length_and_dec() max_length= (max(args[0]->max_length - args[0]->decimals, args[1]->max_length - args[1]->decimals) + decimals); - agg_result_type(&cached_result_type, args, 2); - switch (cached_result_type) { + agg_result_type(&hybrid_type, args, 2); + switch (hybrid_type) { case STRING_RESULT: agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); break; @@ -1153,7 +1153,7 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table) } double -Item_func_ifnull::val_real() +Item_func_ifnull::real_op() { DBUG_ASSERT(fixed == 1); double value= args[0]->val_real(); @@ -1169,7 +1169,7 @@ Item_func_ifnull::val_real() } longlong -Item_func_ifnull::val_int() +Item_func_ifnull::int_op() { DBUG_ASSERT(fixed == 1); longlong value=args[0]->val_int(); @@ -1185,7 +1185,7 @@ Item_func_ifnull::val_int() } -my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) +my_decimal *Item_func_ifnull::decimal_op(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); my_decimal *value= args[0]->val_decimal(decimal_value); @@ -1202,7 +1202,7 @@ my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) String * -Item_func_ifnull::val_str(String *str) +Item_func_ifnull::str_op(String *str) { DBUG_ASSERT(fixed == 1); String *res =args[0]->val_str(str); @@ -1676,7 +1676,7 @@ void Item_func_case::print(String *str) Coalesce - return first not NULL argument. */ -String *Item_func_coalesce::val_str(String *str) +String *Item_func_coalesce::str_op(String *str) { DBUG_ASSERT(fixed == 1); null_value=0; @@ -1690,7 +1690,7 @@ String *Item_func_coalesce::val_str(String *str) return 0; } -longlong Item_func_coalesce::val_int() +longlong Item_func_coalesce::int_op() { DBUG_ASSERT(fixed == 1); null_value=0; @@ -1704,7 +1704,7 @@ longlong Item_func_coalesce::val_int() return 0; } -double Item_func_coalesce::val_real() +double Item_func_coalesce::real_op() { DBUG_ASSERT(fixed == 1); null_value=0; @@ -1719,7 +1719,7 @@ double Item_func_coalesce::val_real() } -my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) +my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); null_value= 0; @@ -1736,8 +1736,8 @@ my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) void Item_func_coalesce::fix_length_and_dec() { - agg_result_type(&cached_result_type, args, arg_count); - switch (cached_result_type) { + agg_result_type(&hybrid_type, args, arg_count); + switch (hybrid_type) { case STRING_RESULT: count_only_length(); decimals= NOT_FIXED_DEC; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a929d509723..7a22e76b217 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -453,23 +453,19 @@ public: }; -class Item_func_coalesce :public Item_func +class Item_func_coalesce :public Item_func_numhybrid { protected: - enum Item_result cached_result_type; - Item_func_coalesce(Item *a, Item *b) - :Item_func(a, b), cached_result_type(INT_RESULT) - {} + Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {} public: - Item_func_coalesce(List &list) - :Item_func(list),cached_result_type(INT_RESULT) - {} - double val_real(); - longlong val_int(); - String *val_str(String *); - my_decimal *val_decimal(my_decimal *); + Item_func_coalesce(List &list) :Item_func_numhybrid(list) {} + double real_op(); + longlong int_op(); + String *str_op(String *); + my_decimal *decimal_op(my_decimal *); void fix_length_and_dec(); - enum Item_result result_type () const { return cached_result_type; } + void find_num_type() {} + enum Item_result result_type () const { return hybrid_type; } const char *func_name() const { return "coalesce"; } table_map not_null_tables() const { return 0; } }; @@ -482,10 +478,10 @@ protected: bool field_type_defined; public: Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {} - double val_real(); - longlong val_int(); - String *val_str(String *str); - my_decimal *val_decimal(my_decimal *); + double real_op(); + longlong int_op(); + String *str_op(String *str); + my_decimal *decimal_op(my_decimal *); enum_field_types field_type() const; void fix_length_and_dec(); const char *func_name() const { return "ifnull"; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 47dffa679e9..21837dfbadb 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -815,6 +815,8 @@ String *Item_func_numhybrid::val_str(String *str) str->set(nr,decimals,&my_charset_bin); break; } + case STRING_RESULT: + return str_op(&str_value); default: DBUG_ASSERT(0); } @@ -839,6 +841,14 @@ double Item_func_numhybrid::val_real() return (double)int_op(); case REAL_RESULT: return real_op(); + case STRING_RESULT: + { + char *end_not_used; + int err_not_used; + String *res= str_op(&str_value); + return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(), + &end_not_used, &err_not_used) : 0.0); + } default: DBUG_ASSERT(0); } @@ -863,6 +873,15 @@ longlong Item_func_numhybrid::val_int() return int_op(); case REAL_RESULT: return (longlong)real_op(); + case STRING_RESULT: + { + char *end_not_used; + int err_not_used; + String *res= str_op(&str_value); + CHARSET_INFO *cs= str_value.charset(); + return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end_not_used, + &err_not_used) : 0); + } default: DBUG_ASSERT(0); } @@ -891,6 +910,12 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value) break; } case STRING_RESULT: + { + String *res= str_op(&str_value); + str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(), + res->length(), res->charset(), decimal_value); + break; + } case ROW_RESULT: default: DBUG_ASSERT(0); diff --git a/sql/item_func.h b/sql/item_func.h index b53f2a0b9c6..797aec952f9 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -194,6 +194,9 @@ public: Item_func_numhybrid(Item *a,Item *b) :Item_func(a,b),hybrid_type(REAL_RESULT) {} + Item_func_numhybrid(List &list) + :Item_func(list),hybrid_type(REAL_RESULT) + {} enum Item_result result_type () const { return hybrid_type; } void fix_length_and_dec(); @@ -208,6 +211,7 @@ public: virtual longlong int_op()= 0; virtual double real_op()= 0; virtual my_decimal *decimal_op(my_decimal *)= 0; + virtual String *str_op(String *)= 0; bool is_null() { (void) val_real(); return null_value; } }; @@ -220,6 +224,7 @@ public: void fix_num_length_and_dec(); void find_num_type(); + String *str_op(String *str) { DBUG_ASSERT(0); return 0; } }; @@ -231,6 +236,7 @@ class Item_num_op :public Item_func_numhybrid virtual void result_precision()= 0; void print(String *str) { print_op(str); } void find_num_type(); + String *str_op(String *str) { DBUG_ASSERT(0); return 0; } }; From 78a9e47e467313231e59c1cc3f8c6f3aca371659 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 16:56:08 +0200 Subject: [PATCH 15/29] Added update_used_tables to add_found_match_trig_cond, to make valgrind happy --- sql/sql_select.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d0038561d5e..811fdc69ba7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5233,7 +5233,10 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) tmp= new Item_func_trig_cond(tmp, &tab->found); } if (tmp) + { tmp->quick_fix_field(); + tmp->update_used_tables(); + } return tmp; } @@ -5454,7 +5457,6 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) */ if (cond) { - COND *unguarded= tmp; /* Because of QUICK_GROUP_MIN_MAX_SELECT there may be a select without a cond, so neutralize the hack above. @@ -5465,11 +5467,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) /* Push condition to storage engine if this is enabled and the condition is not guarded */ tab->table->file->pushed_cond= NULL; - if (thd->variables.engine_condition_pushdown && - unguarded == tmp) + 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); if (push_cond) { /* Push condition to handler */ From e9799ba6fa687fd879e8d2fe84986103c6279b8a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 18:10:32 +0300 Subject: [PATCH 16/29] ha_innodb.cc: Weaken InnoDB table locking at the start of a stored procedure call: this will make multi-transaction stored procedures less deterministic for binlogging, but since they are non-deterministic anyway, it is not that bad; this fix will remove the huge amount of InnoDB tranasctional deadlocks caused by table locking at the start of a stored procedure sql/ha_innodb.cc: Weaken InnoDB table locking at the start of a stored procedure call: this will make multi-transaction stored procedures less deterministic for binlogging, but since they are non-deterministic anyway, it is not that bad; this fix will remove the huge amount of InnoDB tranasctional deadlocks caused by table locking at the start of a stored procedure --- sql/ha_innodb.cc | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 1703a405035..d956e692152 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5963,11 +5963,14 @@ ha_innobase::external_lock( TABLES if AUTOCOMMIT=1. It does not make much sense to acquire an InnoDB table lock if it is released immediately at the end of LOCK TABLES, and InnoDB's table locks in that case cause - VERY easily deadlocks. */ + VERY easily deadlocks. We do not set InnoDB table locks when + MySQL sets them at the start of a stored procedure call + (MySQL does have thd->in_lock_tables TRUE there). */ if (prebuilt->select_lock_type != LOCK_NONE) { if (thd->in_lock_tables && + thd->lex->sql_command != SQLCOM_CALL && thd->variables.innodb_table_locks && (thd->options & OPTION_NOT_AUTOCOMMIT)) { @@ -6478,11 +6481,21 @@ ha_innobase::store_lock( if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { + /* Starting from 5.0.7, we weaken also the table locks + set at the start of a MySQL stored procedure call, just like + we weaken the locks set at the start of an SQL statement. + MySQL does set thd->in_lock_tables TRUE there, but in reality + we do not need table locks to make the execution of a + single transaction stored procedure call deterministic + (if it does not use a consistent read). */ + /* If we are not doing a LOCK TABLE or DISCARD/IMPORT TABLESPACE or TRUNCATE TABLE, then allow multiple writers */ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && - lock_type <= TL_WRITE) && !thd->in_lock_tables + lock_type <= TL_WRITE) + && (!thd->in_lock_tables + || thd->lex->sql_command == SQLCOM_CALL) && !thd->tablespace_op && thd->lex->sql_command != SQLCOM_TRUNCATE && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { @@ -6496,7 +6509,10 @@ ha_innobase::store_lock( to t2. Convert the lock to a normal read lock to allow concurrent inserts to t2. */ - if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) { + if (lock_type == TL_READ_NO_INSERT + && (!thd->in_lock_tables + || thd->lex->sql_command == SQLCOM_CALL)) { + lock_type = TL_READ; } From dd3225b22bf8b478361ac795b9f067f4993fd384 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 11:12:58 -0500 Subject: [PATCH 17/29] fixed compile problem by replacing W_OK with F_OK BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + mysys/my_access.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index aad4399302e..ce1e179789e 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -206,6 +206,7 @@ rburnett@bk-internal.mysql.com rburnett@build.mysql.com reggie@bob.(none) reggie@mdk10.(none) +reggie@monster. root@home.(none) root@mc04.(none) root@x3.internalnet diff --git a/mysys/my_access.c b/mysys/my_access.c index 28210bdfc7d..89e90e16f18 100644 --- a/mysys/my_access.c +++ b/mysys/my_access.c @@ -44,7 +44,7 @@ int my_access(const char *path, int amode) result= GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo); if (! result || - (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & W_OK)) + (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & F_OK)) { my_errno= errno= EACCES; return -1; From 33b114aac25c787ca6a49a099c14af765c19a71b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 10:00:32 -0700 Subject: [PATCH 18/29] item_func.h: Identation correction for the fix of bug #9939. sql/item_func.h: Identation correction for the fix of bug #9939. --- sql/item_func.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/item_func.h b/sql/item_func.h index 797aec952f9..f0c7e25ad53 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -189,13 +189,13 @@ class Item_func_numhybrid: public Item_func protected: Item_result hybrid_type; public: - Item_func_numhybrid(Item *a) :Item_func(a),hybrid_type(REAL_RESULT) + Item_func_numhybrid(Item *a) :Item_func(a), hybrid_type(REAL_RESULT) {} Item_func_numhybrid(Item *a,Item *b) - :Item_func(a,b),hybrid_type(REAL_RESULT) + :Item_func(a,b), hybrid_type(REAL_RESULT) {} Item_func_numhybrid(List &list) - :Item_func(list),hybrid_type(REAL_RESULT) + :Item_func(list), hybrid_type(REAL_RESULT) {} enum Item_result result_type () const { return hybrid_type; } From 28a467c6faeac2e33637ce9bff9670987257a300 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 21:14:14 +0200 Subject: [PATCH 19/29] CommandInterpreter.cpp: Bug #11050 ndb_mgm "show" prints incorrectly after master data node fails ndb/src/mgmclient/CommandInterpreter.cpp: Bug #11050 ndb_mgm "show" prints incorrectly after master data node fails --- ndb/src/mgmclient/CommandInterpreter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index c3b0ee7fe97..34fe57d1fca 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -1176,7 +1176,8 @@ CommandInterpreter::executeShow(char* parameters) api_nodes++; break; case NDB_MGM_NODE_TYPE_NDB: - if (state->node_states[i].dynamic_id < master_id) + if (state->node_states[i].dynamic_id && + state->node_states[i].dynamic_id < master_id) master_id= state->node_states[i].dynamic_id; ndb_nodes++; break; From bdbace6666f82a12d00297fcb82802f2612899b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jun 2005 00:28:18 +0500 Subject: [PATCH 20/29] WL#2286 - Compile MySQL w/YASSL support Compilation errors fixes. config/ac-macros/yassl.m4: Switch to -l/-L instead of passing file name directly. (more portable for ".a" archives) extra/yassl/taocrypt/src/integer.cpp: Instantiate more templates (needed by some 64bit boxes). extra/yassl/taocrypt/src/template_instnt.cpp: Instantiate more templates (needed by some 64bit boxes). Move tcArrayDelete to TaoCrypt namespace (more portable). --- config/ac-macros/yassl.m4 | 4 ++-- extra/yassl/taocrypt/src/integer.cpp | 2 ++ extra/yassl/taocrypt/src/template_instnt.cpp | 14 ++++++++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index ada1a2c0bd1..ddacde51c2a 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -19,8 +19,8 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ AC_MSG_RESULT([using bundled yaSSL]) yassl_dir="extra/yassl" openssl_libs="\ - \$(top_builddir)/extra/yassl/src/libyassl.a\ - \$(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.a" + -L\$(top_builddir)/extra/yassl/src -lyassl\ + -L\$(top_builddir)/extra/yassl/taocrypt/src -ltaocrypt" openssl_includes="-I\$(top_srcdir)/extra/yassl/include" AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) else diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 67f3c963cac..3df1df9beab 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -3941,6 +3941,8 @@ Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, #ifdef __GNUC__ template unsigned int DivideThreeWordsByTwo(unsigned int*, unsigned int, unsigned int, DWord*); +template unsigned int DivideThreeWordsByTwo(unsigned int*, unsigned int, unsigned int, Word*); +template unsigned long long DivideThreeWordsByTwo(unsigned long long*, unsigned long long, unsigned long long, DWord*); #endif } // namespace diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 28dbdc5c739..5fed1ee5ae4 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -11,6 +11,7 @@ template AlignedAllocator::pointer StdReallocate::pointer StdReallocate >(AllocatorWithCleanup&, unsigned char*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, unsigned int*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); +template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, unsigned long long*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); template class RSA_Decryptor; template class RSA_Encryptor; template class RSA_Encryptor; @@ -18,14 +19,19 @@ template class RSA_Encryptor; namespace mySTL { template vector* uninit_fill_n*, unsigned int, vector >(vector*, unsigned int, vector const&); +template vector* uninit_fill_n*, unsigned long, vector >(vector*, unsigned long, vector const&); template void destroy*>(vector*, vector*); template TaoCrypt::Integer* uninit_copy(TaoCrypt::Integer*, TaoCrypt::Integer*, TaoCrypt::Integer*); template TaoCrypt::Integer* uninit_fill_n(TaoCrypt::Integer*, unsigned int, TaoCrypt::Integer const&); +template TaoCrypt::Integer* uninit_fill_n(TaoCrypt::Integer*, unsigned long, TaoCrypt::Integer const&); template void destroy(TaoCrypt::Integer*, TaoCrypt::Integer*); } -template void TaoCrypt::tcDelete(TaoCrypt::HASH*); -template void TaoCrypt::tcArrayDelete(unsigned*); -template void TaoCrypt::tcArrayDelete(unsigned char*); -template void TaoCrypt::tcArrayDelete(char*); +namespace TaoCrypt { +template void tcDelete(HASH*); +template void tcArrayDelete(unsigned*); +template void tcArrayDelete(unsigned long long*); +template void tcArrayDelete(unsigned char*); +template void tcArrayDelete(char*); +} #endif From 892032a2c2db6ecbe983578132f34ce8dc596048 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jun 2005 00:02:47 +0400 Subject: [PATCH 21/29] Give Item_arena::is_stmt_prepare a more descriptive name (it marks the code that is active for SP as well in 5.0) sql/item.cc: Rename of an Item_arena method. sql/item_subselect.cc: Rename of an Item_arena method. sql/sql_class.h: Rename of an Item_arena method. sql/sql_parse.cc: Rename of an Item_arena method. sql/sql_union.cc: Rename of an Item_arena method. --- sql/item.cc | 2 +- sql/item_subselect.cc | 2 +- sql/sql_class.h | 3 ++- sql/sql_parse.cc | 4 ++-- sql/sql_union.cc | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 0db9a56055f..a9c1ef7198e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1027,7 +1027,7 @@ Item_field::Item_field(THD *thd, Field *f) structure can go away and pop up again between subsequent executions of a prepared statement). */ - if (thd->current_arena->is_stmt_prepare()) + if (thd->current_arena->is_stmt_prepare_or_first_sp_execute()) { if (db_name) orig_db_name= thd->strdup(db_name); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index b7aefdd6f2e..4f1e5b9a290 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -362,7 +362,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) because we do not rollback this changes TODO: make rollback for it, or special name resolving mode in 5.0. */ - !arena->is_stmt_prepare() + !arena->is_stmt_prepare_or_first_sp_execute() ) { diff --git a/sql/sql_class.h b/sql/sql_class.h index 47987f3a0c6..7c8ead7558e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -695,7 +695,8 @@ public: virtual Type type() const; virtual ~Item_arena() {}; - inline bool is_stmt_prepare() const { return (int)state < (int)PREPARED; } + inline bool is_stmt_prepare_or_first_sp_execute() const + { return (int)state < (int)PREPARED; } inline bool is_first_stmt_execute() const { return state == PREPARED; } inline bool is_stmt_execute() const { return state == PREPARED || state == EXECUTED; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2af9191110c..a9e68de3705 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5894,7 +5894,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->db= empty_c_string; ptr->db_length= 0; } - if (thd->current_arena->is_stmt_prepare()) + if (thd->current_arena->is_stmt_prepare_or_first_sp_execute()) ptr->db= thd->strdup(ptr->db); ptr->alias= alias_str; @@ -6972,7 +6972,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, against the opened tables to ensure we don't use a table that is part of the view (which can only be done after the table has been opened). */ - if (thd->current_arena->is_stmt_prepare()) + if (thd->current_arena->is_stmt_prepare_or_first_sp_execute()) { /* For temporary tables we don't have to check if the created table exists diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 8d36889df76..56401ced67c 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -323,7 +323,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } if (tmp_arena) thd->restore_backup_item_arena(tmp_arena, &backup); - if (arena->is_stmt_prepare()) + if (arena->is_stmt_prepare_or_first_sp_execute()) { /* prepare fake select to initialize it correctly */ init_prepare_fake_select_lex(thd); From 4d81713cb8e81cb12a2f1de630b373a81a483e6d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Jun 2005 22:59:37 +0200 Subject: [PATCH 22/29] assemble libmysqld.a 5-10 times faster! --- libmysqld/Makefile.am | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 6fc919c904f..5f2425d77c8 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -86,29 +86,24 @@ INC_LIB= $(top_builddir)/regex/libregex.a \ # To make it easy for the end user to use the embedded library we # generate a total libmysqld.a from all library files, +# note - InnoDB libraries have circular dependencies, so in INC_LIB +# few libraries are present two times. Metrowerks linker doesn't like +# it at all. Traditional ar has no problems with it, but still there's no +# need to add the same file twice to the library, so 'sort -u' save us +# some time and spares unnecessary work. + libmysqld.a: libmysqld_int.a $(INC_LIB) if DARWIN_MWCC - mwld -lib -o $@ libmysqld_int.a `ls -1 $(INC_LIB) | sort -u` + mwld -lib -o $@ libmysqld_int.a `echo $(INC_LIB) | sort -u` else if test "$(host_os)" = "netware" ; \ then \ $(libmysqld_a_AR) libmysqld.a libmysqld_int.a $(INC_LIB) ; \ else \ - if test ! -d tmp ; then mkdir tmp ; fi ; \ - rm -f $@ libmysqld_int2.a tmp/*.o tmp/*.a ; \ - cp $(INC_LIB) tmp ; \ - cp libmysqld_int.a libmysqld_int2.a ; \ - cd tmp ; \ - for file in *.a ; do \ - bfile=`basename $$file .a` ; \ - $(AR) x $$file; \ - for obj in *.o ; do mv $$obj $${bfile}_$$obj ; done ; \ - $(AR) q ../libmysqld_int2.a *.o ; \ - rm -f *.o ; \ - done ; \ - cd .. ; \ - mv libmysqld_int2.a libmysqld.a ; \ - rm -f tmp/* ; \ + for arc in ./libmysqld_int.a $(INC_LIB); do \ + arpath=`echo $$arc|sed 's|[^/]*$$||'`; \ + $(AR) t $$arc|sed "s|^|$$arpath|"; \ + done | sort -u | xargs $(AR) cq libmysqld.a ; \ $(RANLIB) libmysqld.a ; \ fi endif From 52b70ceff707657a91787a6b67ce79ca015dcabf Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jun 2005 09:37:53 +0500 Subject: [PATCH 23/29] ctype_utf8.result, ctype_utf8.test: adding test field.cc: bug#10714 Inserting double value into utf8 column crashes server: sprintf was executed with too big length, which caused crash on some Windows platforms. sql/field.cc: bug#10714 Inserting double value into utf8 column crashes server sprintf was executed with too long length, which cau crashe on Windows. mysql-test/t/ctype_utf8.test: adding test mysql-test/r/ctype_utf8.result: adding test --- mysql-test/r/ctype_utf8.result | 3 +++ mysql-test/t/ctype_utf8.test | 7 +++++++ sql/field.cc | 15 ++++++++------- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index ffdb7cb0f3d..b7aa7c68b67 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -888,3 +888,6 @@ NULL select ifnull(NULL, _utf8'string'); ifnull(NULL, _utf8'string') string +create table t1 (a varchar(255)) default character set utf8; +insert into t1 values (1.0); +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 02024adb34e..bac6e60c302 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -724,3 +724,10 @@ select ifnull(a,'') from t1; drop table t1; select repeat(_utf8'+',3) as h union select NULL; select ifnull(NULL, _utf8'string'); + +# +# Bug#10714: Inserting double value into utf8 column crashes server +# +create table t1 (a varchar(255)) default character set utf8; +insert into t1 values (1.0); +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 60287d4003b..21c3fe12bb2 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4981,31 +4981,32 @@ int Field_str::store(double nr) char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; uint length; bool use_scientific_notation= TRUE; + uint char_length= field_length / charset()->mbmaxlen; /* Check fabs(nr) against longest value that can be stored in field, which depends on whether the value is < 1 or not, and negative or not */ double anr= fabs(nr); int neg= (nr < 0.0) ? 1 : 0; - if (field_length > 4 && field_length < 32 && - (anr < 1.0 ? anr > 1/(log_10[max(0,field_length-neg-2)]) /* -2 for "0." */ - : anr < log_10[field_length-neg]-1)) + if (char_length > 4 && char_length < 32 && + (anr < 1.0 ? anr > 1/(log_10[max(0,char_length-neg-2)]) /* -2 for "0." */ + : anr < log_10[char_length-neg]-1)) use_scientific_notation= FALSE; length= (uint) my_sprintf(buff, (buff, "%-.*g", (use_scientific_notation ? - max(0, (int)field_length-neg-5) : - field_length), + max(0, (int)char_length-neg-5) : + char_length), nr)); /* +1 below is because "precision" in %g above means the max. number of significant digits, not the output width. Thus the width can be larger than number of significant digits by 1 (for decimal point) - the test for field_length < 5 is for extreme cases, + the test for char_length < 5 is for extreme cases, like inserting 500.0 in char(1) */ - DBUG_ASSERT(field_length < 5 || length <= field_length+1); + DBUG_ASSERT(char_length < 5 || length <= char_length+1); return store((const char *) buff, length, charset()); } From 9979feb35c1a90ac61c09e2a170e59ba40efcaa6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jun 2005 10:30:58 +0200 Subject: [PATCH 24/29] bundle the check-cpu helper script with source packages. BUG#10696 --- BUILD/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am index 9f3c55c20d5..4e27ffd5e7f 100644 --- a/BUILD/Makefile.am +++ b/BUILD/Makefile.am @@ -19,6 +19,7 @@ EXTRA_DIST = FINISH.sh \ SETUP.sh \ + check-cpu \ compile-alpha \ compile-alpha-ccc \ compile-alpha-cxx \ From fcb3be9f633671b860a6daf21d54bd7fe10f287d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jun 2005 11:21:43 +0200 Subject: [PATCH 25/29] check-cpu fixes/improvements (Bug #11065) - support additional platforms (OpenBSD, Darwin) - make use of /proc/cpuinfo CPU flag information (needed to distinguish EMT64 Xeons from normal ones) - chose the right CPU related options depending on GCC version and target architecture - check if the chosen CPU type is actually supported by the GCC version , fallback to CPUs predecessor until test compile succeeds --- BUILD/check-cpu | 168 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 126 insertions(+), 42 deletions(-) diff --git a/BUILD/check-cpu b/BUILD/check-cpu index 0283c669fb2..3ceb9c269fe 100755 --- a/BUILD/check-cpu +++ b/BUILD/check-cpu @@ -6,113 +6,197 @@ # if test -r /proc/cpuinfo ; then + # on Linux (and others?) we can get detailed CPU information out of /proc cpuinfo="cat /proc/cpuinfo" + + # detect CPU family cpu_family=`$cpuinfo | grep 'family' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` if test -z "$cpu_family" ; then cpu_family=`$cpuinfo | grep 'cpu' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` fi + + # detect CPU vendor and model cpu_vendor=`$cpuinfo | grep 'vendor_id' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` model_name=`$cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -1` if test -z "$model_name" ; then model_name=`$cpuinfo | grep 'cpu model' | cut -d ':' -f 2 | head -1` fi + + # fallback: get CPU model from uname output if test -z "$model_name" ; then model_name=`uname -m` fi + + # parse CPU flags + for flag in `$cpuinfo | grep 'flags' | sed -e 's/^flags.*: //'`; do + eval cpu_flag_$flag=yes + done else # Fallback when there is no /proc/cpuinfo case "`uname -s`" in - FreeBSD) + FreeBSD|OpenBSD) cpu_family=`uname -m`; - model_name=`sysctl -b hw.model` + model_name=`sysctl -n hw.model` + ;; + Darwin) + cpu_family=`uname -p` + model_name=`machine` ;; *) cpu_family=`uname -m`; - model_name="unknown"; + model_name=`uname -p`; ;; esac fi -cpu_flag="" -cpu_flag_old="" +# detect CPU shortname as used by gcc options +# this list is not complete, feel free to add further entries +cpu_arg="" case "$cpu_family--$model_name" in + # DEC Alpha Alpha*EV6*) - cpu_flag="ev6"; + cpu_arg="ev6"; ;; + + # Intel ia32 *Xeon*) - cpu_flag="nocona"; + # a Xeon is just another pentium4 ... + # ... unless it has the "lm" (long-mode) flag set, + # in that case it's a Xeon with EM64T support + if [ -z "$cpu_flag_lm" ]; then + cpu_arg="pentium4"; + else + cpu_arg="nocona"; + fi ;; - *Pentium*4*Mobile*CPU*) - cpu_flag="pentium4m"; + *Pentium*4*Mobile*) + cpu_arg="pentium4m"; ;; - *Pentium*4*CPU*) - cpu_flag="pentium4"; + *Pentium*4*) + cpu_arg="pentium4"; ;; - *Pentium*III*Mobile*CPU*) - cpu_flag="pentium3m"; + *Pentium*III*Mobile*) + cpu_arg="pentium3m"; ;; - *Pentium*III*CPU*) - cpu_flag="pentium3"; + *Pentium*III*) + cpu_arg="pentium3"; ;; *Pentium*M*pro*) - cpu_flag="pentium-m"; - cpu_flag_old="pentium"; + cpu_arg="pentium-m"; ;; *Athlon*64*) - cpu_flag="athlon64"; - cpu_flag_old="athlon"; + cpu_arg="athlon64"; ;; *Athlon*) - cpu_flag="athlon"; + cpu_arg="athlon"; ;; + + # Intel ia64 *Itanium*) # Don't need to set any flags for itanium(at the moment) - cpu_flag=""; + cpu_arg=""; ;; - *ppc) - cpu_flag="powerpc"; - no_march=1; + + # + *powerpc*) + cpu_arg=`echo $model_name | sed -e"s/ppc//g"` ;; + + # unknown *) - cpu_flag=""; + cpu_arg=""; ;; esac -if test -z "$cpu_flag"; then + +if test -z "$cpu_arg"; then echo "BUILD/check-cpu: Oops, could not findout what kind of cpu this machine is using." - check_cpu_flags="" + check_cpu_cflags="" return fi -echo "cpu_flag: $cpu_flag" - +# different compiler versions have different option names +# for CPU specific command line options if test -z "$CC" ; then cc="gcc"; else cc=$CC - fi cc_ver=`$cc --version | sed 1q` cc_verno=`echo $cc_ver | sed -e 's/[^0-9. ]//g; s/^ *//g; s/ .*//g'` case "$cc_ver--$cc_verno" in - *GCC*--3.4*|*GCC*--3.5*|*GCC*--4.*) - check_cpu_cflags="-mtune=$cpu_flag -march=$cpu_flag" - ;; *GCC*) - # Fix for older compiler versions - if test -n "$cpu_flag_old"; then - cpu_flag="$cpu_flag_old" - fi - check_cpu_cflags="-mcpu=$cpu_flag -march=$cpu_flag" - if test -n "$no_march"; then - check_cpu_cflags="-mcpu=$cpu_flag" - fi + # different gcc backends (and versions) have different CPU flags + case `gcc -dumpmachine` in + i?86-*) + case "$cc_verno" in + 3.4*|3.5*|4.*) + check_cpu_args='-mtune=$cpu_arg -march=$cpu_arg' + ;; + *) + check_cpu_args='-mcpu=$cpu_arg -march=$cpu_arg' + ;; + esac + ;; + ppc-*) + check_cpu_args='-mcpu=$cpu_arg -mtune=$cpu_arg' + ;; + *) + check_cpu_cflags="" + return + ;; + esac + ;; + 2.95.*) + # GCC 2.95 doesn't expose its name in --version output + check_cpu_args='-m$cpu_arg' ;; *) check_cpu_cflags="" + return ;; esac -echo $check_cpu_cflags + +# now we check whether the compiler really understands the cpu type +touch __test.c + +while [ "$cpu_arg" ] ; do + echo -n testing $cpu_arg "... " + + # compile check + check_cpu_cflags=`eval echo $check_cpu_args` + if $cc -c $check_cpu_cflags __test.c 2>/dev/null; then + echo ok + break; + fi + + echo failed + check_cpu_cflags="" + + # if compile failed: check whether it supports a predecessor of this CPU + # this list is not complete, feel free to add further entries + case "$cpu_arg" in + # Intel ia32 + nocona) cpu_arg=pentium4 ;; + prescott) cpu_arg=pentium4 ;; + pentium4m) cpu_arg=pentium4 ;; + pentium4) cpu_arg=pentium3 ;; + pentium3m) cpu_arg=pentium3 ;; + pentium3) cpu_arg=pentium2 ;; + pentium2) cpu_arg=pentiumpro ;; + pentiumpro) cpu_arg=pentium ;; + pentium) cpu_arg=i486 ;; + i486) cpu_arg=i386 ;; + + # power / powerPC + 7450) cpu_arg=7400 ;; + + *) cpu_arg="" ;; + esac +done + +rm __test.* + From 6de5ae6816ceb682f2856d7d45704d80d75adef8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jun 2005 12:56:51 +0200 Subject: [PATCH 26/29] Post review fix of BUG#10969. sql/item.h: Return name as LEX_STRING instead of its components. sql/sql_yacc.yy: Name returned as LEX_STRING instead of its components. --- sql/item.h | 8 +++++--- sql/sql_yacc.yy | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/sql/item.h b/sql/item.h index f2e8e582780..4f5ed9934c5 100644 --- a/sql/item.h +++ b/sql/item.h @@ -585,10 +585,12 @@ public: } /* For error printing */ - inline void my_name(char **strp, uint *lengthp) + inline LEX_STRING *my_name(LEX_STRING *get_name) { - *strp= m_name.str; - *lengthp= m_name.length; + if (!get_name) + return &m_name; + (*get_name)= m_name; + return get_name; } bool is_splocal() { return 1; } /* Needed for error checking */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c0f5d6e296c..2f584bc6b4e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4346,11 +4346,11 @@ simple_expr: { if ($3->is_splocal()) { - LEX_STRING name; + LEX_STRING *name; Item_splocal *il= static_cast($3); - il->my_name(&name.str, &name.length); - my_error(ER_WRONG_COLUMN_NAME, MYF(0), name.str); + name= il->my_name(NULL); + my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str); YYABORT; } $$= new Item_default_value($3); From 2906e27a7c3a287be6af12fa2969c034f37f5b40 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jun 2005 13:43:17 +0200 Subject: [PATCH 27/29] yassl template instantiation - don't do too much mysys/my_access.c: remove incorrect fix comments extra/yassl/taocrypt/src/integer.cpp: yassl template instantiation - don't do too much extra/yassl/taocrypt/src/template_instnt.cpp: yassl template instantiation - don't do too much mysys/my_access.c: remove incorrect fix sql/item_func.cc: a couple of comment. assert added. --- extra/yassl/taocrypt/src/integer.cpp | 7 +++--- extra/yassl/taocrypt/src/template_instnt.cpp | 26 +++++++++----------- mysys/my_access.c | 2 +- sql/item_func.cc | 11 ++++++--- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 3df1df9beab..deea376189c 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -3940,9 +3940,10 @@ Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, } #ifdef __GNUC__ -template unsigned int DivideThreeWordsByTwo(unsigned int*, unsigned int, unsigned int, DWord*); -template unsigned int DivideThreeWordsByTwo(unsigned int*, unsigned int, unsigned int, Word*); -template unsigned long long DivideThreeWordsByTwo(unsigned long long*, unsigned long long, unsigned long long, DWord*); +#ifndef TAOCRYPT_NATIVE_DWORD_AVAILABLE +template hword DivideThreeWordsByTwo(hword*, hword, hword, Word*); +#endif +template word DivideThreeWordsByTwo(word*, word, word, DWord*); #endif } // namespace diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 5fed1ee5ae4..81a8273c5c3 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -9,29 +9,27 @@ namespace TaoCrypt { #if defined(SSE2_INTRINSICS_AVAILABLE) template AlignedAllocator::pointer StdReallocate >(AlignedAllocator&, unsigned int*, AlignedAllocator::size_type, AlignedAllocator::size_type, bool); #endif -template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, unsigned char*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); -template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, unsigned int*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); -template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, unsigned long long*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); template class RSA_Decryptor; template class RSA_Encryptor; template class RSA_Encryptor; +template void tcDelete(HASH*); +template void tcArrayDelete(byte*); +template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, byte*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); +template void tcArrayDelete(word*); +template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, word*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); +#ifndef TAOCRYPT_SLOW_WORD64 // defined when word != word32 +template void tcArrayDelete(word32*); +template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, word32*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); +#endif +template void tcArrayDelete(char*); } namespace mySTL { -template vector* uninit_fill_n*, unsigned int, vector >(vector*, unsigned int, vector const&); -template vector* uninit_fill_n*, unsigned long, vector >(vector*, unsigned long, vector const&); +template vector* uninit_fill_n*, size_t, vector >(vector*, size_t, vector const&); template void destroy*>(vector*, vector*); template TaoCrypt::Integer* uninit_copy(TaoCrypt::Integer*, TaoCrypt::Integer*, TaoCrypt::Integer*); -template TaoCrypt::Integer* uninit_fill_n(TaoCrypt::Integer*, unsigned int, TaoCrypt::Integer const&); -template TaoCrypt::Integer* uninit_fill_n(TaoCrypt::Integer*, unsigned long, TaoCrypt::Integer const&); +template TaoCrypt::Integer* uninit_fill_n(TaoCrypt::Integer*, size_t, TaoCrypt::Integer const&); template void destroy(TaoCrypt::Integer*, TaoCrypt::Integer*); } -namespace TaoCrypt { -template void tcDelete(HASH*); -template void tcArrayDelete(unsigned*); -template void tcArrayDelete(unsigned long long*); -template void tcArrayDelete(unsigned char*); -template void tcArrayDelete(char*); -} #endif diff --git a/mysys/my_access.c b/mysys/my_access.c index 89e90e16f18..28210bdfc7d 100644 --- a/mysys/my_access.c +++ b/mysys/my_access.c @@ -44,7 +44,7 @@ int my_access(const char *path, int amode) result= GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo); if (! result || - (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & F_OK)) + (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & W_OK)) { my_errno= errno= EACCES; return -1; diff --git a/sql/item_func.cc b/sql/item_func.cc index 18c2efb0ace..5af99cb8132 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -695,8 +695,8 @@ String *Item_int_func::val_str(String *str) /* - Check arguments here to determine result's type for function with two - arguments. + Check arguments here to determine result's type for a numeric + function of two arguments. SYNOPSIS Item_num_op::find_num_type() @@ -722,8 +722,9 @@ void Item_num_op::find_num_type(void) hybrid_type= DECIMAL_RESULT; result_precision(); } - else if (r0 == INT_RESULT && r1 == INT_RESULT) + else { + DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT); decimals= 0; hybrid_type=INT_RESULT; result_precision(); @@ -738,7 +739,9 @@ void Item_num_op::find_num_type(void) /* - Set result type of function if it (type) is depends only on first argument + Set result type for a numeric function of one argument + (can be also used by a numeric function of many arguments, if the result + type depends only on the first argument) SYNOPSIS Item_func_num1::find_num_type() From 8376d8149960f871917faa6f23f379937019b98e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Jun 2005 21:59:33 +0200 Subject: [PATCH 28/29] client/mysql.cc make print_field_types() somewhat more useful client/mysql.cc: make print_field_types() somewhat more useful --- client/mysql.cc | 95 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 9cdc270e8ed..ca021cd11f0 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -44,7 +44,7 @@ #include #endif -const char *VER= "14.10"; +const char *VER= "14.11"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -1917,7 +1917,7 @@ com_go(String *buffer,char *line __attribute__((unused))) time_buff[0]=0; if (result) { - if (!mysql_num_rows(result) && ! quick) + if (!mysql_num_rows(result) && ! quick && !info_flag) { strmov(buff, "Empty set"); } @@ -2049,18 +2049,93 @@ com_ego(String *buffer,char *line) return result; } +static char *fieldtype2str(enum enum_field_types type) { + switch(type) { + case FIELD_TYPE_BIT: return "BIT"; + case FIELD_TYPE_BLOB: return "BLOB"; + case FIELD_TYPE_DATE: return "DATE"; + case FIELD_TYPE_DATETIME: return "DATETIME"; + case FIELD_TYPE_NEWDECIMAL: return "NEWDECIMAL"; + case FIELD_TYPE_DECIMAL: return "DECIMAL"; + case FIELD_TYPE_DOUBLE: return "DOUBLE"; + case FIELD_TYPE_ENUM: return "ENUM"; + case FIELD_TYPE_FLOAT: return "FLOAT"; + case FIELD_TYPE_GEOMETRY: return "GEOMETRY"; + case FIELD_TYPE_INT24: return "INT24"; + case FIELD_TYPE_LONG: return "LONG"; + case FIELD_TYPE_LONGLONG: return "LONGLONG"; + case FIELD_TYPE_LONG_BLOB: return "LONG_BLOB"; + case FIELD_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB"; + case FIELD_TYPE_NEWDATE: return "NEWDATE"; + case FIELD_TYPE_NULL: return "NULL"; + case FIELD_TYPE_SET: return "SET"; + case FIELD_TYPE_SHORT: return "SHORT"; + case FIELD_TYPE_STRING: return "STRING"; + case FIELD_TYPE_TIME: return "TIME"; + case FIELD_TYPE_TIMESTAMP: return "TIMESTAMP"; + case FIELD_TYPE_TINY: return "TINY"; + case FIELD_TYPE_TINY_BLOB: return "TINY_BLOB"; + case FIELD_TYPE_VAR_STRING: return "VAR_STRING"; + case FIELD_TYPE_YEAR: return "YEAR"; + default: return "?-unknown-?"; + } +} + +static char *fieldflags2str(uint f) { + static char buf[1024]; + char *s=buf; + *s=0; +#define ff2s_check_flag(X) \ + if (f & X ## _FLAG) { s=strmov(s, # X " "); f &= ~ X ## _FLAG; } + ff2s_check_flag(NOT_NULL); + ff2s_check_flag(PRI_KEY); + ff2s_check_flag(UNIQUE_KEY); + ff2s_check_flag(MULTIPLE_KEY); + ff2s_check_flag(BLOB); + ff2s_check_flag(UNSIGNED); + ff2s_check_flag(ZEROFILL); + ff2s_check_flag(BINARY); + ff2s_check_flag(ENUM); + ff2s_check_flag(AUTO_INCREMENT); + ff2s_check_flag(TIMESTAMP); + ff2s_check_flag(SET); + ff2s_check_flag(NO_DEFAULT_VALUE); + ff2s_check_flag(NUM); + ff2s_check_flag(PART_KEY); + ff2s_check_flag(GROUP); + ff2s_check_flag(UNIQUE); + ff2s_check_flag(BINCMP); +#undef ff2s_check_flag + if (f) + sprintf(s, " unknows=0x%04x", f); + return buf; +} + static void print_field_types(MYSQL_RES *result) { - MYSQL_FIELD *field; + MYSQL_FIELD *field; + uint i=0; + while ((field = mysql_fetch_field(result))) { - tee_fprintf(PAGER,"Catalog: '%s'\nDatabase: '%s'\nTable: '%s'\nName: '%s'\nType: %d\nLength: %ld\nMax length: %ld\nIs_null: %d\nFlags: %u\nDecimals: %u\n\n", - field->catalog, field->db, field->table, field->name, - (int) field->type, - field->length, field->max_length, - !IS_NOT_NULL(field->flags), - field->flags, field->decimals); + tee_fprintf(PAGER, "Field %3u: `%s`\n" + "Catalog: `%s`\n" + "Database: `%s`\n" + "Table: `%s`\n" + "Org_table: `%s`\n" + "Type: %s\n" + "Collation: %s (%u)\n" + "Length: %lu\n" + "Max_length: %lu\n" + "Decimals: %u\n" + "Flags: %s\n\n", + ++i, + field->name, field->catalog, field->db, field->table, + field->org_table, fieldtype2str(field->type), + get_charset_name(field->charsetnr), field->charsetnr, + field->length, field->max_length, field->decimals, + fieldflags2str(field->flags)); } tee_puts("", PAGER); } @@ -2078,6 +2153,8 @@ print_table_data(MYSQL_RES *result) if (info_flag) { print_field_types(result); + if (!mysql_num_rows(result)) + return; mysql_field_seek(result,0); } separator.copy("+",1,charset_info); From 8b5ac76d6b31d4bd0bb79d69fed2c06ff2f519fe Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Jun 2005 12:37:10 +0400 Subject: [PATCH 29/29] Add missing STMT_ATTR_PREFETCH_ROWS to mysql_stmt_attr_get --- libmysql/libmysql.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index c87728ab783..d294921aad2 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2809,11 +2809,14 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, { switch (attr_type) { case STMT_ATTR_UPDATE_MAX_LENGTH: - *(unsigned long *) value= stmt->update_max_length; + *(ulong*) value= stmt->update_max_length; break; case STMT_ATTR_CURSOR_TYPE: - *(unsigned long *) value= stmt->flags; + *(ulong*) value= stmt->flags; break; + case STMT_ATTR_PREFETCH_ROWS: + *(ulong*) value= stmt->prefetch_rows; + break; default: return TRUE; }