MySQL 8.4.1
Source Code Documentation
row0sel.cc File Reference

Select. More...

#include "row0sel.h"
#include <sys/types.h>
#include "btr0btr.h"
#include "btr0cur.h"
#include "btr0sea.h"
#include "buf0lru.h"
#include "dict0boot.h"
#include "dict0dd.h"
#include "dict0dict.h"
#include "eval0eval.h"
#include "gis0rtree.h"
#include "ha_innodb.h"
#include "ha_prototypes.h"
#include "handler.h"
#include "lob0lob.h"
#include "lob0undo.h"
#include "lock0lock.h"
#include "mach0data.h"
#include "pars0pars.h"
#include "pars0sym.h"
#include "que0que.h"
#include "read0read.h"
#include "record_buffer.h"
#include "rem0cmp.h"
#include "row0mysql.h"
#include "row0row.h"
#include "row0upd.h"
#include "row0vers.h"
#include "srv0mon.h"
#include "trx0trx.h"
#include "trx0undo.h"
#include "ut0new.h"
#include "my_dbug.h"

Classes

class  Row_sel_get_clust_rec_for_mysql
 Helper class to cache clust_rec and old_ver. More...
 
struct  row_to_range_relation_t
 The return type of row_compare_row_to_range() which summarizes information about the relation between the row being processed, and the range of the scan. More...
 

Functions

static bool row_sel_sec_rec_is_for_blob (trx_t *trx, ulint mtype, ulint prtype, ulint mbminmaxlen, const byte *clust_field, ulint clust_len, const byte *sec_field, ulint sec_len, ulint prefix_len, dict_table_t *table)
 Returns true if the user-defined column in a secondary index record is alphabetically the same as the corresponding BLOB column in the clustered index record. More...
 
static dberr_t row_sel_sec_rec_is_for_clust_rec (const rec_t *sec_rec, dict_index_t *sec_index, const rec_t *clust_rec, dict_index_t *clust_index, que_thr_t *thr, bool &is_equal)
 Returns true if the user-defined column values in a secondary index record are alphabetically the same as the corresponding columns in the clustered index record. More...
 
sel_node_tsel_node_create (mem_heap_t *heap)
 Creates a select node struct. More...
 
void sel_node_free_private (sel_node_t *node)
 Frees the memory private to a select node when a query graph is freed, does not free the heap where the node was originally created. More...
 
static void sel_eval_select_list (sel_node_t *node)
 Evaluates the values in a select list. More...
 
static void sel_assign_into_var_values (sym_node_t *var, sel_node_t *node)
 Assigns the values in the select list to the possible into-variables in SELECT ... INTO ... More...
 
static void sel_reset_aggregate_vals (sel_node_t *node)
 Resets the aggregate value totals in the select list of an aggregate type query. More...
 
static void row_sel_copy_input_variable_vals (sel_node_t *node)
 Copies the input variable values when an explicit cursor is opened. More...
 
static void row_sel_fetch_columns (trx_t *trx, dict_index_t *index, const rec_t *rec, const ulint *offsets, sym_node_t *column, bool allow_null_lob=false)
 Fetches the column values from a record. More...
 
static void sel_col_prefetch_buf_alloc (sym_node_t *column)
 Allocates a prefetch buffer for a column when prefetch is first time done. More...
 
void sel_col_prefetch_buf_free (sel_buf_t *prefetch_buf)
 Frees a prefetch buffer for a column, including the dynamically allocated memory for data stored there. More...
 
static void sel_dequeue_prefetched_row (plan_t *plan)
 Pops the column values for a prefetched, cached row from the column prefetch buffers and places them to the val fields in the column nodes. More...
 
static void sel_enqueue_prefetched_row (plan_t *plan)
 Pushes the column values for a prefetched, cached row to the column prefetch buffers from the val fields in the column nodes. More...
 
static dberr_t row_sel_build_prev_vers (ReadView *read_view, dict_index_t *index, rec_t *rec, ulint **offsets, mem_heap_t **offset_heap, mem_heap_t **old_vers_heap, rec_t **old_vers, mtr_t *mtr)
 Builds a previous version of a clustered index record for a consistent read. More...
 
static void row_sel_build_committed_vers_for_mysql (dict_index_t *clust_index, row_prebuilt_t *prebuilt, const rec_t *rec, ulint **offsets, mem_heap_t **offset_heap, const rec_t **old_vers, const dtuple_t **vrow, mtr_t *mtr)
 Builds the last committed version of a clustered index record for a semi-consistent read. More...
 
static bool row_sel_test_end_conds (plan_t *plan)
 Tests the conditions which determine when the index segment we are searching through has been exhausted. More...
 
static bool row_sel_test_other_conds (plan_t *plan)
 Tests the other conditions. More...
 
static dberr_t row_sel_get_clust_rec (sel_node_t *node, plan_t *plan, rec_t *rec, que_thr_t *thr, rec_t **out_rec, mtr_t *mtr)
 Retrieves the clustered index record corresponding to a record in a non-clustered index. More...
 
static dberr_t sel_set_rtr_rec_lock (btr_pcur_t *pcur, const rec_t *first_rec, dict_index_t *index, const ulint *offsets, select_mode sel_mode, ulint mode, ulint type, que_thr_t *thr, mtr_t *mtr)
 Sets a lock on a page of R-Tree record. More...
 
static dberr_t sel_set_rec_lock (btr_pcur_t *pcur, const rec_t *rec, dict_index_t *index, const ulint *offsets, select_mode sel_mode, ulint mode, ulint type, que_thr_t *thr, mtr_t *mtr)
 Sets a lock on a record. More...
 
static void row_sel_open_pcur (plan_t *plan, bool search_latch_locked, mtr_t *mtr)
 Opens a pcur to a table index. More...
 
static bool row_sel_restore_pcur_pos (plan_t *plan, mtr_t *mtr)
 Restores a stored pcur position to a table index. More...
 
