~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to sql/ha_ndbcluster_cond.h

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2007 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/*
 
17
  This file defines the data structures used by engine condition pushdown in
 
18
  the NDB Cluster handler
 
19
*/
 
20
 
 
21
#ifdef USE_PRAGMA_INTERFACE
 
22
#pragma interface                       /* gcc class implementation */
 
23
#endif
 
24
 
 
25
typedef enum ndb_item_type {
 
26
  NDB_VALUE = 0,   // Qualified more with Item::Type
 
27
  NDB_FIELD = 1,   // Qualified from table definition
 
28
  NDB_FUNCTION = 2,// Qualified from Item_func::Functype
 
29
  NDB_END_COND = 3 // End marker for condition group
 
30
} NDB_ITEM_TYPE;
 
31
 
 
32
typedef enum ndb_func_type {
 
33
  NDB_EQ_FUNC = 0,
 
34
  NDB_NE_FUNC = 1,
 
35
  NDB_LT_FUNC = 2,
 
36
  NDB_LE_FUNC = 3,
 
37
  NDB_GT_FUNC = 4,
 
38
  NDB_GE_FUNC = 5,
 
39
  NDB_ISNULL_FUNC = 6,
 
40
  NDB_ISNOTNULL_FUNC = 7,
 
41
  NDB_LIKE_FUNC = 8,
 
42
  NDB_NOTLIKE_FUNC = 9,
 
43
  NDB_NOT_FUNC = 10,
 
44
  NDB_UNKNOWN_FUNC = 11,
 
45
  NDB_COND_AND_FUNC = 12,
 
46
  NDB_COND_OR_FUNC = 13,
 
47
  NDB_UNSUPPORTED_FUNC = 14
 
48
} NDB_FUNC_TYPE;
 
49
 
 
50
typedef union ndb_item_qualification {
 
51
  Item::Type value_type; 
 
52
  enum_field_types field_type; // Instead of Item::FIELD_ITEM
 
53
  NDB_FUNC_TYPE function_type; // Instead of Item::FUNC_ITEM
 
54
} NDB_ITEM_QUALIFICATION;
 
55
 
 
56
typedef struct ndb_item_field_value {
 
57
  Field* field;
 
58
  int column_no;
 
59
} NDB_ITEM_FIELD_VALUE;
 
60
 
 
61
typedef union ndb_item_value {
 
62
  const Item *item;
 
63
  NDB_ITEM_FIELD_VALUE *field_value;
 
64
  uint arg_count;
 
65
} NDB_ITEM_VALUE;
 
66
 
 
67
struct negated_function_mapping
 
68
{
 
69
  NDB_FUNC_TYPE pos_fun;
 
70
  NDB_FUNC_TYPE neg_fun;
 
71
};
 
72
 
 
73
/*
 
74
  Define what functions can be negated in condition pushdown.
 
75
  Note, these HAVE to be in the same order as in definition enum
 
76
*/
 
77
static const negated_function_mapping neg_map[]= 
 
78
{
 
79
  {NDB_EQ_FUNC, NDB_NE_FUNC},
 
80
  {NDB_NE_FUNC, NDB_EQ_FUNC},
 
81
  {NDB_LT_FUNC, NDB_GE_FUNC},
 
82
  {NDB_LE_FUNC, NDB_GT_FUNC},
 
83
  {NDB_GT_FUNC, NDB_LE_FUNC},
 
84
  {NDB_GE_FUNC, NDB_LT_FUNC},
 
85
  {NDB_ISNULL_FUNC, NDB_ISNOTNULL_FUNC},
 
86
  {NDB_ISNOTNULL_FUNC, NDB_ISNULL_FUNC},
 
87
  {NDB_LIKE_FUNC, NDB_NOTLIKE_FUNC},
 
88
  {NDB_NOTLIKE_FUNC, NDB_LIKE_FUNC},
 
89
  {NDB_NOT_FUNC, NDB_UNSUPPORTED_FUNC},
 
90
  {NDB_UNKNOWN_FUNC, NDB_UNSUPPORTED_FUNC},
 
91
  {NDB_COND_AND_FUNC, NDB_UNSUPPORTED_FUNC},
 
92
  {NDB_COND_OR_FUNC, NDB_UNSUPPORTED_FUNC},
 
93
  {NDB_UNSUPPORTED_FUNC, NDB_UNSUPPORTED_FUNC}
 
94
};
 
