MySQL 8.4.0
Source Code Documentation
sql_update.cc File Reference
#include "sql/sql_update.h"
#include <algorithm>
#include <atomic>
#include <bit>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <memory>
#include <utility>
#include "field_types.h"
#include "lex_string.h"
#include "mem_root_deque.h"
#include "my_alloc.h"
#include "my_base.h"
#include "my_bitmap.h"
#include "my_dbug.h"
#include "my_inttypes.h"
#include "my_io.h"
#include "my_sys.h"
#include "my_table_map.h"
#include "mysql/components/services/bits/psi_bits.h"
#include "mysql/service_mysql_alloc.h"
#include "mysql/strings/m_ctype.h"
#include "mysql_com.h"
#include "mysqld_error.h"
#include "prealloced_array.h"
#include "scope_guard.h"
#include "sql/auth/auth_acls.h"
#include "sql/auth/auth_common.h"
#include "sql/binlog.h"
#include "sql/debug_sync.h"
#include "sql/derror.h"
#include "sql/field.h"
#include "sql/filesort.h"
#include "sql/handler.h"
#include "sql/item.h"
#include "sql/item_json_func.h"
#include "sql/item_subselect.h"
#include "sql/iterators/basic_row_iterators.h"
#include "sql/iterators/row_iterator.h"
#include "sql/iterators/timing_iterator.h"
#include "sql/iterators/update_rows_iterator.h"
#include "sql/join_optimizer/access_path.h"
#include "sql/join_optimizer/bit_utils.h"
#include "sql/join_optimizer/walk_access_paths.h"
#include "sql/key.h"
#include "sql/key_spec.h"
#include "sql/locked_tables_list.h"
#include "sql/mdl.h"
#include "sql/mem_root_array.h"
#include "sql/mysqld.h"
#include "sql/opt_explain.h"
#include "sql/opt_explain_format.h"
#include "sql/opt_trace.h"
#include "sql/opt_trace_context.h"
#include "sql/parse_tree_node_base.h"
#include "sql/partition_info.h"
#include "sql/protocol.h"
#include "sql/psi_memory_key.h"
#include "sql/query_options.h"
#include "sql/range_optimizer/partition_pruning.h"
#include "sql/range_optimizer/path_helpers.h"
#include "sql/range_optimizer/range_optimizer.h"
#include "sql/select_lex_visitor.h"
#include "sql/sql_array.h"
#include "sql/sql_base.h"
#include "sql/sql_bitmap.h"
#include "sql/sql_class.h"
#include "sql/sql_const.h"
#include "sql/sql_data_change.h"
#include "sql/sql_delete.h"
#include "sql/sql_error.h"
#include "sql/sql_executor.h"
#include "sql/sql_lex.h"
#include "sql/sql_list.h"
#include "sql/sql_opt_exec_shared.h"
#include "sql/sql_optimizer.h"
#include "sql/sql_partition.h"
#include "sql/sql_resolver.h"
#include "sql/sql_select.h"
#include "sql/sql_tmp_table.h"
#include "sql/sql_view.h"
#include "sql/system_variables.h"
#include "sql/table.h"
#include "sql/table_trigger_dispatcher.h"
#include "sql/temp_table_param.h"
#include "sql/thd_raii.h"
#include "sql/transaction_info.h"
#include "sql/trigger_chain.h"
#include "sql/trigger_def.h"
#include "sql/visible_fields.h"
#include "template_utils.h"
#include "thr_lock.h"

Functions

static bool prepare_partial_update (Opt_trace_context *trace, const mem_root_deque< Item * > &fields, const mem_root_deque< Item * > &values)
 Mark the columns that can possibly be updated in-place using partial update. More...
 
bool records_are_comparable (const TABLE *table)
 True if the table's input and output record buffers are comparable using compare_records(TABLE*). More...
 
bool compare_records (const TABLE *table)
 Compares the input and output record buffers of the table to see if a row has changed. More...
 
static bool check_constant_expressions (const mem_root_deque< Item * > &values)
 Check if all expressions in list are constant expressions. More...
 
static table_map get_table_map (const mem_root_deque< Item * > &items)
 
static TABLEGetOutermostTable (const JOIN *join)
 Returns the outermost (leftmost) table of a join. More...
 
static bool unsafe_key_update (Table_ref *leaves, table_map tables_for_update)
 If one row is updated through two different aliases and the first update physically moves the row, the second update will error because the row is no longer located where expected. More...
 