static void plan_reset_cursor (plan_t *plan)
 Resets a plan cursor to a closed state. More...
 
static ulint row_sel_try_search_shortcut (trx_t *trx, sel_node_t *node, plan_t *plan, bool search_latch_locked, mtr_t *mtr)
 Tries to do a shortcut to fetch a clustered index record with a unique key, using the hash index if possible (not always). More...
 
static dberr_t row_sel (sel_node_t *node, que_thr_t *thr)
 Performs a select step. More...
 
que_thr_trow_sel_step (que_thr_t *thr)
 Performs a select step. More...
 
que_thr_tfetch_step (que_thr_t *thr)
 Performs a fetch for a cursor. More...
 
void row_sel_convert_mysql_key_to_innobase (dtuple_t *tuple, byte *buf, ulint buf_len, dict_index_t *index, const byte *key_ptr, ulint key_len)
 Converts a key value stored in MySQL format to an Innobase dtuple. More...
 
static void row_sel_store_row_id_to_prebuilt (row_prebuilt_t *prebuilt, const rec_t *index_rec, const dict_index_t *index, const ulint *offsets)
 Stores the row id to the prebuilt struct. More...
 
void row_sel_field_store_in_mysql_format_func (byte *dest, const mysql_row_templ_t *templ, const dict_index_t *index, ulint field_no, const byte *data, ulint len, ulint sec_field)
 Stores a non-SQL-NULL field in the MySQL format. More...
 
static bool row_sel_store_mysql_field (byte *mysql_rec, row_prebuilt_t *prebuilt, const rec_t *rec, const dict_index_t *rec_index, const dict_index_t *prebuilt_index, const ulint *offsets, ulint field_no, const mysql_row_templ_t *templ, ulint sec_field_no, lob::undo_vers_t *lob_undo, mem_heap_t *&blob_heap)
 Convert a field in the Innobase format to a field in the MySQL format. More...
 
bool row_sel_store_mysql_rec (byte *mysql_rec, row_prebuilt_t *prebuilt, const rec_t *rec, const dtuple_t *vrow, bool rec_clust, const dict_index_t *rec_index, const dict_index_t *prebuilt_index, const ulint *offsets, bool clust_templ_for_sec, lob::undo_vers_t *lob_undo, mem_heap_t *&blob_heap)
 Convert a row in the Innobase format to a row in the MySQL format. More...
 
static dberr_t row_sel_build_prev_vers_for_mysql (ReadView *read_view, dict_index_t *clust_index, row_prebuilt_t *prebuilt, const rec_t *rec, ulint **offsets, mem_heap_t **offset_heap, rec_t **old_vers, const dtuple_t **vrow, mtr_t *mtr, lob::undo_vers_t *lob_undo)
 Builds a previous version of a clustered index record for a consistent read. More...
 
static bool sel_restore_position_for_mysql (bool *same_user_rec, ulint latch_mode, btr_pcur_t *pcur, bool moves_up, mtr_t *mtr)
 Restores cursor position after it has been stored. More...
 
static void row_sel_copy_cached_field_for_mysql (byte *buf, const byte *cache, const mysql_row_templ_t *templ)
 Copies a cached field for MySQL from the fetch cache. More...
 
void row_sel_copy_cached_fields_for_mysql (byte *buf, const byte *cached_rec, row_prebuilt_t *prebuilt)
 Copy used fields from cached row. More...
 
static Record_bufferrow_sel_get_record_buffer (const row_prebuilt_t *prebuilt)
 Get the record buffer provided by the server, if there is one. More...
 
static void row_sel_dequeue_cached_row_for_mysql (byte *buf, row_prebuilt_t *prebuilt)
 Pops a cached row for MySQL from the fetch cache. More...
 
static void row_sel_prefetch_cache_init (row_prebuilt_t *prebuilt)
 Initialise the prefetch cache. More...
 
static byterow_sel_fetch_last_buf (row_prebuilt_t *prebuilt)
 Get the last fetch cache buffer from the queue. More...
 
static void row_sel_enqueue_cache_row_for_mysql (byte *mysql_rec, row_prebuilt_t *prebuilt)
 Pushes a row for MySQL to the fetch cache. More...
 
static ulint row_sel_try_search_shortcut_for_mysql (const rec_t **out_rec, row_prebuilt_t *prebuilt, ulint **offsets, mem_heap_t **heap, mtr_t *mtr)
 Tries to do a shortcut to fetch a clustered index record with a unique key, using the hash index if possible (not always). More...
 
static ICP_RESULT row_search_idx_cond_check (byte *mysql_rec, row_prebuilt_t *prebuilt, const rec_t *rec, const ulint *offsets)
 Check a pushed-down index condition. More...
 
static bool row_search_end_range_check (byte *mysql_rec, const rec_t *rec, row_prebuilt_t *prebuilt, bool clust_templ_for_sec, const ulint *offsets, Record_buffer *record_buffer)
 Check the pushed-down end-range condition to avoid extra traversal if records are not with in view and also to avoid prefetching too many records into the record buffer. More...
 
static dberr_t row_search_traverse (bool moves_up, ulint match_mode, btr_pcur_t *pcur, mtr_t *mtr)
 Traverse to next/previous record. More...
 
dberr_t row_search_no_mvcc (byte *buf, page_cur_mode_t mode, row_prebuilt_t *prebuilt, ulint match_mode, ulint direction)
 Searches for rows in the database using cursor. More...
 
static void row_sel_fill_vrow (const rec_t *rec, dict_index_t *index, const dtuple_t **vrow, mem_heap_t *heap)
 Extract virtual column data from a virtual index record and fill a dtuple. More...
 
static row_to_range_relation_t row_compare_row_to_range (const bool set_also_gap_locks, const trx_t *const trx, const bool unique_search, const dict_index_t *const index, const dict_index_t *const clust_index, const rec_t *const rec, const bool comp, const page_cur_mode_t mode, const ulint direction, const dtuple_t *search_tuple, const ulint *const offsets, const bool moves_up, const row_prebuilt_t *const prebuilt)
 A helper function extracted from row_search_mvcc() which compares the row being processed with the range of the scan. More...
 
