opt_sum.cc 35.4 KB
Newer Older
1 2
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
   Copyright (c) 2008-2011 Monty Program Ab
unknown's avatar
unknown committed
3

unknown's avatar
unknown committed
4 5
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
6
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
7

unknown's avatar
unknown committed
8 9 10 11
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
unknown's avatar
unknown committed
12

unknown's avatar
unknown committed
13 14
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
15
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
unknown's avatar
unknown committed
16 17


unknown's avatar
unknown committed
18 19 20
/**
  @file

unknown's avatar
unknown committed
21 22 23 24 25 26 27
  Optimising of MIN(), MAX() and COUNT(*) queries without 'group by' clause
  by replacing the aggregate expression with a constant.  

  Given a table with a compound key on columns (a,b,c), the following
  types of queries are optimised (assuming the table handler supports
  the required methods)

unknown's avatar
unknown committed
28
  @verbatim
unknown's avatar
unknown committed
29 30 31 32 33 34 35
  SELECT COUNT(*) FROM t1[,t2,t3,...]
  SELECT MIN(b) FROM t1 WHERE a=const
  SELECT MAX(c) FROM t1 WHERE a=const AND b=const
  SELECT MAX(b) FROM t1 WHERE a=const AND b<const
  SELECT MIN(b) FROM t1 WHERE a=const AND b>const
  SELECT MIN(b) FROM t1 WHERE a=const AND b BETWEEN const AND const
  SELECT MAX(b) FROM t1 WHERE a=const AND b BETWEEN const AND const
unknown's avatar
unknown committed
36
  @endverbatim
unknown's avatar
unknown committed
37 38 39 40 41 42 43

  Instead of '<' one can use '<=', '>', '>=' and '=' as well.
  Instead of 'a=const' the condition 'a IS NULL' can be used.

  If all selected fields are replaced then we will also remove all
  involved tables and return the answer without any join. Thus, the
  following query will be replaced with a row of two constants:
unknown's avatar
unknown committed
44
  @verbatim
unknown's avatar
unknown committed
45 46
  SELECT MAX(b), MIN(d) FROM t1,t2 
    WHERE a=const AND b<const AND d>const
unknown's avatar
unknown committed
47
  @endverbatim
unknown's avatar
unknown committed
48 49
  (assuming a index for column d of table t2 is defined)
*/
unknown's avatar
unknown committed
50

51
#include <my_global.h>
52 53
#include "sql_priv.h"
#include "key.h"                                // key_cmp_if_same
unknown's avatar
unknown committed
54 55
#include "sql_select.h"

unknown's avatar
unknown committed
56 57 58
static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, Field* field,
                                COND *cond, uint *range_fl,
                                uint *key_prefix_length);
unknown's avatar
unknown committed
59 60 61 62
static int reckey_in_range(bool max_fl, TABLE_REF *ref, Field* field,
                            COND *cond, uint range_fl, uint prefix_len);
static int maxmin_in_range(bool max_fl, Field* field, COND *cond);

unknown's avatar
unknown committed
63

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
/*
  Get exact count of rows in all tables

  SYNOPSIS
    get_exact_records()
    tables		List of tables

  NOTES
    When this is called, we know all table handlers supports HA_HAS_RECORDS
    or HA_STATS_RECORDS_IS_EXACT

  RETURN
    ULONGLONG_MAX	Error: Could not calculate number of rows
    #			Multiplication of number of rows in all tables
*/

80
static ulonglong get_exact_record_count(List<TABLE_LIST> &tables)
81 82
{
  ulonglong count= 1;
83 84 85
  TABLE_LIST *tl;
  List_iterator<TABLE_LIST> ti(tables);
  while ((tl= ti++))
86 87
  {
    ha_rows tmp= tl->table->file->records();
88
    if (tmp == HA_POS_ERROR)
89 90 91 92 93 94 95
      return ULONGLONG_MAX;
    count*= tmp;
  }
  return count;
}


96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
/**
  Use index to read MIN(field) value.
  
  @param table      Table object
  @param ref        Reference to the structure where we store the key value
  @item_field       Field used in MIN()
  @range_fl         Whether range endpoint is strict less than
  @prefix_len       Length of common key part for the range
  
  @retval
    0               No errors
    HA_ERR_...      Otherwise
*/

static int get_index_min_value(TABLE *table, TABLE_REF *ref,
                               Item_field *item_field, uint range_fl,
                               uint prefix_len)
{
  int error;
  
  if (!ref->key_length)
Michael Widenius's avatar
Michael Widenius committed
117
    error= table->file->ha_index_first(table->record[0]);
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
  else 
  {
    /*
      Use index to replace MIN/MAX functions with their values
      according to the following rules:

      1) Insert the minimum non-null values where the WHERE clause still
         matches, or
      2) a NULL value if there are only NULL values for key_part_k.
      3) Fail, producing a row of nulls

      Implementation: Read the smallest value using the search key. If
      the interval is open, read the next value after the search
      key. If read fails, and we're looking for a MIN() value for a
      nullable column, test if there is an exact match for the key.
    */
    if (!(range_fl & NEAR_MIN))
      /* 
         Closed interval: Either The MIN argument is non-nullable, or
         we have a >= predicate for the MIN argument.
      */
Michael Widenius's avatar
Michael Widenius committed
139 140 141 142
      error= table->file->ha_index_read_map(table->record[0],
                                            ref->key_buff,
                                            make_prev_keypart_map(ref->key_parts),
                                            HA_READ_KEY_OR_NEXT);
143 144 145 146 147 148 149
    else
    {
      /*
        Open interval: There are two cases:
        1) We have only MIN() and the argument column is nullable, or
        2) there is a > predicate on it, nullability is irrelevant.
        We need to scan the next bigger record first.
150 151
        Open interval is not used if the search key involves the last keypart,
        and it would not work.
152
      */
153
      DBUG_ASSERT(prefix_len < ref->key_length);
Michael Widenius's avatar
Michael Widenius committed
154 155 156 157
      error= table->file->ha_index_read_map(table->record[0],
                                            ref->key_buff,
                                            make_prev_keypart_map(ref->key_parts),
                                            HA_READ_AFTER_KEY);
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
      /* 
         If the found record is outside the group formed by the search
         prefix, or there is no such record at all, check if all
         records in that group have NULL in the MIN argument
         column. If that is the case return that NULL.

         Check if case 1 from above holds. If it does, we should read
         the skipped tuple.
      */
      if (item_field->field->real_maybe_null() &&
          ref->key_buff[prefix_len] == 1 &&
          /*
            Last keypart (i.e. the argument to MIN) is set to NULL by
            find_key_for_maxmin only if all other keyparts are bound
            to constants in a conjunction of equalities. Hence, we
            can detect this by checking only if the last keypart is
            NULL.
          */
          (error == HA_ERR_KEY_NOT_FOUND ||
           key_cmp_if_same(table, ref->key_buff, ref->key, prefix_len)))
      {
        DBUG_ASSERT(item_field->field->real_maybe_null());
Michael Widenius's avatar
Michael Widenius committed
180 181 182 183
        error= table->file->ha_index_read_map(table->record[0],
                                              ref->key_buff,
                                              make_prev_keypart_map(ref->key_parts),
                                              HA_READ_KEY_EXACT);
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
      }
    }
  }
  return error;
}


