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
f datetime YES NULL
g time YES NULL
h longblob YES NULL
h blob YES NULL
dd time YES NULL
select * from t2;
a b c d e f g h dd
1 -7 7 2000-01-01 b 2000-01-01 00:00:00 05:04:03 yet another binary data 02:00:00
2 -2 2 1825-12-14 a 2003-01-01 03:02:01 04:03:02 binary data 02:00:00
drop table t1, t2;
CREATE TABLE t1 (
c_tinytext tinytext,
c_text text,
c_mediumtext mediumtext,
c_longtext longtext
);
CREATE TABLE t2 AS SELECT
ifnull(c_tinytext, CAST('yet another binary data' AS BINARY)),
ifnull(c_text, CAST('yet another binary data' AS BINARY)),
ifnull(c_mediumtext, CAST('yet another binary data' AS BINARY)),
ifnull(c_longtext, CAST('yet another binary data' AS BINARY))
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`ifnull(c_tinytext, CAST('yet another binary data' AS BINARY))` tinyblob DEFAULT NULL,
`ifnull(c_text, CAST('yet another binary data' AS BINARY))` blob DEFAULT NULL,
`ifnull(c_mediumtext, CAST('yet another binary data' AS BINARY))` mediumblob DEFAULT NULL,
`ifnull(c_longtext, CAST('yet another binary data' AS BINARY))` longblob DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
create table t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float(3,2), g double(4,3), h decimal(5,4), i year, j date, k timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, l datetime, m enum('a','b'), n set('a','b'), o char(10));
create table t2 select ifnull(a,a), ifnull(b,b), ifnull(c,c), ifnull(d,d), ifnull(e,e), ifnull(f,f), ifnull(g,g), ifnull(h,h), ifnull(i,i), ifnull(j,j), ifnull(k,k), ifnull(l,l), ifnull(m,m), ifnull(n,n), ifnull(o,o) from t1;
show create table t2;

View File

@@ -11184,5 +11184,21 @@ SET NAMES utf8;
CREATE TABLE t1 (a SET('a,bü'));
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
#

View File

@@ -3500,5 +3500,17 @@ t2 CREATE TABLE `t2` (
DROP TABLE t2;
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
#

View File

@@ -4661,3 +4661,20 @@ DROP TABLE t1;
#
# 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;
Table Create Table
t1 CREATE TABLE `t1` (
`w` longblob DEFAULT NULL
`w` mediumblob DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select weight_string(NULL);

View File

@@ -381,11 +381,11 @@ POINT(0,0) MOD '0' LIMIT 0;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`POINT(0,0)+'0'` longtext DEFAULT NULL,
`POINT(0,0)-'0'` longtext DEFAULT NULL,
`POINT(0,0)*'0'` longtext DEFAULT NULL,
`POINT(0,0)/'0'` longtext DEFAULT NULL,
`POINT(0,0) MOD '0'` longtext DEFAULT NULL
`POINT(0,0)+'0'` tinytext DEFAULT NULL,
`POINT(0,0)-'0'` tinytext DEFAULT NULL,
`POINT(0,0)*'0'` tinytext DEFAULT NULL,
`POINT(0,0)/'0'` tinytext DEFAULT NULL,
`POINT(0,0) MOD '0'` tinytext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 AS SELECT
@@ -394,8 +394,8 @@ CREATE TABLE t1 AS SELECT
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`'0'+POINT(0,0)` longtext DEFAULT NULL,
`'0'*POINT(0,0)` longtext DEFAULT NULL
`'0'+POINT(0,0)` tinytext DEFAULT NULL,
`'0'*POINT(0,0)` tinytext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
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
select asbinary(g) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def asbinary(g) 252 4294967295 0 Y 128 0 63
def asbinary(g) 251 4294967295 0 Y 128 0 63
asbinary(g)
drop table t1;
create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b));
@@ -4030,65 +4030,65 @@ DROP TABLE t1;
#
CREATE TABLE t1 (a GEOMETRY);
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;
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;
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;
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;
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);
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);
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);
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);
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);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
#
# 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
select 1 union select 1;
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
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
def aaa 1 1 8 20 1 N 32769 0 63
def aaa 1 1 3 11 1 N 32769 0 63
1
1
drop table t1;

View File

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

View File

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

View File

@@ -1019,3 +1019,52 @@ cast('-0.0' as decimal(5,1)) < 0
#
# 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
4 0
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));
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
select * from t1 where f1='';
f1
drop table t1;
SET sql_mode=DEFAULT;
CREATE TABLE t1 (c1 ENUM('a', '', 'b'));
INSERT INTO t1 (c1) VALUES ('b');
@@ -2219,3 +2224,90 @@ SELECT * FROM t1;
SELECT * FROM t1;
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
#
#
# 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;
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
#

View File

