1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge remote-tracking branch 'origin/bb-10.2-ext' into 10.3

This commit is contained in:
Alexander Barkov
2017-05-02 13:52:45 +04:00
59 changed files with 2864 additions and 1102 deletions

View File

@@ -488,13 +488,35 @@ d date YES NULL
e varchar(1) YES NULL e varchar(1) YES NULL
f datetime YES NULL f datetime YES NULL
g time YES NULL g time YES NULL
h longblob YES NULL h blob YES NULL
dd time YES NULL dd time YES NULL
select * from t2; select * from t2;
a b c d e f g h dd 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 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 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; 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 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; 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; show create table t2;

View File

@@ -11184,5 +11184,21 @@ SET NAMES utf8;
CREATE TABLE t1 (a SET('a,bü')); CREATE TABLE t1 (a SET('a,bü'));
ERROR 22007: Illegal set 'a,bü' value found during parsing ERROR 22007: Illegal set 'a,bü' value found during parsing
# #
# MDEV-12607 Hybrid functions create wrong VARBINARY length when mixing character and binary data
#
SET sql_mode='';
SET NAMES utf8;
CREATE OR REPLACE TABLE t1 AS SELECT COALESCE('ßa',_binary 'a');
SELECT * FROM t1;
COALESCE('ßa',_binary 'a')
ßa
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`COALESCE('ßa',_binary 'a')` varbinary(6) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SET sql_mode=DEFAULT;
#
# End of 10.3 tests # End of 10.3 tests
# #

View File

@@ -3500,5 +3500,17 @@ t2 CREATE TABLE `t2` (
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-12601 Hybrid functions create a column of an impossible type DOUBLE(256,4)
#
CREATE TABLE t1 (a DOUBLE(255,4),b DOUBLE(255,3));
CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`COALESCE(a,b)` double(255,4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
#
# End of 10.3 tests # End of 10.3 tests
# #

View File

@@ -4661,3 +4661,20 @@ DROP TABLE t1;
# #
# End of 10.1 tests # End of 10.1 tests
# #
#
# Start of 10.3 tests
#
#
# MDEV-12592 Illegal mix of collations with the HEX function
#
SET NAMES utf8;
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
INSERT INTO t1 VALUES (0x09),('a');
SELECT IF(a<' ',HEX(a),a) FROM t1 ORDER BY a;
IF(a<' ',HEX(a),a)
09
a
DROP TABLE t1;
#
# End of 10.3 tests
#

View File

@@ -57,7 +57,7 @@ create table t1 select weight_string(repeat('t',66000)) as w;
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`w` longblob DEFAULT NULL `w` mediumblob DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
select weight_string(NULL); select weight_string(NULL);

View File

@@ -381,11 +381,11 @@ POINT(0,0) MOD '0' LIMIT 0;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`POINT(0,0)+'0'` longtext DEFAULT NULL, `POINT(0,0)+'0'` tinytext DEFAULT NULL,
`POINT(0,0)-'0'` longtext DEFAULT NULL, `POINT(0,0)-'0'` tinytext DEFAULT NULL,
`POINT(0,0)*'0'` longtext DEFAULT NULL, `POINT(0,0)*'0'` tinytext DEFAULT NULL,
`POINT(0,0)/'0'` longtext DEFAULT NULL, `POINT(0,0)/'0'` tinytext DEFAULT NULL,
`POINT(0,0) MOD '0'` longtext DEFAULT NULL `POINT(0,0) MOD '0'` tinytext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 AS SELECT CREATE TABLE t1 AS SELECT
@@ -394,8 +394,8 @@ CREATE TABLE t1 AS SELECT
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`'0'+POINT(0,0)` longtext DEFAULT NULL, `'0'+POINT(0,0)` tinytext DEFAULT NULL,
`'0'*POINT(0,0)` longtext DEFAULT NULL `'0'*POINT(0,0)` tinytext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 AS SELECT '0'-POINT(0,0) LIMIT 0; CREATE TABLE t1 AS SELECT '0'-POINT(0,0) LIMIT 0;

View File

@@ -709,7 +709,7 @@ def test t1 t1 g g 255 4294967295 0 Y 144 0 63
g g
select asbinary(g) from t1; select asbinary(g) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr 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) asbinary(g)
drop table t1; drop table t1;
create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b));
@@ -4030,65 +4030,65 @@ DROP TABLE t1;
# #
CREATE TABLE t1 (a GEOMETRY); CREATE TABLE t1 (a GEOMETRY);
SELECT POINT(1,1) + 1; SELECT POINT(1,1) + 1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '+' ERROR HY000: Illegal parameter data types geometry and int for operation '+'
SELECT POINT(1,1) - 1; SELECT POINT(1,1) - 1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '-' ERROR HY000: Illegal parameter data types geometry and int for operation '-'
SELECT POINT(1,1) * 1; SELECT POINT(1,1) * 1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '*' ERROR HY000: Illegal parameter data types geometry and int for operation '*'
SELECT POINT(1,1) / 1; SELECT POINT(1,1) / 1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '/' ERROR HY000: Illegal parameter data types geometry and int for operation '/'
SELECT POINT(1,1) MOD 1; SELECT POINT(1,1) MOD 1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '%' ERROR HY000: Illegal parameter data types geometry and int for operation '%'
SELECT 1 + POINT(1,1); SELECT 1 + POINT(1,1);
ERROR HY000: Illegal parameter data types bigint and geometry for operation '+' ERROR HY000: Illegal parameter data types int and geometry for operation '+'
SELECT 1 - POINT(1,1); SELECT 1 - POINT(1,1);
ERROR HY000: Illegal parameter data types bigint and geometry for operation '-' ERROR HY000: Illegal parameter data types int and geometry for operation '-'
SELECT 1 * POINT(1,1); SELECT 1 * POINT(1,1);
ERROR HY000: Illegal parameter data types bigint and geometry for operation '*' ERROR HY000: Illegal parameter data types int and geometry for operation '*'
SELECT 1 / POINT(1,1); SELECT 1 / POINT(1,1);
ERROR HY000: Illegal parameter data types bigint and geometry for operation '/' ERROR HY000: Illegal parameter data types int and geometry for operation '/'
SELECT 1 MOD POINT(1,1); SELECT 1 MOD POINT(1,1);
ERROR HY000: Illegal parameter data types bigint and geometry for operation '%' ERROR HY000: Illegal parameter data types int and geometry for operation '%'
SELECT a + 1 FROM t1; SELECT a + 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '+' ERROR HY000: Illegal parameter data types geometry and int for operation '+'
SELECT a - 1 FROM t1; SELECT a - 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '-' ERROR HY000: Illegal parameter data types geometry and int for operation '-'
SELECT a * 1 FROM t1; SELECT a * 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '*' ERROR HY000: Illegal parameter data types geometry and int for operation '*'
SELECT a / 1 FROM t1; SELECT a / 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '/' ERROR HY000: Illegal parameter data types geometry and int for operation '/'
SELECT a MOD 1 FROM t1; SELECT a MOD 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '%' ERROR HY000: Illegal parameter data types geometry and int for operation '%'
SELECT 1 + a FROM t1; SELECT 1 + a FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '+' ERROR HY000: Illegal parameter data types int and geometry for operation '+'
SELECT 1 - a FROM t1; SELECT 1 - a FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '-' ERROR HY000: Illegal parameter data types int and geometry for operation '-'
SELECT 1 * a FROM t1; SELECT 1 * a FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '*' ERROR HY000: Illegal parameter data types int and geometry for operation '*'
SELECT 1 / a FROM t1; SELECT 1 / a FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '/' ERROR HY000: Illegal parameter data types int and geometry for operation '/'
SELECT 1 MOD a FROM t1; SELECT 1 MOD a FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '%' ERROR HY000: Illegal parameter data types int and geometry for operation '%'
SELECT COALESCE(a) + 1 FROM t1; SELECT COALESCE(a) + 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '+' ERROR HY000: Illegal parameter data types geometry and int for operation '+'
SELECT COALESCE(a) - 1 FROM t1; SELECT COALESCE(a) - 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '-' ERROR HY000: Illegal parameter data types geometry and int for operation '-'
SELECT COALESCE(a) * 1 FROM t1; SELECT COALESCE(a) * 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '*' ERROR HY000: Illegal parameter data types geometry and int for operation '*'
SELECT COALESCE(a) / 1 FROM t1; SELECT COALESCE(a) / 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '/' ERROR HY000: Illegal parameter data types geometry and int for operation '/'
SELECT COALESCE(a) MOD 1 FROM t1; SELECT COALESCE(a) MOD 1 FROM t1;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '%' ERROR HY000: Illegal parameter data types geometry and int for operation '%'
SELECT 1 + COALESCE(a) FROM t1; SELECT 1 + COALESCE(a) FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '+' ERROR HY000: Illegal parameter data types int and geometry for operation '+'
SELECT 1 - COALESCE(a) FROM t1; SELECT 1 - COALESCE(a) FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '-' ERROR HY000: Illegal parameter data types int and geometry for operation '-'
SELECT 1 * COALESCE(a) FROM t1; SELECT 1 * COALESCE(a) FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '*' ERROR HY000: Illegal parameter data types int and geometry for operation '*'
SELECT 1 / COALESCE(a) FROM t1; SELECT 1 / COALESCE(a) FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '/' ERROR HY000: Illegal parameter data types int and geometry for operation '/'
SELECT 1 MOD COALESCE(a) FROM t1; SELECT 1 MOD COALESCE(a) FROM t1;
ERROR HY000: Illegal parameter data types bigint and geometry for operation '%' ERROR HY000: Illegal parameter data types int and geometry for operation '%'
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-12514 Split Item_temporal_func::fix_length_and_dec() # MDEV-12514 Split Item_temporal_func::fix_length_and_dec()

View File

@@ -76,12 +76,12 @@ def aaa @arg00 @arg00 8 20 1 Y 32768 0 63
1 1
select 1 union select 1; select 1 union select 1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def 1 1 8 20 1 N 32769 0 63 def 1 1 3 11 1 N 32769 0 63
1 1
1 1
select * from (select 1 union select 1) aaa; select * from (select 1 union select 1) aaa;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def aaa 1 1 8 20 1 N 32769 0 63 def aaa 1 1 3 11 1 N 32769 0 63
1 1
1 1
drop table t1; drop table t1;

View File

@@ -575,8 +575,14 @@ c_float FLOAT,
c_double DOUBLE, c_double DOUBLE,
c_decimal103 DECIMAL(10,3), c_decimal103 DECIMAL(10,3),
c_varchar10 VARCHAR(10), c_varchar10 VARCHAR(10),
c_tinytext TINYTEXT,
c_text TEXT, c_text TEXT,
c_mediumtext MEDIUMTEXT,
c_longtext LONGTEXT,
c_tinyblob TINYBLOB,
c_blob BLOB, c_blob BLOB,
c_mediumblob MEDIUMBLOB,
c_longblob LONGBLOB,
c_enum ENUM('one','two','tree'), c_enum ENUM('one','two','tree'),
c_datetime3 DATETIME(3), c_datetime3 DATETIME(3),
c_timestamp3 TIMESTAMP(3), c_timestamp3 TIMESTAMP(3),
@@ -899,6 +905,45 @@ t2 CREATE TABLE `t2` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2; DROP TABLE t2;
CREATE TABLE t2 AS SELECT 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, 1),
NULLIF(c_text, c_smallint), NULLIF(c_text, c_smallint),
NULLIF(c_text, c_tinyint), NULLIF(c_text, c_tinyint),
@@ -919,22 +964,139 @@ FROM t1;
SHOW CREATE TABLE t2; SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`NULLIF(c_text, 1)` longtext DEFAULT NULL, `NULLIF(c_text, 1)` text DEFAULT NULL,
`NULLIF(c_text, c_smallint)` longtext DEFAULT NULL, `NULLIF(c_text, c_smallint)` text DEFAULT NULL,
`NULLIF(c_text, c_tinyint)` longtext DEFAULT NULL, `NULLIF(c_text, c_tinyint)` text DEFAULT NULL,
`NULLIF(c_text, c_int)` longtext DEFAULT NULL, `NULLIF(c_text, c_int)` text DEFAULT NULL,
`NULLIF(c_text, c_bigint)` longtext DEFAULT NULL, `NULLIF(c_text, c_bigint)` text DEFAULT NULL,
`NULLIF(c_text, c_float)` longtext DEFAULT NULL, `NULLIF(c_text, c_float)` text DEFAULT NULL,
`NULLIF(c_text, c_double)` longtext DEFAULT NULL, `NULLIF(c_text, c_double)` text DEFAULT NULL,
`NULLIF(c_text, c_decimal103)` longtext DEFAULT NULL, `NULLIF(c_text, c_decimal103)` text DEFAULT NULL,
`NULLIF(c_text, c_varchar10)` longtext DEFAULT NULL, `NULLIF(c_text, c_varchar10)` text DEFAULT NULL,
`NULLIF(c_text, c_text)` longtext DEFAULT NULL, `NULLIF(c_text, c_text)` text DEFAULT NULL,
`NULLIF(c_text, c_blob)` longtext DEFAULT NULL, `NULLIF(c_text, c_blob)` text DEFAULT NULL,
`NULLIF(c_text, c_enum)` longtext DEFAULT NULL, `NULLIF(c_text, c_enum)` text DEFAULT NULL,
`NULLIF(c_text, c_datetime3)` longtext DEFAULT NULL, `NULLIF(c_text, c_datetime3)` text DEFAULT NULL,
`NULLIF(c_text, c_timestamp3)` longtext DEFAULT NULL, `NULLIF(c_text, c_timestamp3)` text DEFAULT NULL,
`NULLIF(c_text, c_date)` longtext DEFAULT NULL, `NULLIF(c_text, c_date)` text DEFAULT NULL,
`NULLIF(c_text, c_time)` longtext 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 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2; DROP TABLE t2;
CREATE TABLE t2 AS SELECT CREATE TABLE t2 AS SELECT
@@ -958,22 +1120,100 @@ FROM t1;
SHOW CREATE TABLE t2; SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`NULLIF(c_blob, 1)` longblob DEFAULT NULL, `NULLIF(c_blob, 1)` blob DEFAULT NULL,
`NULLIF(c_blob, c_smallint)` longblob DEFAULT NULL, `NULLIF(c_blob, c_smallint)` blob DEFAULT NULL,
`NULLIF(c_blob, c_tinyint)` longblob DEFAULT NULL, `NULLIF(c_blob, c_tinyint)` blob DEFAULT NULL,
`NULLIF(c_blob, c_int)` longblob DEFAULT NULL, `NULLIF(c_blob, c_int)` blob DEFAULT NULL,
`NULLIF(c_blob, c_bigint)` longblob DEFAULT NULL, `NULLIF(c_blob, c_bigint)` blob DEFAULT NULL,
`NULLIF(c_blob, c_float)` longblob DEFAULT NULL, `NULLIF(c_blob, c_float)` blob DEFAULT NULL,
`NULLIF(c_blob, c_double)` longblob DEFAULT NULL, `NULLIF(c_blob, c_double)` blob DEFAULT NULL,
`NULLIF(c_blob, c_decimal103)` longblob DEFAULT NULL, `NULLIF(c_blob, c_decimal103)` blob DEFAULT NULL,
`NULLIF(c_blob, c_varchar10)` longblob DEFAULT NULL, `NULLIF(c_blob, c_varchar10)` blob DEFAULT NULL,
`NULLIF(c_blob, c_text)` longblob DEFAULT NULL, `NULLIF(c_blob, c_text)` blob DEFAULT NULL,
`NULLIF(c_blob, c_blob)` longblob DEFAULT NULL, `NULLIF(c_blob, c_blob)` blob DEFAULT NULL,
`NULLIF(c_blob, c_enum)` longblob DEFAULT NULL, `NULLIF(c_blob, c_enum)` blob DEFAULT NULL,
`NULLIF(c_blob, c_datetime3)` longblob DEFAULT NULL, `NULLIF(c_blob, c_datetime3)` blob DEFAULT NULL,
`NULLIF(c_blob, c_timestamp3)` longblob DEFAULT NULL, `NULLIF(c_blob, c_timestamp3)` blob DEFAULT NULL,
`NULLIF(c_blob, c_date)` longblob DEFAULT NULL, `NULLIF(c_blob, c_date)` blob DEFAULT NULL,
`NULLIF(c_blob, c_time)` longblob 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 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2; DROP TABLE t2;
CREATE TABLE t2 AS SELECT CREATE TABLE t2 AS SELECT

View File

@@ -2052,8 +2052,8 @@ CALL p1();
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`var` varchar(255) DEFAULT NULL, `var` tinytext DEFAULT NULL,
`rec.var` varchar(255) DEFAULT NULL `rec.var` tinytext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
DROP PROCEDURE p1; DROP PROCEDURE p1;
@@ -2092,8 +2092,8 @@ CALL p1();
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`var` varchar(255) CHARACTER SET utf8 DEFAULT NULL, `var` text CHARACTER SET utf8 DEFAULT NULL,
`rec.var` varchar(255) CHARACTER SET utf8 DEFAULT NULL `rec.var` text CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
DROP PROCEDURE p1; DROP PROCEDURE p1;

View File