static bool has_json_columns (const mem_root_deque< Item * > &items)
 Check if a list of Items contains an Item whose type is JSON. More...
 
bool should_switch_to_multi_table_if_subqueries (const THD *thd, const Query_block *qb, const Table_ref *table_list)
 Decides if a single-table UPDATE/DELETE statement should switch to the multi-table code path, if there are subqueries which might benefit from semijoin or subquery materialization, and if no feature specific to the single-table path are used. More...
 
static void CollectColumnsReferencedInJoinConditions (const JOIN *join, const Table_ref *table_ref)
 
static bool safe_update_on_fly (const QEP_TAB *join_tab, const Table_ref *table_ref, Table_ref *all_tables)
 Check if table is safe to update on the fly. More...
 
static bool AddRowIdAsTempTableField (THD *thd, TABLE *table, mem_root_deque< Item * > *fields)
 Adds a field for storing row IDs from "table" to "fields". More...
 
static void StoreRowId (TABLE *table, TABLE *tmp_table, int field_num, table_map hash_join_tables)
 Stores the current row ID of "table" in the specified field of "tmp_table". More...
 
static bool PositionScanOnRow (TABLE *updated_table, TABLE *table, TABLE *tmp_table, int field_num)
 Position the scan of "table" using the row ID stored in the specified field of "tmp_table". More...
 
table_map GetImmediateUpdateTable (const JOIN *join, bool single_target)
 Find out which of the target tables can be updated immediately while scanning. More...
 
bool FinalizeOptimizationForUpdate (JOIN *join)
 Makes the TABLE and handler objects ready for being used in an UPDATE statement. More...
 
unique_ptr_destroy_only< RowIteratorCreateUpdateRowsIterator (THD *thd, MEM_ROOT *mem_root, JOIN *join, unique_ptr_destroy_only< RowIterator > source)
 Creates an UpdateRowsIterator which updates the rows returned by the given "source" iterator. More...
 

Function Documentation

◆ AddRowIdAsTempTableField()

static bool AddRowIdAsTempTableField ( THD thd,
TABLE table,
mem_root_deque< Item * > *  fields 
)
static

Adds a field for storing row IDs from "table" to "fields".

◆ check_constant_expressions()

static bool check_constant_expressions ( const mem_root_deque< Item * > &  values)
static

Check if all expressions in list are constant expressions.

Parameters
[in]valuesList of expressions
Return values
trueOnly constant expressions
falseAt least one non-constant expression

◆ CollectColumnsReferencedInJoinConditions()

static void CollectColumnsReferencedInJoinConditions ( const JOIN join,
const Table_ref table_ref 
)
static

◆ compare_records()

bool compare_records ( const TABLE table)

Compares the input and output record buffers of the table to see if a row has changed.

The algorithm iterates over updated columns and if they are nullable compares NULL bits in the buffer before comparing actual data. Special care must be taken to compare only the relevant NULL bits and mask out all others as they may be undefined. The storage engine will not and should not touch them.

Parameters
tableThe table to evaluate.
Returns
true if row has changed.
false otherwise.

◆ CreateUpdateRowsIterator()

unique_ptr_destroy_only< RowIterator > CreateUpdateRowsIterator ( THD thd,
MEM_ROOT mem_root,
JOIN join,
unique_ptr_destroy_only< RowIterator source 
)

Creates an UpdateRowsIterator which updates the rows returned by the given "source" iterator.

◆ FinalizeOptimizationForUpdate()

bool FinalizeOptimizationForUpdate ( JOIN join)

Makes the TABLE and handler objects ready for being used in an UPDATE statement.

Called at the beginning of each execution.

Parameters
joinThe top-level JOIN object of the UPDATE operation.
Returns
true on error.

◆ get_table_map()

static table_map get_table_map ( const mem_root_deque< Item * > &  items)
static

◆ GetImmediateUpdateTable()

table_map GetImmediateUpdateTable ( const JOIN join,
bool  single_target 
)

Find out which of the target tables can be updated immediately while scanning.

This is used by the old optimizer after the plan has been created. The hypergraph optimizer does not use this function, as it makes the decision about immediate update during planning, not after planning.

Parameters
joinThe top-level JOIN object of the UPDATE statement.
single_targetTrue if the UPDATE statement has exactly one target table.
Returns
Map of tables to update while scanning.

