2
Copyright (C) 2000-2007 MySQL AB
3
All rights reserved. Use is subject to license terms.
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
This file defines the data structures used by engine condition pushdown in
21
the NDB Cluster handler
24
typedef enum ndb_item_type {
25
NDB_VALUE = 0, // Qualified more with Item::Type
26
NDB_FIELD = 1, // Qualified from table definition
27
NDB_FUNCTION = 2,// Qualified from Item_func::Functype
28
NDB_END_COND = 3 // End marker for condition group
31
typedef enum ndb_func_type {
39
NDB_ISNOTNULL_FUNC = 7,
43
NDB_UNKNOWN_FUNC = 11,
44
NDB_COND_AND_FUNC = 12,
45
NDB_COND_OR_FUNC = 13,
46
NDB_UNSUPPORTED_FUNC = 14
49
typedef union ndb_item_qualification {
50
Item::Type value_type;
51
enum_field_types field_type; // Instead of Item::FIELD_ITEM
52
NDB_FUNC_TYPE function_type; // Instead of Item::FUNC_ITEM
53
} NDB_ITEM_QUALIFICATION;
55
typedef struct ndb_item_field_value {
58
} NDB_ITEM_FIELD_VALUE;
60
typedef union ndb_item_value {
62
NDB_ITEM_FIELD_VALUE *field_value;
66
struct negated_function_mapping
68
NDB_FUNC_TYPE pos_fun;
69
NDB_FUNC_TYPE neg_fun;
73
Define what functions can be negated in condition pushdown.
74
Note, these HAVE to be in the same order as in definition enum
76
static const negated_function_mapping neg_map[]=
78
{NDB_EQ_FUNC, NDB_NE_FUNC},
79
{NDB_NE_FUNC, NDB_EQ_FUNC},
80
{NDB_LT_FUNC, NDB_GE_FUNC},
81
{NDB_LE_FUNC, NDB_GT_FUNC},
82
{NDB_GT_FUNC, NDB_LE_FUNC},
83
{NDB_GE_FUNC, NDB_LT_FUNC},
84
{NDB_ISNULL_FUNC, NDB_ISNOTNULL_FUNC},
85
{NDB_ISNOTNULL_FUNC, NDB_ISNULL_FUNC},
86
{NDB_LIKE_FUNC, NDB_NOTLIKE_FUNC},
87
{NDB_NOTLIKE_FUNC, NDB_LIKE_FUNC},
88
{NDB_NOT_FUNC, NDB_UNSUPPORTED_FUNC},
89
{NDB_UNKNOWN_FUNC, NDB_UNSUPPORTED_FUNC},
90
{NDB_COND_AND_FUNC, NDB_UNSUPPORTED_FUNC},
91
{NDB_COND_OR_FUNC, NDB_UNSUPPORTED_FUNC},
92
{NDB_UNSUPPORTED_FUNC, NDB_UNSUPPORTED_FUNC}
96
This class is the construction element for serialization of Item tree
97
in condition pushdown.
98
An instance of Ndb_Item represents a constant, table field reference,
99
unary or binary comparison predicate, and start/end of AND/OR.
100
Instances of Ndb_Item are stored in a linked list implemented by Ndb_cond
102
The order of elements produced by Ndb_cond::next corresponds to
103
breadth-first traversal of the Item (i.e. expression) tree in prefix order.
104
AND and OR have arbitrary arity, so the end of AND/OR group is marked with
105
Ndb_item with type == NDB_END_COND.
106
NOT items represent negated conditions and generate NAND/NOR groups.
108
class Ndb_item : public Sql_alloc
111
Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {};
112
Ndb_item(NDB_ITEM_TYPE item_type,
113
NDB_ITEM_QUALIFICATION item_qualification,
114
const Item *item_value)
115
: type(item_type), qualification(item_qualification)
119
value.item= item_value;
122
NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
123
Item_field *field_item= (Item_field *) item_value;
124
field_value->field= field_item->field;
125
field_value->column_no= -1; // Will be fetched at scan filter generation
126
value.field_value= field_value;
130
value.item= item_value;
131
value.arg_count= ((Item_func *) item_value)->argument_count();
137
Ndb_item(Field *field, int column_no) : type(NDB_FIELD)
139
NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
140
qualification.field_type= field->real_type();
141
field_value->field= field;
142
field_value->column_no= column_no;
143
value.field_value= field_value;
145
Ndb_item(Item_func::Functype func_type, const Item *item_value)
148
qualification.function_type= item_func_to_ndb_func(func_type);
149
value.item= item_value;
150
value.arg_count= ((Item_func *) item_value)->argument_count();
152
Ndb_item(Item_func::Functype func_type, uint no_args)
155
qualification.function_type= item_func_to_ndb_func(func_type);
156
value.arg_count= no_args;
160
if (type == NDB_FIELD)
162
delete value.field_value;
163
value.field_value= NULL;
171
if(qualification.value_type == Item::STRING_ITEM)
172
return value.item->str_value.length();
175
return value.field_value->field->pack_length();
183
Field * get_field() { return value.field_value->field; };
185
int get_field_no() { return value.field_value->column_no; };
189
return value.arg_count;
192
const char* get_val()
196
if(qualification.value_type == Item::STRING_ITEM)
197
return value.item->str_value.ptr();
200
return (char*) value.field_value->field->ptr;
208
void save_in_field(Ndb_item *field_item)
210
DBUG_ENTER("save_in_field");
211
Field *field = field_item->value.field_value->field;
212
const Item *item= value.item;
215
DBUG_PRINT("info", ("item length %u, field length %u",
216
item->max_length, field->field_length));
217
if (item->max_length > field->field_length)
219
DBUG_PRINT("info", ("Comparing field with longer value"));
220
DBUG_PRINT("info", ("Field can store %u", field->field_length));
222
my_bitmap_map *old_map=
223
dbug_tmp_use_all_columns(field->table, field->table->write_set);
224
((Item *)item)->save_in_field(field, FALSE);
225
dbug_tmp_restore_column_map(field->table->write_set, old_map);
230
static NDB_FUNC_TYPE item_func_to_ndb_func(Item_func::Functype fun)
233
case (Item_func::EQ_FUNC): { return NDB_EQ_FUNC; }
234
case (Item_func::NE_FUNC): { return NDB_NE_FUNC; }
235
case (Item_func::LT_FUNC): { return NDB_LT_FUNC; }
236
case (Item_func::LE_FUNC): { return NDB_LE_FUNC; }
237
case (Item_func::GT_FUNC): { return NDB_GT_FUNC; }
238
case (Item_func::GE_FUNC): { return NDB_GE_FUNC; }
239
case (Item_func::ISNULL_FUNC): { return NDB_ISNULL_FUNC; }
240
case (Item_func::ISNOTNULL_FUNC): { return NDB_ISNOTNULL_FUNC; }
241
case (Item_func::LIKE_FUNC): { return NDB_LIKE_FUNC; }
242
case (Item_func::NOT_FUNC): { return NDB_NOT_FUNC; }
243
case (Item_func::NEG_FUNC): { return NDB_UNKNOWN_FUNC; }
244
case (Item_func::UNKNOWN_FUNC): { return NDB_UNKNOWN_FUNC; }
245
case (Item_func::COND_AND_FUNC): { return NDB_COND_AND_FUNC; }
246
case (Item_func::COND_OR_FUNC): { return NDB_COND_OR_FUNC; }
247
default: { return NDB_UNSUPPORTED_FUNC; }
251
static NDB_FUNC_TYPE negate(NDB_FUNC_TYPE fun)
254
DBUG_ASSERT(fun == neg_map[i].pos_fun);
255
return neg_map[i].neg_fun;
259
NDB_ITEM_QUALIFICATION qualification;
261
NDB_ITEM_VALUE value;
265
This class implements a linked list used for storing a
266
serialization of the Item tree for condition pushdown.
268
class Ndb_cond : public Sql_alloc
271
Ndb_cond() : ndb_item(NULL), next(NULL), prev(NULL) {};
274
if (ndb_item) delete ndb_item;
277
First item in the linked list deletes all in a loop
278
Note - doing it recursively causes stack issues for
297
This class implements a stack for storing several conditions
298
for pushdown (represented as serialized Item trees using Ndb_cond).
299
The current implementation only pushes one condition, but is
300
prepared for handling several (C1 AND C2 ...) if the logic for
301
pushing conditions is extended in sql_select.
303
class Ndb_cond_stack : public Sql_alloc
306
Ndb_cond_stack() : ndb_cond(NULL), next(NULL) {};
309
if (ndb_cond) delete ndb_cond;
311
if (next) delete next;
315
Ndb_cond_stack *next;
319
This class implements look-ahead during the parsing
320
of the item tree. It contains bit masks for expected
321
items, field types and field results. It also contains
322
expected collation. The parse context (Ndb_cond_traverse_context)
323
always contains one expect_stack instance (top of the stack).
324
More expects (deeper look-ahead) can be pushed to the expect_stack
325
to check specific order (currently used for detecting support for
326
<field> LIKE <string>|<func>, but not <string>|<func> LIKE <field>).
328
class Ndb_expect_stack : public Sql_alloc
330
static const uint MAX_EXPECT_ITEMS = Item::VIEW_FIXER_ITEM + 1;
331
static const uint MAX_EXPECT_FIELD_TYPES = MYSQL_TYPE_GEOMETRY + 1;
332
static const uint MAX_EXPECT_FIELD_RESULTS = DECIMAL_RESULT + 1;
334
Ndb_expect_stack(): collation(NULL), length(0), max_length(0), next(NULL)
336
// Allocate type checking bitmaps using fixed size buffers
337
// since max size is known at compile time
338
bitmap_init(&expect_mask, m_expect_buf,
339
MAX_EXPECT_ITEMS, FALSE);
340
bitmap_init(&expect_field_type_mask, m_expect_field_type_buf,
341
MAX_EXPECT_FIELD_TYPES, FALSE);
342
bitmap_init(&expect_field_result_mask, m_expect_field_result_buf,
343
MAX_EXPECT_FIELD_RESULTS, FALSE);
351
void push(Ndb_expect_stack* expect_next)
359
Ndb_expect_stack* expect_next= next;
360
bitmap_clear_all(&expect_mask);
361
bitmap_union(&expect_mask, &next->expect_mask);
362
bitmap_clear_all(&expect_field_type_mask);
363
bitmap_union(&expect_field_type_mask, &next->expect_field_type_mask);
364
bitmap_clear_all(&expect_field_result_mask);
365
bitmap_union(&expect_field_result_mask, &next->expect_field_result_mask);
366
collation= next->collation;
371
void expect(Item::Type type)
373
bitmap_set_bit(&expect_mask, (uint) type);
374
if (type == Item::FIELD_ITEM)
375
expect_all_field_types();
377
void dont_expect(Item::Type type)
379
bitmap_clear_bit(&expect_mask, (uint) type);
381
bool expecting(Item::Type type)
383
if (unlikely((uint)type > MAX_EXPECT_ITEMS))
385
// Unknown type, can't be expected
388
return bitmap_is_set(&expect_mask, (uint) type);
390
void expect_nothing()
392
bitmap_clear_all(&expect_mask);
394
bool expecting_nothing()
396
return bitmap_is_clear_all(&expect_mask);
398
void expect_only(Item::Type type)
404
void expect_field_type(enum_field_types type)
406
bitmap_set_bit(&expect_field_type_mask, (uint) type);
408
void expect_all_field_types()
410
bitmap_set_all(&expect_field_type_mask);
412
bool expecting_field_type(enum_field_types type)
414
if (unlikely((uint)type > MAX_EXPECT_FIELD_TYPES))
416
// Unknown type, can't be expected
419
return bitmap_is_set(&expect_field_type_mask, (uint) type);
421
void expect_no_field_type()
423
bitmap_clear_all(&expect_field_type_mask);
425
bool expecting_no_field_type()
427
return bitmap_is_clear_all(&expect_field_type_mask);
429
void expect_only_field_type(enum_field_types result)
431
expect_no_field_type();
432
expect_field_type(result);
435
void expect_field_result(Item_result result)
437
bitmap_set_bit(&expect_field_result_mask, (uint) result);
439
bool expecting_field_result(Item_result result)
441
if (unlikely((uint)result > MAX_EXPECT_FIELD_RESULTS))
443
// Unknown result, can't be expected
446
return bitmap_is_set(&expect_field_result_mask,
449
void expect_no_field_result()
451
bitmap_clear_all(&expect_field_result_mask);
453
bool expecting_no_field_result()
455
return bitmap_is_clear_all(&expect_field_result_mask);
457
void expect_only_field_result(Item_result result)
459
expect_no_field_result();
460
expect_field_result(result);
462
void expect_collation(const CHARSET_INFO* col)
466
bool expecting_collation(const CHARSET_INFO* col)
468
bool matching= (!collation)
470
: (collation == col);
475
void expect_length(Uint32 len)
479
void expect_max_length(Uint32 max)
483
bool expecting_length(Uint32 len)
485
return max_length == 0 || len <= max_length;
487
bool expecting_max_length(Uint32 max)
489
return max >= length;
491
void expect_no_length()
493
length= max_length= 0;
498
m_expect_buf[bitmap_buffer_size(MAX_EXPECT_ITEMS)];
500
m_expect_field_type_buf[bitmap_buffer_size(MAX_EXPECT_FIELD_TYPES)];
502
m_expect_field_result_buf[bitmap_buffer_size(MAX_EXPECT_FIELD_RESULTS)];
503
MY_BITMAP expect_mask;
504
MY_BITMAP expect_field_type_mask;
505
MY_BITMAP expect_field_result_mask;
506
const CHARSET_INFO* collation;
509
Ndb_expect_stack* next;
512
class Ndb_rewrite_context : public Sql_alloc
515
Ndb_rewrite_context(Item_func *func)
516
: func_item(func), left_hand_item(NULL), count(0) {};
517
~Ndb_rewrite_context()
519
if (next) delete next;
521
const Item_func *func_item;
522
const Item *left_hand_item;
524
Ndb_rewrite_context *next;
528
This class is used for storing the context when traversing
529
the Item tree. It stores a reference to the table the condition
530
is defined on, the serialized representation being generated,
531
if the condition found is supported, and information what is
532
expected next in the tree inorder for the condition to be supported.
534
class Ndb_cond_traverse_context : public Sql_alloc
537
Ndb_cond_traverse_context(TABLE *tab, const NdbDictionary::Table *ndb_tab,
538
Ndb_cond_stack* stack)
539
: table(tab), ndb_table(ndb_tab),
540
supported(TRUE), cond_stack(stack), cond_ptr(NULL),
541
skip(0), rewrite_stack(NULL)
544
cond_ptr= stack->ndb_cond;
546
~Ndb_cond_traverse_context()
548
if (rewrite_stack) delete rewrite_stack;
550
inline void expect(Item::Type type)
552
expect_stack.expect(type);
554
inline void dont_expect(Item::Type type)
556
expect_stack.dont_expect(type);
558
inline bool expecting(Item::Type type)
560
return expect_stack.expecting(type);
562
inline void expect_nothing()
564
expect_stack.expect_nothing();
566
inline bool expecting_nothing()
568
return expect_stack.expecting_nothing();
570
inline void expect_only(Item::Type type)
572
expect_stack.expect_only(type);
575
inline void expect_field_type(enum_field_types type)
577
expect_stack.expect_field_type(type);
579
inline void expect_all_field_types()
581
expect_stack.expect_all_field_types();
583
inline bool expecting_field_type(enum_field_types type)
585
return expect_stack.expecting_field_type(type);
587
inline void expect_no_field_type()
589
expect_stack.expect_no_field_type();
591
inline bool expecting_no_field_type()
593
return expect_stack.expecting_no_field_type();
595
inline void expect_only_field_type(enum_field_types result)
597
expect_stack.expect_only_field_type(result);
600
inline void expect_field_result(Item_result result)
602
expect_stack.expect_field_result(result);
604
inline bool expecting_field_result(Item_result result)
606
return expect_stack.expecting_field_result(result);
608
inline void expect_no_field_result()
610
expect_stack.expect_no_field_result();
612
inline bool expecting_no_field_result()
614
return expect_stack.expecting_no_field_result();
616
inline void expect_only_field_result(Item_result result)
618
expect_stack.expect_only_field_result(result);
620
inline void expect_collation(const CHARSET_INFO* col)
622
expect_stack.expect_collation(col);
624
inline bool expecting_collation(const CHARSET_INFO* col)
626
return expect_stack.expecting_collation(col);
628
inline void expect_length(Uint32 length)
630
expect_stack.expect_length(length);
632
inline void expect_max_length(Uint32 max)
634
expect_stack.expect_max_length(max);
636
inline bool expecting_length(Uint32 length)
638
return expect_stack.expecting_length(length);
640
inline bool expecting_max_length(Uint32 max)
642
return expect_stack.expecting_max_length(max);
644
inline void expect_no_length()
646
expect_stack.expect_no_length();
651
const NdbDictionary::Table *ndb_table;
653
Ndb_cond_stack* cond_stack;
655
Ndb_expect_stack expect_stack;
657
Ndb_rewrite_context *rewrite_stack;
662
class ha_ndbcluster_cond
668
~ha_ndbcluster_cond()
669
{ if (m_cond_stack) delete m_cond_stack; }
670
const Item *cond_push(const Item *cond,
671
TABLE *table, const NdbDictionary::Table *ndb_table);
674
int generate_scan_filter(NdbInterpretedCode* code,
675
NdbScanOperation::ScanOptions* options);
676
int generate_scan_filter_from_cond(NdbScanFilter& filter);
677
int generate_scan_filter_from_key(NdbInterpretedCode* code,
678
NdbScanOperation::ScanOptions* options,
680
const key_range *start_key,
681
const key_range *end_key,
684
bool serialize_cond(const Item *cond, Ndb_cond_stack *ndb_cond,
685
TABLE *table, const NdbDictionary::Table *ndb_table);
686
int build_scan_filter_predicate(Ndb_cond* &cond,
687
NdbScanFilter* filter,
688
bool negated= false);
689
int build_scan_filter_group(Ndb_cond* &cond,
690
NdbScanFilter* filter);
691
int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
693
Ndb_cond_stack *m_cond_stack;