static rec_trow_search_debug_copy_rec_order_prefix (const btr_pcur_t *pcur, const dict_index_t *index, const rec_t *rec, ulint *n_fields, byte **buf, size_t *buf_size)
 If the record is not old version, copies an initial segment of a physical record to be compared later for debug assertion code. More...
 
dberr_t row_search_mvcc (byte *buf, page_cur_mode_t mode, row_prebuilt_t *prebuilt, ulint match_mode, const ulint direction)
 Searches for rows in the database using cursor. More...
 
dberr_t row_count_rtree_recs (row_prebuilt_t *prebuilt, ulint *n_rows, ulint *n_dups)
 Count rows in a R-Tree leaf level. More...
 
static uint64_t row_search_autoinc_read_column (dict_index_t *index, const rec_t *rec, ulint col_no, ulint mtype, bool unsigned_type)
 Read the AUTOINC column from the current row. More...
 
static const rec_trow_search_get_max_rec (dict_index_t *index, mtr_t *mtr)
 Get the maximum and non-delete-marked record in an index. More...
 
dberr_t row_search_max_autoinc (dict_index_t *index, const char *col_name, uint64_t *value)
 Read the max AUTOINC value from an index. More...
 
static void convert_to_table_stats_record (rec_t *clust_rec, dict_index_t *clust_index, ulint *clust_offsets, TableStatsRecord &tbl_stats)
 Convert the innodb_table_stats clustered index record to table_stats format. More...
 
bool row_search_table_stats (const char *db_name, const char *tbl_name, TableStatsRecord &table_stats)
 Search the record present in innodb_table_stats table using db_name, table_name and fill it in table stats structure. More...
 
bool row_search_index_stats (const char *db_name, const char *tbl_name, const char *index_name, ulint col_offset, ulonglong *cardinality)
 Search the record present in innodb_index_stats using db_name, table name and index_name and fill the cardinality for the each column. More...
 

Variables

constexpr uint32_t SEL_MAX_N_PREFETCH = 16
 Maximum number of rows to prefetch; MySQL interface has another parameter. More...
 
constexpr uint32_t SEL_PREFETCH_LIMIT = 1
 Number of rows fetched, after which to start prefetching; MySQL interface has another parameter. More...
 
constexpr uint32_t SEL_COST_LIMIT = 100
 When a select has accessed about this many pages, it returns control back to que_run_threads: this is to allow canceling runaway queries. More...
 
constexpr uint32_t SEL_FOUND = 0
 Flags for search shortcut. More...
 
constexpr uint32_t SEL_EXHAUSTED = 1
 
constexpr uint32_t SEL_RETRY = 2
 

Detailed Description

Select.

Created 12/19/1997 Heikki Tuuri

Function Documentation

◆ convert_to_table_stats_record()

static void convert_to_table_stats_record ( rec_t clust_rec,
dict_index_t clust_index,
ulint clust_offsets,
TableStatsRecord tbl_stats 
)
static

Convert the innodb_table_stats clustered index record to table_stats format.

Parameters
[in]clust_recclustered index record
[in]clust_indexclustered index
[in]clust_offsetsoffsets of the clustered index record
[out]tbl_statstable_stats information to be filled.

◆ fetch_step()

que_thr_t * fetch_step ( que_thr_t thr)

Performs a fetch for a cursor.

Returns
query thread to run next or NULL
Parameters
thrin: query thread

◆ plan_reset_cursor()

static void plan_reset_cursor ( plan_t plan)
inlinestatic

Resets a plan cursor to a closed state.

Parameters
planin: plan

◆ row_compare_row_to_range()

static row_to_range_relation_t row_compare_row_to_range ( const bool  set_also_gap_locks,
const trx_t *const  trx,
const bool  unique_search,
const dict_index_t *const  index,
const dict_index_t *const  clust_index,
const rec_t *const  rec,
const bool  comp,
const page_cur_mode_t  mode,
const ulint  direction,
const dtuple_t search_tuple,
const ulint *const  offsets,
const bool  moves_up,
const row_prebuilt_t *const  prebuilt 
)
static

A helper function extracted from row_search_mvcc() which compares the row being processed with the range of the scan.

It does not modify any of it's arguments and returns a summary of situation. All the arguments are named the same way as local variables at place of call, and have same values.

◆ row_count_rtree_recs()

dberr_t row_count_rtree_recs ( row_prebuilt_t prebuilt,
ulint n_rows,
ulint n_dups 
)

Count rows in a R-Tree leaf level.

Returns
DB_SUCCESS if successful
Parameters
prebuiltin: prebuilt struct for the table handle; this contains the info of search_tuple, index; if search tuple contains 0 fields then we position the cursor at the start or the end of the index, depending on 'mode'
n_rowsout: number of entries seen in the consistent read
n_dupsout: number of dup entries

◆ row_search_autoinc_read_column()

static uint64_t row_search_autoinc_read_column ( dict_index_t index,
const rec_t rec,
ulint  col_no,
ulint  mtype,
bool  unsigned_type 
)
static

Read the AUTOINC column from the current row.

If the value is less than 0 and the type is not unsigned then we reset the value to 0.

Returns
value read from the column
Parameters
indexin: index to read from
recin: current rec
col_noin: column number
mtypein: column main type
unsigned_typein: signed or unsigned flag

◆ row_search_debug_copy_rec_order_prefix()

static rec_t * row_search_debug_copy_rec_order_prefix ( const btr_pcur_t pcur,
const dict_index_t index,
const rec_t rec,
ulint n_fields,
byte **  buf,
size_t *  buf_size 
)
inlinestatic

If the record is not old version, copies an initial segment of a physical record to be compared later for debug assertion code.