95
  
 
96
/*
 
97
  This class is the construction element for serialization of Item tree 
 
98
  in condition pushdown.
 
99
  An instance of Ndb_Item represents a constant, table field reference,
 
100
  unary or binary comparison predicate, and start/end of AND/OR.
 
101
  Instances of Ndb_Item are stored in a linked list implemented by Ndb_cond
 
102
  class.
 
103
  The order of elements produced by Ndb_cond::next corresponds to
 
104
  breadth-first traversal of the Item (i.e. expression) tree in prefix order.
 
105
  AND and OR have arbitrary arity, so the end of AND/OR group is marked with  
 
106
  Ndb_item with type == NDB_END_COND.
 
107
  NOT items represent negated conditions and generate NAND/NOR groups.
 
108
*/
 
109
class Ndb_item : public Sql_alloc
 
110
{
 
111
public:
 
112
  Ndb_item(NDB_ITEM_TYPE item_type) : type(item_type) {};
 
113
  Ndb_item(NDB_ITEM_TYPE item_type, 
 
114
           NDB_ITEM_QUALIFICATION item_qualification,
 
115
           const Item *item_value)
 
116
    : type(item_type), qualification(item_qualification)
 
117
  { 
 
118
    switch(item_type) {
 
119
    case(NDB_VALUE):
 
120
      value.item= item_value;
 
121
      break;
 
122
    case(NDB_FIELD): {
 
123
      NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
 
124
      Item_field *field_item= (Item_field *) item_value;
 
125
      field_value->field= field_item->field;
 
126
      field_value->column_no= -1; // Will be fetched at scan filter generation
 
127
      value.field_value= field_value;
 
128
      break;
 
129
    }
 
130
    case(NDB_FUNCTION):
 
131
      value.item= item_value;
 
132
      value.arg_count= ((Item_func *) item_value)->argument_count();
 
133
      break;
 
134
    case(NDB_END_COND):
 
135
      break;
 
136
    }
 
137
  };
 
138
  Ndb_item(Field *field, int column_no) : type(NDB_FIELD)
 
139
  {
 
140
    NDB_ITEM_FIELD_VALUE *field_value= new NDB_ITEM_FIELD_VALUE();
 
141
    qualification.field_type= field->type();
 
142
    field_value->field= field;
 
143
    field_value->column_no= column_no;
 
144
    value.field_value= field_value;
 
145
  };
 
146
  Ndb_item(Item_func::Functype func_type, const Item *item_value) 
 
147
    : type(NDB_FUNCTION)
 
148
  {
 
149
    qualification.function_type= item_func_to_ndb_func(func_type);
 
150
    value.item= item_value;
 
151
    value.arg_count= ((Item_func *) item_value)->argument_count();
 
152
  };
 
153
  Ndb_item(Item_func::Functype func_type, uint no_args) 
 
154
    : type(NDB_FUNCTION)
 
155
  {
 
156
    qualification.function_type= item_func_to_ndb_func(func_type);
 
157
    value.arg_count= no_args;
 
158
  };
 
159
  ~Ndb_item()
 
160
  { 
 
161
    if (type == NDB_FIELD)
 
162
      {
 
163
        delete value.field_value;
 
164
        value.field_value= NULL;
 
165
      }
 
166
  };
 
167
 
 
168
  uint32 pack_length() 
 
169
  { 
 
170
    switch(type) {
 
171
    case(NDB_VALUE):
 
172
      if(qualification.value_type == Item::STRING_ITEM)
 
173
        return value.item->str_value.length();
 
174
      break;
 
175
    case(NDB_FIELD):
 
176
      return value.field_value->field->pack_length(); 
 
177
    default:
 
178
      break;
 
179
    }
 
180
    
 
181
    return 0;
 
182
  };
 
183
 
 
184
  Field * get_field() { return value.field_value->field; };
 
185
 
 
186
  int get_field_no() { return value.field_value->column_no; };
 
187
 
 
188
  int argument_count() 
 
189
  { 
 
190
    return value.arg_count;
 
191
  };
 
192
 
 
193
  const char* get_val() 
 
194
  {  
 
195
    switch(type) {
 
196
    case(NDB_VALUE):
 
197
      if(qualification.value_type == Item::STRING_ITEM)
 
198
        return value.item->str_value.ptr();
 
199
      break;
 
200
    case(NDB_FIELD):
 
201
      return (char*) value.field_value->field->ptr; 
 
202
    default:
 
203
      break;
 
204
    }
 
205
    
 
206
    return NULL;
 
207
  };
 
208
 
 
209
  void save_in_field(Ndb_item *field_item)
 
210
  {
 
211
    Field *field = field_item->value.field_value->field;
 
212
    const Item *item= value.item;
 
213
 
 
214
    if (item && field)
 
215
    {
 
216
      my_bitmap_map *old_map=
 
217
        dbug_tmp_use_all_columns(field->table, field->table->write_set);
 
218
      ((Item *)item)->save_in_field(field, FALSE);
 
219
      dbug_tmp_restore_column_map(field->table->write_set, old_map);
 
220
    }
 
221
  };
 
222
 
 
223
  static NDB_FUNC_TYPE item_func_to_ndb_func(Item_func::Functype fun)
 
224
  {
 
225
    switch (fun) {
 
226
    case (Item_func::EQ_FUNC): { return NDB_EQ_FUNC; }
 
227
    case (Item_func::NE_FUNC): { return NDB_NE_FUNC; }
 
228
    case (Item_func::LT_FUNC): { return NDB_LT_FUNC; }
 
229
    case (Item_func::LE_FUNC): { return NDB_LE_FUNC; }
 
230
    case (Item_func::GT_FUNC): { return NDB_GT_FUNC; }
 
231
    case (Item_func::GE_FUNC): { return NDB_GE_FUNC; }
 
232
    case (Item_func::ISNULL_FUNC): { return NDB_ISNULL_FUNC; }
 
233
    case (Item_func::ISNOTNULL_FUNC): { return NDB_ISNOTNULL_FUNC; }
 
234
    case (Item_func::LIKE_FUNC): { return NDB_LIKE_FUNC; }
 
235
    case (Item_func::NOT_FUNC): { return NDB_NOT_FUNC; }
 
236
    case (Item_func::NEG_FUNC): { return NDB_UNKNOWN_FUNC; }
 
237
    case (Item_func::UNKNOWN_FUNC): { return NDB_UNKNOWN_FUNC; }
 
238
    case (Item_func::COND_AND_FUNC): { return NDB_COND_AND_FUNC; }
 
239
    case (Item_func::COND_OR_FUNC): { return NDB_COND_OR_FUNC; }
 
240
    default: { return NDB_UNSUPPORTED_FUNC; }
 
241
    }
 
242
  };
 
243
 
 
244
  static NDB_FUNC_TYPE negate(NDB_FUNC_TYPE fun)
 
245
  {
 
246
    uint i= (uint) fun;
 
247
    DBUG_ASSERT(fun == neg_map[i].pos_fun);
 
248
    return  neg_map[i].neg_fun;
 
249
  };
 
250
 
 
251
  NDB_ITEM_TYPE type;
 
252
  NDB_ITEM_QUALIFICATION qualification;
 
253
 private:
 
254
  NDB_ITEM_VALUE value;
 
255
};
 
