1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge branch '11.7' into 11.8

This commit is contained in:
Sergei Golubchik
2025-02-11 20:29:43 +01:00
511 changed files with 13256 additions and 7184 deletions

View File

@ -990,8 +990,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
if (fields.elements || !value_count || table_list->view != 0)
{
if (table->triggers &&
table->triggers->has_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE))
if (table->field != table->field_to_fill())
{
/* BEFORE INSERT triggers exist, the check will be done later, per row */
}
@ -1067,7 +1066,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
INSERT INTO t1 (fields) VALUES ...
INSERT INTO t1 VALUES ()
*/
restore_record(table,s->default_values); // Get empty record
restore_default_record_for_insert(table);
table->reset_default_fields();
if (unlikely(fill_record_n_invoke_before_triggers(thd, table, fields,
@ -1097,7 +1096,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
*/
if (thd->lex->used_tables || // Column used in values()
table->s->visible_fields != table->s->fields)
restore_record(table,s->default_values); // Get empty record
restore_default_record_for_insert(table);
else
{
TABLE_SHARE *share= table->s;
@ -1137,23 +1136,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
if (trg_skip_row)
continue;
/*
with triggers a field can get a value *conditionally*, so we have to
repeat has_no_default_value() check for every row
*/
if (table->triggers &&
table->triggers->has_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE))
{
for (Field **f=table->field ; *f ; f++)
{
if (unlikely(!(*f)->has_explicit_value() &&
has_no_default_value(thd, *f, table_list)))
{
error= 1;
goto values_loop_end;
}
}
}
if ((res= table_list->view_check_option(thd, ignore)) == VIEW_CHECK_SKIP)
continue;
@ -2233,6 +2215,9 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink)
!table->file->referenced_by_foreign_key() &&
(!table->triggers || !table->triggers->has_delete_triggers()))
{
/*
Optimized dup handling via UPDATE (and insert history for versioned).
*/
if (table->versioned(VERS_TRX_ID))
{
DBUG_ASSERT(table->vers_write);
@ -2270,6 +2255,10 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink)
{
bool trg_skip_row= false;
/*
Normal dup handling via DELETE (or UPDATE to history for versioned)
and repeating the cycle of INSERT.
*/
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE, true,
@ -2279,20 +2268,30 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink)
if (trg_skip_row)
continue;
if (!table->versioned(VERS_TIMESTAMP))
bool do_delete= !table->versioned(VERS_TIMESTAMP);
if (do_delete)
error= table->file->ha_delete_row(table->record[1]);
else
{
/* Update existing row to history */
store_record(table, record[2]);
restore_record(table, record[1]);
table->vers_update_end();
error= table->file->ha_update_row(table->record[1],
table->record[0]);
restore_record(table, record[2]);
if (error == HA_ERR_FOUND_DUPP_KEY || /* Unique index, any SE */
error == HA_ERR_FOREIGN_DUPLICATE_KEY || /* Unique index, InnoDB */
error == HA_ERR_RECORD_IS_THE_SAME) /* No index */
{
/* Such history row was already generated from previous cycles */
error= table->file->ha_delete_row(table->record[1]);
do_delete= true;
}
}
if (unlikely(error))
goto err;
if (!table->versioned(VERS_TIMESTAMP))
if (do_delete)
info->deleted++;
else
info->updated++;
@ -2542,6 +2541,7 @@ public:
delayed_insert_threads--;
my_free(thd.query());
thd.reset_query_inner();
thd.security_ctx->user= 0;
thd.security_ctx->host= 0;
}
@ -2794,12 +2794,21 @@ end_create:
DBUG_RETURN(thd->is_error());
}
#define memdup_vcol(thd, vcol) \
if (vcol) \
{ \
(vcol)= (Virtual_column_info*)(thd)->memdup((vcol), sizeof(*(vcol))); \
(vcol)->expr= NULL; \
static inline
bool memdup_vcol(THD *thd, Virtual_column_info *&vcol)
{
if (vcol)
{
vcol= (Virtual_column_info*)(thd->memdup(vcol, sizeof(*vcol)));
if (!vcol)
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
return true;
}
vcol->expr= NULL;
}
return false;
}
/**
As we can't let many client threads modify the same TABLE
@ -2943,9 +2952,12 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
(*field)->move_field_offset(adjust_ptrs); // Point at copy->record[0]
(*field)->flags|= ((*org_field)->flags & LONG_UNIQUE_HASH_FIELD);
(*field)->invisible= (*org_field)->invisible;
memdup_vcol(client_thd, (*field)->vcol_info);
memdup_vcol(client_thd, (*field)->default_value);
memdup_vcol(client_thd, (*field)->check_constraint);
if (memdup_vcol(client_thd, (*field)->vcol_info))
goto error;
if (memdup_vcol(client_thd, (*field)->default_value))
goto error;
if (memdup_vcol(client_thd, (*field)->check_constraint))
goto error;
if (*org_field == found_next_number_field)
(*field)->table->found_next_number_field= *field;
}
@ -2962,6 +2974,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
&error_reported,
VCOL_INIT_DEPENDENCY_FAILURE_IS_WARNING)))
goto error;
copy->update_keypart_vcol_info();
}
switch_defaults_to_nullable_trigger_fields(copy);
@ -4194,7 +4208,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
*/
table->file->ha_start_bulk_insert((ha_rows) 0);
}
restore_record(table,s->default_values); // Get empty record
restore_default_record_for_insert(table);
table->reset_default_fields();
table->next_number_field=table->found_next_number_field;
@ -4257,6 +4271,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
int select_insert::prepare2(JOIN *)
{
DBUG_ENTER("select_insert::prepare2");
switch_to_nullable_trigger_fields(*fields, table);
if (table->validate_default_values_of_unset_fields(thd))
DBUG_RETURN(1);
if (thd->lex->describe)
@ -4275,7 +4290,7 @@ int select_insert::prepare2(JOIN *)
}
void select_insert::cleanup()
void select_insert::reset_for_next_ps_execution()
{
/* select_insert/select_create are never re-used in prepared statement */
DBUG_ASSERT(0);
@ -4339,7 +4354,7 @@ int select_insert::send_data(List<Item> &values)
originally touched by INSERT ... SELECT, so we have to restore
their original values for the next row.
*/
restore_record(table, s->default_values);
restore_default_record_for_insert(table);
}
if (table->next_number_field)
{
@ -4391,6 +4406,13 @@ bool select_insert::prepare_eof()
DBUG_PRINT("enter", ("trans_table: %d, table_type: '%s'",
trans_table, table->file->table_type()));
/****************************************************************************
NOTE: if you change here be aware that almost the same code is in
select_insert::abort_result_set().
****************************************************************************/
error= IF_WSREP(thd->wsrep_cs().current_error(), 0) ? -1 :
(thd->locked_tables_mode <= LTM_LOCK_TABLES) ?
table->file->ha_end_bulk_insert() : 0;
@ -4532,6 +4554,12 @@ void select_insert::abort_result_set()
*/
if (table && table->file->is_open())
{
/****************************************************************************
NOTE: if you change here be aware that almost the same code is in
select_insert::prepare_eof().
****************************************************************************/
bool changed, transactional_table;
/*
If we are not in prelocked mode, we end the bulk insert started
@ -4559,7 +4587,14 @@ void select_insert::abort_result_set()
If table creation failed, the number of rows modified will also be
zero, so no check for that is made.
*/
changed= (info.copied || info.deleted || info.updated);
if ((changed= (info.copied || info.deleted || info.updated)))
{
/*
We must invalidate the table in the query cache before binlog writing
and ha_autocommit_or_rollback.
*/
query_cache_invalidate3(thd, table, 1);
}
transactional_table= table->file->has_transactions_and_rollback();
if (thd->transaction->stmt.modified_non_trans_table ||
thd->log_current_statement())