Parameters
[in]pcurcursor whose position has been stored
[in]indexindex
[in]recrecord for which to copy prefix
[out]n_fieldsnumber of fields copied
[in,out]bufmemory buffer for the copied prefix, or nullptr
[in,out]buf_sizebuffer size
Returns
pointer to the prefix record if not old version. or nullptr if old

◆ row_search_end_range_check()

static bool row_search_end_range_check ( byte mysql_rec,
const rec_t rec,
row_prebuilt_t prebuilt,
bool  clust_templ_for_sec,
const ulint offsets,
Record_buffer record_buffer 
)
static

Check the pushed-down end-range condition to avoid extra traversal if records are not with in view and also to avoid prefetching too many records into the record buffer.

Parameters
[in]mysql_recrecord in MySQL format
[in]recInnoDB record
[in]prebuiltprebuilt struct
[in]clust_templ_for_sectrue if rec belongs to the secondary index but the prebuilt template is in clustered index format
[in]offsetsinformation about column offsets in the secondary index, if virtual columns need to be copied into mysql_rec
[in,out]record_bufferthe record buffer we are reading into, or nullptr if there is no buffer
Return values
trueif the row in mysql_rec is out of range
falseif the row in mysql_rec is in range

◆ row_search_get_max_rec()

static const rec_t * row_search_get_max_rec ( dict_index_t index,
mtr_t mtr 
)
static

Get the maximum and non-delete-marked record in an index.

Parameters
[in]indexIndex tree
[in,out]mtrMini-transaction (may be committed and restarted)
Returns
maximum record, page s-latched in mtr
Return values
NULLif there are no records, or if all of them are delete-marked

◆ row_search_idx_cond_check()

static ICP_RESULT row_search_idx_cond_check ( byte mysql_rec,
row_prebuilt_t prebuilt,
const rec_t rec,
const ulint offsets 
)
static

Check a pushed-down index condition.

Returns
ICP_NO_MATCH, ICP_MATCH, or ICP_OUT_OF_RANGE
Parameters
mysql_recout: record in MySQL format (invalid unless prebuilt->idx_cond == true and we return ICP_MATCH)
prebuiltin/out: prebuilt struct for the table handle
recin: InnoDB record
offsetsin: rec_get_offsets()

◆ row_search_index_stats()

bool row_search_index_stats ( const char *  db_name,
const char *  tbl_name,
const char *  index_name,
ulint  col_offset,
ulonglong cardinality 
)

Search the record present in innodb_index_stats using db_name, table name and index_name and fill the cardinality for the each column.

Parameters
[in]db_namedatabase name
[in]tbl_nametable name
[in]index_nameindex name
[in]col_offsetoffset of the column in the index
[out]cardinalitycardinality of the column.
Returns
true if successful else false.

Number of fields to search in the table.

Column number of innodb_index_stats.database_name.

Column number of innodb_index_stats.table_name.

Column number of innodb_index_stats.index_name.

Column number of innodb_index_stats.stat_value.

Search the innodb_index_stats table using (database_name, table_name, index_name).

◆ row_search_max_autoinc()

dberr_t row_search_max_autoinc ( dict_index_t index,
const char *  col_name,
uint64_t *  value 
)

Read the max AUTOINC value from an index.

Returns
DB_SUCCESS if all OK else error code, DB_RECORD_NOT_FOUND if column name can't be found in index
Parameters
indexin: index to search
col_namein: name of autoinc column
valueout: AUTOINC value read

◆ row_search_mvcc()

dberr_t row_search_mvcc ( byte buf,
page_cur_mode_t  mode,
row_prebuilt_t prebuilt,
ulint  match_mode,
const ulint  direction 
)

Searches for rows in the database using cursor.

Function is mainly used for tables that are shared accorss connection and so it employs technique that can help re-construct the rows that transaction is suppose to see. It also has optimization such as pre-caching the rows, using AHI, etc.

Parameters
[out]bufbuffer for the fetched row in MySQL format
[in]modesearch mode PAGE_CUR_L
[in,out]prebuiltprebuilt struct for the table handler; this contains the info to search_tuple, index; if search tuple contains 0 field then we position the cursor at start or the end of index, depending on 'mode'
[in]match_mode0 or ROW_SEL_EXACT or ROW_SEL_EXACT_PREFIX
[in]direction0 or ROW_SEL_NEXT or ROW_SEL_PREV; Note: if this is != 0, then prebuilt must has a pcur with stored position! In opening of a cursor 'direction' should be 0.
Returns
DB_SUCCESS or error code

Compare the last record of the page with end range passed to InnoDB when there is no ICP and number of loops in row_search_mvcc for rows found but not reporting due to search views etc.

Secondary index record but the template based on PK.

Create offsets based on prebuilt index.

In case of prebuilt->fetch, set the error in prebuilt->end_range.

◆ row_search_no_mvcc()

dberr_t row_search_no_mvcc ( byte buf,
page_cur_mode_t  mode,
row_prebuilt_t prebuilt,
ulint  match_mode,
ulint  direction 
)

Searches for rows in the database using cursor.

Function is for temporary tables that are not shared across connections and so lot of complexity is reduced especially locking and transaction related. The cursor is an iterator over the table/index.

Parameters
[out]bufbuffer for the fetched row in MySQL format
[in]modesearch mode PAGE_CUR_L
[in,out]prebuiltprebuilt struct for the table handler; this contains the info to search_tuple, index; if search tuple contains 0 field then we position the cursor at start or the end of index, depending on 'mode'
[in]match_mode0 or ROW_SEL_EXACT or ROW_SEL_EXACT_PREFIX
[in]direction0 or ROW_SEL_NEXT or ROW_SEL_PREV; Note: if this is != 0, then prebuilt must has a pcur with stored position! In opening of a cursor 'direction' should be 0.
Returns
DB_SUCCESS or error code

◆ row_search_table_stats()

