diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-23 14:52:59 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-23 14:52:59 +0200 |
commit | 0aa02567dd62d96467f84ba96cc67b103f63c9e0 (patch) | |
tree | 6c379b5f7d84fdb8e724907448a4f015d89881f6 /sql | |
parent | 04741dc736e803b0a91c76d19de464e25b4a1977 (diff) | |
parent | fa1aef39ebc7d84d24d4e3d2124f982526632ee9 (diff) | |
download | mariadb-git-0aa02567dd62d96467f84ba96cc67b103f63c9e0.tar.gz |
Merge 10.3 into 10.4
Diffstat (limited to 'sql')
-rw-r--r-- | sql/opt_split.cc | 2 | ||||
-rw-r--r-- | sql/sql_delete.cc | 10 | ||||
-rw-r--r-- | sql/sql_insert.cc | 10 | ||||
-rw-r--r-- | sql/sql_table.cc | 57 | ||||
-rw-r--r-- | sql/sql_type.cc | 11 | ||||
-rw-r--r-- | sql/sql_update.cc | 69 |
6 files changed, 106 insertions, 53 deletions
diff --git a/sql/opt_split.cc b/sql/opt_split.cc index 6807a623b73..fd7836f55cc 100644 --- a/sql/opt_split.cc +++ b/sql/opt_split.cc @@ -1149,7 +1149,7 @@ bool JOIN_TAB::fix_splitting(SplM_plan_info *spl_plan, bool JOIN::fix_all_splittings_in_plan() { table_map prev_tables= 0; - table_map all_tables= (1 << table_count) - 1; + table_map all_tables= (table_map(1) << table_count) - 1; for (uint tablenr= 0; tablenr < table_count; tablenr++) { POSITION *cur_pos= &best_positions[tablenr]; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 5d006a7518c..be8767af111 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -293,7 +293,15 @@ int TABLE::delete_row() store_record(this, record[1]); vers_update_end(); - return file->ha_update_row(record[1], record[0]); + int err= file->ha_update_row(record[1], record[0]); + /* + MDEV-23644: we get HA_ERR_FOREIGN_DUPLICATE_KEY iff we already got history + row with same trx_id which is the result of foreign key action, so we + don't need one more history row. + */ + if (err == HA_ERR_FOREIGN_DUPLICATE_KEY) + return file->ha_delete_row(record[0]); + return err; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 01e5752def7..8c0e5f0c0ee 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2701,7 +2701,7 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, delayed_row *row= 0; Delayed_insert *di=thd->di; const Discrete_interval *forced_auto_inc; - size_t user_len, host_len, ip_len; + size_t user_len, host_len, ip_length; DBUG_ENTER("write_delayed"); DBUG_PRINT("enter", ("query = '%s' length %lu", query.str, (ulong) query.length)); @@ -2735,7 +2735,7 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, goto err; } - user_len= host_len= ip_len= 0; + user_len= host_len= ip_length= 0; row->user= row->host= row->ip= NULL; if (thd->security_ctx) { @@ -2744,11 +2744,11 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, if (thd->security_ctx->host) host_len= strlen(thd->security_ctx->host) + 1; if (thd->security_ctx->ip) - ip_len= strlen(thd->security_ctx->ip) + 1; + ip_length= strlen(thd->security_ctx->ip) + 1; } /* This can't be THREAD_SPECIFIC as it's freed in delayed thread */ if (!(row->record= (char*) my_malloc(table->s->reclength + - user_len + host_len + ip_len, + user_len + host_len + ip_length, MYF(MY_WME)))) goto err; memcpy(row->record, table->record[0], table->s->reclength); @@ -2768,7 +2768,7 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, if (thd->security_ctx->ip) { row->ip= row->record + table->s->reclength + user_len + host_len; - memcpy(row->ip, thd->security_ctx->ip, ip_len); + memcpy(row->ip, thd->security_ctx->ip, ip_length); } } row->query_id= thd->query_id; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6a52b7d418e..4ddfcabf6c8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2304,8 +2304,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, { bool is_trans= 0; bool table_creation_was_logged= 0; + bool real_table= FALSE; LEX_CSTRING db= table->db; handlerton *table_type= 0; + // reset error state for this table + error= 0; DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p", table->db.str, table->table_name.str, table->table, @@ -2321,9 +2324,35 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, thd->find_temporary_table(table) && table->mdl_request.ticket != NULL)); - if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table) || - (drop_sequence && table->table->s->table_type != TABLE_TYPE_SEQUENCE)) + if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table)) + real_table= TRUE; + else if (drop_sequence && + table->table->s->table_type != TABLE_TYPE_SEQUENCE) + { + was_table= (table->table->s->table_type == TABLE_TYPE_NORMAL); + was_view= (table->table->s->table_type == TABLE_TYPE_VIEW); + if (if_exists) + { + char buff[FN_REFLEN]; + String tbl_name(buff, sizeof(buff), system_charset_info); + tbl_name.length(0); + tbl_name.append(&db); + tbl_name.append('.'); + tbl_name.append(&table->table_name); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_NOT_SEQUENCE2, ER_THD(thd, ER_NOT_SEQUENCE2), + tbl_name.c_ptr_safe()); + + /* + Our job is done here. This statement was added to avoid executing + unnecessary code farther below which in some strange corner cases + caused the server to crash (see MDEV-17896). + */ + goto log_query; + } error= 1; + goto non_critical_err; + } else { table_creation_was_logged= table->table->s->table_creation_was_logged; @@ -2332,29 +2361,28 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, error= 1; goto err; } - error= 0; table->table= 0; } - if ((drop_temporary && if_exists) || !error) + if ((drop_temporary && if_exists) || !real_table) { /* This handles the case of temporary tables. We have the following cases: . "DROP TEMPORARY" was executed and a temporary table was affected - (i.e. drop_temporary && !error) or the if_exists was specified (i.e. - drop_temporary && if_exists). + (i.e. drop_temporary && !real_table) or the + if_exists was specified (i.e. drop_temporary && if_exists). . "DROP" was executed but a temporary table was affected (.i.e - !error). + !real_table). */ if (!dont_log_query && table_creation_was_logged) { /* - If there is an error, we don't know the type of the engine + If there is an real_table, we don't know the type of the engine at this point. So, we keep it in the trx-cache. */ - is_trans= error ? TRUE : is_trans; + is_trans= real_table ? TRUE : is_trans; if (is_trans) trans_tmp_table_deleted= TRUE; else @@ -2381,7 +2409,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, is no need to proceed with the code that tries to drop a regular table. */ - if (!error) continue; + if (!real_table) continue; } else if (!drop_temporary) { @@ -2397,7 +2425,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, reg_ext, 0); } DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table"); - error= 0; if (drop_temporary || (ha_table_exists(thd, &db, &alias, &table_type, &is_sequence) == 0 && table_type == 0) || @@ -2437,6 +2464,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, { non_tmp_error = (drop_temporary ? non_tmp_error : TRUE); error= 1; + /* + non critical error (only for this table), so we continue. + Next we write it to wrong_tables and continue this loop + The same as "goto non_critical_err". + */ } } else @@ -2530,7 +2562,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, } non_tmp_error|= MY_TEST(error); } - +non_critical_err: if (error) { if (wrong_tables.length()) @@ -10031,6 +10063,7 @@ do_continue:; tmp_disable_binlog(thd); create_info->options|=HA_CREATE_TMP_ALTER; + create_info->alias= alter_ctx.table_name; error= create_table_impl(thd, alter_ctx.db, alter_ctx.table_name, alter_ctx.new_db, alter_ctx.tmp_name, alter_ctx.get_tmp_path(), diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 36f128a3a0b..7dea9cdea4a 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -8633,11 +8633,18 @@ LEX_CSTRING Charset::collation_specific_name() const for character sets and collations, so a collation name not necessarily starts with the character set name. */ + LEX_CSTRING retval; size_t csname_length= strlen(m_charset->csname); if (strncmp(m_charset->name, m_charset->csname, csname_length)) - return {NULL, 0}; + { + retval.str= NULL; + retval.length= 0; + return retval; + } const char *ptr= m_charset->name + csname_length; - return {ptr, strlen(ptr) }; + retval.str= ptr; + retval.length= strlen(ptr); + return retval; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 9514b193407..367682c74e9 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -52,8 +52,9 @@ compare_record(TABLE*). */ bool records_are_comparable(const TABLE *table) { - return ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) == 0) || - bitmap_is_subset(table->write_set, table->read_set); + return !table->versioned(VERS_TRX_ID) && + (((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) == 0) || + bitmap_is_subset(table->write_set, table->read_set)); } @@ -1081,20 +1082,9 @@ update_begin: } else if (likely(!error)) { - if (has_vers_fields && table->versioned()) - { - if (table->versioned(VERS_TIMESTAMP)) - { - store_record(table, record[2]); - table->mark_columns_per_binlog_row_image(); - error= vers_insert_history_row(table); - restore_record(table, record[2]); - } - if (likely(!error)) - rows_inserted++; - } - if (likely(!error)) - updated++; + if (has_vers_fields && table->versioned(VERS_TRX_ID)) + rows_inserted++; + updated++; } if (likely(!error) && !record_was_same && table_list->has_period()) @@ -1110,6 +1100,19 @@ update_begin: if (unlikely(error) && (!ignore || table->file->is_fatal_error(error, HA_CHECK_ALL))) { + goto error; + } + } + + if (likely(!error) && has_vers_fields && table->versioned(VERS_TIMESTAMP)) + { + store_record(table, record[2]); + table->mark_columns_per_binlog_row_image(); + error= vers_insert_history_row(table); + restore_record(table, record[2]); + if (unlikely(error)) + { +error: /* If (ignore && error is ignorable) we don't have to do anything; otherwise... @@ -1120,10 +1123,11 @@ update_begin: flags|= ME_FATAL; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); - table->file->print_error(error,MYF(flags)); - error= 1; - break; - } + table->file->print_error(error,MYF(flags)); + error= 1; + break; + } + rows_inserted++; } if (table->triggers && @@ -2548,6 +2552,7 @@ int multi_update::send_data(List<Item> ¬_used_values) if (!ignore || table->file->is_fatal_error(error, HA_CHECK_ALL)) { +error: /* If (ignore && error == is ignorable) we don't have to do anything; otherwise... @@ -2569,19 +2574,8 @@ int multi_update::send_data(List<Item> ¬_used_values) error= 0; updated--; } - else if (has_vers_fields && table->versioned()) + else if (has_vers_fields && table->versioned(VERS_TRX_ID)) { - if (table->versioned(VERS_TIMESTAMP)) - { - store_record(table, record[2]); - if (vers_insert_history_row(table)) - { - restore_record(table, record[2]); - error= 1; - break; - } - restore_record(table, record[2]); - } updated_sys_ver++; } /* non-transactional or transactional table got modified */ @@ -2595,6 +2589,17 @@ int multi_update::send_data(List<Item> ¬_used_values) } } } + if (has_vers_fields && table->versioned(VERS_TIMESTAMP)) + { + store_record(table, record[2]); + if (vers_insert_history_row(table)) + { + restore_record(table, record[2]); + goto error; + } + restore_record(table, record[2]); + updated_sys_ver++; + } if (table->triggers && unlikely(table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE))) |