1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008-2009 Sun Microsystems, Inc.
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.
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.
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
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>
38
void optimizer::add_key_part(DYNAMIC_ARRAY *keyuse_array,
39
optimizer::KeyField *key_field)
41
Field *field= key_field->getField();
42
Table *form= field->getTable();
44
if (key_field->isEqualityCondition() &&
45
! (key_field->getOptimizeFlags() & KEY_OPTIMIZE_EXISTS))
47
for (uint32_t key= 0; key < form->sizeKeys(); key++)
49
if (! (form->keys_in_use_for_query.test(key)))
52
uint32_t key_parts= (uint32_t) form->key_info[key].key_parts;
53
for (uint32_t part= 0; part < key_parts; part++)
55
if (field->eq(form->key_info[key].key_part[part].field))
57
optimizer::KeyUse keyuse(field->getTable(),
58
key_field->getValue(),
59
key_field->getValue()->used_tables(),
62
key_field->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL,
65
key_field->rejectNullValues(),
66
key_field->getConditionalGuard());
67
insert_dynamic(keyuse_array, (unsigned char*) &keyuse);
74
void optimizer::add_key_fields_for_nj(Join *join,
75
TableList *nested_join_table,
76
optimizer::KeyField **end,
78
vector<optimizer::SargableParam> &sargables)
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;
85
assert(nested_join_table->getNestedJoin());
87
while ((table= li++) || (have_another && (li=li2, have_another=false,
90
if (table->getNestedJoin())
94
/* It's a semi-join nest. Walk into it as if it wasn't a nest */
97
li= List<TableList>::iterator(table->getNestedJoin()->join_list.begin());
100
add_key_fields_for_nj(join, table, end, and_level, sargables);
103
if (! table->on_expr)
104
tables|= table->table->map;
106
if (nested_join_table->on_expr)
111
nested_join_table->on_expr,
117
optimizer::KeyField *optimizer::merge_key_fields(optimizer::KeyField *start,
118
optimizer::KeyField *new_fields,
119
optimizer::KeyField *end,
122
if (start == new_fields)
123
return start; // Impossible or
124
if (new_fields == end)
125
return start; // No new fields, skip all
127
optimizer::KeyField *first_free= new_fields;
129
/* Mark all found fields in old array */
130
for (; new_fields != end; new_fields++)
132
for (optimizer::KeyField *old= start; old != first_free; old++)
134
if (old->getField() == new_fields->getField())
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.
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
148
if (! new_fields->getValue()->const_item())
151
If the value matches, we can use the key reference.
152
If not, we keep it until we have examined all new values
154
if (old->getValue()->eq(new_fields->getValue(), old->getField()->binary()))
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());
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()))
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());
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()))
190
/* field = expression OR field IS NULL */
191
old->setLevel(and_level);
192
old->setOptimizeFlags(KEY_OPTIMIZE_REF_OR_NULL);
194
Remember the NOT NULL value unless the value does not depend
197
if (! old->getValue()->used_tables() &&
198
old->getValue()->is_null())
200
old->setValue(new_fields->getValue());
202
/* The referred expression can be NULL: */
203
old->setRejectNullValues(false);
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
212
if (old == --first_free) // If last item
214
*old= *first_free; // Remove old value
215
old--; // Retry this value
220
/* Remove all not used items */
221
for (optimizer::KeyField *old= start; old != first_free;)
223
if (old->getLevel() != and_level)
224
{ // Not used in all levels
225
if (old == --first_free)
227
*old= *first_free; // Remove old value
235
void optimizer::add_key_field(optimizer::KeyField **key_fields,
242
table_map usable_tables,
243
vector<optimizer::SargableParam> &sargables)
245
uint32_t exists_optimize= 0;
246
if (! (field->flags & PART_KEY_FLAG))
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);
257
table_map used_tables= 0;
259
for (uint32_t i= 0; i < num_values; i++)
261
used_tables|= (value[i])->used_tables();
262
if (! ((value[i])->used_tables() & (field->getTable()->map | RAND_TABLE_BIT)))
267
if (! (usable_tables & field->getTable()->map))
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;
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
282
Save the following cases:
284
Field LIKE constant where constant doesn't start with a wildcard
285
Field = field2 where field2 is in a different table
292
stat[0].key_dependent|= used_tables;
295
for (uint32_t i= 0; i < num_values; i++)
297
if (! (is_const&= value[i]->const_item()))
301
stat[0].const_keys|= possible_keys;
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.
310
optimizer::SargableParam tmp(field, value, num_values);
311
sargables.push_back(tmp);
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
321
Additional optimization: if we're processing
322
"t.key BETWEEN c1 AND c1" then proceed as if we were processing
324
TODO: This is a very limited fix. A more generic fix is possible.
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
332
if ((cond->functype() != Item_func::BETWEEN) ||
333
((Item_func_between*) cond)->negated ||
334
! value[0]->eq(value[1], field->binary()))
339
if (field->result_type() == STRING_RESULT)
341
if ((*value)->result_type() != STRING_RESULT)
343
if (field->cmp_type() != (*value)->result_type())
349
We can't use indexes if the effective collation
350
of the operation differ from the field collation.
352
if (field->cmp_type() == STRING_RESULT &&
353
((Field_str*)field)->charset() != cond->compare_collation())
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
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);
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
374
We use null_rejecting in add_not_null_conds() to add
375
'othertbl.field IS NOT NULL' to tab->select_cond.
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);
385
void optimizer::add_key_equal_fields(optimizer::KeyField **key_fields,
388
Item_field *field_item,
392
table_map usable_tables,
393
vector<optimizer::SargableParam> &sargables)
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;
402
Add to the set of possible key values every substitution of
403
the field for an equal field included into item_equal
405
Item_equal_iterator it(*item_equal);
409
if (! field->eq(item->field))
411
add_key_field(key_fields, and_level, cond, item->field,
412
eq_func, val, num_values, usable_tables,
419
void optimizer::add_key_fields(Join *join,
420
optimizer::KeyField **key_fields,
423
table_map usable_tables,
424
vector<optimizer::SargableParam> &sargables)
426
if (cond->type() == Item_func::COND_ITEM)
428
List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
429
optimizer::KeyField *org_key_fields= *key_fields;
431
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
443
for (; org_key_fields != *key_fields; org_key_fields++)
444
org_key_fields->setLevel(*and_level);
458
optimizer::KeyField *start_key_fields= *key_fields;
466
*key_fields= merge_key_fields(org_key_fields, start_key_fields,
467
*key_fields, ++(*and_level));
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.
479
if (cond->type() == Item::FUNC_ITEM &&
480
((Item_func*)cond)->functype() == Item_func::TRIG_COND_FUNC)
482
Item *cond_arg= ((Item_func*)cond)->arguments()[0];
483
if (! join->group_list &&
486
join->unit->item->substype() == Item_subselect::IN_SUBS &&
487
! join->unit->is_union())
489
optimizer::KeyField *save= *key_fields;
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());
504
/* If item is of type 'field op field/constant' add it to key_fields */
505
if (cond->type() != Item::FUNC_ITEM)
507
Item_func *cond_func= (Item_func*) cond;
508
switch (cond_func->select_optimize())
510
case Item_func::OPTIMIZE_NONE:
512
case Item_func::OPTIMIZE_KEY:
516
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
517
! (cond_func->used_tables() & OUTER_REF_TABLE_BIT))
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))
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()),
529
cond_func->argument_count()-1,
530
usable_tables, sargables);
532
if (cond_func->functype() == Item_func::BETWEEN)
534
values= cond_func->arguments();
535
for (uint32_t i= 1 ; i < cond_func->argument_count(); i++)
537
Item_field *field_item;
538
if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM
540
! (cond_func->arguments()[i]->used_tables() & OUTER_REF_TABLE_BIT))
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,
551
case Item_func::OPTIMIZE_OP:
553
bool equal_func= (cond_func->functype() == Item_func::EQ_FUNC ||
554
cond_func->functype() == Item_func::EQUAL_FUNC);
556
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
557
! (cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
559
add_key_equal_fields(key_fields, *and_level, cond_func,
560
(Item_field*) (cond_func->arguments()[0])->real_item(),
562
cond_func->arguments()+1, 1, usable_tables,
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))
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,
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))
581
Item *tmp= new Item_null;
582
if (unlikely(! tmp)) // Should never be true
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);
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);
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.
604
add_key_field(key_fields, *and_level, cond_func, item->field,
605
true, &const_item, 1, usable_tables, sargables);
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.
616
Item_equal_iterator fi(*item_equal);
619
Field *field= item->field;
622
if (! field->eq(item->field))
624
add_key_field(key_fields, *and_level, cond_func, field,
625
true, (Item **) &item, 1, usable_tables,
636
} /* namespace drizzled */