forked from mysql/mysql-server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathha_ndbcluster_push.h
360 lines (295 loc) · 10.8 KB
/
ha_ndbcluster_push.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
/*
Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "sql_bitmap.h"
class NdbTransaction;
class NdbQueryBuilder;
class NdbQueryOperand;
class NdbQueryOperationDef;
class ndb_pushed_builder_ctx;
struct NdbError;
namespace AQP{
class Join_plan;
class Table_access;
};
void ndbcluster_build_key_map(const NdbDictionary::Table* table,
const NDB_INDEX_DATA& index,
const KEY *key_def,
uint ix_map[]);
/**
* This type is used in conjunction with AQP::Join_plan and represents a set
* of the table access operations of the join plan.
* Had to subclass Bitmap as the default Bitmap<64> c'tor didn't initialize its
* map.
*/
typedef Bitmap<(MAX_TABLES > 64 ? MAX_TABLES : 64)> table_bitmap;
class ndb_table_access_map : public table_bitmap
{
public:
explicit ndb_table_access_map()
: table_bitmap(0)
{}
explicit ndb_table_access_map(uint table_no)
: table_bitmap(0)
{ set_bit(table_no);
}
void add(const ndb_table_access_map& table_map)
{ // Require const_cast as signature of class Bitmap::merge is not const correct
merge(const_cast<ndb_table_access_map&>(table_map));
}
void add(uint table_no)
{
set_bit(table_no);
}
bool contain(const ndb_table_access_map& table_map) const
{
return table_map.is_subset(*this);
}
bool contain(uint table_no) const
{
return is_set(table_no);
}
uint first_table(uint start= 0) const;
uint last_table(uint start= MAX_TABLES) const;
}; // class ndb_table_access_map
/** This class represents a prepared pushed (N-way) join operation.
*
* It might be instantiated multiple times whenever the query,
* or this subpart of the query, is being (re-)executed by
* ::createQuery() or it's wrapper method
* ha_ndbcluster::create_pushed_join().
*/
class ndb_pushed_join
{
public:
explicit ndb_pushed_join(const ndb_pushed_builder_ctx& builder_ctx,
const NdbQueryDef* query_def);
~ndb_pushed_join();
/**
* Check that this prepared pushed query matches the type
* of operation specified by the arguments.
*/
bool match_definition(int type, //NdbQueryOperationDef::Type,
const NDB_INDEX_DATA* idx) const;
/** Create an executable instance of this defined query. */
NdbQuery* make_query_instance(
NdbTransaction* trans,
const NdbQueryParamValue* keyFieldParams,
uint paramCnt) const;
/** Get the number of pushed table access operations.*/
uint get_operation_count() const
{ return m_operation_count; }
/**
* In a pushed join, fields in lookup keys and scan bounds may refer to
* result fields of table access operation that execute prior to the pushed
* join. This method returns the number of such references.
*/
uint get_field_referrences_count() const
{ return m_field_count; }
const NdbQueryDef& get_query_def() const
{ return *m_query_def; }
/** Get the table that is accessed by the i'th table access operation.*/
TABLE* get_table(uint i) const
{
DBUG_ASSERT(i < m_operation_count);
return m_tables[i];
}
/**
* This is the maximal number of fields in the key of any pushed table
* access operation.
*/
static const uint MAX_KEY_PART= MAX_KEY;
/**
* In a pushed join, fields in lookup keys and scan bounds may refer to
* result fields of table access operation that execute prior to the pushed
* join. This constant specifies the maximal number of such references for
* a query.
*/
static const uint MAX_REFERRED_FIELDS= 16;
/**
* For each table access operation in a pushed join, this is the maximal
* number of key fields that may refer to the fields of the parent operation.
*/
static const uint MAX_LINKED_KEYS= MAX_KEY;
/**
* This is the maximal number of table access operations there can be in a
* single pushed join.
*/
static const uint MAX_PUSHED_OPERATIONS= MAX_TABLES;
private:
const NdbQueryDef* const m_query_def; // Definition of pushed join query
/** This is the number of table access operations in the pushed join.*/
uint m_operation_count;
/** This is the tables that are accessed by the pushed join.*/
TABLE* m_tables[MAX_PUSHED_OPERATIONS];
/**
* This is the number of referred fields of table access operation that
* execute prior to the pushed join.
*/
const uint m_field_count;
/**
* These are the referred fields of table access operation that execute
* prior to the pushed join.
*/
Field* m_referred_fields[MAX_REFERRED_FIELDS];
}; // class ndb_pushed_join
/**
* Contains the context and helper methods used during ::make_pushed_join().
*
* Interacts with the AQP which provides interface to the query prepared by
* the mysqld optimizer.
*
* Execution plans built for pushed joins are stored inside this builder context.
*/
class ndb_pushed_builder_ctx
{
friend ndb_pushed_join::ndb_pushed_join(
const ndb_pushed_builder_ctx& builder_ctx,
const NdbQueryDef* query_def);
public:
ndb_pushed_builder_ctx(const AQP::Join_plan& plan);
~ndb_pushed_builder_ctx();
/**
* Build the pushed query identified with 'is_pushable_with_root()'.
* Returns:
* = 0: A NdbQueryDef has successfully been prepared for execution.
* > 0: Returned value is the error code.
* < 0: There is a pending NdbError to be retrieved with getNdbError()
*/
int make_pushed_join(const AQP::Table_access* join_root,
const ndb_pushed_join* &pushed_join);
const NdbError& getNdbError() const;
private:
/**
* Collect all tables which may be pushed together with 'root'.
* Returns 'true' if anything is pushable.
*/
bool is_pushable_with_root(
const AQP::Table_access* root);
bool is_pushable_as_child(
const AQP::Table_access* table);
bool is_const_item_pushable(
const Item* key_item,
const KEY_PART_INFO* key_part);
bool is_field_item_pushable(
const AQP::Table_access* table,
const Item* key_item,
const KEY_PART_INFO* key_part,
ndb_table_access_map& parents);
int optimize_query_plan();
int build_query();
void collect_key_refs(
const AQP::Table_access* table,
const Item* key_refs[]) const;
int build_key(const AQP::Table_access* table,
const NdbQueryOperand* op_key[]);
uint get_table_no(const Item* key_item) const;
private:
const AQP::Join_plan& m_plan;
const AQP::Table_access* m_join_root;
// Scope of tables covered by this pushed join
ndb_table_access_map m_join_scope;
// Scope of tables evaluated prior to 'm_join_root'
// These are effectively const or params wrt. the pushed join
ndb_table_access_map m_const_scope;
// Set of tables which 'FirstMatch' algorithm will
// skip when a FirstMatch has been found.
// Use a bitmap as there may be multiple usage of FirstMatch
// in a query, and each FirstMatch may skip multiple tables.
ndb_table_access_map m_firstmatch_skipped;
// Number of internal operations used so far (unique lookups count as two).
uint m_internal_op_count;
uint m_fld_refs;
Field* m_referred_fields[ndb_pushed_join::MAX_REFERRED_FIELDS];
// Handle to the NdbQuery factory.
// Possibly reused if multiple NdbQuery's are pushed.
NdbQueryBuilder* m_builder;
enum pushability
{
PUSHABLE_AS_PARENT= 0x01,
PUSHABLE_AS_CHILD= 0x02
} enum_pushability;
struct pushed_tables
{
pushed_tables() :
m_maybe_pushable(0),
m_common_parents(),
m_extend_parents(),
m_depend_parents(),
m_parent(MAX_TABLES),
m_ancestors(),
m_fanout(1.0),
m_child_fanout(1.0),
m_op(NULL)
{}
int m_maybe_pushable; // OR'ed bits from 'enum_pushability'
/**
* We maintain two sets of parent candidates for each table:
* - 'common' are those parents for which ::collect_key_refs()
* will find key_refs[] (possibly through the EQ-sets) such that all
* linkedValues() refer fields from the same parent.
* - 'extended' are those parents refered from some of the
* key_refs[], and having the rest of the key_refs[] available as
* 'grandparent refs'.
*/
ndb_table_access_map m_common_parents;
ndb_table_access_map m_extend_parents;
/**
* (sub)Set of a parents which *must* be available as ancestors
* due to dependencies on these parents tables.
*
* NOTE1: When the 'm_parent' has been choosen by
* ::optimize_query_plan(), any remaining grandparent
* dependencies has to be added the 'depend_parents'
* of the choosen parents such that it is taken into account
* when calculating the ancestor tables.
*
* NOTE2: These 'depend_parents' place restrictions on which of the
* 'common', 'extend' parents above we actually may use:
* As all 'depend_parents' must be joined as (grand)parents
* prior to one of the selected common/extend parents, only
* parents >= the last 'depend_parents' are the real candidates.
*
* We currently mask away the unusable common/extend parents
* as part of ::optimize_query_plan() prior to selecting
* the parent.
*/
ndb_table_access_map m_depend_parents;
/**
* The actual parent is choosen among (m_common_parents | m_extend_parents)
* by ::optimize_query_plan()
*/
uint m_parent;
/**
* All ancestors available throught the 'm_parent' chain
*/
ndb_table_access_map m_ancestors;
/**
* The fanout of this table.
*/
double m_fanout;
/**
* The (cross) product of all child fanouts.
*/
double m_child_fanout;
const NdbQueryOperationDef* m_op;
} m_tables[MAX_TABLES];
/**
* There are two different table enumerations used:
*/
struct table_remap
{
Uint16 to_external; // m_remap[] is indexed with internal table_no
Uint16 to_internal; // m_remap[] is indexed with external tablenr
} m_remap[MAX_TABLES];
}; // class ndb_pushed_builder_ctx