~drizzle-trunk/drizzle/development

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