MDEV-19611 INPLACE ALTER does not fail on bad implicit default value

- Inplace alter shouldn't set default date column as '0000-00-00' when
table is not empty. So mysql_inplace_alter_table() copied
alter_ctx.error_if_not_empty to a new field of Alter_inplace_info.
In ha_innobase::check_if_supported_inplace_alter() should check the
error_if_not_empty flag and return INPLACE_NOT_SUPPORTED if the table
is not empty
parent 3568fad5
......@@ -124,3 +124,18 @@ SELECT DISTINCT (CURRENT_TIMESTAMP()-d4) <= 60 FROM t1;
(CURRENT_TIMESTAMP()-d4) <= 60
1
DROP TABLE t1;
CREATE TABLE t1(f1 int) ENGINE=InnoDB;
INSERT INTO t1 SELECT * FROM seq_1_to_4096;
connect purge_control,localhost,root,,;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
DELETE FROM t1;
SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE';
ALTER TABLE t1 ADD f2 DATE NOT NULL, ALGORITHM=INPLACE;
INSERT INTO t1 VALUES (1, now());
Warnings:
Note 1265 Data truncated for column 'f2' at row 1
ALTER TABLE t1 ADD f3 DATE NOT NULL, ALGORITHM=INPLACE;
ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY
DROP TABLE t1;
disconnect purge_control;
--source include/have_innodb.inc
--source include/have_sequence.inc
CREATE TABLE t1 (i1 INT UNSIGNED NULL DEFAULT 42) ENGINE=innodb;
INSERT INTO t1 VALUES(NULL);
......@@ -82,3 +83,23 @@ ALTER TABLE t1 ADD COLUMN d4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
SELECT COUNT(DISTINCT d4),COUNT(d4),COUNT(*) FROM t1;
SELECT DISTINCT (CURRENT_TIMESTAMP()-d4) <= 60 FROM t1;
DROP TABLE t1;
# MDEV-19611 INPLACE ALTER does not fail on bad implicit default value
# Empty-table
CREATE TABLE t1(f1 int) ENGINE=InnoDB;
INSERT INTO t1 SELECT * FROM seq_1_to_4096;
connect(purge_control,localhost,root,,);
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
DELETE FROM t1;
SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE';
ALTER TABLE t1 ADD f2 DATE NOT NULL, ALGORITHM=INPLACE;
# Non-empty table
INSERT INTO t1 VALUES (1, now());
--error ER_ALTER_OPERATION_NOT_SUPPORTED
ALTER TABLE t1 ADD f3 DATE NOT NULL, ALGORITHM=INPLACE;
DROP TABLE t1;
disconnect purge_control;
......@@ -2352,11 +2352,14 @@ class Alter_inplace_info
*/
const char *unsupported_reason;
/** true when InnoDB should abort the alter when table is not empty */
bool error_if_not_empty;
Alter_inplace_info(HA_CREATE_INFO *create_info_arg,
Alter_info *alter_info_arg,
KEY *key_info_arg, uint key_count_arg,
partition_info *modified_part_info_arg,
bool ignore_arg)
bool ignore_arg, bool error_non_empty)
: create_info(create_info_arg),
alter_info(alter_info_arg),
key_info_buffer(key_info_arg),
......@@ -2371,7 +2374,8 @@ class Alter_inplace_info
modified_part_info(modified_part_info_arg),
ignore(ignore_arg),
online(false),
unsupported_reason(NULL)
unsupported_reason(NULL),
error_if_not_empty(error_non_empty)
{}
~Alter_inplace_info()
......
......@@ -9814,7 +9814,7 @@ do_continue:;
Alter_inplace_info ha_alter_info(create_info, alter_info,
key_info, key_count,
IF_PARTITIONING(thd->work_part_info, NULL),
ignore);
ignore, alter_ctx.error_if_not_empty);
TABLE *altered_table= NULL;
bool use_inplace= true;
......@@ -10261,7 +10261,7 @@ do_continue:;
thd->abort_on_warning= true;
make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN,
f_val, strlength(f_val), t_type,
new_table->s,
new_table ? new_table->s : table->s,
alter_ctx.datetime_field->field_name.str);
thd->abort_on_warning= save_abort_on_warning;
}
......
......@@ -866,6 +866,63 @@ innobase_fts_check_doc_id_col(
return(false);
}
/** Check whether the table is empty.
@param[in] table table to be checked
@return true if table is empty */
static bool innobase_table_is_empty(const dict_table_t *table)
{
dict_index_t *clust_index= dict_table_get_first_index(table);
mtr_t mtr;
btr_pcur_t pcur;
buf_block_t *block;
page_cur_t *cur;
const rec_t *rec;
bool next_page= false;
mtr.start();
btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF,
&pcur, true, 0, &mtr);
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
if (!rec_is_metadata(btr_pcur_get_rec(&pcur), clust_index))
btr_pcur_move_to_prev_on_page(&pcur);
scan_leaf:
cur= btr_pcur_get_page_cur(&pcur);
page_cur_move_to_next(cur);
next_page:
if (next_page)
{
uint32_t next_page_no= btr_page_get_next(page_cur_get_page(cur));
if (next_page_no == FIL_NULL)
{
mtr.commit();
return true;
}
next_page= false;
block= page_cur_get_block(cur);
block= btr_block_get(page_id_t(block->page.id.space(), next_page_no),
block->page.size, BTR_SEARCH_LEAF, clust_index,
&mtr);
btr_leaf_page_release(page_cur_get_block(cur), BTR_SEARCH_LEAF, &mtr);
page_cur_set_before_first(block, cur);
page_cur_move_to_next(cur);
}
rec= page_cur_get_rec(cur);
if (rec_get_deleted_flag(rec, dict_table_is_comp(table)));
else if (!page_rec_is_supremum(rec))
{
mtr.commit();
return false;
}
else
{
next_page= true;
goto next_page;
}
goto scan_leaf;
}
/** Check if InnoDB supports a particular alter table in-place
@param altered_table TABLE object for new version of table.
@param ha_alter_info Structure describing changes to be done
......@@ -1078,6 +1135,13 @@ ha_innobase::check_if_supported_inplace_alter(
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
/* '0000-00-00' value isn't allowed for datetime datatype
for newly added column when table is not empty */
if (ha_alter_info->error_if_not_empty
&& !innobase_table_is_empty(m_prebuilt->table)) {
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
bool add_drop_v_cols = false;
/* If there is add or drop virtual columns, we will support operations
......
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