bool row_search_table_stats ( const char *  db_name,
const char *  tbl_name,
TableStatsRecord table_stats 
)

Search the record present in innodb_table_stats table using db_name, table_name and fill it in table stats structure.

Parameters
[in]db_namedatabase name
[in]tbl_nametable name
[out]table_statsstats table structure.
Returns
true if successful else false.

◆ row_search_traverse()

static dberr_t row_search_traverse ( bool  moves_up,
ulint  match_mode,
btr_pcur_t pcur,
mtr_t mtr 
)
static

Traverse to next/previous record.

Parameters
[in]moves_upIf true, move to next record else previous
[in]match_mode0 or ROW_SEL_EXACT or ROW_SEL_EXACT_PREFIX
[in,out]pcurCursor to record
[in]mtrMini-transaction
Returns
DB_SUCCESS or error code

◆ row_sel()

static dberr_t row_sel ( sel_node_t node,
que_thr_t thr 
)
static

Performs a select step.

Returns
DB_SUCCESS or error code
Parameters
nodein: select node
thrin: query thread

◆ row_sel_build_committed_vers_for_mysql()

static void row_sel_build_committed_vers_for_mysql ( dict_index_t clust_index,
row_prebuilt_t prebuilt,
const rec_t rec,
ulint **  offsets,
mem_heap_t **  offset_heap,
const rec_t **  old_vers,
const dtuple_t **  vrow,
mtr_t mtr 
)
static

Builds the last committed version of a clustered index record for a semi-consistent read.

Parameters
clust_indexin: clustered index
prebuiltin: prebuilt struct
recin: record in a clustered index
offsetsin/out: offsets returned by rec_get_offsets(rec, clust_index)
offset_heapin/out: memory heap from which the offsets are allocated
old_versout: old version, or NULL if the record does not exist in the view: i.e., it was freshly inserted afterwards
vrowout: to be filled with old virtual column version if any
mtrin: mtr

◆ row_sel_build_prev_vers()

static dberr_t row_sel_build_prev_vers ( ReadView read_view,
dict_index_t index,
rec_t rec,
ulint **  offsets,
mem_heap_t **  offset_heap,
mem_heap_t **  old_vers_heap,
rec_t **  old_vers,
mtr_t mtr 
)
static

Builds a previous version of a clustered index record for a consistent read.

Returns
DB_SUCCESS or error code
Parameters
read_viewin: read view
indexin: plan node for table
recin: record in a clustered index
offsetsin/out: offsets returned by rec_get_offsets(rec, plan->index)
offset_heapin/out: memory heap from which the offsets are allocated
old_vers_heapout: old version heap to use
old_versout: old version, or NULL if the record does not exist in the view: i.e., it was freshly inserted afterwards
mtrin: mtr

◆ row_sel_build_prev_vers_for_mysql()

static dberr_t row_sel_build_prev_vers_for_mysql ( ReadView read_view,
dict_index_t clust_index,
row_prebuilt_t prebuilt,
const rec_t rec,
ulint **  offsets,
mem_heap_t **  offset_heap,
rec_t **  old_vers,
const dtuple_t **  vrow,
mtr_t mtr,
lob::undo_vers_t lob_undo 
)
static

Builds a previous version of a clustered index record for a consistent read.

Parameters
[in]read_viewread view
[in]clust_indexclustered index
[in]prebuiltprebuilt struct
[in]recrecord in clustered index
[in,out]offsetsoffsets returned by rec_get_offsets(rec, clust_index)
[in,out]offset_heapmemory heap from which the offsets are allocated
[out]old_versold version, or NULL if the record does not exist in the view: i.e., it was freshly inserted afterwards
[out]vrowdtuple to hold old virtual column data
[in]mtrthe mini-transaction context.
[in,out]lob_undoUndo information for BLOBs.
Returns
DB_SUCCESS or error code

◆ row_sel_convert_mysql_key_to_innobase()

void row_sel_convert_mysql_key_to_innobase ( dtuple_t tuple,
byte buf,
ulint  buf_len,
dict_index_t index,
const byte key_ptr,
ulint  key_len 
)

Converts a key value stored in MySQL format to an Innobase dtuple.

The last field of the key value may be just a prefix of a fixed length field: hence the parameter key_len. But currently we do not allow search keys where the last field is only a prefix of the full key field len and print a warning if such appears.

Parameters
[in,out]tupleTuple where to build; NOTE: we assume that the type info in the tuple is already according to index!
[in]bufBuffer to use in field conversions; NOTE that dtuple->data may end up pointing inside buf so do not discard that buffer while the tuple is being used. See row_mysql_store_col_in_innobase_format() in the case of DATA_INT.
[in]buf_lenBuffer length.
[in]indexIndex of the key value.
[in]key_ptrMySQL key value
[in]key_lenMySQL key value length

◆ row_sel_copy_cached_field_for_mysql()

static void row_sel_copy_cached_field_for_mysql ( byte buf,
const byte cache,
const mysql_row_templ_t templ 
)
static

Copies a cached field for MySQL from the fetch cache.

Parameters
bufin/out: row buffer
cachein: cached row
templin: column template

◆ row_sel_copy_cached_fields_for_mysql()

void row_sel_copy_cached_fields_for_mysql ( byte buf,
const byte cached_rec,
row_prebuilt_t prebuilt 
)

Copy used fields from cached row.

Copy cache record field by field, don't touch fields that are not covered by current key.

Parameters
[out]bufWhere to copy the MySQL row.
[in]cached_recWhat to copy (in MySQL row format).
[in]prebuiltprebuilt struct.

◆ row_sel_copy_input_variable_vals()

static void row_sel_copy_input_variable_vals ( sel_node_t node)
inlinestatic

Copies the input variable values when an explicit cursor is opened.

Parameters
nodein: select node

◆ row_sel_dequeue_cached_row_for_mysql()

static void row_sel_dequeue_cached_row_for_mysql ( byte buf,
row_prebuilt_t prebuilt 
)
inlinestatic

