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

Use default character set for expressions

- Force usage of () around complex DEFAULT expressions
- Give error if DEFAULT expression contains invalid characters
- Don't use const_charset_conversion for stored Item_func_sysconf expressions
  as the result is not constaint over different executions
- Fixed Item_func_user() to not store calculated value in str_value
This commit is contained in:
Michael Widenius
2016-06-24 23:42:35 +02:00
committed by Sergei Golubchik
parent 8f226121e5
commit fb67cde237
21 changed files with 508 additions and 268 deletions

View File

@@ -264,13 +264,13 @@ drop table t1;
Check default expressions
create or replace table t1 (a int default 1, b int default a+1, c int default a+b) engine myisam;
create or replace table t1 (a int default 1, b int default (a+1), c int default (a+b)) engine myisam;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT '1',
`b` int(11) DEFAULT a+1,
`c` int(11) DEFAULT a+b
`b` int(11) DEFAULT (a+1),
`c` int(11) DEFAULT (a+b)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values ();
insert into t1 (a) values (2);
@@ -299,9 +299,9 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` blob DEFAULT (1),
`c` blob DEFAULT ("hello"),
`t` text DEFAULT (concat(a,b,c))
`b` blob DEFAULT 1,
`c` blob DEFAULT "hello",
`t` text DEFAULT concat(a,b,c)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 (a) values (2);
insert into t1 (a,b) values (10,"test1");
@@ -323,16 +323,17 @@ a > 0
drop table t1;
create or replace table t1 (param_list int DEFAULT (1+1) NOT NULL);
create or replace table t1 (param_list int DEFAULT 1+1 NOT NULL);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '+1 NOT NULL)' at line 1
create or replace table t1 (param_list blob DEFAULT "" NOT NULL);
drop table t1;
create table t1 (a int);
insert into t1 values(-1);
alter table t1 add b int default 1, add c int default -1, add d int default 1+1, add e timestamp;
alter table t1 add b int default 1, add c int default -1, add d int default (1+1), add e timestamp;
select a,b,c,d,e > 0 from t1;
a b c d e > 0
-1 1 -1 2 1
insert into t1 values(10,10,10,10,0);
alter table t1 add f int default 1+1+1 null, add g int default 1+1+1+1 not null,add h int default (2+2+2+2);
alter table t1 add f int default (1+1+1) null, add g int default (1+1+1+1) not null,add h int default (2+2+2+2);
select a,b,c,d,e > 0,f,g,h from t1;
a b c d e > 0 f g h
-1 1 -1 2 1 3 4 8
@@ -343,10 +344,10 @@ t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT '1',
`c` int(11) DEFAULT '-1',
`d` int(11) DEFAULT 1+1,
`d` int(11) DEFAULT (1+1),
`e` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`f` int(11) DEFAULT 1+1+1,
`g` int(11) NOT NULL DEFAULT 1+1+1+1,
`f` int(11) DEFAULT (1+1+1),
`g` int(11) NOT NULL DEFAULT (1+1+1+1),
`h` int(11) DEFAULT (2+2+2+2)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
create table t2 like t1;
@@ -356,10 +357,10 @@ t2 CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT '1',
`c` int(11) DEFAULT '-1',
`d` int(11) DEFAULT 1+1,
`d` int(11) DEFAULT (1+1),
`e` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`f` int(11) DEFAULT 1+1+1,
`g` int(11) NOT NULL DEFAULT 1+1+1+1,
`f` int(11) DEFAULT (1+1+1),
`g` int(11) NOT NULL DEFAULT (1+1+1+1),
`h` int(11) DEFAULT (2+2+2+2)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t2 (a) values (100);
@@ -367,18 +368,21 @@ select a,b,c,d,e > 0,f,g,h from t2;
a b c d e > 0 f g h
100 1 -1 2 1 3 4 8
drop table t1,t2;
create table t1 (a int default 1----1);
create table t1 (a int default (1----1), b int default - 1, c int default +1, e int default (--1));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT 1----1
`a` int(11) DEFAULT (1----1),
`b` int(11) DEFAULT '-1',
`c` int(11) DEFAULT '1',
`e` int(11) DEFAULT '1'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values();
insert into t1 values();
select * from t1;
a
2
2
a b c e
2 -1 1 1
2 -1 1 1
drop table t1;
create or replace can delete a table on error
@@ -395,15 +399,15 @@ create or replace table t1 (a int default 1, b int default a);
create or replace table t1 (a int default 1, b int as (a));
create or replace table t1 (a int default b, b int default 1);
create or replace table t1 (a int as (b), b int default 1);
create or replace table t1 (a int as (b), b int default 1+1);
create or replace table t1 (a int as (b), b int default (1+1));
create or replace table t1 (a int default 1, b int as (c), c int default (a+1));
create or replace table t1 (a int default 1+1, b int as (c), c int default (a+1));
create or replace table t1 (a int default (1+1), b int as (c), c int default (a+1));
create or replace table t1 (a VARCHAR(128) DEFAULT @@version);
create or replace table t1 (a int not null, b int as (a));
create or replace table t1 (a int not null, b int default a+1);
create or replace table t1 (a int not null, b int default (a+1));
create or replace table t1 (a int default a);
ERROR 01000: Expression for field `a` is refering to uninitialized field `a`
create or replace table t1 (a int default b, b int default 1+1);
create or replace table t1 (a int default b, b int default (1+1));
ERROR 01000: Expression for field `a` is refering to uninitialized field `b`
create or replace table t1 (a int default 1, b int as (c), c int as (a+1));
ERROR 01000: Expression for field `b` is refering to uninitialized field `c`
@@ -446,16 +450,22 @@ Error handling
create or replace table t1 (a bigint default xxx());
ERROR HY000: Function or expression '`xxx`' is not allowed for 'DEFAULT' of column/constraint 'a'
create or replace table t1 (a bigint default (select (1)));
ERROR HY000: Function or expression 'subselect' is not allowed for 'DEFAULT' of column/constraint 'a'
create or replace table t1 (a bigint default (1,2,3)));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'select (1)))' at line 1
create or replace table t1 (a bigint default (1,2,3));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '2,3))' at line 1
create or replace table t1 (a bigint default ((1,2,3)));
ERROR 21000: Operand should contain 1 column(s)
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a DIV b);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DIV b)' at line 1
CREATE TABLE t1 (a INT, b INT DEFAULT -a);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a)' at line 1
drop table if exists t1;
Warnings:
Note 1051 Unknown table 'test.t1'
#
# Invalid DEFAULT expressions
#
CREATE TABLE t1 (a INT DEFAULT (SELECT 1));
CREATE TABLE t1 (a INT DEFAULT ((SELECT 1)));
ERROR HY000: Function or expression 'subselect' is not allowed for 'DEFAULT' of column/constraint 'a'
CREATE TABLE t1 (a INT DEFAULT (EXISTS (SELECT 1)));
ERROR HY000: Function or expression 'subselect' is not allowed for 'DEFAULT' of column/constraint 'a'
@@ -463,14 +473,12 @@ CREATE TABLE t1 (a INT DEFAULT (1=ANY (SELECT 1)));
ERROR HY000: Function or expression 'subselect' is not allowed for 'DEFAULT' of column/constraint 'a'
CREATE TABLE t1 (a INT DEFAULT ROW(1,1));
ERROR 21000: Operand should contain 1 column(s)
CREATE TABLE t1 (a INT DEFAULT (1,1));
ERROR 21000: Operand should contain 1 column(s)
CREATE TABLE t1 (a INT DEFAULT ((1,1)));
ERROR 21000: Operand should contain 1 column(s)
CREATE TABLE t1 (a INT DEFAULT ?);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?)' at line 1
Got one of the listed errors
CREATE TABLE t1 (a INT DEFAULT(?));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?))' at line 1
Got one of the listed errors
CREATE TABLE t1 (a INT DEFAULT (b), b INT DEFAULT(a));
ERROR 01000: Expression for field `a` is refering to uninitialized field `b`
CREATE TABLE t1 (a INT DEFAULT @v);
@@ -546,7 +554,7 @@ DEALLOCATE PREPARE stmt;
PREPARE stmt FROM 'CREATE TABLE t1 (a INT DEFAULT(?+?))';
set @a=1;
execute stmt using @a,@a;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?+?))' at line 1
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?+?)' at line 1
DEALLOCATE PREPARE stmt;
#
# Parenthesized Item_basic_constant
@@ -920,7 +928,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT (a)
`b` int(11) DEFAULT a
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (1, 1);
INSERT INTO t1 VALUES (DEFAULT, DEFAULT);
@@ -940,7 +948,7 @@ CREATE TABLE t1 (a INT DEFAULT(DEFAULT(b)), b INT DEFAULT 1);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT (DEFAULT(b)),
`a` int(11) DEFAULT DEFAULT(b),
`b` int(11) DEFAULT '1'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (DEFAULT, DEFAULT);
@@ -953,7 +961,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT '1',
`b` int(11) DEFAULT (DEFAULT(a))
`b` int(11) DEFAULT DEFAULT(a)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (DEFAULT, DEFAULT);
SELECT * FROM t1;
@@ -1135,7 +1143,7 @@ DROP TABLE t1;
#
# Check DEFAULT() function
#
CREATE TABLE `t1` (`a` int(11) DEFAULT 3+3,`b` int(11) DEFAULT '1000');
CREATE TABLE `t1` (`a` int(11) DEFAULT (3+3),`b` int(11) DEFAULT '1000');
insert into t1 values (1,1),(2,2);
insert into t1 values (default,default);
select * from t1;
@@ -1210,7 +1218,7 @@ SELECT * FROM t1;
a b
34 3
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a DIV b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a DIV b));
INSERT INTO t1 (a, b) VALUES (13, 3);
SELECT * FROM t1;
a b c
@@ -1268,6 +1276,8 @@ CREATE TABLE t1 (a INT DEFAULT MASTER_POS_WAIT('test',100));
ERROR HY000: Function or expression 'master_pos_wait' is not allowed for 'DEFAULT' of column/constraint 'a'
CREATE TABLE t1 (a INT DEFAULT MASTER_GTID_WAIT('test'));
ERROR HY000: Function or expression 'master_gtid_wait' is not allowed for 'DEFAULT' of column/constraint 'a'
CREATE TABLE t1 (a VARCHAR(30), b DOUBLE DEFAULT MATCH (a) AGAINST('bbbb' IN BOOLEAN MODE));
ERROR HY000: Function or expression 'match' is not allowed for 'DEFAULT' of column/constraint 'b'
#
# Temporal functions
#
@@ -1601,7 +1611,13 @@ a b c
0 1 2
1 1 1
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT -a);
CREATE TABLE t1 (a INT, b INT DEFAULT (-a));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT (-a)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (10, DEFAULT);
SELECT * FROM t1;
a b
@@ -1621,13 +1637,22 @@ a b c d
1.5 2 1 2
-1.5 -1 -2 -2
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a+b, d INT DEFAULT a-b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a+b), d INT DEFAULT (a-b));
INSERT INTO t1 VALUES (2, 1, DEFAULT, DEFAULT);
SELECT * FROM t1;
a b c d
2 1 3 1
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a*b, d INT DEFAULT a/b, e INT DEFAULT a MOD b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a*b), d INT DEFAULT (a/b), e INT DEFAULT (a MOD b));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT (a*b),
`d` int(11) DEFAULT (a/b),
`e` int(11) DEFAULT (a MOD b)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (7, 3, DEFAULT, DEFAULT, DEFAULT);
SELECT * FROM t1;
a b c d e
@@ -1699,8 +1724,16 @@ CREATE TABLE t1 (
a VARCHAR(10) CHARACTER SET latin1,
b VARCHAR(10) CHARACTER SET latin1 DEFAULT a COLLATE latin1_bin,
c VARCHAR(10) CHARACTER SET utf8 DEFAULT CONVERT(a USING utf8),
d VARBINARY(10) DEFAULT BINARY(a)
d VARBINARY(10) DEFAULT (BINARY(a))
);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
`b` varchar(10) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT a,
`c` varchar(10) CHARACTER SET utf8 DEFAULT CONVERT(a USING utf8),
`d` varbinary(10) DEFAULT (BINARY(a))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 (a) VALUES ('a');
SELECT * FROM t1;
a b c d
@@ -1715,31 +1748,39 @@ SELECT * FROM t1;
a b
7 3
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a|b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a|b));
INSERT INTO t1 (a,b) VALUES (1,2);
SELECT * FROM t1;
a b c
1 2 3
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a&b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a&b));
INSERT INTO t1 (a,b) VALUES (5,4);
SELECT * FROM t1;
a b c
5 4 4
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a^b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a^b));
INSERT INTO t1 (a,b) VALUES (11,3);
SELECT * FROM t1;
a b c
11 3 8
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a&~b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a&~b));
INSERT INTO t1 (a,b) VALUES (5,1);
SELECT * FROM t1;
a b c
5 1 4
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a<<b, d INT DEFAULT a>>b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a<<b), d INT DEFAULT (a>>b));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT (a<<b),
`d` int(11) DEFAULT (a>>b)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 (a,b) VALUES (5,1);
SELECT * FROM t1;
a b c d
@@ -1918,7 +1959,13 @@ ERROR HY000: Function or expression 'load_file' is not allowed for 'DEFAULT' of
#
# Predicates
#
CREATE TABLE t1 (a INT, b INT DEFAULT NOT a);
CREATE TABLE t1 (a INT, b INT DEFAULT (NOT a));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT (NOT a)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
a b
@@ -1926,7 +1973,7 @@ NULL NULL
0 1
1 0
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, x INT DEFAULT a XOR b);
CREATE TABLE t1 (a INT, b INT, x INT DEFAULT (a XOR b));
INSERT INTO t1 (a,b) VALUES (0,0),(0,1),(1,0),(1,1);
SELECT * FROM t1;
a b x
@@ -1935,7 +1982,14 @@ a b x
1 0 1
1 1 0
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT a IS TRUE, c INT DEFAULT a IS NOT TRUE);
CREATE TABLE t1 (a INT, b INT DEFAULT (a IS TRUE), c INT DEFAULT (a IS NOT TRUE));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT (a IS TRUE),
`c` int(11) DEFAULT (a IS NOT TRUE)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
a b c
@@ -1943,7 +1997,7 @@ NULL 0 1
0 0 1
1 1 0
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT a IS FALSE, c INT DEFAULT a IS NOT FALSE);
CREATE TABLE t1 (a INT, b INT DEFAULT (a IS FALSE), c INT DEFAULT (a IS NOT FALSE));
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
a b c
@@ -1951,7 +2005,7 @@ NULL 0 1
0 1 0
1 0 1
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT a IS NULL, c INT DEFAULT a IS NOT NULL);
CREATE TABLE t1 (a INT, b INT DEFAULT (a IS NULL), c INT DEFAULT (a IS NOT NULL));
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
a b c
@@ -1959,7 +2013,7 @@ NULL 1 0
0 0 1
1 0 1
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT a IS UNKNOWN, c INT DEFAULT a IS NOT UNKNOWN);
CREATE TABLE t1 (a INT, b INT DEFAULT (a IS UNKNOWN), c INT DEFAULT (a IS NOT UNKNOWN));
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
a b c
@@ -1968,10 +2022,10 @@ NULL 1 0
1 0 1
DROP TABLE t1;
CREATE TABLE t1 (a INT,
eq INT DEFAULT a=0, equal INT DEFAULT a<=>0,
ne INT DEFAULT a<>0,
lt INT DEFAULT a<0, le INT DEFAULT a<=0,
gt INT DEFAULT a>0, ge INT DEFAULT a>=0);
eq INT DEFAULT (a=0), equal INT DEFAULT (a<=>0),
ne INT DEFAULT (a<>0),
lt INT DEFAULT (a<0), le INT DEFAULT (a<=0),
gt INT DEFAULT (a>0), ge INT DEFAULT (a>=0));
INSERT INTO t1 (a) VALUES (NULL),(-1),(0),(1);
SELECT * FROM t1;
a eq equal ne lt le gt ge
@@ -1980,7 +2034,7 @@ NULL NULL 0 NULL NULL NULL NULL NULL
0 1 1 0 0 1 0 1
1 0 0 1 0 0 1 1
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a LIKE 'a%');
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a LIKE 'a%'));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb');
SELECT * FROM t1;
a b
@@ -1988,7 +2042,7 @@ AAA 1
aaa 1
bbb 0
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a RLIKE 'a$');
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a RLIKE 'a$'));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb');
SELECT * FROM t1;
a b
@@ -1996,7 +2050,7 @@ AAA 1
aaa 1
bbb 0
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a IN ('aaa','bbb'));
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a IN ('aaa','bbb')));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb'),('ccc');
SELECT * FROM t1;
a b
@@ -2005,7 +2059,7 @@ aaa 1
bbb 1
ccc 0
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a NOT IN ('aaa','bbb'));
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a NOT IN ('aaa','bbb')));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb'),('ccc');
SELECT * FROM t1;
a b
@@ -2014,7 +2068,7 @@ aaa 0
bbb 0
ccc 1
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a BETWEEN 'aaa' AND 'bbb');
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a BETWEEN 'aaa' AND 'bbb'));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb'),('ccc');
SELECT * FROM t1;
a b
@@ -2023,7 +2077,7 @@ aaa 1
bbb 1
ccc 0
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a NOT BETWEEN 'aaa' AND 'bbb');
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a NOT BETWEEN 'aaa' AND 'bbb'));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb'),('ccc');
SELECT * FROM t1;
a b
@@ -2159,3 +2213,10 @@ SELECT c FROM t1;
c
test
DROP TABLE t1;
#
# Collations
#
CREATE TABLE t1 (a VARCHAR(20) CHARACTER SET latin1 DEFAULT CONCAT('<27>')) CHARACTER SET koi8r COLLATE koi8r_bin;
ERROR 22007: Encountered illegal value '<27>' when converting to koi8r
CREATE OR REPLACE TABLE t1 (a char(2) default concat('A') COLLATE utf8mb4_unicode_ci);
DROP TABLE t1;

View File

@@ -1,14 +1,14 @@
include/master-slave.inc
[connection master]
connection master;
create table t1 (a int DEFAULT 1+1, b bigint default uuid_short(), u blob default user());
create table t1 (a int DEFAULT (1+1), b bigint default uuid_short(), u blob default user());
insert into t1 (a) values(1);
connection slave;
connection slave;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT 1+1,
`a` int(11) DEFAULT (1+1),
`b` bigint(20) DEFAULT uuid_short(),
`u` blob DEFAULT user()
) ENGINE=MyISAM DEFAULT CHARSET=latin1

View File

@@ -9,7 +9,7 @@
connection master;
create table t1 (a int DEFAULT 1+1, b bigint default uuid_short(), u blob default user());
create table t1 (a int DEFAULT (1+1), b bigint default uuid_short(), u blob default user());
insert into t1 (a) values(1);
let $b=query_get_value(select * from t1, b, 1);

View File

@@ -207,7 +207,7 @@ drop table t1;
--echo Check default expressions
--echo
create or replace table t1 (a int default 1, b int default a+1, c int default a+b) engine myisam;
create or replace table t1 (a int default 1, b int default (a+1), c int default (a+b)) engine myisam;
show create table t1;
insert into t1 values ();
insert into t1 (a) values (2);
@@ -238,16 +238,18 @@ select a > 0 from t1;
drop table t1;
create or replace table t1 (param_list int DEFAULT (1+1) NOT NULL);
--error ER_PARSE_ERROR
create or replace table t1 (param_list int DEFAULT 1+1 NOT NULL);
create or replace table t1 (param_list blob DEFAULT "" NOT NULL);
drop table t1;
create table t1 (a int);
insert into t1 values(-1);
alter table t1 add b int default 1, add c int default -1, add d int default 1+1, add e timestamp;
alter table t1 add b int default 1, add c int default -1, add d int default (1+1), add e timestamp;
select a,b,c,d,e > 0 from t1;
insert into t1 values(10,10,10,10,0);
alter table t1 add f int default 1+1+1 null, add g int default 1+1+1+1 not null,add h int default (2+2+2+2);
alter table t1 add f int default (1+1+1) null, add g int default (1+1+1+1) not null,add h int default (2+2+2+2);
select a,b,c,d,e > 0,f,g,h from t1;
show create table t1;
@@ -257,7 +259,7 @@ insert into t2 (a) values (100);
select a,b,c,d,e > 0,f,g,h from t2;
drop table t1,t2;
create table t1 (a int default 1----1);
create table t1 (a int default (1----1), b int default - 1, c int default +1, e int default (--1));
show create table t1;
insert into t1 values();
insert into t1 values();
@@ -281,18 +283,18 @@ create or replace table t1 (a int default 1, b int default a);
create or replace table t1 (a int default 1, b int as (a));
create or replace table t1 (a int default b, b int default 1);
create or replace table t1 (a int as (b), b int default 1);
create or replace table t1 (a int as (b), b int default 1+1);
create or replace table t1 (a int as (b), b int default (1+1));
create or replace table t1 (a int default 1, b int as (c), c int default (a+1));
create or replace table t1 (a int default 1+1, b int as (c), c int default (a+1));
create or replace table t1 (a int default (1+1), b int as (c), c int default (a+1));
create or replace table t1 (a VARCHAR(128) DEFAULT @@version);
create or replace table t1 (a int not null, b int as (a));
create or replace table t1 (a int not null, b int default a+1);
create or replace table t1 (a int not null, b int default (a+1));
--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
create or replace table t1 (a int default a);
--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
create or replace table t1 (a int default b, b int default 1+1);
create or replace table t1 (a int default b, b int default (1+1));
--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
create or replace table t1 (a int default 1, b int as (c), c int as (a+1));
--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
@@ -323,10 +325,16 @@ drop table t1;
--error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
create or replace table t1 (a bigint default xxx());
--error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
--error ER_PARSE_ERROR
create or replace table t1 (a bigint default (select (1)));
--error ER_PARSE_ERROR
create or replace table t1 (a bigint default (1,2,3));
--error ER_OPERAND_COLUMNS
create or replace table t1 (a bigint default (1,2,3)));
create or replace table t1 (a bigint default ((1,2,3)));
--error ER_PARSE_ERROR
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a DIV b);
--error ER_PARSE_ERROR
CREATE TABLE t1 (a INT, b INT DEFAULT -a);
# Cleanup
drop table if exists t1;
@@ -336,7 +344,7 @@ drop table if exists t1;
--echo #
--error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a INT DEFAULT (SELECT 1));
CREATE TABLE t1 (a INT DEFAULT ((SELECT 1)));
--error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a INT DEFAULT (EXISTS (SELECT 1)));
@@ -347,15 +355,12 @@ CREATE TABLE t1 (a INT DEFAULT (1=ANY (SELECT 1)));
--error ER_OPERAND_COLUMNS
CREATE TABLE t1 (a INT DEFAULT ROW(1,1));
--error ER_OPERAND_COLUMNS
CREATE TABLE t1 (a INT DEFAULT (1,1));
--error ER_OPERAND_COLUMNS
CREATE TABLE t1 (a INT DEFAULT ((1,1)));
--error ER_PARSE_ERROR
--error ER_PARSE_ERROR,2031
CREATE TABLE t1 (a INT DEFAULT ?);
--error ER_PARSE_ERROR
--error ER_PARSE_ERROR,2031
CREATE TABLE t1 (a INT DEFAULT(?));
--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
@@ -864,7 +869,7 @@ DROP TABLE t1;
--echo # Check DEFAULT() function
--echo #
CREATE TABLE `t1` (`a` int(11) DEFAULT 3+3,`b` int(11) DEFAULT '1000');
CREATE TABLE `t1` (`a` int(11) DEFAULT (3+3),`b` int(11) DEFAULT '1000');
insert into t1 values (1,1),(2,2);
insert into t1 values (default,default);
select * from t1;
@@ -919,12 +924,6 @@ INSERT INTO t1 VALUES (PI(), DEFAULT, DEFAULT);
SELECT * FROM t1;
DROP TABLE t1;
# QQ: this sets "b" to (-1), which looks wrong
#CREATE TABLE t1 (a VARCHAR(30), b DOUBLE DEFAULT MATCH (a) AGAINST('bbbb' IN BOOLEAN MODE));
#INSERT INTO t1 VALUES ('aaaa bbbb cccc dddd', DEFAULT);
#SELECT * FROM t1;
#DROP TABLE t1;
--echo #
--echo # INT result functions
--echo #
@@ -934,7 +933,7 @@ INSERT INTO t1 (a) VALUES (34);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a DIV b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a DIV b));
INSERT INTO t1 (a, b) VALUES (13, 3);
SELECT * FROM t1;
DROP TABLE t1;
@@ -994,6 +993,9 @@ CREATE TABLE t1 (a INT DEFAULT MASTER_POS_WAIT('test',100));
--error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a INT DEFAULT MASTER_GTID_WAIT('test'));
--error ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a VARCHAR(30), b DOUBLE DEFAULT MATCH (a) AGAINST('bbbb' IN BOOLEAN MODE));
--echo #
--echo # Temporal functions
--echo #
@@ -1283,8 +1285,8 @@ INSERT INTO t1 VALUES (1, 1, DEFAULT);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT -a);
CREATE TABLE t1 (a INT, b INT DEFAULT (-a));
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES (10, DEFAULT);
SELECT * FROM t1;
DROP TABLE t1;
@@ -1300,12 +1302,13 @@ INSERT INTO t1 VALUES (-1.5, DEFAULT, DEFAULT, DEFAULT);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a+b, d INT DEFAULT a-b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a+b), d INT DEFAULT (a-b));
INSERT INTO t1 VALUES (2, 1, DEFAULT, DEFAULT);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a*b, d INT DEFAULT a/b, e INT DEFAULT a MOD b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a*b), d INT DEFAULT (a/b), e INT DEFAULT (a MOD b));
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES (7, 3, DEFAULT, DEFAULT, DEFAULT);
SELECT * FROM t1;
DROP TABLE t1;
@@ -1362,8 +1365,9 @@ CREATE TABLE t1 (
a VARCHAR(10) CHARACTER SET latin1,
b VARCHAR(10) CHARACTER SET latin1 DEFAULT a COLLATE latin1_bin,
c VARCHAR(10) CHARACTER SET utf8 DEFAULT CONVERT(a USING utf8),
d VARBINARY(10) DEFAULT BINARY(a)
d VARBINARY(10) DEFAULT (BINARY(a))
);
SHOW CREATE TABLE t1;
INSERT INTO t1 (a) VALUES ('a');
SELECT * FROM t1;
DROP TABLE t1;
@@ -1377,23 +1381,24 @@ CREATE TABLE t1 (a INT, b INT DEFAULT BIT_COUNT(a));
INSERT INTO t1 (a) VALUES (7);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a|b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a|b));
INSERT INTO t1 (a,b) VALUES (1,2);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a&b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a&b));
INSERT INTO t1 (a,b) VALUES (5,4);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a^b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a^b));
INSERT INTO t1 (a,b) VALUES (11,3);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a&~b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a&~b));
INSERT INTO t1 (a,b) VALUES (5,1);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT a<<b, d INT DEFAULT a>>b);
CREATE TABLE t1 (a INT, b INT, c INT DEFAULT (a<<b), d INT DEFAULT (a>>b));
SHOW CREATE TABLE t1;
INSERT INTO t1 (a,b) VALUES (5,1);
SELECT * FROM t1;
DROP TABLE t1;
@@ -1543,71 +1548,73 @@ CREATE TABLE t1 (a VARCHAR(30), b BLOB DEFAULT LOAD_FILE(a));
--echo # Predicates
--echo #
CREATE TABLE t1 (a INT, b INT DEFAULT NOT a);
CREATE TABLE t1 (a INT, b INT DEFAULT (NOT a));
SHOW CREATE TABLE t1;
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, x INT DEFAULT a XOR b);
CREATE TABLE t1 (a INT, b INT, x INT DEFAULT (a XOR b));
INSERT INTO t1 (a,b) VALUES (0,0),(0,1),(1,0),(1,1);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT a IS TRUE, c INT DEFAULT a IS NOT TRUE);
CREATE TABLE t1 (a INT, b INT DEFAULT (a IS TRUE), c INT DEFAULT (a IS NOT TRUE));
SHOW CREATE TABLE t1;
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT a IS FALSE, c INT DEFAULT a IS NOT FALSE);
CREATE TABLE t1 (a INT, b INT DEFAULT (a IS FALSE), c INT DEFAULT (a IS NOT FALSE));
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT a IS NULL, c INT DEFAULT a IS NOT NULL);
CREATE TABLE t1 (a INT, b INT DEFAULT (a IS NULL), c INT DEFAULT (a IS NOT NULL));
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT DEFAULT a IS UNKNOWN, c INT DEFAULT a IS NOT UNKNOWN);
CREATE TABLE t1 (a INT, b INT DEFAULT (a IS UNKNOWN), c INT DEFAULT (a IS NOT UNKNOWN));
INSERT INTO t1 (a) VALUES (NULL),(0),(1);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT,
eq INT DEFAULT a=0, equal INT DEFAULT a<=>0,
ne INT DEFAULT a<>0,
lt INT DEFAULT a<0, le INT DEFAULT a<=0,
gt INT DEFAULT a>0, ge INT DEFAULT a>=0);
eq INT DEFAULT (a=0), equal INT DEFAULT (a<=>0),
ne INT DEFAULT (a<>0),
lt INT DEFAULT (a<0), le INT DEFAULT (a<=0),
gt INT DEFAULT (a>0), ge INT DEFAULT (a>=0));
INSERT INTO t1 (a) VALUES (NULL),(-1),(0),(1);
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a LIKE 'a%');
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a LIKE 'a%'));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb');
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a RLIKE 'a$');
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a RLIKE 'a$'));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb');
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a IN ('aaa','bbb'));
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a IN ('aaa','bbb')));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb'),('ccc');
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a NOT IN ('aaa','bbb'));
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a NOT IN ('aaa','bbb')));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb'),('ccc');
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a BETWEEN 'aaa' AND 'bbb');
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a BETWEEN 'aaa' AND 'bbb'));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb'),('ccc');
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT a NOT BETWEEN 'aaa' AND 'bbb');
CREATE TABLE t1 (a VARCHAR(10), b INT DEFAULT (a NOT BETWEEN 'aaa' AND 'bbb'));
INSERT INTO t1 (a) VALUES ('AAA'),('aaa'),('bbb'),('ccc');
SELECT * FROM t1;
DROP TABLE t1;
@@ -1716,3 +1723,12 @@ CREATE TABLE t1 (
INSERT INTO t1 (a) VALUES ('test');
SELECT c FROM t1;
DROP TABLE t1;
--echo #
--echo # Collations
--echo #
--error ER_BAD_DATA
CREATE TABLE t1 (a VARCHAR(20) CHARACTER SET latin1 DEFAULT CONCAT('<27>')) CHARACTER SET koi8r COLLATE koi8r_bin;
CREATE OR REPLACE TABLE t1 (a char(2) default concat('A') COLLATE utf8mb4_unicode_ci);
DROP TABLE t1;

View File

@@ -10575,6 +10575,7 @@ Column_definition::Column_definition(THD *thd, Field *old_field,
default_value->expr_str.length= res->length();
default_value->expr_item=
new (thd->mem_root) Item_string(thd, pos, res->length(), charset);
default_value->utf8= 0;
}
}
}

View File

@@ -395,6 +395,7 @@ enum Derivation
/* The length of the header part for each virtual column in the .frm file */
#define FRM_VCOL_OLD_HEADER_SIZE(b) (3 + MY_TEST(b))
#define FRM_VCOL_NEW_BASE_SIZE 16
#define FRM_VCOL_NEW_HEADER_SIZE 7
class Count_distinct_field;
@@ -571,6 +572,7 @@ public:
/* Flag indicating that the field is physically stored in the database */
bool stored_in_db;
bool non_deterministic;
bool utf8; /* Already in utf8 */
/* The expression to compute the value of the virtual column */
Item *expr_item;
/* Text representation of the defining expression */
@@ -580,7 +582,7 @@ public:
Virtual_column_info()
: field_type((enum enum_field_types)MYSQL_TYPE_VIRTUAL),
in_partitioning_expr(FALSE), stored_in_db(FALSE), non_deterministic(FALSE),
expr_item(NULL)
utf8(TRUE), expr_item(NULL)
{
expr_str.str= name.str= NULL;
name.length= 0;

View File

@@ -1649,7 +1649,7 @@ struct Table_scope_and_contents_source_st
ulong avg_row_length;
ulong used_fields;
ulong key_block_size;
ulong expression_lengths;
ulong expression_length;
ulong field_check_constraints;
/*
number of pages to sample during

View File

@@ -1377,6 +1377,8 @@ public:
virtual void set_result_field(Field *field) {}
virtual bool is_result_field() { return 0; }
virtual bool is_bool_type() { return false; }
/* This is to handle printing of default values */
virtual bool need_parentheses_in_default() { return false; }
virtual void save_in_result_field(bool no_conversions) {}
/*
set value of aggregate function in case of no rows for grouping were found

View File

@@ -197,6 +197,7 @@ public:
virtual CHARSET_INFO *compare_collation() const { return NULL; }
void fix_length_and_dec() { decimals=0; max_length=1; }
uint decimal_precision() const { return 1; }
bool need_parentheses_in_default() { return true; }
};
@@ -1488,6 +1489,7 @@ public:
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
void cleanup();
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);
bool need_parentheses_in_default() { return true; }
};
/*

View File

@@ -572,6 +572,7 @@ class Item_num_op :public Item_func_numhybrid
print_op(str, query_type);
}
void fix_length_and_dec();
bool need_parentheses_in_default() { return true; }
};
@@ -639,6 +640,7 @@ public:
}
virtual void print(String *str, enum_query_type query_type);
uint decimal_precision() const { return args[0]->decimal_precision(); }
bool need_parentheses_in_default() { return true; }
};
@@ -680,6 +682,7 @@ public:
void fix_length_and_dec() {}
const char *func_name() const { return "decimal_typecast"; }
virtual void print(String *str, enum_query_type query_type);
bool need_parentheses_in_default() { return true; }
};
@@ -697,6 +700,7 @@ public:
void fix_length_and_dec() { maybe_null= 1; }
const char *func_name() const { return "double_typecast"; }
virtual void print(String *str, enum_query_type query_type);
bool need_parentheses_in_default() { return true; }
};
@@ -780,6 +784,7 @@ public:
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
bool check_vcol_func_processor(uchar *arg) { return FALSE;}
bool need_parentheses_in_default() { return true; }
};
@@ -811,6 +816,7 @@ public:
uint decimal_precision() const { return args[0]->decimal_precision(); }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
bool check_vcol_func_processor(uchar *arg) { return FALSE;}
bool need_parentheses_in_default() { return true; }
};
@@ -1256,6 +1262,7 @@ public:
{
print_op(str, query_type);
}
bool need_parentheses_in_default() { return true; }
};
class Item_func_bit_or :public Item_func_bit

View File

@@ -2342,6 +2342,18 @@ void Item_func_decode::crypto_transform(String *res)
sql_crypt.decode((char*) res->ptr(),res->length());
}
Item *Item_func_sysconst::safe_charset_converter(THD *thd,
CHARSET_INFO *tocs)
{
/*
In default, virtual functions or constraint expressions, the value
of a sysconst is not constant
*/
if (thd->in_stored_expression)
return Item_str_func::safe_charset_converter(thd, tocs);
return const_charset_converter(thd, tocs, true, fully_qualified_func_name());
}
String *Item_func_database::val_str(String *str)
{
@@ -2366,11 +2378,14 @@ String *Item_func_database::val_str(String *str)
bool Item_func_user::init(THD *thd, const char *user, const char *host)
{
DBUG_ENTER("Item_func_user::init");
DBUG_ASSERT(fixed == 1);
/* Check if we have already calculated the value for this thread */
if (thd->query_id == last_query_id)
return FALSE;
DBUG_RETURN(FALSE);
DBUG_PRINT("enter", ("user: '%s' host: '%s'", user,host));
last_query_id= thd->query_id;
null_value= 0;
@@ -2380,28 +2395,29 @@ bool Item_func_user::init(THD *thd, const char *user, const char *host)
CHARSET_INFO *cs= system_charset_info;
size_t res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
if (str_value.alloc((uint) res_length))
if (cached_value.alloc((uint) res_length))
{
null_value=1;
return TRUE;
DBUG_RETURN(TRUE);
}
str_value.set_charset(cs);
res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), (uint) res_length,
cached_value.set_charset(cs);
res_length=cs->cset->snprintf(cs, (char*)cached_value.ptr(),
(uint) res_length,
"%s@%s", user, host);
str_value.length((uint) res_length);
str_value.mark_as_const();
cached_value.length((uint) res_length);
cached_value.mark_as_const();
}
else
str_value.set("", 0, system_charset_info);
return FALSE;
cached_value.set("", 0, system_charset_info);
DBUG_RETURN(FALSE);
}
String *Item_func_user::val_str(String *str)
{
THD *thd= current_thd;
init(thd, thd->main_security_ctx.user, thd->main_security_ctx.host_or_ip);
return null_value ? 0 : &str_value;
return null_value ? 0 : &cached_value;
}
String *Item_func_current_user::val_str(String *str)
@@ -2410,7 +2426,7 @@ String *Item_func_current_user::val_str(String *str)
Security_context *ctx= (context->security_ctx ?
context->security_ctx : thd->security_ctx);
init(thd, ctx->priv_user, ctx->priv_host);
return null_value ? 0 : &str_value;
return null_value ? 0 : &cached_value;
}

View File

@@ -562,10 +562,7 @@ class Item_func_sysconst :public Item_str_func
public:
Item_func_sysconst(THD *thd): Item_str_func(thd)
{ collation.set(system_charset_info,DERIVATION_SYSCONST); }
Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
{
return const_charset_converter(thd, tocs, true, fully_qualified_func_name());
}
Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
/*
Used to create correct Item name in new converted item in
safe_charset_converter, return string representation of this function
@@ -599,6 +596,7 @@ class Item_func_user :public Item_func_sysconst
{
protected:
query_id_t last_query_id;
String cached_value;
bool init(THD *thd, const char *user, const char *host);
public:
@@ -906,6 +904,7 @@ public:
}
virtual void print(String *str, enum_query_type query_type);
const char *func_name() const { return "cast_as_binary"; }
bool need_parentheses_in_default() { return true; }
};
@@ -1058,6 +1057,7 @@ public:
/* this function is transparent for view updating */
return args[0]->field_for_view_update();
}
bool need_parentheses_in_default() { return true; }
};

View File

@@ -854,6 +854,7 @@ public:
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
bool eq(const Item *item, bool binary_cmp) const;
void print(String *str, enum_query_type query_type);
bool need_parentheses_in_default() { return true; }
};
@@ -931,6 +932,7 @@ public:
String *val_str(String *a);
void fix_length_and_dec();
void print(String *str, enum_query_type query_type);
bool need_parentheses_in_default() { return true; }
};

View File

@@ -870,7 +870,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
is_fatal_sub_stmt_error(false),
rand_used(0),
time_zone_used(0),
in_lock_tables(0),
in_lock_tables(0), in_stored_expression(0),
bootstrap(0),
derived_tables_processing(FALSE),
waiting_on_group_commit(FALSE), has_waiter(FALSE),
@@ -1417,7 +1417,7 @@ void THD::init(void)
TL_WRITE);
tx_isolation= (enum_tx_isolation) variables.tx_isolation;
tx_read_only= variables.tx_read_only;
update_charset();
update_charset(); // plugin_thd_var() changed character sets
reset_current_stmt_binlog_format_row();
reset_binlog_local_stmt_filter();
set_status_var_init();
@@ -2311,12 +2311,19 @@ bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
{
DBUG_ENTER("THD::convert_string");
size_t new_length= to_cs->mbmaxlen * from_length;
uint dummy_errors;
uint errors;
if (alloc_lex_string(to, new_length + 1))
DBUG_RETURN(true); // EOM
to->length= copy_and_convert((char*) to->str, new_length, to_cs,
from, from_length, from_cs, &dummy_errors);
from, from_length, from_cs, &errors);
to->str[to->length]= 0; // Safety
if (errors && in_stored_expression)
{
my_error(ER_BAD_DATA, MYF(0),
ErrConvString(from, from_length, from_cs).ptr(),
to_cs->csname);
DBUG_RETURN(true);
}
DBUG_RETURN(false);
}

View File

@@ -2840,7 +2840,7 @@ public:
bool query_start_sec_part_used;
/* for IS NULL => = last_insert_id() fix in remove_eq_conds() */
bool substitute_null_with_insert_id;
bool in_lock_tables;
bool in_lock_tables, in_stored_expression;
bool bootstrap, cleanup_done, free_connection_done;
/** is set if some thread specific value(s) used in a statement. */

View File

@@ -1286,7 +1286,7 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
{
const char *cpp_tok_start, *m_tok_end, *tok_start;
/*
To be able to handle "DEFAULT 1 NOT NULL" which classes with
To be able to handle "DEFAULT 1 NOT NULL" which clashes with
"DEFAULT 1 NOT IN (..)" we must combine NOT NULL to one lex token
NOT_NULL_SYM. We also have to ensure that NOT NULL IS are still
separate tokens to ensure that NOT NULL IS TRUE is evaluated as

View File

@@ -2077,12 +2077,6 @@ public:
return m_tok_start;
}
/** Get the token start position, in the pre-processed buffer. */
const char *get_cpp_tok_start()
{
return m_cpp_tok_start;
}
void set_cpp_tok_start(const char *pos)
{
m_cpp_tok_start= pos;
@@ -2094,12 +2088,6 @@ public:
return m_tok_end;
}
/** Get the token end position, in the pre-processed buffer. */
const char *get_cpp_tok_end()
{
return m_cpp_tok_end;
}
/** Get the previous token start position, in the raw buffer. */
const char *get_tok_start_prev()
{
@@ -2112,12 +2100,6 @@ public:
return m_ptr;
}
/** Get the current stream pointer, in the pre-processed buffer. */
const char *get_cpp_ptr()
{
return m_cpp_ptr;
}
/** Get the length of the current token, in the raw buffer. */
uint yyLength()
{
@@ -2129,6 +2111,30 @@ public:
return (uint) ((m_ptr - m_tok_start) - 1);
}
/** Get the previus token start position, in the pre-processed buffer. */
const char *get_cpp_start_prev()
{
return m_cpp_tok_start_prev;
}
/** Get the token start position, in the pre-processed buffer. */
const char *get_cpp_tok_start()
{
return m_cpp_tok_start;
}
/** Get the token end position, in the pre-processed buffer. */
const char *get_cpp_tok_end()
{
return m_cpp_tok_end;
}
/** Get the current stream pointer, in the pre-processed buffer. */
const char *get_cpp_ptr()
{
return m_cpp_ptr;
}
/** Get the utf8-body string. */
const char *get_body_utf8_str()
{

View File

@@ -1636,9 +1636,18 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value,
{
if (field->default_value)
{
def_value->set(field->default_value->expr_str.str,
field->default_value->expr_str.length,
system_charset_info);
if (field->default_value->expr_item->need_parentheses_in_default())
{
def_value->set_charset(&my_charset_utf8mb4_general_ci);
def_value->append('(');
def_value->append(field->default_value->expr_str.str,
field->default_value->expr_str.length);
def_value->append(')');
}
else
def_value->set(field->default_value->expr_str.str,
field->default_value->expr_str.length,
&my_charset_utf8mb4_general_ci);
}
else if (has_now_default)
{
@@ -1892,7 +1901,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" AS ("));
packet->append(field->vcol_info->expr_str.str,
field->vcol_info->expr_str.length,
system_charset_info);
&my_charset_utf8mb4_general_ci);
packet->append(STRING_WITH_LEN(")"));
if (field->vcol_info->stored_in_db)
packet->append(STRING_WITH_LEN(" PERSISTENT"));
@@ -1933,7 +1942,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
{
packet->append(STRING_WITH_LEN(" CHECK ("));
packet->append(field->check_constraint->expr_str.str,
field->check_constraint->expr_str.length);
field->check_constraint->expr_str.length,
&my_charset_utf8mb4_general_ci);
packet->append(STRING_WITH_LEN(")"));
}
@@ -2041,7 +2051,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
}
packet->append(STRING_WITH_LEN(" CHECK ("));
packet->append(check->expr_str.str,
check->expr_str.length);
check->expr_str.length,
&my_charset_utf8mb4_general_ci);
packet->append(STRING_WITH_LEN(")"));
}
}

View File

@@ -936,7 +936,7 @@ bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
MYSQL_YYABORT; \
} while(0)
Virtual_column_info *add_virtual_expression(THD *thd, char *txt,
Virtual_column_info *add_virtual_expression(THD *thd, const char *txt,
size_t size, Item *expr)
{
CHARSET_INFO *cs= thd->charset();
@@ -958,6 +958,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, char *txt,
v->expr_str.str= (char* ) thd->strmake(txt, size);
v->expr_str.length= size;
v->expr_item= expr;
v->utf8= 0; /* connection charset */
return v;
}
@@ -1854,9 +1855,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
simple_ident expr opt_expr opt_else sum_expr in_sum_expr
variable variable_aux bool_pri
predicate bit_expr
table_wild simple_expr udf_expr
table_wild simple_expr column_default_non_parenthesized_expr udf_expr
expr_or_default set_expr_or_default
geometry_function
geometry_function signed_literal
opt_escape
sp_opt_default
simple_ident_nospvar simple_ident_q
@@ -1957,6 +1958,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <myvar> select_outvar
%type <virtual_column> opt_check_constraint check_constraint virtual_column_func
column_default_expr
%type <NONE>
analyze_stmt_command
@@ -2021,7 +2023,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
definer_opt no_definer definer get_diagnostics
parse_vcol_expr vcol_opt_specifier vcol_opt_attribute
vcol_opt_attribute_list vcol_attribute
explainable_command
explainable_command opt_impossible_action
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -6420,6 +6422,26 @@ virtual_column_func:
}
;
column_default_expr:
'(' virtual_column_func ')' { $$= $2; }
| remember_name column_default_non_parenthesized_expr opt_impossible_action remember_end
{
if (!($$= add_virtual_expression(thd, $1, (uint) ($4- $1), $2)))
MYSQL_YYABORT;
}
| signed_literal
{
if (!($$= add_virtual_expression(thd, "literal", 6, $1)))
MYSQL_YYABORT;
}
;
/* This is to force remember_end to look at next token */
opt_impossible_action:
IMPOSSIBLE_ACTION {}
| /* empty */ {}
field_type:
int_type opt_field_length field_options { $$.set($1, $2); }
| real_type opt_precision field_options { $$.set($1, $2); }
@@ -6713,7 +6735,7 @@ opt_attribute_list:
attribute:
NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; }
| NOT_NULL_SYM { Lex->last_field->flags|= NOT_NULL_FLAG; }
| DEFAULT virtual_column_func { Lex->last_field->default_value= $2; }
| DEFAULT column_default_expr { Lex->last_field->default_value= $2; }
| ON UPDATE_SYM NOW_SYM opt_default_time_precision
{
Item *item= new (thd->mem_root) Item_func_now_local(thd, $4);
@@ -9490,34 +9512,17 @@ dyncall_create_list:
}
;
simple_expr:
column_default_non_parenthesized_expr:
simple_ident
| function_call_keyword
| function_call_nonkeyword
| function_call_generic
| function_call_conflict
| simple_expr COLLATE_SYM ident_or_text %prec NEG
{
Item *i1= new (thd->mem_root) Item_string(thd, $3.str,
$3.length,
thd->charset());
if (i1 == NULL)
MYSQL_YYABORT;
$$= new (thd->mem_root) Item_func_set_collation(thd, $1, i1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| literal
| param_marker { $$= $1; }
| variable
| sum_expr
| window_func_expr
| simple_expr OR_OR_SYM simple_expr
{
$$= new (thd->mem_root) Item_func_concat(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| NOT_NULL_SYM
{
/* Replace NOT NULL with NULL */
@@ -9525,43 +9530,6 @@ simple_expr:
if ($$ == NULL)
MYSQL_YYABORT;
}
| '+' simple_expr %prec NEG
{
$$= $2;
}
| '-' simple_expr %prec NEG
{
$$= $2->neg(thd);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '~' simple_expr %prec NEG
{
$$= new (thd->mem_root) Item_func_bit_neg(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| not2 simple_expr %prec NEG
{
$$= negate_expression(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '(' subselect ')'
{
$$= new (thd->mem_root) Item_singlerow_subselect(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '(' expr ')'
{ $$= $2; }
| '(' expr ',' expr_list ')'
{
$4->push_front($2, thd->mem_root);
$$= new (thd->mem_root) Item_row(thd, *$4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ROW_SYM '(' expr ',' expr_list ')'
{
$5->push_front($3, thd->mem_root);
@@ -9609,13 +9577,6 @@ simple_expr:
Select->add_ftfunc_to_list(thd, i1);
$$= i1;
}
| BINARY simple_expr %prec NEG
{
$$= create_func_cast(thd, $2, ITEM_CAST_CHAR, NULL, NULL,
&my_charset_bin);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CAST_SYM '(' expr AS cast_type ')'
{
LEX *lex= Lex;
@@ -9664,6 +9625,71 @@ simple_expr:
if ($$ == NULL)
MYSQL_YYABORT;
}
;
simple_expr:
column_default_non_parenthesized_expr
| simple_expr COLLATE_SYM ident_or_text %prec NEG
{
Item *i1= new (thd->mem_root) Item_string(thd, $3.str,
$3.length,
thd->charset());
if (i1 == NULL)
MYSQL_YYABORT;
$$= new (thd->mem_root) Item_func_set_collation(thd, $1, i1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '(' subselect ')'
{
$$= new (thd->mem_root) Item_singlerow_subselect(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '(' expr ')'
{ $$= $2; }
| '(' expr ',' expr_list ')'
{
$4->push_front($2, thd->mem_root);
$$= new (thd->mem_root) Item_row(thd, *$4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BINARY simple_expr %prec NEG
{
$$= create_func_cast(thd, $2, ITEM_CAST_CHAR, NULL, NULL,
&my_charset_bin);
if ($$ == NULL)
MYSQL_YYABORT;
}
| simple_expr OR_OR_SYM simple_expr
{
$$= new (thd->mem_root) Item_func_concat(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '+' simple_expr %prec NEG
{
$$= $2;
}
| '-' simple_expr %prec NEG
{
$$= $2->neg(thd);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '~' simple_expr %prec NEG
{
$$= new (thd->mem_root) Item_func_bit_neg(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| not2 simple_expr %prec NEG
{
$$= negate_expression(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| INTERVAL_SYM expr interval '+' expr %prec INTERVAL_SYM
/* we cannot put interval before - */
{
@@ -14035,6 +14061,15 @@ param_marker:
}
;
signed_literal:
'+' NUM_literal { $$ = $2; }
| '-' NUM_literal
{
$2->max_length++;
$$= $2->neg(thd);
}
;
literal:
text_literal { $$ = $1; }
| NUM_literal { $$ = $1; }

View File

@@ -1653,6 +1653,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
vcol_info_length)))
goto err;
vcol_info->expr_str.length= vcol_info_length;
vcol_info->utf8= 0;
vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;;
share->virtual_fields++;
vcol_info_length= 0;
@@ -1692,6 +1693,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (opt_interval_id)
interval_nr= (uint) vcol_screen_pos[3];
vcol_info->expr_str.length= vcol_expr_length;
vcol_info->utf8= 0;
vcol_screen_pos+= vcol_info_length;
share->virtual_fields++;
}
@@ -2158,12 +2160,16 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
/* Handle virtual expressions */
if (vcol_screen_length && share->frm_version >= FRM_VER_EXPRESSSIONS)
{
uchar *vcol_screen_end= vcol_screen_pos + vcol_screen_length;
/* Skip header */
vcol_screen_pos+= FRM_VCOL_NEW_BASE_SIZE;
/*
Read virtual columns, default values and check constraints
See pack_expression() for how data is stored
*/
for (uchar *vcol_screen_end= vcol_screen_pos + vcol_screen_length ;
vcol_screen_pos < vcol_screen_end ; )
while (vcol_screen_pos < vcol_screen_end)
{
Virtual_column_info *vcol_info;
uint field_nr= uint2korr(vcol_screen_pos);
@@ -2193,8 +2199,11 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
vcol_info->name= name;
/* The following can only be true for check_constraints */
if (field_nr != UINT_MAX32)
if (field_nr != UINT_MAX16)
{
DBUG_ASSERT(field_nr < share->fields);
reg_field= share->field[field_nr];
}
vcol_info->expr_str.str= expr;
vcol_info->expr_str.length= expr_length;
@@ -2554,8 +2563,11 @@ static bool fix_vcol_expr(THD *thd,
thd->where= "virtual column function";
/* Fix fields referenced to by the virtual column function */
thd->in_stored_expression= 1;
if (!func_expr->fixed)
error= func_expr->fix_fields(thd, &vcol->expr_item);
thd->in_stored_expression= 0;
if (unlikely(error))
{
DBUG_PRINT("info",
@@ -2659,7 +2671,7 @@ Virtual_column_info *unpack_vcol_info_from_frm(THD *thd,
{
char *vcol_expr_str;
int str_len;
CHARSET_INFO *old_character_set_client;
CHARSET_INFO *save_character_set_client, *save_collation;
Query_arena *backup_stmt_arena_ptr;
Query_arena backup_arena;
Query_arena *vcol_arena= 0;
@@ -2669,10 +2681,12 @@ Virtual_column_info *unpack_vcol_info_from_frm(THD *thd,
LEX_STRING *vcol_expr= &vcol->expr_str;
LEX *old_lex= thd->lex;
LEX lex;
bool error;
DBUG_ENTER("unpack_vcol_info_from_frm");
DBUG_ASSERT(vcol_expr);
old_character_set_client= thd->variables.character_set_client;
save_character_set_client= thd->variables.character_set_client;
save_collation= thd->variables.collation_connection;
backup_stmt_arena_ptr= thd->stmt_arena;
/*
@@ -2730,10 +2744,17 @@ Virtual_column_info *unpack_vcol_info_from_frm(THD *thd,
/*
Step 3: Use the parser to build an Item object from vcol_expr_str.
*/
if (parse_sql(thd, &parser_state, NULL))
if (vcol->utf8)
{
goto err;
thd->update_charset(&my_charset_utf8mb4_general_ci,
table->s->table_charset);
}
thd->in_stored_expression= 1;
error= parse_sql(thd, &parser_state, NULL);
thd->in_stored_expression= 0;
if (error)
goto err;
/*
mark if expression will be stored in the table. This is also used by
fix_vcol_expr() to mark if we are using non deterministic functions.
@@ -2741,6 +2762,7 @@ Virtual_column_info *unpack_vcol_info_from_frm(THD *thd,
vcol_storage.vcol_info->stored_in_db= vcol->stored_in_db;
vcol_storage.vcol_info->non_deterministic= vcol->non_deterministic;
vcol_storage.vcol_info->name= vcol->name;
vcol_storage.vcol_info->utf8= vcol->utf8;
/* Validate the Item tree. */
if (!fix_vcol_expr(thd, table, field, vcol_storage.vcol_info))
{
@@ -2756,7 +2778,8 @@ end:
if (vcol_arena)
thd->restore_active_arena(vcol_arena, &backup_arena);
end_lex_with_single_table(thd, table, old_lex);
thd->variables.character_set_client= old_character_set_client;
if (vcol->utf8)
thd->update_charset(save_character_set_client, save_collation);
DBUG_RETURN(vcol_info);
}
@@ -3612,7 +3635,7 @@ void prepare_frm_header(THD *thd, uint reclength, uchar *fileinfo,
/* header */
fileinfo[0]=(uchar) 254;
fileinfo[1]= 1;
fileinfo[2]= (create_info->expression_lengths == 0 ? FRM_VER_TRUE_VARCHAR :
fileinfo[2]= (create_info->expression_length == 0 ? FRM_VER_TRUE_VARCHAR :
FRM_VER_EXPRESSSIONS);
DBUG_ASSERT(ha_storage_engine_is_enabled(create_info->db_type));

View File

@@ -42,10 +42,12 @@
static uint pack_keys(uchar *,uint, KEY *, ulong);
static bool pack_header(THD *, uchar *, List<Create_field> &, HA_CREATE_INFO *info, ulong, handler *);
static uint get_interval_id(uint *,List<Create_field> &, Create_field *);
static bool pack_fields(uchar **, List<Create_field> &, ulong);
static bool pack_fields(uchar **, List<Create_field> &, HA_CREATE_INFO*,
ulong);
static void pack_constraints(uchar **buff, List<Virtual_column_info> *constr);
static size_t packed_fields_length(List<Create_field> &);
static size_t packed_constraints_length(List<Virtual_column_info> *constr);
static size_t packed_constraints_length(THD *thd, HA_CREATE_INFO* info,
List<Virtual_column_info> *constr);
static bool make_empty_rec(THD *, uchar *, uint, List<Create_field> &, uint, ulong);
/*
@@ -108,7 +110,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
LEX_STRING str_db_type;
uint reclength, key_info_length, i;
ulong key_buff_length;
ulong filepos, data_offset, expr_length;
ulong filepos, data_offset;
uint options_len;
uint gis_extra2_len= 0;
uchar fileinfo[FRM_HEADER_SIZE],forminfo[FRM_FORMINFO_SIZE];
@@ -130,12 +132,6 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
DBUG_RETURN(frm);
reclength= uint2korr(forminfo+266);
expr_length= packed_constraints_length(create_info->constraint_list);
/* Correct expression length stored by pack_header */
expr_length+= uint2korr(forminfo+286);
int2store(forminfo+286, expr_length);
create_info->expression_lengths= expr_length;
/* Calculate extra data segment length */
str_db_type= *hton_name(create_info->db_type);
@@ -227,9 +223,10 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
filepos= frm.length;
frm.length+= FRM_FORMINFO_SIZE; // forminfo
frm.length+= packed_fields_length(create_fields);
frm.length+= expr_length;
frm.length+= create_info->expression_length;
if (frm.length > FRM_MAX_SIZE || expr_length > UINT_MAX32)
if (frm.length > FRM_MAX_SIZE ||
create_info->expression_length > UINT_MAX32)
{
my_error(ER_TABLE_DEFINITION_TOO_BIG, MYF(0), table);
DBUG_RETURN(frm);
@@ -336,9 +333,8 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
memcpy(frm_ptr + filepos, forminfo, 288);
pos= frm_ptr + filepos + 288;
if (pack_fields(&pos, create_fields, data_offset))
if (pack_fields(&pos, create_fields, create_info, data_offset))
goto err;
pack_constraints(&pos, create_info->constraint_list);
{
/*
@@ -502,23 +498,57 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
/**
Calculate and check length of stored expression (virtual, def, check)
Convert string to utf8, if it isn't already
@param thd Thread handler. Used for memory allocation
@param v_col Virtual expression. Can be 0
@param CREATE INFO For characterset
@param length Sum total lengths here
Note to make calls easier, one can call this with v_col == 0
@return 0 ok
@return 1 error (out of memory or wrong characters in expression)
*/
static void add_expr_length(Virtual_column_info *v_col, size_t *length)
static bool add_expr_length(THD *thd, Virtual_column_info **v_col_ptr,
HA_CREATE_INFO *info,
size_t *length)
{
Virtual_column_info *v_col= *v_col_ptr;
if (!v_col)
return;
return 0;
/*
Convert string to utf8 for storage.
*/
if (!v_col->utf8)
{
/*
We have to create a new Virtual_column_info as for alter table,
the current one may be shared with the original tables
*/
Virtual_column_info *new_vcol= new (thd->mem_root) Virtual_column_info();
LEX_STRING to;
if (thd->copy_with_error(&my_charset_utf8mb4_general_ci,
&to,
thd->variables.character_set_client,
v_col->expr_str.str, v_col->expr_str.length))
return 1;
*new_vcol= *v_col;
new_vcol->expr_str= to;
new_vcol->utf8= 1;
*v_col_ptr= new_vcol;
v_col= new_vcol;
}
/*
Sum up the length of the expression string, it's optional name
and the header.
*/
(*length)+= (FRM_VCOL_NEW_HEADER_SIZE + v_col->name.length +
v_col->expr_str.length);
return;
return 0;
}
@@ -577,10 +607,15 @@ static bool pack_header(THD *thd, uchar *forminfo,
totlength= 0L;
reclength= data_offset;
no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=0;
com_length=expression_length=0;
com_length= 0;
n_length=2L;
create_info->field_check_constraints= 0;
expression_length= packed_constraints_length(thd, create_info,
create_info->constraint_list);
if (!expression_length && create_info->constraint_list->elements)
DBUG_RETURN(1); // Wrong characterset
/* Check fields */
List_iterator<Create_field> it(create_fields);
Create_field *field;
@@ -590,10 +625,16 @@ static bool pack_header(THD *thd, uchar *forminfo,
ER_TOO_LONG_FIELD_COMMENT, field->field_name))
DBUG_RETURN(1);
add_expr_length(field->vcol_info, &expression_length);
if (add_expr_length(thd, &field->vcol_info, create_info,
&expression_length))
DBUG_RETURN(1);
if (field->has_default_expression())
add_expr_length(field->default_value, &expression_length);
add_expr_length(field->check_constraint, &expression_length);
if (add_expr_length(thd, &field->default_value, create_info,
&expression_length))
DBUG_RETURN(1);
if (add_expr_length(thd, &field->check_constraint, create_info,
&expression_length))
DBUG_RETURN(1);
totlength+= field->length;
com_length+= field->comment.length;
@@ -677,6 +718,13 @@ static bool pack_header(THD *thd, uchar *forminfo,
my_error(ER_TOO_BIG_ROWSIZE, MYF(0), static_cast<long>(file->max_record_length()));
DBUG_RETURN(1);
}
if (expression_length)
{
expression_length+= FRM_VCOL_NEW_BASE_SIZE;
create_info->expression_length= expression_length;
}
/* Hack to avoid bugs with small static rows in MySQL */
reclength=MY_MAX(file->min_record_length(table_options),reclength);
if ((ulong) create_fields.elements*FCOMP+FRM_FORMINFO_SIZE+
@@ -760,10 +808,6 @@ static size_t packed_fields_length(List<Create_field> &create_fields)
length++;
}
add_expr_length(field->vcol_info, &length);
if (field->has_default_expression())
add_expr_length(field->default_value, &length);
add_expr_length(field->check_constraint, &length);
length+= FCOMP;
length+= strlen(field->field_name)+1;
length+= field->comment.length;
@@ -773,13 +817,16 @@ static size_t packed_fields_length(List<Create_field> &create_fields)
}
static size_t packed_constraints_length(List<Virtual_column_info> *constr)
static size_t packed_constraints_length(THD *thd, HA_CREATE_INFO *info,
List<Virtual_column_info> *constr)
{
List_iterator<Virtual_column_info> it(*constr);
size_t length= 0;
Virtual_column_info *check;
while ((check= it++))
add_expr_length(check, &length);
if (add_expr_length(thd, it.ref(), info, &length))
return 0;
return length;
}
@@ -795,11 +842,11 @@ static void pack_constraints(uchar **buff, List<Virtual_column_info> *constr)
/* Save fields, fieldnames and intervals */
static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
HA_CREATE_INFO *create_info,
ulong data_offset)
{
uchar *buff= *buff_arg;
uint int_count, comment_length= 0;
bool has_expressions= 0;
Create_field *field;
DBUG_ENTER("pack_fields");
@@ -835,9 +882,6 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
{
buff[11]= buff[14]= 0; // Numerical
}
if (field->vcol_info || field->has_default_expression() ||
field->check_constraint)
has_expressions= 1;
int2store(buff+15, field->comment.length);
comment_length+= field->comment.length;
@@ -922,8 +966,12 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
}
}
if (has_expressions)
if (create_info->expression_length)
{
/* Store header for packed fields (extra space for future) */
bzero(buff, FRM_VCOL_NEW_BASE_SIZE);
buff+= FRM_VCOL_NEW_BASE_SIZE;
/* Store expressions */
it.rewind();
for (uint field_nr=0 ; (field= it++) ; field_nr++)
@@ -936,6 +984,7 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
if (field->check_constraint)
pack_expression(&buff, field->check_constraint, field_nr, 3);
}
pack_constraints(&buff, create_info->constraint_list);
}
*buff_arg= buff;
DBUG_RETURN(0);