/**
  Use index to read MAX(field) value.
  
  @param table      Table object
  @param ref        Reference to the structure where we store the key value
  @range_fl         Whether range endpoint is strict greater than
  
  @retval
    0               No errors
    HA_ERR_...      Otherwise
*/

static int get_index_max_value(TABLE *table, TABLE_REF *ref, uint range_fl)
{
  return (ref->key_length ?
Michael Widenius's avatar
Michael Widenius committed
206 207 208 209 210 211
          table->file->ha_index_read_map(table->record[0], ref->key_buff,
                                         make_prev_keypart_map(ref->key_parts),
                                         range_fl & NEAR_MAX ?
                                         HA_READ_BEFORE_KEY : 
                                         HA_READ_PREFIX_LAST_OR_PREV) :
          table->file->ha_index_last(table->record[0]));
212 213 214 215
}



unknown's avatar
unknown committed
216
/**
unknown's avatar
unknown committed
217 218
  Substitutes constants for some COUNT(), MIN() and MAX() functions.

219
  @param thd                   thread handler
unknown's avatar
unknown committed
220 221 222
  @param tables                list of leaves of join table tree
  @param all_fields            All fields to be returned
  @param conds                 WHERE clause
unknown's avatar
unknown committed
223

unknown's avatar
unknown committed
224
  @note
225
    This function is only called for queries with aggregate functions and no
226 227
    GROUP BY part. This means that the result set shall contain a single
    row only
unknown's avatar
unknown committed
228

unknown's avatar
unknown committed
229
  @retval
unknown's avatar
unknown committed
230
    0                    no errors
unknown's avatar
unknown committed
231
  @retval
unknown's avatar
unknown committed
232
    1                    if all items were resolved
unknown's avatar
unknown committed
233
  @retval
unknown's avatar
unknown committed
234
    HA_ERR_KEY_NOT_FOUND on impossible conditions
unknown's avatar
unknown committed
235 236
  @retval
    HA_ERR_... if a deadlock or a lock wait timeout happens, for example
237 238
  @retval
    ER_...     e.g. ER_SUBQUERY_NO_1_ROW
unknown's avatar
unknown committed
239
*/
unknown's avatar
unknown committed
240

241
int opt_sum_query(THD *thd,
Igor Babaev's avatar
Merge  
Igor Babaev committed
242
                  List<TABLE_LIST> &tables, List<Item> &all_fields, COND *conds)
unknown's avatar
unknown committed
243
{
unknown's avatar
unknown committed
244
  List_iterator_fast<Item> it(all_fields);
245 246
  List_iterator<TABLE_LIST> ti(tables);
  TABLE_LIST *tl;
unknown's avatar
unknown committed
247 248
  int const_result= 1;
  bool recalc_const_item= 0;
249 250
  ulonglong count= 1;
  bool is_exact_count= TRUE, maybe_exact_count= TRUE;
unknown's avatar
unknown committed
251 252
  table_map removed_tables= 0, outer_tables= 0, used_tables= 0;
  table_map where_tables= 0;
unknown's avatar
unknown committed
253
  Item *item;
254
  int error= 0;
255 256
  DBUG_ENTER("opt_sum_query");

unknown's avatar
unknown committed
257 258 259
  if (conds)
    where_tables= conds->used_tables();

260 261 262 263
  /*
    Analyze outer join dependencies, and, if possible, compute the number
    of returned rows.
  */
264
  while ((tl= ti++))
265
  {
unknown's avatar
unknown committed
266 267 268 269 270 271 272
    TABLE_LIST *embedded;
    for (embedded= tl ; embedded; embedded= embedded->embedding)
    {
      if (embedded->on_expr)
        break;
    }
    if (embedded)
273
    /* Don't replace expression on a table that is part of an outer join */
unknown's avatar
unknown committed
274 275 276 277
    {
      outer_tables|= tl->table->map;

      /*
unknown's avatar
unknown committed
278 279
        We can't optimise LEFT JOIN in cases where the WHERE condition
        restricts the table that is used, like in:
unknown's avatar
unknown committed
280
          SELECT MAX(t1.a) FROM t1 LEFT JOIN t2 join-condition
unknown's avatar
unknown committed
281
          WHERE t2.field IS NULL;
unknown's avatar
unknown committed
282 283
      */
      if (tl->table->map & where_tables)
284
        DBUG_RETURN(0);
unknown's avatar
unknown committed
285
    }
unknown's avatar
unknown committed
286 287
    else
      used_tables|= tl->table->map;
288 289

    /*
290 291 292
      If the storage manager of 'tl' gives exact row count as part of
      statistics (cheap), compute the total number of rows. If there are
      no outer table dependencies, this count may be used as the real count.
293 294
      Schema tables are filled after this function is invoked, so we can't
      get row count 
295
    */
296
    if (!(tl->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) ||
297
        tl->schema_table)
298
    {
299 300 301
      maybe_exact_count&= MY_TEST(!tl->schema_table &&
                                  (tl->table->file->ha_table_flags() &
                                   HA_HAS_RECORDS));
302
      is_exact_count= FALSE;
303 304
      count= 1;                                 // ensure count != 0
    }
305 306
    else if (tl->is_materialized_derived() || 
             tl->jtbm_subselect)
307 308 309 310 311
    {
      /*
        Can't remove a derived table as it's number of rows is just an
        estimate.
      */
Igor Babaev's avatar
Merge  
Igor Babaev committed
312
      DBUG_RETURN(0);
313
    }
314 315
    else
    {
316 317 318
      error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
      if(error)
      {
319
        tl->table->file->print_error(error, MYF(ME_FATALERROR));
320
        DBUG_RETURN(error);
321
      }
322
      count*= tl->table->file->stats.records;
323
    }
324 325 326
  }

  /*
327 328
    Iterate through all items in the SELECT clause and replace
    COUNT(), MIN() and MAX() with constants (if possible).
329
  */
unknown's avatar
unknown committed
330 331 332 333 334 335 336 337

  while ((item= it++))
  {
    if (item->type() == Item::SUM_FUNC_ITEM)
    {
      Item_sum *item_sum= (((Item_sum*) item));
      switch (item_sum->sum_func()) {
      case Item_sum::COUNT_FUNC:
unknown's avatar
unknown committed
338
        /*
339
          If the expr in COUNT(expr) can never be null we can change this
340 341
          to the number of rows in the tables if this number is exact and
          there are no outer joins.
unknown's avatar
unknown committed
342
        */
343
        if (!conds && !((Item_sum_count*) item)->get_arg(0)->maybe_null &&
344 345
            !outer_tables && maybe_exact_count &&
            ((item->used_tables() & OUTER_REF_TABLE_BIT) == 0))
unknown's avatar
unknown committed
346
        {
347 348 349 350 351 352 353 354 355 356 357
          if (!is_exact_count)
          {
            if ((count= get_exact_record_count(tables)) == ULONGLONG_MAX)
            {
              /* Error from handler in counting rows. Don't optimize count() */
              const_result= 0;
              continue;
            }
            is_exact_count= 1;                  // count is now exact
          }
          ((Item_sum_count*) item)->make_const((longlong) count);
358
          recalc_const_item= 1;
unknown's avatar
unknown committed
359 360 361 362
        }
        else
          const_result= 0;
        break;
unknown's avatar
unknown committed
363
      case Item_sum::MIN_FUNC:
364
      case Item_sum::MAX_FUNC:
unknown's avatar
unknown committed
365
      {
366
        int is_max= MY_TEST(item_sum->sum_func() == Item_sum::MAX_FUNC);
unknown's avatar
unknown committed
367
        /*
368
          If MIN/MAX(expr) is the first part of a key or if all previous
unknown's avatar
unknown committed
369 370 371
          parts of the key is found in the COND, then we can use
          indexes to find the key.
        */
372
        Item *expr=item_sum->get_arg(0);
373 374
        if (((expr->used_tables() & OUTER_REF_TABLE_BIT) == 0) &&
            expr->real_item()->type() == Item::FIELD_ITEM)
unknown's avatar
unknown committed
375
        {
376
          uchar key_buff[MAX_KEY_LENGTH];
unknown's avatar
unknown committed
377 378 379 380
          TABLE_REF ref;
          uint range_fl, prefix_len;

          ref.key_buff= key_buff;
381
          Item_field *item_field= (Item_field*) (expr->real_item());
unknown's avatar
unknown committed
382 383 384 385 386 387
          TABLE *table= item_field->field->table;

          /* 
            Look for a partial key that can be used for optimization.
            If we succeed, ref.key_length will contain the length of
            this key, while prefix_len will contain the length of 
388
            the beginning of this key without field used in MIN/MAX(). 
unknown's avatar
unknown committed
389 390
            Type of range for the key part for this field will be
            returned in range_fl.
unknown's avatar
unknown committed
391
          */
392
          if (table->file->inited || (outer_tables & table->map) ||
393
              !find_key_for_maxmin(is_max, &ref, item_field->field, conds,
unknown's avatar
unknown committed
394 395 396 397 398
                                   &range_fl, &prefix_len))
          {
            const_result= 0;
            break;
          }
Michael Widenius's avatar
Michael Widenius committed
399 400 401 402 403
          if (!(error= table->file->ha_index_init((uint) ref.key, 1)))
            error= (is_max ? 
                    get_index_max_value(table, &ref, range_fl) :
                    get_index_min_value(table, &ref, item_field, range_fl,
                                        prefix_len));
unknown's avatar
unknown committed
404

405
          /* Verify that the read tuple indeed matches the search key */
406
	  if (!error && reckey_in_range(is_max, &ref, item_field->field, 
unknown's avatar
unknown committed
407
			                conds, range_fl, prefix_len))
unknown's avatar
unknown committed
408
	    error= HA_ERR_KEY_NOT_FOUND;
409
          table->set_keyread(false);
unknown's avatar
unknown committed
410
          table->file->ha_index_end();
unknown's avatar
unknown committed
411
          if (error)
unknown's avatar
unknown committed
412
	  {
unknown's avatar
unknown committed
413
	    if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
414
	      DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); // No rows matching WHERE
unknown's avatar
unknown committed
415 416
	    /* HA_ERR_LOCK_DEADLOCK or some other error */
 	    table->file->print_error(error, MYF(0));
417
            DBUG_RETURN(error);
unknown's avatar
unknown committed
418
	  }
unknown's avatar
unknown committed
419 420
          removed_tables|= table->map;
        }
unknown's avatar
unknown committed
421
        else if (!expr->const_item() || !is_exact_count || conds)
unknown's avatar
unknown committed
422
        {
423 424 425 426 427 428 429 430
          /*
            The optimization is not applicable in both cases:
            (a) 'expr' is a non-constant expression. Then we can't
            replace 'expr' by a constant.
            (b) 'expr' is a costant. According to ANSI, MIN/MAX must return
            NULL if the query does not return any rows. Thus, if we are not
            able to determine if the query returns any rows, we can't apply
            the optimization and replace MIN/MAX with a constant.
unknown's avatar
unknown committed
431 432
            (c) there is a WHERE clause. The WHERE conditions may result in
            an empty result, but the clause cannot be taken into account here.
433
          */
unknown's avatar
unknown committed
434 435 436
          const_result= 0;
          break;
        }
437 438 439
        item_sum->set_aggregator(item_sum->has_with_distinct() ? 
                                 Aggregator::DISTINCT_AGGREGATOR :
                                 Aggregator::SIMPLE_AGGREGATOR);
unknown's avatar
unknown committed
440
        /*
441 442 443
          If count == 0 (so is_exact_count == TRUE) and
          there're no outer joins, set to NULL,
          otherwise set to the constant value.
unknown's avatar
unknown committed
444
        */
445
        if (!count && !outer_tables)
446
        {
447
          item_sum->aggregator_clear();
448 449
        }
        else
450
          item_sum->reset_and_add();
451
        item_sum->make_const();
unknown's avatar
unknown committed
452 453
        recalc_const_item= 1;
        break;
unknown's avatar
unknown committed
454 455
      }
      default:
unknown's avatar
unknown committed
456 457
        const_result= 0;
        break;
unknown's avatar
unknown committed
458 459 460 461 462
      }
    }
    else if (const_result)
    {
      if (recalc_const_item)
unknown's avatar
unknown committed
463
        item->update_used_tables();
unknown's avatar
unknown committed
464
      if (!item->const_item())
unknown's avatar
unknown committed
465
        const_result= 0;
unknown's avatar
unknown committed
466 467
    }
  }
468 469

  if (thd->is_error())
470
    DBUG_RETURN(thd->get_stmt_da()->sql_errno());
471

472 473 474
  /*
    If we have a where clause, we can only ignore searching in the
    tables if MIN/MAX optimisation replaced all used tables
unknown's avatar
unknown committed
475
    We do not use replaced values in case of:
476 477 478 479
    SELECT MIN(key) FROM table_1, empty_table
    removed_tables is != 0 if we have used MIN() or MAX().
  */
  if (removed_tables && used_tables != removed_tables)
unknown's avatar
unknown committed
480
    const_result= 0;                            // We didn't remove all tables
481
  DBUG_RETURN(const_result);
unknown's avatar
unknown committed
482 483 484
}


485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
/*
  Check if both item1 and item2 are strings, and item1 has fewer characters 
  than item2.
*/

static bool check_item1_shorter_item2(Item *item1, Item *item2)
{
  if (item1->cmp_type() == STRING_RESULT &&
      item2->cmp_type() == STRING_RESULT)
  {
    int len1= item1->max_length / item1->collation.collation->mbmaxlen;
    int len2= item2->max_length / item2->collation.collation->mbmaxlen;
    return len1 < len2;
  }
  return false;  /* When the check is not applicable, it means "not bigger" */
}


unknown's avatar
unknown committed
503 504
/**
  Test if the predicate compares a field with constants.
unknown's avatar
unknown committed
505

unknown's avatar
unknown committed
506 507 508 509
  @param func_item        Predicate item
  @param[out] args        Here we store the field followed by constants
  @param[out] inv_order   Is set to 1 if the predicate is of the form
                          'const op field'
unknown's avatar
unknown committed
510

unknown's avatar
unknown committed
511
  @retval
Igor Babaev's avatar
Igor Babaev committed
512 513
    0      func_item is a simple predicate: a field is compared with a constant
           whose length does not exceed the max length of the field values  
unknown's avatar
unknown committed
514
  @retval
unknown's avatar
unknown committed
515 516 517
    1        Otherwise
*/

518
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
unknown's avatar
unknown committed
519 520 521 522
{
  Item *item;
  *inv_order= 0;
  switch (func_item->argument_count()) {
523 524 525 526 527 528
  case 0:
    /* MULT_EQUAL_FUNC */
    {
      Item_equal *item_equal= (Item_equal *) func_item;
      if (!(args[1]= item_equal->get_const()))
        return 0;
Igor Babaev's avatar
Igor Babaev committed
529
      Item_equal_fields_iterator it(*item_equal);
Igor Babaev's avatar
Igor Babaev committed
530
      if (!(item= it++))
531
        return 0;
Igor Babaev's avatar
Igor Babaev committed
532
      args[0]= item->real_item();
533
      if (check_item1_shorter_item2(args[0], args[1]))
Igor Babaev's avatar
Igor Babaev committed
534
        return 0;
Igor Babaev's avatar
Igor Babaev committed
535
      if (it++)
536 537 538
        return 0;
    }
    break;
unknown's avatar
unknown committed
539 540
  case 1:
    /* field IS NULL */
Igor Babaev's avatar
Igor Babaev committed
541
    item= func_item->arguments()[0]->real_item();
unknown's avatar
unknown committed
542 543 544 545 546 547
    if (item->type() != Item::FIELD_ITEM)
      return 0;
    args[0]= item;
    break;
  case 2:
    /* 'field op const' or 'const op field' */
Igor Babaev's avatar
Igor Babaev committed
548
    item= func_item->arguments()[0]->real_item();
unknown's avatar
unknown committed
549
    if (item->type() == Item::FIELD_ITEM)
unknown's avatar
unknown committed
550
    {
unknown's avatar
unknown committed
551
      args[0]= item;
Igor Babaev's avatar
Igor Babaev committed
552
      item= func_item->arguments()[1]->real_item();
unknown's avatar
unknown committed
553 554 555
      if (!item->const_item())
        return 0;
      args[1]= item;
unknown's avatar
unknown committed
556
    }
unknown's avatar
unknown committed
557
    else if (item->const_item())
unknown's avatar
unknown committed
558
    {
unknown's avatar
unknown committed
559
      args[1]= item;
Igor Babaev's avatar
Igor Babaev committed
560
      item= func_item->arguments()[1]->real_item();
unknown's avatar
unknown committed
561 562 563 564
      if (item->type() != Item::FIELD_ITEM)
        return 0;
      args[0]= item;
      *inv_order= 1;
unknown's avatar
unknown committed
565
    }
unknown's avatar
unknown committed
566 567
    else
      return 0;
568
    if (check_item1_shorter_item2(args[0], args[1]))
Igor Babaev's avatar
Igor Babaev committed
569
      return 0;
unknown's avatar
unknown committed
570 571 572
    break;
  case 3:
    /* field BETWEEN const AND const */
Igor Babaev's avatar
Igor Babaev committed
573
    item= func_item->arguments()[0]->real_item();
unknown's avatar
unknown committed
574
    if (item->type() == Item::FIELD_ITEM)
unknown's avatar
unknown committed
575
    {
unknown's avatar
unknown committed
576 577 578
      args[0]= item;
      for (int i= 1 ; i <= 2; i++)
      {
Igor Babaev's avatar
Igor Babaev committed
579
        item= func_item->arguments()[i]->real_item();
unknown's avatar
unknown committed
580 581 582
        if (!item->const_item())
          return 0;
        args[i]= item;
583
        if (check_item1_shorter_item2(args[0], args[i]))
Igor Babaev's avatar
Igor Babaev committed
584
          return 0;
unknown's avatar
unknown committed
585
      }
unknown's avatar
unknown committed
586
    }
unknown's avatar
unknown committed
587 588
    else
      return 0;
unknown's avatar
unknown committed
589
  }
unknown's avatar
unknown committed
590
  return 1;
unknown's avatar
unknown committed
591 592 593
}


unknown's avatar
unknown committed
594 595
/**
  Check whether a condition matches a key to get {MAX|MIN}(field):.
unknown's avatar
unknown committed
596

597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
   For the index specified by the keyinfo parameter and an index that
   contains the field as its component (field_part), the function
   checks whether 

   - the condition cond is a conjunction, 
   - all of its conjuncts refer to columns of the same table, and
   - each conjunct is on one of the following forms:
     - f_i = const_i or const_i = f_i or f_i IS NULL,
       where f_i is part of the index
     - field {<|<=|>=|>|=} const
     - const {<|<=|>=|>|=} field
     - field BETWEEN const_1 AND const_2

   As a side-effect, the key value to be used for looking up the MIN/MAX value
   is actually stored inside the Field object. An interesting feature is that
   the function will find the most restrictive endpoint by over-eager
   evaluation of the @c WHERE condition. It continually stores the current
   endpoint inside the Field object. For a query such as

   @code
   SELECT MIN(a) FROM t1 WHERE a > 3 AND a > 5;
   @endcode

   the algorithm will recurse over the conjuction, storing first a 3 in the
   field. In the next recursive invocation the expression a > 5 is evaluated
   as 3 > 5 (Due to the dual nature of Field objects as value carriers and
   field identifiers), which will obviously fail, leading to 5 being stored in
   the Field object.
   
   @param[in]     max_fl         Set to true if we are optimizing MAX(),
                                 false means we are optimizing %MIN()
   @param[in, out] ref           Reference to the structure where the function 
                                 stores the key value
   @param[in]     keyinfo        Reference to the key info
   @param[in]     field_part     Pointer to the key part for the field
   @param[in]     cond           WHERE condition
   @param[in,out] key_part_used  Map of matchings parts. The function will output
                                 the set of key parts actually being matched in 
                                 this set, yet it relies on the caller to 
                                 initialize the value to zero. This is due 
                                 to the fact that this value is passed 
                                 recursively.
   @param[in,out] range_fl       Says whether endpoints use strict greater/less 
                                 than.
   @param[out]    prefix_len     Length of common key part for the range
                                 where MAX/MIN is searched for
unknown's avatar
unknown committed
643 644

  @retval
645
    false    Index can't be used.
unknown's avatar
unknown committed
646
  @retval
647
    true     We can use the index to get MIN/MAX value
unknown's avatar
unknown committed
648
*/
unknown's avatar
unknown committed
649

unknown's avatar
unknown committed
650 651 652 653
static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, 
                          KEY_PART_INFO *field_part, COND *cond,
                          key_part_map *key_part_used, uint *range_fl,
                          uint *prefix_len)
unknown's avatar
unknown committed
654
{
655
  DBUG_ENTER("matching_cond");
unknown's avatar
unknown committed
656
  if (!cond)
657
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
658
  Field *field= field_part->field;
659 660
  table_map cond_used_tables= cond->used_tables();
  if (cond_used_tables & OUTER_REF_TABLE_BIT)
Igor Babaev's avatar
Igor Babaev committed
661 662 663
  { 
    DBUG_RETURN(FALSE);
  } 
664 665
  if (!(cond_used_tables & field->table->map) &&
      MY_TEST(cond_used_tables & ~PSEUDO_TABLE_BITS))
unknown's avatar
unknown committed
666 667
  {
    /* Condition doesn't restrict the used table */
Igor Babaev's avatar
Igor Babaev committed
668
    DBUG_RETURN(!cond->const_item());
unknown's avatar
unknown committed
669
  }
unknown's avatar
unknown committed
670 671
  else if (cond->is_expensive())
    DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
672 673 674
  if (cond->type() == Item::COND_ITEM)
  {
    if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
675
      DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
676

unknown's avatar
unknown committed
677
    /* AND */
unknown's avatar
unknown committed
678
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
679
    Item *item;
unknown's avatar
unknown committed
680
    while ((item= li++))
unknown's avatar
unknown committed
681
    {
unknown's avatar
unknown committed
682 683
      if (!matching_cond(max_fl, ref, keyinfo, field_part, item,
                         key_part_used, range_fl, prefix_len))
684
        DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
685
    }
686
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
687 688 689
  }

  if (cond->type() != Item::FUNC_ITEM)
690
    DBUG_RETURN(FALSE);                                 // Not operator, can't optimize
unknown's avatar
unknown committed
691 692

  bool eq_type= 0;                            // =, <=> or IS NULL
693
  bool is_null_safe_eq= FALSE;                // The operator is NULL safe, e.g. <=> 
unknown's avatar
unknown committed
694 695
  bool noeq_type= 0;                          // < or >  
  bool less_fl= 0;                            // < or <= 
696 697
  bool is_null= 0;                            // IS NULL
  bool between= 0;                            // BETWEEN ... AND ... 
unknown's avatar
unknown committed
698 699 700 701 702

  switch (((Item_func*) cond)->functype()) {
  case Item_func::ISNULL_FUNC:
    is_null= 1;     /* fall through */
  case Item_func::EQ_FUNC:
703 704
    eq_type= TRUE;
    break;
unknown's avatar
unknown committed
705
  case Item_func::EQUAL_FUNC:
706
    eq_type= is_null_safe_eq= TRUE;
unknown's avatar
unknown committed
707 708 709 710 711 712 713 714 715 716 717
    break;
  case Item_func::LT_FUNC:
    noeq_type= 1;   /* fall through */
  case Item_func::LE_FUNC:
    less_fl= 1;      
    break;
  case Item_func::GT_FUNC:
    noeq_type= 1;   /* fall through */
  case Item_func::GE_FUNC:
    break;
  case Item_func::BETWEEN:
unknown's avatar
unknown committed
718 719
    if (((Item_func_between*) cond)->negated)
      DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
720 721
    between= 1;
    break;
722 723 724
  case Item_func::MULT_EQUAL_FUNC:
    eq_type= 1;
    break;
unknown's avatar
unknown committed
725
  default:
726
    DBUG_RETURN(FALSE);                                        // Can't optimize function
unknown's avatar
unknown committed
727 728 729 730 731 732 733
  }
  
  Item *args[3];
  bool inv;

  /* Test if this is a comparison of a field and constant */
  if (!simple_pred((Item_func*) cond, args, &inv))
734
    DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
735

736 737
  if (!is_null_safe_eq && !is_null &&
      (args[1]->is_null() || (between && args[2]->is_null())))
738
    DBUG_RETURN(FALSE);
739

unknown's avatar
unknown committed
740 741 742 743
  if (inv && !eq_type)
    less_fl= 1-less_fl;                         // Convert '<' -> '>' (etc)

  /* Check if field is part of the tested partial key */
744
  uchar *key_ptr= ref->key_buff;
unknown's avatar
unknown committed
745
  KEY_PART_INFO *part;
746
  for (part= keyinfo->key_part; ; key_ptr+= part++->store_length)
unknown's avatar
unknown committed
747 748 749

  {
    if (part > field_part)
750
      DBUG_RETURN(FALSE);                     // Field is beyond the tested parts
unknown's avatar
unknown committed
751
    if (part->field->eq(((Item_field*) args[0])->field))
752
      break;                        // Found a part of the key for the field
unknown's avatar
unknown committed
753 754 755 756
  }

  bool is_field_part= part == field_part;
  if (!(is_field_part || eq_type))
757
    DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
758 759 760 761 762 763

  key_part_map org_key_part_used= *key_part_used;
  if (eq_type || between || max_fl == less_fl)
  {
    uint length= (key_ptr-ref->key_buff)+part->store_length;
    if (ref->key_length < length)
764
    {
unknown's avatar
unknown committed
765 766
    /* Ultimately ref->key_length will contain the length of the search key */
      ref->key_length= length;      
767 768
      ref->key_parts= (part - keyinfo->key_part) + 1;
    }
unknown's avatar
unknown committed
769 770 771 772 773 774
    if (!*prefix_len && part+1 == field_part)       
      *prefix_len= length;
    if (is_field_part && eq_type)
      *prefix_len= ref->key_length;
  
    *key_part_used|= (key_part_map) 1 << (part - keyinfo->key_part);
unknown's avatar
unknown committed
775
  }
unknown's avatar
unknown committed
776

777 778 779 780 781 782 783 784 785 786 787
  if (org_key_part_used == *key_part_used &&
    /*
      The current search key is not being extended with a new key part.  This
      means that the a condition is added a key part for which there was a
      previous condition. We can only overwrite such key parts in some special
      cases, e.g. a > 2 AND a > 1 (here range_fl must be set to something). In
      all other cases the WHERE condition is always false anyway.
    */
      (eq_type || *range_fl == 0))
      DBUG_RETURN(FALSE);

unknown's avatar
unknown committed
788 789
  if (org_key_part_used != *key_part_used ||
      (is_field_part && 
unknown's avatar
unknown committed
790
       (between || eq_type || max_fl == less_fl) && !cond->val_int()))
unknown's avatar
unknown committed
791
  {
unknown's avatar
unknown committed
792 793 794 795
    /*
      It's the first predicate for this part or a predicate of the
      following form  that moves upper/lower bounds for max/min values:
      - field BETWEEN const AND const
unknown's avatar
unknown committed
796
      - field = const 
unknown's avatar
unknown committed
797 798 799 800
      - field {<|<=} const, when searching for MAX
      - field {>|>=} const, when searching for MIN
    */

801
    if (is_null || (is_null_safe_eq && args[1]->is_null()))
unknown's avatar
unknown committed
802
    {
803 804 805 806 807
      /*
        If we have a non-nullable index, we cannot use it,
        since set_null will be ignored, and we will compare uninitialized data.
      */
      if (!part->field->real_maybe_null())
Michael Widenius's avatar
Michael Widenius committed
808
        DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
809
      part->field->set_null();
810
      *key_ptr= (uchar) 1;
unknown's avatar
unknown committed
811
    }
unknown's avatar
unknown committed
812
    else
unknown's avatar
unknown committed
813
    {
814 815
      /* Update endpoints for MAX/MIN, see function comment. */
      Item *value= args[between && max_fl ? 2 : 1];
816
      value->save_in_field_no_warnings(part->field, 1);
unknown's avatar
unknown committed
817
      if (part->null_bit) 
818
        *key_ptr++= (uchar) MY_TEST(part->field->is_null());
819
      part->field->get_key_image(key_ptr, part->length, Field::itRAW);
unknown's avatar
unknown committed
820 821 822
    }
    if (is_field_part)
    {
unknown's avatar
unknown committed
823
      if (between || eq_type)
unknown's avatar
unknown committed
824 825 826 827 828 829 830 831 832
        *range_fl&= ~(NO_MAX_RANGE | NO_MIN_RANGE);
      else
      {
        *range_fl&= ~(max_fl ? NO_MAX_RANGE : NO_MIN_RANGE);
        if (noeq_type)
          *range_fl|=  (max_fl ? NEAR_MAX : NEAR_MIN);
        else
          *range_fl&= ~(max_fl ? NEAR_MAX : NEAR_MIN);
      }
unknown's avatar
unknown committed
833 834
    }
  }
unknown's avatar
unknown committed
835 836
  else if (eq_type)
  {
837
    if ((!is_null && !cond->val_int()) ||
838
        (is_null && !MY_TEST(part->field->is_null())))
839
     DBUG_RETURN(FALSE);                       // Impossible test
unknown's avatar
unknown committed
840 841 842
  }
  else if (is_field_part)
    *range_fl&= ~(max_fl ? NO_MIN_RANGE : NO_MAX_RANGE);
843
  DBUG_RETURN(TRUE);  
unknown's avatar
unknown committed
844 845 846
}


