~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/key_field.cc

  • Committer: Jay Pipes
  • Date: 2008-07-17 17:54:00 UTC
  • mto: This revision was merged to the branch mainline in revision 182.
  • Revision ID: jay@mysql.com-20080717175400-xm2aazihjra8mdzq
Removal of DBUG from libdrizzle/ - Round 2

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