256
 
 
257
/*
 
258
  This class implements a linked list used for storing a
 
259
  serialization of the Item tree for condition pushdown.
 
260
 */
 
261
class Ndb_cond : public Sql_alloc
 
262
{
 
263
 public:
 
264
  Ndb_cond() : ndb_item(NULL), next(NULL), prev(NULL) {};
 
265
  ~Ndb_cond() 
 
266
  { 
 
267
    if (ndb_item) delete ndb_item; 
 
268
    ndb_item= NULL;
 
269
    /*
 
270
      First item in the linked list deletes all in a loop
 
271
      Note - doing it recursively causes stack issues for
 
272
      big IN clauses
 
273
    */
 
274
    Ndb_cond *n= next;
 
275
    while (n)
 
276
    {
 
277
      Ndb_cond *tmp= n;
 
278
      n= n->next;
 
279
      tmp->next= NULL;
 
280
      delete tmp;
 
281
    }
 
282
    next= prev= NULL; 
 
283
  };
 
284
  Ndb_item *ndb_item;
 
285
  Ndb_cond *next;
 
286
  Ndb_cond *prev;
 
287
};
 
288
 
 
289
/*
 
290
  This class implements a stack for storing several conditions
 
291
  for pushdown (represented as serialized Item trees using Ndb_cond).
 
292
  The current implementation only pushes one condition, but is
 
293
  prepared for handling several (C1 AND C2 ...) if the logic for 
 
294
  pushing conditions is extended in sql_select.
 
295
*/
 
