diff --git a/sql/handler.cc b/sql/handler.cc index a496adb47dc..abf81affe77 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -8087,20 +8087,30 @@ bool handler::prepare_for_row_logging() /* - Do all initialization needed for insert + Do all initialization needed for writes: INSERT/UPDATE/DELETE + + can_set_fields is true if values of individual fields in a record + can be set. That is, INSERT/UPDATE, need uniqueness checks, for example. + + can_lookup is true if the operation needs to look up rows in the table, + that is UPDATE/DELETE, and here we need a separate `lookup_handler` + to avoid disrupting the state of `this` */ -int handler::prepare_for_insert(bool do_create) +int handler::prepare_for_modify(bool can_set_fields, bool can_lookup) { if (table->open_hlindexes_for_write()) return 1; - /* Preparation for unique of blob's */ - if (table->s->long_unique_table || table->s->period.unique_keys) + if (can_set_fields) { - if (do_create && create_lookup_handler()) - return 1; - alloc_lookup_buffer(); + /* Preparation for unique of blob's */ + if (table->s->long_unique_table || table->s->period.unique_keys) + { + if (can_lookup && create_lookup_handler()) + return 1; + alloc_lookup_buffer(); + } } return 0; } @@ -8109,8 +8119,8 @@ int handler::prepare_for_insert(bool do_create) int handler::ha_write_row(const uchar *buf) { int error; - DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE || - m_lock_type == F_WRLCK); + DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE || m_lock_type == F_WRLCK); + DBUG_ASSERT(buf == table->record[0]); DBUG_ENTER("handler::ha_write_row"); DEBUG_SYNC_C("ha_write_row_start"); #ifdef WITH_WSREP @@ -8131,7 +8141,7 @@ int handler::ha_write_row(const uchar *buf) DBUG_ASSERT(inited == NONE || lookup_handler != this); if ((error= check_duplicate_long_entries(buf))) { - if (table->next_number_field && buf == table->record[0]) + if (table->next_number_field) if (int err= update_auto_increment()) error= err; DBUG_RETURN(error); @@ -8265,9 +8275,9 @@ int handler::ha_delete_row(const uchar *buf) m_lock_type == F_WRLCK); /* Normally table->record[0] is used, but sometimes table->record[1] is used. + (notably, for REPLACE and in sql_acl.cc) */ - DBUG_ASSERT(buf == table->record[0] || - buf == table->record[1]); + DBUG_ASSERT(buf == table->record[0] || buf == table->record[1]); MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str); mark_trx_read_write(); diff --git a/sql/handler.h b/sql/handler.h index 812e6943c9f..b44040f914b 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -5162,9 +5162,8 @@ public: virtual int delete_table(const char *name); bool check_table_binlog_row_based(); bool prepare_for_row_logging(); - int prepare_for_insert(bool do_create); - int binlog_log_row(const uchar *before_record, - const uchar *after_record, + int prepare_for_modify(bool can_set_fields, bool can_lookup); + int binlog_log_row(const uchar *before_record, const uchar *after_record, Log_func *log_func); inline void clear_cached_table_binlog_row_based_flag() diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 6c0ea9a10eb..fd944a87cdb 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -5114,7 +5114,8 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) Rows_log_event::Db_restore_ctx restore_ctx(this); master_had_triggers= table->master_had_triggers; bool transactional_table= table->file->has_transactions_and_rollback(); - table->file->prepare_for_insert(get_general_type_code() != WRITE_ROWS_EVENT); + table->file->prepare_for_modify(true, + get_general_type_code() != WRITE_ROWS_EVENT); /* table == NULL means that this table should not be replicated diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 8796b6cd738..43071a58a7c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -467,6 +467,7 @@ bool Sql_cmd_delete::delete_from_single_table(THD *thd) if (thd->lex->describe) goto produce_explain_and_leave; + table->file->prepare_for_modify(false, false); if (likely(!(error=table->file->ha_delete_all_rows()))) { /* @@ -849,8 +850,8 @@ bool Sql_cmd_delete::delete_from_single_table(THD *thd) && !table->versioned() && table->file->has_transactions(); - if (table->versioned(VERS_TIMESTAMP) || (table_list->has_period())) - table->file->prepare_for_insert(1); + table->file->prepare_for_modify(table->versioned(VERS_TIMESTAMP) || + table_list->has_period(), true); DBUG_ASSERT(table->file->inited != handler::NONE); THD_STAGE_INFO(thd, stage_updating); @@ -1178,9 +1179,7 @@ multi_delete::initialize_tables(JOIN *join) normal_tables= 1; tbl->prepare_triggers_for_delete_stmt_or_event(); tbl->prepare_for_position(); - - if (tbl->versioned(VERS_TIMESTAMP)) - tbl->file->prepare_for_insert(1); + tbl->file->prepare_for_modify(tbl->versioned(VERS_TIMESTAMP), true); } else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) && walk == delete_tables) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ed0cc6f9616..4dbe4971b55 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -956,7 +956,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, if (lock_type != TL_WRITE_DELAYED) #endif /* EMBEDDED_LIBRARY */ { - bool create_lookup_handler= duplic != DUP_ERROR; + bool create_lookup_handler= false; if (duplic != DUP_ERROR || ignore) { create_lookup_handler= true; @@ -967,7 +967,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, goto abort; } } - if (table->file->prepare_for_insert(create_lookup_handler)) + if (table->file->prepare_for_modify(true, create_lookup_handler)) goto abort; /** This is a simple check for the case when the table has a trigger @@ -3686,7 +3686,7 @@ bool Delayed_insert::handle_inserts(void) handler_writes() will not have called decide_logging_format. */ table->file->prepare_for_row_logging(); - table->file->prepare_for_insert(1); + table->file->prepare_for_modify(true, true); using_bin_log= table->file->row_logging; /* @@ -4195,7 +4195,7 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) #endif thd->cuted_fields=0; - bool create_lookup_handler= info.handle_duplicates != DUP_ERROR; + bool create_lookup_handler= false; if (info.ignore || info.handle_duplicates != DUP_ERROR) { create_lookup_handler= true; @@ -4206,7 +4206,7 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) DBUG_RETURN(1); } } - table->file->prepare_for_insert(create_lookup_handler); + table->file->prepare_for_modify(true, create_lookup_handler); if (info.handle_duplicates == DUP_REPLACE && (!table->triggers || !table->triggers->has_delete_triggers())) table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); @@ -4980,7 +4980,7 @@ select_create::prepare(List &_values, SELECT_LEX_UNIT *u) restore_record(table,s->default_values); // Get empty record thd->cuted_fields=0; - bool create_lookup_handler= info.handle_duplicates != DUP_ERROR; + bool create_lookup_handler= false; if (info.ignore || info.handle_duplicates != DUP_ERROR) { create_lookup_handler= true; @@ -4991,7 +4991,7 @@ select_create::prepare(List &_values, SELECT_LEX_UNIT *u) DBUG_RETURN(1); } } - table->file->prepare_for_insert(create_lookup_handler); + table->file->prepare_for_modify(true, create_lookup_handler); if (info.handle_duplicates == DUP_REPLACE && (!table->triggers || !table->triggers->has_delete_triggers())) table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 55184af93b6..f384a21cfd6 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -685,14 +685,14 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, thd->abort_on_warning= !ignore && thd->is_strict_mode(); thd->get_stmt_da()->reset_current_row_for_warning(1); - bool create_lookup_handler= handle_duplicates != DUP_ERROR; + bool create_lookup_handler= false; if ((table_list->table->file->ha_table_flags() & HA_DUPLICATE_POS)) { create_lookup_handler= true; if ((error= table_list->table->file->ha_rnd_init_with_error(0))) goto err; } - table->file->prepare_for_insert(create_lookup_handler); + table->file->prepare_for_modify(true, create_lookup_handler); thd_progress_init(thd, 2); fix_rownum_pointers(thd, thd->lex->current_select, &info.copied); if (table_list->table->validate_default_values_of_unset_fields(thd)) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f3e181c1687..a32b799cd71 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -12333,7 +12333,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, from->file->column_bitmaps_signal(); - to->file->prepare_for_insert(0); + to->file->prepare_for_modify(true, false); DBUG_ASSERT(to->file->inited == handler::NONE); /* Tell handler that we have values for all columns in the to table */ diff --git a/sql/sql_update.cc b/sql/sql_update.cc index ad449fc8f7c..e8d010dcfb6 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -956,7 +956,7 @@ update_begin: can_compare_record= records_are_comparable(table); explain->tracker.on_scan_init(); - table->file->prepare_for_insert(1); + table->file->prepare_for_modify(true, true); DBUG_ASSERT(table->file->inited != handler::NONE); THD_STAGE_INFO(thd, stage_updating); @@ -1892,7 +1892,7 @@ int multi_update::prepare(List ¬_used_values, table->read_set= &table->def_read_set; bitmap_union(table->read_set, &table->tmp_set); if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE)) - table->file->prepare_for_insert(1); + table->file->prepare_for_modify(true, true); } } if (unlikely(error))