Pops a cached row for MySQL from the fetch cache.

Parameters
bufin/out: buffer where to copy the row
prebuiltin: prebuilt struct

◆ row_sel_enqueue_cache_row_for_mysql()

static void row_sel_enqueue_cache_row_for_mysql ( byte mysql_rec,
row_prebuilt_t prebuilt 
)
inlinestatic

Pushes a row for MySQL to the fetch cache.

Parameters
mysql_recin/out: MySQL record
prebuiltin/out: prebuilt struct

◆ row_sel_fetch_columns()

static void row_sel_fetch_columns ( trx_t trx,
dict_index_t index,
const rec_t rec,
const ulint offsets,
sym_node_t column,
bool  allow_null_lob = false 
)
static

Fetches the column values from a record.

Parameters
[in]trxthe current transaction or nullptr
[in]indexrecord index
[in]recrecord in a clustered or non-clustered index; must be protected by a page latch
[in]offsetsrec_get_offsets(rec, index)
[in]columnfirst column in a column list, or NULL
[in]allow_null_loballow null lob if true. default is false.

◆ row_sel_fetch_last_buf()

static byte * row_sel_fetch_last_buf ( row_prebuilt_t prebuilt)
inlinestatic

Get the last fetch cache buffer from the queue.

Returns
pointer to buffer.
Parameters
prebuiltin/out: prebuilt struct

◆ row_sel_field_store_in_mysql_format_func()

void row_sel_field_store_in_mysql_format_func ( byte dest,
const mysql_row_templ_t templ,
const dict_index_t index,
ulint  field_no,
const byte data,
ulint  len,
ulint  sec_field 
)

Stores a non-SQL-NULL field in the MySQL format.

The counterpart of this function is row_mysql_store_col_in_innobase_format() in row0mysql.cc.

Parameters
[in,out]destbuffer where to store; NOTE that BLOBs are not in themselves stored here: the caller must allocate and copy the BLOB into buffer before, and pass the pointer to the BLOB in 'data'
[in]templMySQL column template. Its following fields are referenced: type, is_unsigned, mysql_col_len, mbminlen, mbmaxlen
[in]indexInnoDB index
[in]field_notempl->rec_field_no or templ->clust_rec_field_no or templ->icp_rec_field_no
[in]datadata to store
[in]lenlength of the data
[in]sec_fieldsecondary index field no if the secondary index record but the prebuilt template is in clustered index format and used only for end range comparison.

◆ row_sel_fill_vrow()

static void row_sel_fill_vrow ( const rec_t rec,
dict_index_t index,
const dtuple_t **  vrow,
mem_heap_t heap 
)
static

Extract virtual column data from a virtual index record and fill a dtuple.

Parameters
[in]recthe virtual (secondary) index record
[in]indexthe virtual index
[in,out]vrowthe dtuple where data extract to
[in]heapmemory heap to allocate memory

◆ row_sel_get_clust_rec()

static dberr_t row_sel_get_clust_rec ( sel_node_t node,
plan_t plan,
rec_t rec,
que_thr_t thr,
rec_t **  out_rec,
mtr_t mtr 
)
static

Retrieves the clustered index record corresponding to a record in a non-clustered index.

Does the necessary locking.

Returns
DB_SUCCESS or error code
Parameters
nodein: select_node
planin: plan node for table
recin: record in a non-clustered index
thrin: query thread
out_recout: clustered record or an old version of it, NULL if the old version did not exist in the read view, i.e., it was a fresh inserted version
mtrin: mtr used to get access to the non-clustered record; the same mtr is used to access the clustered index

◆ row_sel_get_record_buffer()

static Record_buffer * row_sel_get_record_buffer ( const row_prebuilt_t prebuilt)
static

Get the record buffer provided by the server, if there is one.

Parameters
prebuiltprebuilt struct
Returns
the record buffer, or nullptr if none was provided

◆ row_sel_open_pcur()

static void row_sel_open_pcur ( plan_t plan,
bool  search_latch_locked,
mtr_t mtr 
)
static

Opens a pcur to a table index.

Parameters
planin: table plan
search_latch_lockedin: true if the thread currently has the search latch locked in s-mode
mtrin: mtr

◆ row_sel_prefetch_cache_init()

static void row_sel_prefetch_cache_init ( row_prebuilt_t prebuilt)
inlinestatic

Initialise the prefetch cache.

Parameters
prebuiltin/out: prebuilt struct

◆ row_sel_restore_pcur_pos()

static bool row_sel_restore_pcur_pos ( plan_t plan,
mtr_t mtr 
)
static

Restores a stored pcur position to a table index.

Returns
true if the cursor should be moved to the next record after we return from this function (moved to the previous, in the case of a descending cursor) without processing again the current cursor record
Parameters
planin: table plan
mtrin: mtr

◆ row_sel_sec_rec_is_for_blob()

static bool row_sel_sec_rec_is_for_blob ( trx_t trx,
ulint  mtype,
ulint  prtype,
ulint  mbminmaxlen,
const byte clust_field,
ulint  clust_len,
const byte sec_field,
ulint  sec_len,
ulint  prefix_len,
dict_table_t table 
)
static

Returns true if the user-defined column in a secondary index record is alphabetically the same as the corresponding BLOB column in the clustered index record.

NOTE: the comparison is NOT done as a binary comparison, but character fields are compared with collation!

Returns
true if the columns are equal
Parameters
trxin: the operating transaction
mtypein: main type
prtypein: precise type
mbminmaxlenin: minimum and maximum length of a multi-byte character
clust_fieldin: the locally stored part of the clustered index column, including the BLOB pointer; the clustered index record must be covered by a lock or a page latch to protect it against deletion (rollback or purge)
clust_lenin: length of clust_field
sec_fieldin: column in secondary index
sec_lenin: length of sec_field
prefix_lenin: index column prefix length in bytes
tablein: table

