From 7a0808b01258ff5077a9c8d939486e44adba34d2 Mon Sep 17 00:00:00 2001 From: yuxianjiang Date: Fri, 4 Dec 2020 04:08:56 -0500 Subject: [PATCH] [bugfix] inserting skip check with default value '0000-00-00 00:00:00' in strict sql_mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit problem When sql_mode is strict, binlog format is row and row image is full, insertion will skip check default validation of unset column. So default values like '0000-00-00 00:00:00' will be passed to storage engine and writen to binlog with strict mode in event. Slave recieves the row insert event and reports error during execution the event. solution Store write_set in TABLE object before function TABLE::mark_columns_per_binlog_row_image set all fields bit. And using the stored bitmap for validate_default_values_of_unset_fields. --- sql/sql_insert.cc | 28 ++++++++++++++++++++++++++++ sql/table.cc | 1 + sql/table.h | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 15d80fd05..592e8484b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -288,6 +288,9 @@ bool validate_default_values_of_unset_fields(THD *thd, TABLE *table) MY_BITMAP *write_set= table->write_set; DBUG_ENTER("validate_default_values_of_unset_fields"); + if (table->check_def_bitmap) + write_set= table->check_def_bitmap; + for (Field **field= table->field; *field; field++) { if (!bitmap_is_set(write_set, (*field)->field_index) && @@ -467,6 +470,7 @@ bool Sql_cmd_insert::mysql_insert(THD *thd,TABLE_LIST *table_list) partition_info::PRUNE_NO; MY_BITMAP used_partitions; bool prune_needs_default_values; + MY_BITMAP check_def_bitmap; SELECT_LEX *const select_lex= lex->select_lex; @@ -691,6 +695,24 @@ bool Sql_cmd_insert::mysql_insert(THD *thd,TABLE_LIST *table_list) if (thd->locked_tables_mode <= LTM_LOCK_TABLES) insert_table->file->ha_start_bulk_insert(insert_many_values.elements); + insert_table->check_def_bitmap= NULL; + if ((mysql_bin_log.is_open() && insert_table->in_use && + insert_table->in_use->is_current_stmt_binlog_format_row() && + !ha_check_storage_engine_flag(insert_table->s->db_type(), HTON_NO_BINLOG_ROW_OPT))) + { + THD *thd= current_thd; + if (thd->variables.binlog_row_image == BINLOG_ROW_IMAGE_FULL) + { + if (insert_table->write_set != NULL) + { + insert_table->check_def_bitmap= &check_def_bitmap; + bitmap_init(insert_table->check_def_bitmap, NULL, + insert_table->write_set->n_bits, false); + bitmap_copy(insert_table->check_def_bitmap, insert_table->write_set); + } + } + } + prepare_triggers_for_insert_stmt(insert_table); for (Field** next_field= insert_table->field; *next_field; ++next_field) @@ -782,6 +804,12 @@ bool Sql_cmd_insert::mysql_insert(THD *thd,TABLE_LIST *table_list) break; thd->get_stmt_da()->inc_current_row_for_condition(); } + + if (!insert_table->check_def_bitmap) + { + bitmap_free(insert_table->check_def_bitmap); + insert_table->check_def_bitmap= NULL; + } } // Statement plan is available within these braces error= thd->get_stmt_da()->is_error(); diff --git a/sql/table.cc b/sql/table.cc index cc008ee0c..5af190aa1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4225,6 +4225,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, outparam->s= share; outparam->db_stat= db_stat; outparam->write_row_record= NULL; + outparam->check_def_bitmap= NULL; init_sql_alloc(key_memory_TABLE, &outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); diff --git a/sql/table.h b/sql/table.h index dc3387130..2ba0de740 100644 --- a/sql/table.h +++ b/sql/table.h @@ -998,7 +998,7 @@ typedef Bitmap Field_map; struct TABLE { - TABLE() {} /* Remove gcc warning */ + TABLE() {check_def_bitmap= NULL;} /* Remove gcc warning */ /* Since TABLE instances are often cleared using memset(), do not add virtual members and do not inherit from TABLE. @@ -1109,6 +1109,7 @@ public: MY_BITMAP def_fields_set_during_insert; MY_BITMAP *read_set, *write_set; /* Active column sets */ + MY_BITMAP *check_def_bitmap; /** A pointer to the bitmap of table fields (columns), which are explicitly set -- 2.22.0