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
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"
31
using namespace drizzled;
33
void optimizer::add_key_part(DYNAMIC_ARRAY *keyuse_array,
34
optimizer::KeyField *key_field)
36
Field *field= key_field->getField();
37
Table *form= field->table;
39
if (key_field->isEqualityCondition() &&
40
! (key_field->getOptimizeFlags() & KEY_OPTIMIZE_EXISTS))
42
for (uint32_t key= 0; key < form->sizeKeys(); key++)
44
if (! (form->keys_in_use_for_query.test(key)))
47
uint32_t key_parts= (uint32_t) form->key_info[key].key_parts;
48
for (uint32_t part= 0; part < key_parts; part++)
50
if (field->eq(form->key_info[key].key_part[part].field))
52
optimizer::KeyUse keyuse(field->table,
53
key_field->getValue(),
54
key_field->getValue()->used_tables(),
57
key_field->getOptimizeFlags() & KEY_OPTIMIZE_REF_OR_NULL,
60
key_field->rejectNullValues(),
61
key_field->getConditionalGuard());
62
insert_dynamic(keyuse_array, (unsigned char*) &keyuse);
69
void optimizer::add_key_fields_for_nj(JOIN *join,
70
TableList *nested_join_table,
71
optimizer::KeyField **end,
73
vector<optimizer::SargableParam> &sargables)
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;
80
assert(nested_join_table->nested_join);
82
while ((table= li++) || (have_another && (li=li2, have_another=false,
85
if (table->nested_join)
89
/* It's a semi-join nest. Walk into it as if it wasn't a nest */
92
li= List_iterator<TableList>(table->nested_join->join_list);
95
add_key_fields_for_nj(join, table, end, and_level, sargables);
99
tables|= table->table->map;
101
if (nested_join_table->on_expr)
106
nested_join_table->on_expr,
112
optimizer::KeyField *optimizer::merge_key_fields(optimizer::KeyField *start,
113
optimizer::KeyField *new_fields,
114
optimizer::KeyField *end,
117
if (start == new_fields)
118
return start; // Impossible or
119
if (new_fields == end)
120
return start; // No new fields, skip all
122
optimizer::KeyField *first_free= new_fields;
124
/* Mark all found fields in old array */
125
for (; new_fields != end; new_fields++)
127
for (optimizer::KeyField *old= start; old != first_free; old++)
129
if (old->getField() == new_fields->getField())
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.
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
143
if (! new_fields->getValue()->const_item())
146
If the value matches, we can use the key reference.
147
If not, we keep it until we have examined all new values
149
if (old->getValue()->eq(new_fields->getValue(), old->getField()->binary()))
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());
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()))
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());
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()))
185
/* field = expression OR field IS NULL */
186
old->setLevel(and_level);
187
old->setOptimizeFlags(KEY_OPTIMIZE_REF_OR_NULL);
189
Remember the NOT NULL value unless the value does not depend
192
if (! old->getValue()->used_tables() &&
193
old->getValue()->is_null())
195
old->setValue(new_fields->getValue());
197
/* The referred expression can be NULL: */
198
old->setRejectNullValues(false);
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
207
if (old == --first_free) // If last item
209
*old= *first_free; // Remove old value
210
old--; // Retry this value
215
/* Remove all not used items */
216
for (optimizer::KeyField *old= start; old != first_free;)
218
if (old->getLevel() != and_level)
219
{ // Not used in all levels
220
if (old == --first_free)
222
*old= *first_free; // Remove old value
230
void optimizer::add_key_field(optimizer::KeyField **key_fields,
237
table_map usable_tables,
238
vector<optimizer::SargableParam> &sargables)
240
uint32_t exists_optimize= 0;
241
if (! (field->flags & PART_KEY_FLAG))
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);
252
table_map used_tables= 0;
254
for (uint32_t i= 0; i < num_values; i++)
256
used_tables|= (value[i])->used_tables();
257
if (! ((value[i])->used_tables() & (field->table->map | RAND_TABLE_BIT)))
262
if (! (usable_tables & field->table->map))
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;
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
277
Save the following cases:
279
Field LIKE constant where constant doesn't start with a wildcard
280
Field = field2 where field2 is in a different table
287
stat[0].key_dependent|= used_tables;
290
for (uint32_t i= 0; i < num_values; i++)
292
if (! (is_const&= value[i]->const_item()))
296
stat[0].const_keys|= possible_keys;
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.
305
optimizer::SargableParam tmp(field, value, num_values);
306
sargables.push_back(tmp);
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
316
Additional optimization: if we're processing
317
"t.key BETWEEN c1 AND c1" then proceed as if we were processing
319
TODO: This is a very limited fix. A more generic fix is possible.
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
327
if ((cond->functype() != Item_func::BETWEEN) ||
328
((Item_func_between*) cond)->negated ||
329
! value[0]->eq(value[1], field->binary()))
334
if (field->result_type() == STRING_RESULT)
336
if ((*value)->result_type() != STRING_RESULT)
338
if (field->cmp_type() != (*value)->result_type())
344
We can't use indexes if the effective collation
345
of the operation differ from the field collation.
347
if (field->cmp_type() == STRING_RESULT &&
348
((Field_str*)field)->charset() != cond->compare_collation())
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
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);
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
369
We use null_rejecting in add_not_null_conds() to add
370
'othertbl.field IS NOT NULL' to tab->select_cond.
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);
380
void optimizer::add_key_equal_fields(optimizer::KeyField **key_fields,
383
Item_field *field_item,
387
table_map usable_tables,
388
vector<optimizer::SargableParam> &sargables)
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;
397
Add to the set of possible key values every substitution of
398
the field for an equal field included into item_equal
400
Item_equal_iterator it(*item_equal);
404
if (! field->eq(item->field))
406
add_key_field(key_fields, and_level, cond, item->field,
407
eq_func, val, num_values, usable_tables,
414
void optimizer::add_key_fields(JOIN *join,
415
optimizer::KeyField **key_fields,
418
table_map usable_tables,
419
vector<optimizer::SargableParam> &sargables)
421
if (cond->type() == Item_func::COND_ITEM)
423
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
424
optimizer::KeyField *org_key_fields= *key_fields;
426
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
438
for (; org_key_fields != *key_fields; org_key_fields++)
439
org_key_fields->setLevel(*and_level);
453
optimizer::KeyField *start_key_fields= *key_fields;
461
*key_fields= merge_key_fields(org_key_fields, start_key_fields,
462
*key_fields, ++(*and_level));
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.
474
if (cond->type() == Item::FUNC_ITEM &&
475
((Item_func*)cond)->functype() == Item_func::TRIG_COND_FUNC)
477
Item *cond_arg= ((Item_func*)cond)->arguments()[0];
478
if (! join->group_list &&
481
join->unit->item->substype() == Item_subselect::IN_SUBS &&
482
! join->unit->is_union())
484
optimizer::KeyField *save= *key_fields;
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());
499
/* If item is of type 'field op field/constant' add it to key_fields */
500
if (cond->type() != Item::FUNC_ITEM)
502
Item_func *cond_func= (Item_func*) cond;
503
switch (cond_func->select_optimize())
505
case Item_func::OPTIMIZE_NONE:
507
case Item_func::OPTIMIZE_KEY:
511
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
512
! (cond_func->used_tables() & OUTER_REF_TABLE_BIT))
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))
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()),
524
cond_func->argument_count()-1,
525
usable_tables, sargables);
527
if (cond_func->functype() == Item_func::BETWEEN)
529
values= cond_func->arguments();
530
for (uint32_t i= 1 ; i < cond_func->argument_count(); i++)
532
Item_field *field_item;
533
if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM
535
! (cond_func->arguments()[i]->used_tables() & OUTER_REF_TABLE_BIT))
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,
546
case Item_func::OPTIMIZE_OP:
548
bool equal_func= (cond_func->functype() == Item_func::EQ_FUNC ||
549
cond_func->functype() == Item_func::EQUAL_FUNC);
551
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
552
! (cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
554
add_key_equal_fields(key_fields, *and_level, cond_func,
555
(Item_field*) (cond_func->arguments()[0])->real_item(),
557
cond_func->arguments()+1, 1, usable_tables,
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))
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,
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))
576
Item *tmp= new Item_null;
577
if (unlikely(! tmp)) // Should never be true
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);
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);
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.
599
add_key_field(key_fields, *and_level, cond_func, item->field,
600
true, &const_item, 1, usable_tables, sargables);
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.
611
Item_equal_iterator fi(*item_equal);
614
Field *field= item->field;
617
if (! field->eq(item->field))
619
add_key_field(key_fields, *and_level, cond_func, field,
620
true, (Item **) &item, 1, usable_tables,