@@ -852,7 +852,7 @@ select * from t1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`1` bigint(20) NOT NULL DEFAULT 0
`1` int(11) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
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
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, t2;
CREATE TABLE t1
(
c_varchar varchar(1) character set utf8 collate utf8_general_ci,
c_tinytext tinytext,
c_text text,
c_mediumtext mediumtext,
c_longtext longtext
);
CREATE TABLE t2 AS
SELECT c_tinytext, c_text, c_mediumtext, c_longtext FROM t1
UNION
SELECT c_varchar, c_varchar, c_varchar, c_varchar FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c_tinytext` text CHARACTER SET utf8 DEFAULT NULL,
`c_text` mediumtext CHARACTER SET utf8 DEFAULT NULL,
`c_mediumtext` longtext CHARACTER SET utf8 DEFAULT NULL,
`c_longtext` longtext CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
(select avg(1)) union (select avg(1)) union (select avg(1)) union
(select avg(1)) union (select avg(1)) union (select avg(1)) union
(select avg(1)) union (select avg(1)) union (select avg(1)) union
@@ -2156,3 +2178,33 @@ WHERE t1_2.b NOT IN ( SELECT 4 UNION ALL SELECT 5 );
a b a b
1 1 1 1
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;
Table Create Table
t1 CREATE TABLE "t1" (
"var" varchar(255) DEFAULT NULL,
"rec.var" varchar(255) DEFAULT NULL
"var" tinytext DEFAULT NULL,
"rec.var" tinytext DEFAULT NULL
)
DROP TABLE t1;
DROP PROCEDURE p1;
@@ -2169,8 +2169,8 @@ CALL p1();
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"var" varchar(255) CHARACTER SET utf8 DEFAULT NULL,
"rec.var" varchar(255) CHARACTER SET utf8 DEFAULT NULL
"var" text CHARACTER SET utf8 DEFAULT NULL,
"rec.var" text CHARACTER SET utf8 DEFAULT NULL
)
DROP TABLE t1;
DROP PROCEDURE p1;

View File

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

View File

@@ -1238,7 +1238,7 @@ Table Op Msg_type Msg_text
test.tab check status OK
DROP TABLE tab;
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 SPATIAL INDEX idx1 ON tab(c1) ;
SHOW CREATE TABLE tab;

View File

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

View File

@@ -402,6 +402,22 @@ explain t2;
select * from t2;
drop table t1, t2;
CREATE TABLE t1 (
c_tinytext tinytext,
c_text text,
c_mediumtext mediumtext,
c_longtext longtext
);
CREATE TABLE t2 AS SELECT
ifnull(c_tinytext, CAST('yet another binary data' AS BINARY)),
ifnull(c_text, CAST('yet another binary data' AS BINARY)),
ifnull(c_mediumtext, CAST('yet another binary data' AS BINARY)),
ifnull(c_longtext, CAST('yet another binary data' AS BINARY))
FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
create table t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float(3,2), g double(4,3), h decimal(5,4), i year, j date, k timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, l datetime, m enum('a','b'), n set('a','b'), o char(10));
create table t2 select ifnull(a,a), ifnull(b,b), ifnull(c,c), ifnull(d,d), ifnull(e,e), ifnull(f,f), ifnull(g,g), ifnull(h,h), ifnull(i,i), ifnull(j,j), ifnull(k,k), ifnull(l,l), ifnull(m,m), ifnull(n,n), ifnull(o,o) from t1;
show create table t2;

View File

@@ -2109,6 +2109,18 @@ SET NAMES utf8;
--error ER_ILLEGAL_VALUE_FOR_TYPE
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 # End of 10.3 tests
--echo #

View File

@@ -500,6 +500,16 @@ SHOW CREATE TABLE t2;
DROP TABLE t2;
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 # End of 10.3 tests

View File

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

View File

@@ -612,3 +612,46 @@ select cast('-0.0' as decimal(5,1)) < 0;
--echo #
--echo # End of 5.5 tests
--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.
#
#
SET sql_mode='';
create table t1(f1 enum('a','b'), index(f1));
insert into t1 values(''),(''),('a'),('b');
select * from t1 where f1='';
drop table t1;
SET sql_mode=DEFAULT;
#
@@ -454,3 +456,65 @@ SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
ALTER TABLE t1 MODIFY a ENUM('2001','2002');
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 # End of 10.1 tests
--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;
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 # End of 10.3 tests
--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;
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.
#
@@ -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 );
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_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//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_VARCHAR, MYSQL_TYPE_VARCHAR,
//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_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_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,
const Item *item,
bool is_eq_func) const
{
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;
}
@@ -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,
uchar null_bit_arg, utype unireg_check_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,
unireg_check_arg, field_name_arg)
{
field_charset= charset_arg;
if (charset_arg->state & MY_CS_BINSORT)
field_charset= collation.collation;
if (collation.collation->state & MY_CS_BINSORT)
flags|=BINARY_FLAG;
field_derivation= DERIVATION_IMPLICIT;
field_repertoire= my_charset_repertoire(charset_arg);
field_derivation= collation.derivation;
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)
{
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,
const LEX_CSTRING *field_name_arg,
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),
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
cs),
collation),
packlength(blob_pack_length)
{
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
{
const char *str;
@@ -8638,12 +8593,16 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
{
tmp=0;
set_warning(WARN_DATA_TRUNCATED, 1);
err= 1;
}
if (!get_thd()->count_cuted_fields)
if (!get_thd()->count_cuted_fields && !length)
err= 0;
}
else
{
set_warning(WARN_DATA_TRUNCATED, 1);
err= 1;
}
}
store_type((ulonglong) tmp);
return err;
@@ -8817,6 +8776,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
{
tmp=0;
set_warning(WARN_DATA_TRUNCATED, 1);
err= 1;
}
}
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,
const Item *item) const
{
DBUG_ASSERT(cmp_type() == INT_RESULT);
DBUG_ASSERT(result_type() == STRING_RESULT);
switch (item->cmp_type())
{
case TIME_RESULT:
@@ -10717,7 +10682,7 @@ uint32 Field_blob::char_length() const
case 3:
return 16777215;
case 4:
return (uint32) 4294967295U;
return (uint32) UINT_MAX32;
default:
DBUG_ASSERT(0); // we should never go here
return 0;
@@ -10770,7 +10735,7 @@ uint32 Field_blob::max_display_length()
case 3:
return 16777215 * field_charset->mbmaxlen;
case 4:
return (uint32) 4294967295U;
return (uint32) UINT_MAX32;
default:
DBUG_ASSERT(0); // we should never go here
return 0;

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
{
VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED,
@@ -872,11 +851,13 @@ public:
to be quoted when used in constructing an SQL query.
*/
virtual bool str_needs_quotes() { return FALSE; }
virtual Item_result result_type () const=0;
virtual Item_result cmp_type () const { return result_type(); }
virtual const Type_handler *cast_to_int_type_handler() const
Item_result result_type () 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 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 enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
virtual uint32 key_length() const { return pack_length(); }
virtual enum_field_types type() const =0;
virtual enum_field_types real_type() const { return type(); }
virtual const Type_handler *type_handler() const= 0;
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
{
/*
@@ -1318,9 +1306,6 @@ public:
virtual enum Derivation derivation(void) const
{ return DERIVATION_IMPLICIT; }
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; }
bool set_warning(Sql_condition::enum_warning_level, unsigned int code,
int cuted_increment) const;
@@ -1610,7 +1595,6 @@ public:
uchar null_bit_arg, utype unireg_check_arg,
const LEX_CSTRING *field_name_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; }
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
@@ -1672,8 +1656,8 @@ public:
const Item_equal *item_equal);
Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const LEX_CSTRING *field_name_arg, CHARSET_INFO *charset);
Item_result result_type () const { return STRING_RESULT; }
const LEX_CSTRING *field_name_arg,
const DTCollation &collation);
uint decimals() const { return NOT_FIXED_DEC; }
int save_in_field(Field *to) { return save_in_field_str(to); }
bool memcpy_field_possible(const Field *from) const
@@ -1693,12 +1677,6 @@ public:
uint repertoire(void) const { return field_repertoire; }
CHARSET_INFO *charset(void) const { return field_charset; }
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; }
uint32 max_display_length() { return field_length; }
friend class Create_field;
@@ -1740,9 +1718,10 @@ protected:
public:
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_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_name_arg, charset_arg)
field_name_arg, collation)
{}
int store_decimal(const my_decimal *d);
@@ -1781,7 +1760,6 @@ public:
field_name_arg, dec_arg, zero_arg, unsigned_arg),
not_fixed(dec_arg >= FLOATING_POINT_DECIMALS)
{}
Item_result result_type () const { return REAL_RESULT; }
Copy_func *get_copy_func(const Field *from) const
{
return do_field_real;
@@ -1818,7 +1796,7 @@ public:
unireg_check_arg, field_name_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
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
Copy_func *get_copy_func(const Field *from) const
@@ -1863,12 +1841,8 @@ public:
enum utype unireg_check_arg,
const LEX_CSTRING *field_name_arg,
uint8 dec_arg, bool zero_arg, bool unsigned_arg);
Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
const LEX_CSTRING *field_name_arg, uint8 dec_arg,
bool unsigned_arg);
enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;}
const Type_handler *type_handler() const { return &type_handler_newdecimal; }
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
{
// if (from->real_type() == MYSQL_TYPE_BIT) // QQ: why?
@@ -1918,7 +1892,6 @@ public:
uint16 mflags, int *order_var);
uint is_equal(Create_field *new_field);
virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data);
static Field *create_from_item(MEM_ROOT *root, Item *);
Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item);
};
@@ -1933,7 +1906,7 @@ public:
unireg_check_arg, field_name_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
{ return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; }
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,
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
{ return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;}
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2018,7 +1991,7 @@ public:
unireg_check_arg, field_name_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
{ return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; }
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,
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
{ return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; }
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,
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
{ return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2158,7 +2131,7 @@ public:
if (dec_arg >= FLOATING_POINT_DECIMALS)
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; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -2209,7 +2182,7 @@ public:
if (dec_arg >= FLOATING_POINT_DECIMALS)
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; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -2242,11 +2215,11 @@ class Field_null :public Field_str {
public:
Field_null(uchar *ptr_arg, uint32 len_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,
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
{
return do_field_string;
@@ -2296,7 +2269,6 @@ public:
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg)
{ flags|= BINARY_FLAG; }
Item_result result_type () const { return STRING_RESULT; }
int store_hex_hybrid(const char *str, uint length)
{
return store(str, length, &my_charset_bin);
@@ -2317,7 +2289,6 @@ public:
CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
bool binary() const { return true; }
enum Item_result cmp_type () const { return TIME_RESULT; }
bool val_bool() { return val_real() != 0e0; }
uint is_equal(Create_field *new_field);
bool eq_def(const Field *field) const
@@ -2394,7 +2365,7 @@ public:
enum utype unireg_check_arg,
const LEX_CSTRING *field_name_arg,
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; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -2528,7 +2499,7 @@ public:
Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_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; }
uint32 pack_length() const
{
@@ -2559,14 +2530,19 @@ public:
:Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
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
{
if (eq_def(from))
return get_identical_copy_func();
switch (from->cmp_type()) {
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;
}
case TIME_RESULT:
return do_field_temporal;
case DECIMAL_RESULT:
@@ -2604,7 +2580,7 @@ public:
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,
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; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
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,
unireg_check_arg, field_name_arg)
{}
enum_field_types type() const { return MYSQL_TYPE_DATE;}
enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; }
const Type_handler *type_handler() const { return &type_handler_newdate; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
double val_real(void);
@@ -2679,7 +2654,7 @@ public:
:Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
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; }
Copy_func *get_copy_func(const Field *from) const
{
@@ -2791,7 +2766,7 @@ public:
{
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; }
uint32 pack_length() const
{
@@ -2833,7 +2808,7 @@ public:
unireg_check == TIMESTAMP_DNUN_FIELD)
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; }
double val_real(void);
longlong val_int(void);
@@ -2950,7 +2925,7 @@ public:
:Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_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; }
uint32 pack_length() const
{
@@ -3028,29 +3003,35 @@ class Field_string :public Field_longstr {
public:
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:
bool can_alter_field_type;
Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
uchar null_bit_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,
unireg_check_arg, field_name_arg, cs),
unireg_check_arg, field_name_arg, collation),
can_alter_field_type(1) {};
Field_string(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,
NONE, field_name_arg, cs),
NONE, field_name_arg, collation),
can_alter_field_type(1) {};
enum_field_types type() const
const Type_handler *type_handler() 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 ?
MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING);
if (is_var_string())
return &type_handler_var_string;
return &type_handler_string;
}
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
@@ -3092,7 +3073,6 @@ public:
uint packed_col_length(const uchar *to, uint length);
uint max_packed_col_length(uint max_length);
uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return MYSQL_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
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,
uchar *null_ptr_arg, uchar null_bit_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,
unireg_check_arg, field_name_arg, cs),
unireg_check_arg, field_name_arg, collation),
length_bytes(length_bytes_arg)
{
share->varchar_fields++;
}
Field_varstring(uint32 len_arg,bool maybe_null_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,
NONE, field_name_arg, cs),
NONE, field_name_arg, collation),
length_bytes(len_arg < 256 ? 1 :2)
{
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;
uint row_pack_length() const { return field_length; }
bool zero_pack() const { return 0; }
@@ -3184,7 +3164,6 @@ public:
uint max_packed_col_length(uint max_length);
uint32 data_length();
uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
@@ -3224,20 +3203,21 @@ protected:
public:
Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_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,
CHARSET_INFO *cs)
const DTCollation &collation)
:Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
NONE, field_name_arg, cs),
NONE, field_name_arg, collation),
packlength(4)
{
flags|= BLOB_FLAG;
}
Field_blob(uint32 len_arg,bool maybe_null_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,
NONE, field_name_arg, cs)
NONE, field_name_arg, collation)
{
flags|= BLOB_FLAG;
packlength= 4;
@@ -3252,8 +3232,24 @@ public:
:Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, &temp_lex_str,
system_charset_info),
packlength(packlength_arg) {}
const Type_handler *type_handler() const;
/* 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
{ return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
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_name_arg, share, blob_pack_length, &my_charset_bin)
{ geom_type= geom_type_arg; srid= field_srid; }
Field_geom(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, enum geometry_type geom_type_arg)
:Field_blob(len_arg, maybe_null_arg, field_name_arg, &my_charset_bin)
{ geom_type= geom_type_arg; srid= 0; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
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,
const Item *item,
bool is_eq_func) const;
@@ -3492,20 +3495,15 @@ public:
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint packlength_arg,
TYPELIB *typelib_arg,
CHARSET_INFO *charset_arg)
const DTCollation &collation)
: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)
{
flags|=ENUM_FLAG;
}
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
enum_field_types type() const { return MYSQL_TYPE_STRING; }
enum Item_result cmp_type () const { return INT_RESULT; }
const Type_handler *cast_to_int_type_handler() const
{
return &type_handler_longlong;
}
const Type_handler *type_handler() const { return &type_handler_enum; }
enum ha_base_keytype key_type() const;
Copy_func *get_copy_func(const Field *from) const
{
@@ -3546,7 +3544,6 @@ public:
void store_type(ulonglong value);
void sql_type(String &str) const;
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)
{ return (field_metadata & 0x00ff); }
uint row_pack_length() const { return pack_length(); }
@@ -3576,6 +3573,9 @@ public:
*/
return false;
}
bool can_optimize_range(const Item_bool_func *cond,
const Item *item,
bool is_eq_func) const;
private:
int do_save_field_metadata(uchar *first_byte);
uint is_equal(Create_field *new_field);
@@ -3588,12 +3588,12 @@ public:
uchar null_bit_arg,
enum utype unireg_check_arg, const LEX_CSTRING *field_name_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,
unireg_check_arg, field_name_arg,
packlength_arg,
typelib_arg,charset_arg),
empty_set_string("", 0, charset_arg)
typelib_arg, collation),
empty_set_string("", 0, collation.collation)
{
flags=(flags & ~ENUM_FLAG) | SET_FLAG;
}
@@ -3606,7 +3606,7 @@ public:
String *val_str(String*,String *);
void sql_type(String &str) const;
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; }
private:
const String empty_set_string;
@@ -3636,13 +3636,12 @@ public:
Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_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_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; }
uint32 key_length() const { return (uint32) (field_length + 7) / 8; }
uint32 max_data_length() const { return (field_length + 7) / 8; }
uint32 max_display_length() { return field_length; }
uint size_of() const { return sizeof(*this); }
Item_result result_type () const { return INT_RESULT; }
int reset(void) {
bzero(ptr, bytes_in_rec);
if (bit_ptr && (bit_len > 0)) // reset odd bits among null bits

View File

@@ -518,7 +518,7 @@ Item::Item(THD *thd):
tables.
*/
Item::Item(THD *thd, Item *item):
Type_std_attributes(item),
Type_all_attributes(item),
join_tab_idx(item->join_tab_idx),
is_expensive_cache(-1),
rsize(0),
@@ -2348,7 +2348,7 @@ 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,
uint flags, int item_sep)
{
@@ -2395,7 +2395,7 @@ 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,
Item **args, uint nargs,
uint flags, int item_sep)
@@ -3780,7 +3780,7 @@ bool Item_param::set_from_item(THD *thd, Item *item)
}
}
struct st_value tmp;
if (!item->store(&tmp, 0))
if (!item->save_in_value(&tmp))
{
unsigned_flag= item->unsigned_flag;
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
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 */
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();
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;
}
@@ -9715,9 +9525,8 @@ Item_cache_temporal::Item_cache_temporal(THD *thd,
enum_field_types field_type_arg):
Item_cache_int(thd, field_type_arg)
{
if (mysql_type_to_time_type(Item_cache_temporal::field_type()) ==
MYSQL_TIMESTAMP_ERROR)
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
if (mysql_timestamp_type() == MYSQL_TIMESTAMP_ERROR)
set_handler(&type_handler_datetime2);
}
@@ -9825,7 +9634,7 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
}
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)
{
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))
{
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(),
"UNION");
DBUG_RETURN(true);
@@ -10375,6 +10184,14 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
};
maybe_null|= item->maybe_null;
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 */
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
them later.

View File

@@ -483,7 +483,7 @@ public:
class Item: public Value_source,
public Type_std_attributes
public Type_all_attributes
{
void operator=(Item &);
/**
@@ -536,10 +536,22 @@ protected:
SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param);
virtual Field *make_string_field(TABLE *table);
Field *tmp_table_field_from_field_type(TABLE *table,
bool fixed_length,
bool set_blob_packlength);
/**
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 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);
void push_note_converted_to_negative_complement(THD *thd);
@@ -664,54 +676,9 @@ public:
*/
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()) {
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;
return type_handler()->Item_save_in_value(this, value);
}
/* Function returns 1 on overflow and -1 on fatal errors */
@@ -1150,10 +1117,7 @@ public:
*/
uint decimal_scale() const
{
return decimals < NOT_FIXED_DEC ? decimals :
is_temporal_type_with_time(field_type()) ?
TIME_SECOND_PART_DIGITS :
MY_MIN(max_length, DECIMAL_MAX_SCALE);
return type_handler()->Item_decimal_scale(this);
}
/*
Returns how many digits a divisor adds into a division result.
@@ -1174,10 +1138,7 @@ public:
*/
uint divisor_precision_increment() const
{
return decimals < NOT_FIXED_DEC ? decimals :
is_temporal_type_with_time(field_type()) ?
TIME_SECOND_PART_DIGITS :
decimals;
return type_handler()->Item_divisor_precision_increment(this);
}
/**
TIME or DATETIME precision of the item: 0..6
@@ -1745,6 +1706,8 @@ public:
}
virtual Field::geometry_type get_geometry_type() const
{ return Field::GEOM_GEOMETRY; };
uint uint_geometry_type() const
{ return get_geometry_type(); }
String *check_well_formed_result(String *str, bool send_error= 0);
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
bool too_big_for_varchar() const
@@ -2263,7 +2226,7 @@ public:
based on result_type(), which is less exact.
*/
Field *create_field_for_create_select(TABLE *table)
{ return tmp_table_field_from_field_type(table, false, true); }
{ return tmp_table_field_from_field_type(table); }
};
@@ -2639,19 +2602,29 @@ public:
fast_field_copier setup_fast_field_copier(Field *field);
table_map used_tables() const;
table_map all_used_tables() const;
const Type_handler *type_handler() const
{
const Type_handler *handler= field->type_handler();
return handler->type_handler_for_item_field();
}
enum Item_result result_type () const
{
return field->result_type();
}
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
{
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
{
return MONOTONIC_STRICT_INCREASING;
@@ -3187,6 +3160,17 @@ public:
enum Type type() const { return INT_ITEM; }
enum Item_result result_type () const { return INT_RESULT; }
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; }
double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
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)
{ max_length= length; }
enum Type type() const { return TYPE_HOLDER; }
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
enum_field_types field_type() const
{
return Item_blob::type_handler()->field_type();
}
const Type_handler *type_handler() const
{
return Type_handler::blob_type_handler(max_length);
}
const Type_handler *real_type_handler() const
{
// Should not be called, Item_blob is used for SHOW purposes only.
@@ -3653,7 +3644,7 @@ public:
return &type_handler_varchar;
}
Field *create_field_for_schema(THD *thd, TABLE *table)
{ return tmp_table_field_from_field_type(table, false, true); }
{ return tmp_table_field_from_field_type(table); }
};
@@ -3690,6 +3681,10 @@ public:
unsigned_flag=1;
}
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 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:
/*
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,
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,
return Type_std_attributes::agg_arg_charsets(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,
Item **items, uint nitems,
int item_sep= 1)
{
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
MY_COLL_ALLOW_COERCIBLE_CONV |
MY_COLL_ALLOW_NUMERIC_CONV;
return agg_arg_charsets(c, items, nitems, flags, item_sep);
return Type_std_attributes::
agg_arg_charsets_for_string_result(c, func_name(),
items, nitems, 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,
Item **items,
uint nitems,
int item_sep= 1)
{
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, items, nitems, flags, item_sep);
return Type_std_attributes::
agg_arg_charsets_for_string_result_with_comparison(c, func_name(),
items, nitems,
item_sep);
}
/*
@@ -4153,13 +4099,10 @@ protected:
Item **items, uint nitems,
int item_sep= 1)
{
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
MY_COLL_ALLOW_COERCIBLE_CONV |
MY_COLL_DISALLOW_NONE;
return agg_arg_charsets(c, items, nitems, flags, item_sep);
return Type_std_attributes::
agg_arg_charsets_for_comparison(c, func_name(), items, nitems, item_sep);
}
public:
// This method is used by Arg_comparator
bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b)
@@ -5879,11 +5822,12 @@ public:
Item_type_holder(THD*, Item*);
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
{ 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
{
/*
@@ -5902,16 +5846,22 @@ public:
}
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; }
TYPELIB *get_typelib() const { return enum_set_typelib; }
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
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; };
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[2], m_cache);
}
set_handler_by_field_type(args[2]->field_type());
set_handler(args[2]->type_handler());
collation.set(args[2]->collation);
decimals= args[2]->decimals;
unsigned_flag= args[2]->unsigned_flag;

View File

@@ -1057,7 +1057,7 @@ public:
}
const char *func_name() const { return "ifnull"; }
Field *create_field_for_create_select(TABLE *table)
{ return tmp_table_field_from_field_type(table, false, false); }
{ return tmp_table_field_from_field_type(table); }
table_map not_null_tables() const { return 0; }
uint decimal_precision() const

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()
{
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) ||
(null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH)))
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->set_charset(&my_charset_bin);
DBUG_ASSERT(!null_value);
@@ -902,7 +809,7 @@ double Item_func_hybrid_field_type::val_real_from_date_op()
MYSQL_TIME ltime;
if (date_op_with_null_check(&ltime))
return 0;
ltime.time_type= mysql_type_to_time_type(field_type());
ltime.time_type= mysql_timestamp_type();
return TIME_to_double(&ltime);
}
@@ -911,7 +818,7 @@ longlong Item_func_hybrid_field_type::val_int_from_date_op()
MYSQL_TIME ltime;
if (date_op_with_null_check(&ltime))
return 0;
ltime.time_type= mysql_type_to_time_type(field_type());
ltime.time_type= mysql_timestamp_type();
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);
return 0;
}
ltime.time_type= mysql_type_to_time_type(field_type());
ltime.time_type= mysql_timestamp_type();
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 -
(args[0]->decimals ? args[0]->decimals + 1 : 0) + 2;
max_length= tmp_max_length > (ulonglong) 4294967295U ?
(uint32) 4294967295U : (uint32) tmp_max_length;
max_length= tmp_max_length > (ulonglong) UINT_MAX32 ?
(uint32) UINT_MAX32 : (uint32) tmp_max_length;
uint tmp= float_length(decimals);
set_if_smaller(max_length,tmp);
decimals= 0;

View File

@@ -42,44 +42,8 @@ protected:
uint allowed_arg_cols;
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);
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;
@@ -208,7 +172,7 @@ public:
{
return result_type() != STRING_RESULT ?
create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) :
tmp_table_field_from_field_type(table, false, false);
tmp_table_field_from_field_type(table);
}
Item *get_tmp_table_item(THD *thd);
@@ -2255,12 +2219,6 @@ public:
bool update();
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
Field *create_field_for_create_select(TABLE *table)
{
return result_type() != STRING_RESULT ?
create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) :
tmp_table_field_from_field_type(table, false, true);
}
table_map used_tables() const
{
return used_tables_cache | RAND_TABLE_BIT;
@@ -2302,6 +2260,14 @@ public:
my_decimal *val_decimal(my_decimal*);
String *val_str(String* str);
void fix_length_and_dec();
Field *create_field_for_create_select(TABLE *table)
{
return cmp_type() == STRING_RESULT ?
type_handler_long_blob.make_and_init_table_field(&(Item::name),
Record_addr(maybe_null),
*this, table) :
create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS);
}
virtual void print(String *str, enum_query_type query_type);
/*
We must always return variables as strings to guard against selects of type
@@ -2655,7 +2621,7 @@ public:
{
return result_type() != STRING_RESULT ?
sp_result_field :
tmp_table_field_from_field_type(table, false, false);
tmp_table_field_from_field_type(table);
}
void make_field(THD *thd, Send_field *tmp_field);

View File

@@ -40,20 +40,11 @@
#include "opt_range.h"
Field *Item_geometry_func::create_field_for_create_select(TABLE *t_arg)
{
Field *result;
if ((result= new Field_geom(max_length, maybe_null, &name, t_arg->s,
get_geometry_type())))
result->init(t_arg);
return result;
}
void Item_geometry_func::fix_length_and_dec()
{
collation.set(&my_charset_bin);
decimals=0;
max_length= (uint32) 4294967295U;
max_length= (uint32) UINT_MAX32;
maybe_null= 1;
}
@@ -206,7 +197,7 @@ String *Item_func_as_wkt::val_str_ascii(String *str)
void Item_func_as_wkt::fix_length_and_dec()
{
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
max_length=MAX_BLOB_WIDTH;
max_length= (uint32) UINT_MAX32;
maybe_null= 1;
}

View File

@@ -40,7 +40,6 @@ public:
Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
void fix_length_and_dec();
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
Field *create_field_for_create_select(TABLE *table);
};
class Item_func_geometry_from_text: public Item_geometry_func
@@ -101,7 +100,7 @@ public:
Item_func_as_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
const char *func_name() const { return "st_aswkb"; }
String *val_str(String *);
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_as_wkb>(thd, mem_root, this); }
};

View File

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

View File

@@ -1202,52 +1202,16 @@ 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 *field;
MEM_ROOT *mem_root;
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,
table, NULL)))
field->flags&= ~NOT_NULL_FLAG;
return field;
}
/*
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 *field;
MEM_ROOT *mem_root= table->in_use->mem_root;
if (group)
{
@@ -1679,22 +1641,16 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table)
The easiest way is to do this is to store both value in a string
and unpack on access.
*/
field= new (mem_root)
Field *field= new (table->in_use->mem_root)
Field_string(((Item_sum_avg::result_type() == DECIMAL_RESULT) ?
dec_bin_size : sizeof(double)) + sizeof(longlong),
0, &name, &my_charset_bin);
}
else if (Item_sum_avg::result_type() == DECIMAL_RESULT)
field= Field_new_decimal::create_from_item(mem_root, this);
else
{
field= new (mem_root) Field_double(max_length, maybe_null, &name,
decimals, TRUE);
}
if (field)
field->init(table);
return field;
}
return tmp_table_field_from_field_type(table);
}
void Item_sum_avg::clear()
@@ -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)
{
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,
element_count count __attribute__((unused)),
void* item_arg);
protected:
virtual Field *make_string_field(TABLE *table);
public:
Item_func_group_concat(THD *thd, Name_resolution_context *context_arg,
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 */
DBUG_ASSERT(field_type() == MYSQL_TYPE_STRING ||
ltime.time_type == MYSQL_TIMESTAMP_NONE ||
mysql_type_to_time_type(field_type()) == ltime.time_type);
ltime.time_type == mysql_timestamp_type());
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)
{ return val_decimal_from_date(decimal_value); }
Field *create_field_for_create_select(TABLE *table)
{ return tmp_table_field_from_field_type(table, false, false); }
{ return tmp_table_field_from_field_type(table); }
int save_in_field(Field *field, bool no_conversions)
{ return save_date_in_field(field, no_conversions); }
};
@@ -1018,7 +1018,7 @@ class Item_extract :public Item_int_func
return true;
}
Field *create_field_for_create_select(TABLE *table)
{ return tmp_table_field_from_field_type(table, false, false); }
{ return tmp_table_field_from_field_type(table); }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_extract>(thd, mem_root, this); }

View File

@@ -7926,7 +7926,9 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param,
if (!(res= value->val_str(&tmp)))
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);
/*
@@ -8022,6 +8024,19 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
goto end;
err= value->save_in_field_no_warnings(field, 1);
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)
@@ -8033,8 +8048,7 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
tree= NULL; /* Cannot infer anything */
goto end;
}
if (err > 0)
{
if (field->cmp_type() != value->result_type())
{
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 &&
inner->real_item()->type() == Item::FIELD_ITEM);
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);
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))
{
my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0),
item_field->name);
item_field->name.str);
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
*/
@@ -3114,7 +3134,7 @@ int select_export::send_data(List<Item> &items)
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER_THD(thd, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"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())
{

View File

@@ -3427,6 +3427,20 @@ public:
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(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 */
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 exec();
bool exec_recursive();

View File

@@ -15880,22 +15880,9 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length)
break;
}
case TIME_RESULT:
new_field= tmp_table_field_from_field_type(table, true, false);
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:
new_field= Field_new_decimal::create_from_item(mem_root, this);
case STRING_RESULT:
new_field= tmp_table_field_from_field_type(table);
break;
case ROW_RESULT:
// This case should never be choosen
@@ -15981,7 +15968,7 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table)
field->init(table);
return field;
}
return tmp_table_field_from_field_type(table, false, false);
return tmp_table_field_from_field_type(table);
}
@@ -16032,6 +16019,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
}
switch (type) {
case Item::TYPE_HOLDER:
case Item::SUM_FUNC_ITEM:
{
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,
(make_copy_field ? 0 : copy_func),
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
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
{
uint32 octet_max_length= field->max_display_length();
if (is_blob && octet_max_length != (uint32) 4294967295U)
if (is_blob && octet_max_length != (uint32) UINT_MAX32)
octet_max_length /= field->charset()->mbmaxlen;
longlong char_max_len= is_blob ?
(longlong) octet_max_length / field->charset()->mbminlen :

View File

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

View File

@@ -21,39 +21,44 @@
#include "item.h"
#include "log.h"
static Type_handler_tiny type_handler_tiny;
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_row type_handler_row;
Type_handler_null type_handler_null;
Type_handler_row type_handler_row;
Type_handler_string type_handler_string;
Type_handler_varchar type_handler_varchar;
Type_handler_tiny type_handler_tiny;
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_float type_handler_float;
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_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_newdate type_handler_newdate;
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
Type_handler_geometry type_handler_geometry;
#endif
@@ -80,9 +85,18 @@ bool Type_handler_data::init()
m_type_aggregator_for_result.add(&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,
&type_handler_blob,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_medium_blob,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_long_blob,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_varchar,
&type_handler_long_blob) ||
@@ -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:
- 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:
- 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
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_tiny_blob::m_name_tinyblob(C_STRING_WITH_LEN("tinyblob")),
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;
}
/***************************************************************************/
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());
}
/*************************************************************************/
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
@@ -1436,7 +2065,18 @@ bool Type_handler_string_result::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
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 cmp_item;
class in_vector;
class Type_std_attributes;
class Sort_param;
class Arg_comparator;
struct st_value;
struct TABLE;
struct SORT_FIELD_ATTR;
@@ -130,6 +130,21 @@ public:
derivation= DERIVATION_NONE;
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)
{
collation= collation_arg;
@@ -311,6 +326,155 @@ public:
{
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
{
protected:
@@ -341,8 +530,19 @@ protected:
Item_func_or_sum_illegal_param(const char *name) const;
bool
Item_func_or_sum_illegal_param(const Item_func_or_sum *) const;
bool check_null(const Item *item, st_value *value) const;
public:
static const Type_handler *blob_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_real_type(enum_field_types 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 Item_result result_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:
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 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 const Type_handler*
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_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,
e.g. SUM(DISTINCT expr), AVG(DISTINCT expr), etc.
@@ -427,6 +653,14 @@ public:
virtual Field *make_conversion_table_field(TABLE *TABLE,
uint metadata,
const Field *target) const= 0;
virtual Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const= 0;
Field *make_and_init_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
virtual void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const= 0;
@@ -435,6 +669,7 @@ public:
SORT_FIELD_ATTR *attr) 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,
bool no_conversions) const= 0;
@@ -480,6 +715,9 @@ public:
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
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 bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
@@ -605,6 +843,12 @@ public:
return ROW_RESULT;
}
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
{
DBUG_ASSERT(0);
@@ -617,6 +861,14 @@ public:
DBUG_ASSERT(0);
return NULL;
}
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const
{
DBUG_ASSERT(0);
return NULL;
}
void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const
@@ -633,6 +885,7 @@ public:
DBUG_ASSERT(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
{
DBUG_ASSERT(0);
@@ -834,11 +1087,14 @@ public:
Item_result cmp_type() const { return REAL_RESULT; }
virtual ~Type_handler_real_result() {}
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,
Sort_param *param) const;
void sortlength(THD *thd,
const Type_std_attributes *item,
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;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
@@ -889,6 +1145,8 @@ public:
Item_result cmp_type() const { return DECIMAL_RESULT; }
virtual ~Type_handler_decimal_result() {};
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;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
@@ -896,6 +1154,7 @@ public:
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) 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;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
@@ -943,12 +1202,15 @@ public:
Item_result cmp_type() const { return INT_RESULT; }
virtual ~Type_handler_int_result() {}
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;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
void sortlength(THD *thd,
const Type_std_attributes *item,
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;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
@@ -991,6 +1253,9 @@ public:
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:
Item_result result_type() const { return STRING_RESULT; }
Item_result cmp_type() const { return TIME_RESULT; }
@@ -1005,6 +1270,8 @@ public:
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
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;
bool set_comparator_func(Arg_comparator *cmp) 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);
}
bool Item_save_in_value(Item *item, st_value *value) 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
{
@@ -1081,6 +1349,8 @@ public:
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
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;
bool set_comparator_func(Arg_comparator *cmp) const;
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; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1169,6 +1443,10 @@ public:
uint32 max_display_length(const Item *item) const { return 6; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1185,6 +1463,10 @@ public:
}
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1198,6 +1480,10 @@ public:
uint32 max_display_length(const Item *item) const { return 20; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1211,6 +1497,10 @@ public:
uint32 max_display_length(const Item *item) const { return 8; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1224,6 +1514,10 @@ public:
uint32 max_display_length(const Item *item) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1241,6 +1535,10 @@ public:
}
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1255,6 +1553,10 @@ public:
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1268,6 +1570,10 @@ public:
uint32 max_display_length(const Item *item) const { return 53; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1278,7 +1584,20 @@ public:
virtual ~Type_handler_time_common() { }
const Name name() const { return m_name_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;
bool Item_save_in_value(Item *item, st_value *value) 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;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
@@ -1294,6 +1613,10 @@ public:
virtual ~Type_handler_time() {}
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1304,6 +1627,10 @@ public:
enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1312,6 +1639,7 @@ class Type_handler_temporal_with_date: public Type_handler_temporal_result
public:
virtual ~Type_handler_temporal_with_date() {}
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;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
@@ -1325,6 +1653,10 @@ public:
virtual ~Type_handler_date_common() {}
const Name name() const { return m_name_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;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
@@ -1336,6 +1668,10 @@ public:
virtual ~Type_handler_date() {}
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1343,8 +1679,13 @@ class Type_handler_newdate: public Type_handler_date_common
{
public:
virtual ~Type_handler_newdate() {}
enum_field_types real_field_type() const { return MYSQL_TYPE_NEWDATE; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1355,6 +1696,18 @@ public:
virtual ~Type_handler_datetime_common() {}
const Name name() const { return m_name_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;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
@@ -1367,6 +1720,10 @@ public:
virtual ~Type_handler_datetime() {}
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1377,6 +1734,10 @@ public:
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1387,6 +1748,18 @@ public:
virtual ~Type_handler_timestamp_common() {}
const Name name() const { return m_name_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;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
@@ -1399,6 +1772,10 @@ public:
virtual ~Type_handler_timestamp() {}
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1409,6 +1786,10 @@ public:
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1419,8 +1800,14 @@ public:
virtual ~Type_handler_olddecimal() {}
const Name name() const { return m_name_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,
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; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1444,9 +1835,16 @@ public:
const Name name() const { return m_name_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_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; }
bool Item_save_in_value(Item *item, st_value *value) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1458,8 +1856,36 @@ public:
const Name name() const { return m_name_char; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
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,
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() {}
const Name name() const { return m_name_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; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1480,7 +1918,22 @@ class Type_handler_blob_common: public Type_handler_string_result
{
public:
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 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; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1505,6 +1962,10 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1517,6 +1978,10 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1529,6 +1994,10 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
};
@@ -1542,8 +2011,18 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
bool is_param_long_data_type() const { return true; }
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,
const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
bool is_traditional_type() const
{
return false;
@@ -1576,10 +2055,16 @@ class Type_handler_enum: public Type_handler_string_result
public:
virtual ~Type_handler_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; }
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,
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:
virtual ~Type_handler_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; }
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,
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 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)
{
m_type_handler= other;
@@ -1673,22 +2168,47 @@ public:
extern Type_handler_row type_handler_row;
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_newdate type_handler_newdate;
extern Type_handler_datetime2 type_handler_datetime2;
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_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_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
{

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,
@@ -748,14 +801,21 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
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())
{
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 (prepare_join(thd_arg, sl, tmp_result, additional_options,
is_union_select))
goto err;
/*
setup_tables_done_option should be set only for very first SELECT,
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).
*/
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
information about fields lengths and exact types
*/
if (!is_union_select && !is_recursive)
types= first_sl->item_list;
else if (sl == first_sl)
if (sl == first_sl)
{
if (is_recursive)
{
@@ -846,6 +865,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
Item *type, *item_tmp;
while ((type= tp++, item_tmp= it++))
{
DBUG_ASSERT(item_tmp->fixed);
if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
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
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);
err:
my_error(ER_DUP_FIELDNAME, MYF(0), item->name);
my_error(ER_DUP_FIELDNAME, MYF(0), item->name.str);
DBUG_RETURN(TRUE);
}

View File

@@ -13713,27 +13713,7 @@ load_data_set_elem:
text_literal:
TEXT_STRING
{
LEX_CSTRING tmp;
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)
if (!($$= thd->make_string_literal($1)))
MYSQL_YYABORT;
}
| NCHAR_STRING

View File

@@ -13837,27 +13837,7 @@ load_data_set_elem:
text_literal:
TEXT_STRING
{
LEX_CSTRING tmp;
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)
if (!($$= thd->make_string_literal($1)))
MYSQL_YYABORT;
}
| NCHAR_STRING