Hello Marko, please review a patch for MDEV-14038.
Thanks!
commit 472c814c1e7bacd3b23e05a2b58f455ce161b786 Author: Alexander Barkov <[email protected]> Date: Wed Oct 11 09:18:32 2017 +0400 MDEV-14038 ALTER TABLE does not exit on error with InnoDB + bad default function Changing Field::set_default from void to int. It now uses the same return value notation with Field::store*: 0 OK 1 truncated (e.g. to a smaller number on numeric overflow) 2 truncated (e.g. to a shorter string), or converted some characters to '?' 3 minor acceptable truncation happened (such as TIMESTAMP->DATE) -1 OEM, or a completely bad value (no truncated replacement value possible) diff --git a/mysql-test/suite/innodb/r/innodb-alter.result b/mysql-test/suite/innodb/r/innodb-alter.result index aa78f55..b06c606 100644 --- a/mysql-test/suite/innodb/r/innodb-alter.result +++ b/mysql-test/suite/innodb/r/innodb-alter.result @@ -857,3 +857,33 @@ DROP TABLE dest_db.t1; DROP TABLE source_db.t1; DROP DATABASE source_db; DROP DATABASE dest_db; +USE test; +# +# MDEV-14038 ALTER TABLE does not exit on error with InnoDB + bad default function +# +CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; +iNSERT INTO t1 VALUES (10); +ALTER TABLE t1 ADD b TINYINT NOT NULL DEFAULT if(unix_timestamp()>1,1000,0); +ERROR 22003: Out of range value for column 'b' at row 1 +SELECT * FROM t1; +a +10 +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; +iNSERT INTO t1 VALUES (10); +ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +SELECT * FROM t1; +a b +10 2001-01-01 +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; +iNSERT INTO t1 VALUES (10); +ALTER TABLE t1 ADD b TIME NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +SELECT * FROM t1; +a b +10 10:20:30 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-online-alter-gis.result b/mysql-test/suite/innodb/r/innodb-online-alter-gis.result index c7daac4..b534597 100644 --- a/mysql-test/suite/innodb/r/innodb-online-alter-gis.result +++ b/mysql-test/suite/innodb/r/innodb-online-alter-gis.result @@ -37,3 +37,13 @@ Level Code Message show errors; Level Code Message drop table t1; +# +# MDEV-14038 ALTER TABLE does not exit on error with InnoDB + bad default function +# +CREATE OR REPLACE TABLE t1 (a INT) ENGINE=InnoDB; +ALTER TABLE t1 ADD COLUMN b LINESTRING DEFAULT POINT(1,1); +ERROR 22007: Incorrect LINESTRING value: 'POINT' for column 'b' at row 1 +DESCRIBE t1; +Field Type Null Key Default Extra +a int(11) YES NULL +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-alter.test b/mysql-test/suite/innodb/t/innodb-alter.test index 5e681f9..d936dca 100644 --- a/mysql-test/suite/innodb/t/innodb-alter.test +++ b/mysql-test/suite/innodb/t/innodb-alter.test @@ -494,6 +494,34 @@ eval ALTER TABLE $source_db.t1 DROP INDEX index2, algorithm=inplace; eval DROP TABLE $source_db.t1; eval DROP DATABASE $source_db; eval DROP DATABASE $dest_db; +USE test; +--echo # +--echo # MDEV-14038 ALTER TABLE does not exit on error with InnoDB + bad default function +--echo # +CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; +iNSERT INTO t1 VALUES (10); +--error ER_WARN_DATA_OUT_OF_RANGE +ALTER TABLE t1 ADD b TINYINT NOT NULL DEFAULT if(unix_timestamp()>1,1000,0); +SELECT * FROM t1; +DROP TABLE t1; + +# DATETIME-to-DATE truncation is OK +CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; +iNSERT INTO t1 VALUES (10); +--enable_info +ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0); +--disable_info +SELECT * FROM t1; +DROP TABLE t1; + +# DATETIME-to-TIME truncation is OK +CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; +iNSERT INTO t1 VALUES (10); +--enable_info +ALTER TABLE t1 ADD b TIME NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0); +--disable_info +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-online-alter-gis.test b/mysql-test/suite/innodb/t/innodb-online-alter-gis.test index 64d07ba..3f39750 100644 --- a/mysql-test/suite/innodb/t/innodb-online-alter-gis.test +++ b/mysql-test/suite/innodb/t/innodb-online-alter-gis.test @@ -19,3 +19,13 @@ ALTER ONLINE TABLE t1 ADD PRIMARY KEY(a),DROP INDEX d, LOCK=SHARED; show warnings; show errors; drop table t1; + +--echo # +--echo # MDEV-14038 ALTER TABLE does not exit on error with InnoDB + bad default function +--echo # + +CREATE OR REPLACE TABLE t1 (a INT) ENGINE=InnoDB; +--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD +ALTER TABLE t1 ADD COLUMN b LINESTRING DEFAULT POINT(1,1); +DESCRIBE t1; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index c9cf3c3..6b3f836 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2335,15 +2335,15 @@ Field *Field::clone(MEM_ROOT *root, my_ptrdiff_t diff) return tmp; } -void Field::set_default() +int Field::set_default() { if (default_value) { Query_arena backup_arena; table->in_use->set_n_backup_active_arena(table->expr_arena, &backup_arena); - (void) default_value->expr->save_in_field(this, 0); + int rc= default_value->expr->save_in_field(this, 0); table->in_use->restore_active_arena(table->expr_arena, &backup_arena); - return; + return rc; } /* Copy constant value stored in s->default_values */ my_ptrdiff_t l_offset= (my_ptrdiff_t) (table->s->default_values - @@ -2352,6 +2352,7 @@ void Field::set_default() if (maybe_null_in_table()) *null_ptr= ((*null_ptr & (uchar) ~null_bit) | (null_ptr[l_offset] & null_bit)); + return 0; } @@ -9665,7 +9666,7 @@ Field_bit::unpack(uchar *to, const uchar *from, const uchar *from_end, } -void Field_bit::set_default() +int Field_bit::set_default() { if (bit_len > 0) { @@ -9673,7 +9674,7 @@ void Field_bit::set_default() uchar bits= get_rec_bits(bit_ptr + col_offset, bit_ofs, bit_len); set_rec_bits(bits, bit_ptr, bit_ofs, bit_len); } - Field::set_default(); + return Field::set_default(); } /* diff --git a/sql/field.h b/sql/field.h index 91e97c8..1d0ce8c 100644 --- a/sql/field.h +++ b/sql/field.h @@ -953,7 +953,7 @@ class Field: public Value_source my_ptrdiff_t l_offset= (my_ptrdiff_t) (record - table->record[0]); return ptr + l_offset; } - virtual void set_default(); + virtual int set_default(); bool has_update_default_function() const { @@ -3715,7 +3715,7 @@ class Field_bit :public Field { virtual uchar *pack(uchar *to, const uchar *from, uint max_length); virtual const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data); - virtual void set_default(); + virtual int set_default(); Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 084fc80..6a6295e 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1069,8 +1069,9 @@ ha_innobase::check_if_supported_inplace_alter( /* Compute the DEFAULT values of non-constant columns (VCOL_SESSION_FUNC | VCOL_TIME_FUNC). */ - (*af)->set_default(); - goto next_column; + int rc= (*af)->set_default(); + if (rc == 0 || rc == 3) + goto next_column; } DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
_______________________________________________ Mailing list: https://launchpad.net/~maria-developers Post to : [email protected] Unsubscribe : https://launchpad.net/~maria-developers More help : https://help.launchpad.net/ListHelp

