~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/key_field.cc

  • Committer: Brian Aker
  • Date: 2009-09-27 19:20:46 UTC
  • mfrom: (1108.6.62 optimizer)
  • Revision ID: brian@gaz-20090927192046-prsq4ms1gj8q3aia
Merge Padraig

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#include <drizzled/sql_select.h>
23
23
#include <drizzled/nested_join.h>
24
24
#include <drizzled/item/cmpfunc.h>
25
 
#include <drizzled/optimizer/key_field.h>
 
25
#include "drizzled/optimizer/key_field.h"
 
26
#include "drizzled/optimizer/key_use.h"
26
27
 
27
28
#include <vector>
28
29
 
32
33
void optimizer::add_key_part(DYNAMIC_ARRAY *keyuse_array, 
33
34
                             optimizer::KeyField *key_field)
34
35
{
35
 
  Field *field= key_field->field;
 
36
  Field *field= key_field->getField();
36
37
  Table *form= field->table;
37
 
  KeyUse keyuse;
38
38
 
39
 
  if (key_field->eq_func && ! (key_field->optimize & KEY_OPTIMIZE_EXISTS))
 
39
  if (key_field->isEqualityCondition() && 
 
40
      ! (key_field->getOptimizeFlags() & KEY_OPTIMIZE_EXISTS))
40
41
  {
41
42
    for (uint32_t key= 0; key < form->sizeKeys(); key++)
42
43
    {
48
49
      {
49
50
        if (field->eq(form->key_info[key].key_part[part].field))
50
51
        {
51
 
          keyuse.table= field->table;
52
 
          keyuse.val= key_field->val;
53
 
          keyuse.key= key;
54
 
          keyuse.keypart= part;
55
 
          keyuse.keypart_map= (key_part_map) 1 << part;
56
 
          keyuse.used_tables= key_field->val->used_tables();
57
 
          keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
58
 
          keyuse.null_rejecting= key_field->null_rejecting;
59
 
          keyuse.cond_guard= key_field->cond_guard;
 
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());
60
62
          insert_dynamic(keyuse_array, (unsigned char*) &keyuse);
61
63
        }
62
64
      }
97
99
        tables|= table->table->map;
98
100
  }
99
101
  if (nested_join_table->on_expr)
100
 
    add_key_fields(join, end, and_level, nested_join_table->on_expr, tables,
 
102
  {
 
103
    add_key_fields(join, 
 
104
                   end, 
 
105
                   and_level, 
 
106
                   nested_join_table->on_expr, 
 
107
                   tables,
101
108
                   sargables);
 
109
  }
102
110
}
103
111
 
104
112
optimizer::KeyField *optimizer::merge_key_fields(optimizer::KeyField *start,
118
126
  {
119
127
    for (optimizer::KeyField *old= start; old != first_free; old++)
120
128
    {
121
 
      if (old->field == new_fields->field)
 
129
      if (old->getField() == new_fields->getField())
122
130
      {
123
131
        /*
124
132
          NOTE: below const_item() call really works as "!used_tables()", i.e.
132
140
          The result of this is that we're missing some 'ref' accesses.
133
141
          TODO: OptimizerTeam: Fix this
134
142
        */
135
 
        if (! new_fields->val->const_item())
 
143
        if (! new_fields->getValue()->const_item())
136
144
        {
137
145
          /*
138
146
            If the value matches, we can use the key reference.
139
147
            If not, we keep it until we have examined all new values
140
148
          */
141
 
          if (old->val->eq(new_fields->val, old->field->binary()))
 
149
          if (old->getValue()->eq(new_fields->getValue(), old->getField()->binary()))
142
150
          {
143
 
            old->level= and_level;
144
 
            old->optimize= ((old->optimize & new_fields->optimize &
145
 
                KEY_OPTIMIZE_EXISTS) |
146
 
                ((old->optimize | new_fields->optimize) &
147
 
                KEY_OPTIMIZE_REF_OR_NULL));
148
 
                  old->null_rejecting= (old->null_rejecting &&
149
 
                                        new_fields->null_rejecting);
 
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());
150
160
          }
151
161
        }
152
 
        else if (old->eq_func && new_fields->eq_func &&
153
 
                 old->val->eq_by_collation(new_fields->val,
154
 
                                           old->field->binary(),
155
 
                                           old->field->charset()))
 
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()))
156
167
 
157
168
        {
158
 
          old->level= and_level;
159
 
          old->optimize= ((old->optimize & new_fields->optimize &
160
 
                           KEY_OPTIMIZE_EXISTS) |
161
 
                          ((old->optimize | new_fields->optimize) &
162
 
                            KEY_OPTIMIZE_REF_OR_NULL));
163
 
          old->null_rejecting= (old->null_rejecting &&
164
 
                                new_fields->null_rejecting);
 
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());
165
178
        }
166
 
        else if (old->eq_func && new_fields->eq_func &&
167
 
          ((old->val->const_item() && old->val->is_null()) ||
168
 
                        new_fields->val->is_null()))
 
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()))
169
184
        {
170
185
          /* field = expression OR field IS NULL */
171
 
          old->level= and_level;
172
 
          old->optimize= KEY_OPTIMIZE_REF_OR_NULL;
 
186
          old->setLevel(and_level);
 
187
          old->setOptimizeFlags(KEY_OPTIMIZE_REF_OR_NULL);
173
188
          /*
174
189
            Remember the NOT NULL value unless the value does not depend
175
190
            on other tables.
176
191
           */
177
 
          if (! old->val->used_tables() && old->val->is_null())
178
 
            old->val= new_fields->val;
 
192
          if (! old->getValue()->used_tables() && 
 
193
              old->getValue()->is_null())
 
194
          {
 
195
            old->setValue(new_fields->getValue());
 
196
          }
179
197
          /* The referred expression can be NULL: */
180
 
          old->null_rejecting= 0;
 
198
          old->setRejectNullValues(false);
181
199
        }
