diff options
-rw-r--r-- | mysql-test/r/func_group.result | 2 | ||||
-rw-r--r-- | mysql-test/r/metadata.result | 27 | ||||
-rw-r--r-- | mysql-test/r/union.result | 57 | ||||
-rw-r--r-- | mysql-test/t/metadata.test | 13 | ||||
-rw-r--r-- | mysql-test/t/union.test | 25 | ||||
-rw-r--r-- | sql/field.cc | 995 | ||||
-rw-r--r-- | sql/field.h | 48 | ||||
-rw-r--r-- | sql/item.cc | 344 | ||||
-rw-r--r-- | sql/item.h | 32 | ||||
-rw-r--r-- | sql/item_func.h | 3 | ||||
-rw-r--r-- | sql/item_subselect.cc | 2 | ||||
-rw-r--r-- | sql/sql_derived.cc | 4 | ||||
-rw-r--r-- | sql/sql_lex.h | 3 | ||||
-rw-r--r-- | sql/sql_parse.cc | 6 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 4 | ||||
-rw-r--r-- | sql/sql_select.cc | 14 | ||||
-rw-r--r-- | sql/sql_union.cc | 12 |
17 files changed, 1169 insertions, 422 deletions
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index c22d0d3bec8..2fb18ca92c7 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -747,7 +747,7 @@ insert into t1 values (now()); create table t2 select f2 from (select max(now()) f2 from t1) a; show columns from t2; Field Type Null Key Default Extra -f2 datetime 0000-00-00 00:00:00 +f2 datetime YES NULL drop table t2; create table t2 select f2 from (select now() f2 from t1) a; show columns from t2; diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result index 54b3f1e0466..d691a200b7e 100644 --- a/mysql-test/r/metadata.result +++ b/mysql-test/r/metadata.result @@ -55,8 +55,33 @@ id data data 2 female no select t1.id from t1 union select t2.id from t2; Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 t1 id id 1 3 1 Y 32768 0 63 +def id id 1 4 1 Y 32768 0 63 id 1 2 drop table t1,t2; +create table t1 ( a int, b varchar(30), primary key(a)); +insert into t1 values (1,'one'); +insert into t1 values (2,'two'); +set @arg00=1 ; +select @arg00 FROM t1 where a=1 union distinct select 1 FROM t1 where a=1; +Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr +def @arg00 @arg00 8 20 1 Y 32768 0 63 +@arg00 +1 +select * from (select @arg00) aaa; +Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr +def aaa @arg00 @arg00 8 20 1 Y 32768 0 63 +@arg00 +1 +select 1 union select 1; +Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr +def 1 1 8 20 1 N 32769 0 63 +1 +1 +select * from (select 1 union select 1) aaa; +Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr +def aaa 1 1 8 20 1 N 32769 0 63 +1 +1 +drop table t1; diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index f58f0f5b0ac..6fcdf7c5db5 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -655,7 +655,7 @@ f show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `f` binary(24) default NULL + `f` varbinary(24) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT y from t2 UNION select da from t2; @@ -666,7 +666,7 @@ y show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `y` binary(10) default NULL + `y` varbinary(10) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT y from t2 UNION select dt from t2; @@ -677,7 +677,7 @@ y show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `y` binary(19) default NULL + `y` varbinary(19) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT da from t2 UNION select dt from t2; @@ -699,7 +699,7 @@ testc show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `dt` binary(19) default NULL + `dt` varbinary(19) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT dt from t2 UNION select sv from t2; @@ -710,7 +710,7 @@ testv show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `dt` binary(19) default NULL + `dt` varbinary(19) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT sc from t2 UNION select sv from t2; @@ -732,7 +732,7 @@ tetetetetest show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `dt` blob + `dt` longblob ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT sv from t2 UNION select b from t2; @@ -755,7 +755,7 @@ tetetetetest show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `i` blob + `i` longblob ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT sv from t2 UNION select tx from t2; @@ -766,7 +766,7 @@ teeeeeeeeeeeest show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `sv` text + `sv` longtext ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT b from t2 UNION select tx from t2; @@ -1069,7 +1069,7 @@ create table t1 as show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `_latin1'test' collate latin1_bin` char(4) character set latin1 collate latin1_bin NOT NULL default '' + `_latin1'test' collate latin1_bin` varchar(4) character set latin1 collate latin1_bin NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select count(*) from t1; count(*) @@ -1082,7 +1082,7 @@ create table t1 as show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `test` char(4) character set latin1 collate latin1_bin NOT NULL default '' + `test` varchar(4) character set latin1 collate latin1_bin NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select count(*) from t1; count(*) @@ -1095,7 +1095,7 @@ create table t1 as show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `test` char(4) character set latin1 collate latin1_bin NOT NULL default '' + `test` varchar(4) character set latin1 collate latin1_bin NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select count(*) from t1; count(*) @@ -1195,3 +1195,38 @@ a b 2 b 3 c drop table t1; +CREATE TABLE t1 ( +a ENUM('ä','ö','ü') character set utf8 not null default 'ü', +b ENUM("one", "two") character set utf8, +c ENUM("one", "two") +); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` enum('ä','ö','ü') character set utf8 NOT NULL default 'ü', + `b` enum('one','two') character set utf8 default NULL, + `c` enum('one','two') default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +insert into t1 values ('ä', 'one', 'one'), ('ö', 'two', 'one'), ('ü', NULL, NULL); +create table t2 select NULL union select a from t1; +show columns from t2; +Field Type Null Key Default Extra +NULL enum('ä','ö','ü') YES NULL +drop table t2; +create table t2 select a from t1 union select NULL; +show columns from t2; +Field Type Null Key Default Extra +a enum('ä','ö','ü') YES NULL +drop table t2; +create table t2 select a from t1 union select a from t1; +show columns from t2; +Field Type Null Key Default Extra +a char(1) +drop table t2; +create table t2 select a from t1 union select c from t1; +ERROR HY000: Illegal mix of collations (utf8_general_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation 'UNION' +create table t2 select a from t1 union select b from t1; +show columns from t2; +Field Type Null Key Default Extra +a varchar(3) YES NULL +drop table t2, t1; diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test index d11cb62b04e..ebd58ef4ebb 100644 --- a/mysql-test/t/metadata.test +++ b/mysql-test/t/metadata.test @@ -34,4 +34,17 @@ select t1.id, t1.data, t2.data from t1, t2 where t1.id = t2.id order by t1.id; select t1.id from t1 union select t2.id from t2; drop table t1,t2; +# +# variables union and derived tables metadata test +# +create table t1 ( a int, b varchar(30), primary key(a)); +insert into t1 values (1,'one'); +insert into t1 values (2,'two'); +set @arg00=1 ; +select @arg00 FROM t1 where a=1 union distinct select 1 FROM t1 where a=1; +select * from (select @arg00) aaa; +select 1 union select 1; +select * from (select 1 union select 1) aaa; +drop table t1; + --disable_metadata diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 82f26f63254..88dc5e0d06a 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -711,3 +711,28 @@ select * from ((select * from t1 limit 1) union (select * from t1 limit 1) union select * from ((((select * from t1))) union (select * from t1) union (select * from t1)) a; select * from ((select * from t1) union (((select * from t1))) union (select * from t1)) a; drop table t1; + +# +# Enum merging test +# +CREATE TABLE t1 ( + a ENUM('ä','ö','ü') character set utf8 not null default 'ü', + b ENUM("one", "two") character set utf8, + c ENUM("one", "two") +); +show create table t1; +insert into t1 values ('ä', 'one', 'one'), ('ö', 'two', 'one'), ('ü', NULL, NULL); +create table t2 select NULL union select a from t1; +show columns from t2; +drop table t2; +create table t2 select a from t1 union select NULL; +show columns from t2; +drop table t2; +create table t2 select a from t1 union select a from t1; +show columns from t2; +drop table t2; +-- error 1267 +create table t2 select a from t1 union select c from t1; +create table t2 select a from t1 union select b from t1; +show columns from t2; +drop table t2, t1; diff --git a/sql/field.cc b/sql/field.cc index 2baf1bf84fd..bf581e62f34 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -48,6 +48,793 @@ const char field_separator=','; #define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320 +/* + Rules for merging different types of fields in UNION + + NOTE: to avoid 256*256 table, gap in table types numeration is skiped + following #defines describe that gap and how to canculate number of fields + and index of field in thia array. +*/ +#define FIELDTYPE_TEAR_FROM (MYSQL_TYPE_NEWDATE+1) +#define FIELDTYPE_TEAR_TO (MYSQL_TYPE_ENUM-1) +#define FIELDTYPE_NUM (FIELDTYPE_TEAR_FROM + (255-FIELDTYPE_TEAR_TO)) +inline int field_type2index (enum_field_types field_type) +{ + return (field_type < FIELDTYPE_TEAR_FROM ? + field_type : + ((int)FIELDTYPE_TEAR_FROM) + (field_type - FIELDTYPE_TEAR_TO) - 1); +} + +static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]= +{ + /* MYSQL_TYPE_DECIMAL -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_TINY -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_TINY, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_SHORT -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_SHORT, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_SHORT, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_SHORT, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_LONG -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_LONG, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_LONG, MYSQL_TYPE_LONG, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_LONG, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONG, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_LONG, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_FLOAT -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_FLOAT, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_FLOAT, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_FLOAT, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_FLOAT, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_DOUBLE -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_NULL -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_NEWDATE, MYSQL_TYPE_TIME, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_NEWDATE, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_ENUM, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY + }, + /* MYSQL_TYPE_TIMESTAMP -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_TIMESTAMP, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_DATETIME, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_LONGLONG -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_LONGLONG, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONGLONG, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_LONGLONG, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONG, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_LONGLONG, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_INT24 -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_INT24, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_INT24, MYSQL_TYPE_LONG, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_INT24, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_INT24, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_DATE -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_NEWDATE, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_TIME -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIME, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_DATETIME, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_DATETIME -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_DATETIME, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_YEAR -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_YEAR, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_YEAR, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_NEWDATE -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_NEWDATE, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_ENUM -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_ENUM, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_SET -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_SET, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_TINY_BLOB -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_TINY_BLOB, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB + }, + /* MYSQL_TYPE_MEDIUM_BLOB -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_MEDIUM_BLOB, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB + }, + /* MYSQL_TYPE_LONG_BLOB -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_LONG_BLOB, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB + }, + /* MYSQL_TYPE_BLOB -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_BLOB, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_BLOB, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB + }, + /* MYSQL_TYPE_VAR_STRING -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING + }, + /* MYSQL_TYPE_STRING -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_STRING, MYSQL_TYPE_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_STRING, MYSQL_TYPE_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_STRING, MYSQL_TYPE_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_STRING, MYSQL_TYPE_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_STRING, MYSQL_TYPE_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_STRING, MYSQL_TYPE_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_STRING, MYSQL_TYPE_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_STRING + }, + /* MYSQL_TYPE_GEOMETRY -> */ + { + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_GEOMETRY, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_NEWDATE <14> + MYSQL_TYPE_VAR_STRING, + //<246> MYSQL_TYPE_ENUM + MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY + } +}; + +/* + Return type of which can carry value of both given types in UNION result + + SYNOPSIS + Field::field_type_merge() + a, b types for merging + + RETURN + type of field +*/ + +enum_field_types Field::field_type_merge(enum_field_types a, + enum_field_types b) +{ + DBUG_ASSERT(a < FIELDTYPE_TEAR_FROM || a > FIELDTYPE_TEAR_TO); + DBUG_ASSERT(b < FIELDTYPE_TEAR_FROM || b > FIELDTYPE_TEAR_TO); + return field_types_merge_rules[field_type2index(a)] + [field_type2index(b)]; +} + + +static Item_result field_types_result_type [FIELDTYPE_NUM]= +{ + //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + REAL_RESULT, INT_RESULT, + //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + INT_RESULT, INT_RESULT, + //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + REAL_RESULT, REAL_RESULT, + //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + STRING_RESULT, STRING_RESULT, + //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + INT_RESULT, INT_RESULT, + //MYSQL_TYPE_DATE MYSQL_TYPE_TIME + STRING_RESULT, STRING_RESULT, + //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + STRING_RESULT, INT_RESULT, + //MYSQL_TYPE_NEWDATE <14> + STRING_RESULT, + //<246> MYSQL_TYPE_ENUM + STRING_RESULT, + //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + STRING_RESULT, STRING_RESULT, + //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + STRING_RESULT, STRING_RESULT, + //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + STRING_RESULT, STRING_RESULT, + //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + STRING_RESULT, STRING_RESULT +}; + + +/* + Detect Item_result by given field type of UNION merge result + + SYNOPSIS + Field::result_merge_type() + field_type given field type + + RETURN + Item_result (type of internal MySQL expression result) +*/ + +Item_result Field::result_merge_type(enum_field_types field_type) +{ + DBUG_ASSERT(field_type < FIELDTYPE_TEAR_FROM || field_type + > FIELDTYPE_TEAR_TO); + return field_types_result_type[field_type2index(field_type)]; +} + /***************************************************************************** Static help functions *****************************************************************************/ @@ -164,156 +951,6 @@ static bool test_if_real(const char *str,int length, CHARSET_INFO *cs) #endif -/* - Tables of filed type compatibility. - - There are tables for every type, table consist of list of types in which - given type can be converted without data lost, list should be ended with - FIELD_CAST_STOP -*/ -static Field::field_cast_enum field_cast_decimal[]= -{Field::FIELD_CAST_DECIMAL, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_tiny[]= -{Field::FIELD_CAST_TINY, - Field::FIELD_CAST_SHORT, Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, - Field::FIELD_CAST_LONGLONG, - Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_short[]= -{Field::FIELD_CAST_SHORT, - Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, Field::FIELD_CAST_LONGLONG, - Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_medium[]= -{Field::FIELD_CAST_MEDIUM, - Field::FIELD_CAST_LONG, Field::FIELD_CAST_LONGLONG, - Field::FIELD_CAST_DOUBLE, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_long[]= -{Field::FIELD_CAST_LONG, - Field::FIELD_CAST_LONGLONG, - Field::FIELD_CAST_DOUBLE, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_longlong[]= -{Field::FIELD_CAST_LONGLONG, - Field::FIELD_CAST_DOUBLE, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_float[]= -{Field::FIELD_CAST_FLOAT, - Field::FIELD_CAST_DOUBLE, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_double[]= -{Field::FIELD_CAST_DOUBLE, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_null[]= -{Field::FIELD_CAST_NULL, - Field::FIELD_CAST_DECIMAL, Field::FIELD_CAST_TINY, Field::FIELD_CAST_SHORT, - Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, Field::FIELD_CAST_LONGLONG, - Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE, - Field::FIELD_CAST_TIMESTAMP, Field::FIELD_CAST_YEAR, - Field::FIELD_CAST_DATE, Field::FIELD_CAST_NEWDATE, - Field::FIELD_CAST_TIME, Field::FIELD_CAST_DATETIME, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, - Field::FIELD_CAST_GEOM, Field::FIELD_CAST_ENUM, Field::FIELD_CAST_SET, - Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_timestamp[]= -{Field::FIELD_CAST_TIMESTAMP, - Field::FIELD_CAST_DATETIME, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_year[]= -{Field::FIELD_CAST_YEAR, - Field::FIELD_CAST_SHORT, Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, - Field::FIELD_CAST_LONGLONG, - Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_date[]= -{Field::FIELD_CAST_DATE, - Field::FIELD_CAST_DATETIME, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_newdate[]= -{Field::FIELD_CAST_NEWDATE, - Field::FIELD_CAST_DATE, - Field::FIELD_CAST_DATETIME, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_time[]= -{Field::FIELD_CAST_TIME, - Field::FIELD_CAST_DATETIME, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_datetime[]= -{Field::FIELD_CAST_DATETIME, - Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_string[]= -{Field::FIELD_CAST_STRING, - Field::FIELD_CAST_VARSTRING, Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_varstring[]= -{Field::FIELD_CAST_VARSTRING, - Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_blob[]= -{Field::FIELD_CAST_BLOB, - Field::FIELD_CAST_STOP}; -/* - Geometrical, enum and set fields can be casted only to expressions -*/ -static Field::field_cast_enum field_cast_geom[]= -{Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_enum[]= -{Field::FIELD_CAST_STOP}; -static Field::field_cast_enum field_cast_set[]= -{Field::FIELD_CAST_STOP}; -// Array of pointers on conversion table for all fields types casting -static Field::field_cast_enum *field_cast_array[]= -{0, //FIELD_CAST_STOP - field_cast_decimal, field_cast_tiny, field_cast_short, - field_cast_medium, field_cast_long, field_cast_longlong, - field_cast_float, field_cast_double, - field_cast_null, - field_cast_timestamp, field_cast_year, field_cast_date, field_cast_newdate, - field_cast_time, field_cast_datetime, - field_cast_string, field_cast_varstring, field_cast_blob, - field_cast_geom, field_cast_enum, field_cast_set -}; - - -/* - Check if field of given type can store a value of this field. - - SYNOPSIS - type type for test - - RETURN - 1 can - 0 can not -*/ - -bool Field::field_cast_compatible(Field::field_cast_enum type) -{ - DBUG_ASSERT(type != FIELD_CAST_STOP); - Field::field_cast_enum *array= field_cast_array[field_cast_type()]; - while (*array != FIELD_CAST_STOP) - { - if (*(array++) == type) - return 1; - } - return 0; -} - - /**************************************************************************** ** Functions for the base classes ** This is an unpacked number. @@ -373,9 +1010,15 @@ void Field_num::add_zerofill_and_unsigned(String &res) const void Field_num::make_field(Send_field *field) { /* table_cache_key is not set for temp tables */ - field->db_name= (orig_table->table_cache_key ? orig_table->table_cache_key : - ""); - field->org_table_name= orig_table->real_name; + if (orig_table->table_cache_key) + { + field->db_name= orig_table->table_cache_key; + field->org_table_name= orig_table->real_name; + } + else + { + field->db_name= field->org_table_name= ""; + } field->table_name= orig_table->table_name; field->col_name=field->org_col_name=field_name; field->charsetnr= charset()->number; @@ -389,9 +1032,15 @@ void Field_num::make_field(Send_field *field) void Field_str::make_field(Send_field *field) { /* table_cache_key is not set for temp tables */ - field->db_name= (orig_table->table_cache_key ? orig_table->table_cache_key : - ""); - field->org_table_name= orig_table->real_name; + if (orig_table->table_cache_key) + { + field->db_name= orig_table->table_cache_key; + field->org_table_name= orig_table->real_name; + } + else + { + field->db_name= field->org_table_name= ""; + } field->table_name= orig_table->table_name; field->col_name=field->org_col_name=field_name; field->charsetnr= charset()->number; @@ -6057,40 +6706,6 @@ Field *make_field(char *ptr, uint32 field_length, } -/* - Check if field_type is appropriate field type - to create field for tmp table using - item->tmp_table_field() method - - SYNOPSIS - field_types_to_be_kept() - field_type - field type - - NOTE - it is used in function get_holder_example_field() - from item.cc - - RETURN - 1 - can use item->tmp_table_field() method - 0 - can not use item->tmp_table_field() method - -*/ - -bool field_types_to_be_kept(enum_field_types field_type) -{ - switch (field_type) - { - case FIELD_TYPE_DATE: - case FIELD_TYPE_NEWDATE: - case FIELD_TYPE_TIME: - case FIELD_TYPE_DATETIME: - return 1; - default: - return 0; - } -} - - /* Create a field suitable for create of table */ create_field::create_field(Field *old_field,Field *orig_field) diff --git a/sql/field.h b/sql/field.h index b5d88504939..5dc124aba35 100644 --- a/sql/field.h +++ b/sql/field.h @@ -31,6 +31,17 @@ class Protocol; struct st_cache_field; void field_conv(Field *to,Field *from); +inline uint get_enum_pack_length(int elements) +{ + return elements < 256 ? 1 : 2; +} + +inline uint get_set_pack_length(int elements) +{ + uint len= (elements + 7) / 8; + return len > 4 ? 8 : len; +} + class Field { Field(const Item &); /* Prevent use of these */ @@ -75,17 +86,6 @@ public: GEOM_GEOMETRYCOLLECTION = 7 }; enum imagetype { itRAW, itMBR}; - enum field_cast_enum - { - FIELD_CAST_STOP, FIELD_CAST_DECIMAL, FIELD_CAST_TINY, FIELD_CAST_SHORT, - FIELD_CAST_MEDIUM, FIELD_CAST_LONG, FIELD_CAST_LONGLONG, - FIELD_CAST_FLOAT, FIELD_CAST_DOUBLE, - FIELD_CAST_NULL, - FIELD_CAST_TIMESTAMP, FIELD_CAST_YEAR, FIELD_CAST_DATE, FIELD_CAST_NEWDATE, - FIELD_CAST_TIME, FIELD_CAST_DATETIME, - FIELD_CAST_STRING, FIELD_CAST_VARSTRING, FIELD_CAST_BLOB, - FIELD_CAST_GEOM, FIELD_CAST_ENUM, FIELD_CAST_SET - }; utype unireg_check; uint32 field_length; // Length of field @@ -119,6 +119,8 @@ public: virtual String *val_str(String*,String *)=0; virtual Item_result result_type () const=0; virtual Item_result cmp_type () const { return result_type(); } + static enum_field_types field_type_merge(enum_field_types, enum_field_types); + static Item_result result_merge_type(enum_field_types); bool eq(Field *field) { return ptr == field->ptr && null_ptr == field->null_ptr; } virtual bool eq_def(Field *field); virtual uint32 pack_length() const { return (uint32) field_length; } @@ -290,8 +292,6 @@ public: int cuted_increment); void set_datetime_warning(const uint level, const uint code, double nr, timestamp_type ts_type); - virtual field_cast_enum field_cast_type()= 0; - bool field_cast_compatible(field_cast_enum type); /* maximum possible display length */ virtual uint32 max_length()= 0; friend bool reopen_table(THD *,struct st_table *,bool); @@ -398,7 +398,6 @@ public: bool zero_pack() const { return 0; } void sql_type(String &str) const; uint32 max_length() { return field_length; } - field_cast_enum field_cast_type() { return FIELD_CAST_DECIMAL; } }; @@ -430,7 +429,6 @@ public: uint32 pack_length() const { return 1; } void sql_type(String &str) const; uint32 max_length() { return 4; } - field_cast_enum field_cast_type() { return FIELD_CAST_TINY; } }; @@ -467,7 +465,6 @@ public: uint32 pack_length() const { return 2; } void sql_type(String &str) const; uint32 max_length() { return 6; } - field_cast_enum field_cast_type() { return FIELD_CAST_SHORT; } }; @@ -499,7 +496,6 @@ public: uint32 pack_length() const { return 3; } void sql_type(String &str) const; uint32 max_length() { return 8; } - field_cast_enum field_cast_type() { return FIELD_CAST_MEDIUM; } }; @@ -536,7 +532,6 @@ public: uint32 pack_length() const { return 4; } void sql_type(String &str) const; uint32 max_length() { return 11; } - field_cast_enum field_cast_type() { return FIELD_CAST_LONG; } }; @@ -576,7 +571,6 @@ public: void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } uint32 max_length() { return 20; } - field_cast_enum field_cast_type() { return FIELD_CAST_LONGLONG; } }; #endif @@ -611,7 +605,6 @@ public: uint32 pack_length() const { return sizeof(float); } void sql_type(String &str) const; uint32 max_length() { return 24; } - field_cast_enum field_cast_type() { return FIELD_CAST_FLOAT; } }; @@ -646,7 +639,6 @@ public: uint32 pack_length() const { return sizeof(double); } void sql_type(String &str) const; uint32 max_length() { return 53; } - field_cast_enum field_cast_type() { return FIELD_CAST_DOUBLE; } }; @@ -677,7 +669,6 @@ public: void sql_type(String &str) const; uint size_of() const { return sizeof(*this); } uint32 max_length() { return 4; } - field_cast_enum field_cast_type() { return FIELD_CAST_NULL; } }; @@ -729,7 +720,6 @@ public: } bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); - field_cast_enum field_cast_type() { return FIELD_CAST_TIMESTAMP; } timestamp_auto_set_type get_auto_set_type() const; }; @@ -753,7 +743,6 @@ public: bool send_binary(Protocol *protocol); void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } - field_cast_enum field_cast_type() { return FIELD_CAST_YEAR; } }; @@ -786,7 +775,6 @@ public: void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } - field_cast_enum field_cast_type() { return FIELD_CAST_DATE; } }; class Field_newdate :public Field_str { @@ -818,7 +806,6 @@ public: bool zero_pack() const { return 1; } bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); - field_cast_enum field_cast_type() { return FIELD_CAST_NEWDATE; } }; @@ -853,7 +840,6 @@ public: void sql_type(String &str) const; bool can_be_compared_as_longlong() const { return TRUE; } bool zero_pack() const { return 1; } - field_cast_enum field_cast_type() { return FIELD_CAST_TIME; } }; @@ -891,7 +877,6 @@ public: bool zero_pack() const { return 1; } bool get_date(TIME *ltime,uint fuzzydate); bool get_time(TIME *ltime); - field_cast_enum field_cast_type() { return FIELD_CAST_DATETIME; } }; @@ -937,7 +922,6 @@ public: enum_field_types real_type() const { return FIELD_TYPE_STRING; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } - field_cast_enum field_cast_type() { return FIELD_CAST_STRING; } }; @@ -986,7 +970,6 @@ public: enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } - field_cast_enum field_cast_type() { return FIELD_CAST_VARSTRING; } }; @@ -1081,7 +1064,6 @@ public: uint size_of() const { return sizeof(*this); } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } - field_cast_enum field_cast_type() { return FIELD_CAST_BLOB; } uint32 max_length(); }; @@ -1111,7 +1093,6 @@ public: void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type); void set_key_image(char *buff,uint length, CHARSET_INFO *cs); - field_cast_enum field_cast_type() { return FIELD_CAST_GEOM; } }; #endif /*HAVE_SPATIAL*/ @@ -1155,7 +1136,6 @@ public: bool has_charset(void) const { return TRUE; } /* enum and set are sorted as integers */ CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } - field_cast_enum field_cast_type() { return FIELD_CAST_ENUM; } }; @@ -1181,7 +1161,6 @@ public: void sql_type(String &str) const; enum_field_types real_type() const { return FIELD_TYPE_SET; } bool has_charset(void) const { return TRUE; } - field_cast_enum field_cast_type() { return FIELD_CAST_SET; } }; @@ -1268,7 +1247,6 @@ int set_field_to_null(Field *field); int set_field_to_null_with_conversions(Field *field, bool no_conversions); bool test_if_int(const char *str, int length, const char *int_end, CHARSET_INFO *cs); -bool field_types_to_be_kept(enum_field_types field_type); /* The following are for the interface with the .frm file diff --git a/sql/item.cc b/sql/item.cc index 2250bd9b32c..8bc6b878868 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1700,10 +1700,10 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table) case MYSQL_TYPE_NULL: return new Field_null((char*) 0, max_length, Field::NONE, name, table, &my_charset_bin); - case MYSQL_TYPE_NEWDATE: case MYSQL_TYPE_INT24: return new Field_medium((char*) 0, max_length, null_ptr, 0, Field::NONE, name, table, 0, unsigned_flag); + case MYSQL_TYPE_NEWDATE: case MYSQL_TYPE_DATE: return new Field_date(maybe_null, name, table, &my_charset_bin); case MYSQL_TYPE_TIME: @@ -2701,204 +2701,268 @@ void Item_cache_row::bring_value() } -/* - Returns field for temporary table dependind on item type - - SYNOPSIS - get_holder_example_field() - thd - thread handler - item - pointer to item - table - empty table object - - NOTE - It is possible to return field for Item_func - items only if field type of this item is - date or time or datetime type. - also see function field_types_to_be_kept() from - field.cc - - RETURN - # - field - 0 - no field -*/ - -Field *get_holder_example_field(THD *thd, Item *item, TABLE *table) -{ - DBUG_ASSERT(table); - - Item_func *tmp_item= 0; - if (item->type() == Item::FIELD_ITEM) - return (((Item_field*) item)->field); - if (item->type() == Item::FUNC_ITEM) - tmp_item= (Item_func *) item; - else if (item->type() == Item::SUM_FUNC_ITEM) - { - Item_sum *item_sum= (Item_sum *) item; - if (item_sum->keep_field_type()) - { - if (item_sum->args[0]->type() == Item::FIELD_ITEM) - return (((Item_field*) item_sum->args[0])->field); - if (item_sum->args[0]->type() == Item::FUNC_ITEM) - tmp_item= (Item_func *) item_sum->args[0]; - } - } - return (tmp_item && field_types_to_be_kept(tmp_item->field_type()) ? - tmp_item->tmp_table_field(table) : 0); -} - - -Item_type_holder::Item_type_holder(THD *thd, Item *item, TABLE *table) - :Item(thd, item), item_type(item->result_type()), - orig_type(item_type) +Item_type_holder::Item_type_holder(THD *thd, Item *item) + :Item(thd, item), enum_set_typelib(0), fld_type(get_real_type(item)) { DBUG_ASSERT(item->fixed); - /* - It is safe assign pointer on field, because it will be used just after - all JOIN::prepare calls and before any SELECT execution - */ - field_example= get_holder_example_field(thd, item, table); - max_length= real_length(item); + max_length= display_length(item); maybe_null= item->maybe_null; collation.set(item->collation); + get_full_info(item); } /* - STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT + Return expression type of Item_type_holder - ROW_RESULT should never appear in Item_type_holder::join_types, - but it is included in following table just to make table full - (there DBUG_ASSERT in function to catch ROW_RESULT) + SYNOPSIS + Item_type_holder::result_type() + + RETURN + Item_result (type of internal MySQL expression result) */ -static Item_result type_convertor[4][4]= -{{STRING_RESULT, STRING_RESULT, STRING_RESULT, ROW_RESULT}, - {STRING_RESULT, REAL_RESULT, REAL_RESULT, ROW_RESULT}, - {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT}, - {ROW_RESULT, ROW_RESULT, ROW_RESULT, ROW_RESULT}}; + +Item_result Item_type_holder::result_type() const +{ + return Field::result_merge_type(fld_type); +} /* - Values of 'from' field can be stored in 'to' field. + Find real field type of item SYNOPSIS - is_attr_compatible() - from Item which values should be saved - to Item where values should be saved + Item_type_holder::get_real_type() RETURN - 1 can be saved - 0 can not be saved + type of field which should be created to store item value */ -inline bool is_attr_compatible(Item *from, Item *to) -{ - return ((to->max_length >= from->max_length) && - (to->maybe_null || !from->maybe_null) && - (to->result_type() != STRING_RESULT || - from->result_type() != STRING_RESULT || - (from->collation.collation == to->collation.collation))); -} - - -bool Item_type_holder::join_types(THD *thd, Item *item, TABLE *table) +enum_field_types Item_type_holder::get_real_type(Item *item) { - uint32 new_length= real_length(item); - bool use_new_field= 0, use_expression_type= 0; - Item_result new_result_type= type_convertor[item_type][item->result_type()]; - Field *field= get_holder_example_field(thd, item, table); - bool item_is_a_field= (field != NULL); - /* - Check if both items point to fields: in this case we - can adjust column types of result table in the union smartly. - */ - if (field_example && item_is_a_field) + switch(item->type()) { - /* Can 'field_example' field store data of the column? */ - if ((use_new_field= - (!field->field_cast_compatible(field_example->field_cast_type()) || - !is_attr_compatible(item, this)))) - { - /* - The old field can't store value of the new field. - Check if the new field can store value of the old one. - */ - use_expression_type|= - (!field_example->field_cast_compatible(field->field_cast_type()) || - !is_attr_compatible(this, item)); - } - } - else if (field_example || item_is_a_field) + case FIELD_ITEM: { /* - Expression types can't be mixed with field types, we have to use - expression types. + Item_fields::field_type ask Field_type() but sometimes field return + a different type, like for enum/set, so we need to ask real type. */ - use_new_field= 1; // make next if test easier - use_expression_type= 1; + Field *field= ((Item_field *) item)->field; + enum_field_types type= field->real_type(); + /* work around about varchar type field detection */ + if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING) + return MYSQL_TYPE_VAR_STRING; + return type; } - - /* Check whether size/type of the result item should be changed */ - if (use_new_field || - (new_result_type != item_type) || (new_length > max_length) || - (!maybe_null && item->maybe_null) || - (item_type == STRING_RESULT && - collation.collation != item->collation.collation)) + case SUM_FUNC_ITEM: { - const char *old_cs,*old_derivation; - if (use_expression_type || !item_is_a_field) - field_example= 0; - else + /* + Argument of aggregate function sometimes should be asked about field + type + */ + Item_sum *item_sum= (Item_sum *) item; + if (item_sum->keep_field_type()) + return get_real_type(item_sum->args[0]); + break; + } + case FUNC_ITEM: + if (((Item_func *) item)->functype() == Item_func::VAR_VALUE_FUNC) { /* - It is safe to assign a pointer to field here, because it will be used - before any table is closed. + There are work around of problem with changing variable type on the + fly and variable always report "string" as field type to get + acceptable information for client in send_field, so we make field + type from expression type. */ - field_example= field; + switch (item->result_type()) + { + case STRING_RESULT: + return MYSQL_TYPE_VAR_STRING; + case INT_RESULT: + return MYSQL_TYPE_LONGLONG; + case REAL_RESULT: + return MYSQL_TYPE_DOUBLE; + case ROW_RESULT: + default: + DBUG_ASSERT(0); + return MYSQL_TYPE_VAR_STRING; + } } + break; + default: + break; + } + return item->field_type(); +} + +/* + Find field type which can carry current Item_type_holder type and + type of given Item. + SYNOPSIS + Item_type_holder::join_types() + thd thread handler + item given item to join its parameters with this item ones + + RETURN + TRUE error - types are incompatible + FALSE OK +*/ + +bool Item_type_holder::join_types(THD *thd, Item *item) +{ + max_length= max(max_length, display_length(item)); + fld_type= Field::field_type_merge(fld_type, get_real_type(item)); + if (Field::result_merge_type(fld_type) == STRING_RESULT) + { + const char *old_cs, *old_derivation; old_cs= collation.collation->name; old_derivation= collation.derivation_name(); - if (item_type == STRING_RESULT && collation.aggregate(item->collation)) + if (collation.aggregate(item->collation)) { my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0), old_cs, old_derivation, item->collation.collation->name, item->collation.derivation_name(), "UNION"); - return 1; + return TRUE; } - - max_length= max(max_length, new_length); - decimals= max(decimals, item->decimals); - maybe_null|= item->maybe_null; - item_type= new_result_type; } - DBUG_ASSERT(item_type != ROW_RESULT); - return 0; + decimals= max(decimals, item->decimals); + maybe_null|= item->maybe_null; + get_full_info(item); + return FALSE; } +/* + Calculate lenth for merging result for given Item type -uint32 Item_type_holder::real_length(Item *item) + SYNOPSIS + Item_type_holder::real_length() + item Item for lrngth detection + + RETURN + length +*/ + +uint32 Item_type_holder::display_length(Item *item) { if (item->type() == Item::FIELD_ITEM) return ((Item_field *)item)->max_disp_length(); - switch (item->result_type()) + switch (item->field_type()) { - case STRING_RESULT: + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_NEWDATE: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_GEOMETRY: return item->max_length; - case REAL_RESULT: + case MYSQL_TYPE_TINY: + return 4; + case MYSQL_TYPE_SHORT: + return 6; + case MYSQL_TYPE_LONG: + return 11; + case MYSQL_TYPE_FLOAT: + return 25; + case MYSQL_TYPE_DOUBLE: return 53; - case INT_RESULT: + case MYSQL_TYPE_NULL: + return 4; + case MYSQL_TYPE_LONGLONG: return 20; - case ROW_RESULT: + case MYSQL_TYPE_INT24: + return 8; default: DBUG_ASSERT(0); // we should never go there return 0; } } + +/* + Make temporary table field according collected information about type + of UNION result + + SYNOPSIS + Item_type_holder::make_field_by_type() + table temporary table for which we create fields + + RETURN + created field +*/ + +Field *Item_type_holder::make_field_by_type(TABLE *table) +{ + if (fld_type == MYSQL_TYPE_ENUM || fld_type == MYSQL_TYPE_SET) + { + DBUG_ASSERT(enum_set_typelib); + /* + The field functions defines a field to be not null if null_ptr is not 0 + */ + uchar *null_ptr= maybe_null ? (uchar*) "" : 0; + + if (fld_type == MYSQL_TYPE_ENUM) + return new Field_enum((char *) 0, max_length, null_ptr, 0, + Field::NONE, name, + table, get_enum_pack_length(enum_set_typelib->count), + enum_set_typelib, collation.collation); + else + return new Field_set((char *) 0, max_length, null_ptr, 0, + Field::NONE, name, + table, get_set_pack_length(enum_set_typelib->count), + enum_set_typelib, collation.collation); + } + return tmp_table_field_from_field_type(table); +} + + +/* + Get full information from Item about enum/set fields to be able to create + them later + + SYNOPSIS + Item_type_holder::get_full_info + item Item for information collection +*/ +void Item_type_holder::get_full_info(Item *item) +{ + if (fld_type == MYSQL_TYPE_ENUM || + fld_type == MYSQL_TYPE_SET) + { + /* + We can have enum/set type after merging only if we have one enum/set + field and number of NULL fields + */ + DBUG_ASSERT((enum_set_typelib && + get_real_type(item) == MYSQL_TYPE_NULL) || + (!enum_set_typelib && + item->type() == Item::FIELD_ITEM && + (get_real_type(item) == MYSQL_TYPE_ENUM || + get_real_type(item) == MYSQL_TYPE_SET) && + ((Field_enum*)((Item_field *) item)->field)->typelib)); + if (!enum_set_typelib) + { + enum_set_typelib= ((Field_enum*)((Item_field *) item)->field)->typelib; + } + } +} + + double Item_type_holder::val() { DBUG_ASSERT(0); // should never be called diff --git a/sql/item.h b/sql/item.h index 78de2a1f58e..20e8759a47c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1321,32 +1321,32 @@ public: /* - Used to store type. name, length of Item for UNIONS & derived table + Item_type_holder used to store type. name, length of Item for UNIONS & + derived tables. + + Item_type_holder do not need cleanup() because its time of live limited by + single SP/PS execution. */ class Item_type_holder: public Item { protected: - Item_result item_type; - Item_result orig_type; - Field *field_example; + TYPELIB *enum_set_typelib; + enum_field_types fld_type; + + void get_full_info(Item *item); public: - Item_type_holder(THD*, Item*, TABLE *); + Item_type_holder(THD*, Item*); - Item_result result_type () const { return item_type; } + Item_result result_type() const; + virtual enum_field_types field_type() const { return fld_type; }; enum Type type() const { return TYPE_HOLDER; } double val(); longlong val_int(); String *val_str(String*); - bool join_types(THD *thd, Item *, TABLE *); - Field *example() { return field_example; } - static uint32 real_length(Item *item); - void cleanup() - { - DBUG_ENTER("Item_type_holder::cleanup"); - Item::cleanup(); - item_type= orig_type; - DBUG_VOID_RETURN; - } + bool join_types(THD *thd, Item *); + Field *make_field_by_type(TABLE *table); + static uint32 display_length(Item *item); + static enum_field_types get_real_type(Item *); }; diff --git a/sql/item_func.h b/sql/item_func.h index 2738c7419ca..7cd82dc7c10 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -51,7 +51,7 @@ public: SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC, SP_STARTPOINT,SP_ENDPOINT,SP_EXTERIORRING, SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN, - NOT_FUNC, NOT_ALL_FUNC, NOW_FUNC}; + NOT_FUNC, NOT_ALL_FUNC, NOW_FUNC, VAR_VALUE_FUNC}; enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL }; enum Type type() const { return FUNC_ITEM; } virtual enum Functype functype() const { return UNKNOWN_FUNC; } @@ -980,6 +980,7 @@ public: select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b) */ enum_field_types field_type() const { return MYSQL_TYPE_STRING; } + enum Functype functype() const { return VAR_VALUE_FUNC; } const char *func_name() const { return "get_user_var"; } bool const_item() const; table_map used_tables() const diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 97daa4d700c..5ecd5617a3c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1235,7 +1235,7 @@ int subselect_single_select_engine::prepare() int subselect_union_engine::prepare() { - return unit->prepare(thd, result, SELECT_NO_UNLOCK); + return unit->prepare(thd, result, SELECT_NO_UNLOCK, ""); } int subselect_uniquesubquery_engine::prepare() diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 3e627243b9f..e9f9b432c21 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -123,7 +123,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, DBUG_RETURN(1); // out of memory // st_select_lex_unit::prepare correctly work for single select - if ((res= unit->prepare(thd, derived_result, 0))) + if ((res= unit->prepare(thd, derived_result, 0, org_table_list->alias))) goto exit; @@ -161,7 +161,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, if (is_union) { // execute union without clean up - if (!(res= unit->prepare(thd, derived_result, SELECT_NO_UNLOCK))) + if (!(res= unit->prepare(thd, derived_result, SELECT_NO_UNLOCK, ""))) res= unit->exec(); } else diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f48ff42bbf8..927982e444f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -389,7 +389,8 @@ public: void exclude_tree(); /* UNION methods */ - int prepare(THD *thd, select_result *result, ulong additional_options); + int prepare(THD *thd, select_result *result, ulong additional_options, + const char *tmp_table_alias); int exec(); int cleanup(); inline void unclean() { cleaned= 0; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 10d6ddc3f98..17c5cfbc01b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4539,9 +4539,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, net_printf(thd,ER_TOO_BIG_SET,field_name); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } - new_field->pack_length= (interval_list->elements + 7) / 8; - if (new_field->pack_length > 4) - new_field->pack_length=8; + new_field->pack_length= get_set_pack_length(interval_list->elements); List_iterator<String> it(*interval_list); String *tmp; @@ -4558,7 +4556,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, case FIELD_TYPE_ENUM: { // Should be safe - new_field->pack_length= interval_list->elements < 256 ? 1 : 2; + new_field->pack_length= get_enum_pack_length(interval_list->elements); List_iterator<String> it(*interval_list); String *tmp; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 1dc46aef4da..b57f88ac172 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1079,7 +1079,7 @@ static int mysql_test_select(Prepared_statement *stmt, thd->used_tables= 0; // Updated by setup_fields // JOIN::prepare calls - if (unit->prepare(thd, 0, 0)) + if (unit->prepare(thd, 0, 0, "")) { send_error(thd); goto err_prep; @@ -1228,7 +1228,7 @@ static int select_like_statement_test(Prepared_statement *stmt, thd->used_tables= 0; // Updated by setup_fields // JOIN::prepare calls - if (lex->unit.prepare(thd, 0, 0)) + if (lex->unit.prepare(thd, 0, 0, "")) { res= thd->net.report_error ? -1 : 1; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b00f9e422a1..f91e591a14a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4836,14 +4836,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, return create_tmp_field_from_item(thd, item, table, copy_func, modify_item, convert_blob_length); case Item::TYPE_HOLDER: - { - Field *example= ((Item_type_holder *)item)->example(); - if (example) - return create_tmp_field_from_field(thd, example, item, table, 0, - convert_blob_length); - return create_tmp_field_from_item(thd, item, table, copy_func, 0, - convert_blob_length); - } + return ((Item_type_holder *)item)->make_field_by_type(table); default: // Dosen't have to be stored return 0; } @@ -5340,8 +5333,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, if (create_myisam_tmp_table(table,param,select_options)) goto err; } - /* Set table_name for easier debugging */ - table->table_name= base_name(tmpname); if (!open_tmp_table(table)) DBUG_RETURN(table); @@ -9525,7 +9516,8 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization unit->fake_select_lex->type= "UNION RESULT"; unit->fake_select_lex->options|= SELECT_DESCRIBE; - if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE))) + if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE, + ""))) res= unit->exec(); res|= unit->cleanup(); } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 5fd59500ace..57479d6f64f 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -29,7 +29,7 @@ int mysql_union(THD *thd, LEX *lex, select_result *result, { DBUG_ENTER("mysql_union"); int res= 0; - if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK))) + if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK, ""))) res= unit->exec(); res|= unit->cleanup(); DBUG_RETURN(res); @@ -142,7 +142,8 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd) int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, - ulong additional_options) + ulong additional_options, + const char *tmp_table_alias) { SELECT_LEX *lex_select_save= thd_arg->lex->current_select; SELECT_LEX *sl, *first_select; @@ -252,7 +253,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, while ((item_tmp= it++)) { /* Error's in 'new' will be detected after loop */ - types.push_back(new Item_type_holder(thd_arg, item_tmp, empty_table)); + types.push_back(new Item_type_holder(thd_arg, item_tmp)); } if (thd_arg->is_fatal_error) @@ -271,8 +272,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, Item *type, *item_tmp; while ((type= tp++, item_tmp= it++)) { - if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp, - empty_table)) + if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp)) DBUG_RETURN(-1); } } @@ -304,7 +304,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, (first_select_in_union()->options | thd_arg->options | TMP_TABLE_ALL_COLUMNS), - HA_POS_ERROR, (char*) ""))) + HA_POS_ERROR, (char *) tmp_table_alias))) goto err; table->file->extra(HA_EXTRA_WRITE_CACHE); table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); |