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
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
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"
35
void optimizer::add_key_part(DYNAMIC_ARRAY *keyuse_array,
36
optimizer::KeyField *key_field)
38
Field *field= key_field->getField();
39
Table *form= field->table;
41
if (key_field->isEqualityCondition() &&
42
! (key_field->getOptimizeFlags() & KEY_OPTIMIZE_EXISTS))
44
for (uint32_t key= 0; key < form->sizeKeys(); key++)
46
if (! (form->keys_in_use_for_query.test(key)))
49
uint32_t key_parts= (uint32_t) form->key_info[key].key_parts;
50
for (uint32_t part= 0; part < key_parts; part++)
52
if (field->eq(form->key_info[key].key_part[part].field))
54
optimizer::KeyUse keyuse(field->table,
55
key_field->getValue(),
56
key_field->getValue()->used_tables(),
59
key_field->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL,
62
key_field->rejectNullValues(),
63
key_field->getConditionalGuard());
64
insert_dynamic(keyuse_array, (unsigned char*) &keyuse);
71
void optimizer::add_key_fields_for_nj(JOIN *join,
72
TableList *nested_join_table,
73
optimizer::KeyField **end,
75
vector<optimizer::SargableParam> &sargables)
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;
82
assert(nested_join_table->nested_join);
84
while ((table= li++) || (have_another && (li=li2, have_another=false,
87
if (table->nested_join)
91
/* It's a semi-join nest. Walk into it as if it wasn't a nest */
94
li= List_iterator<TableList>(table->nested_join->join_list);
97
add_key_fields_for_nj(join, table, end, and_level, sargables);
100
if (! table->on_expr)
101
tables|= table->table->map;
103
if (nested_join_table->on_expr)
108
nested_join_table->on_expr,
114
optimizer::KeyField *optimizer::merge_key_fields(optimizer::KeyField *start,
115
optimizer::KeyField *new_fields,
116
optimizer::KeyField *end,
119
if (start == new_fields)
120
return start; // Impossible or
121
if (new_fields == end)
122
return start; // No new fields, skip all
124
optimizer::KeyField *first_free= new_fields;
126
/* Mark all found fields in old array */
127
for (; new_fields != end; new_fields++)
129
for (optimizer::KeyField *old= start; old != first_free; old++)
131
if (old->getField() == new_fields->getField())
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.
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
145
if (! new_fields->getValue()->const_item())
148
If the value matches, we can use the key reference.
149
If not, we keep it until we have examined all new values
151
if (old->getValue()->eq(new_fields->getValue(), old->getField()->binary()))
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());
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()))
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());
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()))
187
/* field = expression OR field IS NULL */
188
old->setLevel(and_level);
189
old->setOptimizeFlags(KEY_OPTIMIZE_REF_OR_NULL);
191
Remember the NOT NULL value unless the value does not depend
194
if (! old->getValue()->used_tables() &&
195
old->getValue()->is_null())
197
old->setValue(new_fields->getValue());
199
/* The referred expression can be NULL: */
200
old->setRejectNullValues(false);
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
209
if (old == --first_free) // If last item
211
*old= *first_free; // Remove old value
212
old--; // Retry this value
217
/* Remove all not used items */
218
for (optimizer::KeyField *old= start; old != first_free;)
220
if (old->getLevel() != and_level)
221
{ // Not used in all levels
222
if (old == --first_free)
224
*old= *first_free; // Remove old value
232
void optimizer::add_key_field(optimizer::KeyField **key_fields,
239
table_map usable_tables,
240
vector<optimizer::SargableParam> &sargables)
242
uint32_t exists_optimize= 0;
243
if (! (field->flags & PART_KEY_FLAG))
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);
254
table_map used_tables= 0;
256
for (uint32_t i= 0; i < num_values; i++)
258
used_tables|= (value[i])->used_tables();
259
if (! ((value[i])->used_tables() & (field->table->map | RAND_TABLE_BIT)))
264
if (! (usable_tables & field->table->map))
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;
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
279
Save the following cases:
281
Field LIKE constant where constant doesn't start with a wildcard
282
Field = field2 where field2 is in a different table
289
stat[0].key_dependent|= used_tables;
292
for (uint32_t i= 0; i < num_values; i++)
294
if (! (is_const&= value[i]->const_item()))
298
stat[0].const_keys|= possible_keys;
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.
307
optimizer::SargableParam tmp(field, value, num_values);
308
sargables.push_back(tmp);
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
318
Additional optimization: if we're processing
319
"t.key BETWEEN c1 AND c1" then proceed as if we were processing
321
TODO: This is a very limited fix. A more generic fix is possible.
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
329
if ((cond->functype() != Item_func::BETWEEN) ||
330
((Item_func_between*) cond)->negated ||
331
! value[0]->eq(value[1], field->binary()))
336
if (field->result_type() == STRING_RESULT)
338
if ((*value)->result_type() != STRING_RESULT)
340
if (field->cmp_type() != (*value)->result_type())
346
We can't use indexes if the effective collation
347
of the operation differ from the field collation.
349
if (field->cmp_type() == STRING_RESULT &&
350
((Field_str*)field)->charset() != cond->compare_collation())
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
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);
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
371
We use null_rejecting in add_not_null_conds() to add
372
'othertbl.field IS NOT NULL' to tab->select_cond.
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);
382
void optimizer::add_key_equal_fields(optimizer::KeyField **key_fields,
385
Item_field *field_item,
389
table_map usable_tables,
390
vector<optimizer::SargableParam> &sargables)
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;
399
Add to the set of possible key values every substitution of
400
the field for an equal field included into item_equal
402
Item_equal_iterator it(*item_equal);
406
if (! field->eq(item->field))
408
add_key_field(key_fields, and_level, cond, item->field,
409
eq_func, val, num_values, usable_tables,
416
void optimizer::add_key_fields(JOIN *join,
417
optimizer::KeyField **key_fields,
420
table_map usable_tables,
421
vector<optimizer::SargableParam> &sargables)
423
if (cond->type() == Item_func::COND_ITEM)
425
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
426
optimizer::KeyField *org_key_fields= *key_fields;
428
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
440
for (; org_key_fields != *key_fields; org_key_fields++)
441
org_key_fields->setLevel(*and_level);
455
optimizer::KeyField *start_key_fields= *key_fields;
463
*key_fields= merge_key_fields(org_key_fields, start_key_fields,
464
*key_fields, ++(*and_level));
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.
476
if (cond->type() == Item::FUNC_ITEM &&
477
((Item_func*)cond)->functype() == Item_func::TRIG_COND_FUNC)
479
Item *cond_arg= ((Item_func*)cond)->arguments()[0];
480
if (! join->group_list &&
483
join->unit->item->substype() == Item_subselect::IN_SUBS &&
484
! join->unit->is_union())
486
optimizer::KeyField *save= *key_fields;
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());
501
/* If item is of type 'field op field/constant' add it to key_fields */
502
if (cond->type() != Item::FUNC_ITEM)
504
Item_func *cond_func= (Item_func*) cond;
505
switch (cond_func->select_optimize())
507
case Item_func::OPTIMIZE_NONE:
509
case Item_func::OPTIMIZE_KEY:
513
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
514
! (cond_func->used_tables() & OUTER_REF_TABLE_BIT))
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))
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()),
526
cond_func->argument_count()-1,
527
usable_tables, sargables);
529
if (cond_func->functype() == Item_func::BETWEEN)
531
values= cond_func->arguments();
532
for (uint32_t i= 1 ; i < cond_func->argument_count(); i++)
534
Item_field *field_item;
535
if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM
537
! (cond_func->arguments()[i]->used_tables() & OUTER_REF_TABLE_BIT))
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,
548
case Item_func::OPTIMIZE_OP:
550
bool equal_func= (cond_func->functype() == Item_func::EQ_FUNC ||
551
cond_func->functype() == Item_func::EQUAL_FUNC);
553
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
554
! (cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
556
add_key_equal_fields(key_fields, *and_level, cond_func,
557
(Item_field*) (cond_func->arguments()[0])->real_item(),
559
cond_func->arguments()+1, 1, usable_tables,
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))
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,
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))
578
Item *tmp= new Item_null;
579
if (unlikely(! tmp)) // Should never be true
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);
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);
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.
601
add_key_field(key_fields, *and_level, cond_func, item->field,
602
true, &const_item, 1, usable_tables, sargables);
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.
613
Item_equal_iterator fi(*item_equal);
616
Field *field= item->field;
619
if (! field->eq(item->field))
621
add_key_field(key_fields, *and_level, cond_func, field,
622
true, (Item **) &item, 1, usable_tables,
633
} /* namespace drizzled */