MySQL  8.0.17
Source Code Documentation
row_iterator.h
Go to the documentation of this file.
1 #ifndef SQL_ROW_ITERATOR_H_
2 #define SQL_ROW_ITERATOR_H_
3 
4 /* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License, version 2.0,
8  as published by the Free Software Foundation.
9 
10  This program is also distributed with certain software (including
11  but not limited to OpenSSL) that is licensed under separate terms,
12  as designated in a particular file or component or in included license
13  documentation. The authors of MySQL hereby grant you an additional
14  permission to link the program and your derivative works with the
15  separately licensed software that they have included with MySQL.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License, version 2.0, for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
25 
26 #include <string>
27 #include <vector>
28 
29 class Item;
30 class JOIN;
31 class THD;
32 struct TABLE;
33 
34 /**
35  A context for reading through a single table using a chosen access method:
36  index read, scan, etc, use of cache, etc.. It is mostly meant as an interface,
37  but also contains some private member functions that are useful for many
38  implementations, such as error handling.
39 
40  A RowIterator is a simple iterator; you initialize it, and then read one
41  record at a time until Read() returns EOF. A RowIterator can read from
42  other Iterators if you want to, e.g., SortingIterator, which takes in records
43  from another RowIterator and sorts them.
44 
45  The abstraction is not completely tight. In particular, it still leaves some
46  specifics to TABLE, such as which columns to read (the read_set). This means
47  it would probably be hard as-is to e.g. sort a join of two tables.
48 
49  Use by:
50 @code
51  unique_ptr<RowIterator> iterator(new ...);
52  if (iterator->Init())
53  return true;
54  while (iterator->Read() == 0) {
55  ...
56  }
57 @endcode
58  */
59 class RowIterator {
60  public:
62  virtual ~RowIterator() {}
63 
64  /**
65  Initialize or reinitialize the iterator. You must always call Init()
66  before trying a Read() (but Init() does not imply Read()).
67 
68  You can call Init() multiple times; subsequent calls will rewind the
69  iterator (or reposition it, depending on whether the iterator takes in
70  e.g. a TABLE_REF) and allow you to read the records anew.
71  */
72  virtual bool Init() = 0;
73 
74  /**
75  Read a single row. The row data is not actually returned from the function;
76  it is put in the table's (or tables', in case of a join) record buffer, ie.,
77  table->records[0].
78 
79  @retval
80  0 OK
81  @retval
82  -1 End of records
83  @retval
84  1 Error
85  */
86  virtual int Read() = 0;
87 
88  /**
89  Mark the current row buffer as containing a NULL row or not, so that if you
90  read from it and the flag is true, you'll get only NULLs no matter what is
91  actually in the buffer (typically some old leftover row). This is used
92  for outer joins, when an iterator hasn't produced any rows and we need to
93  produce a NULL-complemented row. Init() or Read() won't necessarily
94  reset this flag, so if you ever set is to true, make sure to also set it
95  to false when needed.
96 
97  Note that this can be called without Init() having been called first.
98  For example, NestedLoopIterator can hit EOF immediately on the outer
99  iterator, which means the inner iterator doesn't get an Init() call,
100  but will still forward SetNullRowFlag to both inner and outer iterators.
101 
102  TODO: We shouldn't need this. See the comments on AggregateIterator for
103  a bit more discussion on abstracting out a row interface.
104  */
105  virtual void SetNullRowFlag(bool is_null_row) = 0;
106 
107  // In certain queries, such as SELECT FOR UPDATE, UPDATE or DELETE queries,
108  // reading rows will automatically take locks on them. (This means that the
109  // set of locks taken will depend on whether e.g. the optimizer chose a table
110  // scan or used an index, due to InnoDB's row locking scheme with “gap locks”
111  // for B-trees instead of full predicate locks.)
112  //
113  // However, under some transaction isolation levels (READ COMMITTED or
114  // less strict), it is possible to release such locks if and only if the row
115  // failed a WHERE predicate, as only the returned rows are protected,
116  // not _which_ rows are returned. Thus, if Read() returned a row that you did
117  // not actually use, you should call UnlockRow() afterwards, which allows the
118  // storage engine to release the row lock in such situations.
119  //
120  // TableRowIterator has a default implementation of this; other iterators
121  // should usually either forward the call to their source iterator (if any)
122  // or just ignore it. The right behavior depends on the iterator.
123  virtual void UnlockRow() = 0;
124 
125  struct Child {
127 
128  // Normally blank. If not blank, a heading for this iterator
129  // saying what kind of role it has to the parent if it is not
130  // obvious. E.g., FilterIterator can print iterators that are
131  // children because they come out of subselect conditions.
132  std::string description;
133  };
134 
135  virtual std::vector<Child> children() const { return std::vector<Child>(); }
136 
137  virtual std::vector<std::string> DebugString() const = 0;
138 
139  // If this is the root iterator of a join, points back to the join object.
140  // This has one single purpose: EXPLAIN uses it to be able to get the SELECT
141  // list and print out any subselects in it; they are not children of
142  // the iterator per se, but need to be printed with it.
143  //
144  // We could have stored the list of these extra subselect iterators directly
145  // on the iterator (it breaks the abstraction a bit to refer to JOIN here),
146  // but setting a single pointer is cheaper, especially considering that most
147  // queries are not EXPLAIN queries and we don't want the overhead for them.
148  JOIN *join() const { return m_join; }
149 
150  // Should be called by JOIN::create_iterators() only.
151  void set_join(JOIN *join) { m_join = join; }
152 
153  /**
154  Start performance schema batch mode, if supported (otherwise ignored).
155 
156  PFS batch mode is a hack to reduce the overhead of performance schema,
157  typically applied at the innermost table of the entire join. If you start
158  it before scanning the table and then end it afterwards, the entire set
159  of handler calls will be timed only once, as a group, and the costs will
160  be distributed evenly out. This reduces timer overhead.
161 
162  If you start PFS batch mode, you must also take care to end it at the
163  end of the scan, one way or the other. Do note that this is true even
164  if the query ends abruptly (LIMIT is reached, or an error happens).
165  The easiest workaround for this is to simply go through all the open
166  handlers and call end_psi_batch_mode_if_started(). See the PFSBatchMode
167  class for a useful helper.
168  */
169  virtual void StartPSIBatchMode() {}
170 
171  /**
172  Ends performance schema batch mode, if started. It's always safe to
173  call this.
174  */
175  virtual void EndPSIBatchModeIfStarted() {}
176 
177  protected:
178  THD *thd() const { return m_thd; }
179 
180  private:
181  THD *const m_thd;
182  JOIN *m_join = nullptr;
183 };
184 
186  public:
188 
189  void UnlockRow() override;
190  void SetNullRowFlag(bool is_null_row) override;
191  void StartPSIBatchMode() override;
192  void EndPSIBatchModeIfStarted() override;
193 
194  protected:
195  int HandleError(int error);
196  void PrintError(int error);
197  TABLE *table() const { return m_table; }
198 
199  private:
200  TABLE *const m_table;
201 
202  friend class AlternativeIterator;
203 };
204 
205 #endif // SQL_ROW_ITERATOR_H_
std::string description
Definition: row_iterator.h:132
virtual void StartPSIBatchMode()
Start performance schema batch mode, if supported (otherwise ignored).
Definition: row_iterator.h:169
int HandleError(int error)
Definition: records.cc:291
Definition: sql_optimizer.h:177
Definition: row_iterator.h:185
virtual ~RowIterator()
Definition: row_iterator.h:62
TABLE *const m_table
Definition: row_iterator.h:200
virtual void UnlockRow()=0
A context for reading through a single table using a chosen access method: index read...
Definition: row_iterator.h:59
void SetNullRowFlag(bool is_null_row) override
Mark the current row buffer as containing a NULL row or not, so that if you read from it and the flag...
Definition: records.cc:283
virtual std::vector< std::string > DebugString() const =0
RowIterator(THD *thd)
Definition: row_iterator.h:61
THD *const m_thd
Definition: row_iterator.h:181
void PrintError(int error)
Definition: records.cc:306
Definition: table.h:1294
TABLE * table() const
Definition: row_iterator.h:197
virtual int Read()=0
Read a single row.
void EndPSIBatchModeIfStarted() override
Ends performance schema batch mode, if started.
Definition: records.cc:314
Definition: item.h:666
virtual void EndPSIBatchModeIfStarted()
Ends performance schema batch mode, if started.
Definition: row_iterator.h:175
TableRowIterator(THD *thd, TABLE *table)
Definition: row_iterator.h:187
void StartPSIBatchMode() override
Start performance schema batch mode, if supported (otherwise ignored).
Definition: records.cc:310
An iterator that switches between another iterator (typically a RefIterator or similar) and a TableSc...
Definition: ref_row_iterators.h:246
RowIterator * iterator
Definition: row_iterator.h:126
THD * thd() const
Definition: row_iterator.h:178
void set_join(JOIN *join)
Definition: row_iterator.h:151
Definition: row_iterator.h:125
virtual void SetNullRowFlag(bool is_null_row)=0
Mark the current row buffer as containing a NULL row or not, so that if you read from it and the flag...
JOIN * join() const
Definition: row_iterator.h:148
virtual bool Init()=0
Initialize or reinitialize the iterator.
JOIN * m_join
Definition: row_iterator.h:182
void UnlockRow() override
The default implementation of unlock-row method of READ_RECORD, used in all access methods except EQR...
Definition: records.cc:281
virtual std::vector< Child > children() const
Definition: row_iterator.h:135
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_class.h:777
Log error(cerr, "ERROR")