Commit 3062445a authored by Alexander Barkov's avatar Alexander Barkov

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*()
and Item::save_in_field().
parent f9066dc3
...@@ -857,3 +857,33 @@ DROP TABLE dest_db.t1; ...@@ -857,3 +857,33 @@ DROP TABLE dest_db.t1;
DROP TABLE source_db.t1; DROP TABLE source_db.t1;
DROP DATABASE source_db; DROP DATABASE source_db;
DROP DATABASE dest_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;
...@@ -37,3 +37,13 @@ Level Code Message ...@@ -37,3 +37,13 @@ Level Code Message
show errors; show errors;
Level Code Message Level Code Message
drop table t1; drop table t1;
#
# MDEV-14038 ALTER TABLE does not exit on error with InnoDB + bad default function
#
CREATE 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;
...@@ -494,6 +494,34 @@ eval ALTER TABLE $source_db.t1 DROP INDEX index2, algorithm=inplace; ...@@ -494,6 +494,34 @@ eval ALTER TABLE $source_db.t1 DROP INDEX index2, algorithm=inplace;
eval DROP TABLE $source_db.t1; eval DROP TABLE $source_db.t1;
eval DROP DATABASE $source_db; eval DROP DATABASE $source_db;
eval DROP DATABASE $dest_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;
...@@ -19,3 +19,13 @@ ALTER ONLINE TABLE t1 ADD PRIMARY KEY(a),DROP INDEX d, LOCK=SHARED; ...@@ -19,3 +19,13 @@ ALTER ONLINE TABLE t1 ADD PRIMARY KEY(a),DROP INDEX d, LOCK=SHARED;
show warnings; show warnings;
show errors; show errors;
drop table t1; drop table t1;
--echo #
--echo # MDEV-14038 ALTER TABLE does not exit on error with InnoDB + bad default function
--echo #
CREATE 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;
...@@ -2335,15 +2335,15 @@ Field *Field::clone(MEM_ROOT *root, my_ptrdiff_t diff) ...@@ -2335,15 +2335,15 @@ Field *Field::clone(MEM_ROOT *root, my_ptrdiff_t diff)
return tmp; return tmp;
} }
void Field::set_default() int Field::set_default()
{ {
if (default_value) if (default_value)
{ {
Query_arena backup_arena; Query_arena backup_arena;
table->in_use->set_n_backup_active_arena(table->expr_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); table->in_use->restore_active_arena(table->expr_arena, &backup_arena);
return; return rc;
} }
/* Copy constant value stored in s->default_values */ /* Copy constant value stored in s->default_values */
my_ptrdiff_t l_offset= (my_ptrdiff_t) (table->s->default_values - my_ptrdiff_t l_offset= (my_ptrdiff_t) (table->s->default_values -
...@@ -2352,6 +2352,7 @@ void Field::set_default() ...@@ -2352,6 +2352,7 @@ void Field::set_default()
if (maybe_null_in_table()) if (maybe_null_in_table())
*null_ptr= ((*null_ptr & (uchar) ~null_bit) | *null_ptr= ((*null_ptr & (uchar) ~null_bit) |
(null_ptr[l_offset] & 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, ...@@ -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) if (bit_len > 0)
{ {
...@@ -9673,7 +9674,7 @@ void Field_bit::set_default() ...@@ -9673,7 +9674,7 @@ void Field_bit::set_default()
uchar bits= get_rec_bits(bit_ptr + col_offset, bit_ofs, bit_len); uchar bits= get_rec_bits(bit_ptr + col_offset, bit_ofs, bit_len);
set_rec_bits(bits, bit_ptr, bit_ofs, bit_len); set_rec_bits(bits, bit_ptr, bit_ofs, bit_len);
} }
Field::set_default(); return Field::set_default();
} }
/* /*
......
...@@ -953,7 +953,7 @@ class Field: public Value_source ...@@ -953,7 +953,7 @@ class Field: public Value_source
my_ptrdiff_t l_offset= (my_ptrdiff_t) (record - table->record[0]); my_ptrdiff_t l_offset= (my_ptrdiff_t) (record - table->record[0]);
return ptr + l_offset; return ptr + l_offset;
} }
virtual void set_default(); virtual int set_default();
bool has_update_default_function() const bool has_update_default_function() const
{ {
...@@ -3715,7 +3715,7 @@ class Field_bit :public Field { ...@@ -3715,7 +3715,7 @@ class Field_bit :public Field {
virtual uchar *pack(uchar *to, const uchar *from, uint max_length); virtual uchar *pack(uchar *to, const uchar *from, uint max_length);
virtual const uchar *unpack(uchar *to, const uchar *from, virtual const uchar *unpack(uchar *to, const uchar *from,
const uchar *from_end, uint param_data); 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, Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uint32 length, uchar *new_ptr, uint32 length,
......
...@@ -1076,8 +1076,15 @@ ha_innobase::check_if_supported_inplace_alter( ...@@ -1076,8 +1076,15 @@ ha_innobase::check_if_supported_inplace_alter(
/* Compute the DEFAULT values of non-constant columns /* Compute the DEFAULT values of non-constant columns
(VCOL_SESSION_FUNC | VCOL_TIME_FUNC). */ (VCOL_SESSION_FUNC | VCOL_TIME_FUNC). */
(*af)->set_default(); switch ((*af)->set_default()) {
goto next_column; case 0: /* OK */
case 3: /* DATETIME to TIME or DATE conversion */
goto next_column;
case -1: /* OOM, or GEOMETRY type mismatch */
case 1: /* A number adjusted to the min/max value */
case 2: /* String truncation, or conversion problem */
break;
}
} }
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
......
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