~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/key_field.cc

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
RemoveĀ uint.

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