summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-12-23 14:52:59 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-12-23 14:52:59 +0200
commit0aa02567dd62d96467f84ba96cc67b103f63c9e0 (patch)
tree6c379b5f7d84fdb8e724907448a4f015d89881f6 /sql
parent04741dc736e803b0a91c76d19de464e25b4a1977 (diff)
parentfa1aef39ebc7d84d24d4e3d2124f982526632ee9 (diff)
downloadmariadb-git-0aa02567dd62d96467f84ba96cc67b103f63c9e0.tar.gz
Merge 10.3 into 10.4
Diffstat (limited to 'sql')
-rw-r--r--sql/opt_split.cc2
-rw-r--r--sql/sql_delete.cc10
-rw-r--r--sql/sql_insert.cc10
-rw-r--r--sql/sql_table.cc57
-rw-r--r--sql/sql_type.cc11
-rw-r--r--sql/sql_update.cc69
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> &not_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> &not_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> &not_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)))