1 /*
2 Copyright (c) 2000, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
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
25 /*
26 This file defines the data structures used by engine condition pushdown in
27 the NDB Cluster handler
28 */
29
30 typedef enum ndb_item_type {
31 NDB_VALUE = 0, // Qualified more with Item::Type
32 NDB_FIELD = 1, // Qualified from table definition
33 NDB_FUNCTION = 2,// Qualified from Item_func::Functype
34 NDB_END_COND = 3 // End marker for condition group
35 } NDB_ITEM_TYPE;
36
37 typedef enum ndb_func_type {
38 NDB_EQ_FUNC = 0,
39 NDB_NE_FUNC = 1,
40 NDB_LT_FUNC = 2,
41 NDB_LE_FUNC = 3,
42 NDB_GT_FUNC = 4,
43 NDB_GE_FUNC = 5,
44 NDB_ISNULL_FUNC = 6,
45 NDB_ISNOTNULL_FUNC = 7,
46 NDB_LIKE_FUNC = 8,
47 NDB_NOTLIKE_FUNC = 9,
48 NDB_NOT_FUNC = 10,
49 NDB_UNKNOWN_FUNC = 11,
50 NDB_COND_AND_FUNC = 12,
51 NDB_COND_OR_FUNC = 13,
52 NDB_UNSUPPORTED_FUNC = 14
53 } NDB_FUNC_TYPE;
54
55 typedef union ndb_item_qualification {
56 Item::Type value_type;
57 enum_field_types field_type; // Instead of Item::FIELD_ITEM
58 NDB_FUNC_TYPE function_type; // Instead of Item::FUNC_ITEM
59 } NDB_ITEM_QUALIFICATION;
60
61 typedef struct ndb_item_field_value {
62 Field* field;
63 int column_no;
64 } NDB_ITEM_FIELD_VALUE;
65
66 typedef union ndb_item_value {
67 const Item *item;
68 NDB_ITEM_FIELD_VALUE *field_value;
69 uint arg_count;
70 } NDB_ITEM_VALUE;
71
72 struct negated_function_mapping
73 {
74 NDB_FUNC_TYPE pos_fun;
75 NDB_FUNC_TYPE neg_fun;
76 };
77
78 /*
79 Define what functions can be negated in condition pushdown.
80 Note, these HAVE to be in the same order as in definition enum
81 */
82 static const negated_function_mapping neg_map[]=
83 {
84 {NDB_EQ_FUNC, NDB_NE_FUNC},
85 {NDB_NE_FUNC, NDB_EQ_FUNC},
86 {NDB_LT_FUNC, NDB_GE_FUNC},
87 {NDB_LE_FUNC, NDB_GT_FUNC},
88 {NDB_GT_FUNC, NDB_LE_FUNC},
89 {NDB_GE_FUNC, NDB_LT_FUNC},
90 {NDB_ISNULL_FUNC, NDB_ISNOTNULL_FUNC},
91 {NDB_ISNOTNULL_FUNC, NDB_ISNULL_FUNC},
92 {NDB_LIKE_FUNC, NDB_NOTLIKE_FUNC},
93 {NDB_NOTLIKE_FUNC, NDB_LIKE_FUNC},
94 {NDB_NOT_FUNC, NDB_UNSUPPORTED_FUNC},
95 {NDB_UNKNOWN_FUNC, NDB_UNSUPPORTED_FUNC},
96 {NDB_COND_AND_FUNC, NDB_UNSUPPORTED_FUNC},
97 {NDB_COND_OR_FUNC, NDB_UNSUPPORTED_FUNC},
98 {NDB_UNSUPPORTED_FUNC, NDB_UNSUPPORTED_FUNC}
99 };
100
101 /*
102 This class is the construction element for serialization of Item tree
103 in condition pushdown.
104 An instance of Ndb_Item represents a constant, table field reference,
105 unary or binary comparison predicate, and start/end of AND/OR.
106 Instances of Ndb_Item are stored in a linked list implemented by Ndb_cond
107 class.
108 The order of elements produced by Ndb_cond::next corresponds to
109 breadth-first traversal of the Item (i.e. expression) tree in prefix order.
110 AND and OR have arbitrary arity, so the end of AND/OR group is marked with
111 Ndb_item with type == NDB_END_COND.
112 NOT items represent negated conditions and generate NAND/NOR groups.
113 */
114 class Ndb_item : public Sql_alloc
115 {
116 public:
Ndb_item(NDB_ITEM_TYPE item_type)117 Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {}
Ndb_item(NDB_ITEM_TYPE item_type,NDB_ITEM_QUALIFICATION item_qualification,const Item * item_value)118 Ndb_item(NDB_ITEM_TYPE item_type,
119 NDB_ITEM_QUALIFICATION item_qualification,
120 const Item *item_value)
121 : type(item_type), qualification(item_qualification)
122 {
123 switch(item_type) {
124 case(NDB_VALUE):
125 value.item= item_value;
126 break;
127 case(NDB_FIELD): {
128 NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
129 Item_field *field_item= (Item_field *) item_value;
130 field_value->field= field_item->field;
131 field_value->column_no= -1; // Will be fetched at scan filter generation
132 value.field_value= field_value;
133 break;
134 }
135 case(NDB_FUNCTION):
136 value.item= item_value;
137 value.arg_count= ((Item_func *) item_value)->argument_count();
138 break;
139 case(NDB_END_COND):
140 break;
141 }
142 }
Ndb_item(Field * field,int column_no)143 Ndb_item(Field *field, int column_no) : type(NDB_FIELD)
144 {
145 NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
146 qualification.field_type= field->real_type();
147 field_value->field= field;
148 field_value->column_no= column_no;
149 value.field_value= field_value;
150 }
Ndb_item(Item_func::Functype func_type,const Item * item_value)151 Ndb_item(Item_func::Functype func_type, const Item *item_value)
152 : type(NDB_FUNCTION)
153 {
154 qualification.function_type= item_func_to_ndb_func(func_type);
155 value.item= item_value;
156 value.arg_count= ((Item_func *) item_value)->argument_count();
157 }
Ndb_item(Item_func::Functype func_type,uint no_args)158 Ndb_item(Item_func::Functype func_type, uint no_args)
159 : type(NDB_FUNCTION)
160 {
161 qualification.function_type= item_func_to_ndb_func(func_type);
162 value.arg_count= no_args;
163 }
~Ndb_item()164 ~Ndb_item()
165 {
166 if (type == NDB_FIELD)
167 {
168 delete value.field_value;
169 value.field_value= NULL;
170 }
171 }
172
pack_length()173 uint32 pack_length()
174 {
175 switch(type) {
176 case(NDB_VALUE):
177 if(qualification.value_type == Item::STRING_ITEM)
178 return value.item->str_value.length();
179 break;
180 case(NDB_FIELD):
181 return value.field_value->field->pack_length();
182 default:
183 break;
184 }
185
186 return 0;
187 }
188
get_field()189 Field * get_field() { return value.field_value->field; }
190
get_field_no()191 int get_field_no() { return value.field_value->column_no; }
192
argument_count()193 int argument_count()
194 {
195 return value.arg_count;
196 }
197
get_val()198 const char* get_val()
199 {
200 switch(type) {
201 case(NDB_VALUE):
202 if(qualification.value_type == Item::STRING_ITEM)
203 return value.item->str_value.ptr();
204 break;
205 case(NDB_FIELD):
206 return (char*) value.field_value->field->ptr;
207 case(NDB_FUNCTION):
208 if(qualification.value_type == Item::STRING_ITEM)
209 return value.item->str_value.ptr();
210 default:
211 break;
212 }
213
214 return NULL;
215 }
216
get_field_charset()217 const CHARSET_INFO *get_field_charset()
218 {
219 Field *field= get_field();
220 if (field)
221 return field->charset();
222
223 return NULL;
224 }
225
get_field_val_str(String * str)226 String *get_field_val_str(String *str)
227 {
228 Field *field= get_field();
229 if (field)
230 return field->val_str(str);
231
232 return NULL;
233 }
234
is_const_func()235 bool is_const_func()
236 {
237 const Item *item= value.item;
238
239 if (item->type() == Item::FUNC_ITEM)
240 {
241 Item_func *func_item= (Item_func *) item;
242 if (func_item->const_item())
243 return true;
244 }
245 return false;
246 }
247
is_cached()248 bool is_cached()
249 {
250 const Item *item= value.item;
251
252 return (item->type() == Item::CACHE_ITEM);
253 }
254
255
save_in_field(Ndb_item * field_item)256 uint32 save_in_field(Ndb_item *field_item)
257 {
258 uint32 length= 0;
259 DBUG_ENTER("save_in_field");
260 Field *field = field_item->value.field_value->field;
261 const Item *item= value.item;
262 if (item && field)
263 {
264 length= item->max_length;
265 my_bitmap_map *old_map=
266 dbug_tmp_use_all_columns(field->table, field->table->write_set);
267 ((Item *)item)->save_in_field(field, false);
268 dbug_tmp_restore_column_map(field->table->write_set, old_map);
269 }
270 DBUG_RETURN(length);
271 }
272
item_func_to_ndb_func(Item_func::Functype fun)273 static NDB_FUNC_TYPE item_func_to_ndb_func(Item_func::Functype fun)
274 {
275 switch (fun) {
276 case (Item_func::EQ_FUNC): { return NDB_EQ_FUNC; }
277 case (Item_func::NE_FUNC): { return NDB_NE_FUNC; }
278 case (Item_func::LT_FUNC): { return NDB_LT_FUNC; }
279 case (Item_func::LE_FUNC): { return NDB_LE_FUNC; }
280 case (Item_func::GT_FUNC): { return NDB_GT_FUNC; }
281 case (Item_func::GE_FUNC): { return NDB_GE_FUNC; }
282 case (Item_func::ISNULL_FUNC): { return NDB_ISNULL_FUNC; }
283 case (Item_func::ISNOTNULL_FUNC): { return NDB_ISNOTNULL_FUNC; }
284 case (Item_func::LIKE_FUNC): { return NDB_LIKE_FUNC; }
285 case (Item_func::NOT_FUNC): { return NDB_NOT_FUNC; }
286 case (Item_func::NEG_FUNC): { return NDB_UNKNOWN_FUNC; }
287 case (Item_func::UNKNOWN_FUNC): { return NDB_UNKNOWN_FUNC; }
288 case (Item_func::COND_AND_FUNC): { return NDB_COND_AND_FUNC; }
289 case (Item_func::COND_OR_FUNC): { return NDB_COND_OR_FUNC; }
290 default: { return NDB_UNSUPPORTED_FUNC; }
291 }
292 }
293
negate(NDB_FUNC_TYPE fun)294 static NDB_FUNC_TYPE negate(NDB_FUNC_TYPE fun)
295 {
296 uint i= (uint) fun;
297 assert(fun == neg_map[i].pos_fun);
298 return neg_map[i].neg_fun;
299 }
300
301 NDB_ITEM_TYPE type;
302 NDB_ITEM_QUALIFICATION qualification;
303 private:
304 NDB_ITEM_VALUE value;
305 };
306
307 /*
308 This class implements a linked list used for storing a
309 serialization of the Item tree for condition pushdown.
310 */
311 class Ndb_cond : public Sql_alloc
312 {
313 public:
Ndb_cond()314 Ndb_cond() : ndb_item(NULL), next(NULL), prev(NULL) {}
~Ndb_cond()315 ~Ndb_cond()
316 {
317 if (ndb_item) delete ndb_item;
318 ndb_item= NULL;
319 /*
320 First item in the linked list deletes all in a loop
321 Note - doing it recursively causes stack issues for
322 big IN clauses
323 */
324 Ndb_cond *n= next;
325 while (n)
326 {
327 Ndb_cond *tmp= n;
328 n= n->next;
329 tmp->next= NULL;
330 delete tmp;
331 }
332 next= prev= NULL;
333 }
334 Ndb_item *ndb_item;
335 Ndb_cond *next;
336 Ndb_cond *prev;
337 };
338
339 /*
340 This class implements a stack for storing several conditions
341 for pushdown (represented as serialized Item trees using Ndb_cond).
342 The current implementation only pushes one condition, but is
343 prepared for handling several (C1 AND C2 ...) if the logic for
344 pushing conditions is extended in sql_select.
345 */
346 class Ndb_cond_stack : public Sql_alloc
347 {
348 public:
Ndb_cond_stack()349 Ndb_cond_stack() : ndb_cond(NULL), next(NULL) {}
~Ndb_cond_stack()350 ~Ndb_cond_stack()
351 {
352 if (ndb_cond) delete ndb_cond;
353 ndb_cond= NULL;
354 if (next) delete next;
355 next= NULL;
356 }
357 Ndb_cond *ndb_cond;
358 Ndb_cond_stack *next;
359 };
360
361 /*
362 This class implements look-ahead during the parsing
363 of the item tree. It contains bit masks for expected
364 items, field types and field results. It also contains
365 expected collation. The parse context (Ndb_cond_traverse_context)
366 always contains one expect_stack instance (top of the stack).
367 More expects (deeper look-ahead) can be pushed to the expect_stack
368 to check specific order (currently used for detecting support for
369 <field> LIKE <string>|<func>, but not <string>|<func> LIKE <field>).
370 */
371 class Ndb_expect_stack : public Sql_alloc
372 {
373 static const uint MAX_EXPECT_ITEMS = Item::VIEW_FIXER_ITEM + 1;
374 static const uint MAX_EXPECT_FIELD_TYPES = MYSQL_TYPE_GEOMETRY + 1;
375 static const uint MAX_EXPECT_FIELD_RESULTS = DECIMAL_RESULT + 1;
376 public:
Ndb_expect_stack()377 Ndb_expect_stack(): collation(NULL), length(0), max_length(0), next(NULL)
378 {
379 // Allocate type checking bitmaps using fixed size buffers
380 // since max size is known at compile time
381 bitmap_init(&expect_mask, m_expect_buf,
382 MAX_EXPECT_ITEMS, FALSE);
383 bitmap_init(&expect_field_type_mask, m_expect_field_type_buf,
384 MAX_EXPECT_FIELD_TYPES, FALSE);
385 bitmap_init(&expect_field_result_mask, m_expect_field_result_buf,
386 MAX_EXPECT_FIELD_RESULTS, FALSE);
387 }
~Ndb_expect_stack()388 ~Ndb_expect_stack()
389 {
390 if (next)
391 delete next;
392 next= NULL;
393 }
push(Ndb_expect_stack * expect_next)394 void push(Ndb_expect_stack* expect_next)
395 {
396 next= expect_next;
397 }
pop()398 void pop()
399 {
400 if (next)
401 {
402 Ndb_expect_stack* expect_next= next;
403 bitmap_clear_all(&expect_mask);
404 bitmap_union(&expect_mask, &next->expect_mask);
405 bitmap_clear_all(&expect_field_type_mask);
406 bitmap_union(&expect_field_type_mask, &next->expect_field_type_mask);
407 bitmap_clear_all(&expect_field_result_mask);
408 bitmap_union(&expect_field_result_mask, &next->expect_field_result_mask);
409 collation= next->collation;
410 next= next->next;
411 delete expect_next;
412 }
413 }
expect(Item::Type type)414 void expect(Item::Type type)
415 {
416 bitmap_set_bit(&expect_mask, (uint) type);
417 if (type == Item::FIELD_ITEM)
418 expect_all_field_types();
419 }
dont_expect(Item::Type type)420 void dont_expect(Item::Type type)
421 {
422 bitmap_clear_bit(&expect_mask, (uint) type);
423 }
expecting(Item::Type type)424 bool expecting(Item::Type type)
425 {
426 if (unlikely((uint)type > MAX_EXPECT_ITEMS))
427 {
428 // Unknown type, can't be expected
429 return false;
430 }
431 return bitmap_is_set(&expect_mask, (uint) type);
432 }
expect_nothing()433 void expect_nothing()
434 {
435 bitmap_clear_all(&expect_mask);
436 }
expecting_nothing()437 bool expecting_nothing()
438 {
439 return bitmap_is_clear_all(&expect_mask);
440 }
expect_only(Item::Type type)441 void expect_only(Item::Type type)
442 {
443 expect_nothing();
444 expect(type);
445 }
446
expect_field_type(enum_field_types type)447 void expect_field_type(enum_field_types type)
448 {
449 bitmap_set_bit(&expect_field_type_mask, (uint) type);
450 }
expect_all_field_types()451 void expect_all_field_types()
452 {
453 bitmap_set_all(&expect_field_type_mask);
454 }
expecting_field_type(enum_field_types type)455 bool expecting_field_type(enum_field_types type)
456 {
457 if (unlikely((uint)type > MAX_EXPECT_FIELD_TYPES))
458 {
459 // Unknown type, can't be expected
460 return false;
461 }
462 return bitmap_is_set(&expect_field_type_mask, (uint) type);
463 }
expect_no_field_type()464 void expect_no_field_type()
465 {
466 bitmap_clear_all(&expect_field_type_mask);
467 }
expecting_no_field_type()468 bool expecting_no_field_type()
469 {
470 return bitmap_is_clear_all(&expect_field_type_mask);
471 }
expect_only_field_type(enum_field_types result)472 void expect_only_field_type(enum_field_types result)
473 {
474 expect_no_field_type();
475 expect_field_type(result);
476 }
477
expect_field_result(Item_result result)478 void expect_field_result(Item_result result)
479 {
480 bitmap_set_bit(&expect_field_result_mask, (uint) result);
481 }
expecting_field_result(Item_result result)482 bool expecting_field_result(Item_result result)
483 {
484 if (unlikely((uint)result > MAX_EXPECT_FIELD_RESULTS))
485 {
486 // Unknown result, can't be expected
487 return false;
488 }
489 return bitmap_is_set(&expect_field_result_mask,
490 (uint) result);
491 }
expect_no_field_result()492 void expect_no_field_result()
493 {
494 bitmap_clear_all(&expect_field_result_mask);
495 }
expecting_no_field_result()496 bool expecting_no_field_result()
497 {
498 return bitmap_is_clear_all(&expect_field_result_mask);
499 }
expect_only_field_result(Item_result result)500 void expect_only_field_result(Item_result result)
501 {
502 expect_no_field_result();
503 expect_field_result(result);
504 }
expect_collation(const CHARSET_INFO * col)505 void expect_collation(const CHARSET_INFO* col)
506 {
507 collation= col;
508 }
expecting_collation(const CHARSET_INFO * col)509 bool expecting_collation(const CHARSET_INFO* col)
510 {
511 bool matching= (!collation)
512 ? true
513 : (collation == col);
514 collation= NULL;
515
516 return matching;
517 }
expect_length(Uint32 len)518 void expect_length(Uint32 len)
519 {
520 length= len;
521 }
expect_max_length(Uint32 max)522 void expect_max_length(Uint32 max)
523 {
524 max_length= max;
525 }
expecting_length(Uint32 len)526 bool expecting_length(Uint32 len)
527 {
528 return max_length == 0 || len <= max_length;
529 }
expecting_max_length(Uint32 max)530 bool expecting_max_length(Uint32 max)
531 {
532 return max >= length;
533 }
expect_no_length()534 void expect_no_length()
535 {
536 length= max_length= 0;
537 }
538
539 private:
540 my_bitmap_map
541 m_expect_buf[bitmap_buffer_size(MAX_EXPECT_ITEMS)];
542 my_bitmap_map
543 m_expect_field_type_buf[bitmap_buffer_size(MAX_EXPECT_FIELD_TYPES)];
544 my_bitmap_map
545 m_expect_field_result_buf[bitmap_buffer_size(MAX_EXPECT_FIELD_RESULTS)];
546 MY_BITMAP expect_mask;
547 MY_BITMAP expect_field_type_mask;
548 MY_BITMAP expect_field_result_mask;
549 const CHARSET_INFO* collation;
550 Uint32 length;
551 Uint32 max_length;
552 Ndb_expect_stack* next;
553 };
554
555 class Ndb_rewrite_context : public Sql_alloc
556 {
557 public:
Ndb_rewrite_context(Item_func * func)558 Ndb_rewrite_context(Item_func *func)
559 : func_item(func), left_hand_item(NULL), count(0) {}
~Ndb_rewrite_context()560 ~Ndb_rewrite_context()
561 {
562 if (next) delete next;
563 }
564 const Item_func *func_item;
565 const Item *left_hand_item;
566 uint count;
567 Ndb_rewrite_context *next;
568 };
569
570 /*
571 This class is used for storing the context when traversing
572 the Item tree. It stores a reference to the table the condition
573 is defined on, the serialized representation being generated,
574 if the condition found is supported, and information what is
575 expected next in the tree inorder for the condition to be supported.
576 */
577 class Ndb_cond_traverse_context : public Sql_alloc
578 {
579 public:
Ndb_cond_traverse_context(TABLE * tab,const NdbDictionary::Table * ndb_tab,Ndb_cond_stack * stack)580 Ndb_cond_traverse_context(TABLE *tab, const NdbDictionary::Table *ndb_tab,
581 Ndb_cond_stack* stack)
582 : table(tab), ndb_table(ndb_tab),
583 supported(TRUE), cond_stack(stack), cond_ptr(NULL),
584 skip(0), rewrite_stack(NULL)
585 {
586 if (stack)
587 cond_ptr= stack->ndb_cond;
588 }
~Ndb_cond_traverse_context()589 ~Ndb_cond_traverse_context()
590 {
591 if (rewrite_stack) delete rewrite_stack;
592 }
expect(Item::Type type)593 inline void expect(Item::Type type)
594 {
595 expect_stack.expect(type);
596 }
dont_expect(Item::Type type)597 inline void dont_expect(Item::Type type)
598 {
599 expect_stack.dont_expect(type);
600 }
expecting(Item::Type type)601 inline bool expecting(Item::Type type)
602 {
603 return expect_stack.expecting(type);
604 }
expect_nothing()605 inline void expect_nothing()
606 {
607 expect_stack.expect_nothing();
608 }
expecting_nothing()609 inline bool expecting_nothing()
610 {
611 return expect_stack.expecting_nothing();
612 }
expect_only(Item::Type type)613 inline void expect_only(Item::Type type)
614 {
615 expect_stack.expect_only(type);
616 }
617
expect_field_type(enum_field_types type)618 inline void expect_field_type(enum_field_types type)
619 {
620 expect_stack.expect_field_type(type);
621 }
expect_all_field_types()622 inline void expect_all_field_types()
623 {
624 expect_stack.expect_all_field_types();
625 }
expecting_field_type(enum_field_types type)626 inline bool expecting_field_type(enum_field_types type)
627 {
628 return expect_stack.expecting_field_type(type);
629 }
expect_no_field_type()630 inline void expect_no_field_type()
631 {
632 expect_stack.expect_no_field_type();
633 }
expecting_no_field_type()634 inline bool expecting_no_field_type()
635 {
636 return expect_stack.expecting_no_field_type();
637 }
expect_only_field_type(enum_field_types result)638 inline void expect_only_field_type(enum_field_types result)
639 {
640 expect_stack.expect_only_field_type(result);
641 }
642
expect_field_result(Item_result result)643 inline void expect_field_result(Item_result result)
644 {
645 expect_stack.expect_field_result(result);
646 }
expecting_field_result(Item_result result)647 inline bool expecting_field_result(Item_result result)
648 {
649 return expect_stack.expecting_field_result(result);
650 }
expect_no_field_result()651 inline void expect_no_field_result()
652 {
653 expect_stack.expect_no_field_result();
654 }
expecting_no_field_result()655 inline bool expecting_no_field_result()
656 {
657 return expect_stack.expecting_no_field_result();
658 }
expect_only_field_result(Item_result result)659 inline void expect_only_field_result(Item_result result)
660 {
661 expect_stack.expect_only_field_result(result);
662 }
expect_collation(const CHARSET_INFO * col)663 inline void expect_collation(const CHARSET_INFO* col)
664 {
665 expect_stack.expect_collation(col);
666 }
expecting_collation(const CHARSET_INFO * col)667 inline bool expecting_collation(const CHARSET_INFO* col)
668 {
669 return expect_stack.expecting_collation(col);
670 }
expect_length(Uint32 length)671 inline void expect_length(Uint32 length)
672 {
673 expect_stack.expect_length(length);
674 }
expect_max_length(Uint32 max)675 inline void expect_max_length(Uint32 max)
676 {
677 expect_stack.expect_max_length(max);
678 }
expecting_length(Uint32 length)679 inline bool expecting_length(Uint32 length)
680 {
681 return expect_stack.expecting_length(length);
682 }
expecting_max_length(Uint32 max)683 inline bool expecting_max_length(Uint32 max)
684 {
685 return expect_stack.expecting_max_length(max);
686 }
expect_no_length()687 inline void expect_no_length()
688 {
689 expect_stack.expect_no_length();
690 }
691
692
693 TABLE* table;
694 const NdbDictionary::Table *ndb_table;
695 bool supported;
696 Ndb_cond_stack* cond_stack;
697 Ndb_cond* cond_ptr;
698 Ndb_expect_stack expect_stack;
699 uint skip;
700 Ndb_rewrite_context *rewrite_stack;
701 };
702
703 class ha_ndbcluster;
704
705 class ha_ndbcluster_cond
706 {
707 public:
ha_ndbcluster_cond()708 ha_ndbcluster_cond()
709 : m_cond_stack(NULL)
710 {}
~ha_ndbcluster_cond()711 ~ha_ndbcluster_cond()
712 { if (m_cond_stack) delete m_cond_stack; }
713 const Item *cond_push(const Item *cond,
714 TABLE *table, const NdbDictionary::Table *ndb_table);
715 void cond_pop();
716 void cond_clear();
717 int generate_scan_filter(NdbInterpretedCode* code,
718 NdbScanOperation::ScanOptions* options) const;
719 int generate_scan_filter_from_cond(NdbScanFilter& filter) const;
720 int generate_scan_filter_from_key(NdbInterpretedCode* code,
721 NdbScanOperation::ScanOptions* options,
722 const KEY* key_info,
723 const key_range *start_key,
724 const key_range *end_key) const;
725 private:
726 bool serialize_cond(const Item *cond, Ndb_cond_stack *ndb_cond,
727 TABLE *table,
728 const NdbDictionary::Table *ndb_table) const;
729 int build_scan_filter_predicate(Ndb_cond* &cond,
730 NdbScanFilter* filter,
731 bool negated= false) const;
732 int build_scan_filter_group(Ndb_cond* &cond,
733 NdbScanFilter* filter) const;
734 int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter) const;
735
736 Ndb_cond_stack *m_cond_stack;
737 };
738