Commit 0e9ba176 authored by Nikita Malyavin's avatar Nikita Malyavin

MDEV-17890 Server crash on DELETE with YEAR field with truncated expr

The failing reason was inconsistent truncation rules: the value of virtual
column could have been evaluated to '2000' sometimes instead of '0000' for
value 'a'.

The reason why `c YEAR AS ('aaaa')` was not evaluated same is that len=4 is
a special case insidew Field_year::store.

The correct fix is: always evaluate a bad value to 0000 instead 2000.
The truncated values should be evaluated as usual.

$support_virtual_index is finally changed to 1 in gcol.gcol_ins_upd_innodb,
which is also enough for testing.

The test from original bug report is also added.
parent b0827168
...@@ -607,4 +607,26 @@ DELETE FROM t1; ...@@ -607,4 +607,26 @@ DELETE FROM t1;
DROP TEMPORARY TABLE t1; DROP TEMPORARY TABLE t1;
--echo #
--echo # Original test case from MDEV-17890
--echo #
CREATE TABLE t1 (
pk BIGINT AUTO_INCREMENT,
b BIT(15),
v BIT(10) AS (b) VIRTUAL,
PRIMARY KEY(pk),
UNIQUE(v)
);
INSERT IGNORE INTO t1 (b) VALUES (b'101110001110100'),(b'011101');
SELECT pk, b FROM t1 INTO OUTFILE 'load.data';
--error ER_DATA_TOO_LONG
LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b);
# Cleanup
DROP TABLE t1;
--let $datadir= `SELECT @@datadir`
--remove_file $datadir/test/load.data
} }
...@@ -812,7 +812,7 @@ DROP TABLE t1; ...@@ -812,7 +812,7 @@ DROP TABLE t1;
--echo # MDEV-19011 Assertion `file->s->base.reclength < file->s->vreclength' --echo # MDEV-19011 Assertion `file->s->base.reclength < file->s->vreclength'
--echo # failed in ha_myisam::setup_vcols_for_repair --echo # failed in ha_myisam::setup_vcols_for_repair
CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL) ENGINE=MyISAM; CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL);
ALTER TABLE t1 ADD KEY (a); ALTER TABLE t1 ADD KEY (a);
DROP TABLE t1; DROP TABLE t1;
......
...@@ -435,6 +435,26 @@ UPDATE t1 SET col1 = 2; ...@@ -435,6 +435,26 @@ UPDATE t1 SET col1 = 2;
UPDATE t1 SET col7 = DEFAULT; UPDATE t1 SET col7 = DEFAULT;
UPDATE t1 SET col8 = DEFAULT; UPDATE t1 SET col8 = DEFAULT;
DROP TABLE t1; DROP TABLE t1;
Bug#20797344: WL#8149: ALLOCATED SPACE FOR INDEXED BLOB VGC CAN BE
OVERWRITTEN FOR UPDATE
#
CREATE TABLE t (a varchar(100), b blob,
c blob GENERATED ALWAYS AS (concat(a,b)) VIRTUAL,
d blob GENERATED ALWAYS AS (b) VIRTUAL,
e int(11) GENERATED ALWAYS AS (10) VIRTUAL,
h int(11) NOT NULL, PRIMARY KEY (h), key(c(20)));
INSERT INTO t(a,b,h) VALUES('aaaaaaa','1111111', 11);
INSERT INTO t(a,b,h) VALUES('bbbbbbb','2222222', 22);
SELECT c FROM t;
c
aaaaaaa1111111
bbbbbbb2222222
UPDATE t SET a='ccccccc';
SELECT c FROM t;
c
ccccccc1111111
ccccccc2222222
DROP TABLE t;
# Bug#21081742: ASSERTION !TABLE || (!TABLE->WRITE_SET || # Bug#21081742: ASSERTION !TABLE || (!TABLE->WRITE_SET ||
# BITMAP_IS_SET(TABLE->WRITE_SET # BITMAP_IS_SET(TABLE->WRITE_SET
# #
...@@ -491,6 +511,21 @@ SELECT * FROM t; ...@@ -491,6 +511,21 @@ SELECT * FROM t;
x y gc x y gc
2 1 3 2 1 3
DROP TABLE t; DROP TABLE t;
CREATE TABLE t (
x INT, y INT, gc INT GENERATED ALWAYS AS (x+1), KEY (x,gc)
);
INSERT INTO t VALUES ();
UPDATE t t1, t t2 SET t1.x = 1, t2.y = 2;
SELECT * FROM t;
x y gc
1 2 2
SELECT gc FROM t;
gc
2
CHECK TABLE t;
Table Op Msg_type Msg_text
test.t check status OK
DROP TABLE t;
# stored # stored
CREATE TABLE C ( CREATE TABLE C (
col_varchar_nokey VARCHAR(1), col_varchar_nokey VARCHAR(1),
...@@ -552,6 +587,99 @@ SELECT * from C; ...@@ -552,6 +587,99 @@ SELECT * from C;
col_varchar_nokey col_varchar_key col_varchar_nokey col_varchar_key
a aa a aa
DROP TABLE C; DROP TABLE C;
# virtual, indexed
CREATE TABLE C (
col_varchar_nokey VARCHAR(1),
col_varchar_key VARCHAR(2) GENERATED ALWAYS AS
(CONCAT(col_varchar_nokey, col_varchar_nokey)) VIRTUAL,
KEY (col_varchar_key, col_varchar_nokey)
);
INSERT INTO C (col_varchar_nokey) VALUES ('c');
EXPLAIN UPDATE C AS OUTR1, C AS OUTR2
SET OUTR1.`col_varchar_nokey` = 'f',
OUTR2.`col_varchar_nokey` = "a";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE OUTR1 ALL NULL NULL NULL NULL 1
1 SIMPLE OUTR2 ALL NULL NULL NULL NULL 1
UPDATE C AS OUTR1, C AS OUTR2
SET OUTR1.`col_varchar_nokey` = 'f',
OUTR2.`col_varchar_nokey` = "a";
SELECT * from C;
col_varchar_nokey col_varchar_key
a aa
DROP TABLE C;
#
# Bug #21530366 CRASH/ASSERTION, CORRUPTION WITH INDEXES +
# VIRTUAL COLUMNS, BLOB
#
CREATE TABLE t (
a INTEGER,
b BLOB GENERATED ALWAYS AS (a) VIRTUAL,
INDEX (b(57))
);
INSERT INTO t (a) VALUES (9);
UPDATE t SET a = 10;
DELETE FROM t WHERE a = 10;
DROP TABLE t;
# Bug#21807818: Generated columns not updated with empty insert list
CREATE TABLE t (
a BLOB GENERATED ALWAYS AS ('') VIRTUAL,
b TIMESTAMP(4) GENERATED ALWAYS AS ('') VIRTUAL,
KEY (a(183),b)
);
INSERT IGNORE INTO t VALUES(), (), ();
Warnings:
Warning 1265 Data truncated for column 'b' at row 1
Warning 1265 Data truncated for column 'b' at row 2
Warning 1265 Data truncated for column 'b' at row 3
DELETE IGNORE FROM t;
DROP TABLE t;
#
# Bug#22195458:GCOLS: ASSERTION 0 AND CORRUPTION...
#
CREATE TABLE t (
a INT,
b YEAR GENERATED ALWAYS AS ('a') VIRTUAL,
c YEAR GENERATED ALWAYS AS ('aaaa') VIRTUAL,
b1 YEAR GENERATED ALWAYS AS ('a') STORED,
c1 YEAR GENERATED ALWAYS AS ('aaaa') STORED,
UNIQUE(b),
UNIQUE(b1)
);
INSERT IGNORE INTO t VALUES();
SELECT b from t;
b
0000
SELECT b1 from t;
b1
0000
SELECT * from t;
a b c b1 c1
NULL 0000 0000 0000 0000
DELETE FROM t;
CHECK TABLE t EXTENDED;
Table Op Msg_type Msg_text
test.t check status OK
DROP TABLE t;
# Bug#22195364:GCOLS: FAILING ASSERTION:
# DFIELD_IS_NULL(DFIELD2) || DFIELD2->DATA
CREATE TABLE t (
a INT,
c BLOB GENERATED ALWAYS AS ('') VIRTUAL,
UNIQUE KEY(c(1),a)
);
INSERT INTO t(a) VALUES(1) ON DUPLICATE KEY UPDATE a=2;
SELECT * FROM t;
a c
1
INSERT INTO t(a) VALUES(1) ON DUPLICATE KEY UPDATE a=2;
SELECT * FROM t;
a c
2
SELECT GROUP_CONCAT(c ORDER BY c) FROM t;
GROUP_CONCAT(c ORDER BY c)
DROP TABLE t;
#Bug#21929967:GCOLS:GCOL VALUE CHANGES WHEN SESSION CHANGES SQL_MODE #Bug#21929967:GCOLS:GCOL VALUE CHANGES WHEN SESSION CHANGES SQL_MODE
CREATE TABLE t(c1 INT GENERATED ALWAYS AS (1) VIRTUAL, CREATE TABLE t(c1 INT GENERATED ALWAYS AS (1) VIRTUAL,
c2 INT GENERATED ALWAYS AS(2) STORED); c2 INT GENERATED ALWAYS AS(2) STORED);
...@@ -593,6 +721,49 @@ i1 i2 ...@@ -593,6 +721,49 @@ i1 i2
5 10 5 10
5 10 5 10
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# Bug#22070021 GCOL:ASSERTION `!TABLE || (!TABLE->WRITE_SET ||
# BITMAP_IS_SET(TABLE->WRITE_SET,
#
CREATE TABLE t1(
c1 INT,
c2 INT GENERATED ALWAYS AS (c1 + c1) VIRTUAL,
KEY(c2)
);
INSERT INTO t1(c1) VALUES(0);
DELETE O1.* FROM t1 AS O1, t1 AS O2;
SELECT * FROM t1;
c1 c2
DROP TABLE t1;
#
# Bug#21944199 SIMPLE DELETE QUERY CAUSES INNODB: FAILING ASSERTION: 0
# & DATA CORRUPTION
#
CREATE TEMPORARY TABLE t1 (
a INTEGER NOT NULL,
b INTEGER GENERATED ALWAYS AS (a+1) VIRTUAL
);
INSERT INTO t1 (a) VALUES (0), (0), (0);
ALTER TABLE t1 ADD INDEX idx (b);
DELETE FROM t1;
DROP TEMPORARY TABLE t1;
#
# Original test case from MDEV-17890
#
CREATE TABLE t1 (
pk BIGINT AUTO_INCREMENT,
b BIT(15),
v BIT(10) AS (b) VIRTUAL,
PRIMARY KEY(pk),
UNIQUE(v)
);
INSERT IGNORE INTO t1 (b) VALUES (b'101110001110100'),(b'011101');
Warnings:
Warning 1264 Out of range value for column 'v' at row 1
SELECT pk, b FROM t1 INTO OUTFILE 'load.data';
LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b);
ERROR 22001: Data too long for column 'v' at row 1
DROP TABLE t1;
DROP VIEW IF EXISTS v1,v2; DROP VIEW IF EXISTS v1,v2;
DROP TABLE IF EXISTS t1,t2,t3; DROP TABLE IF EXISTS t1,t2,t3;
DROP PROCEDURE IF EXISTS p1; DROP PROCEDURE IF EXISTS p1;
......
...@@ -571,13 +571,13 @@ UNIQUE(b1) ...@@ -571,13 +571,13 @@ UNIQUE(b1)
INSERT IGNORE INTO t VALUES(); INSERT IGNORE INTO t VALUES();
SELECT b from t; SELECT b from t;
b b
2000 0000
SELECT b1 from t; SELECT b1 from t;
b1 b1
0000 0000
SELECT * from t; SELECT * from t;
a b c b1 c1 a b c b1 c1
NULL 2000 0000 0000 0000 NULL 0000 0000 0000 0000
DELETE FROM t; DELETE FROM t;
CHECK TABLE t EXTENDED; CHECK TABLE t EXTENDED;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
...@@ -669,6 +669,23 @@ INSERT INTO t1 (a) VALUES (0), (0), (0); ...@@ -669,6 +669,23 @@ INSERT INTO t1 (a) VALUES (0), (0), (0);
ALTER TABLE t1 ADD INDEX idx (b); ALTER TABLE t1 ADD INDEX idx (b);
DELETE FROM t1; DELETE FROM t1;
DROP TEMPORARY TABLE t1; DROP TEMPORARY TABLE t1;
#
# Original test case from MDEV-17890
#
CREATE TABLE t1 (
pk BIGINT AUTO_INCREMENT,
b BIT(15),
v BIT(10) AS (b) VIRTUAL,
PRIMARY KEY(pk),
UNIQUE(v)
);
INSERT IGNORE INTO t1 (b) VALUES (b'101110001110100'),(b'011101');
Warnings:
Warning 1264 Out of range value for column 'v' at row 1
SELECT pk, b FROM t1 INTO OUTFILE 'load.data';
LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b);
ERROR 22001: Data too long for column 'v' at row 1
DROP TABLE t1;
DROP VIEW IF EXISTS v1,v2; DROP VIEW IF EXISTS v1,v2;
DROP TABLE IF EXISTS t1,t2,t3; DROP TABLE IF EXISTS t1,t2,t3;
DROP PROCEDURE IF EXISTS p1; DROP PROCEDURE IF EXISTS p1;
......
...@@ -879,7 +879,7 @@ ERROR 22003: Out of range value for column 'vi' at row 1 ...@@ -879,7 +879,7 @@ ERROR 22003: Out of range value for column 'vi' at row 1
DROP TABLE t1; DROP TABLE t1;
# MDEV-19011 Assertion `file->s->base.reclength < file->s->vreclength' # MDEV-19011 Assertion `file->s->base.reclength < file->s->vreclength'
# failed in ha_myisam::setup_vcols_for_repair # failed in ha_myisam::setup_vcols_for_repair
CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL) ENGINE=MyISAM; CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL);
ALTER TABLE t1 ADD KEY (a); ALTER TABLE t1 ADD KEY (a);
DROP TABLE t1; DROP TABLE t1;
# #
......
...@@ -879,7 +879,7 @@ ERROR 22003: Out of range value for column 'vi' at row 1 ...@@ -879,7 +879,7 @@ ERROR 22003: Out of range value for column 'vi' at row 1
DROP TABLE t1; DROP TABLE t1;
# MDEV-19011 Assertion `file->s->base.reclength < file->s->vreclength' # MDEV-19011 Assertion `file->s->base.reclength < file->s->vreclength'
# failed in ha_myisam::setup_vcols_for_repair # failed in ha_myisam::setup_vcols_for_repair
CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL) ENGINE=MyISAM; CREATE TABLE t1 (a INT GENERATED ALWAYS AS (1) VIRTUAL);
ALTER TABLE t1 ADD KEY (a); ALTER TABLE t1 ADD KEY (a);
DROP TABLE t1; DROP TABLE t1;
DROP VIEW IF EXISTS v1,v2; DROP VIEW IF EXISTS v1,v2;
......
...@@ -36,7 +36,7 @@ eval SET @@session.default_storage_engine = 'InnoDB'; ...@@ -36,7 +36,7 @@ eval SET @@session.default_storage_engine = 'InnoDB';
#------------------------------------------------------------------------------# #------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines # Execute the tests to be applied to all storage engines
let $support_virtual_index= 0; let $support_virtual_index= 1;
--source suite/gcol/inc/gcol_ins_upd.inc --source suite/gcol/inc/gcol_ins_upd.inc
#------------------------------------------------------------------------------# #------------------------------------------------------------------------------#
......
...@@ -6373,6 +6373,7 @@ bool Field_timef::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) ...@@ -6373,6 +6373,7 @@ bool Field_timef::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
{ {
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
THD *thd= get_thd();
char *end; char *end;
int error; int error;
longlong nr= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); longlong nr= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error);
...@@ -6384,7 +6385,14 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) ...@@ -6384,7 +6385,14 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1; return 1;
} }
if (get_thd()->count_cuted_fields &&
if (!thd->count_cuted_fields && error == MY_ERRNO_EDOM)
{
*ptr= 0;
return 1;
}
if (thd->count_cuted_fields &&
(error= check_int(cs, from, len, end, error))) (error= check_int(cs, from, len, end, error)))
{ {
if (error == 1) /* empty or incorrect string */ if (error == 1) /* empty or incorrect string */
......
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