diff options
-rw-r--r-- | mysql-test/r/create.result | 24 | ||||
-rw-r--r-- | mysql-test/r/func_weight_string.result | 2 | ||||
-rw-r--r-- | mysql-test/r/gis.result | 2 | ||||
-rw-r--r-- | mysql-test/r/null.result | 304 | ||||
-rw-r--r-- | mysql-test/r/union.result | 22 | ||||
-rw-r--r-- | mysql-test/suite/innodb_gis/r/1.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/innodb_gis/r/gis.result | 2 | ||||
-rw-r--r-- | mysql-test/t/create.test | 16 | ||||
-rw-r--r-- | mysql-test/t/null.test | 135 | ||||
-rw-r--r-- | mysql-test/t/union.test | 16 | ||||
-rw-r--r-- | sql/field.cc | 65 | ||||
-rw-r--r-- | sql/field.h | 25 | ||||
-rw-r--r-- | sql/item.cc | 125 | ||||
-rw-r--r-- | sql/item.h | 25 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 2 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 2 | ||||
-rw-r--r-- | sql/item_func.cc | 4 | ||||
-rw-r--r-- | sql/item_func.h | 18 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 13 | ||||
-rw-r--r-- | sql/item_geofunc.h | 3 | ||||
-rw-r--r-- | sql/item_sum.cc | 20 | ||||
-rw-r--r-- | sql/item_timefunc.h | 4 | ||||
-rw-r--r-- | sql/sql_select.cc | 10 | ||||
-rw-r--r-- | sql/sql_show.cc | 2 | ||||
-rw-r--r-- | sql/sql_table.cc | 2 | ||||
-rw-r--r-- | sql/sql_type.cc | 459 | ||||
-rw-r--r-- | sql/sql_type.h | 186 |
27 files changed, 1213 insertions, 277 deletions
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 1f032faaa40..1a3289b2618 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -488,13 +488,35 @@ d date YES NULL e varchar(1) YES NULL f datetime YES NULL g time YES NULL -h longblob YES NULL +h blob YES NULL dd time YES NULL 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; +CREATE TABLE t1 ( +c_tinytext tinytext, +c_text text, +c_mediumtext mediumtext, +c_longtext longtext +); +CREATE TABLE t2 AS SELECT +ifnull(c_tinytext, CAST('yet another binary data' AS BINARY)), +ifnull(c_text, CAST('yet another binary data' AS BINARY)), +ifnull(c_mediumtext, CAST('yet another binary data' AS BINARY)), +ifnull(c_longtext, CAST('yet another binary data' AS BINARY)) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `ifnull(c_tinytext, CAST('yet another binary data' AS BINARY))` tinyblob DEFAULT NULL, + `ifnull(c_text, CAST('yet another binary data' AS BINARY))` blob DEFAULT NULL, + `ifnull(c_mediumtext, CAST('yet another binary data' AS BINARY))` mediumblob DEFAULT NULL, + `ifnull(c_longtext, CAST('yet another binary data' AS BINARY))` longblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +DROP TABLE t1; create table t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float(3,2), g double(4,3), h decimal(5,4), i year, j date, k timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, l datetime, m enum('a','b'), n set('a','b'), o char(10)); create table t2 select ifnull(a,a), ifnull(b,b), ifnull(c,c), ifnull(d,d), ifnull(e,e), ifnull(f,f), ifnull(g,g), ifnull(h,h), ifnull(i,i), ifnull(j,j), ifnull(k,k), ifnull(l,l), ifnull(m,m), ifnull(n,n), ifnull(o,o) from t1; show create table t2; diff --git a/mysql-test/r/func_weight_string.result b/mysql-test/r/func_weight_string.result index 04fd9962218..5fa78c861a9 100644 --- a/mysql-test/r/func_weight_string.result +++ b/mysql-test/r/func_weight_string.result @@ -57,7 +57,7 @@ create table t1 select weight_string(repeat('t',66000)) as w; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `w` longblob DEFAULT NULL + `w` mediumblob DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; select weight_string(NULL); diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 77150ee3142..43de7d2e7d6 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -709,7 +709,7 @@ def test t1 t1 g g 255 4294967295 0 Y 144 0 63 g select asbinary(g) from t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def asbinary(g) 252 4294967295 0 Y 128 0 63 +def asbinary(g) 251 4294967295 0 Y 128 0 63 asbinary(g) drop table t1; create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index 0ff5c3243d8..8bbdfb2f90b 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -575,8 +575,14 @@ c_float FLOAT, c_double DOUBLE, c_decimal103 DECIMAL(10,3), c_varchar10 VARCHAR(10), +c_tinytext TINYTEXT, c_text TEXT, +c_mediumtext MEDIUMTEXT, +c_longtext LONGTEXT, +c_tinyblob TINYBLOB, c_blob BLOB, +c_mediumblob MEDIUMBLOB, +c_longblob LONGBLOB, c_enum ENUM('one','two','tree'), c_datetime3 DATETIME(3), c_timestamp3 TIMESTAMP(3), @@ -899,6 +905,45 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; CREATE TABLE t2 AS SELECT +NULLIF(c_tinytext, 1), +NULLIF(c_tinytext, c_smallint), +NULLIF(c_tinytext, c_tinyint), +NULLIF(c_tinytext, c_int), +NULLIF(c_tinytext, c_bigint), +NULLIF(c_tinytext, c_float), +NULLIF(c_tinytext, c_double), +NULLIF(c_tinytext, c_decimal103), +NULLIF(c_tinytext, c_varchar10), +NULLIF(c_tinytext, c_text), +NULLIF(c_tinytext, c_blob), +NULLIF(c_tinytext, c_enum), +NULLIF(c_tinytext, c_datetime3), +NULLIF(c_tinytext, c_timestamp3), +NULLIF(c_tinytext, c_date), +NULLIF(c_tinytext, c_time) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `NULLIF(c_tinytext, 1)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_smallint)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_tinyint)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_int)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_bigint)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_float)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_double)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_decimal103)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_varchar10)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_text)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_blob)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_enum)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_datetime3)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_timestamp3)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_date)` tinytext DEFAULT NULL, + `NULLIF(c_tinytext, c_time)` tinytext DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +CREATE TABLE t2 AS SELECT NULLIF(c_text, 1), NULLIF(c_text, c_smallint), NULLIF(c_text, c_tinyint), @@ -919,22 +964,139 @@ FROM t1; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( - `NULLIF(c_text, 1)` longtext DEFAULT NULL, - `NULLIF(c_text, c_smallint)` longtext DEFAULT NULL, - `NULLIF(c_text, c_tinyint)` longtext DEFAULT NULL, - `NULLIF(c_text, c_int)` longtext DEFAULT NULL, - `NULLIF(c_text, c_bigint)` longtext DEFAULT NULL, - `NULLIF(c_text, c_float)` longtext DEFAULT NULL, - `NULLIF(c_text, c_double)` longtext DEFAULT NULL, - `NULLIF(c_text, c_decimal103)` longtext DEFAULT NULL, - `NULLIF(c_text, c_varchar10)` longtext DEFAULT NULL, - `NULLIF(c_text, c_text)` longtext DEFAULT NULL, - `NULLIF(c_text, c_blob)` longtext DEFAULT NULL, - `NULLIF(c_text, c_enum)` longtext DEFAULT NULL, - `NULLIF(c_text, c_datetime3)` longtext DEFAULT NULL, - `NULLIF(c_text, c_timestamp3)` longtext DEFAULT NULL, - `NULLIF(c_text, c_date)` longtext DEFAULT NULL, - `NULLIF(c_text, c_time)` longtext DEFAULT NULL + `NULLIF(c_text, 1)` text DEFAULT NULL, + `NULLIF(c_text, c_smallint)` text DEFAULT NULL, + `NULLIF(c_text, c_tinyint)` text DEFAULT NULL, + `NULLIF(c_text, c_int)` text DEFAULT NULL, + `NULLIF(c_text, c_bigint)` text DEFAULT NULL, + `NULLIF(c_text, c_float)` text DEFAULT NULL, + `NULLIF(c_text, c_double)` text DEFAULT NULL, + `NULLIF(c_text, c_decimal103)` text DEFAULT NULL, + `NULLIF(c_text, c_varchar10)` text DEFAULT NULL, + `NULLIF(c_text, c_text)` text DEFAULT NULL, + `NULLIF(c_text, c_blob)` text DEFAULT NULL, + `NULLIF(c_text, c_enum)` text DEFAULT NULL, + `NULLIF(c_text, c_datetime3)` text DEFAULT NULL, + `NULLIF(c_text, c_timestamp3)` text DEFAULT NULL, + `NULLIF(c_text, c_date)` text DEFAULT NULL, + `NULLIF(c_text, c_time)` text DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +CREATE TABLE t2 AS SELECT +NULLIF(c_mediumtext, 1), +NULLIF(c_mediumtext, c_smallint), +NULLIF(c_mediumtext, c_tinyint), +NULLIF(c_mediumtext, c_int), +NULLIF(c_mediumtext, c_bigint), +NULLIF(c_mediumtext, c_float), +NULLIF(c_mediumtext, c_double), +NULLIF(c_mediumtext, c_decimal103), +NULLIF(c_mediumtext, c_varchar10), +NULLIF(c_mediumtext, c_text), +NULLIF(c_mediumtext, c_blob), +NULLIF(c_mediumtext, c_enum), +NULLIF(c_mediumtext, c_datetime3), +NULLIF(c_mediumtext, c_timestamp3), +NULLIF(c_mediumtext, c_date), +NULLIF(c_mediumtext, c_time) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `NULLIF(c_mediumtext, 1)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_smallint)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_tinyint)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_int)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_bigint)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_float)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_double)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_decimal103)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_varchar10)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_text)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_blob)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_enum)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_datetime3)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_timestamp3)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_date)` mediumtext DEFAULT NULL, + `NULLIF(c_mediumtext, c_time)` mediumtext DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +CREATE TABLE t2 AS SELECT +NULLIF(c_longtext, 1), +NULLIF(c_longtext, c_smallint), +NULLIF(c_longtext, c_tinyint), +NULLIF(c_longtext, c_int), +NULLIF(c_longtext, c_bigint), +NULLIF(c_longtext, c_float), +NULLIF(c_longtext, c_double), +NULLIF(c_longtext, c_decimal103), +NULLIF(c_longtext, c_varchar10), +NULLIF(c_longtext, c_text), +NULLIF(c_longtext, c_blob), +NULLIF(c_longtext, c_enum), +NULLIF(c_longtext, c_datetime3), +NULLIF(c_longtext, c_timestamp3), +NULLIF(c_longtext, c_date), +NULLIF(c_longtext, c_time) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `NULLIF(c_longtext, 1)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_smallint)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_tinyint)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_int)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_bigint)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_float)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_double)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_decimal103)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_varchar10)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_text)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_blob)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_enum)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_datetime3)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_timestamp3)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_date)` longtext DEFAULT NULL, + `NULLIF(c_longtext, c_time)` longtext DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +CREATE TABLE t2 AS SELECT +NULLIF(c_tinyblob, 1), +NULLIF(c_tinyblob, c_smallint), +NULLIF(c_tinyblob, c_tinyint), +NULLIF(c_tinyblob, c_int), +NULLIF(c_tinyblob, c_bigint), +NULLIF(c_tinyblob, c_float), +NULLIF(c_tinyblob, c_double), +NULLIF(c_tinyblob, c_decimal103), +NULLIF(c_tinyblob, c_varchar10), +NULLIF(c_tinyblob, c_text), +NULLIF(c_tinyblob, c_blob), +NULLIF(c_tinyblob, c_enum), +NULLIF(c_tinyblob, c_datetime3), +NULLIF(c_tinyblob, c_timestamp3), +NULLIF(c_tinyblob, c_date), +NULLIF(c_tinyblob, c_time) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `NULLIF(c_tinyblob, 1)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_smallint)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_tinyint)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_int)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_bigint)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_float)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_double)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_decimal103)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_varchar10)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_text)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_blob)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_enum)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_datetime3)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_timestamp3)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_date)` tinyblob DEFAULT NULL, + `NULLIF(c_tinyblob, c_time)` tinyblob DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; CREATE TABLE t2 AS SELECT @@ -958,22 +1120,100 @@ FROM t1; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( - `NULLIF(c_blob, 1)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_smallint)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_tinyint)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_int)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_bigint)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_float)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_double)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_decimal103)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_varchar10)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_text)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_blob)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_enum)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_datetime3)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_timestamp3)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_date)` longblob DEFAULT NULL, - `NULLIF(c_blob, c_time)` longblob DEFAULT NULL + `NULLIF(c_blob, 1)` blob DEFAULT NULL, + `NULLIF(c_blob, c_smallint)` blob DEFAULT NULL, + `NULLIF(c_blob, c_tinyint)` blob DEFAULT NULL, + `NULLIF(c_blob, c_int)` blob DEFAULT NULL, + `NULLIF(c_blob, c_bigint)` blob DEFAULT NULL, + `NULLIF(c_blob, c_float)` blob DEFAULT NULL, + `NULLIF(c_blob, c_double)` blob DEFAULT NULL, + `NULLIF(c_blob, c_decimal103)` blob DEFAULT NULL, + `NULLIF(c_blob, c_varchar10)` blob DEFAULT NULL, + `NULLIF(c_blob, c_text)` blob DEFAULT NULL, + `NULLIF(c_blob, c_blob)` blob DEFAULT NULL, + `NULLIF(c_blob, c_enum)` blob DEFAULT NULL, + `NULLIF(c_blob, c_datetime3)` blob DEFAULT NULL, + `NULLIF(c_blob, c_timestamp3)` blob DEFAULT NULL, + `NULLIF(c_blob, c_date)` blob DEFAULT NULL, + `NULLIF(c_blob, c_time)` blob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +CREATE TABLE t2 AS SELECT +NULLIF(c_mediumblob, 1), +NULLIF(c_mediumblob, c_smallint), +NULLIF(c_mediumblob, c_tinyint), +NULLIF(c_mediumblob, c_int), +NULLIF(c_mediumblob, c_bigint), +NULLIF(c_mediumblob, c_float), +NULLIF(c_mediumblob, c_double), +NULLIF(c_mediumblob, c_decimal103), +NULLIF(c_mediumblob, c_varchar10), +NULLIF(c_mediumblob, c_text), +NULLIF(c_mediumblob, c_blob), +NULLIF(c_mediumblob, c_enum), +NULLIF(c_mediumblob, c_datetime3), +NULLIF(c_mediumblob, c_timestamp3), +NULLIF(c_mediumblob, c_date), +NULLIF(c_mediumblob, c_time) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `NULLIF(c_mediumblob, 1)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_smallint)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_tinyint)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_int)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_bigint)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_float)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_double)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_decimal103)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_varchar10)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_text)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_blob)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_enum)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_datetime3)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_timestamp3)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_date)` mediumblob DEFAULT NULL, + `NULLIF(c_mediumblob, c_time)` mediumblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +CREATE TABLE t2 AS SELECT +NULLIF(c_longblob, 1), +NULLIF(c_longblob, c_smallint), +NULLIF(c_longblob, c_tinyint), +NULLIF(c_longblob, c_int), +NULLIF(c_longblob, c_bigint), +NULLIF(c_longblob, c_float), +NULLIF(c_longblob, c_double), +NULLIF(c_longblob, c_decimal103), +NULLIF(c_longblob, c_varchar10), +NULLIF(c_longblob, c_text), +NULLIF(c_longblob, c_blob), +NULLIF(c_longblob, c_enum), +NULLIF(c_longblob, c_datetime3), +NULLIF(c_longblob, c_timestamp3), +NULLIF(c_longblob, c_date), +NULLIF(c_longblob, c_time) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `NULLIF(c_longblob, 1)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_smallint)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_tinyint)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_int)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_bigint)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_float)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_double)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_decimal103)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_varchar10)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_text)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_blob)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_enum)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_datetime3)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_timestamp3)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_date)` longblob DEFAULT NULL, + `NULLIF(c_longblob, c_time)` longblob DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; CREATE TABLE t2 AS SELECT diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index fe456e2aa80..807a194e773 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1449,6 +1449,28 @@ t2 CREATE TABLE `t2` ( `f8` mediumtext CHARACTER SET utf8 DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1, t2; +CREATE TABLE t1 +( +c_varchar varchar(1) character set utf8 collate utf8_general_ci, +c_tinytext tinytext, +c_text text, +c_mediumtext mediumtext, +c_longtext longtext +); +CREATE TABLE t2 AS +SELECT c_tinytext, c_text, c_mediumtext, c_longtext FROM t1 +UNION +SELECT c_varchar, c_varchar, c_varchar, c_varchar FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c_tinytext` text CHARACTER SET utf8 DEFAULT NULL, + `c_text` mediumtext CHARACTER SET utf8 DEFAULT NULL, + `c_mediumtext` longtext CHARACTER SET utf8 DEFAULT NULL, + `c_longtext` longtext CHARACTER SET utf8 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +DROP TABLE t1; (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union diff --git a/mysql-test/suite/innodb_gis/r/1.result b/mysql-test/suite/innodb_gis/r/1.result index 31579a18ea0..3ab57babc43 100644 --- a/mysql-test/suite/innodb_gis/r/1.result +++ b/mysql-test/suite/innodb_gis/r/1.result @@ -681,7 +681,7 @@ def test t1 t1 g g 255 4294967295 0 Y 144 0 63 g select ST_asbinary(g) from t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def ST_asbinary(g) 252 4294967295 0 Y 128 0 63 +def ST_asbinary(g) 251 4294967295 0 Y 128 0 63 ST_asbinary(g) drop table t1; create table t1 (a TEXT, b GEOMETRY NOT NULL, INDEX(b(5))); diff --git a/mysql-test/suite/innodb_gis/r/gis.result b/mysql-test/suite/innodb_gis/r/gis.result index 4257413f816..beb411505f9 100644 --- a/mysql-test/suite/innodb_gis/r/gis.result +++ b/mysql-test/suite/innodb_gis/r/gis.result @@ -681,7 +681,7 @@ def test t1 t1 g g 255 4294967295 0 Y 144 0 63 g select ST_asbinary(g) from t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def ST_asbinary(g) 252 4294967295 0 Y 128 0 63 +def ST_asbinary(g) 251 4294967295 0 Y 128 0 63 ST_asbinary(g) drop table t1; create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 6461204f06e..bd89f220060 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -402,6 +402,22 @@ explain t2; select * from t2; drop table t1, t2; +CREATE TABLE t1 ( + c_tinytext tinytext, + c_text text, + c_mediumtext mediumtext, + c_longtext longtext +); +CREATE TABLE t2 AS SELECT + ifnull(c_tinytext, CAST('yet another binary data' AS BINARY)), + ifnull(c_text, CAST('yet another binary data' AS BINARY)), + ifnull(c_mediumtext, CAST('yet another binary data' AS BINARY)), + ifnull(c_longtext, CAST('yet another binary data' AS BINARY)) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; + create table t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float(3,2), g double(4,3), h decimal(5,4), i year, j date, k timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, l datetime, m enum('a','b'), n set('a','b'), o char(10)); create table t2 select ifnull(a,a), ifnull(b,b), ifnull(c,c), ifnull(d,d), ifnull(e,e), ifnull(f,f), ifnull(g,g), ifnull(h,h), ifnull(i,i), ifnull(j,j), ifnull(k,k), ifnull(l,l), ifnull(m,m), ifnull(n,n), ifnull(o,o) from t1; show create table t2; diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test index 3de35a74a73..403790356ce 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -414,8 +414,14 @@ CREATE TABLE t1 c_double DOUBLE, c_decimal103 DECIMAL(10,3), c_varchar10 VARCHAR(10), + c_tinytext TINYTEXT, c_text TEXT, + c_mediumtext MEDIUMTEXT, + c_longtext LONGTEXT, + c_tinyblob TINYBLOB, c_blob BLOB, + c_mediumblob MEDIUMBLOB, + c_longblob LONGBLOB, c_enum ENUM('one','two','tree'), c_datetime3 DATETIME(3), c_timestamp3 TIMESTAMP(3), @@ -597,6 +603,27 @@ SHOW CREATE TABLE t2; DROP TABLE t2; CREATE TABLE t2 AS SELECT + NULLIF(c_tinytext, 1), + NULLIF(c_tinytext, c_smallint), + NULLIF(c_tinytext, c_tinyint), + NULLIF(c_tinytext, c_int), + NULLIF(c_tinytext, c_bigint), + NULLIF(c_tinytext, c_float), + NULLIF(c_tinytext, c_double), + NULLIF(c_tinytext, c_decimal103), + NULLIF(c_tinytext, c_varchar10), + NULLIF(c_tinytext, c_text), + NULLIF(c_tinytext, c_blob), + NULLIF(c_tinytext, c_enum), + NULLIF(c_tinytext, c_datetime3), + NULLIF(c_tinytext, c_timestamp3), + NULLIF(c_tinytext, c_date), + NULLIF(c_tinytext, c_time) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +CREATE TABLE t2 AS SELECT NULLIF(c_text, 1), NULLIF(c_text, c_smallint), NULLIF(c_text, c_tinyint), @@ -617,7 +644,70 @@ FROM t1; SHOW CREATE TABLE t2; DROP TABLE t2; -# QQ: this should probably create BLOB instead of LONGBLOB +CREATE TABLE t2 AS SELECT + NULLIF(c_mediumtext, 1), + NULLIF(c_mediumtext, c_smallint), + NULLIF(c_mediumtext, c_tinyint), + NULLIF(c_mediumtext, c_int), + NULLIF(c_mediumtext, c_bigint), + NULLIF(c_mediumtext, c_float), + NULLIF(c_mediumtext, c_double), + NULLIF(c_mediumtext, c_decimal103), + NULLIF(c_mediumtext, c_varchar10), + NULLIF(c_mediumtext, c_text), + NULLIF(c_mediumtext, c_blob), + NULLIF(c_mediumtext, c_enum), + NULLIF(c_mediumtext, c_datetime3), + NULLIF(c_mediumtext, c_timestamp3), + NULLIF(c_mediumtext, c_date), + NULLIF(c_mediumtext, c_time) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +CREATE TABLE t2 AS SELECT + NULLIF(c_longtext, 1), + NULLIF(c_longtext, c_smallint), + NULLIF(c_longtext, c_tinyint), + NULLIF(c_longtext, c_int), + NULLIF(c_longtext, c_bigint), + NULLIF(c_longtext, c_float), + NULLIF(c_longtext, c_double), + NULLIF(c_longtext, c_decimal103), + NULLIF(c_longtext, c_varchar10), + NULLIF(c_longtext, c_text), + NULLIF(c_longtext, c_blob), + NULLIF(c_longtext, c_enum), + NULLIF(c_longtext, c_datetime3), + NULLIF(c_longtext, c_timestamp3), + NULLIF(c_longtext, c_date), + NULLIF(c_longtext, c_time) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + + +CREATE TABLE t2 AS SELECT + NULLIF(c_tinyblob, 1), + NULLIF(c_tinyblob, c_smallint), + NULLIF(c_tinyblob, c_tinyint), + NULLIF(c_tinyblob, c_int), + NULLIF(c_tinyblob, c_bigint), + NULLIF(c_tinyblob, c_float), + NULLIF(c_tinyblob, c_double), + NULLIF(c_tinyblob, c_decimal103), + NULLIF(c_tinyblob, c_varchar10), + NULLIF(c_tinyblob, c_text), + NULLIF(c_tinyblob, c_blob), + NULLIF(c_tinyblob, c_enum), + NULLIF(c_tinyblob, c_datetime3), + NULLIF(c_tinyblob, c_timestamp3), + NULLIF(c_tinyblob, c_date), + NULLIF(c_tinyblob, c_time) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + CREATE TABLE t2 AS SELECT NULLIF(c_blob, 1), NULLIF(c_blob, c_smallint), @@ -639,6 +729,49 @@ FROM t1; SHOW CREATE TABLE t2; DROP TABLE t2; +CREATE TABLE t2 AS SELECT + NULLIF(c_mediumblob, 1), + NULLIF(c_mediumblob, c_smallint), + NULLIF(c_mediumblob, c_tinyint), + NULLIF(c_mediumblob, c_int), + NULLIF(c_mediumblob, c_bigint), + NULLIF(c_mediumblob, c_float), + NULLIF(c_mediumblob, c_double), + NULLIF(c_mediumblob, c_decimal103), + NULLIF(c_mediumblob, c_varchar10), + NULLIF(c_mediumblob, c_text), + NULLIF(c_mediumblob, c_blob), + NULLIF(c_mediumblob, c_enum), + NULLIF(c_mediumblob, c_datetime3), + NULLIF(c_mediumblob, c_timestamp3), + NULLIF(c_mediumblob, c_date), + NULLIF(c_mediumblob, c_time) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +CREATE TABLE t2 AS SELECT + NULLIF(c_longblob, 1), + NULLIF(c_longblob, c_smallint), + NULLIF(c_longblob, c_tinyint), + NULLIF(c_longblob, c_int), + NULLIF(c_longblob, c_bigint), + NULLIF(c_longblob, c_float), + NULLIF(c_longblob, c_double), + NULLIF(c_longblob, c_decimal103), + NULLIF(c_longblob, c_varchar10), + NULLIF(c_longblob, c_text), + NULLIF(c_longblob, c_blob), + NULLIF(c_longblob, c_enum), + NULLIF(c_longblob, c_datetime3), + NULLIF(c_longblob, c_timestamp3), + NULLIF(c_longblob, c_date), + NULLIF(c_longblob, c_time) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + + # QQ: this should probably create a ENUM column instead of VARCHAR(4) CREATE TABLE t2 AS SELECT NULLIF(c_enum, 1), diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index e0c011e3d20..fa07dc22dbb 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -889,6 +889,22 @@ create table t2 as select *, f6 as f8 from t1 union select *, f7 from t1; show create table t2; drop table t1, t2; +CREATE TABLE t1 +( + c_varchar varchar(1) character set utf8 collate utf8_general_ci, + c_tinytext tinytext, + c_text text, + c_mediumtext mediumtext, + c_longtext longtext +); +CREATE TABLE t2 AS +SELECT c_tinytext, c_text, c_mediumtext, c_longtext FROM t1 +UNION +SELECT c_varchar, c_varchar, c_varchar, c_varchar FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; + # # Bug#18175: Union select over 129 tables with a sum function fails. # diff --git a/sql/field.cc b/sql/field.cc index 9215a6b8e60..91efcd52b0f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2912,67 +2912,6 @@ Field_new_decimal::Field_new_decimal(uchar *ptr_arg, } -Field_new_decimal::Field_new_decimal(uint32 len_arg, - bool maybe_null_arg, - const LEX_CSTRING *name, - uint8 dec_arg, - bool unsigned_arg) - :Field_num((uchar*) 0, len_arg, - maybe_null_arg ? (uchar*) "": 0, 0, - NONE, name, dec_arg, 0, unsigned_arg) -{ - precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg); - set_if_smaller(precision, DECIMAL_MAX_PRECISION); - DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) && - (dec <= DECIMAL_MAX_SCALE)); - bin_size= my_decimal_get_binary_size(precision, dec); -} - - -Field *Field_new_decimal::create_from_item(MEM_ROOT *mem_root, Item *item) -{ - uint8 dec= item->decimals; - uint8 intg= item->decimal_precision() - dec; - uint32 len= item->max_char_length(); - DBUG_ASSERT (item->result_type() == DECIMAL_RESULT); - - /* - Trying to put too many digits overall in a DECIMAL(prec,dec) - will always throw a warning. We must limit dec to - DECIMAL_MAX_SCALE however to prevent an assert() later. - */ - - if (dec > 0) - { - signed int overflow; - - dec= MY_MIN(dec, DECIMAL_MAX_SCALE); - - /* - If the value still overflows the field with the corrected dec, - we'll throw out decimals rather than integers. This is still - bad and of course throws a truncation warning. - +1: for decimal point - */ - - const int required_length= - my_decimal_precision_to_length(intg + dec, dec, - item->unsigned_flag); - - overflow= required_length - len; - - if (overflow > 0) - dec= MY_MAX(0, dec - overflow); // too long, discard fract - else - /* Corrected value fits. */ - len= required_length; - } - return new (mem_root) - Field_new_decimal(len, item->maybe_null, &item->name, - dec, item->unsigned_flag); -} - - int Field_new_decimal::reset(void) { store_value(&decimal_zero); @@ -10717,7 +10656,7 @@ uint32 Field_blob::char_length() const case 3: return 16777215; case 4: - return (uint32) 4294967295U; + return (uint32) UINT_MAX32; default: DBUG_ASSERT(0); // we should never go here return 0; @@ -10770,7 +10709,7 @@ uint32 Field_blob::max_display_length() case 3: return 16777215 * field_charset->mbmaxlen; case 4: - return (uint32) 4294967295U; + return (uint32) UINT_MAX32; default: DBUG_ASSERT(0); // we should never go here return 0; diff --git a/sql/field.h b/sql/field.h index e62b98936b7..5f5fd83b407 100644 --- a/sql/field.h +++ b/sql/field.h @@ -971,6 +971,10 @@ public: virtual bool zero_pack() const { return 1; } virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } virtual uint32 key_length() const { return pack_length(); } + virtual const Type_handler *type_handler() const + { + return Type_handler::get_handler_by_field_type(type()); + } virtual enum_field_types type() const =0; virtual enum_field_types real_type() const { return type(); } virtual enum_field_types binlog_type() const @@ -1842,9 +1846,6 @@ public: enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, uint8 dec_arg, bool zero_arg, bool unsigned_arg); - Field_new_decimal(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, uint8 dec_arg, - bool unsigned_arg); enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } Item_result result_type () const { return DECIMAL_RESULT; } @@ -1897,7 +1898,6 @@ public: uint16 mflags, int *order_var); uint is_equal(Create_field *new_field); virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data); - static Field *create_from_item(MEM_ROOT *root, Item *); Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item); }; @@ -3231,6 +3231,15 @@ public: :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, &temp_lex_str, system_charset_info), packlength(packlength_arg) {} + const Type_handler *type_handler() const + { + switch (packlength) { + case 1: return &type_handler_tiny_blob; + case 2: return &type_handler_blob; + case 3: return &type_handler_medium_blob; + } + return &type_handler_long_blob; + } /* Note that the default copy constructor is used, in clone() */ enum_field_types type() const { return MYSQL_TYPE_BLOB;} enum ha_base_keytype key_type() const @@ -3417,11 +3426,11 @@ public: :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, share, blob_pack_length, &my_charset_bin) { geom_type= geom_type_arg; srid= field_srid; } - Field_geom(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, - TABLE_SHARE *share, enum geometry_type geom_type_arg) - :Field_blob(len_arg, maybe_null_arg, field_name_arg, &my_charset_bin) - { geom_type= geom_type_arg; srid= 0; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; } + const Type_handler *type_handler() const + { + return &type_handler_geometry; + } enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; } bool can_optimize_range(const Item_bool_func *cond, const Item *item, diff --git a/sql/item.cc b/sql/item.cc index 1889ecd6f39..307c299e410 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -518,7 +518,7 @@ Item::Item(THD *thd): tables. */ Item::Item(THD *thd, Item *item): - Type_std_attributes(item), + Type_all_attributes(item), join_tab_idx(item->join_tab_idx), is_expensive_cache(-1), rsize(0), @@ -5854,6 +5854,8 @@ const Type_handler *Item_field::real_type_handler() const // TODO: We should add Field::real_type_handler() eventually if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING) type= MYSQL_TYPE_VAR_STRING; + else if (type == MYSQL_TYPE_BLOB) + return field->type_handler(); return Type_handler::get_handler_by_real_type(type); } @@ -6276,122 +6278,23 @@ Field *Item::make_string_field(TABLE *table) \# Created field */ -Field *Item::tmp_table_field_from_field_type(TABLE *table, - bool fixed_length, - bool set_blob_packlength) +Field *Item::tmp_table_field_from_field_type(TABLE *table) { - /* - The field functions defines a field to be not null if null_ptr is not 0 - */ - uchar *null_ptr= maybe_null ? (uchar*) "" : 0; - Field *field; - MEM_ROOT *mem_root= table->in_use->mem_root; + const Type_handler *handler= type_handler(); + Record_addr addr(maybe_null); - switch (field_type()) { - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - field= Field_new_decimal::create_from_item(mem_root, this); - break; - case MYSQL_TYPE_TINY: - field= new (mem_root) - Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE, - &name, 0, unsigned_flag); - break; - case MYSQL_TYPE_SHORT: - field= new (mem_root) - Field_short((uchar*) 0, max_length, null_ptr, 0, Field::NONE, - &name, 0, unsigned_flag); - break; - case MYSQL_TYPE_LONG: - field= new (mem_root) - Field_long((uchar*) 0, max_length, null_ptr, 0, Field::NONE, - &name, 0, unsigned_flag); - break; -#ifdef HAVE_LONG_LONG - case MYSQL_TYPE_LONGLONG: - field= new (mem_root) - Field_longlong((uchar*) 0, max_length, null_ptr, 0, Field::NONE, - &name, 0, unsigned_flag); - break; -#endif - case MYSQL_TYPE_FLOAT: - field= new (mem_root) - Field_float((uchar*) 0, max_length, null_ptr, 0, Field::NONE, - &name, decimals, 0, unsigned_flag); - break; - case MYSQL_TYPE_DOUBLE: - field= new (mem_root) - Field_double((uchar*) 0, max_length, null_ptr, 0, Field::NONE, - &name, decimals, 0, unsigned_flag); - break; - case MYSQL_TYPE_INT24: - field= new (mem_root) - Field_medium((uchar*) 0, max_length, null_ptr, 0, Field::NONE, - &name, 0, unsigned_flag); - break; - case MYSQL_TYPE_NEWDATE: - case MYSQL_TYPE_DATE: - field= new (mem_root) - Field_newdate(0, null_ptr, 0, Field::NONE, &name); - break; - case MYSQL_TYPE_TIME: - field= new_Field_time(mem_root, 0, null_ptr, 0, Field::NONE, &name, - decimals); - break; - case MYSQL_TYPE_TIMESTAMP: - field= new_Field_timestamp(mem_root, 0, null_ptr, 0, - Field::NONE, &name, 0, decimals); - break; - case MYSQL_TYPE_DATETIME: - field= new_Field_datetime(mem_root, 0, null_ptr, 0, Field::NONE, - &name, decimals); - break; - case MYSQL_TYPE_YEAR: - field= new (mem_root) - Field_year((uchar*) 0, max_length, null_ptr, 0, Field::NONE, - &name); - break; - case MYSQL_TYPE_BIT: - field= new (mem_root) - Field_bit_as_char(NULL, max_length, null_ptr, 0, Field::NONE, - &name); - break; - default: - /* This case should never be chosen */ - DBUG_ASSERT(0); - /* If something goes awfully wrong, it's better to get a string than die */ + switch (handler->field_type()) { case MYSQL_TYPE_NULL: case MYSQL_TYPE_STRING: - if (fixed_length && !too_big_for_varchar()) - { - field= new (mem_root) - Field_string(max_length, maybe_null, &name, collation.collation); - break; - } - /* Fall through to make_string_field() */ case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VARCHAR: return make_string_field(table); - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - field= new (mem_root) - Field_blob(max_length, maybe_null, &name, - collation.collation, set_blob_packlength); - break; // Blob handled outside of case -#ifdef HAVE_SPATIAL - case MYSQL_TYPE_GEOMETRY: - field= new (mem_root) - Field_geom(max_length, maybe_null, &name, table->s, - get_geometry_type()); -#endif /* HAVE_SPATIAL */ + default: + break; } - if (field) - field->init(table); - return field; + return handler->make_and_init_table_field(&name, addr, *this, table); } @@ -10423,10 +10326,16 @@ Field *Item_type_holder::make_field_by_type(TABLE *table) } case MYSQL_TYPE_NULL: return make_string_field(table); + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + set_handler(Type_handler::blob_type_handler(max_length)); + break; default: break; } - return tmp_table_field_from_field_type(table, false, true); + return tmp_table_field_from_field_type(table); } diff --git a/sql/item.h b/sql/item.h index e3d6c4e365f..0d4dbf77d6d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -483,7 +483,7 @@ public: class Item: public Value_source, - public Type_std_attributes + public Type_all_attributes { void operator=(Item &); /** @@ -537,9 +537,7 @@ protected: SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param); virtual Field *make_string_field(TABLE *table); - Field *tmp_table_field_from_field_type(TABLE *table, - bool fixed_length, - bool set_blob_packlength); + Field *tmp_table_field_from_field_type(TABLE *table); Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length); void push_note_converted_to_negative_complement(THD *thd); @@ -1744,6 +1742,8 @@ public: } virtual Field::geometry_type get_geometry_type() const { return Field::GEOM_GEOMETRY; }; + uint uint_geometry_type() const + { return get_geometry_type(); } String *check_well_formed_result(String *str, bool send_error= 0); bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs); bool too_big_for_varchar() const @@ -2262,7 +2262,7 @@ public: based on result_type(), which is less exact. */ Field *create_field_for_create_select(TABLE *table) - { return tmp_table_field_from_field_type(table, false, true); } + { return tmp_table_field_from_field_type(table); } }; @@ -2638,6 +2638,10 @@ public: fast_field_copier setup_fast_field_copier(Field *field); table_map used_tables() const; table_map all_used_tables() const; + const Type_handler *type_handler() const + { + return field->type_handler(); + } enum Item_result result_type () const { return field->result_type(); @@ -3637,7 +3641,14 @@ public: Item_partition_func_safe_string(thd, name_arg, safe_strlen(name_arg), &my_charset_bin) { max_length= length; } enum Type type() const { return TYPE_HOLDER; } - enum_field_types field_type() const { return MYSQL_TYPE_BLOB; } + enum_field_types field_type() const + { + return Item_blob::type_handler()->field_type(); + } + const Type_handler *type_handler() const + { + return Type_handler::blob_type_handler(max_length); + } const Type_handler *real_type_handler() const { // Should not be called, Item_blob is used for SHOW purposes only. @@ -3645,7 +3656,7 @@ public: return &type_handler_varchar; } Field *create_field_for_schema(THD *thd, TABLE *table) - { return tmp_table_field_from_field_type(table, false, true); } + { return tmp_table_field_from_field_type(table); } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 6d2135db91e..6712b98dbc3 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2577,7 +2577,7 @@ Item_func_nullif::fix_length_and_dec() thd->change_item_tree(&args[0], m_cache); thd->change_item_tree(&args[2], m_cache); } - set_handler_by_field_type(args[2]->field_type()); + set_handler(args[2]->type_handler()); collation.set(args[2]->collation); decimals= args[2]->decimals; unsigned_flag= args[2]->unsigned_flag; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a94105b352d..6a6adb28ebd 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1057,7 +1057,7 @@ public: } const char *func_name() const { return "ifnull"; } Field *create_field_for_create_select(TABLE *table) - { return tmp_table_field_from_field_type(table, false, false); } + { return tmp_table_field_from_field_type(table); } table_map not_null_tables() const { return 0; } uint decimal_precision() const diff --git a/sql/item_func.cc b/sql/item_func.cc index 00e0c8caa07..584d387f89c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2254,8 +2254,8 @@ void Item_func_int_val::fix_length_and_dec_int_or_decimal() { ulonglong tmp_max_length= (ulonglong ) args[0]->max_length - (args[0]->decimals ? args[0]->decimals + 1 : 0) + 2; - max_length= tmp_max_length > (ulonglong) 4294967295U ? - (uint32) 4294967295U : (uint32) tmp_max_length; + max_length= tmp_max_length > (ulonglong) UINT_MAX32 ? + (uint32) UINT_MAX32 : (uint32) tmp_max_length; uint tmp= float_length(decimals); set_if_smaller(max_length,tmp); decimals= 0; diff --git a/sql/item_func.h b/sql/item_func.h index e16b3bd8fa6..4e93c93aec6 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -208,7 +208,7 @@ public: { return result_type() != STRING_RESULT ? create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) : - tmp_table_field_from_field_type(table, false, false); + tmp_table_field_from_field_type(table); } Item *get_tmp_table_item(THD *thd); @@ -2255,12 +2255,6 @@ public: bool update(); bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec(); - Field *create_field_for_create_select(TABLE *table) - { - return result_type() != STRING_RESULT ? - create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) : - tmp_table_field_from_field_type(table, false, true); - } table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; @@ -2302,6 +2296,14 @@ public: my_decimal *val_decimal(my_decimal*); String *val_str(String* str); void fix_length_and_dec(); + Field *create_field_for_create_select(TABLE *table) + { + return cmp_type() == STRING_RESULT ? + type_handler_long_blob.make_and_init_table_field(&(Item::name), + Record_addr(maybe_null), + *this, table) : + create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS); + } virtual void print(String *str, enum_query_type query_type); /* We must always return variables as strings to guard against selects of type @@ -2655,7 +2657,7 @@ public: { return result_type() != STRING_RESULT ? sp_result_field : - tmp_table_field_from_field_type(table, false, false); + tmp_table_field_from_field_type(table); } void make_field(THD *thd, Send_field *tmp_field); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index e361793f77d..8a61ab583c9 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -40,20 +40,11 @@ #include "opt_range.h" -Field *Item_geometry_func::create_field_for_create_select(TABLE *t_arg) -{ - Field *result; - if ((result= new Field_geom(max_length, maybe_null, &name, t_arg->s, - get_geometry_type()))) - result->init(t_arg); - return result; -} - void Item_geometry_func::fix_length_and_dec() { collation.set(&my_charset_bin); decimals=0; - max_length= (uint32) 4294967295U; + max_length= (uint32) UINT_MAX32; maybe_null= 1; } @@ -206,7 +197,7 @@ String *Item_func_as_wkt::val_str_ascii(String *str) void Item_func_as_wkt::fix_length_and_dec() { collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); - max_length=MAX_BLOB_WIDTH; + max_length= (uint32) UINT_MAX32; maybe_null= 1; } diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index a164f9dec89..b6a49a38743 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -40,7 +40,6 @@ public: Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {} void fix_length_and_dec(); enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } - Field *create_field_for_create_select(TABLE *table); }; class Item_func_geometry_from_text: public Item_geometry_func @@ -101,7 +100,7 @@ public: Item_func_as_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {} const char *func_name() const { return "st_aswkb"; } String *val_str(String *); - enum_field_types field_type() const { return MYSQL_TYPE_BLOB; } + enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_as_wkb>(thd, mem_root, this); } }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index d95240d6d6d..42e634b1caa 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1669,8 +1669,6 @@ Item *Item_sum_avg::copy_or_same(THD* thd) Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table) { - Field *field; - MEM_ROOT *mem_root= table->in_use->mem_root; if (group) { @@ -1679,21 +1677,15 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table) The easiest way is to do this is to store both value in a string and unpack on access. */ - field= new (mem_root) + Field *field= new (table->in_use->mem_root) Field_string(((Item_sum_avg::result_type() == DECIMAL_RESULT) ? - dec_bin_size : sizeof(double)) + sizeof(longlong), + dec_bin_size : sizeof(double)) + sizeof(longlong), 0, &name, &my_charset_bin); + if (field) + field->init(table); + return field; } - else if (Item_sum_avg::result_type() == DECIMAL_RESULT) - field= Field_new_decimal::create_from_item(mem_root, this); - else - { - field= new (mem_root) Field_double(max_length, maybe_null, &name, - decimals, TRUE); - } - if (field) - field->init(table); - return field; + return tmp_table_field_from_field_type(table); } diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 5caeea489f6..d52eeba1f15 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -536,7 +536,7 @@ public: my_decimal *val_decimal(my_decimal *decimal_value) { return val_decimal_from_date(decimal_value); } Field *create_field_for_create_select(TABLE *table) - { return tmp_table_field_from_field_type(table, false, false); } + { return tmp_table_field_from_field_type(table); } int save_in_field(Field *field, bool no_conversions) { return save_date_in_field(field, no_conversions); } }; @@ -1018,7 +1018,7 @@ class Item_extract :public Item_int_func return true; } Field *create_field_for_create_select(TABLE *table) - { return tmp_table_field_from_field_type(table, false, false); } + { return tmp_table_field_from_field_type(table); } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_extract>(thd, mem_root, this); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f82c7580469..3eecd9b2544 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15879,7 +15879,8 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length) break; } case TIME_RESULT: - new_field= tmp_table_field_from_field_type(table, true, false); + case DECIMAL_RESULT: + new_field= tmp_table_field_from_field_type(table); break; case STRING_RESULT: DBUG_ASSERT(collation.collation); @@ -15888,14 +15889,11 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length) To preserve type they needed to be handled separately. */ if (field_type() == MYSQL_TYPE_GEOMETRY) - new_field= tmp_table_field_from_field_type(table, true, false); + new_field= tmp_table_field_from_field_type(table); else new_field= make_string_field(table); new_field->set_derivation(collation.derivation, collation.repertoire); break; - case DECIMAL_RESULT: - new_field= Field_new_decimal::create_from_item(mem_root, this); - break; case ROW_RESULT: // This case should never be choosen DBUG_ASSERT(0); @@ -15980,7 +15978,7 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table) field->init(table); return field; } - return tmp_table_field_from_field_type(table, false, false); + return tmp_table_field_from_field_type(table); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2f4993f0437..1fbd631b754 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5439,7 +5439,7 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs, field->real_type() == MYSQL_TYPE_STRING) // For binary type { uint32 octet_max_length= field->max_display_length(); - if (is_blob && octet_max_length != (uint32) 4294967295U) + if (is_blob && octet_max_length != (uint32) UINT_MAX32) octet_max_length /= field->charset()->mbmaxlen; longlong char_max_len= is_blob ? (longlong) octet_max_length / field->charset()->mbminlen : diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8c05d0fa02b..5fed57fbb0d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7368,7 +7368,7 @@ blob_length_by_type(enum_field_types type) case MYSQL_TYPE_MEDIUM_BLOB: return 16777215; case MYSQL_TYPE_LONG_BLOB: - return 4294967295U; + return (uint) UINT32_MAX; default: DBUG_ASSERT(0); // we should never go here return 0; diff --git a/sql/sql_type.cc b/sql/sql_type.cc index a34619b5e36..659e5839585 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -31,10 +31,6 @@ static Type_handler_date type_handler_date; static Type_handler_timestamp type_handler_timestamp; static Type_handler_timestamp2 type_handler_timestamp2; static Type_handler_olddecimal type_handler_olddecimal; -static Type_handler_tiny_blob type_handler_tiny_blob; -static Type_handler_medium_blob type_handler_medium_blob; -static Type_handler_long_blob type_handler_long_blob; -static Type_handler_blob type_handler_blob; Type_handler_null type_handler_null; @@ -54,6 +50,11 @@ Type_handler_time2 type_handler_time2; Type_handler_newdate type_handler_newdate; Type_handler_datetime2 type_handler_datetime2; +Type_handler_tiny_blob type_handler_tiny_blob; +Type_handler_medium_blob type_handler_medium_blob; +Type_handler_long_blob type_handler_long_blob; +Type_handler_blob type_handler_blob; + #ifdef HAVE_SPATIAL Type_handler_geometry type_handler_geometry; #endif @@ -81,9 +82,18 @@ bool Type_handler_data::init() &type_handler_geometry, &type_handler_geometry) || m_type_aggregator_for_result.add(&type_handler_geometry, + &type_handler_tiny_blob, + &type_handler_long_blob) || + m_type_aggregator_for_result.add(&type_handler_geometry, &type_handler_blob, &type_handler_long_blob) || m_type_aggregator_for_result.add(&type_handler_geometry, + &type_handler_medium_blob, + &type_handler_long_blob) || + m_type_aggregator_for_result.add(&type_handler_geometry, + &type_handler_long_blob, + &type_handler_long_blob) || + m_type_aggregator_for_result.add(&type_handler_geometry, &type_handler_varchar, &type_handler_long_blob) || m_type_aggregator_for_result.add(&type_handler_geometry, @@ -140,6 +150,19 @@ Type_handler::string_type_handler(uint max_octet_length) } +const Type_handler * +Type_handler::blob_type_handler(uint max_octet_length) +{ + if (max_octet_length <= 255) + return &type_handler_tiny_blob; + if (max_octet_length <= 65535) + return &type_handler_blob; + if (max_octet_length <= 16777215) + return &type_handler_medium_blob; + return &type_handler_long_blob; +} + + /** This method is used by: - Item_sum_hybrid, e.g. MAX(item), MIN(item). @@ -1153,6 +1176,423 @@ Field *Type_handler_set::make_conversion_table_field(TABLE *table, } /*************************************************************************/ +Field *Type_handler::make_and_init_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + Field *field= make_table_field(name, addr, attr, table); + if (field) + field->init(table); + return field; +} + + +Field *Type_handler_tiny::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_tiny(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); +} + + +Field *Type_handler_short::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_short(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); +} + + +Field *Type_handler_int24::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_medium(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field::NONE, name, + 0/*zerofill*/, attr.unsigned_flag); +} + + +Field *Type_handler_long::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_long(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); +} + + +Field *Type_handler_longlong::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_longlong(addr.ptr, attr.max_length, + addr.null_ptr, addr.null_bit, + Field::NONE, name, + 0/*zerofill*/, attr.unsigned_flag); +} + + +Field *Type_handler_float::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_float(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field::NONE, name, + attr.decimals, 0/*zerofill*/, attr.unsigned_flag); +} + + +Field *Type_handler_double::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_double(addr.ptr, attr.max_length, + addr.null_ptr, addr.null_bit, + Field::NONE, name, + attr.decimals, 0/*zerofill*/, attr.unsigned_flag); +} + + +Field * +Type_handler_olddecimal::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + /* + Currently make_table_field() is used for Item purpose only. + On Item level we have type_handler_newdecimal only. + Will be implemented when we reuse Type_handler::make_table_field() + in make_field() in field.cc, to open old tables with old decimal. + */ + DBUG_ASSERT(0); + return NULL; +} + + +Field * +Type_handler_newdecimal::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + uint8 dec= attr.decimals; + uint8 intg= attr.decimal_precision() - dec; + uint32 len= attr.max_char_length(); + + /* + Trying to put too many digits overall in a DECIMAL(prec,dec) + will always throw a warning. We must limit dec to + DECIMAL_MAX_SCALE however to prevent an assert() later. + */ + + if (dec > 0) + { + signed int overflow; + + dec= MY_MIN(dec, DECIMAL_MAX_SCALE); + + /* + If the value still overflows the field with the corrected dec, + we'll throw out decimals rather than integers. This is still + bad and of course throws a truncation warning. + +1: for decimal point + */ + + const int required_length= + my_decimal_precision_to_length(intg + dec, dec, attr.unsigned_flag); + + overflow= required_length - len; + + if (overflow > 0) + dec= MY_MAX(0, dec - overflow); // too long, discard fract + else + /* Corrected value fits. */ + len= required_length; + } + return new (table->in_use->mem_root) + Field_new_decimal(addr.ptr, len, addr.null_ptr, addr.null_bit, + Field::NONE, name, + dec, 0/*zerofill*/, attr.unsigned_flag); +} + + +Field *Type_handler_year::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_year(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field::NONE, name); +} + + +Field *Type_handler_null::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_null(addr.ptr, attr.max_length, + Field::NONE, name, attr.collation.collation); +} + + +Field *Type_handler_timestamp::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new_Field_timestamp(table->in_use->mem_root, + addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, table->s, attr.decimals); +} + + +Field *Type_handler_timestamp2::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_timestampf(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, table->s, attr.decimals); +} + + +Field *Type_handler_newdate::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_newdate(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name); +} + + +Field *Type_handler_date::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_date(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name); +} + + +Field *Type_handler_time::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new_Field_time(table->in_use->mem_root, + addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, attr.decimals); +} + + +Field *Type_handler_time2::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + + +{ + return new (table->in_use->mem_root) + Field_timef(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, attr.decimals); +} + + +Field *Type_handler_datetime::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new_Field_datetime(table->in_use->mem_root, + addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, attr.decimals); +} + + +Field *Type_handler_datetime2::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_datetimef(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, attr.decimals); +} + + +Field *Type_handler_bit::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_bit_as_char(addr.ptr, attr.max_length, + addr.null_ptr, addr.null_bit, + Field::NONE, name); +} + + +Field *Type_handler_string::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_string(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field::NONE, name, attr.collation.collation); +} + + +Field *Type_handler_varchar::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_varstring(addr.ptr, attr.max_length, + HA_VARCHAR_PACKLENGTH(attr.max_length), + addr.null_ptr, addr.null_bit, + Field::NONE, name, + table->s, attr.collation.collation); +} + + +Field *Type_handler_tiny_blob::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, table->s, + 1, attr.collation.collation); +} + + +Field *Type_handler_blob::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, table->s, + 2, attr.collation.collation); +} + + +Field * +Type_handler_medium_blob::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, table->s, + 3, attr.collation.collation); +} + + +Field *Type_handler_long_blob::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + return new (table->in_use->mem_root) + Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, table->s, + 4, attr.collation.collation); +} + + + +#ifdef HAVE_SPATIAL +Field *Type_handler_geometry::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + return new (table->in_use->mem_root) + Field_geom(addr.ptr, addr.null_ptr, addr.null_bit, + Field::NONE, name, table->s, 4, + (Field::geometry_type) attr.uint_geometry_type(), + 0); +} +#endif + + +Field *Type_handler_enum::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const +{ + /* + Will be implemented when we split Item_type_holder::make_field_by_type() + and/or reuse Type_handler::make_table_field() in make_field() in field.cc + */ + DBUG_ASSERT(0); + return 0; +} + + +Field *Type_handler_set::make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + +{ + /* + Will be implemented when we split Item_type_holder::make_field_by_type() + and/or reuse Type_handler::make_table_field() in make_field() in field.cc + */ + DBUG_ASSERT(0); + return 0; +} + +/*************************************************************************/ uint32 Type_handler_decimal_result::max_display_length(const Item *item) const { @@ -1440,6 +1880,17 @@ bool Type_handler_string_result:: } +bool Type_handler_blob_common:: + Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, + Item **items, uint nitems) const +{ + if (func->aggregate_attributes_string(items, nitems)) + return true; + func->set_handler(blob_type_handler(func->max_length)); + return false; +} + + bool Type_handler_date_common:: Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, Item **items, uint nitems) const diff --git a/sql/sql_type.h b/sql/sql_type.h index 0652e56da4f..0df54315763 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -314,6 +314,27 @@ public: }; +class Type_all_attributes: public Type_std_attributes +{ +public: + Type_all_attributes() + :Type_std_attributes() + { } + Type_all_attributes(const Type_all_attributes *other) + :Type_std_attributes(other) + { } + // Returns total number of decimal digits + virtual uint decimal_precision() const= 0; + /* + Field::geometry_type is not visible here. + Let's use an "uint" wrapper for now. Later when we move Field_geom + into a plugin, this method will be replaced to some generic + datatype indepented method. + */ + virtual uint uint_geometry_type() const= 0; +}; + + class Name: private LEX_CSTRING { public: @@ -327,6 +348,31 @@ public: }; +class Record_addr +{ +public: + uchar *ptr; // Position to field in record + /** + Byte where the @c NULL bit is stored inside a record. If this Field is a + @c NOT @c NULL field, this member is @c NULL. + */ + uchar *null_ptr; + uchar null_bit; // Bit used to test null bit + Record_addr(uchar *ptr_arg, + uchar *null_ptr_arg, + uchar null_bit_arg) + :ptr(ptr_arg), + null_ptr(null_ptr_arg), + null_bit(null_bit_arg) + { } + Record_addr(bool maybe_null) + :ptr(NULL), + null_ptr(maybe_null ? (uchar*) "" : 0), + null_bit(0) + { } +}; + + class Type_handler { protected: @@ -342,6 +388,7 @@ protected: bool Item_func_or_sum_illegal_param(const Item_func_or_sum *) const; public: + static const Type_handler *blob_type_handler(uint max_octet_length); static const Type_handler *string_type_handler(uint max_octet_length); static const Type_handler *get_handler_by_field_type(enum_field_types type); static const Type_handler *get_handler_by_real_type(enum_field_types type); @@ -431,6 +478,14 @@ public: virtual Field *make_conversion_table_field(TABLE *TABLE, uint metadata, const Field *target) const= 0; + virtual Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const= 0; + Field *make_and_init_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; virtual void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const= 0; @@ -630,6 +685,14 @@ public: DBUG_ASSERT(0); return NULL; } + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const + { + DBUG_ASSERT(0); + return NULL; + } void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const @@ -1179,6 +1242,10 @@ public: uint32 max_display_length(const Item *item) const { return 4; } Field *make_conversion_table_field(TABLE *TABLE, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1192,6 +1259,10 @@ public: uint32 max_display_length(const Item *item) const { return 6; } Field *make_conversion_table_field(TABLE *TABLE, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1208,6 +1279,10 @@ public: } Field *make_conversion_table_field(TABLE *TABLE, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1221,6 +1296,10 @@ public: uint32 max_display_length(const Item *item) const { return 20; } Field *make_conversion_table_field(TABLE *TABLE, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1234,6 +1313,10 @@ public: uint32 max_display_length(const Item *item) const { return 8; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1247,6 +1330,10 @@ public: uint32 max_display_length(const Item *item) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1264,6 +1351,10 @@ public: } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1278,6 +1369,10 @@ public: Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1291,6 +1386,10 @@ public: uint32 max_display_length(const Item *item) const { return 53; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1321,6 +1420,10 @@ public: virtual ~Type_handler_time() {} Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1331,6 +1434,10 @@ public: enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1367,6 +1474,10 @@ public: virtual ~Type_handler_date() {} Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1376,6 +1487,10 @@ public: virtual ~Type_handler_newdate() {} Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1402,6 +1517,10 @@ public: virtual ~Type_handler_datetime() {} Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1412,6 +1531,10 @@ public: enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1438,6 +1561,10 @@ public: virtual ~Type_handler_timestamp() {} Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1448,6 +1575,10 @@ public: enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1460,6 +1591,10 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1472,6 +1607,10 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1486,6 +1625,10 @@ public: uint32 max_display_length(const Item *item) const { return 0; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1499,6 +1642,10 @@ public: bool is_param_long_data_type() const { return true; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1512,6 +1659,10 @@ public: bool is_param_long_data_type() const { return true; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1525,6 +1676,8 @@ public: return false; // Materialization does not work with BLOB columns } bool is_param_long_data_type() const { return true; } + bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, + Item **items, uint nitems) const; }; @@ -1537,6 +1690,10 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1549,6 +1706,10 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1561,6 +1722,10 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1573,6 +1738,10 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_BLOB; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1593,6 +1762,11 @@ public: } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; + bool is_traditional_type() const { return false; @@ -1629,6 +1803,10 @@ public: virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1642,6 +1820,10 @@ public: virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + Field *make_table_field(const LEX_CSTRING *name, + const Record_addr &addr, + const Type_all_attributes &attr, + TABLE *table) const; }; @@ -1742,6 +1924,10 @@ extern Type_handler_time2 type_handler_time2; extern Type_handler_newdate type_handler_newdate; extern Type_handler_datetime2 type_handler_datetime2; +extern Type_handler_tiny_blob type_handler_tiny_blob; +extern Type_handler_blob type_handler_blob; +extern Type_handler_medium_blob type_handler_medium_blob; +extern Type_handler_long_blob type_handler_long_blob; class Type_aggregator { |