MDEV-16365 Setting a column NOT NULL fails to return error for

		NULL values when there is no DEFAULT

Copy and inplace algorithm works similarly for
NULL to NOT NULL conversion for the following cases:
(1) strict sql mode - Should give error.
(2) non-strict sql mode - Should give warnings alone
(3) alter ignore table command. - Should give warnings alone.
parent 1abd877e
......@@ -1150,6 +1150,7 @@ alter table t1 change column a a int;
analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t1 analyze status OK
flush table t1;
explain extended select * from t1 where a between 5 and 7;
......
......@@ -1086,6 +1086,9 @@ test t2 idx4 3 1.1304
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS() INDEXES ALL;
Table Op Msg_type Msg_text
test.t2 analyze status Engine-independent statistics collected
test.t2 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t2 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t2 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t2 analyze status OK
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
......@@ -1146,6 +1149,11 @@ test t2 idx4 4 1.0000
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL;
Table Op Msg_type Msg_text
test.t2 analyze status Engine-independent statistics collected
test.t2 analyze Note Data truncated for column 'avg_length' at row 1
test.t2 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t2 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t2 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t2 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t2 analyze status OK
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
......@@ -1171,6 +1179,8 @@ test t2 idx3 1 8.5000
ANALYZE TABLE t2 PERSISTENT FOR COLUMNS() INDEXES ALL;
Table Op Msg_type Msg_text
test.t2 analyze status Engine-independent statistics collected
test.t2 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t2 analyze Note Data truncated for column 'avg_frequency' at row 1
test.t2 analyze status OK
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
......
......@@ -691,9 +691,13 @@ a b c
1 127 0
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
ALTER TABLE t ADD UNIQUE INDEX (c(1));
Warnings:
Warning 1264 Out of range value for column 'b' at row 1
SELECT * FROM t WHERE c = '0';
a b c
1 127 0
Warnings:
Warning 1264 Out of range value for column 'b' at row 1
DROP TABLE t;
#
# Bug#21688115 VIRTUAL COLUMN COMPUTATION SAVE_IN_FIELD()
......
--source include/have_innodb.inc
CREATE TABLE t1(f1 INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
--enable_info
--error $error_code
ALTER TABLE t1 CHANGE f1 f1 INT NOT NULL;
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 CHAR(10))ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
--enable_info
--error $error_code
ALTER TABLE t1 CHANGE f1 f1 CHAR(10) NOT NULL;
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 VARCHAR(10))ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
--enable_info
--error $error_code
ALTER TABLE t1 CHANGE f1 f1 VARCHAR(20) NOT NULL;
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 TEXT)ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
--enable_info
--error $error_code
ALTER TABLE t1 CHANGE f1 f1 TEXT NOT NULL DEFAULT 'abc';
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, f3 INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(2, 2, NULL);
SELECT * FROM t1;
--enable_info
--error $error_code
ALTER TABLE t1 CHANGE f3 f3 INT NOT NULL DEFAULT (f1 + f2);
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL DEFAULT 0, b TINYINT)ENGINE=InnoDB;
INSERT INTO t1 VALUES(10, NULL);
SELECT * FROM t1;
--enable_info
--error $error_code
ALTER TABLE t1 CHANGE b b TINYINT NOT NULL DEFAULT if(unix_timestamp()>1,1000,0);
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
# Alter ignore should work irrespective of sql mode
CREATE TABLE t1(c1 INT NOT NULL, c2 INT, PRIMARY KEY(c1))ENGINE=INNODB;
INSERT INTO t1 VALUES(1, NULL);
--enable_info
ALTER IGNORE TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2;
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
......@@ -2,66 +2,61 @@
--source include/have_debug.inc
--source include/have_debug_sync.inc
# Alter table should fail for strict sql mode
CREATE TABLE t1(c1 INT NOT NULL, c2 INT, PRIMARY KEY(c1))ENGINE=INNODB;
INSERT INTO t1 VALUES(1, NULL);
INSERT INTO t1 VALUES(1, 1);
--enable_info
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
send ALTER TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2, ALGORITHM=INPLACE;
send ALTER TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2;
connect (con1,localhost,root);
SET DEBUG_SYNC= 'now WAIT_FOR opened';
INSERT INTO t1 VALUES(2, NULL);
UPDATE t1 SET c1 = 3 WHERE c2 = 1;
SET DEBUG_SYNC= 'now SIGNAL flushed';
connection default;
--error ER_INVALID_USE_OF_NULL
--error $error_code
reap;
--disable_info
SELECT * FROM t1;
UPDATE t1 SET c2 = 0 WHERE c1 = 2;
DROP TABLE t1;
# Alter table should successfully apply the log for the alter operation
CREATE TABLE t1(c1 INT NOT NULL, c2 INT, PRIMARY KEY(c1))ENGINE=INNODB;
INSERT INTO t1 VALUES(1, 1);
--enable_info
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
--echo # Alter ignore can convert the NULL values from
--echo # CONCURRENT DML to constants
send ALTER IGNORE TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2, ALGORITHM=INPLACE;
send ALTER TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2;
connection con1;
SET DEBUG_SYNC= 'now WAIT_FOR opened';
UPDATE t1 SET c2 = NULL WHERE c1 = 2;
INSERT INTO t1 VALUES (3, NULL);
INSERT INTO t1 VALUES(2, 3);
UPDATE t1 SET c1 = 3 WHERE c2 = 1;
SET DEBUG_SYNC= 'now SIGNAL flushed';
connection default;
reap;
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
# Alter ignore should not give error
CREATE TABLE t1(c1 INT NOT NULL, c2 INT, c3 INT, PRIMARY KEY(c1))ENGINE=INNODB;
INSERT INTO t1 VALUES(1, NULL, NULL);
INSERT INTO t1 VALUES(1, 2, 3);
--enable_info
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
--echo # Alter Successfully converts from null to not null
send ALTER TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2, ALGORITHM=INPLACE;
send ALTER IGNORE TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2;
connection con1;
SET DEBUG_SYNC= 'now WAIT_FOR opened';
UPDATE t1 SET c2= 2 WHERE c1 = 1;
INSERT INTO t1 VALUES (2, 3, 4);
SET DEBUG_SYNC= 'now SIGNAL flushed';
connection default;
reap;
SELECT * FROM t1;
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
--echo # Alter fails because concurrent dml inserts null value
send ALTER TABLE t1 CHANGE c3 c3 INT NOT NULL DEFAULT 2, ALGORITHM=INPLACE;
connection con1;
SET DEBUG_SYNC= 'now WAIT_FOR opened';
UPDATE t1 SET c3= 2 WHERE c1 = 2;
INSERT INTO t1 VALUES (4, 3, NULL);
INSERT INTO t1 VALUES (2, NULL, 4);
SET DEBUG_SYNC= 'now SIGNAL flushed';
connection default;
--error ER_INVALID_USE_OF_NULL
reap;
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
disconnect con1;
......
7,8c7,8
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
---
> affected rows: 1
> info: Records: 1 Duplicates: 0 Warnings: 1
21,22c21,22
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
---
> affected rows: 1
> info: Records: 1 Duplicates: 0 Warnings: 1
35,36c35,36
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
---
> affected rows: 1
> info: Records: 1 Duplicates: 0 Warnings: 1
49,50c49,50
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
---
> affected rows: 1
> info: Records: 1 Duplicates: 0 Warnings: 1
63,64c63,64
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
---
> affected rows: 1
> info: Records: 1 Duplicates: 0 Warnings: 1
77,78c77,78
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
---
> affected rows: 1
> info: Records: 1 Duplicates: 0 Warnings: 1
88,89c88,89
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
---
> affected rows: 1
> info: Records: 1 Duplicates: 0 Warnings: 1
7,10c7
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f1' at row 1
---
> ERROR 01000: Data truncated for column 'f1' at row 1
13c10
< 0
---
> NULL
21,24c18
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f1' at row 1
---
> ERROR 01000: Data truncated for column 'f1' at row 1
27c21
<
---
> NULL
35,38c29
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f1' at row 1
---
> ERROR 01000: Data truncated for column 'f1' at row 1
41c32
<
---
> NULL
49,52c40
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f1' at row 1
---
> ERROR 01000: Data truncated for column 'f1' at row 1
55c43
<
---
> NULL
63,66c51
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f3' at row 1
---
> ERROR 01000: Data truncated for column 'f3' at row 1
69c54
< 2 2 0
---
> 2 2 NULL
77,80c62
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'b' at row 1
---
> ERROR 01000: Data truncated for column 'b' at row 1
83c65
< 10 0
---
> 10 NULL
88,89c70,71
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
---
> affected rows: 1
> info: Records: 1 Duplicates: 0 Warnings: 1
7,10c7
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f1' at row 1
---
> ERROR 01000: Data truncated for column 'f1' at row 1
13c10
< 0
---
> NULL
21,24c18
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f1' at row 1
---
> ERROR 01000: Data truncated for column 'f1' at row 1
27c21
<
---
> NULL
35,38c29
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f1' at row 1
---
> ERROR 01000: Data truncated for column 'f1' at row 1
41c32
<
---
> NULL
49,52c40
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f1' at row 1
---
> ERROR 01000: Data truncated for column 'f1' at row 1
55c43
<
---
> NULL
63,66c51
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'f3' at row 1
---
> ERROR 01000: Data truncated for column 'f3' at row 1
69c54
< 2 2 0
---
> 2 2 NULL
77,80c62
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'b' at row 1
---
> ERROR 01000: Data truncated for column 'b' at row 1
83c65
< 10 0
---
> 10 NULL
CREATE TABLE t1(f1 INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
f1
NULL
ALTER TABLE t1 CHANGE f1 f1 INT NOT NULL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
SELECT * FROM t1;
f1
0
DROP TABLE t1;
CREATE TABLE t1(f1 CHAR(10))ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
f1
NULL
ALTER TABLE t1 CHANGE f1 f1 CHAR(10) NOT NULL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
SELECT * FROM t1;
f1
DROP TABLE t1;
CREATE TABLE t1(f1 VARCHAR(10))ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
f1
NULL
ALTER TABLE t1 CHANGE f1 f1 VARCHAR(20) NOT NULL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
SELECT * FROM t1;
f1
DROP TABLE t1;
CREATE TABLE t1(f1 TEXT)ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
f1
NULL
ALTER TABLE t1 CHANGE f1 f1 TEXT NOT NULL DEFAULT 'abc';
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
SELECT * FROM t1;
f1
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, f3 INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(2, 2, NULL);
SELECT * FROM t1;
f1 f2 f3
2 2 NULL
ALTER TABLE t1 CHANGE f3 f3 INT NOT NULL DEFAULT (f1 + f2);
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'f3' at row 1
SELECT * FROM t1;
f1 f2 f3
2 2 0
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL DEFAULT 0, b TINYINT)ENGINE=InnoDB;
INSERT INTO t1 VALUES(10, NULL);
SELECT * FROM t1;
f1 b
10 NULL
ALTER TABLE t1 CHANGE b b TINYINT NOT NULL DEFAULT if(unix_timestamp()>1,1000,0);
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'b' at row 1
SELECT * FROM t1;
f1 b
10 0
DROP TABLE t1;
CREATE TABLE t1(c1 INT NOT NULL, c2 INT, PRIMARY KEY(c1))ENGINE=INNODB;
INSERT INTO t1 VALUES(1, NULL);
ALTER IGNORE TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'c2' at row 1
SELECT * FROM t1;
c1 c2
1 0
DROP TABLE t1;
18,21c18
< affected rows: 0
< info: Records: 0 Duplicates: 0 Warnings: 1
< Warnings:
< Warning 1265 Data truncated for column 'c2' at row 3
---
> ERROR 01000: Data truncated for column 'c2' at row 3
24c21
< 2 0
---
> 2 NULL
71c68
< Warning 1265 Data truncated for column 'c2' at row 7
---
> Warning 1265 Data truncated for column 'c2' at row 6
CREATE TABLE t1(c1 INT NOT NULL, c2 INT, PRIMARY KEY(c1))ENGINE=INNODB;
INSERT INTO t1 VALUES(1, NULL);
INSERT INTO t1 VALUES(1, 1);
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
ALTER TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2, ALGORITHM=INPLACE;
affected rows: 0
ALTER TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2;
connect con1,localhost,root;
SET DEBUG_SYNC= 'now WAIT_FOR opened';
affected rows: 0
INSERT INTO t1 VALUES(2, NULL);
affected rows: 1
UPDATE t1 SET c1 = 3 WHERE c2 = 1;
affected rows: 1
info: Rows matched: 1 Changed: 1 Warnings: 0
SET DEBUG_SYNC= 'now SIGNAL flushed';
affected rows: 0
connection default;
ERROR 22004: Invalid use of NULL value
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'c2' at row 3
SELECT * FROM t1;
c1 c2
1 NULL
2 NULL
UPDATE t1 SET c2 = 0 WHERE c1 = 2;
2 0
3 1
DROP TABLE t1;
CREATE TABLE t1(c1 INT NOT NULL, c2 INT, PRIMARY KEY(c1))ENGINE=INNODB;
INSERT INTO t1 VALUES(1, 1);
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
# Alter ignore can convert the NULL values from
# CONCURRENT DML to constants
ALTER IGNORE TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2, ALGORITHM=INPLACE;
affected rows: 0
ALTER TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2;
connection con1;
SET DEBUG_SYNC= 'now WAIT_FOR opened';
UPDATE t1 SET c2 = NULL WHERE c1 = 2;
INSERT INTO t1 VALUES (3, NULL);
affected rows: 0
INSERT INTO t1 VALUES(2, 3);
affected rows: 1
UPDATE t1 SET c1 = 3 WHERE c2 = 1;
affected rows: 1
info: Rows matched: 1 Changed: 1 Warnings: 0
SET DEBUG_SYNC= 'now SIGNAL flushed';
affected rows: 0
connection default;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
SELECT * FROM t1;
c1 c2
1 2
2 2
3 2
2 3
3 1
DROP TABLE t1;
CREATE TABLE t1(c1 INT NOT NULL, c2 INT, c3 INT, PRIMARY KEY(c1))ENGINE=INNODB;
INSERT INTO t1 VALUES(1, NULL, NULL);
INSERT INTO t1 VALUES(1, 2, 3);
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
# Alter Successfully converts from null to not null
ALTER TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2, ALGORITHM=INPLACE;
affected rows: 0
ALTER IGNORE TABLE t1 CHANGE c2 c2 INT NOT NULL DEFAULT 2;
connection con1;
SET DEBUG_SYNC= 'now WAIT_FOR opened';
affected rows: 0
UPDATE t1 SET c2= 2 WHERE c1 = 1;
INSERT INTO t1 VALUES (2, 3, 4);
SET DEBUG_SYNC= 'now SIGNAL flushed';
connection default;
SELECT * FROM t1;
c1 c2 c3
1 2 NULL
2 3 4
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
# Alter fails because concurrent dml inserts null value
ALTER TABLE t1 CHANGE c3 c3 INT NOT NULL DEFAULT 2, ALGORITHM=INPLACE;
connection con1;
SET DEBUG_SYNC= 'now WAIT_FOR opened';
UPDATE t1 SET c3= 2 WHERE c1 = 2;
INSERT INTO t1 VALUES (4, 3, NULL);
affected rows: 0
info: Rows matched: 1 Changed: 0 Warnings: 0
INSERT INTO t1 VALUES (2, NULL, 4);
affected rows: 1
SET DEBUG_SYNC= 'now SIGNAL flushed';
affected rows: 0
connection default;
ERROR 22004: Invalid use of NULL value
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'c2' at row 7
SELECT * FROM t1;
c1 c2 c3
1 2 NULL
2 3 2
4 3 NULL
1 2 3
2 0 4
DROP TABLE t1;
disconnect con1;
SET DEBUG_SYNC='RESET';
set @@sql_mode = 'STRICT_TRANS_TABLES';
CREATE TABLE t1(f1 INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
f1
NULL
ALTER TABLE t1 CHANGE f1 f1 INT NOT NULL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
SELECT * FROM t1;
f1
0
DROP TABLE t1;
CREATE TABLE t1(f1 CHAR(10))ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
f1
NULL
ALTER TABLE t1 CHANGE f1 f1 CHAR(10) NOT NULL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
SELECT * FROM t1;
f1
DROP TABLE t1;
CREATE TABLE t1(f1 VARCHAR(10))ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
f1
NULL
ALTER TABLE t1 CHANGE f1 f1 VARCHAR(20) NOT NULL;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
SELECT * FROM t1;
f1
DROP TABLE t1;
CREATE TABLE t1(f1 TEXT)ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
f1
NULL
ALTER TABLE t1 CHANGE f1 f1 TEXT NOT NULL DEFAULT 'abc';
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
SELECT * FROM t1;
f1
abc
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, f3 INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(2, 2, NULL);
SELECT * FROM t1;
f1 f2 f3
2 2 NULL
ALTER TABLE t1 CHANGE f3 f3 INT NOT NULL DEFAULT (f1 + f2), ALGORITHM=INPLACE;
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: cannot convert NULL to non-constant DEFAULT. Try ALGORITHM=COPY
UPDATE t1 SET f3 = 0;
SELECT * FROM t1;
f1 f2 f3
2 2 0
ALTER TABLE t1 CHANGE f3 f3 INT NOT NULL DEFAULT (f1 + f2);
affected rows: 1
info: Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM t1;
f1 f2 f3
2 2 0
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL DEFAULT 0, b TINYINT)ENGINE=InnoDB;
INSERT INTO t1 VALUES(10, NULL);
SELECT * FROM t1;
f1 b
10 NULL
ALTER TABLE t1 CHANGE b b TINYINT NOT NULL DEFAULT if(unix_timestamp()>1,1000,0), algorithm=INPLACE;
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: cannot convert NULL to non-constant DEFAULT. Try ALGORITHM=COPY
DROP TABLE t1;
CREATE TABLE t1(a INT, v INT AS (a), c INT, d INT NOT NULL, e INT) ENGINE=InnoDB;
ALTER TABLE t1 DROP COLUMN c, CHANGE COLUMN e e INT NOT NULL, ALGORITHM=INPLACE;
DROP TABLE t1;
......
......@@ -2,16 +2,18 @@ CREATE TABLE t1 (i1 INT UNSIGNED NULL DEFAULT 42) ENGINE=innodb;
INSERT INTO t1 VALUES(NULL);
ALTER TABLE t1 CHANGE i1 i1 INT UNSIGNED NOT NULL DEFAULT rand(),
ALGORITHM=INPLACE;
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: cannot convert NULL to non-constant DEFAULT. Try ALGORITHM=COPY
ERROR 01000: Data truncated for column 'i1' at row 1
ALTER TABLE t1 CHANGE i1 i1 INT UNSIGNED NOT NULL DEFAULT rand(),
ALGORITHM=COPY;
ERROR 01000: Data truncated for column 'i1' at row 1
ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT,
ADD PRIMARY KEY(id), ALGORITHM=INPLACE;
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY
ALTER TABLE t1 ADD PRIMARY KEY(i1), ALGORITHM=INPLACE;
ALTER IGNORE TABLE t1 ADD PRIMARY KEY(i1), ALGORITHM=INPLACE;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
info: Records: 0 Duplicates: 0 Warnings: 1
Warnings:
Warning 1265 Data truncated for column 'i1' at row 1
ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT;
affected rows: 1
info: Records: 1 Duplicates: 0 Warnings: 0
......
......@@ -409,7 +409,7 @@ ALTER TABLE t1 DROP COLUMN c22f, ADD PRIMARY KEY c3p5(c3(5));
ERROR 42000: Key column 'c22f' doesn't exist in table
SET @old_sql_mode = @@sql_mode;
SET @@sql_mode = 'STRICT_TRANS_TABLES';
ALTER TABLE t1 DROP COLUMN c22f, DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
ALTER IGNORE TABLE t1 DROP COLUMN c22f, DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
ALGORITHM = INPLACE;
ERROR 23000: Duplicate entry '' for key 'PRIMARY'
SET @@sql_mode = @old_sql_mode;
......@@ -428,7 +428,7 @@ INSERT INTO t1 VALUES(33101,347,NULL,'');
SET DEBUG_SYNC = 'now SIGNAL ins_done0';
# session con1
connection con1;
ERROR 22004: Invalid use of NULL value
ERROR 01000: Data truncated for column 'c3' at row 1
SET @@sql_mode = @old_sql_mode;
# session default
connection default;
......
[COPY]
--alter_algorithm=copy
[INPLACE]
--alter_algorithm=inplace
# See also alter_non_null.combinations
--source include/have_innodb.inc
--source alter_sql_mode.inc
let $sql_mode = `SELECT @@SQL_MODE`;
let $error_code = 0;
if ($sql_mode == "STRICT_TRANS_TABLES") {
let $error_code = WARN_DATA_TRUNCATED;
}
--source include/alter_non_null.inc
--source alter_sql_mode.inc
let $sql_mode = `SELECT @@SQL_MODE`;
let $error_code = 0;
if ($sql_mode == "STRICT_TRANS_TABLES") {
let $error_code = WARN_DATA_TRUNCATED;
}
--source include/alter_non_null_debug.inc
--source include/have_innodb.inc
set @@sql_mode = 'STRICT_TRANS_TABLES';
CREATE TABLE t1(f1 INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
--enable_info
ALTER TABLE t1 CHANGE f1 f1 INT NOT NULL;
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 CHAR(10))ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
--enable_info
ALTER TABLE t1 CHANGE f1 f1 CHAR(10) NOT NULL;
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 VARCHAR(10))ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
--enable_info
ALTER TABLE t1 CHANGE f1 f1 VARCHAR(20) NOT NULL;
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 TEXT)ENGINE=INNODB;
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
--enable_info
ALTER TABLE t1 CHANGE f1 f1 TEXT NOT NULL DEFAULT 'abc';
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, f3 INT)ENGINE=INNODB;
INSERT INTO t1 VALUES(2, 2, NULL);
SELECT * FROM t1;
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE t1 CHANGE f3 f3 INT NOT NULL DEFAULT (f1 + f2), ALGORITHM=INPLACE;
UPDATE t1 SET f3 = 0;
SELECT * FROM t1;
--enable_info
ALTER TABLE t1 CHANGE f3 f3 INT NOT NULL DEFAULT (f1 + f2);
--disable_info
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL DEFAULT 0, b TINYINT)ENGINE=InnoDB;
INSERT INTO t1 VALUES(10, NULL);
SELECT * FROM t1;
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE t1 CHANGE b b TINYINT NOT NULL DEFAULT if(unix_timestamp()>1,1000,0), algorithm=INPLACE;
DROP TABLE t1;
CREATE TABLE t1(a INT, v INT AS (a), c INT, d INT NOT NULL, e INT) ENGINE=InnoDB;
ALTER TABLE t1 DROP COLUMN c, CHANGE COLUMN e e INT NOT NULL, ALGORITHM=INPLACE;
DROP TABLE t1;
......
[STRICT]
--sql_mode=STRICT_TRANS_TABLES
[NON-STRICT]
--sql_mode=
# See also alter_sql_mode.combinations
--source include/have_innodb.inc
......@@ -3,7 +3,7 @@
CREATE TABLE t1 (i1 INT UNSIGNED NULL DEFAULT 42) ENGINE=innodb;
INSERT INTO t1 VALUES(NULL);
--enable_info
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
--error WARN_DATA_TRUNCATED
ALTER TABLE t1 CHANGE i1 i1 INT UNSIGNED NOT NULL DEFAULT rand(),
ALGORITHM=INPLACE;
--error WARN_DATA_TRUNCATED
......@@ -12,7 +12,7 @@ ALGORITHM=COPY;
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT,
ADD PRIMARY KEY(id), ALGORITHM=INPLACE;
ALTER TABLE t1 ADD PRIMARY KEY(i1), ALGORITHM=INPLACE;
ALTER IGNORE TABLE t1 ADD PRIMARY KEY(i1), ALGORITHM=INPLACE;
ALTER TABLE t1 CHANGE i1 id INT UNSIGNED NOT NULL AUTO_INCREMENT;
--disable_info
SELECT * FROM t1;
......
......@@ -359,7 +359,7 @@ SET @old_sql_mode = @@sql_mode;
# And adding a PRIMARY KEY will also add NOT NULL implicitly!
SET @@sql_mode = 'STRICT_TRANS_TABLES';
--error ER_DUP_ENTRY
ALTER TABLE t1 DROP COLUMN c22f, DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
ALTER IGNORE TABLE t1 DROP COLUMN c22f, DROP PRIMARY KEY, ADD PRIMARY KEY c3p5(c3(5)),
ALGORITHM = INPLACE;
SET @@sql_mode = @old_sql_mode;
......@@ -384,7 +384,7 @@ SET DEBUG_SYNC = 'now SIGNAL ins_done0';
--echo # session con1
connection con1;
--error ER_INVALID_USE_OF_NULL
--error WARN_DATA_TRUNCATED
reap;
SET @@sql_mode = @old_sql_mode;
......
......@@ -11135,6 +11135,7 @@ uint32 Field_blob::max_display_length() const
@param level - level of message (Note/Warning/Error)
@param code - error code of message to be produced
@param cut_increment - whenever we should increase cut fields count
@current_row - current row number
@note
This function won't produce warning or notes or increase cut fields counter
......@@ -11152,7 +11153,7 @@ uint32 Field_blob::max_display_length() const
bool
Field::set_warning(Sql_condition::enum_warning_level level, uint code,
int cut_increment) const
int cut_increment, ulong current_row) const
{
/*
If this field was created only for type conversion purposes it
......@@ -11163,7 +11164,8 @@ Field::set_warning(Sql_condition::enum_warning_level level, uint code,
{
thd->cuted_fields+= cut_increment;
push_warning_printf(thd, level, code, ER_THD(thd, code), field_name.str,
thd->get_stmt_da()->current_row_for_warning());
current_row ? current_row
: thd->get_stmt_da()->current_row_for_warning());
return 0;
}
return level >= Sql_condition::WARN_LEVEL_WARN;
......
......@@ -1368,7 +1368,7 @@ class Field: public Value_source
virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; }
virtual int set_time() { return 1; }
bool set_warning(Sql_condition::enum_warning_level, unsigned int code,
int cuted_increment) const;
int cuted_increment, ulong current_row=0) const;
protected:
bool set_warning(unsigned int code, int cuted_increment) const
{
......
......@@ -7412,6 +7412,11 @@ static bool mysql_inplace_alter_table(THD *thd,
bool reopen_tables= false;
bool res;
/*
Set the truncated column values of thd as warning
for alter table.
*/
thd->count_cuted_fields = CHECK_FIELD_WARN;
DBUG_ENTER("mysql_inplace_alter_table");
/*
......
......@@ -203,8 +203,12 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
/** original column names of the table */
const char* const old_col_names;
/** Whether alter ignore issued. */
const bool ignore;
/** Allow non-null conversion.
(1) Alter ignore should allow the conversion
irrespective of sql mode.
(2) Don't allow the conversion in strict mode
(3) Allow the conversion only in non-strict mode. */
const bool allow_not_null;
ha_innobase_inplace_ctx(row_prebuilt_t*& prebuilt_arg,
dict_index_t** drop_arg,
......@@ -222,7 +226,7 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
ulint add_autoinc_arg,
ulonglong autoinc_col_min_value_arg,
ulonglong autoinc_col_max_value_arg,
bool ignore_flag) :
bool allow_not_null_flag) :
inplace_alter_handler_ctx(),
prebuilt (prebuilt_arg),
add_index (0), add_key_numbers (0), num_to_add_index (0),
......@@ -250,7 +254,7 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
old_n_cols(prebuilt_arg->table->n_cols),
old_cols(prebuilt_arg->table->cols),
old_col_names(prebuilt_arg->table->col_names),
ignore(ignore_flag)
allow_not_null(allow_not_null_flag)
{
ut_ad(old_n_cols >= DATA_N_SYS_COLS);
#ifdef UNIV_DEBUG
......@@ -919,18 +923,6 @@ ha_innobase::check_if_supported_inplace_alter(
DBUG_RETURN(HA_ALTER_INPLACE_INSTANT);
}
/* Only support NULL -> NOT NULL change if strict table sql_mode
is set. Fall back to COPY for conversion if not strict tables.
In-Place will fail with an error when trying to convert
NULL to a NOT NULL value. */
if ((ha_alter_info->handler_flags
& ALTER_COLUMN_NOT_NULLABLE)
&& !thd_is_strict_mode(m_user_thd)) {
ha_alter_info->unsupported_reason = my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
/* DROP PRIMARY KEY is only allowed in combination with ADD
PRIMARY KEY. */
if ((ha_alter_info->handler_flags
......@@ -1253,20 +1245,6 @@ ha_innobase::check_if_supported_inplace_alter(
}
break;
default:
/* Changing from NULL to NOT NULL and
set the default constant values. */
if (f->real_maybe_null()
&& !(*af)->real_maybe_null()) {
if (is_non_const_value(*af)) {
break;
}
if (!set_default_value(*af)) {
break;
}
}
/* For any other data type, NULL
values are not converted.
(An AUTO_INCREMENT attribute cannot
......@@ -3252,20 +3230,23 @@ innobase_check_foreigns(
}
/** Convert a default value for ADD COLUMN.
@param heap Memory heap where allocated
@param dfield InnoDB data field to copy to
@param field MySQL value for the column
@param comp nonzero if in compact format */
static MY_ATTRIBUTE((nonnull))
void
innobase_build_col_map_add(
/*=======================*/
@param[in,out] heap Memory heap where allocated
@param[out] dfield InnoDB data field to copy to
@param[in] field MySQL value for the column
@param[in] old_field Old field or NULL if new col is added
@param[in] comp nonzero if in compact format. */
static void innobase_build_col_map_add(
mem_heap_t* heap,
dfield_t* dfield,
const Field* field,
const Field* old_field,
ulint comp)
{
if (old_field && old_field->real_maybe_null()
&& field->real_maybe_null()) {
return;
}
if (field->is_real_null()) {
dfield_set_null(dfield);
return;
......@@ -3275,7 +3256,7 @@ innobase_build_col_map_add(
byte* buf = static_cast<byte*>(mem_heap_alloc(heap, size));
const byte* mysql_data = field->ptr;
const byte* mysql_data = old_field ? old_field->ptr : field->ptr;
row_mysql_store_col_in_innobase_format(
dfield, buf, true, mysql_data, size, comp);
......@@ -3362,16 +3343,15 @@ innobase_build_col_map(
const Field* altered_field =
altered_table->field[i + num_v];
if (field->real_maybe_null()
&& !altered_field->real_maybe_null()) {
/* Don't consider virtual column.
NULL to NOT NULL is not applicable
for virtual column. */
if (defaults) {
innobase_build_col_map_add(
heap, dtuple_get_nth_field(
heap,
dtuple_get_nth_field(
defaults, i),
altered_field,
dict_table_is_comp(new_table));
field,
dict_table_is_comp(
new_table));
}
col_map[old_i - num_old_v] = i;
......@@ -3383,6 +3363,7 @@ innobase_build_col_map(
innobase_build_col_map_add(
heap, dtuple_get_nth_field(defaults, i),
altered_table->field[i + num_v],
NULL,
dict_table_is_comp(new_table));
found_col:
if (is_v) {
......@@ -5611,7 +5592,8 @@ prepare_inplace_alter_table_dict(
!(ha_alter_info->handler_flags
& ALTER_ADD_PK_INDEX),
ctx->defaults, ctx->col_map, path,
ctx->ignore);
old_table,
ctx->allow_not_null);
rw_lock_x_unlock(&clust_index->lock);
if (!ok) {
......@@ -5669,7 +5651,9 @@ prepare_inplace_alter_table_dict(
ctx->prebuilt->trx,
index,
NULL, true, NULL, NULL,
path, ctx->ignore);
path, old_table,
ctx->allow_not_null);
rw_lock_x_unlock(&index->lock);
if (!ok) {
......@@ -6850,7 +6834,8 @@ ha_innobase::prepare_inplace_alter_table(
ha_alter_info->online,
heap, indexed_table,
col_names, ULINT_UNDEFINED, 0, 0,
ha_alter_info->ignore);
(ha_alter_info->ignore
|| !thd_is_strict_mode(m_user_thd)));
}
DBUG_ASSERT(m_prebuilt->trx->dict_operation_lock_mode == 0);
......@@ -6978,7 +6963,8 @@ ha_innobase::prepare_inplace_alter_table(
heap, m_prebuilt->table, col_names,
add_autoinc_col_no,
ha_alter_info->create_info->auto_increment_value,
autoinc_col_max_value, ha_alter_info->ignore);
autoinc_col_max_value,
ha_alter_info->ignore || !thd_is_strict_mode(m_user_thd));
DBUG_RETURN(prepare_inplace_alter_table_dict(
ha_alter_info, altered_table, table,
......@@ -7210,7 +7196,7 @@ ha_innobase::inplace_alter_table(
ctx->add_index, ctx->add_key_numbers, ctx->num_to_add_index,
altered_table, ctx->defaults, ctx->col_map,
ctx->add_autoinc, ctx->sequence, ctx->skip_pk_sort,
ctx->m_stage, add_v, eval_table);
ctx->m_stage, add_v, eval_table, ctx->allow_not_null);
#ifndef DBUG_OFF
oom:
......
......@@ -61,7 +61,9 @@ row_log_allocate(
const ulint* col_map,/*!< in: mapping of old column
numbers to new ones, or NULL if !table */
const char* path, /*!< in: where to create temporary file */
bool ignore) /*!< in: Whether alter ignore issued */
const TABLE* old_table, /*!< in:table definition before alter */
bool allow_not_null) /*!< in: allow null to non-null
conversion */
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/******************************************************//**
......
......@@ -322,6 +322,7 @@ this function and it will be passed to other functions for further accounting.
@param[in] add_v new virtual columns added along with indexes
@param[in] eval_table mysql table used to evaluate virtual column
value, see innobase_get_computed_value().
@param[in] allow_non_null allow the conversion from null to not-null
@return DB_SUCCESS or error code */
dberr_t
row_merge_build_indexes(
......@@ -340,7 +341,8 @@ row_merge_build_indexes(
bool skip_pk_sort,
ut_stage_alter_t* stage,
const dict_add_v_col_t* add_v,
struct TABLE* eval_table)
struct TABLE* eval_table,
bool allow_non_null)
MY_ATTRIBUTE((warn_unused_result));
/********************************************************************//**
......
......@@ -39,6 +39,7 @@ Created 2011-05-26 Marko Makela
#include "ut0stage.h"
#include "trx0rec.h"
#include <sql_class.h>
#include <algorithm>
#include <map>
......@@ -226,9 +227,11 @@ struct row_log_t {
table could be emptied, so that table->is_instant() no longer holds,
but all log records must be in the "instant" format. */
unsigned n_core_fields;
bool ignore; /*!< Whether the alter ignore is being used;
bool allow_not_null; /*!< Whether the alter ignore is being
used or if the sql mode is non-strict mode;
if not, NULL values will not be converted to
defaults */
const TABLE* old_table; /*< Use old table in case of error. */
/** Determine whether the log should be in the 'instant ADD' format
@param[in] index the clustered index of the source table
......@@ -1107,6 +1110,7 @@ table
@param[in] i rec field corresponding to col
@param[in] page_size page size of the old table
@param[in] max_len maximum length of dfield
@param[in] log row log for the table
@retval DB_INVALID_NULL if a NULL value is encountered
@retval DB_TOO_BIG_INDEX_COL if the maximum prefix length is exceeded */
static
......@@ -1120,8 +1124,7 @@ row_log_table_get_pk_col(
ulint i,
const page_size_t& page_size,
ulint max_len,
bool ignore,
const dtuple_t* defaults)
const row_log_t* log)
{
const byte* field;
ulint len;
......@@ -1129,12 +1132,16 @@ row_log_table_get_pk_col(
field = rec_get_nth_field(rec, offsets, i, &len);
if (len == UNIV_SQL_NULL) {
if (!ignore || !defaults->fields[i].data) {
if (!log->allow_not_null) {
return(DB_INVALID_NULL);
}
field = static_cast<const byte*>(defaults->fields[i].data);
len = defaults->fields[i].len;
ulint n_default_cols = i - DATA_N_SYS_COLS;
field = static_cast<const byte*>(
log->defaults->fields[n_default_cols].data);
len = log->defaults->fields[i - DATA_N_SYS_COLS].len;
}
if (rec_offs_nth_extern(offsets, i)) {
......@@ -1298,8 +1305,7 @@ row_log_table_get_pk(
log->error = row_log_table_get_pk_col(
ifield, dfield, *heap,
rec, offsets, i, page_size, max_len,
log->ignore, log->defaults);
rec, offsets, i, page_size, max_len, log);
if (log->error != DB_SUCCESS) {
err_exit:
......@@ -1484,7 +1490,9 @@ row_log_table_apply_convert_mrec(
reason of failure */
{
dtuple_t* row;
static ulong n_rows = index->table->stat_n_rows;
n_rows++;
*error = DB_SUCCESS;
/* This is based on row_build(). */
......@@ -1613,8 +1621,12 @@ row_log_table_apply_convert_mrec(
const dfield_t& default_field
= log->defaults->fields[col_no];
Field* field = log->old_table->field[col_no];
field->set_warning(Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1, n_rows);
if (!log->ignore || !default_field.data) {
if (!log->allow_not_null) {
/* We got a NULL value for a NOT NULL column. */
*error = DB_INVALID_NULL;
return NULL;
......@@ -3109,7 +3121,9 @@ row_log_allocate(
const ulint* col_map,/*!< in: mapping of old column
numbers to new ones, or NULL if !table */
const char* path, /*!< in: where to create temporary file */
const bool ignore) /*!< in: alter ignore issued */
const TABLE* old_table, /*!< in: table definition before alter */
const bool allow_not_null) /*!< in: allow null to not-null
conversion */
{
row_log_t* log;
DBUG_ENTER("row_log_allocate");
......@@ -3150,7 +3164,8 @@ row_log_allocate(
log->path = path;
log->n_core_fields = index->n_core_fields;
ut_ad(!table || log->is_instant(index) == index->is_instant());
log->ignore=ignore;
log->allow_not_null = allow_not_null;
log->old_table = old_table;
dict_index_set_online_status(index, ONLINE_INDEX_CREATION);
index->online_log = log;
......
......@@ -1674,6 +1674,7 @@ stage->inc() will be called for each page read.
@param[in,out] crypt_block crypted file buffer
@param[in] eval_table mysql table used to evaluate virtual column
value, see innobase_get_computed_value().
@param[in] allow_not_null allow null to not-null conversion
@return DB_SUCCESS or error */
static MY_ATTRIBUTE((warn_unused_result))
dberr_t
......@@ -1700,7 +1701,8 @@ row_merge_read_clustered_index(
ut_stage_alter_t* stage,
double pct_cost,
row_merge_block_t* crypt_block,
struct TABLE* eval_table)
struct TABLE* eval_table,
bool allow_not_null)
{
dict_index_t* clust_index; /* Clustered index */
mem_heap_t* row_heap; /* Heap memory to create
......@@ -1914,6 +1916,7 @@ row_merge_read_clustered_index(
mach_write_to_8(new_sys_trx_start, trx->id);
mach_write_to_8(new_sys_trx_end, TRX_ID_MAX);
ulong n_rows = 0;
/* Scan the clustered index. */
for (;;) {
......@@ -2046,6 +2049,8 @@ row_merge_read_clustered_index(
rec = page_cur_get_rec(cur);
n_rows++;
if (online) {
offsets = rec_get_offsets(rec, clust_index, NULL, true,
ULINT_UNDEFINED, &row_heap);
......@@ -2174,15 +2179,23 @@ row_merge_read_clustered_index(
ut_ad(dfield_get_type(field)->prtype & DATA_NOT_NULL);
if (dfield_is_null(field)) {
const dfield_t& default_field
= defaults->fields[nonnull[i]];
if (default_field.data == NULL) {
Field* null_field =
table->field[nonnull[i]];
null_field->set_warning(
Sql_condition::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, 1, n_rows);
if (!allow_not_null) {
err = DB_INVALID_NULL;
trx->error_key_num = 0;
goto func_exit;
}
const dfield_t& default_field
= defaults->fields[nonnull[i]];
*field = default_field;
}
}
......@@ -4547,6 +4560,7 @@ this function and it will be passed to other functions for further accounting.
@param[in] add_v new virtual columns added along with indexes
@param[in] eval_table mysql table used to evaluate virtual column
value, see innobase_get_computed_value().
@param[in] allow_not_null allow the conversion from null to not-null
@return DB_SUCCESS or error code */
dberr_t
row_merge_build_indexes(
......@@ -4565,7 +4579,8 @@ row_merge_build_indexes(
bool skip_pk_sort,
ut_stage_alter_t* stage,
const dict_add_v_col_t* add_v,
struct TABLE* eval_table)
struct TABLE* eval_table,
bool allow_not_null)
{
merge_file_t* merge_files;
row_merge_block_t* block;
......@@ -4729,7 +4744,7 @@ row_merge_build_indexes(
fts_sort_idx, psort_info, merge_files, key_numbers,
n_indexes, defaults, add_v, col_map, add_autoinc,
sequence, block, skip_pk_sort, &tmpfd, stage,
pct_cost, crypt_block, eval_table);
pct_cost, crypt_block, eval_table, allow_not_null);
stage->end_phase_read_pk();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment