~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2003 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
17
/**
18
  @file
19
20
  Optimising of MIN(), MAX() and COUNT(*) queries without 'group by' clause
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
21
  by replacing the aggregate expression with a constant.
1 by brian
clean slate
22
23
  Given a table with a compound key on columns (a,b,c), the following
24
  types of queries are optimised (assuming the table handler supports
25
  the required methods)
26
27
  @verbatim
28
  SELECT COUNT(*) FROM t1[,t2,t3,...]
29
  SELECT MIN(b) FROM t1 WHERE a=const
30
  SELECT MAX(c) FROM t1 WHERE a=const AND b=const
31
  SELECT MAX(b) FROM t1 WHERE a=const AND b<const
32
  SELECT MIN(b) FROM t1 WHERE a=const AND b>const
33
  SELECT MIN(b) FROM t1 WHERE a=const AND b BETWEEN const AND const
34
  SELECT MAX(b) FROM t1 WHERE a=const AND b BETWEEN const AND const
35
  @endverbatim
36
37
  Instead of '<' one can use '<=', '>', '>=' and '=' as well.
38
  Instead of 'a=const' the condition 'a IS NULL' can be used.
39
40
  If all selected fields are replaced then we will also remove all
41
  involved tables and return the answer without any join. Thus, the
42
  following query will be replaced with a row of two constants:
43
  @verbatim
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
44
  SELECT MAX(b), MIN(d) FROM t1,t2
1 by brian
clean slate
45
    WHERE a=const AND b<const AND d>const
46
  @endverbatim
47
  (assuming a index for column d of table t2 is defined)
48
*/
49
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
50
#include <drizzled/server_includes.h>
51
#include <drizzled/sql_select.h>
584.4.7 by Monty Taylor
Removed a big bank of includes from item.h.
52
#include <drizzled/item/sum.h>
53
#include <drizzled/item/cmpfunc.h>
1 by brian
clean slate
54
55
static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, Field* field,
482 by Brian Aker
Remove uint.
56
                                COND *cond, uint32_t *range_fl,
57
                                uint32_t *key_prefix_length);
1 by brian
clean slate
58
static int reckey_in_range(bool max_fl, TABLE_REF *ref, Field* field,
482 by Brian Aker
Remove uint.
59
                            COND *cond, uint32_t range_fl, uint32_t prefix_len);
1 by brian
clean slate
60
static int maxmin_in_range(bool max_fl, Field* field, COND *cond);
61
62
63
/*
64
  Get exact count of rows in all tables
65
66
  SYNOPSIS
67
    get_exact_records()
68
    tables		List of tables
69
70
  NOTES
71
    When this is called, we know all table handlers supports HA_HAS_RECORDS
72
    or HA_STATS_RECORDS_IS_EXACT
73
74
  RETURN
163 by Brian Aker
Merge Monty's code.
75
    UINT64_MAX	Error: Could not calculate number of rows
1 by brian
clean slate
76
    #			Multiplication of number of rows in all tables
77
*/
78
327.2.4 by Brian Aker
Refactoring table.h
79
static uint64_t get_exact_record_count(TableList *tables)
1 by brian
clean slate
80
{
151 by Brian Aker
Ulonglong to uint64_t
81
  uint64_t count= 1;
327.2.4 by Brian Aker
Refactoring table.h
82
  for (TableList *tl= tables; tl; tl= tl->next_leaf)
1 by brian
clean slate
83
  {
84
    ha_rows tmp= tl->table->file->records();
85
    if ((tmp == HA_POS_ERROR))
163 by Brian Aker
Merge Monty's code.
86
      return UINT64_MAX;
1 by brian
clean slate
87
    count*= tmp;
88
  }
89
  return count;
90
}
91
92
93
/**
94
  Substitutes constants for some COUNT(), MIN() and MAX() functions.
95
96
  @param tables                list of leaves of join table tree
97
  @param all_fields            All fields to be returned
98
  @param conds                 WHERE clause
99
100
  @note
101
    This function is only called for queries with sum functions and no
102
    GROUP BY part.
103
104
  @retval
105
    0                    no errors
106
  @retval
107
    1                    if all items were resolved
108
  @retval
109
    HA_ERR_KEY_NOT_FOUND on impossible conditions
110
  @retval
111
    HA_ERR_... if a deadlock or a lock wait timeout happens, for example
112
*/
113
327.2.4 by Brian Aker
Refactoring table.h
114
int opt_sum_query(TableList *tables, List<Item> &all_fields,COND *conds)
1 by brian
clean slate
115
{
116
  List_iterator_fast<Item> it(all_fields);
117
  int const_result= 1;
118
  bool recalc_const_item= 0;
151 by Brian Aker
Ulonglong to uint64_t
119
  uint64_t count= 1;
163 by Brian Aker
Merge Monty's code.
120
  bool is_exact_count= true, maybe_exact_count= true;
1 by brian
clean slate
121
  table_map removed_tables= 0, outer_tables= 0, used_tables= 0;
122
  table_map where_tables= 0;
123
  Item *item;
124
  int error;
125
126
  if (conds)
127
    where_tables= conds->used_tables();
128
129
  /*
130
    Analyze outer join dependencies, and, if possible, compute the number
131
    of returned rows.
132
  */
327.2.4 by Brian Aker
Refactoring table.h
133
  for (TableList *tl= tables; tl; tl= tl->next_leaf)
1 by brian
clean slate
134
  {
327.2.4 by Brian Aker
Refactoring table.h
135
    TableList *embedded;
1 by brian
clean slate
136
    for (embedded= tl ; embedded; embedded= embedded->embedding)
137
    {
138
      if (embedded->on_expr)
139
        break;
140
    }
141
    if (embedded)
142
    /* Don't replace expression on a table that is part of an outer join */
143
    {
144
      outer_tables|= tl->table->map;
145
146
      /*
147
        We can't optimise LEFT JOIN in cases where the WHERE condition
148
        restricts the table that is used, like in:
149
          SELECT MAX(t1.a) FROM t1 LEFT JOIN t2 join-condition
150
          WHERE t2.field IS NULL;
151
      */
152
      if (tl->table->map & where_tables)
153
        return 0;
154
    }
155
    else
156
      used_tables|= tl->table->map;
157
158
    /*
159
      If the storage manager of 'tl' gives exact row count as part of
160
      statistics (cheap), compute the total number of rows. If there are
161
      no outer table dependencies, this count may be used as the real count.
162
      Schema tables are filled after this function is invoked, so we can't
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
163
      get row count
1 by brian
clean slate
164
    */
165
    if (!(tl->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) ||
166
        tl->schema_table)
167
    {
168
      maybe_exact_count&= test(!tl->schema_table &&
169
                               (tl->table->file->ha_table_flags() &
170
                                HA_HAS_RECORDS));
51.1.35 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
171
      is_exact_count= false;
1 by brian
clean slate
172
      count= 1;                                 // ensure count != 0
173
    }
174
    else
175
    {
176
      error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
177
      if(error)
178
      {
179
        tl->table->file->print_error(error, MYF(ME_FATALERROR));
180
        return error;
181
      }
182
      count*= tl->table->file->stats.records;
183
    }
184
  }
185
186
  /*
187
    Iterate through all items in the SELECT clause and replace
188
    COUNT(), MIN() and MAX() with constants (if possible).
189
  */
190
191
  while ((item= it++))
192
  {
193
    if (item->type() == Item::SUM_FUNC_ITEM)
194
    {
195
      Item_sum *item_sum= (((Item_sum*) item));
196
      switch (item_sum->sum_func()) {
197
      case Item_sum::COUNT_FUNC:
198
        /*
199
          If the expr in COUNT(expr) can never be null we can change this
200
          to the number of rows in the tables if this number is exact and
201
          there are no outer joins.
202
        */
203
        if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null &&
204
            !outer_tables && maybe_exact_count)
205
        {
206
          if (!is_exact_count)
207
          {
163 by Brian Aker
Merge Monty's code.
208
            if ((count= get_exact_record_count(tables)) == UINT64_MAX)
1 by brian
clean slate
209
            {
210
              /* Error from handler in counting rows. Don't optimize count() */
211
              const_result= 0;
212
              continue;
213
            }
214
            is_exact_count= 1;                  // count is now exact
215
          }
152 by Brian Aker
longlong replacement
216
          ((Item_sum_count*) item)->make_const((int64_t) count);
1 by brian
clean slate
217
          recalc_const_item= 1;
218
        }
219
        else
220
          const_result= 0;
221
        break;
222
      case Item_sum::MIN_FUNC:
223
      {
224
        /*
225
          If MIN(expr) is the first part of a key or if all previous
226
          parts of the key is found in the COND, then we can use
227
          indexes to find the key.
228
        */
229
        Item *expr=item_sum->args[0];
230
        if (expr->real_item()->type() == Item::FIELD_ITEM)
231
        {
481 by Brian Aker
Remove all of uchar.
232
          unsigned char key_buff[MAX_KEY_LENGTH];
1 by brian
clean slate
233
          TABLE_REF ref;
482 by Brian Aker
Remove uint.
234
          uint32_t range_fl, prefix_len;
1 by brian
clean slate
235
236
          ref.key_buff= key_buff;
237
          Item_field *item_field= (Item_field*) (expr->real_item());
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
238
          Table *table= item_field->field->table;
1 by brian
clean slate
239
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
240
          /*
1 by brian
clean slate
241
            Look for a partial key that can be used for optimization.
242
            If we succeed, ref.key_length will contain the length of
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
243
            this key, while prefix_len will contain the length of
244
            the beginning of this key without field used in MIN().
1 by brian
clean slate
245
            Type of range for the key part for this field will be
246
            returned in range_fl.
247
          */
248
          if (table->file->inited || (outer_tables & table->map) ||
249
              !find_key_for_maxmin(0, &ref, item_field->field, conds,
250
                                   &range_fl, &prefix_len))
251
          {
252
            const_result= 0;
253
            break;
254
          }
255
          error= table->file->ha_index_init((uint) ref.key, 1);
256
257
          if (!ref.key_length)
258
            error= table->file->index_first(table->record[0]);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
259
          else
1 by brian
clean slate
260
          {
261
            /*
262
              Use index to replace MIN/MAX functions with their values
263
              according to the following rules:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
264
1 by brian
clean slate
265
              1) Insert the minimum non-null values where the WHERE clause still
266
                 matches, or
267
              2) a NULL value if there are only NULL values for key_part_k.
268
              3) Fail, producing a row of nulls
269
270
              Implementation: Read the smallest value using the search key. If
271
              the interval is open, read the next value after the search
272
              key. If read fails, and we're looking for a MIN() value for a
273
              nullable column, test if there is an exact match for the key.
274
            */
275
            if (!(range_fl & NEAR_MIN))
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
276
              /*
1 by brian
clean slate
277
                 Closed interval: Either The MIN argument is non-nullable, or
278
                 we have a >= predicate for the MIN argument.
279
              */
280
              error= table->file->index_read_map(table->record[0],
281
                                                 ref.key_buff,
282
                                                 make_prev_keypart_map(ref.key_parts),
283
                                                 HA_READ_KEY_OR_NEXT);
284
            else
285
            {
286
              /*
287
                Open interval: There are two cases:
288
                1) We have only MIN() and the argument column is nullable, or
289
                2) there is a > predicate on it, nullability is irrelevant.
290
                We need to scan the next bigger record first.
291
              */
292
              error= table->file->index_read_map(table->record[0],
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
293
                                                 ref.key_buff,
1 by brian
clean slate
294
                                                 make_prev_keypart_map(ref.key_parts),
295
                                                 HA_READ_AFTER_KEY);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
296
              /*
1 by brian
clean slate
297
                 If the found record is outside the group formed by the search
298
                 prefix, or there is no such record at all, check if all
299
                 records in that group have NULL in the MIN argument
300
                 column. If that is the case return that NULL.
301
302
                 Check if case 1 from above holds. If it does, we should read
303
                 the skipped tuple.
304
              */
305
              if (item_field->field->real_maybe_null() &&
306
                  ref.key_buff[prefix_len] == 1 &&
307
                  /*
308
                     Last keypart (i.e. the argument to MIN) is set to NULL by
309
                     find_key_for_maxmin only if all other keyparts are bound
310
                     to constants in a conjunction of equalities. Hence, we
311
                     can detect this by checking only if the last keypart is
312
                     NULL.
313
                  */
314
                  (error == HA_ERR_KEY_NOT_FOUND ||
315
                   key_cmp_if_same(table, ref.key_buff, ref.key, prefix_len)))
316
              {
51.1.35 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
317
                assert(item_field->field->real_maybe_null());
1 by brian
clean slate
318
                error= table->file->index_read_map(table->record[0],
319
                                                   ref.key_buff,
320
                                                   make_prev_keypart_map(ref.key_parts),
321
                                                   HA_READ_KEY_EXACT);
322
              }
323
            }
324
          }
325
          /* Verify that the read tuple indeed matches the search key */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
326
	  if (!error && reckey_in_range(0, &ref, item_field->field,
1 by brian
clean slate
327
			                conds, range_fl, prefix_len))
328
	    error= HA_ERR_KEY_NOT_FOUND;
329
          if (table->key_read)
330
          {
331
            table->key_read= 0;
332
            table->file->extra(HA_EXTRA_NO_KEYREAD);
333
          }
334
          table->file->ha_index_end();
335
          if (error)
336
	  {
337
	    if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
338
	      return HA_ERR_KEY_NOT_FOUND;	      // No rows matching WHERE
339
	    /* HA_ERR_LOCK_DEADLOCK or some other error */
340
 	    table->file->print_error(error, MYF(0));
341
            return(error);
342
	  }
343
          removed_tables|= table->map;
344
        }
345
        else if (!expr->const_item() || !is_exact_count)
346
        {
347
          /*
348
            The optimization is not applicable in both cases:
349
            (a) 'expr' is a non-constant expression. Then we can't
350
            replace 'expr' by a constant.
351
            (b) 'expr' is a costant. According to ANSI, MIN/MAX must return
352
            NULL if the query does not return any rows. Thus, if we are not
353
            able to determine if the query returns any rows, we can't apply
354
            the optimization and replace MIN/MAX with a constant.
355
          */
356
          const_result= 0;
357
          break;
358
        }
359
        if (!count)
360
        {
163 by Brian Aker
Merge Monty's code.
361
          /* If count == 0, then we know that is_exact_count == true. */
1 by brian
clean slate
362
          ((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */
363
        }
364
        else
365
          ((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */
366
        ((Item_sum_min*) item_sum)->make_const();
367
        recalc_const_item= 1;
368
        break;
369
      }
370
      case Item_sum::MAX_FUNC:
371
      {
372
        /*
373
          If MAX(expr) is the first part of a key or if all previous
374
          parts of the key is found in the COND, then we can use
375
          indexes to find the key.
376
        */
377
        Item *expr=item_sum->args[0];
378
        if (expr->real_item()->type() == Item::FIELD_ITEM)
379
        {
481 by Brian Aker
Remove all of uchar.
380
          unsigned char key_buff[MAX_KEY_LENGTH];
1 by brian
clean slate
381
          TABLE_REF ref;
482 by Brian Aker
Remove uint.
382
          uint32_t range_fl, prefix_len;
1 by brian
clean slate
383
384
          ref.key_buff= key_buff;
385
          Item_field *item_field= (Item_field*) (expr->real_item());
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
386
          Table *table= item_field->field->table;
1 by brian
clean slate
387
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
388
          /*
1 by brian
clean slate
389
            Look for a partial key that can be used for optimization.
390
            If we succeed, ref.key_length will contain the length of
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
391
            this key, while prefix_len will contain the length of
1 by brian
clean slate
392
            the beginning of this key without field used in MAX().
393
            Type of range for the key part for this field will be
394
            returned in range_fl.
395
          */
396
          if (table->file->inited || (outer_tables & table->map) ||
397
	          !find_key_for_maxmin(1, &ref, item_field->field, conds,
398
				                   &range_fl, &prefix_len))
399
          {
400
            const_result= 0;
401
            break;
402
          }
403
          error= table->file->ha_index_init((uint) ref.key, 1);
404
405
          if (!ref.key_length)
406
            error= table->file->index_last(table->record[0]);
407
          else
408
	    error= table->file->index_read_map(table->record[0], key_buff,
409
                                               make_prev_keypart_map(ref.key_parts),
410
                                               range_fl & NEAR_MAX ?
411
                                               HA_READ_BEFORE_KEY :
412
                                               HA_READ_PREFIX_LAST_OR_PREV);
413
	  if (!error && reckey_in_range(1, &ref, item_field->field,
414
			                conds, range_fl, prefix_len))
415
	    error= HA_ERR_KEY_NOT_FOUND;
416
          if (table->key_read)
417
          {
418
            table->key_read=0;
419
            table->file->extra(HA_EXTRA_NO_KEYREAD);
420
          }
421
          table->file->ha_index_end();
422
          if (error)
423
          {
424
	    if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
425
	      return HA_ERR_KEY_NOT_FOUND;	     // No rows matching WHERE
426
	    /* HA_ERR_LOCK_DEADLOCK or some other error */
427
            table->file->print_error(error, MYF(ME_FATALERROR));
428
            return(error);
429
	  }
430
          removed_tables|= table->map;
431
        }
432
        else if (!expr->const_item() || !is_exact_count)
433
        {
434
          /*
435
            The optimization is not applicable in both cases:
436
            (a) 'expr' is a non-constant expression. Then we can't
437
            replace 'expr' by a constant.
438
            (b) 'expr' is a costant. According to ANSI, MIN/MAX must return
439
            NULL if the query does not return any rows. Thus, if we are not
440
            able to determine if the query returns any rows, we can't apply
441
            the optimization and replace MIN/MAX with a constant.
442
          */
443
          const_result= 0;
444
          break;
445
        }
446
        if (!count)
447
        {
163 by Brian Aker
Merge Monty's code.
448
          /* If count != 1, then we know that is_exact_count == true. */
1 by brian
clean slate
449
          ((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */
450
        }
451
        else
452
          ((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */
453
        ((Item_sum_max*) item_sum)->make_const();
454
        recalc_const_item= 1;
455
        break;
456
      }
457
      default:
458
        const_result= 0;
459
        break;
460
      }
461
    }
462
    else if (const_result)
463
    {
464
      if (recalc_const_item)
465
        item->update_used_tables();
466
      if (!item->const_item())
467
        const_result= 0;
468
    }
469
  }
470
  /*
471
    If we have a where clause, we can only ignore searching in the
472
    tables if MIN/MAX optimisation replaced all used tables
473
    We do not use replaced values in case of:
474
    SELECT MIN(key) FROM table_1, empty_table
475
    removed_tables is != 0 if we have used MIN() or MAX().
476
  */
477
  if (removed_tables && used_tables != removed_tables)
478
    const_result= 0;                            // We didn't remove all tables
479
  return const_result;
480
}
481
482
483
/**
484
  Test if the predicate compares a field with constants.
485
486
  @param func_item        Predicate item
487
  @param[out] args        Here we store the field followed by constants
488
  @param[out] inv_order   Is set to 1 if the predicate is of the form
489
                          'const op field'
490
491
  @retval
492
    0        func_item is a simple predicate: a field is compared with
493
    constants
494
  @retval
495
    1        Otherwise
496
*/
497
498
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
499
{
500
  Item *item;
501
  *inv_order= 0;
502
  switch (func_item->argument_count()) {
503
  case 0:
504
    /* MULT_EQUAL_FUNC */
505
    {
506
      Item_equal *item_equal= (Item_equal *) func_item;
507
      Item_equal_iterator it(*item_equal);
508
      args[0]= it++;
509
      if (it++)
510
        return 0;
511
      if (!(args[1]= item_equal->get_const()))
512
        return 0;
513
    }
514
    break;
515
  case 1:
516
    /* field IS NULL */
517
    item= func_item->arguments()[0];
518
    if (item->type() != Item::FIELD_ITEM)
519
      return 0;
520
    args[0]= item;
521
    break;
522
  case 2:
523
    /* 'field op const' or 'const op field' */
524
    item= func_item->arguments()[0];
525
    if (item->type() == Item::FIELD_ITEM)
526
    {
527
      args[0]= item;
528
      item= func_item->arguments()[1];
529
      if (!item->const_item())
530
        return 0;
531
      args[1]= item;
532
    }
533
    else if (item->const_item())
534
    {
535
      args[1]= item;
536
      item= func_item->arguments()[1];
537
      if (item->type() != Item::FIELD_ITEM)
538
        return 0;
539
      args[0]= item;
540
      *inv_order= 1;
541
    }
542
    else
543
      return 0;
544
    break;
545
  case 3:
546
    /* field BETWEEN const AND const */
547
    item= func_item->arguments()[0];
548
    if (item->type() == Item::FIELD_ITEM)
549
    {
550
      args[0]= item;
551
      for (int i= 1 ; i <= 2; i++)
552
      {
553
        item= func_item->arguments()[i];
554
        if (!item->const_item())
555
          return 0;
556
        args[i]= item;
557
      }
558
    }
559
    else
560
      return 0;
561
  }
562
  return 1;
563
}
564
565
566
/**
567
  Check whether a condition matches a key to get {MAX|MIN}(field):.
568
569
     For the index specified by the keyinfo parameter, index that
570
     contains field as its component (field_part), the function
571
     checks whether the condition cond is a conjunction and all its
572
     conjuncts referring to the columns of the same table as column
573
     field are one of the following forms:
574
     - f_i= const_i or const_i= f_i or f_i is null,
575
     where f_i is part of the index
576
     - field {<|<=|>=|>|=} const or const {<|<=|>=|>|=} field
577
     - field between const1 and const2
578
579
  @param[in]     max_fl         Set to 1 if we are optimising MAX()
580
  @param[in,out] ref            Reference to the structure we store the key
581
    value
582
  @param[in]     keyinfo        Reference to the key info
583
  @param[in]     field_part     Pointer to the key part for the field
584
  @param[in]     cond           WHERE condition
585
  @param[in,out] key_part_used  Map of matchings parts
586
  @param[in,out] range_fl       Says whether including key will be used
587
  @param[out]    prefix_len     Length of common key part for the range
588
    where MAX/MIN is searched for
589
590
  @retval
591
    0        Index can't be used.
592
  @retval
593
    1        We can use index to get MIN/MAX value
594
*/
595
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
596
static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
1 by brian
clean slate
597
                          KEY_PART_INFO *field_part, COND *cond,
482 by Brian Aker
Remove uint.
598
                          key_part_map *key_part_used, uint32_t *range_fl,
599
                          uint32_t *prefix_len)
1 by brian
clean slate
600
{
601
  if (!cond)
602
    return 1;
603
  Field *field= field_part->field;
604
  if (!(cond->used_tables() & field->table->map))
605
  {
606
    /* Condition doesn't restrict the used table */
607
    return 1;
608
  }
609
  if (cond->type() == Item::COND_ITEM)
610
  {
611
    if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
612
      return 0;
613
614
    /* AND */
615
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
616
    Item *item;
617
    while ((item= li++))
618
    {
619
      if (!matching_cond(max_fl, ref, keyinfo, field_part, item,
620
                         key_part_used, range_fl, prefix_len))
621
        return 0;
622
    }
623
    return 1;
624
  }
625
626
  if (cond->type() != Item::FUNC_ITEM)
627
    return 0;                                 // Not operator, can't optimize
628
629
  bool eq_type= 0;                            // =, <=> or IS NULL
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
630
  bool noeq_type= 0;                          // < or >
631
  bool less_fl= 0;                            // < or <=
1 by brian
clean slate
632
  bool is_null= 0;
633
  bool between= 0;
634
635
  switch (((Item_func*) cond)->functype()) {
636
  case Item_func::ISNULL_FUNC:
637
    is_null= 1;     /* fall through */
638
  case Item_func::EQ_FUNC:
639
  case Item_func::EQUAL_FUNC:
640
    eq_type= 1;
641
    break;
642
  case Item_func::LT_FUNC:
643
    noeq_type= 1;   /* fall through */
644
  case Item_func::LE_FUNC:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
645
    less_fl= 1;
1 by brian
clean slate
646
    break;
647
  case Item_func::GT_FUNC:
648
    noeq_type= 1;   /* fall through */
649
  case Item_func::GE_FUNC:
650
    break;
651
  case Item_func::BETWEEN:
652
    between= 1;
653
    break;
654
  case Item_func::MULT_EQUAL_FUNC:
655
    eq_type= 1;
656
    break;
657
  default:
658
    return 0;                                        // Can't optimize function
659
  }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
660
1 by brian
clean slate
661
  Item *args[3];
662
  bool inv;
663
664
  /* Test if this is a comparison of a field and constant */
665
  if (!simple_pred((Item_func*) cond, args, &inv))
666
    return 0;
667
668
  if (inv && !eq_type)
669
    less_fl= 1-less_fl;                         // Convert '<' -> '>' (etc)
670
671
  /* Check if field is part of the tested partial key */
481 by Brian Aker
Remove all of uchar.
672
  unsigned char *key_ptr= ref->key_buff;
1 by brian
clean slate
673
  KEY_PART_INFO *part;
674
  for (part= keyinfo->key_part; ; key_ptr+= part++->store_length)
675
676
  {
677
    if (part > field_part)
678
      return 0;                     // Field is beyond the tested parts
679
    if (part->field->eq(((Item_field*) args[0])->field))
680
      break;                        // Found a part of the key for the field
681
  }
682
683
  bool is_field_part= part == field_part;
684
  if (!(is_field_part || eq_type))
685
    return 0;
686
687
  key_part_map org_key_part_used= *key_part_used;
688
  if (eq_type || between || max_fl == less_fl)
689
  {
482 by Brian Aker
Remove uint.
690
    uint32_t length= (key_ptr-ref->key_buff)+part->store_length;
1 by brian
clean slate
691
    if (ref->key_length < length)
692
    {
693
    /* Ultimately ref->key_length will contain the length of the search key */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
694
      ref->key_length= length;
1 by brian
clean slate
695
      ref->key_parts= (part - keyinfo->key_part) + 1;
696
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
697
    if (!*prefix_len && part+1 == field_part)
1 by brian
clean slate
698
      *prefix_len= length;
699
    if (is_field_part && eq_type)
700
      *prefix_len= ref->key_length;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
701
1 by brian
clean slate
702
    *key_part_used|= (key_part_map) 1 << (part - keyinfo->key_part);
703
  }
704
705
  if (org_key_part_used != *key_part_used ||
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
706
      (is_field_part &&
1 by brian
clean slate
707
       (between || eq_type || max_fl == less_fl) && !cond->val_int()))
708
  {
709
    /*
710
      It's the first predicate for this part or a predicate of the
711
      following form  that moves upper/lower bounds for max/min values:
712
      - field BETWEEN const AND const
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
713
      - field = const
1 by brian
clean slate
714
      - field {<|<=} const, when searching for MAX
715
      - field {>|>=} const, when searching for MIN
716
    */
717
718
    if (is_null)
719
    {
720
      part->field->set_null();
481 by Brian Aker
Remove all of uchar.
721
      *key_ptr= (unsigned char) 1;
1 by brian
clean slate
722
    }
723
    else
724
    {
725
      store_val_in_field(part->field, args[between && max_fl ? 2 : 1],
726
                         CHECK_FIELD_IGNORE);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
727
      if (part->null_bit)
481 by Brian Aker
Remove all of uchar.
728
        *key_ptr++= (unsigned char) test(part->field->is_null());
1 by brian
clean slate
729
      part->field->get_key_image(key_ptr, part->length, Field::itRAW);
730
    }
731
    if (is_field_part)
732
    {
733
      if (between || eq_type)
734
        *range_fl&= ~(NO_MAX_RANGE | NO_MIN_RANGE);
735
      else
736
      {
737
        *range_fl&= ~(max_fl ? NO_MAX_RANGE : NO_MIN_RANGE);
738
        if (noeq_type)
739
          *range_fl|=  (max_fl ? NEAR_MAX : NEAR_MIN);
740
        else
741
          *range_fl&= ~(max_fl ? NEAR_MAX : NEAR_MIN);
742
      }
743
    }
744
  }
745
  else if (eq_type)
746
  {
747
    if ((!is_null && !cond->val_int()) ||
748
        (is_null && !test(part->field->is_null())))
749
     return 0;                       // Impossible test
750
  }
751
  else if (is_field_part)
752
    *range_fl&= ~(max_fl ? NO_MIN_RANGE : NO_MAX_RANGE);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
753
  return 1;
1 by brian
clean slate
754
}
755
756
757
/**
758
  Check whether we can get value for {max|min}(field) by using a key.
759
760
     If where-condition is not a conjunction of 0 or more conjuct the
761
     function returns false, otherwise it checks whether there is an
762
     index including field as its k-th component/part such that:
763
764
     -# for each previous component f_i there is one and only one conjunct
765
        of the form: f_i= const_i or const_i= f_i or f_i is null
766
     -# references to field occur only in conjucts of the form:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
767
        field {<|<=|>=|>|=} const or const {<|<=|>=|>|=} field or
1 by brian
clean slate
768
        field BETWEEN const1 AND const2
769
     -# all references to the columns from the same table as column field
770
        occur only in conjucts mentioned above.
771
     -# each of k first components the index is not partial, i.e. is not
772
        defined on a fixed length proper prefix of the field.
773
774
     If such an index exists the function through the ref parameter
775
     returns the key value to find max/min for the field using the index,
776
     the length of first (k-1) components of the key and flags saying
777
     how to apply the key for the search max/min value.
778
     (if we have a condition field = const, prefix_len contains the length
779
     of the whole search key)
780
781
  @param[in]     max_fl      0 for MIN(field) / 1 for MAX(field)
782
  @param[in,out] ref         Reference to the structure we store the key value
783
  @param[in]     field       Field used inside MIN() / MAX()
784
  @param[in]     cond        WHERE condition
785
  @param[out]    range_fl    Bit flags for how to search if key is ok
786
  @param[out]    prefix_len  Length of prefix for the search range
787
788
  @note
789
    This function may set table->key_read to 1, which must be reset after
790
    index is used! (This can only happen when function returns 1)
791
792
  @retval
793
    0   Index can not be used to optimize MIN(field)/MAX(field)
794
  @retval
795
    1   Can use key to optimize MIN()/MAX().
796
    In this case ref, range_fl and prefix_len are updated
797
*/
798
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
799
1 by brian
clean slate
800
static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
801
                                Field* field, COND *cond,
482 by Brian Aker
Remove uint.
802
                                uint32_t *range_fl, uint32_t *prefix_len)
1 by brian
clean slate
803
{
804
  if (!(field->flags & PART_KEY_FLAG))
805
    return 0;                                        // Not key field
806
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
807
  Table *table= field->table;
482 by Brian Aker
Remove uint.
808
  uint32_t idx= 0;
1 by brian
clean slate
809
810
  KEY *keyinfo,*keyinfo_end;
811
  for (keyinfo= table->key_info, keyinfo_end= keyinfo+table->s->keys ;
812
       keyinfo != keyinfo_end;
813
       keyinfo++,idx++)
814
  {
815
    KEY_PART_INFO *part,*part_end;
816
    key_part_map key_part_to_use= 0;
817
    /*
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
818
      Perform a check if index is not disabled by ALTER Table
1 by brian
clean slate
819
      or IGNORE INDEX.
820
    */
821
    if (!table->keys_in_use_for_query.is_set(idx))
822
      continue;
482 by Brian Aker
Remove uint.
823
    uint32_t jdx= 0;
1 by brian
clean slate
824
    *prefix_len= 0;
825
    for (part= keyinfo->key_part, part_end= part+keyinfo->key_parts ;
826
         part != part_end ;
827
         part++, jdx++, key_part_to_use= (key_part_to_use << 1) | 1)
828
    {
829
      if (!(table->file->index_flags(idx, jdx, 0) & HA_READ_ORDER))
830
        return 0;
831
832
      /* Check whether the index component is partial */
833
      Field *part_field= table->field[part->fieldnr-1];
834
      if ((part_field->flags & BLOB_FLAG) ||
835
          part->length < part_field->key_length())
836
        break;
837
838
      if (field->eq(part->field))
839
      {
840
        ref->key= idx;
841
        ref->key_length= 0;
842
        ref->key_parts= 0;
843
        key_part_map key_part_used= 0;
844
        *range_fl= NO_MIN_RANGE | NO_MAX_RANGE;
845
        if (matching_cond(max_fl, ref, keyinfo, part, cond,
846
                          &key_part_used, range_fl, prefix_len) &&
847
            !(key_part_to_use & ~key_part_used))
848
        {
849
          if (!max_fl && key_part_used == key_part_to_use && part->null_bit)
850
          {
851
            /*
852
              The query is on this form:
853
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
854
              SELECT MIN(key_part_k)
855
              FROM t1
1 by brian
clean slate
856
              WHERE key_part_1 = const and ... and key_part_k-1 = const
857
858
              If key_part_k is nullable, we want to find the first matching row
859
              where key_part_k is not null. The key buffer is now {const, ...,
860
              NULL}. This will be passed to the handler along with a flag
861
              indicating open interval. If a tuple is read that does not match
862
              these search criteria, an attempt will be made to read an exact
863
              match for the key buffer.
864
            */
865
            /* Set the first byte of key_part_k to 1, that means NULL */
866
            ref->key_buff[ref->key_length]= 1;
867
            ref->key_length+= part->store_length;
868
            ref->key_parts++;
51.1.35 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
869
            assert(ref->key_parts == jdx+1);
1 by brian
clean slate
870
            *range_fl&= ~NO_MIN_RANGE;
871
            *range_fl|= NEAR_MIN; // Open interval
872
          }
873
          /*
874
            The following test is false when the key in the key tree is
875
            converted (for example to upper case)
876
          */
877
          if (field->part_of_key.is_set(idx))
878
          {
879
            table->key_read= 1;
880
            table->file->extra(HA_EXTRA_KEYREAD);
881
          }
882
          return 1;
883
        }
884
      }
885
    }
886
  }
887
  return 0;
888
}
889
890
891
/**
892
  Check whether found key is in range specified by conditions.
893
894
  @param[in] max_fl         0 for MIN(field) / 1 for MAX(field)
895
  @param[in] ref            Reference to the key value and info
896
  @param[in] field          Field used the MIN/MAX expression
897
  @param[in] cond           WHERE condition
898
  @param[in] range_fl       Says whether there is a condition to to be checked
899
  @param[in] prefix_len     Length of the constant part of the key
900
901
  @retval
902
    0        ok
903
  @retval
904
    1        WHERE was not true for the found row
905
*/
906
907
static int reckey_in_range(bool max_fl, TABLE_REF *ref, Field* field,
482 by Brian Aker
Remove uint.
908
                            COND *cond, uint32_t range_fl, uint32_t prefix_len)
1 by brian
clean slate
909
{
910
  if (key_cmp_if_same(field->table, ref->key_buff, ref->key, prefix_len))
911
    return 1;
912
  if (!cond || (range_fl & (max_fl ? NO_MIN_RANGE : NO_MAX_RANGE)))
913
    return 0;
914
  return maxmin_in_range(max_fl, field, cond);
915
}
916
917
918
/**
919
  Check whether {MAX|MIN}(field) is in range specified by conditions.
920
921
  @param[in] max_fl          0 for MIN(field) / 1 for MAX(field)
922
  @param[in] field           Field used the MIN/MAX expression
923
  @param[in] cond            WHERE condition
924
925
  @retval
926
    0        ok
927
  @retval
928
    1        WHERE was not true for the found row
929
*/
930
931
static int maxmin_in_range(bool max_fl, Field* field, COND *cond)
932
{
933
  /* If AND/OR condition */
934
  if (cond->type() == Item::COND_ITEM)
935
  {
936
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
937
    Item *item;
938
    while ((item= li++))
939
    {
940
      if (maxmin_in_range(max_fl, field, item))
941
        return 1;
942
    }
943
    return 0;
944
  }
945
946
  if (cond->used_tables() != field->table->map)
947
    return 0;
948
  bool less_fl= 0;
949
  switch (((Item_func*) cond)->functype()) {
950
  case Item_func::BETWEEN:
951
    return cond->val_int() == 0;                // Return 1 if WHERE is false
952
  case Item_func::LT_FUNC:
953
  case Item_func::LE_FUNC:
954
    less_fl= 1;
955
  case Item_func::GT_FUNC:
956
  case Item_func::GE_FUNC:
957
  {
958
    Item *item= ((Item_func*) cond)->arguments()[1];
959
    /* In case of 'const op item' we have to swap the operator */
960
    if (!item->const_item())
961
      less_fl= 1-less_fl;
962
    /*
963
      We only have to check the expression if we are using an expression like
964
      SELECT MAX(b) FROM t1 WHERE a=const AND b>const
965
      not for
966
      SELECT MAX(b) FROM t1 WHERE a=const AND b<const
967
    */
968
    if (max_fl != less_fl)
969
      return cond->val_int() == 0;                // Return 1 if WHERE is false
970
    return 0;
971
  }
972
  case Item_func::EQ_FUNC:
973
  case Item_func::EQUAL_FUNC:
974
    break;
975
  default:                                        // Keep compiler happy
51.1.35 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
976
    assert(1);                               // Impossible
1 by brian
clean slate
977
    break;
978
  }
979
  return 0;
980
}
981