MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ha_ndbcluster_cond.h
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 as published by
7  the Free Software Foundation; version 2 of the License.
8 
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.
13 
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
17 */
18 
19 /*
20  This file defines the data structures used by engine condition pushdown in
21  the NDB Cluster handler
22 */
23 
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
29 } NDB_ITEM_TYPE;
30 
31 typedef enum ndb_func_type {
32  NDB_EQ_FUNC = 0,
33  NDB_NE_FUNC = 1,
34  NDB_LT_FUNC = 2,
35  NDB_LE_FUNC = 3,
36  NDB_GT_FUNC = 4,
37  NDB_GE_FUNC = 5,
38  NDB_ISNULL_FUNC = 6,
39  NDB_ISNOTNULL_FUNC = 7,
40  NDB_LIKE_FUNC = 8,
41  NDB_NOTLIKE_FUNC = 9,
42  NDB_NOT_FUNC = 10,
43  NDB_UNKNOWN_FUNC = 11,
44  NDB_COND_AND_FUNC = 12,
45  NDB_COND_OR_FUNC = 13,
46  NDB_UNSUPPORTED_FUNC = 14
47 } NDB_FUNC_TYPE;
48 
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
54 
55 typedef struct ndb_item_field_value {
56  Field* field;
57  int column_no;
59 
60 typedef union ndb_item_value {
61  const Item *item;
62  NDB_ITEM_FIELD_VALUE *field_value;
63  uint arg_count;
65 
67 {
68  NDB_FUNC_TYPE pos_fun;
69  NDB_FUNC_TYPE neg_fun;
70 };
71 
72 /*
73  Define what functions can be negated in condition pushdown.
74  Note, these HAVE to be in the same order as in definition enum
75 */
76 static const negated_function_mapping neg_map[]=
77 {
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}
93 };
94 
95 /*
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
101  class.
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.
107 */
108 class Ndb_item : public Sql_alloc
109 {
110 public:
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)
116  {
117  switch(item_type) {
118  case(NDB_VALUE):
119  value.item= item_value;
120  break;
121  case(NDB_FIELD): {
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;
127  break;
128  }
129  case(NDB_FUNCTION):
130  value.item= item_value;
131  value.arg_count= ((Item_func *) item_value)->argument_count();
132  break;
133  case(NDB_END_COND):
134  break;
135  }
136  };
137  Ndb_item(Field *field, int column_no) : type(NDB_FIELD)
138  {
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;
144  };
145  Ndb_item(Item_func::Functype func_type, const Item *item_value)
146  : type(NDB_FUNCTION)
147  {
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();
151  };
152  Ndb_item(Item_func::Functype func_type, uint no_args)
153  : type(NDB_FUNCTION)
154  {
155  qualification.function_type= item_func_to_ndb_func(func_type);
156  value.arg_count= no_args;
157  };
158  ~Ndb_item()
159  {
160  if (type == NDB_FIELD)
161  {
162  delete value.field_value;
163  value.field_value= NULL;
164  }
165  };
166 
167  uint32 pack_length()
168  {
169  switch(type) {
170  case(NDB_VALUE):
171  if(qualification.value_type == Item::STRING_ITEM)
172  return value.item->str_value.length();
173  break;
174  case(NDB_FIELD):
175  return value.field_value->field->pack_length();
176  default:
177  break;
178  }
179 
180  return 0;
181  };
182 
183  Field * get_field() { return value.field_value->field; };
184 
185  int get_field_no() { return value.field_value->column_no; };
186 
187  int argument_count()
188  {
189  return value.arg_count;
190  };
191 
192  const char* get_val()
193  {
194  switch(type) {
195  case(NDB_VALUE):
196  if(qualification.value_type == Item::STRING_ITEM)
197  return value.item->str_value.ptr();
198  break;
199  case(NDB_FIELD):
200  return (char*) value.field_value->field->ptr;
201  default:
202  break;
203  }
204 
205  return NULL;
206  };
207 
208  void save_in_field(Ndb_item *field_item)
209  {
210  DBUG_ENTER("save_in_field");
211  Field *field = field_item->value.field_value->field;
212  const Item *item= value.item;
213  if (item && field)
214  {
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)
218  {
219  DBUG_PRINT("info", ("Comparing field with longer value"));
220  DBUG_PRINT("info", ("Field can store %u", field->field_length));
221  }
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);
226  }
227  DBUG_VOID_RETURN;
228  };
229 
230  static NDB_FUNC_TYPE item_func_to_ndb_func(Item_func::Functype fun)
231  {
232  switch (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; }
248  }
249  };
250 
251  static NDB_FUNC_TYPE negate(NDB_FUNC_TYPE fun)
252  {
253  uint i= (uint) fun;
254  DBUG_ASSERT(fun == neg_map[i].pos_fun);
255  return neg_map[i].neg_fun;
256  };
257 
258  NDB_ITEM_TYPE type;
259  NDB_ITEM_QUALIFICATION qualification;
260  private:
261  NDB_ITEM_VALUE value;
262 };
263 
264 /*
265  This class implements a linked list used for storing a
266  serialization of the Item tree for condition pushdown.
267  */
268 class Ndb_cond : public Sql_alloc
269 {
270  public:
271  Ndb_cond() : ndb_item(NULL), next(NULL), prev(NULL) {};
272  ~Ndb_cond()
273  {
274  if (ndb_item) delete ndb_item;
275  ndb_item= NULL;
276  /*
277  First item in the linked list deletes all in a loop
278  Note - doing it recursively causes stack issues for
279  big IN clauses
280  */
281  Ndb_cond *n= next;
282  while (n)
283  {
284  Ndb_cond *tmp= n;
285  n= n->next;
286  tmp->next= NULL;
287  delete tmp;
288  }
289  next= prev= NULL;
290  };
291  Ndb_item *ndb_item;
292  Ndb_cond *next;
293  Ndb_cond *prev;
294 };
295 
296 /*
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.
302 */
303 class Ndb_cond_stack : public Sql_alloc
304 {
305  public:
306  Ndb_cond_stack() : ndb_cond(NULL), next(NULL) {};
307  ~Ndb_cond_stack()
308  {
309  if (ndb_cond) delete ndb_cond;
310  ndb_cond= NULL;
311  if (next) delete next;
312  next= NULL;
313  };
314  Ndb_cond *ndb_cond;
315  Ndb_cond_stack *next;
316 };
317 
318 /*
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>).
327  */
329 {
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;
333  public:
334 Ndb_expect_stack(): collation(NULL), length(0), max_length(0), next(NULL)
335  {
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);
344  };
346  {
347  if (next)
348  delete next;
349  next= NULL;
350  }
351  void push(Ndb_expect_stack* expect_next)
352  {
353  next= expect_next;
354  }
355  void pop()
356  {
357  if (next)
358  {
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;
367  next= next->next;
368  delete expect_next;
369  }
370  }
371  void expect(Item::Type type)
372  {
373  bitmap_set_bit(&expect_mask, (uint) type);
374  if (type == Item::FIELD_ITEM)
375  expect_all_field_types();
376  }
377  void dont_expect(Item::Type type)
378  {
379  bitmap_clear_bit(&expect_mask, (uint) type);
380  }
381  bool expecting(Item::Type type)
382  {
383  if (unlikely((uint)type > MAX_EXPECT_ITEMS))
384  {
385  // Unknown type, can't be expected
386  return false;
387  }
388  return bitmap_is_set(&expect_mask, (uint) type);
389  }
390  void expect_nothing()
391  {
392  bitmap_clear_all(&expect_mask);
393  }
394  bool expecting_nothing()
395  {
396  return bitmap_is_clear_all(&expect_mask);
397  }
398  void expect_only(Item::Type type)
399  {
400  expect_nothing();
401  expect(type);
402  }
403 
404  void expect_field_type(enum_field_types type)
405  {
406  bitmap_set_bit(&expect_field_type_mask, (uint) type);
407  }
408  void expect_all_field_types()
409  {
410  bitmap_set_all(&expect_field_type_mask);
411  }
412  bool expecting_field_type(enum_field_types type)
413  {
414  if (unlikely((uint)type > MAX_EXPECT_FIELD_TYPES))
415  {
416  // Unknown type, can't be expected
417  return false;
418  }
419  return bitmap_is_set(&expect_field_type_mask, (uint) type);
420  }
421  void expect_no_field_type()
422  {
423  bitmap_clear_all(&expect_field_type_mask);
424  }
425  bool expecting_no_field_type()
426  {
427  return bitmap_is_clear_all(&expect_field_type_mask);
428  }
429  void expect_only_field_type(enum_field_types result)
430  {
431  expect_no_field_type();
432  expect_field_type(result);
433  }
434 
435  void expect_field_result(Item_result result)
436  {
437  bitmap_set_bit(&expect_field_result_mask, (uint) result);
438  }
439  bool expecting_field_result(Item_result result)
440  {
441  if (unlikely((uint)result > MAX_EXPECT_FIELD_RESULTS))
442  {
443  // Unknown result, can't be expected
444  return false;
445  }
446  return bitmap_is_set(&expect_field_result_mask,
447  (uint) result);
448  }
449  void expect_no_field_result()
450  {
451  bitmap_clear_all(&expect_field_result_mask);
452  }
453  bool expecting_no_field_result()
454  {
455  return bitmap_is_clear_all(&expect_field_result_mask);
456  }
457  void expect_only_field_result(Item_result result)
458  {
459  expect_no_field_result();
460  expect_field_result(result);
461  }
462  void expect_collation(const CHARSET_INFO* col)
463  {
464  collation= col;
465  }
466  bool expecting_collation(const CHARSET_INFO* col)
467  {
468  bool matching= (!collation)
469  ? true
470  : (collation == col);
471  collation= NULL;
472 
473  return matching;
474  }
475  void expect_length(Uint32 len)
476  {
477  length= len;
478  }
479  void expect_max_length(Uint32 max)
480  {
481  max_length= max;
482  }
483  bool expecting_length(Uint32 len)
484  {
485  return max_length == 0 || len <= max_length;
486  }
487  bool expecting_max_length(Uint32 max)
488  {
489  return max >= length;
490  }
491  void expect_no_length()
492  {
493  length= max_length= 0;
494  }
495 
496 private:
497  my_bitmap_map
498  m_expect_buf[bitmap_buffer_size(MAX_EXPECT_ITEMS)];
499  my_bitmap_map
500  m_expect_field_type_buf[bitmap_buffer_size(MAX_EXPECT_FIELD_TYPES)];
501  my_bitmap_map
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;
507  Uint32 length;
508  Uint32 max_length;
509  Ndb_expect_stack* next;
510 };
511 
513 {
514 public:
516  : func_item(func), left_hand_item(NULL), count(0) {};
518  {
519  if (next) delete next;
520  }
521  const Item_func *func_item;
522  const Item *left_hand_item;
523  uint count;
524  Ndb_rewrite_context *next;
525 };
526 
527 /*
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.
533 */
535 {
536  public:
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)
542  {
543  if (stack)
544  cond_ptr= stack->ndb_cond;
545  }
547  {
548  if (rewrite_stack) delete rewrite_stack;
549  }
550  inline void expect(Item::Type type)
551  {
552  expect_stack.expect(type);
553  }
554  inline void dont_expect(Item::Type type)
555  {
556  expect_stack.dont_expect(type);
557  }
558  inline bool expecting(Item::Type type)
559  {
560  return expect_stack.expecting(type);
561  }
562  inline void expect_nothing()
563  {
564  expect_stack.expect_nothing();
565  }
566  inline bool expecting_nothing()
567  {
568  return expect_stack.expecting_nothing();
569  }
570  inline void expect_only(Item::Type type)
571  {
572  expect_stack.expect_only(type);
573  }
574 
575  inline void expect_field_type(enum_field_types type)
576  {
577  expect_stack.expect_field_type(type);
578  }
579  inline void expect_all_field_types()
580  {
581  expect_stack.expect_all_field_types();
582  }
583  inline bool expecting_field_type(enum_field_types type)
584  {
585  return expect_stack.expecting_field_type(type);
586  }
587  inline void expect_no_field_type()
588  {
589  expect_stack.expect_no_field_type();
590  }
591  inline bool expecting_no_field_type()
592  {
593  return expect_stack.expecting_no_field_type();
594  }
595  inline void expect_only_field_type(enum_field_types result)
596  {
597  expect_stack.expect_only_field_type(result);
598  }
599 
600  inline void expect_field_result(Item_result result)
601  {
602  expect_stack.expect_field_result(result);
603  }
604  inline bool expecting_field_result(Item_result result)
605  {
606  return expect_stack.expecting_field_result(result);
607  }
608  inline void expect_no_field_result()
609  {
610  expect_stack.expect_no_field_result();
611  }
612  inline bool expecting_no_field_result()
613  {
614  return expect_stack.expecting_no_field_result();
615  }
616  inline void expect_only_field_result(Item_result result)
617  {
618  expect_stack.expect_only_field_result(result);
619  }
620  inline void expect_collation(const CHARSET_INFO* col)
621  {
622  expect_stack.expect_collation(col);
623  }
624  inline bool expecting_collation(const CHARSET_INFO* col)
625  {
626  return expect_stack.expecting_collation(col);
627  }
628  inline void expect_length(Uint32 length)
629  {
630  expect_stack.expect_length(length);
631  }
632  inline void expect_max_length(Uint32 max)
633  {
634  expect_stack.expect_max_length(max);
635  }
636  inline bool expecting_length(Uint32 length)
637  {
638  return expect_stack.expecting_length(length);
639  }
640  inline bool expecting_max_length(Uint32 max)
641  {
642  return expect_stack.expecting_max_length(max);
643  }
644  inline void expect_no_length()
645  {
646  expect_stack.expect_no_length();
647  }
648 
649 
650  TABLE* table;
651  const NdbDictionary::Table *ndb_table;
652  bool supported;
653  Ndb_cond_stack* cond_stack;
654  Ndb_cond* cond_ptr;
655  Ndb_expect_stack expect_stack;
656  uint skip;
657  Ndb_rewrite_context *rewrite_stack;
658 };
659 
660 class ha_ndbcluster;
661 
663 {
664 public:
666  : m_cond_stack(NULL)
667  {}
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);
672  void cond_pop();
673  void cond_clear();
674  int generate_scan_filter(NdbInterpretedCode* code,
676  int generate_scan_filter_from_cond(NdbScanFilter& filter);
677  int generate_scan_filter_from_key(NdbInterpretedCode* code,
679  const KEY* key_info,
680  const key_range *start_key,
681  const key_range *end_key,
682  uchar *buf);
683 private:
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);
692 
693  Ndb_cond_stack *m_cond_stack;
694 };