182
200
        else
183
201
        {
197
215
  /* Remove all not used items */
198
216
  for (optimizer::KeyField *old= start; old != first_free;)
199
217
  {
200
 
    if (old->level != and_level)
 
218
    if (old->getLevel() != and_level)
201
219
    {                                           // Not used in all levels
202
220
      if (old == --first_free)
203
221
        break;
339
357
  */
340
358
  assert(eq_func);
341
359
  /* Store possible eq field */
342
 
  (*key_fields)->field= field;
343
 
  (*key_fields)->eq_func=       eq_func;
344
 
  (*key_fields)->val= *value;
345
 
  (*key_fields)->level= and_level;
346
 
  (*key_fields)->optimize= exists_optimize;
 
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);
347
365
  /*
348
366
    If the condition has form "tbl.keypart = othertbl.field" and
349
367
    othertbl.field can be NULL, there will be no matches if othertbl.field
351
369
    We use null_rejecting in add_not_null_conds() to add
352
370
    'othertbl.field IS NOT NULL' to tab->select_cond.
353
371
  */
354
 
  (*key_fields)->null_rejecting= ((cond->functype() == Item_func::EQ_FUNC ||
355
 
                                   cond->functype() == Item_func::MULT_EQUAL_FUNC) &&
356
 
                                  ((*value)->type() == Item::FIELD_ITEM) &&
357
 
                                  ((Item_field*)*value)->field->maybe_null());
358
 
  (*key_fields)->cond_guard= NULL;
 
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);
359
377
  (*key_fields)++;
360
378
}
361
379
 
409
427
    {
410
428
      Item *item;
411
429
      while ((item= li++))
412
 
        add_key_fields(join, key_fields, and_level, item, usable_tables,
 
430
      {
 
431
        add_key_fields(join, 
 
432
                       key_fields, 
 
433
                       and_level, 
 
434
                       item, 
 
435
                       usable_tables,
413
436
                       sargables);
414
 
      for (; org_key_fields != *key_fields ; org_key_fields++)
415
 
        org_key_fields->level= *and_level;
 
437
      }
 
438
      for (; org_key_fields != *key_fields; org_key_fields++)
 
439
        org_key_fields->setLevel(*and_level);
416
440
    }
417
441
    else
418
442
    {
419
443
      (*and_level)++;
420
 
      add_key_fields(join, key_fields, and_level, li++, usable_tables,
 
444
      add_key_fields(join, 
 
445
                     key_fields, 
 
446
                     and_level, 
 
447
                     li++, 
 
448
                     usable_tables,
421
449
                     sargables);
422
450
      Item *item;
423
451
      while ((item= li++))
424
452
      {
425
453
        optimizer::KeyField *start_key_fields= *key_fields;
426
454
        (*and_level)++;
427
 
        add_key_fields(join, key_fields, and_level, item, usable_tables,
 
455
        add_key_fields(join, 
 
456
                       key_fields, 
 
457
                       and_level, 
 
458
                       item, 
 
459
                       usable_tables,
428
460
                       sargables);
429
461
        *key_fields= merge_key_fields(org_key_fields, start_key_fields,
430
462
                                      *key_fields, ++(*and_level));
443
475
        ((Item_func*)cond)->functype() == Item_func::TRIG_COND_FUNC)
444
476
    {
445
477
      Item *cond_arg= ((Item_func*)cond)->arguments()[0];
446
 
      if (! join->group_list && ! join->order &&
 
478
      if (! join->group_list && 
 
479
          ! join->order &&
447
480
          join->unit->item &&
448
481
          join->unit->item->substype() == Item_subselect::IN_SUBS &&
449
482
          ! join->unit->is_union())
450
483
      {
451
484
        optimizer::KeyField *save= *key_fields;
452
 
        add_key_fields(join, key_fields, and_level, cond_arg, usable_tables,
 
485
        add_key_fields(join, 
 
486
                       key_fields, 
 
487
                       and_level, 
 
488
                       cond_arg, 
 
489
                       usable_tables,
453
490
                       sargables);
454
 
        // Indicate that this ref access candidate is for subquery lookup:
 
491
        /* Indicate that this ref access candidate is for subquery lookup */
455
492
        for (; save != *key_fields; save++)
456
 
          save->cond_guard= ((Item_func_trig_cond*)cond)->get_trig_var();
 
493
          save->setConditionalGuard(((Item_func_trig_cond*)cond)->get_trig_var());
457
494
      }
458
495
      return;
459
496
    }