@@ -1019,3 +1019,52 @@ cast('-0.0' as decimal(5,1)) < 0
# #
# End of 5.5 tests # End of 5.5 tests
# #
#
# Start of 10.3 tests
#
#
# MDEV-9217 Split Item::tmp_table_field_from_field_type() into virtual methods in Type_handler
#
# This creates the old DECIMAL. Will be fixed in MDEV-12574.
CREATE TABLE t1 AS SELECT MAX(a) FROM t1dec102;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`MAX(a)` decimal(10,2)/*old*/ DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 AS SELECT COALESCE(a) FROM t1dec102;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`COALESCE(a)` decimal(10,2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a BIGINT);
CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` decimal(21,2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (a MEDIUMINT);
CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` decimal(10,2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (a YEAR);
CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT a FROM t1dec102;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` decimal(10,2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
DROP TABLE t1dec102;

View File

@@ -1803,13 +1803,18 @@ id c1 + 0 c1
3 2 3 2
4 0 4 0
DROP TABLE t1; DROP TABLE t1;
End of 4.1 tests End of 4.1 tests
SET sql_mode='';
create table t1(f1 enum('a','b'), index(f1)); create table t1(f1 enum('a','b'), index(f1));
insert into t1 values(''),(''),('a'),('b');
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f1' at row 2 Warning 1265 Data truncated for column 'f1' at row 2
select * from t1 where f1=''; select * from t1 where f1='';
f1 f1
drop table t1;
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
CREATE TABLE t1 (c1 ENUM('a', '', 'b')); CREATE TABLE t1 (c1 ENUM('a', '', 'b'));
INSERT INTO t1 (c1) VALUES ('b'); INSERT INTO t1 (c1) VALUES ('b');
@@ -2219,3 +2224,90 @@ SELECT * FROM t1;
SELECT * FROM t1; SELECT * FROM t1;
a a
DROP TABLE t1;
#
# Start of 10.3 tests
#
#
# MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
#
CREATE TABLE t1 (a ENUM('a','b','c','1'),KEY(a));
INSERT INTO t1 VALUES ('a'),('b'),('c'),('1');
EXPLAIN SELECT * FROM t1 WHERE a='xx';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='99999999';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a=100.1e0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a=100.1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='100';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='1x';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='1.0';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='1.1';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
DROP TABLE t1;
#
# MDEV-12656 Crash in CREATE..SELECT..UNION with a ENUM column and NULL
#
CREATE TABLE t1 (a ENUM('a'));
# non-UNION + table column
CREATE TABLE t2 AS SELECT (SELECT a FROM t1);
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`(SELECT a FROM t1)` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
# UNION + table column
CREATE TABLE t2 AS SELECT (SELECT a FROM t1 UNION SELECT NULL);
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`(SELECT a FROM t1 UNION SELECT NULL)` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
# UNION + SP variable
CREATE PROCEDURE p1()
BEGIN
DECLARE va ENUM('a');
CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
SHOW CREATE TABLE t2;
DROP TABLE t2;
END;
$$
CALL p1();
Table Create Table
t2 CREATE TABLE `t2` (
`(SELECT va FROM t1 UNION SELECT NULL)` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP PROCEDURE p1;
# UNION + anchored SP variable
CREATE PROCEDURE p1()
BEGIN
DECLARE va TYPE OF t1.a;
CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
SHOW CREATE TABLE t2;
DROP TABLE t2;
END;
$$
CALL p1();
Table Create Table
t2 CREATE TABLE `t2` (
`(SELECT va FROM t1 UNION SELECT NULL)` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP PROCEDURE p1;

View File

@@ -316,3 +316,39 @@ DROP TABLE t1;
# #
# End of 10.1 tests # End of 10.1 tests
# #
#
# Start of 10.3 tests
#
#
# MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
#
CREATE TABLE t1 (a SET('a','b','c','1'),KEY(a));
INSERT INTO t1 VALUES ('a'),('b'),('c'),('1');
EXPLAIN SELECT * FROM t1 WHERE a='xx';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='99999999';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a=100.1e0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a=100.1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='100';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='1x';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='1.0';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE a='1.1';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
DROP TABLE t1;

View File

@@ -992,5 +992,25 @@ a b
DROP TABLE t1; DROP TABLE t1;
SET @@timestamp=DEFAULT; SET @@timestamp=DEFAULT;
# #
# MDEV-12582 Wrong data type for CREATE..SELECT MAX(COALESCE(timestamp_column))
#
CREATE TABLE t1 (a TIMESTAMP);
CREATE TABLE t2 AS SELECT
MAX(a),
COALESCE(a),
COALESCE(MAX(a)),
MAX(COALESCE(a))
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`MAX(a)` timestamp NULL DEFAULT NULL,
`COALESCE(a)` timestamp NULL DEFAULT NULL,
`COALESCE(MAX(a))` timestamp NULL DEFAULT NULL,
`MAX(COALESCE(a))` timestamp NULL DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
#
# End of 10.3 tests # End of 10.3 tests
# #

View File

@@ -852,7 +852,7 @@ select * from t1;
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`1` bigint(20) NOT NULL DEFAULT 0 `1` int(11) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 select _latin1"test" union select _latin2"testt" ; create table t1 select _latin1"test" union select _latin2"testt" ;
@@ -1449,6 +1449,28 @@ t2 CREATE TABLE `t2` (
`f8` mediumtext CHARACTER SET utf8 DEFAULT NULL `f8` mediumtext CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, 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;
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 (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
@@ -2156,3 +2178,33 @@ WHERE t1_2.b NOT IN ( SELECT 4 UNION ALL SELECT 5 );
a b a b a b a b
1 1 1 1 1 1 1 1
DROP TABLE t1; DROP TABLE t1;
#
# Start of 10.3 tests
#
#
# MDEV-12619 UNION creates excessive integer column types for integer literals
#
CREATE TABLE t1 AS SELECT 1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`1` int(1) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 AS SELECT 1 UNION SELECT 1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`1` int(11) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM (SELECT 1 UNION SELECT 1) AS t0;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`1` int(11) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# End of 10.3 tests
#

View File

@@ -2129,8 +2129,8 @@ CALL p1();
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE "t1" ( t1 CREATE TABLE "t1" (
"var" varchar(255) DEFAULT NULL, "var" tinytext DEFAULT NULL,
"rec.var" varchar(255) DEFAULT NULL "rec.var" tinytext DEFAULT NULL
) )
DROP TABLE t1; DROP TABLE t1;
DROP PROCEDURE p1; DROP PROCEDURE p1;
@@ -2169,8 +2169,8 @@ CALL p1();
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE "t1" ( t1 CREATE TABLE "t1" (
"var" varchar(255) CHARACTER SET utf8 DEFAULT NULL, "var" text CHARACTER SET utf8 DEFAULT NULL,
"rec.var" varchar(255) CHARACTER SET utf8 DEFAULT NULL "rec.var" text CHARACTER SET utf8 DEFAULT NULL
) )
DROP TABLE t1; DROP TABLE t1;
DROP PROCEDURE p1; DROP PROCEDURE p1;

View File

@@ -681,7 +681,7 @@ def test t1 t1 g g 255 4294967295 0 Y 144 0 63
g g
select ST_asbinary(g) from t1; select ST_asbinary(g) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr 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) ST_asbinary(g)
drop table t1; drop table t1;
create table t1 (a TEXT, b GEOMETRY NOT NULL, INDEX(b(5))); create table t1 (a TEXT, b GEOMETRY NOT NULL, INDEX(b(5)));

View File

@@ -1238,7 +1238,7 @@ Table Op Msg_type Msg_text
test.tab check status OK test.tab check status OK
DROP TABLE tab; DROP TABLE tab;
CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(c1 > 0) ) ENGINE=InnoDB; CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(c1 > 0) ) ENGINE=InnoDB;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '>' ERROR HY000: Illegal parameter data types geometry and int for operation '>'
CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(CAST(c1 AS BINARY) > 0) ) ENGINE=InnoDB; CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(CAST(c1 AS BINARY) > 0) ) ENGINE=InnoDB;
CREATE SPATIAL INDEX idx1 ON tab(c1) ; CREATE SPATIAL INDEX idx1 ON tab(c1) ;
SHOW CREATE TABLE tab; SHOW CREATE TABLE tab;

View File

@@ -681,7 +681,7 @@ def test t1 t1 g g 255 4294967295 0 Y 144 0 63
g g
select ST_asbinary(g) from t1; select ST_asbinary(g) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr 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) ST_asbinary(g)
drop table t1; drop table t1;
create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b));

View File

@@ -402,6 +402,22 @@ explain t2;
select * from t2; select * from t2;
drop table t1, 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 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; 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; show create table t2;

View File

@@ -2109,6 +2109,18 @@ SET NAMES utf8;
--error ER_ILLEGAL_VALUE_FOR_TYPE --error ER_ILLEGAL_VALUE_FOR_TYPE
CREATE TABLE t1 (a SET('a,bü')); CREATE TABLE t1 (a SET('a,bü'));
--echo #
--echo # MDEV-12607 Hybrid functions create wrong VARBINARY length when mixing character and binary data
--echo #
SET sql_mode='';
SET NAMES utf8;
CREATE OR REPLACE TABLE t1 AS SELECT COALESCE('ßa',_binary 'a');
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
SET sql_mode=DEFAULT;
--echo # --echo #
--echo # End of 10.3 tests --echo # End of 10.3 tests
--echo # --echo #

View File

@@ -500,6 +500,16 @@ SHOW CREATE TABLE t2;
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-12601 Hybrid functions create a column of an impossible type DOUBLE(256,4)
--echo #
CREATE TABLE t1 (a DOUBLE(255,4),b DOUBLE(255,3));
CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.3 tests --echo # End of 10.3 tests

View File

@@ -1806,3 +1806,23 @@ DROP TABLE t1;
--echo # --echo #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-12592 Illegal mix of collations with the HEX function
--echo #
SET NAMES utf8;
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
INSERT INTO t1 VALUES (0x09),('a');
SELECT IF(a<' ',HEX(a),a) FROM t1 ORDER BY a;
DROP TABLE t1;
--echo #
--echo # End of 10.3 tests
--echo #

View File

@@ -414,8 +414,14 @@ CREATE TABLE t1
c_double DOUBLE, c_double DOUBLE,
c_decimal103 DECIMAL(10,3), c_decimal103 DECIMAL(10,3),
c_varchar10 VARCHAR(10), c_varchar10 VARCHAR(10),
c_tinytext TINYTEXT,
c_text TEXT, c_text TEXT,
c_mediumtext MEDIUMTEXT,
c_longtext LONGTEXT,
c_tinyblob TINYBLOB,
c_blob BLOB, c_blob BLOB,
c_mediumblob MEDIUMBLOB,
c_longblob LONGBLOB,
c_enum ENUM('one','two','tree'), c_enum ENUM('one','two','tree'),
c_datetime3 DATETIME(3), c_datetime3 DATETIME(3),
c_timestamp3 TIMESTAMP(3), c_timestamp3 TIMESTAMP(3),
@@ -596,6 +602,27 @@ FROM t1;
SHOW CREATE TABLE t2; SHOW CREATE TABLE t2;
DROP 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 CREATE TABLE t2 AS SELECT
NULLIF(c_text, 1), NULLIF(c_text, 1),
NULLIF(c_text, c_smallint), NULLIF(c_text, c_smallint),
@@ -617,7 +644,70 @@ FROM t1;
SHOW CREATE TABLE t2; SHOW CREATE TABLE t2;
DROP 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 CREATE TABLE t2 AS SELECT
NULLIF(c_blob, 1), NULLIF(c_blob, 1),
NULLIF(c_blob, c_smallint), NULLIF(c_blob, c_smallint),
@@ -639,6 +729,49 @@ FROM t1;
SHOW CREATE TABLE t2; SHOW CREATE TABLE t2;
DROP 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) # QQ: this should probably create a ENUM column instead of VARCHAR(4)
CREATE TABLE t2 AS SELECT CREATE TABLE t2 AS SELECT
NULLIF(c_enum, 1), NULLIF(c_enum, 1),

View File

@@ -612,3 +612,46 @@ select cast('-0.0' as decimal(5,1)) < 0;
--echo # --echo #
--echo # End of 5.5 tests --echo # End of 5.5 tests
--echo # --echo #
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-9217 Split Item::tmp_table_field_from_field_type() into virtual methods in Type_handler
--echo #
let $MYSQLD_DATADIR= `select @@datadir`;
--copy_file std_data/old_decimal/t1dec102.frm $MYSQLD_DATADIR/test/t1dec102.frm
--copy_file std_data/old_decimal/t1dec102.MYD $MYSQLD_DATADIR/test/t1dec102.MYD
--copy_file std_data/old_decimal/t1dec102.MYI $MYSQLD_DATADIR/test/t1dec102.MYI
--echo # This creates the old DECIMAL. Will be fixed in MDEV-12574.
CREATE TABLE t1 AS SELECT MAX(a) FROM t1dec102;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 AS SELECT COALESCE(a) FROM t1dec102;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a BIGINT);
CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (a MEDIUMINT);
CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (a YEAR);
CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT a FROM t1dec102;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
DROP TABLE t1dec102;

View File

@@ -179,10 +179,12 @@ DROP TABLE t1;
# #
# Bug#28729: Field_enum wrongly reported an error while storing an empty string. # Bug#28729: Field_enum wrongly reported an error while storing an empty string.
# #
SET sql_mode='';
create table t1(f1 enum('a','b'), index(f1)); create table t1(f1 enum('a','b'), index(f1));
insert into t1 values(''),(''),('a'),('b'); insert into t1 values(''),(''),('a'),('b');
select * from t1 where f1=''; select * from t1 where f1='';
drop table t1;
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
# #
@@ -454,3 +456,65 @@ SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
ALTER TABLE t1 MODIFY a ENUM('2001','2002'); ALTER TABLE t1 MODIFY a ENUM('2001','2002');
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
--echo #
CREATE TABLE t1 (a ENUM('a','b','c','1'),KEY(a));
INSERT INTO t1 VALUES ('a'),('b'),('c'),('1');
EXPLAIN SELECT * FROM t1 WHERE a='xx';
EXPLAIN SELECT * FROM t1 WHERE a='99999999';
EXPLAIN SELECT * FROM t1 WHERE a=100.1e0;
EXPLAIN SELECT * FROM t1 WHERE a=100;
EXPLAIN SELECT * FROM t1 WHERE a=100.1;
EXPLAIN SELECT * FROM t1 WHERE a='100';
EXPLAIN SELECT * FROM t1 WHERE a='1x';
EXPLAIN SELECT * FROM t1 WHERE a='1.0';
EXPLAIN SELECT * FROM t1 WHERE a='1.1';
DROP TABLE t1;
--echo #
--echo # MDEV-12656 Crash in CREATE..SELECT..UNION with a ENUM column and NULL
--echo #
CREATE TABLE t1 (a ENUM('a'));
--echo # non-UNION + table column
CREATE TABLE t2 AS SELECT (SELECT a FROM t1);
SHOW CREATE TABLE t2;
DROP TABLE t2;
--echo # UNION + table column
CREATE TABLE t2 AS SELECT (SELECT a FROM t1 UNION SELECT NULL);
SHOW CREATE TABLE t2;
DROP TABLE t2;
--echo # UNION + SP variable
DELIMITER $$;
CREATE PROCEDURE p1()
BEGIN
DECLARE va ENUM('a');
CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
SHOW CREATE TABLE t2;
DROP TABLE t2;
END;
$$
DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;
--echo # UNION + anchored SP variable
DELIMITER $$;
CREATE PROCEDURE p1()
BEGIN
DECLARE va TYPE OF t1.a;
CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
SHOW CREATE TABLE t2;
DROP TABLE t2;
END;
$$
DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;

View File

@@ -218,3 +218,25 @@ DROP TABLE t1;
--echo # --echo #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
--echo #
CREATE TABLE t1 (a SET('a','b','c','1'),KEY(a));
INSERT INTO t1 VALUES ('a'),('b'),('c'),('1');
EXPLAIN SELECT * FROM t1 WHERE a='xx';
EXPLAIN SELECT * FROM t1 WHERE a='99999999';
EXPLAIN SELECT * FROM t1 WHERE a=100.1e0;
EXPLAIN SELECT * FROM t1 WHERE a=100;
EXPLAIN SELECT * FROM t1 WHERE a=100.1;
EXPLAIN SELECT * FROM t1 WHERE a='100';
EXPLAIN SELECT * FROM t1 WHERE a='1x';
EXPLAIN SELECT * FROM t1 WHERE a='1.0';
EXPLAIN SELECT * FROM t1 WHERE a='1.1';
DROP TABLE t1;

View File

@@ -587,6 +587,22 @@ SELECT * FROM t1 WHERE TIME'10:20:30' BETWEEN a and b;
DROP TABLE t1; DROP TABLE t1;
SET @@timestamp=DEFAULT; SET @@timestamp=DEFAULT;
--echo #
--echo # MDEV-12582 Wrong data type for CREATE..SELECT MAX(COALESCE(timestamp_column))
--echo #
CREATE TABLE t1 (a TIMESTAMP);
CREATE TABLE t2 AS SELECT
MAX(a),
COALESCE(a),
COALESCE(MAX(a)),
MAX(COALESCE(a))
FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.3 tests --echo # End of 10.3 tests
--echo # --echo #

View File

@@ -889,6 +889,22 @@ create table t2 as select *, f6 as f8 from t1 union select *, f7 from t1;
show create table t2; show create table t2;
drop table t1, 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. # Bug#18175: Union select over 129 tables with a sum function fails.
# #
@@ -1507,3 +1523,27 @@ SELECT * FROM t1 t1_1 LEFT JOIN t1 t1_2 ON ( t1_2.b = t1_1.a )
WHERE t1_2.b NOT IN ( SELECT 4 UNION ALL SELECT 5 ); WHERE t1_2.b NOT IN ( SELECT 4 UNION ALL SELECT 5 );
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-12619 UNION creates excessive integer column types for integer literals
--echo #
CREATE TABLE t1 AS SELECT 1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 AS SELECT 1 UNION SELECT 1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM (SELECT 1 UNION SELECT 1) AS t0;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # End of 10.3 tests
--echo #

View File

@@ -125,7 +125,7 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR, MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
@@ -520,7 +520,7 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
/* MYSQL_TYPE_YEAR -> */ /* MYSQL_TYPE_YEAR -> */
{ {
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_TINY,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
@@ -1256,14 +1256,14 @@ bool Field::can_optimize_group_min_max(const Item_bool_func *cond,
/* /*
This covers all numeric types, ENUM, SET, BIT This covers all numeric types, BIT
*/ */
bool Field::can_optimize_range(const Item_bool_func *cond, bool Field::can_optimize_range(const Item_bool_func *cond,
const Item *item, const Item *item,
bool is_eq_func) const bool is_eq_func) const
{ {
DBUG_ASSERT(cmp_type() != TIME_RESULT); // Handled in Field_temporal DBUG_ASSERT(cmp_type() != TIME_RESULT); // Handled in Field_temporal
DBUG_ASSERT(cmp_type() != STRING_RESULT); // Handled in Field_longstr DBUG_ASSERT(cmp_type() != STRING_RESULT); // Handled in Field_str descendants
return item->cmp_type() != TIME_RESULT; return item->cmp_type() != TIME_RESULT;
} }
@@ -2003,15 +2003,15 @@ bool Field_num::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg, uchar null_bit_arg, utype unireg_check_arg,
const LEX_CSTRING *field_name_arg, const LEX_CSTRING *field_name_arg,
CHARSET_INFO *charset_arg) const DTCollation &collation)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg) unireg_check_arg, field_name_arg)
{ {
field_charset= charset_arg; field_charset= collation.collation;
if (charset_arg->state & MY_CS_BINSORT) if (collation.collation->state & MY_CS_BINSORT)
flags|=BINARY_FLAG; flags|=BINARY_FLAG;
field_derivation= DERIVATION_IMPLICIT; field_derivation= collation.derivation;
field_repertoire= my_charset_repertoire(charset_arg); field_repertoire= collation.repertoire;
} }
@@ -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) int Field_new_decimal::reset(void)
{ {
store_value(&decimal_zero); store_value(&decimal_zero);
@@ -7817,10 +7756,10 @@ Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, enum utype unireg_check_arg,
const LEX_CSTRING *field_name_arg, const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, uint blob_pack_length, TABLE_SHARE *share, uint blob_pack_length,
CHARSET_INFO *cs) const DTCollation &collation)
:Field_longstr(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length), :Field_longstr(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length),
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
cs), collation),
packlength(blob_pack_length) packlength(blob_pack_length)
{ {
DBUG_ASSERT(blob_pack_length <= 4); // Only pack lengths 1-4 supported currently DBUG_ASSERT(blob_pack_length <= 4); // Only pack lengths 1-4 supported currently
@@ -8237,6 +8176,22 @@ void Field_blob::sort_string(uchar *to,uint length)
} }
/*
Return the data type handler, according to packlength.
Implemented in field.cc rather than in field.h
to avoid exporting type_handler_xxx with MYSQL_PLUGIN_IMPORT.
*/
const Type_handler *Field_blob::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;
}
void Field_blob::sql_type(String &res) const void Field_blob::sql_type(String &res) const
{ {
const char *str; const char *str;
@@ -8638,12 +8593,16 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
{ {
tmp=0; tmp=0;
set_warning(WARN_DATA_TRUNCATED, 1); set_warning(WARN_DATA_TRUNCATED, 1);
err= 1;
} }
if (!get_thd()->count_cuted_fields) if (!get_thd()->count_cuted_fields && !length)
err= 0; err= 0;
} }
else else
{
set_warning(WARN_DATA_TRUNCATED, 1); set_warning(WARN_DATA_TRUNCATED, 1);
err= 1;
}
} }
store_type((ulonglong) tmp); store_type((ulonglong) tmp);
return err; return err;
@@ -8817,6 +8776,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
{ {
tmp=0; tmp=0;
set_warning(WARN_DATA_TRUNCATED, 1); set_warning(WARN_DATA_TRUNCATED, 1);
err= 1;
} }
} }
else if (got_warning) else if (got_warning)
@@ -9055,12 +9015,17 @@ uint Field_num::is_equal(Create_field *new_field)
} }
bool Field_enum::can_optimize_range(const Item_bool_func *cond,
const Item *item,
bool is_eq_func) const
{
return item->cmp_type() != TIME_RESULT;
}
bool Field_enum::can_optimize_keypart_ref(const Item_bool_func *cond, bool Field_enum::can_optimize_keypart_ref(const Item_bool_func *cond,
const Item *item) const const Item *item) const
{ {
DBUG_ASSERT(cmp_type() == INT_RESULT);
DBUG_ASSERT(result_type() == STRING_RESULT);
switch (item->cmp_type()) switch (item->cmp_type())
{ {
case TIME_RESULT: case TIME_RESULT:
@@ -10717,7 +10682,7 @@ uint32 Field_blob::char_length() const
case 3: case 3:
return 16777215; return 16777215;
case 4: case 4:
return (uint32) 4294967295U; return (uint32) UINT_MAX32;
default: default:
DBUG_ASSERT(0); // we should never go here DBUG_ASSERT(0); // we should never go here
return 0; return 0;
@@ -10770,7 +10735,7 @@ uint32 Field_blob::max_display_length()
case 3: case 3:
return 16777215 * field_charset->mbmaxlen; return 16777215 * field_charset->mbmaxlen;
case 4: case 4:
return (uint32) 4294967295U; return (uint32) UINT_MAX32;
default: default:
DBUG_ASSERT(0); // we should never go here DBUG_ASSERT(0); // we should never go here
return 0; return 0;

View File

@@ -525,27 +525,6 @@ inline bool is_temporal_type(enum_field_types type)
} }
/**
Tests if field type is temporal and has time part,
i.e. represents TIME, DATETIME or TIMESTAMP types in SQL.
@param type Field type, as returned by field->type().
@retval true If field type is temporal type with time part.
@retval false If field type is not temporal type with time part.
*/
inline bool is_temporal_type_with_time(enum_field_types type)
{
switch (type)
{
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
return true;
default:
return false;
}
}
enum enum_vcol_info_type enum enum_vcol_info_type
{ {
VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED, VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED,
@@ -872,11 +851,13 @@ public:
to be quoted when used in constructing an SQL query. to be quoted when used in constructing an SQL query.
*/ */
virtual bool str_needs_quotes() { return FALSE; } virtual bool str_needs_quotes() { return FALSE; }
virtual Item_result result_type () const=0; Item_result result_type () const
virtual Item_result cmp_type () const { return result_type(); }
virtual const Type_handler *cast_to_int_type_handler() const
{ {
return Type_handler::get_handler_by_field_type(type()); return type_handler()->result_type();
}
Item_result cmp_type () const
{
return type_handler()->cmp_type();
} }
static bool type_can_have_key_part(enum_field_types); static bool type_can_have_key_part(enum_field_types);
static enum_field_types field_type_merge(enum_field_types, enum_field_types); static enum_field_types field_type_merge(enum_field_types, enum_field_types);
@@ -992,8 +973,15 @@ public:
virtual bool zero_pack() const { return 1; } virtual bool zero_pack() const { return 1; }
virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
virtual uint32 key_length() const { return pack_length(); } virtual uint32 key_length() const { return pack_length(); }
virtual enum_field_types type() const =0; virtual const Type_handler *type_handler() const= 0;
virtual enum_field_types real_type() const { return type(); } virtual enum_field_types type() const
{
return type_handler()->field_type();
}
virtual enum_field_types real_type() const
{
return type_handler()->real_field_type();
}
virtual enum_field_types binlog_type() const virtual enum_field_types binlog_type() const
{ {
/* /*
@@ -1318,9 +1306,6 @@ public:
virtual enum Derivation derivation(void) const virtual enum Derivation derivation(void) const
{ return DERIVATION_IMPLICIT; } { return DERIVATION_IMPLICIT; }
virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; } virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; }
virtual void set_derivation(enum Derivation derivation_arg,
uint repertoire_arg)
{ }
virtual int set_time() { return 1; } virtual int set_time() { return 1; }
bool set_warning(Sql_condition::enum_warning_level, unsigned int code, bool set_warning(Sql_condition::enum_warning_level, unsigned int code,
int cuted_increment) const; int cuted_increment) const;
@@ -1610,7 +1595,6 @@ public:
uchar null_bit_arg, utype unireg_check_arg, uchar null_bit_arg, utype unireg_check_arg,
const LEX_CSTRING *field_name_arg, const LEX_CSTRING *field_name_arg,
uint8 dec_arg, bool zero_arg, bool unsigned_arg); uint8 dec_arg, bool zero_arg, bool unsigned_arg);
enum Item_result result_type () const { return INT_RESULT; }
enum Derivation derivation(void) const { return DERIVATION_NUMERIC; } enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; } uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
CHARSET_INFO *charset(void) const { return &my_charset_numeric; } CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
@@ -1672,8 +1656,8 @@ public:
const Item_equal *item_equal); const Item_equal *item_equal);
Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg, uchar null_bit_arg, utype unireg_check_arg,
const LEX_CSTRING *field_name_arg, CHARSET_INFO *charset); const LEX_CSTRING *field_name_arg,
Item_result result_type () const { return STRING_RESULT; } const DTCollation &collation);
uint decimals() const { return NOT_FIXED_DEC; } uint decimals() const { return NOT_FIXED_DEC; }
int save_in_field(Field *to) { return save_in_field_str(to); } int save_in_field(Field *to) { return save_in_field_str(to); }
bool memcpy_field_possible(const Field *from) const bool memcpy_field_possible(const Field *from) const
@@ -1693,12 +1677,6 @@ public:
uint repertoire(void) const { return field_repertoire; } uint repertoire(void) const { return field_repertoire; }
CHARSET_INFO *charset(void) const { return field_charset; } CHARSET_INFO *charset(void) const { return field_charset; }
enum Derivation derivation(void) const { return field_derivation; } enum Derivation derivation(void) const { return field_derivation; }
void set_derivation(enum Derivation derivation_arg,
uint repertoire_arg)
{
field_derivation= derivation_arg;
field_repertoire= repertoire_arg;
}
bool binary() const { return field_charset == &my_charset_bin; } bool binary() const { return field_charset == &my_charset_bin; }
uint32 max_display_length() { return field_length; } uint32 max_display_length() { return field_length; }
friend class Create_field; friend class Create_field;
@@ -1740,9 +1718,10 @@ protected:
public: public:
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg, uchar null_bit_arg, utype unireg_check_arg,
const LEX_CSTRING *field_name_arg, CHARSET_INFO *charset_arg) const LEX_CSTRING *field_name_arg,
const DTCollation &collation)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg, charset_arg) field_name_arg, collation)
{} {}
int store_decimal(const my_decimal *d); int store_decimal(const my_decimal *d);
@@ -1781,7 +1760,6 @@ public:
field_name_arg, dec_arg, zero_arg, unsigned_arg), field_name_arg, dec_arg, zero_arg, unsigned_arg),
not_fixed(dec_arg >= FLOATING_POINT_DECIMALS) not_fixed(dec_arg >= FLOATING_POINT_DECIMALS)
{} {}
Item_result result_type () const { return REAL_RESULT; }
Copy_func *get_copy_func(const Field *from) const Copy_func *get_copy_func(const Field *from) const
{ {
return do_field_real; return do_field_real;
@@ -1818,7 +1796,7 @@ public:
unireg_check_arg, field_name_arg, unireg_check_arg, field_name_arg,
dec_arg, zero_arg, unsigned_arg) dec_arg, zero_arg, unsigned_arg)
{} {}
enum_field_types type() const { return MYSQL_TYPE_DECIMAL;} const Type_handler *type_handler() const { return &type_handler_olddecimal; }
enum ha_base_keytype key_type() const enum ha_base_keytype key_type() const
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; } { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
Copy_func *get_copy_func(const Field *from) const Copy_func *get_copy_func(const Field *from) const
@@ -1863,12 +1841,8 @@ public:
enum utype unireg_check_arg, enum utype unireg_check_arg,
const LEX_CSTRING *field_name_arg, const LEX_CSTRING *field_name_arg,
uint8 dec_arg, bool zero_arg, bool unsigned_arg); uint8 dec_arg, bool zero_arg, bool unsigned_arg);
Field_new_decimal(uint32 len_arg, bool maybe_null_arg, const Type_handler *type_handler() const { return &type_handler_newdecimal; }
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; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
Item_result result_type () const { return DECIMAL_RESULT; }
Copy_func *get_copy_func(const Field *from) const Copy_func *get_copy_func(const Field *from) const
{ {
// if (from->real_type() == MYSQL_TYPE_BIT) // QQ: why? // if (from->real_type() == MYSQL_TYPE_BIT) // QQ: why?
@@ -1918,7 +1892,6 @@ public:
uint16 mflags, int *order_var); uint16 mflags, int *order_var);
uint is_equal(Create_field *new_field); uint is_equal(Create_field *new_field);
virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data); 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); Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item);
}; };
@@ -1933,7 +1906,7 @@ public:
unireg_check_arg, field_name_arg, unireg_check_arg, field_name_arg,
0, zero_arg,unsigned_arg) 0, zero_arg,unsigned_arg)
{} {}
enum_field_types type() const { return MYSQL_TYPE_TINY;} const Type_handler *type_handler() const { return &type_handler_tiny; }
enum ha_base_keytype key_type() const enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; } { return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; }
int store(const char *to,uint length,CHARSET_INFO *charset); int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -1983,7 +1956,7 @@ public:
:Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, 0, 0, unsigned_arg) NONE, field_name_arg, 0, 0, unsigned_arg)
{} {}
enum_field_types type() const { return MYSQL_TYPE_SHORT;} const Type_handler *type_handler() const { return &type_handler_short; }
enum ha_base_keytype key_type() const enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;} { return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;}
int store(const char *to,uint length,CHARSET_INFO *charset); int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2018,7 +1991,7 @@ public:
unireg_check_arg, field_name_arg, unireg_check_arg, field_name_arg,
0, zero_arg,unsigned_arg) 0, zero_arg,unsigned_arg)
{} {}
enum_field_types type() const { return MYSQL_TYPE_INT24;} const Type_handler *type_handler() const { return &type_handler_int24; }
enum ha_base_keytype key_type() const enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; } { return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; }
int store(const char *to,uint length,CHARSET_INFO *charset); int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2058,7 +2031,7 @@ public:
:Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg,0,0,unsigned_arg) NONE, field_name_arg,0,0,unsigned_arg)
{} {}
enum_field_types type() const { return MYSQL_TYPE_LONG;} const Type_handler *type_handler() const { return &type_handler_long; }
enum ha_base_keytype key_type() const enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; } { return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; }
int store(const char *to,uint length,CHARSET_INFO *charset); int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2104,7 +2077,7 @@ public:
:Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0, :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg,0,0,unsigned_arg) NONE, field_name_arg,0,0,unsigned_arg)
{} {}
enum_field_types type() const { return MYSQL_TYPE_LONGLONG;} const Type_handler *type_handler() const { return &type_handler_longlong; }
enum ha_base_keytype key_type() const enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; } { return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; }
int store(const char *to,uint length,CHARSET_INFO *charset); int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2158,7 +2131,7 @@ public:
if (dec_arg >= FLOATING_POINT_DECIMALS) if (dec_arg >= FLOATING_POINT_DECIMALS)
dec_arg= NOT_FIXED_DEC; dec_arg= NOT_FIXED_DEC;
} }
enum_field_types type() const { return MYSQL_TYPE_FLOAT;} const Type_handler *type_handler() const { return &type_handler_float; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; }
int store(const char *to,uint length,CHARSET_INFO *charset); int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr); int store(double nr);
@@ -2209,7 +2182,7 @@ public:
if (dec_arg >= FLOATING_POINT_DECIMALS) if (dec_arg >= FLOATING_POINT_DECIMALS)
dec_arg= NOT_FIXED_DEC; dec_arg= NOT_FIXED_DEC;
} }
enum_field_types type() const { return MYSQL_TYPE_DOUBLE;} const Type_handler *type_handler() const { return &type_handler_double; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; }
int store(const char *to,uint length,CHARSET_INFO *charset); int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr); int store(double nr);
@@ -2242,11 +2215,11 @@ class Field_null :public Field_str {
public: public:
Field_null(uchar *ptr_arg, uint32 len_arg, Field_null(uchar *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
CHARSET_INFO *cs) const DTCollation &collation)
:Field_str(ptr_arg, len_arg, null, 1, :Field_str(ptr_arg, len_arg, null, 1,
unireg_check_arg, field_name_arg, cs) unireg_check_arg, field_name_arg, collation)
{} {}
enum_field_types type() const { return MYSQL_TYPE_NULL;} const Type_handler *type_handler() const { return &type_handler_null; }
Copy_func *get_copy_func(const Field *from) const Copy_func *get_copy_func(const Field *from) const
{ {
return do_field_string; return do_field_string;
@@ -2296,7 +2269,6 @@ public:
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg) field_name_arg)
{ flags|= BINARY_FLAG; } { flags|= BINARY_FLAG; }
Item_result result_type () const { return STRING_RESULT; }
int store_hex_hybrid(const char *str, uint length) int store_hex_hybrid(const char *str, uint length)
{ {
return store(str, length, &my_charset_bin); return store(str, length, &my_charset_bin);
@@ -2317,7 +2289,6 @@ public:
CHARSET_INFO *charset(void) const { return &my_charset_numeric; } CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
bool binary() const { return true; } bool binary() const { return true; }
enum Item_result cmp_type () const { return TIME_RESULT; }
bool val_bool() { return val_real() != 0e0; } bool val_bool() { return val_real() != 0e0; }
uint is_equal(Create_field *new_field); uint is_equal(Create_field *new_field);
bool eq_def(const Field *field) const bool eq_def(const Field *field) const
@@ -2394,7 +2365,7 @@ public:
enum utype unireg_check_arg, enum utype unireg_check_arg,
const LEX_CSTRING *field_name_arg, const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share); TABLE_SHARE *share);
enum_field_types type() const { return MYSQL_TYPE_TIMESTAMP;} const Type_handler *type_handler() const { return &type_handler_timestamp; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
int store(const char *to,uint length,CHARSET_INFO *charset); int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr); int store(double nr);
@@ -2528,7 +2499,7 @@ public:
Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, share, dec_arg) unireg_check_arg, field_name_arg, share, dec_arg)
{} {}
enum_field_types real_type() const { return MYSQL_TYPE_TIMESTAMP2; } const Type_handler *type_handler() const { return &type_handler_timestamp2; }
enum_field_types binlog_type() const { return MYSQL_TYPE_TIMESTAMP2; } enum_field_types binlog_type() const { return MYSQL_TYPE_TIMESTAMP2; }
uint32 pack_length() const uint32 pack_length() const
{ {
@@ -2559,14 +2530,19 @@ public:
:Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, :Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, 1, 1) unireg_check_arg, field_name_arg, 1, 1)
{} {}
enum_field_types type() const { return MYSQL_TYPE_YEAR;} const Type_handler *type_handler() const { return &type_handler_year; }
Copy_func *get_copy_func(const Field *from) const Copy_func *get_copy_func(const Field *from) const
{ {
if (eq_def(from)) if (eq_def(from))
return get_identical_copy_func(); return get_identical_copy_func();
switch (from->cmp_type()) { switch (from->cmp_type()) {
case STRING_RESULT: case STRING_RESULT:
{
const Type_handler *handler= from->type_handler();
if (handler == &type_handler_enum || handler == &type_handler_set)
return do_field_int;
return do_field_string; return do_field_string;
}
case TIME_RESULT: case TIME_RESULT:
return do_field_temporal; return do_field_temporal;
case DECIMAL_RESULT: case DECIMAL_RESULT:
@@ -2604,7 +2580,7 @@ public:
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg)
:Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg, :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg) {} unireg_check_arg, field_name_arg) {}
enum_field_types type() const { return MYSQL_TYPE_DATE;} const Type_handler *type_handler() const { return &type_handler_date; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
@@ -2640,8 +2616,7 @@ public:
:Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg, :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg) unireg_check_arg, field_name_arg)
{} {}
enum_field_types type() const { return MYSQL_TYPE_DATE;} const Type_handler *type_handler() const { return &type_handler_newdate; }
enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; } int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
double val_real(void); double val_real(void);
@@ -2679,7 +2654,7 @@ public:
:Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg, :Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg), curdays(0) unireg_check_arg, field_name_arg), curdays(0)
{} {}
enum_field_types type() const { return MYSQL_TYPE_TIME;} const Type_handler *type_handler() const { return &type_handler_time; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
Copy_func *get_copy_func(const Field *from) const Copy_func *get_copy_func(const Field *from) const
{ {
@@ -2791,7 +2766,7 @@ public:
{ {
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
} }
enum_field_types real_type() const { return MYSQL_TYPE_TIME2; } const Type_handler *type_handler() const { return &type_handler_time2; }
enum_field_types binlog_type() const { return MYSQL_TYPE_TIME2; } enum_field_types binlog_type() const { return MYSQL_TYPE_TIME2; }
uint32 pack_length() const uint32 pack_length() const
{ {
@@ -2833,7 +2808,7 @@ public:
unireg_check == TIMESTAMP_DNUN_FIELD) unireg_check == TIMESTAMP_DNUN_FIELD)
flags|= ON_UPDATE_NOW_FLAG; flags|= ON_UPDATE_NOW_FLAG;
} }
enum_field_types type() const { return MYSQL_TYPE_DATETIME;} const Type_handler *type_handler() const { return &type_handler_datetime; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
@@ -2950,7 +2925,7 @@ public:
:Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg, :Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, dec_arg) unireg_check_arg, field_name_arg, dec_arg)
{} {}
enum_field_types real_type() const { return MYSQL_TYPE_DATETIME2; } const Type_handler *type_handler() const { return &type_handler_datetime2; }
enum_field_types binlog_type() const { return MYSQL_TYPE_DATETIME2; } enum_field_types binlog_type() const { return MYSQL_TYPE_DATETIME2; }
uint32 pack_length() const uint32 pack_length() const
{ {
@@ -3028,29 +3003,35 @@ class Field_string :public Field_longstr {
public: public:
Warn_filter_string(const THD *thd, const Field_string *field); Warn_filter_string(const THD *thd, const Field_string *field);
}; };
bool is_var_string() const
{
return can_alter_field_type &&
orig_table &&
(orig_table->s->db_create_options & HA_OPTION_PACK_RECORD) &&
field_length >= 4 &&
orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR;
}
public: public:
bool can_alter_field_type; bool can_alter_field_type;
Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg, Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
uchar null_bit_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
CHARSET_INFO *cs) const DTCollation &collation)
:Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, cs), unireg_check_arg, field_name_arg, collation),
can_alter_field_type(1) {}; can_alter_field_type(1) {};
Field_string(uint32 len_arg,bool maybe_null_arg, Field_string(uint32 len_arg,bool maybe_null_arg,
const LEX_CSTRING *field_name_arg, const LEX_CSTRING *field_name_arg,
CHARSET_INFO *cs) const DTCollation &collation)
:Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
NONE, field_name_arg, cs), NONE, field_name_arg, collation),
can_alter_field_type(1) {}; can_alter_field_type(1) {};
enum_field_types type() const const Type_handler *type_handler() const
{ {
return ((can_alter_field_type && orig_table && if (is_var_string())
orig_table->s->db_create_options & HA_OPTION_PACK_RECORD && return &type_handler_var_string;
field_length >= 4) && return &type_handler_string;
orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR ?
MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING);
} }
enum ha_base_keytype key_type() const enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; } { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
@@ -3092,7 +3073,6 @@ public:
uint packed_col_length(const uchar *to, uint length); uint packed_col_length(const uchar *to, uint length);
uint max_packed_col_length(uint max_length); uint max_packed_col_length(uint max_length);
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return MYSQL_TYPE_STRING; }
bool has_charset(void) const bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; } { return charset() == &my_charset_bin ? FALSE : TRUE; }
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
@@ -3123,24 +3103,24 @@ public:
uint32 len_arg, uint length_bytes_arg, uint32 len_arg, uint length_bytes_arg,
uchar *null_ptr_arg, uchar null_bit_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, CHARSET_INFO *cs) TABLE_SHARE *share, const DTCollation &collation)
:Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, :Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, cs), unireg_check_arg, field_name_arg, collation),
length_bytes(length_bytes_arg) length_bytes(length_bytes_arg)
{ {
share->varchar_fields++; share->varchar_fields++;
} }
Field_varstring(uint32 len_arg,bool maybe_null_arg, Field_varstring(uint32 len_arg,bool maybe_null_arg,
const LEX_CSTRING *field_name_arg, const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, CHARSET_INFO *cs) TABLE_SHARE *share, const DTCollation &collation)
:Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
NONE, field_name_arg, cs), NONE, field_name_arg, collation),
length_bytes(len_arg < 256 ? 1 :2) length_bytes(len_arg < 256 ? 1 :2)
{ {
share->varchar_fields++; share->varchar_fields++;
} }
enum_field_types type() const { return MYSQL_TYPE_VARCHAR; } const Type_handler *type_handler() const { return &type_handler_varchar; }
enum ha_base_keytype key_type() const; enum ha_base_keytype key_type() const;
uint row_pack_length() const { return field_length; } uint row_pack_length() const { return field_length; }
bool zero_pack() const { return 0; } bool zero_pack() const { return 0; }
@@ -3184,7 +3164,6 @@ public:
uint max_packed_col_length(uint max_length); uint max_packed_col_length(uint max_length);
uint32 data_length(); uint32 data_length();
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; } { return charset() == &my_charset_bin ? FALSE : TRUE; }
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
@@ -3224,20 +3203,21 @@ protected:
public: public:
Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, uint blob_pack_length, CHARSET_INFO *cs); TABLE_SHARE *share, uint blob_pack_length,
const DTCollation &collation);
Field_blob(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg, Field_blob(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg,
CHARSET_INFO *cs) const DTCollation &collation)
:Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, :Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
NONE, field_name_arg, cs), NONE, field_name_arg, collation),
packlength(4) packlength(4)
{ {
flags|= BLOB_FLAG; flags|= BLOB_FLAG;
} }
Field_blob(uint32 len_arg,bool maybe_null_arg, Field_blob(uint32 len_arg,bool maybe_null_arg,
const LEX_CSTRING *field_name_arg, const LEX_CSTRING *field_name_arg,
CHARSET_INFO *cs, bool set_packlength) const DTCollation &collation, bool set_packlength)
:Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, :Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
NONE, field_name_arg, cs) NONE, field_name_arg, collation)
{ {
flags|= BLOB_FLAG; flags|= BLOB_FLAG;
packlength= 4; packlength= 4;
@@ -3252,8 +3232,24 @@ public:
:Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, &temp_lex_str, :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, &temp_lex_str,
system_charset_info), system_charset_info),
packlength(packlength_arg) {} packlength(packlength_arg) {}
const Type_handler *type_handler() const;
/* Note that the default copy constructor is used, in clone() */ /* Note that the default copy constructor is used, in clone() */
enum_field_types type() const { return MYSQL_TYPE_BLOB;} enum_field_types type() const
{
/*
We cannot return type_handler()->field_type() here.
Some pieces of the code (e.g. in engines) rely on the fact
that Field::type(), Field::real_type() and Item_field::field_type()
return MYSQL_TYPE_BLOB for all blob variants.
We should eventually fix all such code pieces to expect
all BLOB type codes.
*/
return MYSQL_TYPE_BLOB;
}
enum_field_types real_type() const
{
return MYSQL_TYPE_BLOB;
}
enum ha_base_keytype key_type() const enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; } { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
Copy_func *get_copy_func(const Field *from) const Copy_func *get_copy_func(const Field *from) const
@@ -3438,12 +3434,19 @@ public:
:Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg, share, blob_pack_length, &my_charset_bin) field_name_arg, share, blob_pack_length, &my_charset_bin)
{ geom_type= geom_type_arg; srid= field_srid; } { 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; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; } const Type_handler *type_handler() const
{
return &type_handler_geometry;
}
enum_field_types type() const
{
return MYSQL_TYPE_GEOMETRY;
}
enum_field_types real_type() const
{
return MYSQL_TYPE_GEOMETRY;
}
bool can_optimize_range(const Item_bool_func *cond, bool can_optimize_range(const Item_bool_func *cond,
const Item *item, const Item *item,
bool is_eq_func) const; bool is_eq_func) const;
@@ -3492,20 +3495,15 @@ public:
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint packlength_arg, uint packlength_arg,
TYPELIB *typelib_arg, TYPELIB *typelib_arg,
CHARSET_INFO *charset_arg) const DTCollation &collation)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, charset_arg), unireg_check_arg, field_name_arg, collation),
packlength(packlength_arg),typelib(typelib_arg) packlength(packlength_arg),typelib(typelib_arg)
{ {
flags|=ENUM_FLAG; flags|=ENUM_FLAG;
} }
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
enum_field_types type() const { return MYSQL_TYPE_STRING; } const Type_handler *type_handler() const { return &type_handler_enum; }
enum Item_result cmp_type () const { return INT_RESULT; }
const Type_handler *cast_to_int_type_handler() const
{
return &type_handler_longlong;
}
enum ha_base_keytype key_type() const; enum ha_base_keytype key_type() const;
Copy_func *get_copy_func(const Field *from) const Copy_func *get_copy_func(const Field *from) const
{ {
@@ -3546,7 +3544,6 @@ public:
void store_type(ulonglong value); void store_type(ulonglong value);
void sql_type(String &str) const; void sql_type(String &str) const;
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return MYSQL_TYPE_ENUM; }
uint pack_length_from_metadata(uint field_metadata) uint pack_length_from_metadata(uint field_metadata)
{ return (field_metadata & 0x00ff); } { return (field_metadata & 0x00ff); }
uint row_pack_length() const { return pack_length(); } uint row_pack_length() const { return pack_length(); }
@@ -3576,6 +3573,9 @@ public:
*/ */
return false; return false;
} }
bool can_optimize_range(const Item_bool_func *cond,
const Item *item,
bool is_eq_func) const;
private: private:
int do_save_field_metadata(uchar *first_byte); int do_save_field_metadata(uchar *first_byte);
uint is_equal(Create_field *new_field); uint is_equal(Create_field *new_field);
@@ -3588,12 +3588,12 @@ public:
uchar null_bit_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint32 packlength_arg, uint32 packlength_arg,
TYPELIB *typelib_arg, CHARSET_INFO *charset_arg) TYPELIB *typelib_arg, const DTCollation &collation)
:Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, :Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, unireg_check_arg, field_name_arg,
packlength_arg, packlength_arg,
typelib_arg,charset_arg), typelib_arg, collation),
empty_set_string("", 0, charset_arg) empty_set_string("", 0, collation.collation)
{ {
flags=(flags & ~ENUM_FLAG) | SET_FLAG; flags=(flags & ~ENUM_FLAG) | SET_FLAG;
} }
@@ -3606,7 +3606,7 @@ public:
String *val_str(String*,String *); String *val_str(String*,String *);
void sql_type(String &str) const; void sql_type(String &str) const;
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return MYSQL_TYPE_SET; } const Type_handler *type_handler() const { return &type_handler_set; }
bool has_charset(void) const { return TRUE; } bool has_charset(void) const { return TRUE; }
private: private:
const String empty_set_string; const String empty_set_string;
@@ -3636,13 +3636,12 @@ public:
Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg); enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg);
enum_field_types type() const { return MYSQL_TYPE_BIT; } const Type_handler *type_handler() const { return &type_handler_bit; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; }
uint32 key_length() const { return (uint32) (field_length + 7) / 8; } uint32 key_length() const { return (uint32) (field_length + 7) / 8; }
uint32 max_data_length() const { return (field_length + 7) / 8; } uint32 max_data_length() const { return (field_length + 7) / 8; }
uint32 max_display_length() { return field_length; } uint32 max_display_length() { return field_length; }
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
Item_result result_type () const { return INT_RESULT; }
int reset(void) { int reset(void) {
bzero(ptr, bytes_in_rec); bzero(ptr, bytes_in_rec);
if (bit_ptr && (bit_len > 0)) // reset odd bits among null bits if (bit_ptr && (bit_len > 0)) // reset odd bits among null bits

View File

@@ -518,7 +518,7 @@ Item::Item(THD *thd):
tables. tables.
*/ */
Item::Item(THD *thd, Item *item): Item::Item(THD *thd, Item *item):
Type_std_attributes(item), Type_all_attributes(item),
join_tab_idx(item->join_tab_idx), join_tab_idx(item->join_tab_idx),
is_expensive_cache(-1), is_expensive_cache(-1),
rsize(0), rsize(0),
@@ -2348,9 +2348,9 @@ void my_coll_agg_error(Item** args, uint count, const char *fname,
} }
bool Item_func_or_sum::agg_item_collations(DTCollation &c, const char *fname, bool Type_std_attributes::agg_item_collations(DTCollation &c, const char *fname,
Item **av, uint count, Item **av, uint count,
uint flags, int item_sep) uint flags, int item_sep)
{ {
uint i; uint i;
Item **arg; Item **arg;
@@ -2395,10 +2395,10 @@ bool Item_func_or_sum::agg_item_collations(DTCollation &c, const char *fname,
} }
bool Item_func_or_sum::agg_item_set_converter(const DTCollation &coll, bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll,
const char *fname, const char *fname,
Item **args, uint nargs, Item **args, uint nargs,
uint flags, int item_sep) uint flags, int item_sep)
{ {
Item **arg, *safe_args[2]= {NULL, NULL}; Item **arg, *safe_args[2]= {NULL, NULL};
@@ -3780,7 +3780,7 @@ bool Item_param::set_from_item(THD *thd, Item *item)
} }
} }
struct st_value tmp; struct st_value tmp;
if (!item->store(&tmp, 0)) if (!item->save_in_value(&tmp))
{ {
unsigned_flag= item->unsigned_flag; unsigned_flag= item->unsigned_flag;
switch (item->cmp_type()) { switch (item->cmp_type()) {
@@ -5834,24 +5834,6 @@ error:
} }
const Type_handler *Item_field::real_type_handler() const
{
/*
Item_field::field_type ask Field_type() but sometimes field return
a different type, like for enum/set, so we need to ask real type.
*/
if (field->is_created_from_null_item)
return &type_handler_null;
/* work around about varchar type field detection */
enum_field_types type= field->real_type();
// 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;
return Type_handler::get_handler_by_real_type(type);
}
/* /*
@brief @brief
Mark virtual columns as used in a partitioning expression Mark virtual columns as used in a partitioning expression
@@ -6216,178 +6198,6 @@ bool Item::eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs)
} }
/**
Create a field to hold a string value from an item.
If too_big_for_varchar() create a blob @n
If max_length > 0 create a varchar @n
If max_length == 0 create a CHAR(0)
@param table Table for which the field is created
*/
Field *Item::make_string_field(TABLE *table)
{
Field *field;
MEM_ROOT *mem_root= table->in_use->mem_root;
DBUG_ASSERT(collation.collation);
/*
Note: the following check is repeated in
subquery_types_allow_materialization():
*/
if (too_big_for_varchar())
field= new (mem_root)
Field_blob(max_length, maybe_null, &name,
collation.collation, TRUE);
/* Item_type_holder holds the exact type, do not change it */
else if (max_length > 0 &&
(type() != Item::TYPE_HOLDER || field_type() != MYSQL_TYPE_STRING))
field= new (mem_root)
Field_varstring(max_length, maybe_null, &name, table->s,
collation.collation);
else
field= new (mem_root)
Field_string(max_length, maybe_null, &name, collation.collation);
if (field)
field->init(table);
return field;
}
/**
Create a field based on field_type of argument.
This is used to create a field for
- IFNULL(x,something)
- time functions
- prepared statement placeholders
- SP variables with data type references: DECLARE a t1.a%TYPE;
@retval
NULL error
@retval
\# Created field
*/
Field *Item::tmp_table_field_from_field_type(TABLE *table,
bool fixed_length,
bool set_blob_packlength)
{
/*
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;
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 */
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 */
}
if (field)
field->init(table);
return field;
}
/* ARGSUSED */ /* ARGSUSED */
void Item_field::make_field(THD *thd, Send_field *tmp_field) void Item_field::make_field(THD *thd, Send_field *tmp_field)
{ {
@@ -8945,7 +8755,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
real_arg= arg->real_item(); real_arg= arg->real_item();
if (real_arg->type() != FIELD_ITEM) if (real_arg->type() != FIELD_ITEM)
{ {
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name); my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name.str);
goto error; goto error;
} }
@@ -9715,9 +9525,8 @@ Item_cache_temporal::Item_cache_temporal(THD *thd,
enum_field_types field_type_arg): enum_field_types field_type_arg):
Item_cache_int(thd, field_type_arg) Item_cache_int(thd, field_type_arg)
{ {
if (mysql_type_to_time_type(Item_cache_temporal::field_type()) == if (mysql_timestamp_type() == MYSQL_TIMESTAMP_ERROR)
MYSQL_TIMESTAMP_ERROR) set_handler(&type_handler_datetime2);
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
} }
@@ -9825,7 +9634,7 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
} }
unpack_time(value, ltime); unpack_time(value, ltime);
ltime->time_type= mysql_type_to_time_type(field_type()); ltime->time_type= mysql_timestamp_type();
if (ltime->time_type == MYSQL_TIMESTAMP_TIME) if (ltime->time_type == MYSQL_TIMESTAMP_TIME)
{ {
ltime->hour+= (ltime->month*32+ltime->day)*24; ltime->hour+= (ltime->month*32+ltime->day)*24;
@@ -10267,7 +10076,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
if (aggregate_for_result(item_type_handler)) if (aggregate_for_result(item_type_handler))
{ {
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0), my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
Item_type_holder::type_handler()->name().ptr(), Item_type_holder::real_type_handler()->name().ptr(),
item_type_handler->name().ptr(), item_type_handler->name().ptr(),
"UNION"); "UNION");
DBUG_RETURN(true); DBUG_RETURN(true);
@@ -10375,6 +10184,14 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
}; };
maybe_null|= item->maybe_null; maybe_null|= item->maybe_null;
get_full_info(item); get_full_info(item);
/*
Adjust data type for union, e.g.:
- convert type_handler_null to type_handler_string
- convert type_handler_olddecimal to type_handler_newdecimal
- adjust varchar/blob according to max_length
*/
set_handler(Item_type_holder::
real_type_handler()->type_handler_for_union(this));
/* Remember decimal integer part to be used in DECIMAL_RESULT handleng */ /* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
prev_decimal_int_part= decimal_int_part(); prev_decimal_int_part= decimal_int_part();
@@ -10385,56 +10202,6 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
} }
/**
Make temporary table field according collected information about type
of UNION result.
@param table temporary table for which we create fields
@return
created field
*/
Field *Item_type_holder::make_field_by_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;
switch (Item_type_holder::real_type_handler()->real_field_type()) {
case MYSQL_TYPE_ENUM:
{
DBUG_ASSERT(enum_set_typelib);
field= new Field_enum((uchar *) 0, max_length, null_ptr, 0,
Field::NONE, &name,
get_enum_pack_length(enum_set_typelib->count),
enum_set_typelib, collation.collation);
if (field)
field->init(table);
return field;
}
case MYSQL_TYPE_SET:
{
DBUG_ASSERT(enum_set_typelib);
field= new Field_set((uchar *) 0, max_length, null_ptr, 0,
Field::NONE, &name,
get_set_pack_length(enum_set_typelib->count),
enum_set_typelib, collation.collation);
if (field)
field->init(table);
return field;
}
case MYSQL_TYPE_NULL:
return make_string_field(table);
default:
break;
}
return tmp_table_field_from_field_type(table, false, true);
}
/** /**
Get full information from Item about enum/set fields to be able to create Get full information from Item about enum/set fields to be able to create
them later. them later.

View File

@@ -483,7 +483,7 @@ public:
class Item: public Value_source, class Item: public Value_source,
public Type_std_attributes public Type_all_attributes
{ {
void operator=(Item &); void operator=(Item &);
/** /**
@@ -536,10 +536,22 @@ protected:
SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param); 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, Create a field based on field_type of argument.
bool fixed_length, This is used to create a field for
bool set_blob_packlength); - IFNULL(x,something)
- time functions
- prepared statement placeholders
- SP variables with data type references: DECLARE a TYPE OF t1.a;
@retval NULL error
@retval !NULL on success
*/
Field *tmp_table_field_from_field_type(TABLE *table)
{
const Type_handler *h= type_handler()->type_handler_for_tmp_table(this);
return h->make_and_init_table_field(&name, Record_addr(maybe_null),
*this, table);
}
Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length); Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length);
void push_note_converted_to_negative_complement(THD *thd); void push_note_converted_to_negative_complement(THD *thd);
@@ -664,54 +676,9 @@ public:
*/ */
virtual inline void quick_fix_field() { fixed= 1; } virtual inline void quick_fix_field() { fixed= 1; }
bool store(struct st_value *value, ulonglong fuzzydate) bool save_in_value(struct st_value *value)
{ {
switch (cmp_type()) { return type_handler()->Item_save_in_value(this, value);
case INT_RESULT:
{
value->m_type= unsigned_flag ? DYN_COL_UINT : DYN_COL_INT;
value->value.m_longlong= val_int();
break;
}
case REAL_RESULT:
{
value->m_type= DYN_COL_DOUBLE;
value->value.m_double= val_real();
break;
}
case DECIMAL_RESULT:
{
value->m_type= DYN_COL_DECIMAL;
my_decimal *dec= val_decimal(&value->m_decimal);
if (dec != &value->m_decimal && !null_value)
my_decimal2decimal(dec, &value->m_decimal);
break;
}
case STRING_RESULT:
{
value->m_type= DYN_COL_STRING;
String *str= val_str(&value->m_string);
if (str != &value->m_string && !null_value)
value->m_string.set(str->ptr(), str->length(), str->charset());
break;
}
case TIME_RESULT:
{
value->m_type= DYN_COL_DATETIME;
get_date(&value->value.m_time, fuzzydate);
break;
}
case ROW_RESULT:
DBUG_ASSERT(false);
null_value= true;
break;
}
if (null_value)
{
value->m_type= DYN_COL_NULL;
return true;
}
return false;
} }
/* Function returns 1 on overflow and -1 on fatal errors */ /* Function returns 1 on overflow and -1 on fatal errors */
@@ -1150,10 +1117,7 @@ public:
*/ */
uint decimal_scale() const uint decimal_scale() const
{ {
return decimals < NOT_FIXED_DEC ? decimals : return type_handler()->Item_decimal_scale(this);
is_temporal_type_with_time(field_type()) ?
TIME_SECOND_PART_DIGITS :
MY_MIN(max_length, DECIMAL_MAX_SCALE);
} }
/* /*
Returns how many digits a divisor adds into a division result. Returns how many digits a divisor adds into a division result.
@@ -1174,10 +1138,7 @@ public:
*/ */
uint divisor_precision_increment() const uint divisor_precision_increment() const
{ {
return decimals < NOT_FIXED_DEC ? decimals : return type_handler()->Item_divisor_precision_increment(this);
is_temporal_type_with_time(field_type()) ?
TIME_SECOND_PART_DIGITS :
decimals;
} }
/** /**
TIME or DATETIME precision of the item: 0..6 TIME or DATETIME precision of the item: 0..6
@@ -1745,6 +1706,8 @@ public:
} }
virtual Field::geometry_type get_geometry_type() const virtual Field::geometry_type get_geometry_type() const
{ return Field::GEOM_GEOMETRY; }; { return Field::GEOM_GEOMETRY; };
uint uint_geometry_type() const
{ return get_geometry_type(); }
String *check_well_formed_result(String *str, bool send_error= 0); String *check_well_formed_result(String *str, bool send_error= 0);
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs); bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
bool too_big_for_varchar() const bool too_big_for_varchar() const
@@ -2263,7 +2226,7 @@ public:
based on result_type(), which is less exact. based on result_type(), which is less exact.
*/ */
Field *create_field_for_create_select(TABLE *table) 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); }
}; };
@@ -2639,19 +2602,29 @@ public:
fast_field_copier setup_fast_field_copier(Field *field); fast_field_copier setup_fast_field_copier(Field *field);
table_map used_tables() const; table_map used_tables() const;
table_map all_used_tables() const; table_map all_used_tables() const;
const Type_handler *type_handler() const
{
const Type_handler *handler= field->type_handler();
return handler->type_handler_for_item_field();
}
enum Item_result result_type () const enum Item_result result_type () const
{ {
return field->result_type(); return field->result_type();
} }
const Type_handler *cast_to_int_type_handler() const const Type_handler *cast_to_int_type_handler() const
{ {
return field->cast_to_int_type_handler(); return field->type_handler()->cast_to_int_type_handler();
} }
enum_field_types field_type() const enum_field_types field_type() const
{ {
return field->type(); return field->type();
} }
const Type_handler *real_type_handler() const; const Type_handler *real_type_handler() const
{
if (field->is_created_from_null_item)
return &type_handler_null;
return field->type_handler();
}
enum_monotonicity_info get_monotonicity_info() const enum_monotonicity_info get_monotonicity_info() const
{ {
return MONOTONIC_STRICT_INCREASING; return MONOTONIC_STRICT_INCREASING;
@@ -3187,6 +3160,17 @@ public:
enum Type type() const { return INT_ITEM; } enum Type type() const { return INT_ITEM; }
enum Item_result result_type () const { return INT_RESULT; } enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
const Type_handler *type_handler() const
{
// The same condition is repeated in Item::create_tmp_field()
if (max_length > MY_INT32_NUM_DECIMAL_DIGITS - 2)
return &type_handler_longlong;
return &type_handler_long;
}
Field *create_tmp_field(bool group, TABLE *table)
{ return tmp_table_field_from_field_type(table); }
Field *create_field_for_create_select(TABLE *table)
{ return tmp_table_field_from_field_type(table); }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
@@ -3645,7 +3629,14 @@ public:
Item_partition_func_safe_string(thd, name_arg, safe_strlen(name_arg), &my_charset_bin) Item_partition_func_safe_string(thd, name_arg, safe_strlen(name_arg), &my_charset_bin)
{ max_length= length; } { max_length= length; }
enum Type type() const { return TYPE_HOLDER; } 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 const Type_handler *real_type_handler() const
{ {
// Should not be called, Item_blob is used for SHOW purposes only. // Should not be called, Item_blob is used for SHOW purposes only.
@@ -3653,7 +3644,7 @@ public:
return &type_handler_varchar; return &type_handler_varchar;
} }
Field *create_field_for_schema(THD *thd, TABLE *table) 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); }
}; };
@@ -3690,6 +3681,10 @@ public:
unsigned_flag=1; unsigned_flag=1;
} }
enum_field_types field_type() const { return int_field_type; } enum_field_types field_type() const { return int_field_type; }
const Type_handler *type_handler() const
{
return Type_handler::get_handler_by_field_type(int_field_type);
}
}; };
@@ -4068,80 +4063,31 @@ class Item_func_or_sum: public Item_result_field,
public Item_args, public Item_args,
public Used_tables_and_const_cache public Used_tables_and_const_cache
{ {
bool agg_item_collations(DTCollation &c, const char *name,
Item **items, uint nitems,
uint flags, int item_sep);
bool agg_item_set_converter(const DTCollation &coll, const char *fname,
Item **args, uint nargs,
uint flags, int item_sep);
protected: protected:
/*
Collect arguments' character sets together.
We allow to apply automatic character set conversion in some cases.
The conditions when conversion is possible are:
- arguments A and B have different charsets
- A wins according to coercibility rules
(i.e. a column is stronger than a string constant,
an explicit COLLATE clause is stronger than a column)
- character set of A is either superset for character set of B,
or B is a string constant which can be converted into the
character set of A without data loss.
If all of the above is true, then it's possible to convert
B into the character set of A, and then compare according
to the collation of A.
For functions with more than two arguments:
collect(A,B,C) ::= collect(collect(A,B),C)
Since this function calls THD::change_item_tree() on the passed Item **
pointers, it is necessary to pass the original Item **'s, not copies.
Otherwise their values will not be properly restored (see BUG#20769).
If the items are not consecutive (eg. args[2] and args[5]), use the
item_sep argument, ie.
agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
*/
bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
uint flags, int item_sep) uint flags, int item_sep)
{ {
if (agg_item_collations(c, func_name(), items, nitems, flags, item_sep)) return Type_std_attributes::agg_arg_charsets(c, func_name(),
return true; items, nitems,
flags, item_sep);
return agg_item_set_converter(c, func_name(), items, nitems,
flags, item_sep);
} }
/*
Aggregate arguments for string result, e.g: CONCAT(a,b)
- convert to @@character_set_connection if all arguments are numbers
- allow DERIVATION_NONE
*/
bool agg_arg_charsets_for_string_result(DTCollation &c, bool agg_arg_charsets_for_string_result(DTCollation &c,
Item **items, uint nitems, Item **items, uint nitems,
int item_sep= 1) int item_sep= 1)
{ {
uint flags= MY_COLL_ALLOW_SUPERSET_CONV | return Type_std_attributes::
MY_COLL_ALLOW_COERCIBLE_CONV | agg_arg_charsets_for_string_result(c, func_name(),
MY_COLL_ALLOW_NUMERIC_CONV; items, nitems, item_sep);
return agg_arg_charsets(c, items, nitems, flags, item_sep);
} }
/*
Aggregate arguments for string result, when some comparison
is involved internally, e.g: REPLACE(a,b,c)
- convert to @@character_set_connection if all arguments are numbers
- disallow DERIVATION_NONE
*/
bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c, bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c,
Item **items, Item **items,
uint nitems, uint nitems,
int item_sep= 1) int item_sep= 1)
{ {
uint flags= MY_COLL_ALLOW_SUPERSET_CONV | return Type_std_attributes::
MY_COLL_ALLOW_COERCIBLE_CONV | agg_arg_charsets_for_string_result_with_comparison(c, func_name(),
MY_COLL_ALLOW_NUMERIC_CONV | items, nitems,
MY_COLL_DISALLOW_NONE; item_sep);
return agg_arg_charsets(c, items, nitems, flags, item_sep);
} }
/* /*
@@ -4153,13 +4099,10 @@ protected:
Item **items, uint nitems, Item **items, uint nitems,
int item_sep= 1) int item_sep= 1)
{ {
uint flags= MY_COLL_ALLOW_SUPERSET_CONV | return Type_std_attributes::
MY_COLL_ALLOW_COERCIBLE_CONV | agg_arg_charsets_for_comparison(c, func_name(), items, nitems, item_sep);
MY_COLL_DISALLOW_NONE;
return agg_arg_charsets(c, items, nitems, flags, item_sep);
} }
public: public:
// This method is used by Arg_comparator // This method is used by Arg_comparator
bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b) bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b)
@@ -5879,11 +5822,12 @@ public:
Item_type_holder(THD*, Item*); Item_type_holder(THD*, Item*);
const Type_handler *type_handler() const const Type_handler *type_handler() const
{ return Type_handler_hybrid_field_type::type_handler(); } {
const Type_handler *handler= Type_handler_hybrid_field_type::type_handler();
return handler->type_handler_for_item_field();
}
enum_field_types field_type() const enum_field_types field_type() const
{ return Type_handler_hybrid_field_type::field_type(); } { return Type_handler_hybrid_field_type::field_type(); }
enum_field_types real_field_type() const
{ return Type_handler_hybrid_field_type::real_field_type(); }
enum Item_result result_type () const enum Item_result result_type () const
{ {
/* /*
@@ -5902,16 +5846,22 @@ public:
} }
const Type_handler *real_type_handler() const const Type_handler *real_type_handler() const
{ {
return Item_type_holder::type_handler(); return Type_handler_hybrid_field_type::type_handler();
} }
enum Type type() const { return TYPE_HOLDER; } enum Type type() const { return TYPE_HOLDER; }
TYPELIB *get_typelib() const { return enum_set_typelib; }
double val_real(); double val_real();
longlong val_int(); longlong val_int();
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
String *val_str(String*); String *val_str(String*);
bool join_types(THD *thd, Item *); bool join_types(THD *thd, Item *);
Field *make_field_by_type(TABLE *table); Field *create_tmp_field(bool group, TABLE *table)
{
return Item_type_holder::real_type_handler()->
make_and_init_table_field(&name, Record_addr(maybe_null),
*this, table);
}
Field::geometry_type get_geometry_type() const { return geometry_type; }; Field::geometry_type get_geometry_type() const { return geometry_type; };
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
}; };

View File

@@ -2577,7 +2577,7 @@ Item_func_nullif::fix_length_and_dec()
thd->change_item_tree(&args[0], m_cache); thd->change_item_tree(&args[0], m_cache);
thd->change_item_tree(&args[2], 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); collation.set(args[2]->collation);
decimals= args[2]->decimals; decimals= args[2]->decimals;
unsigned_flag= args[2]->unsigned_flag; unsigned_flag= args[2]->unsigned_flag;

View File

@@ -1057,7 +1057,7 @@ public:
} }
const char *func_name() const { return "ifnull"; } const char *func_name() const { return "ifnull"; }
Field *create_field_for_create_select(TABLE *table) 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; } table_map not_null_tables() const { return 0; }
uint decimal_precision() const uint decimal_precision() const

View File

@@ -592,99 +592,6 @@ void Item_udf_func::fix_num_length_and_dec()
} }
/**
Set max_length/decimals of function if function is fixed point and
result length/precision depends on argument ones.
*/
void Item_func::count_decimal_length(Item **item, uint nitems)
{
int max_int_part= 0;
decimals= 0;
unsigned_flag= 1;
for (uint i=0 ; i < nitems ; i++)
{
set_if_bigger(decimals, item[i]->decimals);
set_if_bigger(max_int_part, item[i]->decimal_int_part());
set_if_smaller(unsigned_flag, item[i]->unsigned_flag);
}
int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION);
fix_char_length(my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag));
}
/**
Set max_length of if it is maximum length of its arguments.
*/
void Item_func::count_only_length(Item **item, uint nitems)
{
uint32 char_length= 0;
unsigned_flag= 0;
for (uint i= 0; i < nitems ; i++)
{
set_if_bigger(char_length, item[i]->max_char_length());
set_if_bigger(unsigned_flag, item[i]->unsigned_flag);
}
fix_char_length(char_length);
}
/**
Set max_length/decimals of function if function is floating point and
result length/precision depends on argument ones.
*/
void Item_func::count_real_length(Item **items, uint nitems)
{
uint32 length= 0;
decimals= 0;
max_length= 0;
unsigned_flag= false;
for (uint i=0 ; i < nitems ; i++)
{
if (decimals < FLOATING_POINT_DECIMALS)
{
set_if_bigger(decimals, items[i]->decimals);
/* Will be ignored if items[i]->decimals >= FLOATING_POINT_DECIMALS */
set_if_bigger(length, (items[i]->max_length - items[i]->decimals));
}
set_if_bigger(max_length, items[i]->max_length);
}
if (decimals < FLOATING_POINT_DECIMALS)
{
max_length= length;
length+= decimals;
if (length < max_length) // If previous operation gave overflow
max_length= UINT_MAX32;
else
max_length= length;
}
}
/**
Calculate max_length and decimals for string functions.
@param field_type Field type.
@param items Argument array.
@param nitems Number of arguments.
@retval False on success, true on error.
*/
bool Item_func::count_string_length(Item **items, uint nitems)
{
DBUG_ASSERT(!is_temporal_type(field_type()));
if (agg_arg_charsets_for_string_result(collation, items, nitems, 1))
return true;
count_only_length(items, nitems);
decimals= max_length ? NOT_FIXED_DEC : 0;
return false;
}
void Item_func::signal_divide_by_null() void Item_func::signal_divide_by_null()
{ {
THD *thd= current_thd; THD *thd= current_thd;
@@ -890,7 +797,7 @@ String *Item_func_hybrid_field_type::val_str_from_date_op(String *str)
if (date_op_with_null_check(&ltime) || if (date_op_with_null_check(&ltime) ||
(null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH))) (null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH)))
return (String *) 0; return (String *) 0;
ltime.time_type= mysql_type_to_time_type(field_type()); ltime.time_type= mysql_timestamp_type();
str->length(my_TIME_to_str(&ltime, const_cast<char*>(str->ptr()), decimals)); str->length(my_TIME_to_str(&ltime, const_cast<char*>(str->ptr()), decimals));
str->set_charset(&my_charset_bin); str->set_charset(&my_charset_bin);
DBUG_ASSERT(!null_value); DBUG_ASSERT(!null_value);
@@ -902,7 +809,7 @@ double Item_func_hybrid_field_type::val_real_from_date_op()
MYSQL_TIME ltime; MYSQL_TIME ltime;
if (date_op_with_null_check(&ltime)) if (date_op_with_null_check(&ltime))
return 0; return 0;
ltime.time_type= mysql_type_to_time_type(field_type()); ltime.time_type= mysql_timestamp_type();
return TIME_to_double(&ltime); return TIME_to_double(&ltime);
} }
@@ -911,7 +818,7 @@ longlong Item_func_hybrid_field_type::val_int_from_date_op()
MYSQL_TIME ltime; MYSQL_TIME ltime;
if (date_op_with_null_check(&ltime)) if (date_op_with_null_check(&ltime))
return 0; return 0;
ltime.time_type= mysql_type_to_time_type(field_type()); ltime.time_type= mysql_timestamp_type();
return TIME_to_ulonglong(&ltime); return TIME_to_ulonglong(&ltime);
} }
@@ -924,7 +831,7 @@ Item_func_hybrid_field_type::val_decimal_from_date_op(my_decimal *dec)
my_decimal_set_zero(dec); my_decimal_set_zero(dec);
return 0; return 0;
} }
ltime.time_type= mysql_type_to_time_type(field_type()); ltime.time_type= mysql_timestamp_type();
return date2my_decimal(&ltime, dec); return date2my_decimal(&ltime, dec);
} }
@@ -2255,8 +2162,8 @@ void Item_func_int_val::fix_length_and_dec_int_or_decimal()
{ {
ulonglong tmp_max_length= (ulonglong ) args[0]->max_length - ulonglong tmp_max_length= (ulonglong ) args[0]->max_length -
(args[0]->decimals ? args[0]->decimals + 1 : 0) + 2; (args[0]->decimals ? args[0]->decimals + 1 : 0) + 2;
max_length= tmp_max_length > (ulonglong) 4294967295U ? max_length= tmp_max_length > (ulonglong) UINT_MAX32 ?
(uint32) 4294967295U : (uint32) tmp_max_length; (uint32) UINT_MAX32 : (uint32) tmp_max_length;
uint tmp= float_length(decimals); uint tmp= float_length(decimals);
set_if_smaller(max_length,tmp); set_if_smaller(max_length,tmp);
decimals= 0; decimals= 0;

View File

@@ -42,44 +42,8 @@ protected:
uint allowed_arg_cols; uint allowed_arg_cols;
String *val_str_from_val_str_ascii(String *str, String *str2); String *val_str_from_val_str_ascii(String *str, String *str2);
void count_only_length(Item **item, uint nitems);
void count_real_length(Item **item, uint nitems);
void count_decimal_length(Item **item, uint nitems);
bool count_string_length(Item **item, uint nitems);
uint count_max_decimals(Item **item, uint nitems)
{
uint res= 0;
for (uint i= 0; i < nitems; i++)
set_if_bigger(res, item[i]->decimals);
return res;
}
virtual bool check_allowed_arg_cols(uint argno); virtual bool check_allowed_arg_cols(uint argno);
public: public:
void aggregate_attributes_int(Item **items, uint nitems)
{
collation.set_numeric();
count_only_length(items, nitems);
decimals= 0;
}
void aggregate_attributes_real(Item **items, uint nitems)
{
collation.set_numeric();
count_real_length(items, nitems);
}
void aggregate_attributes_decimal(Item **items, uint nitems)
{
collation.set_numeric();
count_decimal_length(items, nitems);
}
bool aggregate_attributes_string(Item **item, uint nitems)
{
return count_string_length(item, nitems);
}
void aggregate_attributes_temporal(uint int_part_length,
Item **item, uint nitems)
{
fix_attributes_temporal(int_part_length, count_max_decimals(item, nitems));
}
table_map not_null_tables_cache; table_map not_null_tables_cache;
@@ -208,7 +172,7 @@ public:
{ {
return result_type() != STRING_RESULT ? return result_type() != STRING_RESULT ?
create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) : 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); Item *get_tmp_table_item(THD *thd);
@@ -2255,12 +2219,6 @@ public:
bool update(); bool update();
bool fix_fields(THD *thd, Item **ref); bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec(); 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 table_map used_tables() const
{ {
return used_tables_cache | RAND_TABLE_BIT; return used_tables_cache | RAND_TABLE_BIT;
@@ -2302,6 +2260,14 @@ public:
my_decimal *val_decimal(my_decimal*); my_decimal *val_decimal(my_decimal*);
String *val_str(String* str); String *val_str(String* str);
void fix_length_and_dec(); 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); virtual void print(String *str, enum_query_type query_type);
/* /*
We must always return variables as strings to guard against selects of type We must always return variables as strings to guard against selects of type
@@ -2655,7 +2621,7 @@ public:
{ {
return result_type() != STRING_RESULT ? return result_type() != STRING_RESULT ?
sp_result_field : 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); void make_field(THD *thd, Send_field *tmp_field);

View File

@@ -40,20 +40,11 @@
#include "opt_range.h" #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() void Item_geometry_func::fix_length_and_dec()
{ {
collation.set(&my_charset_bin); collation.set(&my_charset_bin);
decimals=0; decimals=0;
max_length= (uint32) 4294967295U; max_length= (uint32) UINT_MAX32;
maybe_null= 1; 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() void Item_func_as_wkt::fix_length_and_dec()
{ {
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
max_length=MAX_BLOB_WIDTH; max_length= (uint32) UINT_MAX32;
maybe_null= 1; maybe_null= 1;
} }

View File

@@ -40,7 +40,6 @@ public:
Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {} Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
void fix_length_and_dec(); void fix_length_and_dec();
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } 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 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) {} Item_func_as_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
const char *func_name() const { return "st_aswkb"; } const char *func_name() const { return "st_aswkb"; }
String *val_str(String *); 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) Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_as_wkb>(thd, mem_root, this); } { return get_item_copy<Item_func_as_wkb>(thd, mem_root, this); }
}; };

View File

@@ -1074,7 +1074,7 @@ public:
} }
void fix_length_and_dec() void fix_length_and_dec()
{ {
collation.set(default_charset()); collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
decimals=0; decimals=0;
fix_char_length(args[0]->max_length * 2); fix_char_length(args[0]->max_length * 2);
m_arg0_type_handler= args[0]->type_handler(); m_arg0_type_handler= args[0]->type_handler();

View File

@@ -1202,51 +1202,15 @@ void Item_sum_hybrid::setup_hybrid(THD *thd, Item *item, Item *value_arg)
Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table) Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table)
{ {
Field *field;
MEM_ROOT *mem_root;
if (args[0]->type() == Item::FIELD_ITEM) if (args[0]->type() == Item::FIELD_ITEM)
{ {
field= ((Item_field*) args[0])->field; Field *field= ((Item_field*) args[0])->field;
if ((field= create_tmp_field_from_field(table->in_use, field, &name, if ((field= create_tmp_field_from_field(table->in_use, field, &name,
table, NULL))) table, NULL)))
field->flags&= ~NOT_NULL_FLAG; field->flags&= ~NOT_NULL_FLAG;
return field; return field;
} }
return Item_sum::create_tmp_field(group, table);
/*
DATE/TIME fields have STRING_RESULT result types.
In order to preserve field type, it's needed to handle DATE/TIME
fields creations separately.
*/
mem_root= table->in_use->mem_root;
switch (args[0]->field_type()) {
case MYSQL_TYPE_DATE:
{
field= new (mem_root)
Field_newdate(0, maybe_null ? (uchar*)"" : 0, 0, Field::NONE,
&name);
break;
}
case MYSQL_TYPE_TIME:
{
field= new_Field_time(mem_root, 0, maybe_null ? (uchar*)"" : 0, 0,
Field::NONE, &name, decimals);
break;
}
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME:
{
field= new_Field_datetime(mem_root, 0, maybe_null ? (uchar*)"" : 0, 0,
Field::NONE, &name, decimals);
break;
}
default:
return Item_sum::create_tmp_field(group, table);
}
if (field)
field->init(table);
return field;
} }
@@ -1669,8 +1633,6 @@ Item *Item_sum_avg::copy_or_same(THD* thd)
Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table) Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table)
{ {
Field *field;
MEM_ROOT *mem_root= table->in_use->mem_root;
if (group) if (group)
{ {
@@ -1679,21 +1641,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 The easiest way is to do this is to store both value in a string
and unpack on access. 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) ? 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); 0, &name, &my_charset_bin);
if (field)
field->init(table);
return field;
} }
else if (Item_sum_avg::result_type() == DECIMAL_RESULT) return tmp_table_field_from_field_type(table);
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;
} }
@@ -3362,24 +3318,6 @@ void Item_func_group_concat::cleanup()
} }
Field *Item_func_group_concat::make_string_field(TABLE *table_arg)
{
Field *field;
DBUG_ASSERT(collation.collation);
if (too_big_for_varchar())
field= new Field_blob(max_length,
maybe_null, &name, collation.collation, TRUE);
else
field= new Field_varstring(max_length,
maybe_null, &name, table_arg->s, collation.collation);
if (field)
field->init(table_arg);
return field;
}
Item *Item_func_group_concat::copy_or_same(THD* thd) Item *Item_func_group_concat::copy_or_same(THD* thd)
{ {
return new (thd->mem_root) Item_func_group_concat(thd, this); return new (thd->mem_root) Item_func_group_concat(thd, this);

View File

@@ -1636,9 +1636,6 @@ class Item_func_group_concat : public Item_sum
friend int dump_leaf_key(void* key_arg, friend int dump_leaf_key(void* key_arg,
element_count count __attribute__((unused)), element_count count __attribute__((unused)),
void* item_arg); void* item_arg);
protected:
virtual Field *make_string_field(TABLE *table);
public: public:
Item_func_group_concat(THD *thd, Name_resolution_context *context_arg, Item_func_group_concat(THD *thd, Name_resolution_context *context_arg,
bool is_distinct, List<Item> *is_select, bool is_distinct, List<Item> *is_select,

View File

@@ -1532,7 +1532,7 @@ String *Item_temporal_hybrid_func::val_str_ascii(String *str)
/* Check that the returned timestamp type matches to the function type */ /* Check that the returned timestamp type matches to the function type */
DBUG_ASSERT(field_type() == MYSQL_TYPE_STRING || DBUG_ASSERT(field_type() == MYSQL_TYPE_STRING ||
ltime.time_type == MYSQL_TIMESTAMP_NONE || ltime.time_type == MYSQL_TIMESTAMP_NONE ||
mysql_type_to_time_type(field_type()) == ltime.time_type); ltime.time_type == mysql_timestamp_type());
return str; return str;
} }
@@ -3226,7 +3226,7 @@ void Item_func_str_to_date::fix_length_and_dec()
} }
} }
} }
cached_timestamp_type= mysql_type_to_time_type(field_type()); cached_timestamp_type= mysql_timestamp_type();
} }

View File

@@ -536,7 +536,7 @@ public:
my_decimal *val_decimal(my_decimal *decimal_value) my_decimal *val_decimal(my_decimal *decimal_value)
{ return val_decimal_from_date(decimal_value); } { return val_decimal_from_date(decimal_value); }
Field *create_field_for_create_select(TABLE *table) 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) int save_in_field(Field *field, bool no_conversions)
{ return save_date_in_field(field, no_conversions); } { return save_date_in_field(field, no_conversions); }
}; };
@@ -1018,7 +1018,7 @@ class Item_extract :public Item_int_func
return true; return true;
} }
Field *create_field_for_create_select(TABLE *table) 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) Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_extract>(thd, mem_root, this); } { return get_item_copy<Item_extract>(thd, mem_root, this); }

View File

@@ -7926,7 +7926,9 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param,
if (!(res= value->val_str(&tmp))) if (!(res= value->val_str(&tmp)))
DBUG_RETURN(&null_element); DBUG_RETURN(&null_element);
if (field->cmp_type() != STRING_RESULT) if (field->cmp_type() != STRING_RESULT ||
field->type_handler() == &type_handler_enum ||
field->type_handler() == &type_handler_set)
DBUG_RETURN(0); DBUG_RETURN(0);
/* /*
@@ -8022,19 +8024,31 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
goto end; goto end;
err= value->save_in_field_no_warnings(field, 1); err= value->save_in_field_no_warnings(field, 1);
if (err == 2 && field->cmp_type() == STRING_RESULT)
{
if (type == EQ_FUNC || type == EQUAL_FUNC)
{
tree= new (alloc) SEL_ARG(field, 0, 0);
tree->type= SEL_ARG::IMPOSSIBLE;
}
else
tree= NULL; /* Cannot infer anything */
goto end;
}
if (err > 0) if (err > 0)
{ {
if (field->type_handler() == &type_handler_enum ||
field->type_handler() == &type_handler_set)
{
if (type == EQ_FUNC || type == EQUAL_FUNC)
{
tree= new (alloc) SEL_ARG(field, 0, 0);
tree->type= SEL_ARG::IMPOSSIBLE;
}
goto end;
}
if (err == 2 && field->cmp_type() == STRING_RESULT)
{
if (type == EQ_FUNC || type == EQUAL_FUNC)
{
tree= new (alloc) SEL_ARG(field, 0, 0);
tree->type= SEL_ARG::IMPOSSIBLE;
}
else
tree= NULL; /* Cannot infer anything */
goto end;
}
if (field->cmp_type() != value->result_type()) if (field->cmp_type() != value->result_type())
{ {
if ((type == EQ_FUNC || type == EQUAL_FUNC) && if ((type == EQ_FUNC || type == EQUAL_FUNC) &&

View File

@@ -843,34 +843,9 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM && all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM &&
inner->real_item()->type() == Item::FIELD_ITEM); inner->real_item()->type() == Item::FIELD_ITEM);
total_key_length += inner->max_length; total_key_length += inner->max_length;
if (outer->cmp_type() != inner->cmp_type()) if (!inner->type_handler()->subquery_type_allows_materialization(inner,
outer))
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
switch (outer->cmp_type()) {
case STRING_RESULT:
if (!(outer->collation.collation == inner->collation.collation))
DBUG_RETURN(FALSE);
// Materialization does not work with BLOB columns
if (inner->field_type() == MYSQL_TYPE_BLOB ||
inner->field_type() == MYSQL_TYPE_GEOMETRY)
DBUG_RETURN(FALSE);
/*
Materialization also is unable to work when create_tmp_table() will
create a blob column because item->max_length is too big.
The following check is copied from Item::make_string_field():
*/
if (inner->too_big_for_varchar())
{
DBUG_RETURN(FALSE);
}
break;
case TIME_RESULT:
if (mysql_type_to_time_type(outer->field_type()) !=
mysql_type_to_time_type(inner->field_type()))
DBUG_RETURN(FALSE);
default:
/* suitable for materialization */
break;
}
} }
/* /*

View File

@@ -1922,7 +1922,7 @@ void partition_info::report_part_expr_error(bool use_subpart_expr)
!(type == HASH_PARTITION && list_of_fields)) !(type == HASH_PARTITION && list_of_fields))
{ {
my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0), my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0),
item_field->name); item_field->name.str);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
} }

View File

@@ -2352,6 +2352,26 @@ bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
} }
Item_string *THD::make_string_literal(const char *str, size_t length,
uint repertoire)
{
if (!charset_is_collation_connection &&
(repertoire != MY_REPERTOIRE_ASCII ||
!my_charset_is_ascii_based(variables.collation_connection)))
{
LEX_STRING to;
if (convert_string(&to, variables.collation_connection,
str, length, variables.character_set_client))
return NULL;
str= to.str;
length= to.length;
}
return new (mem_root) Item_string(this, str, length,
variables.collation_connection,
DERIVATION_COERCIBLE, repertoire);
}
/* /*
Update some cache variables when character set changes Update some cache variables when character set changes
*/ */
@@ -3114,7 +3134,7 @@ int select_export::send_data(List<Item> &items)
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER_THD(thd, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), ER_THD(thd, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"string", printable_buff, "string", printable_buff,
item->name, static_cast<long>(row_count)); item->name.str, static_cast<long>(row_count));
} }
else if (copier.source_end_pos() < res->ptr() + res->length()) else if (copier.source_end_pos() < res->ptr() + res->length())
{ {

View File

@@ -3427,6 +3427,20 @@ public:
bool convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs); bool convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs);
/*
Create a string literal with optional client->connection conversion.
@param str - the string in the client character set
@param length - length of the string
@param repertoire - the repertoire of the string
*/
Item_string *make_string_literal(const char *str, size_t length,
uint repertoire);
Item_string *make_string_literal(const Lex_string_with_metadata_st &str)
{
uint repertoire= str.repertoire(variables.character_set_client);
return make_string_literal(str.str, str.length, repertoire);
}
void add_changed_table(TABLE *table); void add_changed_table(TABLE *table);
void add_changed_table(const char *key, long key_length); void add_changed_table(const char *key, long key_length);
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length); CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);

View File

@@ -749,6 +749,9 @@ public:
/* UNION methods */ /* UNION methods */
bool prepare(THD *thd, select_result *result, ulong additional_options); bool prepare(THD *thd, select_result *result, ulong additional_options);
bool prepare_join(THD *thd, SELECT_LEX *sl, select_result *result,
ulong additional_options,
bool is_union_select);
bool optimize(); bool optimize();
bool exec(); bool exec();
bool exec_recursive(); bool exec_recursive();

View File

@@ -15880,22 +15880,9 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length)
break; break;
} }
case TIME_RESULT: case TIME_RESULT:
new_field= tmp_table_field_from_field_type(table, true, false);
break;
case STRING_RESULT:
DBUG_ASSERT(collation.collation);
/*
GEOMETRY fields have STRING_RESULT result type.
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);
else
new_field= make_string_field(table);
new_field->set_derivation(collation.derivation, collation.repertoire);
break;
case DECIMAL_RESULT: case DECIMAL_RESULT:
new_field= Field_new_decimal::create_from_item(mem_root, this); case STRING_RESULT:
new_field= tmp_table_field_from_field_type(table);
break; break;
case ROW_RESULT: case ROW_RESULT:
// This case should never be choosen // This case should never be choosen
@@ -15981,7 +15968,7 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table)
field->init(table); field->init(table);
return field; return field;
} }
return tmp_table_field_from_field_type(table, false, false); return tmp_table_field_from_field_type(table);
} }
@@ -16032,6 +16019,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
} }
switch (type) { switch (type) {
case Item::TYPE_HOLDER:
case Item::SUM_FUNC_ITEM: case Item::SUM_FUNC_ITEM:
{ {
result= item->create_tmp_field(group, table); result= item->create_tmp_field(group, table);
@@ -16161,11 +16149,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
return create_tmp_field_from_item(thd, item, table, return create_tmp_field_from_item(thd, item, table,
(make_copy_field ? 0 : copy_func), (make_copy_field ? 0 : copy_func),
modify_item); modify_item);
case Item::TYPE_HOLDER:
result= ((Item_type_holder *)item)->make_field_by_type(table);
result->set_derivation(item->collation.derivation,
item->collation.repertoire);
return result;
default: // Dosen't have to be stored default: // Dosen't have to be stored
return 0; return 0;
} }

View File

@@ -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 field->real_type() == MYSQL_TYPE_STRING) // For binary type
{ {
uint32 octet_max_length= field->max_display_length(); 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; octet_max_length /= field->charset()->mbmaxlen;
longlong char_max_len= is_blob ? longlong char_max_len= is_blob ?
(longlong) octet_max_length / field->charset()->mbminlen : (longlong) octet_max_length / field->charset()->mbminlen :

View File

@@ -7368,7 +7368,7 @@ blob_length_by_type(enum_field_types type)
case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_MEDIUM_BLOB:
return 16777215; return 16777215;
case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_LONG_BLOB:
return 4294967295U; return (uint) UINT_MAX32;
default: default:
DBUG_ASSERT(0); // we should never go here DBUG_ASSERT(0); // we should never go here
return 0; return 0;

View File

@@ -21,39 +21,44 @@
#include "item.h" #include "item.h"
#include "log.h" #include "log.h"
static Type_handler_tiny type_handler_tiny; Type_handler_row type_handler_row;
static Type_handler_short type_handler_short;
static Type_handler_long type_handler_long;
static Type_handler_int24 type_handler_int24;
static Type_handler_year type_handler_year;
static Type_handler_time type_handler_time;
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; Type_handler_null type_handler_null;
Type_handler_row type_handler_row;
Type_handler_string type_handler_string; Type_handler_tiny type_handler_tiny;
Type_handler_varchar type_handler_varchar; Type_handler_short type_handler_short;
Type_handler_long type_handler_long;
Type_handler_int24 type_handler_int24;
Type_handler_longlong type_handler_longlong; Type_handler_longlong type_handler_longlong;
Type_handler_float type_handler_float; Type_handler_float type_handler_float;
Type_handler_double type_handler_double; Type_handler_double type_handler_double;
Type_handler_newdecimal type_handler_newdecimal;
Type_handler_datetime type_handler_datetime;
Type_handler_bit type_handler_bit; Type_handler_bit type_handler_bit;
Type_handler_enum type_handler_enum;
Type_handler_set type_handler_set;
Type_handler_olddecimal type_handler_olddecimal;
Type_handler_newdecimal type_handler_newdecimal;
Type_handler_year type_handler_year;
Type_handler_time type_handler_time;
Type_handler_date type_handler_date;
Type_handler_timestamp type_handler_timestamp;
Type_handler_timestamp2 type_handler_timestamp2;
Type_handler_datetime type_handler_datetime;
Type_handler_time2 type_handler_time2; Type_handler_time2 type_handler_time2;
Type_handler_newdate type_handler_newdate; Type_handler_newdate type_handler_newdate;
Type_handler_datetime2 type_handler_datetime2; Type_handler_datetime2 type_handler_datetime2;
Type_handler_enum type_handler_enum;
Type_handler_set type_handler_set;
Type_handler_string type_handler_string;
Type_handler_var_string type_handler_var_string;
Type_handler_varchar type_handler_varchar;
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 #ifdef HAVE_SPATIAL
Type_handler_geometry type_handler_geometry; Type_handler_geometry type_handler_geometry;
#endif #endif
@@ -80,9 +85,18 @@ bool Type_handler_data::init()
m_type_aggregator_for_result.add(&type_handler_geometry, m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_geometry, &type_handler_geometry,
&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, m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_blob, &type_handler_blob,
&type_handler_long_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, m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_varchar, &type_handler_varchar,
&type_handler_long_blob) || &type_handler_long_blob) ||
@@ -115,6 +129,126 @@ void Type_std_attributes::set(const Field *field)
} }
uint Type_std_attributes::count_max_decimals(Item **item, uint nitems)
{
uint res= 0;
for (uint i= 0; i < nitems; i++)
set_if_bigger(res, item[i]->decimals);
return res;
}
/**
Set max_length/decimals of function if function is fixed point and
result length/precision depends on argument ones.
*/
void Type_std_attributes::count_decimal_length(Item **item, uint nitems)
{
int max_int_part= 0;
decimals= 0;
unsigned_flag= 1;
for (uint i=0 ; i < nitems ; i++)
{
set_if_bigger(decimals, item[i]->decimals);
set_if_bigger(max_int_part, item[i]->decimal_int_part());
set_if_smaller(unsigned_flag, item[i]->unsigned_flag);
}
int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION);
fix_char_length(my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag));
}
/**
Set max_length of if it is maximum length of its arguments.
*/
void Type_std_attributes::count_only_length(Item **item, uint nitems)
{
uint32 char_length= 0;
unsigned_flag= 0;
for (uint i= 0; i < nitems ; i++)
{
set_if_bigger(char_length, item[i]->max_char_length());
set_if_bigger(unsigned_flag, item[i]->unsigned_flag);
}
fix_char_length(char_length);
}
void Type_std_attributes::count_octet_length(Item **item, uint nitems)
{
max_length= 0;
unsigned_flag= 0;
for (uint i= 0; i < nitems ; i++)
{
set_if_bigger(max_length, item[i]->max_length);
set_if_bigger(unsigned_flag, item[i]->unsigned_flag);
}
}
/**
Set max_length/decimals of function if function is floating point and
result length/precision depends on argument ones.
*/
void Type_std_attributes::count_real_length(Item **items, uint nitems)
{
uint32 length= 0;
decimals= 0;
max_length= 0;
unsigned_flag= false;
for (uint i=0 ; i < nitems ; i++)
{
if (decimals < FLOATING_POINT_DECIMALS)
{
set_if_bigger(decimals, items[i]->decimals);
/* Will be ignored if items[i]->decimals >= FLOATING_POINT_DECIMALS */
set_if_bigger(length, (items[i]->max_length - items[i]->decimals));
}
set_if_bigger(max_length, items[i]->max_length);
}
if (decimals < FLOATING_POINT_DECIMALS)
{
max_length= length;
length+= decimals;
if (length < max_length) // If previous operation gave overflow
max_length= UINT_MAX32;
else
max_length= length;
}
// Corner case: COALESCE(DOUBLE(255,4), DOUBLE(255,3)) -> FLOAT(255, 4)
set_if_smaller(max_length, MAX_FIELD_CHARLENGTH);
}
/**
Calculate max_length and decimals for string functions.
@param field_type Field type.
@param items Argument array.
@param nitems Number of arguments.
@retval False on success, true on error.
*/
bool Type_std_attributes::count_string_length(const char *func_name,
Item **items, uint nitems)
{
if (agg_arg_charsets_for_string_result(collation, func_name,
items, nitems, 1))
return true;
if (collation.collation == &my_charset_bin)
count_octet_length(items, nitems);
else
count_only_length(items, nitems);
decimals= max_length ? NOT_FIXED_DEC : 0;
return false;
}
/** /**
This method is used by: This method is used by:
- Item_user_var_as_out_param::field_type() - Item_user_var_as_out_param::field_type()
@@ -140,6 +274,36 @@ Type_handler::string_type_handler(uint max_octet_length)
} }
const Type_handler *
Type_handler::varstring_type_handler(const Item *item)
{
if (!item->max_length)
return &type_handler_string;
if (item->too_big_for_varchar())
return blob_type_handler(item->max_length);
return &type_handler_varchar;
}
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;
}
const Type_handler *
Type_handler::blob_type_handler(const Item *item)
{
return blob_type_handler(item->max_length);
}
/** /**
This method is used by: This method is used by:
- Item_sum_hybrid, e.g. MAX(item), MIN(item). - Item_sum_hybrid, e.g. MAX(item), MIN(item).
@@ -222,6 +386,7 @@ const Name Type_handler_null::m_name_null(C_STRING_WITH_LEN("null"));
const Name const Name
Type_handler_string::m_name_char(C_STRING_WITH_LEN("char")), Type_handler_string::m_name_char(C_STRING_WITH_LEN("char")),
Type_handler_var_string::m_name_var_string(C_STRING_WITH_LEN("varchar")),
Type_handler_varchar::m_name_varchar(C_STRING_WITH_LEN("varchar")), Type_handler_varchar::m_name_varchar(C_STRING_WITH_LEN("varchar")),
Type_handler_tiny_blob::m_name_tinyblob(C_STRING_WITH_LEN("tinyblob")), Type_handler_tiny_blob::m_name_tinyblob(C_STRING_WITH_LEN("tinyblob")),
Type_handler_medium_blob::m_name_mediumblob(C_STRING_WITH_LEN("mediumblob")), Type_handler_medium_blob::m_name_mediumblob(C_STRING_WITH_LEN("mediumblob")),
@@ -303,6 +468,30 @@ const Type_handler *Type_handler_row::type_handler_for_comparison() const
return &type_handler_row; return &type_handler_row;
} }
/***************************************************************************/
const Type_handler *Type_handler_enum::type_handler_for_item_field() const
{
return &type_handler_string;
}
const Type_handler *Type_handler_enum::cast_to_int_type_handler() const
{
return &type_handler_longlong;
}
const Type_handler *Type_handler_set::type_handler_for_item_field() const
{
return &type_handler_string;
}
const Type_handler *Type_handler_set::cast_to_int_type_handler() const
{
return &type_handler_longlong;
}
/***************************************************************************/ /***************************************************************************/
@@ -1152,6 +1341,446 @@ Field *Type_handler_set::make_conversion_table_field(TABLE *table,
((const Field_enum*) target)->typelib, target->charset()); ((const Field_enum*) target)->typelib, target->charset());
} }
/*************************************************************************/
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.
For now we have DBUG_ASSERT(0).
It will be removed 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 new (table->in_use->mem_root)
Field_decimal(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
Field::NONE, name, attr.decimals,
0/*zerofill*/,attr.unsigned_flag);
}
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
{
/*
Will be changed to "new Field_timestampf" when we reuse
make_table_field() for make_field() purposes in field.cc.
*/
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_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
{
/*
DBUG_ASSERT will be removed when we reuse make_table_field()
for make_field() in field.cc
*/
DBUG_ASSERT(0);
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
{
/*
Will be changed to "new Field_timef" when we reuse
make_table_field() for make_field() purposes in field.cc.
*/
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_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
{
/*
Will be changed to "new Field_datetimef" when we reuse
make_table_field() for make_field() purposes in field.cc.
*/
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_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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
#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
{
TYPELIB *typelib= attr.get_typelib();
DBUG_ASSERT(typelib);
return new (table->in_use->mem_root)
Field_enum(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
Field::NONE, name,
get_enum_pack_length(typelib->count), typelib,
attr.collation);
}
Field *Type_handler_set::make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const
{
TYPELIB *typelib= attr.get_typelib();
DBUG_ASSERT(typelib);
return new (table->in_use->mem_root)
Field_set(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
Field::NONE, name,
get_enum_pack_length(typelib->count), typelib,
attr.collation);
}
/*************************************************************************/ /*************************************************************************/
uint32 Type_handler_decimal_result::max_display_length(const Item *item) const uint32 Type_handler_decimal_result::max_display_length(const Item *item) const
@@ -1436,7 +2065,18 @@ bool Type_handler_string_result::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const Item **items, uint nitems) const
{ {
return func->aggregate_attributes_string(items, nitems); return func->aggregate_attributes_string(func->func_name(), items, nitems);
}
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(func->func_name(), items, nitems))
return true;
func->set_handler(blob_type_handler(func->max_length));
return false;
} }
@@ -3187,3 +3827,204 @@ uint Type_handler_string_result::Item_temporal_precision(Item *item,
} }
/***************************************************************************/ /***************************************************************************/
uint Type_handler::Item_decimal_scale(const Item *item) const
{
return item->decimals < NOT_FIXED_DEC ?
item->decimals :
MY_MIN(item->max_length, DECIMAL_MAX_SCALE);
}
uint Type_handler_temporal_result::
Item_decimal_scale_with_seconds(const Item *item) const
{
return item->decimals < NOT_FIXED_DEC ?
item->decimals :
TIME_SECOND_PART_DIGITS;
}
uint Type_handler::Item_divisor_precision_increment(const Item *item) const
{
return item->decimals;
}
uint Type_handler_temporal_result::
Item_divisor_precision_increment_with_seconds(const Item *item) const
{
return item->decimals < NOT_FIXED_DEC ?
item->decimals :
TIME_SECOND_PART_DIGITS;
}
/***************************************************************************/
bool Type_handler_real_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == REAL_RESULT);
return outer->cmp_type() == REAL_RESULT;
}
bool Type_handler_int_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == INT_RESULT);
return outer->cmp_type() == INT_RESULT;
}
bool Type_handler_decimal_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == DECIMAL_RESULT);
return outer->cmp_type() == DECIMAL_RESULT;
}
bool Type_handler_string_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == STRING_RESULT);
return outer->cmp_type() == STRING_RESULT &&
outer->collation.collation == inner->collation.collation &&
/*
Materialization also is unable to work when create_tmp_table() will
create a blob column because item->max_length is too big.
The following test is copied from varstring_type_handler().
*/
!inner->too_big_for_varchar();
}
bool Type_handler_temporal_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == TIME_RESULT);
return mysql_timestamp_type() ==
outer->type_handler()->mysql_timestamp_type();
}
/***************************************************************************/
const Type_handler *
Type_handler_null::type_handler_for_tmp_table(const Item *item) const
{
return &type_handler_string;
}
const Type_handler *
Type_handler_null::type_handler_for_union(const Item *item) const
{
return &type_handler_string;
}
const Type_handler *
Type_handler_olddecimal::type_handler_for_tmp_table(const Item *item) const
{
return &type_handler_newdecimal;
}
const Type_handler *
Type_handler_olddecimal::type_handler_for_union(const Item *item) const
{
return &type_handler_newdecimal;
}
/***************************************************************************/
bool Type_handler::check_null(const Item *item, st_value *value) const
{
if (item->null_value)
{
value->m_type= DYN_COL_NULL;
return true;
}
return false;
}
bool Type_handler_null::
Item_save_in_value(Item *item, st_value *value) const
{
value->m_type= DYN_COL_NULL;
return true;
}
bool Type_handler_row::
Item_save_in_value(Item *item, st_value *value) const
{
DBUG_ASSERT(0);
value->m_type= DYN_COL_NULL;
return true;
}
bool Type_handler_int_result::
Item_save_in_value(Item *item, st_value *value) const
{
value->m_type= item->unsigned_flag ? DYN_COL_UINT : DYN_COL_INT;
value->value.m_longlong= item->val_int();
return check_null(item, value);
}
bool Type_handler_real_result::
Item_save_in_value(Item *item, st_value *value) const
{
value->m_type= DYN_COL_DOUBLE;
value->value.m_double= item->val_real();
return check_null(item, value);
}
bool Type_handler_decimal_result::
Item_save_in_value(Item *item, st_value *value) const
{
value->m_type= DYN_COL_DECIMAL;
my_decimal *dec= item->val_decimal(&value->m_decimal);
if (dec != &value->m_decimal && !item->null_value)
my_decimal2decimal(dec, &value->m_decimal);
return check_null(item, value);
}
bool Type_handler_string_result::
Item_save_in_value(Item *item, st_value *value) const
{
value->m_type= DYN_COL_STRING;
String *str= item->val_str(&value->m_string);
if (str != &value->m_string && !item->null_value)
value->m_string.set(str->ptr(), str->length(), str->charset());
return check_null(item, value);
}
bool Type_handler_temporal_with_date::
Item_save_in_value(Item *item, st_value *value) const
{
value->m_type= DYN_COL_DATETIME;
item->get_date(&value->value.m_time, sql_mode_for_dates(current_thd));
return check_null(item, value);
}
bool Type_handler_time_common::
Item_save_in_value(Item *item, st_value *value) const
{
value->m_type= DYN_COL_DATETIME;
item->get_time(&value->value.m_time);
return check_null(item, value);
}
/***************************************************************************/

View File

@@ -60,9 +60,9 @@ class Item_func_div;
class Item_func_mod; class Item_func_mod;
class cmp_item; class cmp_item;
class in_vector; class in_vector;
class Type_std_attributes;
class Sort_param; class Sort_param;
class Arg_comparator; class Arg_comparator;
struct st_value;
struct TABLE; struct TABLE;
struct SORT_FIELD_ATTR; struct SORT_FIELD_ATTR;
@@ -130,6 +130,21 @@ public:
derivation= DERIVATION_NONE; derivation= DERIVATION_NONE;
repertoire= MY_REPERTOIRE_UNICODE30; repertoire= MY_REPERTOIRE_UNICODE30;
} }
DTCollation(CHARSET_INFO *collation_arg)
{
/*
This constructor version is used in combination with Field constructors,
to pass "CHARSET_INFO" instead of the full DTCollation.
Therefore, derivation is set to DERIVATION_IMPLICIT, which is the
proper derivation for table fields.
We should eventually remove all code pieces that pass "CHARSET_INFO"
(e.g. in storage engine sources) and fix to pass the full DTCollation
instead. Then, this constructor can be removed.
*/
collation= collation_arg;
derivation= DERIVATION_IMPLICIT;
repertoire= my_charset_repertoire(collation_arg);
}
DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg) DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg)
{ {
collation= collation_arg; collation= collation_arg;
@@ -311,6 +326,155 @@ public:
{ {
fix_attributes_temporal(MAX_DATETIME_WIDTH, dec); fix_attributes_temporal(MAX_DATETIME_WIDTH, dec);
} }
void count_only_length(Item **item, uint nitems);
void count_octet_length(Item **item, uint nitems);
void count_real_length(Item **item, uint nitems);
void count_decimal_length(Item **item, uint nitems);
bool count_string_length(const char *func_name, Item **item, uint nitems);
uint count_max_decimals(Item **item, uint nitems);
void aggregate_attributes_int(Item **items, uint nitems)
{
collation.set_numeric();
count_only_length(items, nitems);
decimals= 0;
}
void aggregate_attributes_real(Item **items, uint nitems)
{
collation.set_numeric();
count_real_length(items, nitems);
}
void aggregate_attributes_decimal(Item **items, uint nitems)
{
collation.set_numeric();
count_decimal_length(items, nitems);
}
bool aggregate_attributes_string(const char *func_name,
Item **item, uint nitems)
{
return count_string_length(func_name, item, nitems);
}
void aggregate_attributes_temporal(uint int_part_length,
Item **item, uint nitems)
{
fix_attributes_temporal(int_part_length, count_max_decimals(item, nitems));
}
bool agg_item_collations(DTCollation &c, const char *name,
Item **items, uint nitems,
uint flags, int item_sep);
bool agg_item_set_converter(const DTCollation &coll, const char *fname,
Item **args, uint nargs,
uint flags, int item_sep);
/*
Collect arguments' character sets together.
We allow to apply automatic character set conversion in some cases.
The conditions when conversion is possible are:
- arguments A and B have different charsets
- A wins according to coercibility rules
(i.e. a column is stronger than a string constant,
an explicit COLLATE clause is stronger than a column)
- character set of A is either superset for character set of B,
or B is a string constant which can be converted into the
character set of A without data loss.
If all of the above is true, then it's possible to convert
B into the character set of A, and then compare according
to the collation of A.
For functions with more than two arguments:
collect(A,B,C) ::= collect(collect(A,B),C)
Since this function calls THD::change_item_tree() on the passed Item **
pointers, it is necessary to pass the original Item **'s, not copies.
Otherwise their values will not be properly restored (see BUG#20769).
If the items are not consecutive (eg. args[2] and args[5]), use the
item_sep argument, ie.
agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
*/
bool agg_arg_charsets(DTCollation &c, const char *func_name,
Item **items, uint nitems,
uint flags, int item_sep)
{
if (agg_item_collations(c, func_name, items, nitems, flags, item_sep))
return true;
return agg_item_set_converter(c, func_name, items, nitems, flags, item_sep);
}
/*
Aggregate arguments for string result, e.g: CONCAT(a,b)
- convert to @@character_set_connection if all arguments are numbers
- allow DERIVATION_NONE
*/
bool agg_arg_charsets_for_string_result(DTCollation &c, const char *func_name,
Item **items, uint nitems,
int item_sep)
{
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
MY_COLL_ALLOW_COERCIBLE_CONV |
MY_COLL_ALLOW_NUMERIC_CONV;
return agg_arg_charsets(c, func_name, items, nitems, flags, item_sep);
}
/*
Aggregate arguments for string result, when some comparison
is involved internally, e.g: REPLACE(a,b,c)
- convert to @@character_set_connection if all arguments are numbers
- disallow DERIVATION_NONE
*/
bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c,
const char *func_name,
Item **items,
uint nitems,
int item_sep)
{
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
MY_COLL_ALLOW_COERCIBLE_CONV |
MY_COLL_ALLOW_NUMERIC_CONV |
MY_COLL_DISALLOW_NONE;
return agg_arg_charsets(c, func_name, items, nitems, flags, item_sep);
}
/*
Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b
- don't convert to @@character_set_connection if all arguments are numbers
- don't allow DERIVATION_NONE
*/
bool agg_arg_charsets_for_comparison(DTCollation &c,
const char *func_name,
Item **items, uint nitems,
int item_sep)
{
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
MY_COLL_ALLOW_COERCIBLE_CONV |
MY_COLL_DISALLOW_NONE;
return agg_arg_charsets(c, func_name, items, nitems, flags, item_sep);
}
};
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;
virtual TYPELIB *get_typelib() const { return NULL; }
}; };
@@ -327,6 +491,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 class Type_handler
{ {
protected: protected:
@@ -341,8 +530,19 @@ protected:
Item_func_or_sum_illegal_param(const char *name) const; Item_func_or_sum_illegal_param(const char *name) const;
bool bool
Item_func_or_sum_illegal_param(const Item_func_or_sum *) const; Item_func_or_sum_illegal_param(const Item_func_or_sum *) const;
bool check_null(const Item *item, st_value *value) const;
public: 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 *string_type_handler(uint max_octet_length);
/**
Return a string type handler for Item
If too_big_for_varchar() returns a BLOB variant, according to length.
If max_length > 0 create a VARCHAR(n)
If max_length == 0 create a CHAR(0)
@param item - the Item to get the handler to.
*/
static const Type_handler *varstring_type_handler(const Item *item);
static const Type_handler *blob_type_handler(const Item *item);
static const Type_handler *get_handler_by_field_type(enum_field_types type); 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); static const Type_handler *get_handler_by_real_type(enum_field_types type);
static const Type_handler *get_handler_by_cmp_type(Item_result type); static const Type_handler *get_handler_by_cmp_type(Item_result type);
@@ -367,6 +567,10 @@ public:
virtual enum_field_types real_field_type() const { return field_type(); } virtual enum_field_types real_field_type() const { return field_type(); }
virtual Item_result result_type() const= 0; virtual Item_result result_type() const= 0;
virtual Item_result cmp_type() const= 0; virtual Item_result cmp_type() const= 0;
virtual enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_ERROR;
}
/** /**
Prepared statement long data: Prepared statement long data:
Check whether this parameter data type is compatible with long data. Check whether this parameter data type is compatible with long data.
@@ -375,6 +579,22 @@ public:
*/ */
virtual bool is_param_long_data_type() const { return false; } virtual bool is_param_long_data_type() const { return false; }
virtual const Type_handler *type_handler_for_comparison() const= 0; virtual const Type_handler *type_handler_for_comparison() const= 0;
virtual const Type_handler *type_handler_for_item_field() const
{
return this;
}
virtual const Type_handler *type_handler_for_tmp_table(const Item *) const
{
return this;
}
virtual const Type_handler *type_handler_for_union(const Item *) const
{
return this;
}
virtual const Type_handler *cast_to_int_type_handler() const
{
return this;
}
virtual CHARSET_INFO *charset_for_protocol(const Item *item) const; virtual CHARSET_INFO *charset_for_protocol(const Item *item) const;
virtual const Type_handler* virtual const Type_handler*
type_handler_adjusted_to_max_octet_length(uint max_octet_length, type_handler_adjusted_to_max_octet_length(uint max_octet_length,
@@ -391,6 +611,12 @@ public:
} }
virtual uint Item_time_precision(Item *item) const; virtual uint Item_time_precision(Item *item) const;
virtual uint Item_datetime_precision(Item *item) const; virtual uint Item_datetime_precision(Item *item) const;
virtual uint Item_decimal_scale(const Item *item) const;
/*
Returns how many digits a divisor adds into a division result.
See Item::divisor_precision_increment() in item.h for more comments.
*/
virtual uint Item_divisor_precision_increment(const Item *) const;
/** /**
Makes a temporary table Field to handle numeric aggregate functions, Makes a temporary table Field to handle numeric aggregate functions,
e.g. SUM(DISTINCT expr), AVG(DISTINCT expr), etc. e.g. SUM(DISTINCT expr), AVG(DISTINCT expr), etc.
@@ -427,6 +653,14 @@ public:
virtual Field *make_conversion_table_field(TABLE *TABLE, virtual Field *make_conversion_table_field(TABLE *TABLE,
uint metadata, uint metadata,
const Field *target) const= 0; 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, virtual void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const= 0; Sort_param *param) const= 0;
@@ -435,6 +669,7 @@ public:
SORT_FIELD_ATTR *attr) const= 0; SORT_FIELD_ATTR *attr) const= 0;
virtual uint32 max_display_length(const Item *item) const= 0; virtual uint32 max_display_length(const Item *item) const= 0;
virtual bool Item_save_in_value(Item *item, st_value *value) const= 0;
virtual int Item_save_in_field(Item *item, Field *field, virtual int Item_save_in_field(Item *item, Field *field,
bool no_conversions) const= 0; bool no_conversions) const= 0;
@@ -480,6 +715,9 @@ public:
Item *target_expr, Item *target_value, Item *target_expr, Item *target_value,
Item_bool_func2 *source, Item_bool_func2 *source,
Item *source_expr, Item *source_const) const= 0; Item *source_expr, Item *source_const) const= 0;
virtual bool
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const= 0;
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0; virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0; virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
@@ -605,6 +843,12 @@ public:
return ROW_RESULT; return ROW_RESULT;
} }
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(0);
return false;
}
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);
@@ -617,6 +861,14 @@ public:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return NULL; 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, void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const Sort_param *param) const
@@ -633,6 +885,7 @@ public:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return 0; return 0;
} }
bool Item_save_in_value(Item *item, st_value *value) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const int Item_save_in_field(Item *item, Field *field, bool no_conversions) const
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);
@@ -834,11 +1087,14 @@ public:
Item_result cmp_type() const { return REAL_RESULT; } Item_result cmp_type() const { return REAL_RESULT; }
virtual ~Type_handler_real_result() {} virtual ~Type_handler_real_result() {}
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const; Sort_param *param) const;
void sortlength(THD *thd, void sortlength(THD *thd,
const Type_std_attributes *item, const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const; SORT_FIELD_ATTR *attr) const;
bool Item_save_in_value(Item *item, st_value *value) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
@@ -889,6 +1145,8 @@ public:
Item_result cmp_type() const { return DECIMAL_RESULT; } Item_result cmp_type() const { return DECIMAL_RESULT; }
virtual ~Type_handler_decimal_result() {}; virtual ~Type_handler_decimal_result() {};
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const; Sort_param *param) const;
@@ -896,6 +1154,7 @@ public:
const Type_std_attributes *item, const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const; SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) const; uint32 max_display_length(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
@@ -943,12 +1202,15 @@ public:
Item_result cmp_type() const { return INT_RESULT; } Item_result cmp_type() const { return INT_RESULT; }
virtual ~Type_handler_int_result() {} virtual ~Type_handler_int_result() {}
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const; Sort_param *param) const;
void sortlength(THD *thd, void sortlength(THD *thd,
const Type_std_attributes *item, const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const; SORT_FIELD_ATTR *attr) const;
bool Item_save_in_value(Item *item, st_value *value) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
@@ -991,6 +1253,9 @@ public:
class Type_handler_temporal_result: public Type_handler class Type_handler_temporal_result: public Type_handler
{ {
protected:
uint Item_decimal_scale_with_seconds(const Item *item) const;
uint Item_divisor_precision_increment_with_seconds(const Item *) const;
public: public:
Item_result result_type() const { return STRING_RESULT; } Item_result result_type() const { return STRING_RESULT; }
Item_result cmp_type() const { return TIME_RESULT; } Item_result cmp_type() const { return TIME_RESULT; }
@@ -1005,6 +1270,8 @@ public:
Item *target_expr, Item *target_value, Item *target_expr, Item *target_value,
Item_bool_func2 *source, Item_bool_func2 *source,
Item *source_expr, Item *source_const) const; Item *source_expr, Item *source_const) const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
@@ -1072,6 +1339,7 @@ public:
{ {
return Item_temporal_precision(item, false); return Item_temporal_precision(item, false);
} }
bool Item_save_in_value(Item *item, st_value *value) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
String *print_item_value(THD *thd, Item *item, String *str) const String *print_item_value(THD *thd, Item *item, String *str) const
{ {
@@ -1081,6 +1349,8 @@ public:
Item *target_expr, Item *target_value, Item *target_expr, Item *target_value,
Item_bool_func2 *source, Item_bool_func2 *source,
Item *source_expr, Item *source_const) const; Item *source_expr, Item *source_const) const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
@@ -1156,6 +1426,10 @@ public:
uint32 max_display_length(const Item *item) const { return 4; } uint32 max_display_length(const Item *item) const { return 4; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata, Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1169,6 +1443,10 @@ public:
uint32 max_display_length(const Item *item) const { return 6; } uint32 max_display_length(const Item *item) const { return 6; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata, Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1185,6 +1463,10 @@ public:
} }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata, Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1198,6 +1480,10 @@ public:
uint32 max_display_length(const Item *item) const { return 20; } uint32 max_display_length(const Item *item) const { return 20; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata, Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1211,6 +1497,10 @@ public:
uint32 max_display_length(const Item *item) const { return 8; } uint32 max_display_length(const Item *item) const { return 8; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1224,6 +1514,10 @@ public:
uint32 max_display_length(const Item *item) const; uint32 max_display_length(const Item *item) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1241,6 +1535,10 @@ public:
} }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1255,6 +1553,10 @@ public:
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1268,6 +1570,10 @@ public:
uint32 max_display_length(const Item *item) const { return 53; } uint32 max_display_length(const Item *item) const { return 53; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; 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,7 +1584,20 @@ public:
virtual ~Type_handler_time_common() { } virtual ~Type_handler_time_common() { }
const Name name() const { return m_name_time; } const Name name() const { return m_name_time; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; } enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_TIME;
}
uint Item_decimal_scale(const Item *item) const
{
return Item_decimal_scale_with_seconds(item);
}
uint Item_divisor_precision_increment(const Item *item) const
{
return Item_divisor_precision_increment_with_seconds(item);
}
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool Item_save_in_value(Item *item, st_value *value) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
@@ -1294,6 +1613,10 @@ public:
virtual ~Type_handler_time() {} virtual ~Type_handler_time() {}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1304,6 +1627,10 @@ public:
enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; } enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1312,6 +1639,7 @@ class Type_handler_temporal_with_date: public Type_handler_temporal_result
public: public:
virtual ~Type_handler_temporal_with_date() {} virtual ~Type_handler_temporal_with_date() {}
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool Item_save_in_value(Item *item, st_value *value) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
@@ -1325,6 +1653,10 @@ public:
virtual ~Type_handler_date_common() {} virtual ~Type_handler_date_common() {}
const Name name() const { return m_name_date; } const Name name() const { return m_name_date; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; } enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_DATE;
}
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const; Item **items, uint nitems) const;
@@ -1336,6 +1668,10 @@ public:
virtual ~Type_handler_date() {} virtual ~Type_handler_date() {}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1343,8 +1679,13 @@ class Type_handler_newdate: public Type_handler_date_common
{ {
public: public:
virtual ~Type_handler_newdate() {} virtual ~Type_handler_newdate() {}
enum_field_types real_field_type() const { return MYSQL_TYPE_NEWDATE; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1355,6 +1696,18 @@ public:
virtual ~Type_handler_datetime_common() {} virtual ~Type_handler_datetime_common() {}
const Name name() const { return m_name_datetime; } const Name name() const { return m_name_datetime; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_DATETIME;
}
uint Item_decimal_scale(const Item *item) const
{
return Item_decimal_scale_with_seconds(item);
}
uint Item_divisor_precision_increment(const Item *item) const
{
return Item_divisor_precision_increment_with_seconds(item);
}
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const; Item **items, uint nitems) const;
@@ -1367,6 +1720,10 @@ public:
virtual ~Type_handler_datetime() {} virtual ~Type_handler_datetime() {}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1377,6 +1734,10 @@ public:
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; } enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1387,6 +1748,18 @@ public:
virtual ~Type_handler_timestamp_common() {} virtual ~Type_handler_timestamp_common() {}
const Name name() const { return m_name_timestamp; } const Name name() const { return m_name_timestamp; }
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; } enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_DATETIME;
}
uint Item_decimal_scale(const Item *item) const
{
return Item_decimal_scale_with_seconds(item);
}
uint Item_divisor_precision_increment(const Item *item) const
{
return Item_divisor_precision_increment_with_seconds(item);
}
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const; Item **items, uint nitems) const;
@@ -1399,6 +1772,10 @@ public:
virtual ~Type_handler_timestamp() {} virtual ~Type_handler_timestamp() {}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1409,6 +1786,10 @@ public:
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; } enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1419,8 +1800,14 @@ public:
virtual ~Type_handler_olddecimal() {} virtual ~Type_handler_olddecimal() {}
const Name name() const { return m_name_decimal; } const Name name() const { return m_name_decimal; }
enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; } enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
const Type_handler *type_handler_for_tmp_table(const Item *item) const;
const Type_handler *type_handler_for_union(const Item *item) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1433,6 +1820,10 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; } enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1444,9 +1835,16 @@ public:
const Name name() const { return m_name_null; } const Name name() const { return m_name_null; }
enum_field_types field_type() const { return MYSQL_TYPE_NULL; } enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
const Type_handler *type_handler_for_tmp_table(const Item *item) const;
const Type_handler *type_handler_for_union(const Item *) const;
uint32 max_display_length(const Item *item) const { return 0; } uint32 max_display_length(const Item *item) const { return 0; }
bool Item_save_in_value(Item *item, st_value *value) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1458,8 +1856,36 @@ public:
const Name name() const { return m_name_char; } const Name name() const { return m_name_char; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; } enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
bool is_param_long_data_type() const { return true; } bool is_param_long_data_type() const { return true; }
const Type_handler *type_handler_for_tmp_table(const Item *item) const
{
return varstring_type_handler(item);
}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
/* Old varchar */
class Type_handler_var_string: public Type_handler_string
{
static const Name m_name_var_string;
public:
virtual ~Type_handler_var_string() {}
const Name name() const { return m_name_var_string; }
enum_field_types field_type() const { return MYSQL_TYPE_VAR_STRING; }
enum_field_types real_field_type() const { return MYSQL_TYPE_STRING; }
const Type_handler *type_handler_for_tmp_table(const Item *item) const
{
return varstring_type_handler(item);
}
const Type_handler *type_handler_for_union(const Item *item) const
{
return varstring_type_handler(item);
}
}; };
@@ -1470,9 +1896,21 @@ public:
virtual ~Type_handler_varchar() {} virtual ~Type_handler_varchar() {}
const Name name() const { return m_name_varchar; } const Name name() const { return m_name_varchar; }
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
const Type_handler *type_handler_for_tmp_table(const Item *item) const
{
return varstring_type_handler(item);
}
const Type_handler *type_handler_for_union(const Item *item) const
{
return varstring_type_handler(item);
}
bool is_param_long_data_type() const { return true; } bool is_param_long_data_type() const { return true; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1480,7 +1918,22 @@ class Type_handler_blob_common: public Type_handler_string_result
{ {
public: public:
virtual ~Type_handler_blob_common() { } virtual ~Type_handler_blob_common() { }
const Type_handler *type_handler_for_tmp_table(const Item *item) const
{
return blob_type_handler(item);
}
const Type_handler *type_handler_for_union(const Item *item) const
{
return blob_type_handler(item);
}
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
return false; // Materialization does not work with BLOB columns
}
bool is_param_long_data_type() const { return true; } 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;
}; };
@@ -1493,6 +1946,10 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; } enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1505,6 +1962,10 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; } enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1517,6 +1978,10 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; } enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1529,6 +1994,10 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; } enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1542,8 +2011,18 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
bool is_param_long_data_type() const { return true; } bool is_param_long_data_type() const { return true; }
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
return false; // Materialization does not work with GEOMETRY columns
}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; 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 bool is_traditional_type() const
{ {
return false; return false;
@@ -1576,10 +2055,16 @@ class Type_handler_enum: public Type_handler_string_result
public: public:
virtual ~Type_handler_enum() {} virtual ~Type_handler_enum() {}
const Name name() const { return m_name_enum; } const Name name() const { return m_name_enum; }
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; } virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
const Type_handler *type_handler_for_item_field() const;
const Type_handler *cast_to_int_type_handler() const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1589,10 +2074,16 @@ class Type_handler_set: public Type_handler_string_result
public: public:
virtual ~Type_handler_set() {} virtual ~Type_handler_set() {}
const Name name() const { return m_name_set; } const Name name() const { return m_name_set; }
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; } virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
const Type_handler *type_handler_for_item_field() const;
const Type_handler *cast_to_int_type_handler() const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
}; };
@@ -1628,6 +2119,10 @@ public:
} }
Item_result result_type() const { return m_type_handler->result_type(); } Item_result result_type() const { return m_type_handler->result_type(); }
Item_result cmp_type() const { return m_type_handler->cmp_type(); } Item_result cmp_type() const { return m_type_handler->cmp_type(); }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return m_type_handler->mysql_timestamp_type();
}
void set_handler(const Type_handler *other) void set_handler(const Type_handler *other)
{ {
m_type_handler= other; m_type_handler= other;
@@ -1671,24 +2166,49 @@ public:
}; };
extern Type_handler_row type_handler_row; extern Type_handler_row type_handler_row;
extern Type_handler_null type_handler_null; extern Type_handler_null type_handler_null;
extern Type_handler_string type_handler_string;
extern Type_handler_varchar type_handler_varchar;
extern Type_handler_longlong type_handler_longlong;
extern Type_handler_float type_handler_float;
extern Type_handler_double type_handler_double;
extern Type_handler_newdecimal type_handler_newdecimal;
extern Type_handler_datetime type_handler_datetime;
extern Type_handler_longlong type_handler_longlong;
extern Type_handler_bit type_handler_bit;
extern Type_handler_enum type_handler_enum;
extern Type_handler_set type_handler_set;
extern Type_handler_time2 type_handler_time2; extern Type_handler_float type_handler_float;
extern Type_handler_double type_handler_double;
extern Type_handler_bit type_handler_bit;
extern Type_handler_enum type_handler_enum;
extern Type_handler_set type_handler_set;
extern Type_handler_string type_handler_string;
extern Type_handler_var_string type_handler_var_string;
extern Type_handler_varchar type_handler_varchar;
extern Type_handler_tiny_blob type_handler_tiny_blob;
extern Type_handler_medium_blob type_handler_medium_blob;
extern Type_handler_long_blob type_handler_long_blob;
extern Type_handler_blob type_handler_blob;
extern Type_handler_tiny type_handler_tiny;
extern Type_handler_short type_handler_short;
extern Type_handler_int24 type_handler_int24;
extern Type_handler_long type_handler_long;
extern Type_handler_longlong type_handler_longlong;
extern Type_handler_newdecimal type_handler_newdecimal;
extern Type_handler_olddecimal type_handler_olddecimal;
extern Type_handler_year type_handler_year;
extern Type_handler_newdate type_handler_newdate; extern Type_handler_newdate type_handler_newdate;
extern Type_handler_date type_handler_date;
extern Type_handler_time type_handler_time;
extern Type_handler_time2 type_handler_time2;
extern Type_handler_datetime type_handler_datetime;
extern Type_handler_datetime2 type_handler_datetime2; extern Type_handler_datetime2 type_handler_datetime2;
extern Type_handler_timestamp type_handler_timestamp;
extern Type_handler_timestamp2 type_handler_timestamp2;
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 class Type_aggregator
{ {

View File

@@ -636,6 +636,59 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg,
} }
bool st_select_lex_unit::prepare_join(THD *thd_arg, SELECT_LEX *sl,
select_result *tmp_result,
ulong additional_options,
bool is_union_select)
{
DBUG_ENTER("st_select_lex_unit::prepare_join");
bool can_skip_order_by;
sl->options|= SELECT_NO_UNLOCK;
JOIN *join= new JOIN(thd_arg, sl->item_list,
(sl->options | thd_arg->variables.option_bits |
additional_options),
tmp_result);
if (!join)
DBUG_RETURN(true);
thd_arg->lex->current_select= sl;
can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
saved_error= join->prepare(sl->table_list.first,
sl->with_wild,
sl->where,
(can_skip_order_by ? 0 :
sl->order_list.elements) +
sl->group_list.elements,
can_skip_order_by ?
NULL : sl->order_list.first,
can_skip_order_by,
sl->group_list.first,
sl->having,
(is_union_select ? NULL :
thd_arg->lex->proc_list.first),
sl, this);
/* There are no * in the statement anymore (for PS) */
sl->with_wild= 0;
last_procedure= join->procedure;
if (saved_error || (saved_error= thd_arg->is_fatal_error))
DBUG_RETURN(true);
/*
Remove all references from the select_lex_units to the subqueries that
are inside the ORDER BY clause.
*/
if (can_skip_order_by)
{
for (ORDER *ord= (ORDER *)sl->order_list.first; ord; ord= ord->next)
{
(*ord->item)->walk(&Item::eliminate_subselect_processor, FALSE, NULL);
}
}
DBUG_RETURN(false);
}
bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
@@ -748,14 +801,21 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
sl->context.resolve_in_select_list= TRUE; sl->context.resolve_in_select_list= TRUE;
if (!is_union_select && !is_recursive)
{
if (prepare_join(thd_arg, first_sl, tmp_result, additional_options,
is_union_select))
goto err;
types= first_sl->item_list;
goto cont;
}
for (;sl; sl= sl->next_select()) for (;sl; sl= sl->next_select())
{ {
bool can_skip_order_by; if (prepare_join(thd_arg, sl, tmp_result, additional_options,
sl->options|= SELECT_NO_UNLOCK; is_union_select))
JOIN *join= new JOIN(thd_arg, sl->item_list, goto err;
(sl->options | thd_arg->variables.option_bits |
additional_options),
tmp_result);
/* /*
setup_tables_done_option should be set only for very first SELECT, setup_tables_done_option should be set only for very first SELECT,
because it protect from secont setup_tables call for select-like non because it protect from secont setup_tables call for select-like non
@@ -763,53 +823,12 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
SELECT (for union it can be only INSERT ... SELECT). SELECT (for union it can be only INSERT ... SELECT).
*/ */
additional_options&= ~OPTION_SETUP_TABLES_DONE; additional_options&= ~OPTION_SETUP_TABLES_DONE;
if (!join)
goto err;
thd_arg->lex->current_select= sl;
can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
saved_error= join->prepare(sl->table_list.first,
sl->with_wild,
sl->where,
(can_skip_order_by ? 0 :
sl->order_list.elements) +
sl->group_list.elements,
can_skip_order_by ?
NULL : sl->order_list.first,
can_skip_order_by,
sl->group_list.first,
sl->having,
(is_union_select ? NULL :
thd_arg->lex->proc_list.first),
sl, this);
/* There are no * in the statement anymore (for PS) */
sl->with_wild= 0;
last_procedure= join->procedure;
if (saved_error || (saved_error= thd_arg->is_fatal_error))
goto err;
/*
Remove all references from the select_lex_units to the subqueries that
are inside the ORDER BY clause.
*/
if (can_skip_order_by)
{
for (ORDER *ord= (ORDER *)sl->order_list.first; ord; ord= ord->next)
{
(*ord->item)->walk(&Item::eliminate_subselect_processor, FALSE, NULL);
}
}
/* /*
Use items list of underlaid select for derived tables to preserve Use items list of underlaid select for derived tables to preserve
information about fields lengths and exact types information about fields lengths and exact types
*/ */
if (!is_union_select && !is_recursive) if (sl == first_sl)
types= first_sl->item_list;
else if (sl == first_sl)
{ {
if (is_recursive) if (is_recursive)
{ {
@@ -846,6 +865,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
Item *type, *item_tmp; Item *type, *item_tmp;
while ((type= tp++, item_tmp= it++)) while ((type= tp++, item_tmp= it++))
{ {
DBUG_ASSERT(item_tmp->fixed);
if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp)) if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
@@ -878,6 +898,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
} }
} }
cont:
/* /*
If the query is using select_union_direct, we have postponed If the query is using select_union_direct, we have postponed
preparation of the underlying select_result until column types preparation of the underlying select_result until column types

View File

@@ -156,7 +156,7 @@ bool check_duplicate_names(THD *thd, List<Item> &item_list, bool gen_unique_view
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
err: err:
my_error(ER_DUP_FIELDNAME, MYF(0), item->name); my_error(ER_DUP_FIELDNAME, MYF(0), item->name.str);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }

View File

@@ -13713,27 +13713,7 @@ load_data_set_elem:
text_literal: text_literal:
TEXT_STRING TEXT_STRING
{ {
LEX_CSTRING tmp; if (!($$= thd->make_string_literal($1)))
CHARSET_INFO *cs_con= thd->variables.collation_connection;
CHARSET_INFO *cs_cli= thd->variables.character_set_client;
uint repertoire= $1.repertoire(cs_cli);
if (thd->charset_is_collation_connection ||
(repertoire == MY_REPERTOIRE_ASCII &&
my_charset_is_ascii_based(cs_con)))
tmp= $1;
else
{
LEX_STRING to;
if (thd->convert_string(&to, cs_con, $1.str, $1.length, cs_cli))
MYSQL_YYABORT;
tmp.str= to.str;
tmp.length= to.length;
}
$$= new (thd->mem_root) Item_string(thd, tmp.str, tmp.length,
cs_con,
DERIVATION_COERCIBLE,
repertoire);
if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| NCHAR_STRING | NCHAR_STRING

View File

@@ -13837,27 +13837,7 @@ load_data_set_elem:
text_literal: text_literal:
TEXT_STRING TEXT_STRING
{ {
LEX_CSTRING tmp; if (!($$= thd->make_string_literal($1)))
CHARSET_INFO *cs_con= thd->variables.collation_connection;
CHARSET_INFO *cs_cli= thd->variables.character_set_client;
uint repertoire= $1.repertoire(cs_cli);
if (thd->charset_is_collation_connection ||
(repertoire == MY_REPERTOIRE_ASCII &&
my_charset_is_ascii_based(cs_con)))
tmp= $1;
else
{
LEX_STRING to;
if (thd->convert_string(&to, cs_con, $1.str, $1.length, cs_cli))
MYSQL_YYABORT;
tmp.str= to.str;
tmp.length= to.length;
}
$$= new (thd->mem_root) Item_string(thd, tmp.str, tmp.length,
cs_con,
DERIVATION_COERCIBLE,
repertoire);
if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| NCHAR_STRING | NCHAR_STRING