unknown's avatar
unknown committed
847
/**
unknown's avatar
unknown committed
848
  Check whether we can get value for {max|min}(field) by using a key.
unknown's avatar
unknown committed
849

unknown's avatar
unknown committed
850 851 852 853 854
     If where-condition is not a conjunction of 0 or more conjuct the
     function returns false, otherwise it checks whether there is an
     index including field as its k-th component/part such that:

     -# for each previous component f_i there is one and only one conjunct
unknown's avatar
unknown committed
855
        of the form: f_i= const_i or const_i= f_i or f_i is null
unknown's avatar
unknown committed
856
     -# references to field occur only in conjucts of the form:
unknown's avatar
unknown committed
857 858
        field {<|<=|>=|>|=} const or const {<|<=|>=|>|=} field or 
        field BETWEEN const1 AND const2
unknown's avatar
unknown committed
859
     -# all references to the columns from the same table as column field
unknown's avatar
unknown committed
860
        occur only in conjucts mentioned above.
unknown's avatar
unknown committed
861
     -# each of k first components the index is not partial, i.e. is not
unknown's avatar
unknown committed
862
        defined on a fixed length proper prefix of the field.
unknown's avatar
unknown committed
863 864 865 866 867 868

     If such an index exists the function through the ref parameter
     returns the key value to find max/min for the field using the index,
     the length of first (k-1) components of the key and flags saying
     how to apply the key for the search max/min value.
     (if we have a condition field = const, prefix_len contains the length
unknown's avatar
unknown committed
869 870 871 872 873 874 875 876
     of the whole search key)

  @param[in]     max_fl      0 for MIN(field) / 1 for MAX(field)
  @param[in,out] ref         Reference to the structure we store the key value
  @param[in]     field       Field used inside MIN() / MAX()
  @param[in]     cond        WHERE condition
  @param[out]    range_fl    Bit flags for how to search if key is ok
  @param[out]    prefix_len  Length of prefix for the search range
unknown's avatar
unknown committed
877

unknown's avatar
unknown committed
878
  @note
879 880 881
    This function may set field->table->key_read to true,
    which must be reset after index is used!
    (This can only happen when function returns 1)
unknown's avatar
unknown committed
882

unknown's avatar
unknown committed
883
  @retval
unknown's avatar
unknown committed
884
    0   Index can not be used to optimize MIN(field)/MAX(field)
unknown's avatar
unknown committed
885 886 887 888
  @retval
    1   Can use key to optimize MIN()/MAX().
    In this case ref, range_fl and prefix_len are updated
*/
unknown's avatar
unknown committed
889 890 891 892
      
static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
                                Field* field, COND *cond,
                                uint *range_fl, uint *prefix_len)
unknown's avatar
unknown committed
893 894
{
  if (!(field->flags & PART_KEY_FLAG))
Michael Widenius's avatar
Michael Widenius committed
895
    return FALSE;                               // Not key field
896 897

  DBUG_ENTER("find_key_for_maxmin");
unknown's avatar
unknown committed
898

unknown's avatar
unknown committed
899 900
  TABLE *table= field->table;
  uint idx= 0;
unknown's avatar
unknown committed
901

unknown's avatar
unknown committed
902
  KEY *keyinfo,*keyinfo_end;
903
  for (keyinfo= table->key_info, keyinfo_end= keyinfo+table->s->keys ;
unknown's avatar
unknown committed
904 905
       keyinfo != keyinfo_end;
       keyinfo++,idx++)
unknown's avatar
unknown committed
906
  {
unknown's avatar
unknown committed
907 908
    KEY_PART_INFO *part,*part_end;
    key_part_map key_part_to_use= 0;
909 910 911 912 913 914
    /*
      Perform a check if index is not disabled by ALTER TABLE
      or IGNORE INDEX.
    */
    if (!table->keys_in_use_for_query.is_set(idx))
      continue;
unknown's avatar
unknown committed
915
    uint jdx= 0;
unknown's avatar
unknown committed
916
    *prefix_len= 0;
917 918
    part_end= keyinfo->key_part+table->actual_n_key_parts(keyinfo);
    for (part= keyinfo->key_part ;
unknown's avatar
unknown committed
919
         part != part_end ;
unknown's avatar
unknown committed
920
         part++, jdx++, key_part_to_use= (key_part_to_use << 1) | 1)
unknown's avatar
unknown committed
921
    {
922
      if (!(table->file->index_flags(idx, jdx, 0) & HA_READ_ORDER))
Michael Widenius's avatar
Michael Widenius committed
923
        DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
924

925 926 927 928
      /* Check whether the index component is partial */
      Field *part_field= table->field[part->fieldnr-1];
      if ((part_field->flags & BLOB_FLAG) ||
          part->length < part_field->key_length())
unknown's avatar
unknown committed
929 930
        break;

unknown's avatar
unknown committed
931 932 933 934
      if (field->eq(part->field))
      {
        ref->key= idx;
        ref->key_length= 0;
935
        ref->key_parts= 0;
unknown's avatar
unknown committed
936 937 938 939 940 941 942 943 944
        key_part_map key_part_used= 0;
        *range_fl= NO_MIN_RANGE | NO_MAX_RANGE;
        if (matching_cond(max_fl, ref, keyinfo, part, cond,
                          &key_part_used, range_fl, prefix_len) &&
            !(key_part_to_use & ~key_part_used))
        {
          if (!max_fl && key_part_used == key_part_to_use && part->null_bit)
          {
            /*
945 946 947 948 949 950 951 952 953 954 955 956
              The query is on this form:

              SELECT MIN(key_part_k) 
              FROM t1 
              WHERE key_part_1 = const and ... and key_part_k-1 = const

              If key_part_k is nullable, we want to find the first matching row
              where key_part_k is not null. The key buffer is now {const, ...,
              NULL}. This will be passed to the handler along with a flag
              indicating open interval. If a tuple is read that does not match
              these search criteria, an attempt will be made to read an exact
              match for the key buffer.
unknown's avatar
unknown committed
957
            */
958
            /* Set the first byte of key_part_k to 1, that means NULL */
959 960
            ref->key_buff[ref->key_length]= 1;
            ref->key_length+= part->store_length;
961 962
            ref->key_parts++;
            DBUG_ASSERT(ref->key_parts == jdx+1);
unknown's avatar
unknown committed
963
            *range_fl&= ~NO_MIN_RANGE;
964
            *range_fl|= NEAR_MIN; // Open interval
unknown's avatar
unknown committed
965 966 967 968 969
          }
          /*
            The following test is false when the key in the key tree is
            converted (for example to upper case)
          */
unknown's avatar
unknown committed
970
          if (field->part_of_key.is_set(idx))
971
            table->set_keyread(true);
Michael Widenius's avatar
Michael Widenius committed
972
          DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
973 974
        }
      }
unknown's avatar
unknown committed
975 976
    }
  }
Michael Widenius's avatar
Michael Widenius committed
977
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
978 979
}