296
class Ndb_cond_stack : public Sql_alloc
 
297
{
 
298
 public:
 
299
  Ndb_cond_stack() : ndb_cond(NULL), next(NULL) {};
 
300
  ~Ndb_cond_stack() 
 
301
  { 
 
302
    if (ndb_cond) delete ndb_cond; 
 
303
    ndb_cond= NULL; 
 
304
    if (next) delete next;
 
305
    next= NULL; 
 
306
  };
 
307
  Ndb_cond *ndb_cond;
 
308
  Ndb_cond_stack *next;
 
309
};
 
310
 
 
311
class Ndb_rewrite_context : public Sql_alloc
 
312
{
 
313
public:
 
314
  Ndb_rewrite_context(Item_func *func) 
 
315
    : func_item(func), left_hand_item(NULL), count(0) {};
 
316
  ~Ndb_rewrite_context()
 
317
  {
 
318
    if (next) delete next;
 
319
  }
 
320
  const Item_func *func_item;
 
321
  const Item *left_hand_item;
 
322
  uint count;
 
323
  Ndb_rewrite_context *next;
 
324
};
 
325
 
 
326
/*
 
327
  This class is used for storing the context when traversing
 
328
  the Item tree. It stores a reference to the table the condition
 
329
  is defined on, the serialized representation being generated, 
 
330
  if the condition found is supported, and information what is
 
331
  expected next in the tree inorder for the condition to be supported.
 
332
*/
 
333
class Ndb_cond_traverse_context : public Sql_alloc
 