◆ row_sel_sec_rec_is_for_clust_rec()

static dberr_t row_sel_sec_rec_is_for_clust_rec ( const rec_t sec_rec,
dict_index_t sec_index,
const rec_t clust_rec,
dict_index_t clust_index,
que_thr_t thr,
bool &  is_equal 
)
static

Returns true if the user-defined column values in a secondary index record are alphabetically the same as the corresponding columns in the clustered index record.

NOTE: the comparison is NOT done as a binary comparison, but character fields are compared with collation!

Parameters
[in]sec_recsecondary index record
[in]sec_indexsecondary index
[in]clust_recclustered index record; must be protected by a page s-latch
[in]clust_indexclustered index
[in]thrquery thread
[out]is_equalset to true if the secondary record is equal to the corresponding fields in the clustered record, when compared with collation; false if not equal or if the clustered record has been marked for deletion; only valid if DB_SUCCESS was returned
Returns
DB_SUCCESS or error code

◆ row_sel_step()

que_thr_t * row_sel_step ( que_thr_t thr)

Performs a select step.

This is a high-level function used in SQL execution graphs.

Returns
query thread to run next or NULL
Parameters
thrin: query thread

◆ row_sel_store_mysql_field()

static bool row_sel_store_mysql_field ( byte mysql_rec,
row_prebuilt_t prebuilt,
const rec_t rec,
const dict_index_t rec_index,
const dict_index_t prebuilt_index,
const ulint offsets,
ulint  field_no,
const mysql_row_templ_t templ,
ulint  sec_field_no,
lob::undo_vers_t lob_undo,
mem_heap_t *&  blob_heap 
)
static

Convert a field in the Innobase format to a field in the MySQL format.

Parameters
[out]mysql_recRecord in the MySQL format
[in,out]prebuiltPrebuilt struct
[in]recInnoDB record; must be protected by a page latch
[in]rec_indexIndex of rec
[in]prebuilt_indexprebuilt->index
[in]offsetsArray returned by rec_get_offsets()
[in]field_notempl->rec_field_no or templ->clust_rec_field_no or templ->icp_rec_field_no or sec field no if clust_templ_for_sec is true
[in]templrow template
[in]sec_field_noSecondary index field no if the secondary index record but the prebuilt template is in clustered index format and used only for end range comparison.
[in]lob_undothe LOB undo information.
[in,out]blob_heapIf not null then use this heap for BLOBs

◆ row_sel_store_mysql_rec()

bool row_sel_store_mysql_rec ( byte mysql_rec,
row_prebuilt_t prebuilt,
const rec_t rec,
const dtuple_t vrow,
bool  rec_clust,
const dict_index_t rec_index,
const dict_index_t prebuilt_index,
const ulint offsets,
bool  clust_templ_for_sec,
lob::undo_vers_t lob_undo,
mem_heap_t *&  blob_heap 
)

Convert a row in the Innobase format to a row in the MySQL format.

Note that the template in prebuilt may advise us to copy only a few columns to mysql_rec, other columns are left blank. All columns may not be needed in the query.

Parameters
[out]mysql_recrow in the MySQL format
[in,out]prebuiltprebuilt structure
[in]recInnobase record in the index which was described in prebuilt's template, or in the clustered index; must be protected by a page latch
[in]vrowvirtual columns
[in]rec_clusttrue if rec is in the clustered index instead of index which could belong to prebuilt->index
[in]rec_indexindex of rec
[in]prebuilt_indexprebuilt->index
[in]offsetsarray returned by rec_get_offsets(rec)
[in]clust_templ_for_sectrue if rec belongs to secondary index but the prebuilt->template is in clustered index format and it is used only for end range comparison
[in]lob_undothe LOB undo information.
[in,out]blob_heapIf not null then use this heap for BLOBs
Returns
true on success, false if not all columns could be retrieved

◆ row_sel_store_row_id_to_prebuilt()

static void row_sel_store_row_id_to_prebuilt ( row_prebuilt_t prebuilt,
const rec_t index_rec,
const dict_index_t index,
const ulint offsets 
)
static

Stores the row id to the prebuilt struct.

Parameters
prebuiltin/out: prebuilt
index_recin: record
indexin: index of the record
offsetsin: rec_get_offsets (index_rec, index)

◆ row_sel_test_end_conds()

static bool row_sel_test_end_conds ( plan_t plan)
inlinestatic

Tests the conditions which determine when the index segment we are searching through has been exhausted.

Returns
true if row passed the tests
Parameters
planin: plan for the table; the column values must already have been retrieved and the right sides of comparisons evaluated

◆ row_sel_test_other_conds()

static bool row_sel_test_other_conds ( plan_t plan)
inlinestatic

Tests the other conditions.

Returns
true if row passed the tests
Parameters
planin: plan for the table; the column values must already have been retrieved

◆ row_sel_try_search_shortcut()

static ulint row_sel_try_search_shortcut ( trx_t trx,
sel_node_t node,
plan_t plan,
bool  search_latch_locked,
mtr_t mtr 
)
static

Tries to do a shortcut to fetch a clustered index record with a unique key, using the hash index if possible (not always).

Returns
SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY
Parameters
trxin: trx doing the operation.
nodein: select node for a consistent read
planin: plan for a unique search in clustered index
search_latch_lockedin: whether the search holds latch on search system.
mtrin: mtr

◆ row_sel_try_search_shortcut_for_mysql()

static ulint row_sel_try_search_shortcut_for_mysql ( const rec_t **  out_rec,
row_prebuilt_t prebuilt,
ulint **  offsets,
mem_heap_t **  heap,
mtr_t mtr 
)
static

Tries to do a shortcut to fetch a clustered index record with a unique key, using the hash index if possible (not always).

We assume that the search mode is PAGE_CUR_GE, it is a consistent read, there is a read view in trx, btr search latch has been locked in S-mode if AHI is enabled.