unknown's avatar
unknown committed
980

unknown's avatar
unknown committed
981 982
/**
  Check whether found key is in range specified by conditions.
unknown's avatar
unknown committed
983

unknown's avatar
unknown committed
984 985 986 987 988 989
  @param[in] max_fl         0 for MIN(field) / 1 for MAX(field)
  @param[in] ref            Reference to the key value and info
  @param[in] field          Field used the MIN/MAX expression
  @param[in] cond           WHERE condition
  @param[in] range_fl       Says whether there is a condition to to be checked
  @param[in] prefix_len     Length of the constant part of the key
unknown's avatar
unknown committed
990

unknown's avatar
unknown committed
991
  @retval
unknown's avatar
unknown committed
992
    0        ok
unknown's avatar
unknown committed
993
  @retval
unknown's avatar
unknown committed
994 995 996 997 998 999
    1        WHERE was not true for the found row
*/

static int reckey_in_range(bool max_fl, TABLE_REF *ref, Field* field,
                            COND *cond, uint range_fl, uint prefix_len)
{
unknown's avatar
unknown committed
1000
  if (key_cmp_if_same(field->table, ref->key_buff, ref->key, prefix_len))
unknown's avatar
unknown committed
1001 1002
    return 1;
  if (!cond || (range_fl & (max_fl ? NO_MIN_RANGE : NO_MAX_RANGE)))
unknown's avatar
unknown committed
1003
    return 0;
unknown's avatar
unknown committed
1004 1005
  return maxmin_in_range(max_fl, field, cond);
}
unknown's avatar
unknown committed
1006

unknown's avatar
unknown committed
1007

unknown's avatar
unknown committed
1008 1009
/**
  Check whether {MAX|MIN}(field) is in range specified by conditions.
unknown's avatar
unknown committed
1010

unknown's avatar
unknown committed
1011 1012 1013 1014 1015
  @param[in] max_fl          0 for MIN(field) / 1 for MAX(field)
  @param[in] field           Field used the MIN/MAX expression
  @param[in] cond            WHERE condition

  @retval
unknown's avatar
unknown committed
1016
    0        ok
unknown's avatar
unknown committed
1017
  @retval
unknown's avatar
unknown committed
1018 1019 1020 1021 1022 1023 1024
    1        WHERE was not true for the found row
*/

static int maxmin_in_range(bool max_fl, Field* field, COND *cond)
{
  /* If AND/OR condition */
  if (cond->type() == Item::COND_ITEM)
unknown's avatar
unknown committed
1025
  {
unknown's avatar
unknown committed
1026 1027 1028
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
    Item *item;
    while ((item= li++))
unknown's avatar
unknown committed
1029
    {
unknown's avatar
unknown committed
1030 1031
      if (maxmin_in_range(max_fl, field, item))
        return 1;
unknown's avatar
unknown committed
1032
    }
unknown's avatar
unknown committed
1033
    return 0;
unknown's avatar
unknown committed
1034
  }
unknown's avatar
unknown committed
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047

  if (cond->used_tables() != field->table->map)
    return 0;
  bool less_fl= 0;
  switch (((Item_func*) cond)->functype()) {
  case Item_func::BETWEEN:
    return cond->val_int() == 0;                // Return 1 if WHERE is false
  case Item_func::LT_FUNC:
  case Item_func::LE_FUNC:
    less_fl= 1;
  case Item_func::GT_FUNC:
  case Item_func::GE_FUNC:
  {
unknown's avatar
unknown committed
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
    Item *item= ((Item_func*) cond)->arguments()[1];
    /* In case of 'const op item' we have to swap the operator */
    if (!item->const_item())
      less_fl= 1-less_fl;
    /*
      We only have to check the expression if we are using an expression like
      SELECT MAX(b) FROM t1 WHERE a=const AND b>const
      not for
      SELECT MAX(b) FROM t1 WHERE a=const AND b<const
    */
    if (max_fl != less_fl)
1059
      return cond->val_int() == 0;               // Return 1 if WHERE is false
unknown's avatar
unknown committed
1060 1061
    return 0;
  }
1062 1063
  default:
    break;                                      // Ignore
unknown's avatar
unknown committed
1064 1065
  }
  return 0;
unknown's avatar
unknown committed
1066
}
unknown's avatar
unknown committed
1067