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