334
{
 
335
 public:
 
336
   Ndb_cond_traverse_context(TABLE *tab, const NdbDictionary::Table *ndb_tab,
 
337
                             Ndb_cond_stack* stack)
 
338
    : table(tab), ndb_table(ndb_tab), 
 
339
    supported(TRUE), stack_ptr(stack), cond_ptr(NULL),
 
340
    skip(0), collation(NULL), rewrite_stack(NULL)
 
341
  {
 
342
    // Allocate type checking bitmaps   
 
343
    bitmap_init(&expect_mask, 0, 512, FALSE);
 
344
    bitmap_init(&expect_field_type_mask, 0, 512, FALSE);
 
345
    bitmap_init(&expect_field_result_mask, 0, 512, FALSE);
 
346
 
 
347
    if (stack)
 
348
      cond_ptr= stack->ndb_cond;
 
349
  };
 
350
  ~Ndb_cond_traverse_context()
 
351
  {
 
352
    bitmap_free(&expect_mask);
 
353
    bitmap_free(&expect_field_type_mask);
 
354
    bitmap_free(&expect_field_result_mask);
 
355
    if (rewrite_stack) delete rewrite_stack;
 
356
  }
 
357
  void expect(Item::Type type)
 
358
  {
 
359
    bitmap_set_bit(&expect_mask, (uint) type);
 
360
    if (type == Item::FIELD_ITEM) expect_all_field_types();
 
361
  };
 
362
  void dont_expect(Item::Type type)
 
363
  {
 
364
    bitmap_clear_bit(&expect_mask, (uint) type);
 
365
  };
 
366
  bool expecting(Item::Type type)
 
367
  {
 
368
    return bitmap_is_set(&expect_mask, (uint) type);
 
369
  };
 
370
  void expect_nothing()
 
371
  {
 
372
    bitmap_clear_all(&expect_mask);
 
373
  };
 
374
  bool expecting_nothing()
 
375
  {
 
376
    return bitmap_is_clear_all(&expect_mask);
 
377
  }
 
378
  void expect_only(Item::Type type)
 
379
  {
 
380
    expect_nothing();
 
381
    expect(type);
 
382
  };
 
383
 
 
384
  void expect_field_type(enum_field_types type)
 
385
  {
 
386
    bitmap_set_bit(&expect_field_type_mask, (uint) type);
 
387
  };
 
388
  void expect_all_field_types()
 
389
  {
 
390
    bitmap_set_all(&expect_field_type_mask);
 
391
  };
 
392
  bool expecting_field_type(enum_field_types type)
 
393
  {
 
394
    return bitmap_is_set(&expect_field_type_mask, (uint) type);
 
395
  };
 
396
  void expect_no_field_type()
 
397
  {
 
398
    bitmap_clear_all(&expect_field_type_mask);
 
399
  };
 
400
  bool expecting_no_field_type()
 
401
  {
 
402
    return bitmap_is_clear_all(&expect_field_type_mask);
 
403
  }
 
404
  void expect_only_field_type(enum_field_types result)
 
405
  {
 
406
    expect_no_field_type();
 
407
    expect_field_type(result);
 
408
  };
 
409
 
 
410
  void expect_field_result(Item_result result)
 
411
  {
 
412
    bitmap_set_bit(&expect_field_result_mask, (uint) result);
 
413
  };
 
414
  bool expecting_field_result(Item_result result)
 
415
  {
 
416
    return bitmap_is_set(&expect_field_result_mask, (uint) result);
 
417
  };
 
418
  void expect_no_field_result()
 
419
  {
 
420
    bitmap_clear_all(&expect_field_result_mask);
 
421
  };
 
422
  bool expecting_no_field_result()
 
423
  {
 
424
    return bitmap_is_clear_all(&expect_field_result_mask);
 
425
  }
 
426
  void expect_only_field_result(Item_result result)
 
427
  {
 
428
    expect_no_field_result();
 
429
    expect_field_result(result);
 
430
  };
 
431
  void expect_collation(CHARSET_INFO* col)
 
432
  {
 
433
    collation= col;
 
434
  };
 
435
  bool expecting_collation(CHARSET_INFO* col)
 
436
  {
 
437
    bool matching= (!collation) ? true : (collation == col);
 
438
    collation= NULL;
 
439
 
 
440
    return matching;
 
441
  };
 
442
 
 
443
  TABLE* table;
 
444
  const NdbDictionary::Table *ndb_table;
 
445
  bool supported;
 
446
  Ndb_cond_stack* stack_ptr;
 
447
  Ndb_cond* cond_ptr;
 
448
  MY_BITMAP expect_mask;
 
449
  MY_BITMAP expect_field_type_mask;
 
450
  MY_BITMAP expect_field_result_mask;
 
451
  uint skip;
 
452
  CHARSET_INFO* collation;
 
453
  Ndb_rewrite_context *rewrite_stack;
 
454
};
 
455
 
 
456
class ha_ndbcluster;
 
457
 
 
458
class ha_ndbcluster_cond
 
459
{
 
460
public:
 
461
  ha_ndbcluster_cond() 
 
462
  : m_cond_stack(NULL)
 
463
  {}
 
464
  ~ha_ndbcluster_cond() 
 
465
  { if (m_cond_stack) delete m_cond_stack; }
 
466
  const COND *cond_push(const COND *cond, 
 
467
                        TABLE *table, const NdbDictionary::Table *ndb_table);
 
468
  void cond_pop();
 
469
  void cond_clear();
 
470
  int generate_scan_filter(NdbScanOperation* op);
 
471
  int generate_scan_filter_from_cond(NdbScanFilter& filter);
 
472
  int generate_scan_filter_from_key(NdbScanOperation* op,
 
473
                                    const KEY* key_info, 
 
474
                                    const uchar *key, 
 
475
                                    uint key_len,
 
476
                                    uchar *buf);
 
477
private:
 
478
  bool serialize_cond(const COND *cond, Ndb_cond_stack *ndb_cond,
 
479
                      TABLE *table, const NdbDictionary::Table *ndb_table);
 
480
  int build_scan_filter_predicate(Ndb_cond* &cond, 
 
481
                                  NdbScanFilter* filter,
 
482
                                  bool negated= false);
 
483
  int build_scan_filter_group(Ndb_cond* &cond, 
 
484
                              NdbScanFilter* filter);
 
485
  int build_scan_filter(Ndb_cond* &cond, NdbScanFilter* filter);
 
486
 
 
487
  Ndb_cond_stack *m_cond_stack;
 
488
};