~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/key_field.cc

  • Committer: Stewart Smith
  • Date: 2010-02-15 03:55:09 UTC
  • mto: (1273.13.96 build)
  • mto: This revision was merged to the branch mainline in revision 1308.
  • Revision ID: stewart@flamingspork.com-20100215035509-y6sry4q4yymph2by
move SUBSTR, SUBSTRING and SUBSTR_INDEX to plugins. add parser hooks for substr being a plugin now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008-2009 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
#include <drizzled/sql_select.h>
 
23
#include <drizzled/nested_join.h>
 
24
#include <drizzled/item/cmpfunc.h>
 
25
#include "drizzled/optimizer/key_field.h"
 
26
#include "drizzled/optimizer/key_use.h"
 
27
 
 
28
#include <vector>
 
29
 
 
30
using namespace std;
 
31
 
 
32
namespace drizzled
 
33
{
 
34
 
 
35
void optimizer::add_key_part(DYNAMIC_ARRAY *keyuse_array,
 
36
                             optimizer::KeyField *key_field)
 
37
{
 
38
  Field *field= key_field->getField();
 
39
  Table *form= field->table;
 
40
 
 
41
  if (key_field->isEqualityCondition() &&
 
42
      ! (key_field->getOptimizeFlags() & KEY_OPTIMIZE_EXISTS))
 
43
  {
 
44
    for (uint32_t key= 0; key < form->sizeKeys(); key++)
 
45
    {
 
46
      if (! (form->keys_in_use_for_query.test(key)))
 
47
        continue;
 
48
 
 
49
      uint32_t key_parts= (uint32_t) form->key_info[key].key_parts;
 
50
      for (uint32_t part= 0; part < key_parts; part++)
 
51
      {
 
52
        if (field->eq(form->key_info[key].key_part[part].field))
 
53
        {
 
54
          optimizer::KeyUse keyuse(field->table,
 
55
                                   key_field->getValue(),
 
56
                                   key_field->getValue()->used_tables(),
 
57
                                   key,
 
58
                                   part,
 
59
                                   key_field->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL,
 
60
                                   1 << part,
 
61
                                   0,
 
62
                                   key_field->rejectNullValues(),
 
63
                                   key_field->getConditionalGuard());
 
64
          insert_dynamic(keyuse_array, (unsigned char*) &keyuse);
 
65
        }
 
66
      }
 
67
    }
 
68
  }
 
69
}
 
70
 
 
71
void optimizer::add_key_fields_for_nj(JOIN *join,
 
72
                                      TableList *nested_join_table,
 
73
                                      optimizer::KeyField **end,
 
74
                                      uint32_t *and_level,
 
75
                                      vector<optimizer::SargableParam> &sargables)
 
76
{
 
77
  List_iterator<TableList> li(nested_join_table->nested_join->join_list);
 
78
  List_iterator<TableList> li2(nested_join_table->nested_join->join_list);
 
79
  bool have_another= false;
 
80
  table_map tables= 0;
 
81
  TableList *table;
 
82
  assert(nested_join_table->nested_join);
 
83
 
 
84
  while ((table= li++) || (have_another && (li=li2, have_another=false,
 
85
                                            (table= li++))))
 
86
  {
 
87
    if (table->nested_join)
 
88
    {
 
89
      if (! table->on_expr)
 
90
      {
 
91
        /* It's a semi-join nest. Walk into it as if it wasn't a nest */
 
92
        have_another= true;
 
93
        li2= li;
 
94
        li= List_iterator<TableList>(table->nested_join->join_list);
 
95
      }
 
96
      else
 
97
        add_key_fields_for_nj(join, table, end, and_level, sargables);
 
98
    }
 
99
    else
 
100
      if (! table->on_expr)
 
101
        tables|= table->table->map;
 
102
  }
 
103
  if (nested_join_table->on_expr)
 
104
  {
 
105
    add_key_fields(join,
 
106
                   end,
 
107
                   and_level,
 
108
                   nested_join_table->on_expr,
 
109
                   tables,
 
110
                   sargables);
 
111
  }
 
112
}
 
113
 
 
114
optimizer::KeyField *optimizer::merge_key_fields(optimizer::KeyField *start,
 
115
                                                 optimizer::KeyField *new_fields,
 
116
                                                 optimizer::KeyField *end,
 
117
                                                 uint32_t and_level)
 
118
{
 
119
  if (start == new_fields)
 
120
    return start;                               // Impossible or
 
121
  if (new_fields == end)
 
122
    return start;                               // No new fields, skip all
 
123
 
 
124
  optimizer::KeyField *first_free= new_fields;
 
125
 
 
126
  /* Mark all found fields in old array */
 
127
  for (; new_fields != end; new_fields++)
 
128
  {
 
129
    for (optimizer::KeyField *old= start; old != first_free; old++)
 
130
    {
 
131
      if (old->getField() == new_fields->getField())
 
132
      {
 
133
        /*
 
134
          NOTE: below const_item() call really works as "!used_tables()", i.e.
 
135
          it can return false where it is feasible to make it return true.
 
136
 
 
137
          The cause is as follows: Some of the tables are already known to be
 
138
          const tables (the detection code is in make_join_statistics(),
 
139
          above the update_ref_and_keys() call), but we didn't propagate
 
140
          information about this: Table::const_table is not set to true, and
 
141
          Item::update_used_tables() hasn't been called for each item.
 
142
          The result of this is that we're missing some 'ref' accesses.
 
143
          TODO: OptimizerTeam: Fix this
 
144
        */
 
145
        if (! new_fields->getValue()->const_item())
 
146
        {
 
147
          /*
 
148
            If the value matches, we can use the key reference.
 
149
            If not, we keep it until we have examined all new values
 
150
          */
 
151
          if (old->getValue()->eq(new_fields->getValue(), old->getField()->binary()))
 
152
          {
 
153
            old->setLevel(and_level);
 
154
            old->setOptimizeFlags(((old->getOptimizeFlags() &
 
155
                                    new_fields->getOptimizeFlags() &
 
156
                                    KEY_OPTIMIZE_EXISTS) |
 
157
                                   ((old->getOptimizeFlags() |
 
158
                                     new_fields->getOptimizeFlags()) &
 
159
                                    KEY_OPTIMIZE_REF_OR_NULL)));
 
160
            old->setRejectNullValues(old->rejectNullValues() &&
 
161
                                     new_fields->rejectNullValues());
 
162
          }
 
163
        }
 
164
        else if (old->isEqualityCondition() &&
 
165
                 new_fields->isEqualityCondition() &&
 
166
                 old->getValue()->eq_by_collation(new_fields->getValue(),
 
167
                                                  old->getField()->binary(),
 
168
                                                  old->getField()->charset()))
 
169
 
 
170
        {
 
171
          old->setLevel(and_level);
 
172
          old->setOptimizeFlags(((old->getOptimizeFlags() &
 
173
                                  new_fields->getOptimizeFlags() &
 
174
                                  KEY_OPTIMIZE_EXISTS) |
 
175
                                 ((old->getOptimizeFlags() |
 
176
                                   new_fields->getOptimizeFlags()) &
 
177
                                 KEY_OPTIMIZE_REF_OR_NULL)));
 
178
          old->setRejectNullValues(old->rejectNullValues() &&
 
179
                                   new_fields->rejectNullValues());
 
180
        }
 
181
        else if (old->isEqualityCondition() &&
 
182
                 new_fields->isEqualityCondition() &&
 
183
                 ((old->getValue()->const_item() &&
 
184
                   old->getValue()->is_null()) ||
 
185
                   new_fields->getValue()->is_null()))
 
186
        {
 
187
          /* field = expression OR field IS NULL */
 
188
          old->setLevel(and_level);
 
189
          old->setOptimizeFlags(KEY_OPTIMIZE_REF_OR_NULL);
 
190
          /*
 
191
            Remember the NOT NULL value unless the value does not depend
 
192
            on other tables.
 
193
           */
 
194
          if (! old->getValue()->used_tables() &&
 
195
              old->getValue()->is_null())
 
196
          {
 
197
            old->setValue(new_fields->getValue());
 
198
          }
 
199
          /* The referred expression can be NULL: */
 
200
          old->setRejectNullValues(false);
 
201
        }
 
202
        else
 
203
        {
 
204
          /*
 
205
            We are comparing two different const.  In this case we can't
 
206
            use a key-lookup on this so it's better to remove the value
 
207
            and let the range optimzier handle it
 
208
          */
 
209
          if (old == --first_free)              // If last item
 
210
            break;
 
211
          *old= *first_free;                    // Remove old value
 
212
          old--;                                // Retry this value
 
213
        }
 
214
      }
 
215
    }
 
216
  }
 
217
  /* Remove all not used items */
 
218
  for (optimizer::KeyField *old= start; old != first_free;)
 
219
  {
 
220
    if (old->getLevel() != and_level)
 
221
    {                                           // Not used in all levels
 
222
      if (old == --first_free)
 
223
        break;
 
224
      *old= *first_free;                        // Remove old value
 
225
      continue;
 
226
    }
 
227
    old++;
 
228
  }
 
229
  return first_free;
 
230
}
 
231
 
 
232
void optimizer::add_key_field(optimizer::KeyField **key_fields,
 
233
                              uint32_t and_level,
 
234
                              Item_func *cond,
 
235
                              Field *field,
 
236
                              bool eq_func,
 
237
                              Item **value,
 
238
                              uint32_t num_values,
 
239
                              table_map usable_tables,
 
240
                              vector<optimizer::SargableParam> &sargables)
 
241
{
 
242
  uint32_t exists_optimize= 0;
 
243
  if (! (field->flags & PART_KEY_FLAG))
 
244
  {
 
245
    // Don't remove column IS NULL on a LEFT JOIN table
 
246
    if (! eq_func || (*value)->type() != Item::NULL_ITEM ||
 
247
        ! field->table->maybe_null || field->null_ptr)
 
248
      return;                                   // Not a key. Skip it
 
249
    exists_optimize= KEY_OPTIMIZE_EXISTS;
 
250
    assert(num_values == 1);
 
251
  }
 
252
  else
 
253
  {
 
254
    table_map used_tables= 0;
 
255
    bool optimizable= 0;
 
256
    for (uint32_t i= 0; i < num_values; i++)
 
257
    {
 
258
      used_tables|= (value[i])->used_tables();
 
259
      if (! ((value[i])->used_tables() & (field->table->map | RAND_TABLE_BIT)))
 
260
        optimizable= 1;
 
261
    }
 
262
    if (! optimizable)
 
263
      return;
 
264
    if (! (usable_tables & field->table->map))
 
265
    {
 
266
      if (! eq_func || (*value)->type() != Item::NULL_ITEM ||
 
267
          ! field->table->maybe_null || field->null_ptr)
 
268
        return;                                 // Can't use left join optimize
 
269
      exists_optimize= KEY_OPTIMIZE_EXISTS;
 
270
    }
 
271
    else
 
272
    {
 
273
      JoinTable *stat= field->table->reginfo.join_tab;
 
274
      key_map possible_keys= field->key_start;
 
275
      possible_keys&= field->table->keys_in_use_for_query;
 
276
      stat[0].keys|= possible_keys;             // Add possible keys
 
277
 
 
278
      /*
 
279
        Save the following cases:
 
280
        Field op constant
 
281
        Field LIKE constant where constant doesn't start with a wildcard
 
282
        Field = field2 where field2 is in a different table
 
283
        Field op formula
 
284
        Field IS NULL
 
285
        Field IS NOT NULL
 
286
        Field BETWEEN ...
 
287
        Field IN ...
 
288
      */
 
289
      stat[0].key_dependent|= used_tables;
 
290
 
 
291
      bool is_const= 1;
 
292
      for (uint32_t i= 0; i < num_values; i++)
 
293
      {
 
294
        if (! (is_const&= value[i]->const_item()))
 
295
          break;
 
296
      }
 
297
      if (is_const)
 
298
        stat[0].const_keys|= possible_keys;
 
299
      else if (! eq_func)
 
300
      {
 
301
        /*
 
302
          Save info to be able check whether this predicate can be
 
303
          considered as sargable for range analisis after reading const tables.
 
304
          We do not save info about equalities as update_const_equal_items
 
305
          will take care of updating info on keys from sargable equalities.
 
306
        */
 
307
        optimizer::SargableParam tmp(field, value, num_values);
 
308
        sargables.push_back(tmp);
 
309
      }
 
310
      /*
 
311
        We can't always use indexes when comparing a string index to a
 
312
        number. cmp_type() is checked to allow compare of dates to numbers.
 
313
        eq_func is NEVER true when num_values > 1
 
314
       */
 
315
      if (! eq_func)
 
316
      {
 
317
        /*
 
318
          Additional optimization: if we're processing
 
319
          "t.key BETWEEN c1 AND c1" then proceed as if we were processing
 
320
          "t.key = c1".
 
321
          TODO: This is a very limited fix. A more generic fix is possible.
 
322
          There are 2 options:
 
323
          A) Make equality propagation code be able to handle BETWEEN
 
324
             (including cases like t1.key BETWEEN t2.key AND t3.key)
 
325
          B) Make range optimizer to infer additional "t.key = c" equalities
 
326
             and use them in equality propagation process (see details in
 
327
             OptimizerKBAndTodo)
 
328
        */
 
329
        if ((cond->functype() != Item_func::BETWEEN) ||
 
330
            ((Item_func_between*) cond)->negated ||
 
331
            ! value[0]->eq(value[1], field->binary()))
 
332
          return;
 
333
        eq_func= true;
 
334
      }
 
335
 
 
336
      if (field->result_type() == STRING_RESULT)
 
337
      {
 
338
        if ((*value)->result_type() != STRING_RESULT)
 
339
        {
 
340
          if (field->cmp_type() != (*value)->result_type())
 
341
            return;
 
342
        }
 
343
        else
 
344
        {
 
345
          /*
 
346
            We can't use indexes if the effective collation
 
347
            of the operation differ from the field collation.
 
348
          */
 
349
          if (field->cmp_type() == STRING_RESULT &&
 
350
              ((Field_str*)field)->charset() != cond->compare_collation())
 
351
            return;
 
352
        }
 
353
      }
 
354
    }
 
355
  }
 
356
  /*
 
357
    For the moment eq_func is always true. This slot is reserved for future
 
358
    extensions where we want to remembers other things than just eq comparisons
 
359
  */
 
360
  assert(eq_func);
 
361
  /* Store possible eq field */
 
362
  (*key_fields)->setField(field);
 
363
  (*key_fields)->setEqualityConditionUsed(eq_func);
 
364
  (*key_fields)->setValue(*value);
 
365
  (*key_fields)->setLevel(and_level);
 
366
  (*key_fields)->setOptimizeFlags(exists_optimize);
 
367
  /*
 
368
    If the condition has form "tbl.keypart = othertbl.field" and
 
369
    othertbl.field can be NULL, there will be no matches if othertbl.field
 
370
    has NULL value.
 
371
    We use null_rejecting in add_not_null_conds() to add
 
372
    'othertbl.field IS NOT NULL' to tab->select_cond.
 
373
  */
 
374
  (*key_fields)->setRejectNullValues((cond->functype() == Item_func::EQ_FUNC ||
 
375
                                      cond->functype() == Item_func::MULT_EQUAL_FUNC) &&
 
376
                                     ((*value)->type() == Item::FIELD_ITEM) &&
 
377
                                     ((Item_field*)*value)->field->maybe_null());
 
378
  (*key_fields)->setConditionalGuard(NULL);
 
379
  (*key_fields)++;
 
380
}
 
381
 
 
382
void optimizer::add_key_equal_fields(optimizer::KeyField **key_fields,
 
383
                                     uint32_t and_level,
 
384
                                     Item_func *cond,
 
385
                                     Item_field *field_item,
 
386
                                     bool eq_func,
 
387
                                     Item **val,
 
388
                                     uint32_t num_values,
 
389
                                     table_map usable_tables,
 
390
                                     vector<optimizer::SargableParam> &sargables)
 
391
{
 
392
  Field *field= field_item->field;
 
393
  add_key_field(key_fields, and_level, cond, field,
 
394
                eq_func, val, num_values, usable_tables, sargables);
 
395
  Item_equal *item_equal= field_item->item_equal;
 
396
  if (item_equal)
 
397
  {
 
398
    /*
 
399
      Add to the set of possible key values every substitution of
 
400
      the field for an equal field included into item_equal
 
401
    */
 
402
    Item_equal_iterator it(*item_equal);
 
403
    Item_field *item;
 
404
    while ((item= it++))
 
405
    {
 
406
      if (! field->eq(item->field))
 
407
      {
 
408
        add_key_field(key_fields, and_level, cond, item->field,
 
409
                      eq_func, val, num_values, usable_tables,
 
410
                      sargables);
 
411
      }
 
412
    }
 
413
  }
 
414
}
 
415
 
 
416
void optimizer::add_key_fields(JOIN *join,
 
417
                               optimizer::KeyField **key_fields,
 
418
                               uint32_t *and_level,
 
419
                               COND *cond,
 
420
                               table_map usable_tables,
 
421
                               vector<optimizer::SargableParam> &sargables)
 
422
{
 
423
  if (cond->type() == Item_func::COND_ITEM)
 
424
  {
 
425
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
 
426
    optimizer::KeyField *org_key_fields= *key_fields;
 
427
 
 
428
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
 
429
    {
 
430
      Item *item;
 
431
      while ((item= li++))
 
432
      {
 
433
        add_key_fields(join,
 
434
                       key_fields,
 
435
                       and_level,
 
436
                       item,
 
437
                       usable_tables,
 
438
                       sargables);
 
439
      }
 
440
      for (; org_key_fields != *key_fields; org_key_fields++)
 
441
        org_key_fields->setLevel(*and_level);
 
442
    }
 
443
    else
 
444
    {
 
445
      (*and_level)++;
 
446
      add_key_fields(join,
 
447
                     key_fields,
 
448
                     and_level,
 
449
                     li++,
 
450
                     usable_tables,
 
451
                     sargables);
 
452
      Item *item;
 
453
      while ((item= li++))
 
454
      {
 
455
        optimizer::KeyField *start_key_fields= *key_fields;
 
456
        (*and_level)++;
 
457
        add_key_fields(join,
 
458
                       key_fields,
 
459
                       and_level,
 
460
                       item,
 
461
                       usable_tables,
 
462
                       sargables);
 
463
        *key_fields= merge_key_fields(org_key_fields, start_key_fields,
 
464
                                      *key_fields, ++(*and_level));
 
465
      }
 
466
    }
 
467
    return;
 
468
  }
 
469
 
 
470
  /*
 
471
    Subquery optimization: Conditions that are pushed down into subqueries
 
472
    are wrapped into Item_func_trig_cond. We process the wrapped condition
 
473
    but need to set cond_guard for KeyUse elements generated from it.
 
474
  */
 
475
  {
 
476
    if (cond->type() == Item::FUNC_ITEM &&
 
477
        ((Item_func*)cond)->functype() == Item_func::TRIG_COND_FUNC)
 
478
    {
 
479
      Item *cond_arg= ((Item_func*)cond)->arguments()[0];
 
480
      if (! join->group_list &&
 
481
          ! join->order &&
 
482
          join->unit->item &&
 
483
          join->unit->item->substype() == Item_subselect::IN_SUBS &&
 
484
          ! join->unit->is_union())
 
485
      {
 
486
        optimizer::KeyField *save= *key_fields;
 
487
        add_key_fields(join,
 
488
                       key_fields,
 
489
                       and_level,
 
490
                       cond_arg,
 
491
                       usable_tables,
 
492
                       sargables);
 
493
        /* Indicate that this ref access candidate is for subquery lookup */
 
494
        for (; save != *key_fields; save++)
 
495
          save->setConditionalGuard(((Item_func_trig_cond*)cond)->get_trig_var());
 
496
      }
 
497
      return;
 
498
    }
 
499
  }
 
500
 
 
501
  /* If item is of type 'field op field/constant' add it to key_fields */
 
502
  if (cond->type() != Item::FUNC_ITEM)
 
503
    return;
 
504
  Item_func *cond_func= (Item_func*) cond;
 
505
  switch (cond_func->select_optimize())
 
506
  {
 
507
  case Item_func::OPTIMIZE_NONE:
 
508
    break;
 
509
  case Item_func::OPTIMIZE_KEY:
 
510
  {
 
511
    Item **values;
 
512
    // BETWEEN, IN, NE
 
513
    if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
 
514
        ! (cond_func->used_tables() & OUTER_REF_TABLE_BIT))
 
515
    {
 
516
      values= cond_func->arguments() + 1;
 
517
      if (cond_func->functype() == Item_func::NE_FUNC &&
 
518
          cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
 
519
          ! (cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
 
520
        values--;
 
521
      assert(cond_func->functype() != Item_func::IN_FUNC ||
 
522
             cond_func->argument_count() != 2);
 
523
      add_key_equal_fields(key_fields, *and_level, cond_func,
 
524
                           (Item_field*) (cond_func->key_item()->real_item()),
 
525
                           0, values,
 
526
                           cond_func->argument_count()-1,
 
527
                           usable_tables, sargables);
 
528
    }
 
529
    if (cond_func->functype() == Item_func::BETWEEN)
 
530
    {
 
531
      values= cond_func->arguments();
 
532
      for (uint32_t i= 1 ; i < cond_func->argument_count(); i++)
 
533
      {
 
534
        Item_field *field_item;
 
535
        if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM
 
536
            &&
 
537
            ! (cond_func->arguments()[i]->used_tables() & OUTER_REF_TABLE_BIT))
 
538
        {
 
539
          field_item= (Item_field *) (cond_func->arguments()[i]->real_item());
 
540
          add_key_equal_fields(key_fields, *and_level, cond_func,
 
541
                               field_item, 0, values, 1, usable_tables,
 
542
                               sargables);
 
543
        }
 
544
      }
 
545
    }
 
546
    break;
 
547
  }
 
548
  case Item_func::OPTIMIZE_OP:
 
549
  {
 
550
    bool equal_func= (cond_func->functype() == Item_func::EQ_FUNC ||
 
551
                                  cond_func->functype() == Item_func::EQUAL_FUNC);
 
552
 
 
553
    if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
 
554
        ! (cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
 
555
    {
 
556
      add_key_equal_fields(key_fields, *and_level, cond_func,
 
557
                           (Item_field*) (cond_func->arguments()[0])->real_item(),
 
558
                           equal_func,
 
559
                           cond_func->arguments()+1, 1, usable_tables,
 
560
                           sargables);
 
561
    }
 
562
    if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
 
563
        cond_func->functype() != Item_func::LIKE_FUNC &&
 
564
        ! (cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT))
 
565
    {
 
566
      add_key_equal_fields(key_fields, *and_level, cond_func,
 
567
                           (Item_field*) (cond_func->arguments()[1])->real_item(), equal_func,
 
568
                           cond_func->arguments(),1,usable_tables,
 
569
                           sargables);
 
570
    }
 
571
    break;
 
572
  }
 
573
  case Item_func::OPTIMIZE_NULL:
 
574
    /* column_name IS [NOT] NULL */
 
575
    if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
 
576
        ! (cond_func->used_tables() & OUTER_REF_TABLE_BIT))
 
577
    {
 
578
      Item *tmp= new Item_null;
 
579
      if (unlikely(! tmp))                       // Should never be true
 
580
        return;
 
581
      add_key_equal_fields(key_fields, *and_level, cond_func,
 
582
                           (Item_field*) (cond_func->arguments()[0])->real_item(),
 
583
                           cond_func->functype() == Item_func::ISNULL_FUNC,
 
584
                           &tmp, 1, usable_tables, sargables);
 
585
    }
 
586
    break;
 
587
  case Item_func::OPTIMIZE_EQUAL:
 
588
    Item_equal *item_equal= (Item_equal *) cond;
 
589
    Item *const_item= item_equal->get_const();
 
590
    Item_equal_iterator it(*item_equal);
 
591
    Item_field *item;
 
592
    if (const_item)
 
593
    {
 
594
      /*
 
595
        For each field field1 from item_equal consider the equality
 
596
        field1=const_item as a condition allowing an index access of the table
 
597
        with field1 by the keys value of field1.
 
598
      */
 
599
      while ((item= it++))
 
600
      {
 
601
        add_key_field(key_fields, *and_level, cond_func, item->field,
 
602
                      true, &const_item, 1, usable_tables, sargables);
 
603
      }
 
604
    }
 
605
    else
 
606
    {
 
607
      /*
 
608
        Consider all pairs of different fields included into item_equal.
 
609
        For each of them (field1, field1) consider the equality
 
610
        field1=field2 as a condition allowing an index access of the table
 
611
        with field1 by the keys value of field2.
 
612
      */
 
613
      Item_equal_iterator fi(*item_equal);
 
614
      while ((item= fi++))
 
615
      {
 
616
        Field *field= item->field;
 
617
        while ((item= it++))
 
618
        {
 
619
          if (! field->eq(item->field))
 
620
          {
 
621
            add_key_field(key_fields, *and_level, cond_func, field,
 
622
                          true, (Item **) &item, 1, usable_tables,
 
623
                          sargables);
 
624
          }
 
625
        }
 
626
        it.rewind();
 
627
      }
 
628
    }
 
629
    break;
 
630
  }
 
631
}
 
632
 
 
633
} /* namespace drizzled */