◆ GetOutermostTable()

static TABLE * GetOutermostTable ( const JOIN join)
static

Returns the outermost (leftmost) table of a join.

◆ has_json_columns()

static bool has_json_columns ( const mem_root_deque< Item * > &  items)
static

Check if a list of Items contains an Item whose type is JSON.

◆ PositionScanOnRow()

static bool PositionScanOnRow ( TABLE updated_table,
TABLE table,
TABLE tmp_table,
int  field_num 
)
static

Position the scan of "table" using the row ID stored in the specified field of "tmp_table".

Parameters
updated_tableThe table that is being updated.
tableThe table to position on a given row.
tmp_tableThe temporary table that holds the row ID.
field_numThe field of tmp_table that holds the row ID.
Returns
True on error.

◆ prepare_partial_update()

static bool prepare_partial_update ( Opt_trace_context trace,
const mem_root_deque< Item * > &  fields,
const mem_root_deque< Item * > &  values 
)
static

Mark the columns that can possibly be updated in-place using partial update.

Only JSON columns can be updated in-place, and only if all the updates of the column are on the form

json_col = JSON_SET(json_col, ...)

json_col = JSON_REPLACE(json_col, ...)

json_col = JSON_REMOVE(json_col, ...)

Even though a column is marked for partial update, it is not necessarily updated as a partial update during execution. It depends on the actual data in the column if it is possible to do it as a partial update. Also, for multi-table updates, it is only possible to perform partial updates in the first table of the join operation, and it is not determined until later (in Query_result_update::optimize()) which table it is.

Parameters
tracethe optimizer trace context
fieldsthe fields that are updated by the update statement
valuesthe values they are updated to
Returns
false on success, true on error

◆ records_are_comparable()

bool records_are_comparable ( const TABLE table)

True if the table's input and output record buffers are comparable using compare_records(TABLE*).

◆ safe_update_on_fly()

static bool safe_update_on_fly ( const QEP_TAB join_tab,
const Table_ref table_ref,
Table_ref all_tables 
)
static

Check if table is safe to update on the fly.

Parameters
join_tabTable (always the first one in the JOIN plan)
table_refTable reference for 'join_tab'
all_tablesList of tables (updated or not)

We can update the first table in join on the fly if we know that:

  • a row in this table will never be read twice (that depends, among other things, on the access method), and
  • updating this row won't influence the selection of rows in next tables.

This function gets information about fields to be updated from the TABLE::write_set bitmap. And it gets information about which fields influence the selection of rows in next tables, from the TABLE::tmp_set bitmap.

Returns
true if it is safe to update on the fly.

◆ should_switch_to_multi_table_if_subqueries()

bool should_switch_to_multi_table_if_subqueries ( const THD thd,
const Query_block qb,
const Table_ref table_list 
)

Decides if a single-table UPDATE/DELETE statement should switch to the multi-table code path, if there are subqueries which might benefit from semijoin or subquery materialization, and if no feature specific to the single-table path are used.

Parameters
thdThread handler
qbQuery block
table_listTable to modify
Returns
true if we should switch

◆ StoreRowId()

static void StoreRowId ( TABLE table,
TABLE tmp_table,
int  field_num,
table_map  hash_join_tables 
)
static

Stores the current row ID of "table" in the specified field of "tmp_table".

Parameters
tableThe table to get a row ID from.
tmp_tableThe temporary table in which to store the row ID.
field_numThe field of tmp_table in which to store the row ID.
hash_join_tablesA map of all tables that are part of a hash join.

◆ unsafe_key_update()

static bool unsafe_key_update ( Table_ref leaves,
table_map  tables_for_update 
)
static

If one row is updated through two different aliases and the first update physically moves the row, the second update will error because the row is no longer located where expected.

This function checks if the multiple-table update is about to do that and if so returns with an error.

The following update operations physically moves rows: 1) Update of a column in a clustered primary key 2) Update of a column used to calculate which partition the row belongs to

This function returns with an error if both of the following are true:

a) A table in the multiple-table update statement is updated through multiple aliases (including views) b) At least one of the updates on the table from a) may physically moves the row. Note: Updating a column used to calculate which partition a row belongs to does not necessarily mean that the row is moved. The new value may or may not belong to the same partition.

Parameters
leavesFirst leaf table
tables_for_updateMap of tables that are updated
Returns
true if the update is unsafe, in which case an error message is also set, false otherwise.