From a73058a77c0fe693ea825ab5f9b896fd7eb1bc2c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Aug 2003 19:11:54 -0400 Subject: [PATCH 1/2] fixed bug #910 (right type of ifnull function) mysql-test/r/create.result: added test for bug #910 (right type of ifnull function) mysql-test/t/create.test: added test for bug #910 (right type of ifnull function) sql/field.h: added new constructors of Field_decimal, Field_tiny, Field_short, Field_float, Field_null, Field_year for using in Item::tmp_table_field_from_field_type sql/item.cc: added Item::tmp_table_field_from_field_type sql/item.h: added Item::tmp_table_field_from_field_type --- mysql-test/r/create.result | 49 ++++++++++++++++++++++++++++ mysql-test/t/create.test | 38 +++++++++++++++++++++ sql/field.h | 29 +++++++++++++++++ sql/item.cc | 67 ++++++++++++++++++++++++++++++++++++++ sql/item.h | 2 ++ sql/item_cmpfunc.cc | 13 ++++++++ sql/item_cmpfunc.h | 4 +++ 7 files changed, 202 insertions(+) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 9a0eca52b84..5567cc7c841 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -310,3 +310,52 @@ t1 CREATE TABLE `t1` ( ) TYPE=MyISAM CHARSET=latin1 SET SESSION table_type=default; drop table t1; +create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob); +insert into t1(a)values(1); +insert into t1(a,b,c,d,e,f,g,h) +values(2,-2,2,'1825-12-14','a','2003-1-1 3:2:1','4:3:2','binary data'); +select * from t1; +a b c d e f g h +1 NULL NULL NULL NULL NULL NULL NULL +2 -2 2 1825-12-14 a 2003-01-01 03:02:01 04:03:02 binary data +select a, +ifnull(b,cast(-7 as signed)) as b, +ifnull(c,cast(7 as unsigned)) as c, +ifnull(d,cast('2000-01-01' as date)) as d, +ifnull(e,cast('b' as char)) as e, +ifnull(f,cast('2000-01-01' as datetime)) as f, +ifnull(g,cast('5:4:3' as time)) as g, +ifnull(h,cast('yet another binary data' as binary)) as h, +addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd +from t1; +a b c d e f g h dd +1 -7 7 2000-01-01 b 2000-01-01 00:00:00 05:04:03 yet another binary data 02:00:00 +2 -2 2 1825-12-14 a 2003-01-01 03:02:01 04:03:02 binary data 02:00:00 +create table t2 +select +a, +ifnull(b,cast(-7 as signed)) as b, +ifnull(c,cast(7 as unsigned)) as c, +ifnull(d,cast('2000-01-01' as date)) as d, +ifnull(e,cast('b' as char)) as e, +ifnull(f,cast('2000-01-01' as datetime)) as f, +ifnull(g,cast('5:4:3' as time)) as g, +ifnull(h,cast('yet another binary data' as binary)) as h, +addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd +from t1; +explain t2; +Field Type Null Key Default Extra +a int(11) YES NULL +b bigint(11) 0 +c bigint(10) 0 +d date 0000-00-00 +e char(1) +f datetime 0000-00-00 00:00:00 +g time 00:00:00 +h mediumblob +dd time 00:00:00 +select * from t2; +a b c d e f g h dd +1 -7 7 2000-01-01 b 2000-01-01 00:00:00 05:04:03 yet another binary data 02:00:00 +2 -2 2 1825-12-14 a 2003-01-01 03:02:01 04:03:02 binary data 02:00:00 +drop table t1, t2; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 9bc37a0864d..b89cf854ffb 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -215,3 +215,41 @@ CREATE TABLE t1 (a int not null); show create table t1; SET SESSION table_type=default; drop table t1; + +# +# Test types of data for create select with functions +# + +create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob); +insert into t1(a)values(1); +insert into t1(a,b,c,d,e,f,g,h) +values(2,-2,2,'1825-12-14','a','2003-1-1 3:2:1','4:3:2','binary data'); +select * from t1; +select a, + ifnull(b,cast(-7 as signed)) as b, + ifnull(c,cast(7 as unsigned)) as c, + ifnull(d,cast('2000-01-01' as date)) as d, + ifnull(e,cast('b' as char)) as e, + ifnull(f,cast('2000-01-01' as datetime)) as f, + ifnull(g,cast('5:4:3' as time)) as g, + ifnull(h,cast('yet another binary data' as binary)) as h, + addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd +from t1; + +create table t2 +select + a, + ifnull(b,cast(-7 as signed)) as b, + ifnull(c,cast(7 as unsigned)) as c, + ifnull(d,cast('2000-01-01' as date)) as d, + ifnull(e,cast('b' as char)) as e, + ifnull(f,cast('2000-01-01' as datetime)) as f, + ifnull(g,cast('5:4:3' as time)) as g, + ifnull(h,cast('yet another binary data' as binary)) as h, + addtime(cast('1:0:0' as time),cast('1:0:0' as time)) as dd +from t1; +explain t2; + +select * from t2; + +drop table t1, t2; diff --git a/sql/field.h b/sql/field.h index 79c45a99a43..a69178b4c92 100644 --- a/sql/field.h +++ b/sql/field.h @@ -305,6 +305,11 @@ public: unireg_check_arg, field_name_arg, table_arg, dec_arg, zero_arg,unsigned_arg) {} + Field_decimal(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg,bool unsigned_arg) + :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, + NONE, field_name_arg, table_arg,0,0,unsigned_arg) + {} enum_field_types type() const { return FIELD_TYPE_DECIMAL;} enum ha_base_keytype key_type() const { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; } @@ -334,6 +339,11 @@ public: unireg_check_arg, field_name_arg, table_arg, 0, zero_arg,unsigned_arg) {} + Field_tiny(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg,bool unsigned_arg) + :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, + NONE, field_name_arg, table_arg,0,0,unsigned_arg) + {} enum Item_result result_type () const { return INT_RESULT; } enum_field_types type() const { return FIELD_TYPE_TINY;} enum ha_base_keytype key_type() const @@ -364,6 +374,11 @@ public: unireg_check_arg, field_name_arg, table_arg, 0, zero_arg,unsigned_arg) {} + Field_short(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg,bool unsigned_arg) + :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, + NONE, field_name_arg, table_arg,0,0,unsigned_arg) + {} enum Item_result result_type () const { return INT_RESULT; } enum_field_types type() const { return FIELD_TYPE_SHORT;} enum ha_base_keytype key_type() const @@ -497,6 +512,11 @@ public: unireg_check_arg, field_name_arg, table_arg, dec_arg, zero_arg,unsigned_arg) {} + Field_float(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg, uint8 dec_arg) + :Field_num((char*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, + NONE, field_name_arg, table_arg,dec_arg,0,0) + {} enum_field_types type() const { return FIELD_TYPE_FLOAT;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; } int store(const char *to,uint length,CHARSET_INFO *charset); @@ -558,6 +578,11 @@ public: :Field_str(ptr_arg, len_arg, null, 1, unireg_check_arg, field_name_arg, table_arg, cs) {} + Field_null(uint32 len_arg, const char *field_name_arg, + struct st_table *table_arg, CHARSET_INFO *cs) + :Field_str((char*) 0, len_arg, null, 1, + NONE, field_name_arg, table_arg, cs) + {} enum_field_types type() const { return FIELD_TYPE_NULL;} int store(const char *to, uint length, CHARSET_INFO *cs) { null[0]=1; return 0; } int store(double nr) { null[0]=1; return 0; } @@ -627,6 +652,10 @@ public: :Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, table_arg, 1, 1) {} + Field_year(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg) + :Field_tiny(len_arg,maybe_null_arg,field_name_arg,table_arg,1) + {} enum_field_types type() const { return FIELD_TYPE_YEAR;} int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); diff --git a/sql/item.cc b/sql/item.cc index 17b0519b61c..29f76ecff94 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -983,6 +983,73 @@ enum_field_types Item::field_type() const FIELD_TYPE_DOUBLE); } +Field *Item::tmp_table_field_from_field_type(TABLE *table) +{ + switch (field_type()) + { + case MYSQL_TYPE_DECIMAL: + return new Field_decimal(max_length, maybe_null, name, table, + unsigned_flag); + case MYSQL_TYPE_TINY: + return new Field_tiny(max_length, maybe_null, name, table, + unsigned_flag); + case MYSQL_TYPE_SHORT: + return new Field_short(max_length, maybe_null, name, table, + unsigned_flag); + case MYSQL_TYPE_LONG: + return new Field_long(max_length, maybe_null, name, table, + unsigned_flag); + case MYSQL_TYPE_FLOAT: + return new Field_float(max_length, maybe_null, name, table, decimals); + case MYSQL_TYPE_DOUBLE: + return new Field_double(max_length, maybe_null, name, table, decimals); + case MYSQL_TYPE_NULL: + return new Field_null(max_length, name, table, &my_charset_bin); +#ifdef HAVE_LONG_LONG + case MYSQL_TYPE_LONGLONG: + return new Field_longlong(max_length, maybe_null, name, table, + unsigned_flag); +#endif + case MYSQL_TYPE_NEWDATE: + case MYSQL_TYPE_INT24: + return new Field_long(max_length, maybe_null, name, table, + unsigned_flag); + case MYSQL_TYPE_DATE: + return new Field_date(maybe_null, name, table, &my_charset_bin); + case MYSQL_TYPE_TIME: + return new Field_time(maybe_null, name, table, &my_charset_bin); + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: + return new Field_datetime(maybe_null, name, table, &my_charset_bin); + case MYSQL_TYPE_YEAR: + return new Field_year(max_length, maybe_null, name, table); + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + return new Field_long(max_length, maybe_null, name, table, + unsigned_flag); + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_GEOMETRY: + return new Field_blob(max_length, maybe_null, name, table, collation.collation); + case MYSQL_TYPE_VAR_STRING: + if (max_length > 255) + return new Field_blob(max_length, maybe_null, name, table, collation.collation); + else + return new Field_varstring(max_length, maybe_null, name, table, collation.collation); + case MYSQL_TYPE_STRING: + if (max_length > 255) + return new Field_blob(max_length, maybe_null, name, table, collation.collation); + else + return new Field_string(max_length, maybe_null, name, table, collation.collation); + default: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; + } +} + /* ARGSUSED */ void Item_field::make_field(Send_field *tmp_field) { diff --git a/sql/item.h b/sql/item.h index 621dc017d25..13ebe8c6cf8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -180,6 +180,8 @@ public: virtual bool null_inside() { return 0; } // used in row subselects to get value of elements virtual void bring_value() {} + + Field *tmp_table_field_from_field_type(TABLE *table); }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 7d8da16338b..6ec84704fca 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -687,8 +687,21 @@ Item_func_ifnull::fix_length_and_dec() agg_arg_collations(collation, args, arg_count); else if (cached_result_type != REAL_RESULT) decimals= 0; + + cached_field_type= args[0]->field_type(); + if (cached_field_type != args[1]->field_type()) + cached_field_type= Item_func::field_type(); } +enum_field_types Item_func_ifnull::field_type() const +{ + return cached_field_type; +} + +Field *Item_func_ifnull::tmp_table_field(TABLE *table) +{ + return tmp_table_field_from_field_type(table); +} double Item_func_ifnull::val() diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 25cc97d60bf..5dd919c984b 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -281,6 +281,8 @@ public: class Item_func_ifnull :public Item_func { enum Item_result cached_result_type; + enum_field_types cached_field_type; + bool field_type_defined; public: Item_func_ifnull(Item *a,Item *b) :Item_func(a,b), cached_result_type(INT_RESULT) @@ -289,8 +291,10 @@ public: longlong val_int(); String *val_str(String *str); enum Item_result result_type () const { return cached_result_type; } + enum_field_types field_type() const; void fix_length_and_dec(); const char *func_name() const { return "ifnull"; } + Field *tmp_table_field(TABLE *table); }; From f8e55811316ada1a24de26493ae38bdf8a312f22 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Aug 2003 10:26:56 -0400 Subject: [PATCH 2/2] fixed merge mistake --- mysql-test/r/create.result | 1 - mysql-test/t/create.test | 2 -- 2 files changed, 3 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index be35bda3b6c..80ff8aef15b 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -310,7 +310,6 @@ t1 CREATE TABLE `t1` ( ) TYPE=MyISAM CHARSET=latin1 SET SESSION table_type=default; drop table t1; -drop table t1; create table t1 select x'4132'; drop table t1; create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob); diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index fee3e796805..2e21768dc0b 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -216,8 +216,6 @@ show create table t1; SET SESSION table_type=default; drop table t1; -drop table t1; - # # Bug # 801 #