1
/* Copyright (C) 2000-2007 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
This file defines the data structures used by engine condition pushdown in
18
the NDB Cluster handler
21
#ifdef USE_PRAGMA_INTERFACE
22
#pragma interface /* gcc class implementation */
25
typedef enum ndb_item_type {
26
NDB_VALUE = 0, // Qualified more with Item::Type
27
NDB_FIELD = 1, // Qualified from table definition
28
NDB_FUNCTION = 2,// Qualified from Item_func::Functype
29
NDB_END_COND = 3 // End marker for condition group
32
typedef enum ndb_func_type {
40
NDB_ISNOTNULL_FUNC = 7,
44
NDB_UNKNOWN_FUNC = 11,
45
NDB_COND_AND_FUNC = 12,
46
NDB_COND_OR_FUNC = 13,
47
NDB_UNSUPPORTED_FUNC = 14
50
typedef union ndb_item_qualification {
51
Item::Type value_type;
52
enum_field_types field_type; // Instead of Item::FIELD_ITEM
53
NDB_FUNC_TYPE function_type; // Instead of Item::FUNC_ITEM
54
} NDB_ITEM_QUALIFICATION;
56
typedef struct ndb_item_field_value {
59
} NDB_ITEM_FIELD_VALUE;
61
typedef union ndb_item_value {
63
NDB_ITEM_FIELD_VALUE *field_value;
67
struct negated_function_mapping
69
NDB_FUNC_TYPE pos_fun;
70
NDB_FUNC_TYPE neg_fun;
74
Define what functions can be negated in condition pushdown.
75
Note, these HAVE to be in the same order as in definition enum
77
static const negated_function_mapping neg_map[]=
79
{NDB_EQ_FUNC, NDB_NE_FUNC},
80
{NDB_NE_FUNC, NDB_EQ_FUNC},
81
{NDB_LT_FUNC, NDB_GE_FUNC},
82
{NDB_LE_FUNC, NDB_GT_FUNC},
83
{NDB_GT_FUNC, NDB_LE_FUNC},
84
{NDB_GE_FUNC, NDB_LT_FUNC},
85
{NDB_ISNULL_FUNC, NDB_ISNOTNULL_FUNC},
86
{NDB_ISNOTNULL_FUNC, NDB_ISNULL_FUNC},
87
{NDB_LIKE_FUNC, NDB_NOTLIKE_FUNC},
88
{NDB_NOTLIKE_FUNC, NDB_LIKE_FUNC},
89
{NDB_NOT_FUNC, NDB_UNSUPPORTED_FUNC},
90
{NDB_UNKNOWN_FUNC, NDB_UNSUPPORTED_FUNC},
91
{NDB_COND_AND_FUNC, NDB_UNSUPPORTED_FUNC},
92
{NDB_COND_OR_FUNC, NDB_UNSUPPORTED_FUNC},
93
{NDB_UNSUPPORTED_FUNC, NDB_UNSUPPORTED_FUNC}
97
This class is the construction element for serialization of Item tree
98
in condition pushdown.
99
An instance of Ndb_Item represents a constant, table field reference,
100
unary or binary comparison predicate, and start/end of AND/OR.
101
Instances of Ndb_Item are stored in a linked list implemented by Ndb_cond
103
The order of elements produced by Ndb_cond::next corresponds to
104
breadth-first traversal of the Item (i.e. expression) tree in prefix order.
105
AND and OR have arbitrary arity, so the end of AND/OR group is marked with
106
Ndb_item with type == NDB_END_COND.
107
NOT items represent negated conditions and generate NAND/NOR groups.
109
class Ndb_item : public Sql_alloc
112
Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {};
113
Ndb_item(NDB_ITEM_TYPE item_type,
114
NDB_ITEM_QUALIFICATION item_qualification,
115
const Item *item_value)
116
: type(item_type), qualification(item_qualification)
120
value.item= item_value;
123
NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
124
Item_field *field_item= (Item_field *) item_value;
125
field_value->field= field_item->field;
126
field_value->column_no= -1; // Will be fetched at scan filter generation
127
value.field_value= field_value;
131
value.item= item_value;
132
value.arg_count= ((Item_func *) item_value)->argument_count();
138
Ndb_item(Field *field, int column_no) : type(NDB_FIELD)
140
NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
141
qualification.field_type= field->type();
142
field_value->field= field;
143
field_value->column_no= column_no;
144
value.field_value= field_value;
146
Ndb_item(Item_func::Functype func_type, const Item *item_value)
149
qualification.function_type= item_func_to_ndb_func(func_type);
150
value.item= item_value;
151
value.arg_count= ((Item_func *) item_value)->argument_count();
153
Ndb_item(Item_func::Functype func_type, uint no_args)
156
qualification.function_type= item_func_to_ndb_func(func_type);
157
value.arg_count= no_args;
161
if (type == NDB_FIELD)
163
delete value.field_value;
164
value.field_value= NULL;
172
if(qualification.value_type == Item::STRING_ITEM)
173
return value.item->str_value.length();
176
return value.field_value->field->pack_length();
184
Field * get_field() { return value.field_value->field; };
186
int get_field_no() { return value.field_value->column_no; };
190
return value.arg_count;
193
const char* get_val()
197
if(qualification.value_type == Item::STRING_ITEM)
198
return value.item->str_value.ptr();
201
return (char*) value.field_value->field->ptr;
209
void save_in_field(Ndb_item *field_item)
211
Field *field = field_item->value.field_value->field;
212
const Item *item= value.item;
216
my_bitmap_map *old_map=
217
dbug_tmp_use_all_columns(field->table, field->table->write_set);
218
((Item *)item)->save_in_field(field, FALSE);
219
dbug_tmp_restore_column_map(field->table->write_set, old_map);
223
static NDB_FUNC_TYPE item_func_to_ndb_func(Item_func::Functype fun)
226
case (Item_func::EQ_FUNC): { return NDB_EQ_FUNC; }
227
case (Item_func::NE_FUNC): { return NDB_NE_FUNC; }
228
case (Item_func::LT_FUNC): { return NDB_LT_FUNC; }
229
case (Item_func::LE_FUNC): { return NDB_LE_FUNC; }
230
case (Item_func::GT_FUNC): { return NDB_GT_FUNC; }
231
case (Item_func::GE_FUNC): { return NDB_GE_FUNC; }
232
case (Item_func::ISNULL_FUNC): { return NDB_ISNULL_FUNC; }
233
case (Item_func::ISNOTNULL_FUNC): { return NDB_ISNOTNULL_FUNC; }
234
case (Item_func::LIKE_FUNC): { return NDB_LIKE_FUNC; }
235
case (Item_func::NOT_FUNC): { return NDB_NOT_FUNC; }
236
case (Item_func::NEG_FUNC): { return NDB_UNKNOWN_FUNC; }
237
case (Item_func::UNKNOWN_FUNC): { return NDB_UNKNOWN_FUNC; }
238
case (Item_func::COND_AND_FUNC): { return NDB_COND_AND_FUNC; }
239
case (Item_func::COND_OR_FUNC): { return NDB_COND_OR_FUNC; }
240
default: { return NDB_UNSUPPORTED_FUNC; }
244
static NDB_FUNC_TYPE negate(NDB_FUNC_TYPE fun)
247
DBUG_ASSERT(fun == neg_map[i].pos_fun);
248
return neg_map[i].neg_fun;
252
NDB_ITEM_QUALIFICATION qualification;
254
NDB_ITEM_VALUE value;
258
This class implements a linked list used for storing a
259
serialization of the Item tree for condition pushdown.
261
class Ndb_cond : public Sql_alloc
264
Ndb_cond() : ndb_item(NULL), next(NULL), prev(NULL) {};
267
if (ndb_item) delete ndb_item;
270
First item in the linked list deletes all in a loop
271
Note - doing it recursively causes stack issues for
290
This class implements a stack for storing several conditions
291
for pushdown (represented as serialized Item trees using Ndb_cond).
292
The current implementation only pushes one condition, but is
293
prepared for handling several (C1 AND C2 ...) if the logic for
294
pushing conditions is extended in sql_select.
296
class Ndb_cond_stack : public Sql_alloc
299
Ndb_cond_stack() : ndb_cond(NULL), next(NULL) {};
302
if (ndb_cond) delete ndb_cond;
304
if (next) delete next;
308
Ndb_cond_stack *next;
311
class Ndb_rewrite_context : public Sql_alloc
314
Ndb_rewrite_context(Item_func *func)
315
: func_item(func), left_hand_item(NULL), count(0) {};
316
~Ndb_rewrite_context()
318
if (next) delete next;
320
const Item_func *func_item;
321
const Item *left_hand_item;
323
Ndb_rewrite_context *next;
327
This class is used for storing the context when traversing
328
the Item tree. It stores a reference to the table the condition
329
is defined on, the serialized representation being generated,
330
if the condition found is supported, and information what is
331
expected next in the tree inorder for the condition to be supported.
333
class Ndb_cond_traverse_context : public Sql_alloc
336
Ndb_cond_traverse_context(TABLE *tab, const NdbDictionary::Table *ndb_tab,
337
Ndb_cond_stack* stack)
338
: table(tab), ndb_table(ndb_tab),
339
supported(TRUE), stack_ptr(stack), cond_ptr(NULL),
340
skip(0), collation(NULL), rewrite_stack(NULL)
342
// Allocate type checking bitmaps
343
bitmap_init(&expect_mask, 0, 512, FALSE);
344
bitmap_init(&expect_field_type_mask, 0, 512, FALSE);
345
bitmap_init(&expect_field_result_mask, 0, 512, FALSE);
348
cond_ptr= stack->ndb_cond;
350
~Ndb_cond_traverse_context()
352
bitmap_free(&expect_mask);
353
bitmap_free(&expect_field_type_mask);
354
bitmap_free(&expect_field_result_mask);
355
if (rewrite_stack) delete rewrite_stack;
357
void expect(Item::Type type)
359
bitmap_set_bit(&expect_mask, (uint) type);
360
if (type == Item::FIELD_ITEM) expect_all_field_types();
362
void dont_expect(Item::Type type)
364
bitmap_clear_bit(&expect_mask, (uint) type);
366
bool expecting(Item::Type type)
368
return bitmap_is_set(&expect_mask, (uint) type);
370
void expect_nothing()
372
bitmap_clear_all(&expect_mask);
374
bool expecting_nothing()
376
return bitmap_is_clear_all(&expect_mask);
378
void expect_only(Item::Type type)
384
void expect_field_type(enum_field_types type)
386
bitmap_set_bit(&expect_field_type_mask, (uint) type);
388
void expect_all_field_types()
390
bitmap_set_all(&expect_field_type_mask);
392
bool expecting_field_type(enum_field_types type)
394
return bitmap_is_set(&expect_field_type_mask, (uint) type);
396
void expect_no_field_type()
398
bitmap_clear_all(&expect_field_type_mask);
400
bool expecting_no_field_type()
402
return bitmap_is_clear_all(&expect_field_type_mask);
404
void expect_only_field_type(enum_field_types result)
406
expect_no_field_type();
407
expect_field_type(result);
410
void expect_field_result(Item_result result)
412
bitmap_set_bit(&expect_field_result_mask, (uint) result);
414
bool expecting_field_result(Item_result result)
416
return bitmap_is_set(&expect_field_result_mask, (uint) result);
418
void expect_no_field_result()
420
bitmap_clear_all(&expect_field_result_mask);
422
bool expecting_no_field_result()
424
return bitmap_is_clear_all(&expect_field_result_mask);
426
void expect_only_field_result(Item_result result)
428
expect_no_field_result();
429
expect_field_result(result);
431
void expect_collation(CHARSET_INFO* col)
435
bool expecting_collation(CHARSET_INFO* col)
437
bool matching= (!collation) ? true : (collation == col);
444
const NdbDictionary::Table *ndb_table;
446
Ndb_cond_stack* stack_ptr;
448
MY_BITMAP expect_mask;
449
MY_BITMAP expect_field_type_mask;
450
MY_BITMAP expect_field_result_mask;
452
CHARSET_INFO* collation;
453
Ndb_rewrite_context *rewrite_stack;
458
class ha_ndbcluster_cond
464
~ha_ndbcluster_cond()
465
{ if (m_cond_stack) delete m_cond_stack; }
466
const COND *cond_push(const COND *cond,
467
TABLE *table, const NdbDictionary::Table *ndb_table);
470
int generate_scan_filter(NdbScanOperation* op);
471
int generate_scan_filter_from_cond(NdbScanFilter& filter);
472
int generate_scan_filter_from_key(NdbScanOperation* op,
478
bool serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond,
479
TABLE *table, const NdbDictionary::Table *ndb_table);
480
int build_scan_filter_predicate(Ndb_cond* &cond,
481
NdbScanFilter* filter,
482
bool negated= false);
483
int build_scan_filter_group(Ndb_cond* &cond,
484
NdbScanFilter* filter);
485
int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
487
Ndb_cond_stack *m_cond_stack;