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