MySQL 9.5.0
Source Code Documentation
rowid_ordered_retrieval.h
Go to the documentation of this file.
1/* Copyright (c) 2000, 2025, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef SQL_RANGE_OPTIMIZER_ROWID_ORDERED_RETRIEVAL_H_
25#define SQL_RANGE_OPTIMIZER_ROWID_ORDERED_RETRIEVAL_H_
26
27#include <assert.h>
28#include <sys/types.h>
29#include <vector>
30
31#include "my_alloc.h"
32#include "my_inttypes.h"
33#include "priority_queue.h"
34#include "sql/handler.h"
38#include "sql/sql_list.h"
39#include "sql/table.h"
40
41class String;
42class THD;
43struct MY_BITMAP;
44
45/*
46 Rowid-Ordered Retrieval (ROR) index intersection quick select.
47 This quick select produces intersection of row sequences returned
48 by several IndexRangeScanIterators it "merges".
49
50 All merged IndexRangeScanIterators must return rowids in rowid order.
51 RowIDIntersectionIterator will return rows in rowid order, too.
52
53 All merged quick selects retrieve {rowid, covered_fields} tuples (not full
54 table records).
55 RowIDIntersectionIterator retrieves full records if it is not being used
56 by RowIDUnionIterator and all merged quick selects together don't
57 cover needed all fields.
58
59 If one of the merged quick selects is a Clustered PK range scan, it is
60 used only to filter rowid sequence produced by other merged quick selects.
61*/
62
64 public:
66 THD *thd, MEM_ROOT *return_mem_root, TABLE *table_arg,
71
72 uchar *last_rowid() const override {
74 return m_last_rowid;
75 }
76
77 private:
78 bool DoInit() override;
79 int DoRead() override;
80
81 /*
82 Range quick selects this intersection consists of, not including
83 cpk_quick.
84 */
86
87 /*
88 Merged quick select that uses Clustered PK, if there is one. This quick
89 select is not used for row retrieval, it is used for row retrieval.
90 */
92
93 /*
94 If true, do retrieve full table rows.
95
96 The way this works is somewhat convoluted; this is my (sgunders')
97 understanding as of September 2021:
98
99 For covering indexes (for some complicated value of “covering” if there are
100 multiple indexes involved), we always use index-only scans; otherwise,
101 the index range scan uses a normal scan (table->file->set_keyread(false)),
102 which does first a lookup into the index, and then the secondary lookup to
103 get the actual row.
104
105 However, for intersection scans, we don't actually need all sub-scans to
106 fetch the actual row; that's just a waste, especially since in most cases,
107 we won't need the row. So in this case, the _intention_ is that we'd always
108 turn on index-only scans, although it seems the code for this was never
109 written. The idea is that the intersection iterator then is responsible for
110 doing a kind of “fetch after the fact” once the intersection has yielded a
111 row (unless we're covering). This is done by
112
113 table->file->ha_rnd_pos(table->record[0], rowid);
114
115 although index merge uses position() instead of ha_rnd_pos().
116 Both seem to have the (undocumented?) side effect of actually fetching the
117 row even on an index-only scan. This is the reason why we need the
118 intersection iterator to reuse the handler reuse for MyISAM; otherwise, we'd
119 never actually get the row, since it's stored privately in MI_INFO and not
120 in the row ID.
121
122 But if there's something above the intersection scan again (which can only
123 be a union), it's the same game; when we find a row, it might be a duplicate
124 of the same row ID from another sub-iterator of the union (whether a range
125 scan or an intersection of range scans), and then it's not worth it to fetch
126 the entire row. So that's why the intersection scan needs to be told “no,
127 don't do ha_rnd_pos; your parent will be doing that if it's interested”. And
128 that is what this variable is for.
129 */
131
132 /* in top-level quick select, true if merged scans where initialized */
134
137 bool inited = false;
138
140};
141
142/*
143 Comparison function to be used RowIDUnionIterator::queue priority
144 queue.
145*/
150 down_cast<RowIDCapableRowIterator *>(a->real_iterator());
152 down_cast<RowIDCapableRowIterator *>(b->real_iterator());
153 return m_file->cmp_ref(real_a->last_rowid(), real_b->last_rowid()) > 0;
154 }
156};
157
158/*
159 Rowid-Ordered Retrieval index union select.
160 This quick select produces union of row sequences returned by several
161 quick select it "merges".
162
163 All merged quick selects must return rowids in rowid order.
164 RowIDUnionIterator will return rows in rowid order, too.
165
166 All merged quick selects are set not to retrieve full table records.
167 ROR-union quick select always retrieves full records.
168
169*/
170
172 public:
174 THD *thd, MEM_ROOT *return_mem_root, TABLE *table,
176 ~RowIDUnionIterator() override;
177
178 private:
179 bool DoInit() override;
180 int DoRead() override;
181
183
185 std::vector<RowIterator *, Malloc_allocator<RowIterator *>>,
187 queue; /* Priority queue for merge operation */
188
189 MEM_ROOT *mem_root; /* Memory pool for this and merged quick selects data. */
190 uchar *cur_rowid; /* buffer used in Read() */
191 uchar *prev_rowid; /* rowid of last row returned by Read() */
192 bool have_prev_rowid; /* true if prev_rowid has valid data */
193 uint rowid_length; /* table rowid length */
194
196 bool inited = false;
197};
198
199#endif // SQL_RANGE_OPTIMIZER_ROWID_ORDERED_RETRIEVAL_H_
A typesafe replacement for DYNAMIC_ARRAY.
Definition: mem_root_array.h:432
Implements a priority queue using a vector-based max-heap.
Definition: priority_queue.h:104
An interface for RowIterators that have a given row ID, ie., they can be children in ROR (rowid-order...
Definition: rowid_capable_row_iterator.h:36
virtual uchar * last_rowid() const =0
Definition: rowid_ordered_retrieval.h:63
bool init_ror_merged_scan()
Definition: rowid_ordered_retrieval.cc:170
int DoRead() override
Definition: rowid_ordered_retrieval.cc:323
const bool need_rows_in_rowid_order
Definition: rowid_ordered_retrieval.h:135
bool inited
Definition: rowid_ordered_retrieval.h:137
RowIDIntersectionIterator(THD *thd, MEM_ROOT *return_mem_root, TABLE *table_arg, bool retrieve_full_rows, bool need_rows_in_rowid_order, Mem_root_array< unique_ptr_destroy_only< RowIterator > > children, unique_ptr_destroy_only< RowIterator > cpk_child)
Definition: rowid_ordered_retrieval.cc:48
Mem_root_array< unique_ptr_destroy_only< RowIterator > > m_children
Definition: rowid_ordered_retrieval.h:85
uchar * m_last_rowid
Definition: rowid_ordered_retrieval.h:136
uchar * last_rowid() const override
Definition: rowid_ordered_retrieval.h:72
unique_ptr_destroy_only< RowIterator > m_cpk_child
Definition: rowid_ordered_retrieval.h:91
~RowIDIntersectionIterator() override
Definition: rowid_ordered_retrieval.cc:226
bool DoInit() override
Definition: rowid_ordered_retrieval.cc:199
bool retrieve_full_rows
Definition: rowid_ordered_retrieval.h:130
bool scans_inited
Definition: rowid_ordered_retrieval.h:133
Definition: rowid_ordered_retrieval.h:171
bool DoInit() override
Definition: rowid_ordered_retrieval.cc:242
uchar * cur_rowid
Definition: rowid_ordered_retrieval.h:190
Priority_queue< RowIterator *, std::vector< RowIterator *, Malloc_allocator< RowIterator * > >, Quick_ror_union_less > queue
Definition: rowid_ordered_retrieval.h:187
uint rowid_length
Definition: rowid_ordered_retrieval.h:193
Mem_root_array< unique_ptr_destroy_only< RowIterator > > m_children
Definition: rowid_ordered_retrieval.h:182
RowIDUnionIterator(THD *thd, MEM_ROOT *return_mem_root, TABLE *table, Mem_root_array< unique_ptr_destroy_only< RowIterator > > children)
Definition: rowid_ordered_retrieval.cc:230
~RowIDUnionIterator() override
Definition: rowid_ordered_retrieval.cc:294
bool have_prev_rowid
Definition: rowid_ordered_retrieval.h:192
bool inited
Definition: rowid_ordered_retrieval.h:196
bool scans_inited
Definition: rowid_ordered_retrieval.h:195
uchar * prev_rowid
Definition: rowid_ordered_retrieval.h:191
MEM_ROOT * mem_root
Definition: rowid_ordered_retrieval.h:189
int DoRead() override
Definition: rowid_ordered_retrieval.cc:434
A context for reading through a single table using a chosen access method: index read,...
Definition: row_iterator.h:82
THD * thd() const
Definition: row_iterator.h:255
virtual RowIterator * real_iterator()
If this iterator is wrapping a different iterator (e.g.
Definition: row_iterator.h:240
Using this class is fraught with peril, and you need to be very careful when doing so.
Definition: sql_string.h:169
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:36
Definition: row_iterator.h:267
TABLE * table() const
Definition: row_iterator.h:279
The handler class is the interface for dynamically loadable storage engines.
Definition: handler.h:4741
virtual int cmp_ref(const uchar *ref1, const uchar *ref2) const
Compare two positions.
Definition: handler.h:6326
This file follows Google coding style, except for the name MEM_ROOT (which is kept for historical rea...
std::unique_ptr< T, Destroy_only< T > > unique_ptr_destroy_only
std::unique_ptr, but only destroying.
Definition: my_alloc.h:480
Some integer typedefs for easier portability.
unsigned char uchar
Definition: my_inttypes.h:52
Definition: os0file.h:89
The MEM_ROOT is a simple arena, where allocations are carved out of larger blocks.
Definition: my_alloc.h:83
Definition: my_bitmap.h:43
Definition: rowid_ordered_retrieval.h:146
const handler * m_file
Definition: rowid_ordered_retrieval.h:155
Quick_ror_union_less(const handler *file)
Definition: rowid_ordered_retrieval.h:147
bool operator()(RowIterator *a, RowIterator *b)
Definition: rowid_ordered_retrieval.h:148
Definition: table.h:1435