Returns
SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY
Parameters
out_recout: record if found
prebuiltin: prebuilt struct
offsetsin/out: for rec_get_offsets(*out_rec)
heapin/out: heap for rec_get_offsets()
mtrin: started mtr

◆ sel_assign_into_var_values()

static void sel_assign_into_var_values ( sym_node_t var,
sel_node_t node 
)
inlinestatic

Assigns the values in the select list to the possible into-variables in SELECT ... INTO ...

Parameters
varin: first variable in a list of variables
nodein: select node

◆ sel_col_prefetch_buf_alloc()

static void sel_col_prefetch_buf_alloc ( sym_node_t column)
static

Allocates a prefetch buffer for a column when prefetch is first time done.

Parameters
columnin: symbol table node for a column

◆ sel_col_prefetch_buf_free()

void sel_col_prefetch_buf_free ( sel_buf_t prefetch_buf)

Frees a prefetch buffer for a column, including the dynamically allocated memory for data stored there.

in, own: prefetch buffer

Parameters
prefetch_bufin, own: prefetch buffer

◆ sel_dequeue_prefetched_row()

static void sel_dequeue_prefetched_row ( plan_t plan)
static

Pops the column values for a prefetched, cached row from the column prefetch buffers and places them to the val fields in the column nodes.

Parameters
planin: plan node for a table

◆ sel_enqueue_prefetched_row()

static void sel_enqueue_prefetched_row ( plan_t plan)
inlinestatic

Pushes the column values for a prefetched, cached row to the column prefetch buffers from the val fields in the column nodes.

Parameters
planin: plan node for a table

◆ sel_eval_select_list()

static void sel_eval_select_list ( sel_node_t node)
inlinestatic

Evaluates the values in a select list.

If there are aggregate functions, their argument value is added to the aggregate total.

Parameters
nodein: select node

◆ sel_node_create()

sel_node_t * sel_node_create ( mem_heap_t heap)

Creates a select node struct.

Returns
own: select node struct
Parameters
heapin: memory heap where created

◆ sel_node_free_private()

void sel_node_free_private ( sel_node_t node)

Frees the memory private to a select node when a query graph is freed, does not free the heap where the node was originally created.

in: select node struct

Parameters
nodein: select node struct

◆ sel_reset_aggregate_vals()

static void sel_reset_aggregate_vals ( sel_node_t node)
inlinestatic

Resets the aggregate value totals in the select list of an aggregate type query.

Parameters
nodein: select node

◆ sel_restore_position_for_mysql()

static bool sel_restore_position_for_mysql ( bool *  same_user_rec,
ulint  latch_mode,
btr_pcur_t pcur,
bool  moves_up,
mtr_t mtr 
)
static

Restores cursor position after it has been stored.

We have to take into account that the record cursor was positioned on may have been deleted. Then we may have to move the cursor one step up or down.

Returns
true if we may need to process the record the cursor is now positioned on (i.e. we should not go to the next record yet)
Parameters
same_user_recout: true if we were able to restore the cursor on a user record with the same ordering prefix in in the B-tree index
latch_modein: latch mode wished in restoration
pcurin: cursor whose position has been stored
moves_upin: true if the cursor moves up in the index
mtrin: mtr; CAUTION: may commit mtr temporarily!

◆ sel_set_rec_lock()

static dberr_t sel_set_rec_lock ( btr_pcur_t pcur,
const rec_t rec,
dict_index_t index,
const ulint offsets,
select_mode  sel_mode,
ulint  mode,
ulint  type,
que_thr_t thr,
mtr_t mtr 
)
inlinestatic

Sets a lock on a record.

mostly due to we cannot reposition a record in R-Tree (with the nature of splitting)

Parameters
[in]pcurcursor
[in]recrecord
[in]indexindex
[in]offsetsrec_get_offsets(rec, index)
[in]sel_modeselect mode: SELECT_ORDINARY, SELECT_SKIP_LOKCED, or SELECT_NO_WAIT
[in]modelock mode
[in]typeLOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP
[in]thrquery thread
[in]mtrmtr
Returns
DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code

◆ sel_set_rtr_rec_lock()

static dberr_t sel_set_rtr_rec_lock ( btr_pcur_t pcur,
const rec_t first_rec,
dict_index_t index,
const ulint offsets,
select_mode  sel_mode,
ulint  mode,
ulint  type,
que_thr_t thr,
mtr_t mtr 
)
inlinestatic

Sets a lock on a page of R-Tree record.

This is all or none action, mostly due to we cannot reposition a record in R-Tree (with the nature of splitting)

Parameters
[in]pcurcursor
[in]first_recrecord
[in]indexindex
[in]offsetsrec_get_offsets(rec, index)
[in]sel_modeselect mode: SELECT_ORDINARY, SELECT_SKIP_LOKCED, or SELECT_NO_WAIT
[in]modelock mode
[in]typeLOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP
[in]thrquery thread
[in]mtrmtr
Returns
DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code

Variable Documentation

◆ SEL_COST_LIMIT

constexpr uint32_t SEL_COST_LIMIT = 100
constexpr

When a select has accessed about this many pages, it returns control back to que_run_threads: this is to allow canceling runaway queries.

◆ SEL_EXHAUSTED

constexpr uint32_t SEL_EXHAUSTED = 1
constexpr

◆ SEL_FOUND

constexpr uint32_t SEL_FOUND = 0
constexpr

Flags for search shortcut.

◆ SEL_MAX_N_PREFETCH

constexpr uint32_t SEL_MAX_N_PREFETCH = 16
constexpr

Maximum number of rows to prefetch; MySQL interface has another parameter.

◆ SEL_PREFETCH_LIMIT

constexpr uint32_t SEL_PREFETCH_LIMIT = 1
constexpr

Number of rows fetched, after which to start prefetching; MySQL interface has another parameter.

◆ SEL_RETRY

constexpr uint32_t SEL_RETRY = 2
constexpr