mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
@ -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;
|
||||
|
@ -1,4 +1,5 @@
|
||||
--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 @@ public:
|
||||
*/
|
||||
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 @@ public:
|
||||
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 @@ err_new_table_cleanup:
|
||||
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
|
||||
|
Reference in New Issue
Block a user