Drizzled Public API Documentation

sum.cc
Go to the documentation of this file.
00001 /* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008-2009 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00054 #include <config.h>
00055 
00056 #include <drizzled/sql_select.h>
00057 #include <drizzled/item/sum.h>
00058 #include <drizzled/item/cmpfunc.h>
00059 #include <drizzled/optimizer/sum.h>
00060 #include <drizzled/plugin/storage_engine.h>
00061 #include <drizzled/table_list.h>
00062 #include <drizzled/key.h>
00063 #include <drizzled/error.h>
00064 
00065 namespace drizzled
00066 {
00067 
00068 static bool find_key_for_maxmin(bool max_fl,
00069                                 table_reference_st *ref,
00070                                 Field* field,
00071                                 COND *cond,
00072                                 uint32_t *range_fl,
00073                                 uint32_t *key_prefix_length);
00074 
00075 static int reckey_in_range(bool max_fl,
00076                            table_reference_st *ref,
00077                            Field* field,
00078                            COND *cond,
00079                            uint32_t range_fl,
00080                            uint32_t prefix_len);
00081 
00082 static int maxmin_in_range(bool max_fl, Field *field, COND *cond);
00083 
00084 
00085 /*
00086   Get exact count of rows in all tables
00087 
00088   SYNOPSIS
00089     get_exact_records()
00090     tables    List of tables
00091 
00092   NOTES
00093     When this is called, we know all table handlers supports HA_HAS_RECORDS
00094     or HA_STATS_RECORDS_IS_EXACT
00095 
00096   RETURN
00097     UINT64_MAX  Error: Could not calculate number of rows
00098     #     Multiplication of number of rows in all tables
00099 */
00100 static uint64_t get_exact_record_count(TableList *tables)
00101 {
00102   uint64_t count= 1;
00103   for (TableList *tl= tables; tl; tl= tl->next_leaf)
00104   {
00105     ha_rows tmp= tl->table->cursor->records();
00106     if ((tmp == HA_POS_ERROR))
00107     {
00108       return UINT64_MAX;
00109     }
00110     count*= tmp;
00111   }
00112   return count;
00113 }
00114 
00115 
00116 int optimizer::sum_query(TableList *tables, List<Item> &all_fields, COND *conds)
00117 {
00118   List<Item>::iterator it(all_fields.begin());
00119   int const_result= 1;
00120   bool recalc_const_item= false;
00121   uint64_t count= 1;
00122   bool is_exact_count= true;
00123   bool maybe_exact_count= true;
00124   table_map removed_tables= 0;
00125   table_map outer_tables= 0;
00126   table_map used_tables= 0;
00127   table_map where_tables= 0;
00128   Item *item= NULL;
00129   int error;
00130 
00131   if (conds)
00132   {
00133     where_tables= conds->used_tables();
00134   }
00135 
00136   /*
00137      Analyze outer join dependencies, and, if possible, compute the number
00138      of returned rows.
00139    */
00140   for (TableList *tl= tables; tl; tl= tl->next_leaf)
00141   {
00142     TableList *embedded= NULL;
00143     for (embedded= tl; embedded; embedded= embedded->getEmbedding())
00144     {
00145       if (embedded->on_expr)
00146         break;
00147     }
00148     if (embedded)
00149       /* Don't replace expression on a table that is part of an outer join */
00150     {
00151       outer_tables|= tl->table->map;
00152 
00153       /*
00154          We can't optimise LEFT JOIN in cases where the WHERE condition
00155          restricts the table that is used, like in:
00156          SELECT MAX(t1.a) FROM t1 LEFT JOIN t2 join-condition
00157          WHERE t2.field IS NULL;
00158        */
00159       if (tl->table->map & where_tables)
00160         return 0;
00161     }
00162     else
00163     {
00164       used_tables|= tl->table->map;
00165     }
00166 
00167     /*
00168        If the storage manager of 'tl' gives exact row count as part of
00169        statistics (cheap), compute the total number of rows. If there are
00170        no outer table dependencies, this count may be used as the real count.
00171        Schema tables are filled after this function is invoked, so we can't
00172        get row count
00173      */
00174     if (! (tl->table->cursor->getEngine()->check_flag(HTON_BIT_STATS_RECORDS_IS_EXACT)))
00175     {
00176       maybe_exact_count&= test(tl->table->cursor->getEngine()->check_flag(HTON_BIT_HAS_RECORDS));
00177       is_exact_count= false;
00178       count= 1; // ensure count != 0
00179     }
00180     else
00181     {
00182       error= tl->table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
00183       if(error)
00184       {
00185         tl->table->print_error(error, MYF(ME_FATALERROR));
00186         return error;
00187       }
00188       count*= tl->table->cursor->stats.records;
00189     }
00190   }
00191 
00192   /*
00193      Iterate through all items in the SELECT clause and replace
00194      COUNT(), MIN() and MAX() with constants (if possible).
00195    */
00196 
00197   while ((item= it++))
00198   {
00199     if (item->type() == Item::SUM_FUNC_ITEM)
00200     {
00201       Item_sum *item_sum= (((Item_sum*) item));
00202       switch (item_sum->sum_func())
00203       {
00204         case Item_sum::COUNT_FUNC:
00205           /*
00206              If the expr in COUNT(expr) can never be null we can change this
00207              to the number of rows in the tables if this number is exact and
00208              there are no outer joins.
00209            */
00210           if (! conds && ! ((Item_sum_count*) item)->args[0]->maybe_null &&
00211               ! outer_tables && maybe_exact_count)
00212           {
00213             if (! is_exact_count)
00214             {
00215               if ((count= get_exact_record_count(tables)) == UINT64_MAX)
00216               {
00217                 /* Error from handler in counting rows. Don't optimize count() */
00218                 const_result= 0;
00219                 continue;
00220               }
00221               is_exact_count= 1;                  // count is now exact
00222             }
00223             ((Item_sum_count*) item)->make_const_count((int64_t) count);
00224             recalc_const_item= 1;
00225           }
00226           else
00227           {
00228             const_result= 0;
00229           }
00230           break;
00231         case Item_sum::MIN_FUNC:
00232           {
00233             /*
00234                If MIN(expr) is the first part of a key or if all previous
00235                parts of the key is found in the COND, then we can use
00236                indexes to find the key.
00237              */
00238             Item *expr=item_sum->args[0];
00239             if (expr->real_item()->type() == Item::FIELD_ITEM)
00240             {
00241               unsigned char key_buff[MAX_KEY_LENGTH];
00242               table_reference_st ref;
00243               uint32_t range_fl, prefix_len;
00244 
00245               ref.key_buff= key_buff;
00246               Item_field *item_field= (Item_field*) (expr->real_item());
00247               Table *table= item_field->field->getTable();
00248 
00249               /*
00250                  Look for a partial key that can be used for optimization.
00251                  If we succeed, ref.key_length will contain the length of
00252                  this key, while prefix_len will contain the length of
00253                  the beginning of this key without field used in MIN().
00254                  Type of range for the key part for this field will be
00255                  returned in range_fl.
00256                */
00257               if (table->cursor->inited ||
00258                   (outer_tables & table->map) ||
00259                   ! find_key_for_maxmin(0,
00260                                         &ref,
00261                                         item_field->field,
00262                                         conds,
00263                                         &range_fl,
00264                                         &prefix_len))
00265               {
00266                 const_result= 0;
00267                 break;
00268               }
00269               error= table->cursor->startIndexScan(static_cast<uint32_t>(ref.key), 1);
00270               if (error)
00271               {
00272                 if (table->key_read)
00273                 {
00274                   table->key_read= 0;
00275                   table->cursor->extra(HA_EXTRA_NO_KEYREAD);
00276                 }
00277                 table->print_error(error, MYF(0));
00278                 return error;
00279               }
00280 
00281               if (! ref.key_length)
00282               {
00283                 error= table->cursor->index_first(table->record[0]);
00284               }
00285               else
00286               {
00287                 /*
00288                    Use index to replace MIN/MAX functions with their values
00289                    according to the following rules:
00290 
00291                    1) Insert the minimum non-null values where the WHERE clause still
00292                    matches, or
00293                    2) a NULL value if there are only NULL values for key_part_k.
00294                    3) Fail, producing a row of nulls
00295 
00296                    Implementation: Read the smallest value using the search key. If
00297                    the interval is open, read the next value after the search
00298                    key. If read fails, and we're looking for a MIN() value for a
00299                    nullable column, test if there is an exact match for the key.
00300                  */
00301                 if (! (range_fl & NEAR_MIN))
00302                 {
00303                   /*
00304                      Closed interval: Either The MIN argument is non-nullable, or
00305                      we have a >= predicate for the MIN argument.
00306                    */
00307                   error= table->cursor->index_read_map(table->record[0],
00308                                                        ref.key_buff,
00309                                                        make_prev_keypart_map(ref.key_parts),
00310                                                        HA_READ_KEY_OR_NEXT);
00311                 }
00312                 else
00313                 {
00314                   /*
00315                      Open interval: There are two cases:
00316                      1) We have only MIN() and the argument column is nullable, or
00317                      2) there is a > predicate on it, nullability is irrelevant.
00318                      We need to scan the next bigger record first.
00319                    */
00320                   error= table->cursor->index_read_map(table->record[0],
00321                                                        ref.key_buff,
00322                                                        make_prev_keypart_map(ref.key_parts),
00323                                                        HA_READ_AFTER_KEY);
00324                   /*
00325                      If the found record is outside the group formed by the search
00326                      prefix, or there is no such record at all, check if all
00327                      records in that group have NULL in the MIN argument
00328                      column. If that is the case return that NULL.
00329 
00330                      Check if case 1 from above holds. If it does, we should read
00331                      the skipped tuple.
00332                    */
00333                   if (item_field->field->real_maybe_null() &&
00334                       ref.key_buff[prefix_len] == 1 &&
00335                       /*
00336                          Last keypart (i.e. the argument to MIN) is set to NULL by
00337                          find_key_for_maxmin only if all other keyparts are bound
00338                          to constants in a conjunction of equalities. Hence, we
00339                          can detect this by checking only if the last keypart is
00340                          NULL.
00341                        */
00342                       (error == HA_ERR_KEY_NOT_FOUND ||
00343                        key_cmp_if_same(table, ref.key_buff, ref.key, prefix_len)))
00344                   {
00345                     assert(item_field->field->real_maybe_null());
00346                     error= table->cursor->index_read_map(table->record[0],
00347                                                          ref.key_buff,
00348                                                          make_prev_keypart_map(ref.key_parts),
00349                                                          HA_READ_KEY_EXACT);
00350                   }
00351                 }
00352               }
00353               /* Verify that the read tuple indeed matches the search key */
00354               if (! error &&
00355                   reckey_in_range(0,
00356                                   &ref,
00357                                   item_field->field,
00358                                   conds,
00359                                   range_fl,
00360                                   prefix_len))
00361               {
00362                 error= HA_ERR_KEY_NOT_FOUND;
00363               }
00364               if (table->key_read)
00365               {
00366                 table->key_read= 0;
00367                 table->cursor->extra(HA_EXTRA_NO_KEYREAD);
00368               }
00369               table->cursor->endIndexScan();
00370               if (error)
00371               {
00372                 if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
00373                 {
00374                   return HA_ERR_KEY_NOT_FOUND;        // No rows matching WHERE
00375                 }
00376                 /* HA_ERR_LOCK_DEADLOCK or some other error */
00377                 table->print_error(error, MYF(0));
00378                 return error;
00379               }
00380               removed_tables|= table->map;
00381             }
00382             else if (! expr->const_item() || ! is_exact_count)
00383             {
00384               /*
00385                  The optimization is not applicable in both cases:
00386                  (a) 'expr' is a non-constant expression. Then we can't
00387                  replace 'expr' by a constant.
00388                  (b) 'expr' is a costant. According to ANSI, MIN/MAX must return
00389                  NULL if the query does not return any rows. Thus, if we are not
00390                  able to determine if the query returns any rows, we can't apply
00391                  the optimization and replace MIN/MAX with a constant.
00392                */
00393               const_result= 0;
00394               break;
00395             }
00396             if (! count)
00397             {
00398               /* If count == 0, then we know that is_exact_count == true. */
00399               ((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */
00400             }
00401             else
00402             {
00403               ((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */
00404             }
00405             ((Item_sum_min*) item_sum)->make_const();
00406             recalc_const_item= 1;
00407             break;
00408           }
00409         case Item_sum::MAX_FUNC:
00410           {
00411             /*
00412                If MAX(expr) is the first part of a key or if all previous
00413                parts of the key is found in the COND, then we can use
00414                indexes to find the key.
00415              */
00416             Item *expr= item_sum->args[0];
00417             if (expr->real_item()->type() == Item::FIELD_ITEM)
00418             {
00419               unsigned char key_buff[MAX_KEY_LENGTH];
00420               table_reference_st ref;
00421               uint32_t range_fl, prefix_len;
00422 
00423               ref.key_buff= key_buff;
00424               Item_field *item_field= (Item_field*) (expr->real_item());
00425               Table *table= item_field->field->getTable();
00426 
00427               /*
00428                  Look for a partial key that can be used for optimization.
00429                  If we succeed, ref.key_length will contain the length of
00430                  this key, while prefix_len will contain the length of
00431                  the beginning of this key without field used in MAX().
00432                  Type of range for the key part for this field will be
00433                  returned in range_fl.
00434                */
00435               if (table->cursor->inited ||
00436                   (outer_tables & table->map) ||
00437                   ! find_key_for_maxmin(1,
00438                                         &ref,
00439                                         item_field->field,
00440                                         conds,
00441                                         &range_fl,
00442                                         &prefix_len))
00443               {
00444                 const_result= 0;
00445                 break;
00446               }
00447               error= table->cursor->startIndexScan(static_cast<uint32_t>(ref.key), 1);
00448 
00449               if (! ref.key_length)
00450               {
00451                 error= table->cursor->index_last(table->record[0]);
00452               }
00453               else
00454               {
00455                 error= table->cursor->index_read_map(table->record[0],
00456                                                      key_buff,
00457                                                      make_prev_keypart_map(ref.key_parts),
00458                                                      range_fl & NEAR_MAX ?
00459                                                      HA_READ_BEFORE_KEY :
00460                                                      HA_READ_PREFIX_LAST_OR_PREV);
00461               }
00462               if (! error &&
00463                   reckey_in_range(1,
00464                                   &ref,
00465                                   item_field->field,
00466                                   conds,
00467                                   range_fl,
00468                                   prefix_len))
00469               {
00470                 error= HA_ERR_KEY_NOT_FOUND;
00471               }
00472               if (table->key_read)
00473               {
00474                 table->key_read= 0;
00475                 table->cursor->extra(HA_EXTRA_NO_KEYREAD);
00476               }
00477               table->cursor->endIndexScan();
00478               if (error)
00479               {
00480                 if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
00481                 {
00482                   return HA_ERR_KEY_NOT_FOUND;       // No rows matching WHERE
00483                 }
00484                 /* HA_ERR_LOCK_DEADLOCK or some other error */
00485                 table->print_error(error, MYF(ME_FATALERROR));
00486                 return error;
00487               }
00488               removed_tables|= table->map;
00489             }
00490             else if (! expr->const_item() || ! is_exact_count)
00491             {
00492               /*
00493                  The optimization is not applicable in both cases:
00494                  (a) 'expr' is a non-constant expression. Then we can't
00495                  replace 'expr' by a constant.
00496                  (b) 'expr' is a costant. According to ANSI, MIN/MAX must return
00497                  NULL if the query does not return any rows. Thus, if we are not
00498                  able to determine if the query returns any rows, we can't apply
00499                  the optimization and replace MIN/MAX with a constant.
00500                */
00501               const_result= 0;
00502               break;
00503             }
00504             if (! count)
00505             {
00506               /* If count != 1, then we know that is_exact_count == true. */
00507               ((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */
00508             }
00509             else
00510             {
00511               ((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */
00512             }
00513             ((Item_sum_max*) item_sum)->make_const();
00514             recalc_const_item= 1;
00515             break;
00516           }
00517         default:
00518           const_result= 0;
00519           break;
00520       }
00521     }
00522     else if (const_result)
00523     {
00524       if (recalc_const_item)
00525       {
00526         item->update_used_tables();
00527       }
00528       if (! item->const_item())
00529       {
00530         const_result= 0;
00531       }
00532     }
00533   }
00534   /*
00535      If we have a where clause, we can only ignore searching in the
00536      tables if MIN/MAX optimisation replaced all used tables
00537      We do not use replaced values in case of:
00538      SELECT MIN(key) FROM table_1, empty_table
00539      removed_tables is != 0 if we have used MIN() or MAX().
00540    */
00541   if (removed_tables && used_tables != removed_tables)
00542   {
00543     const_result= 0;                            // We didn't remove all tables
00544   }
00545   return const_result;
00546 }
00547 
00548 
00549 bool optimizer::simple_pred(Item_func *func_item, Item **args, bool &inv_order)
00550 {
00551   Item *item= NULL;
00552   inv_order= false;
00553   switch (func_item->argument_count())
00554   {
00555   case 0:
00556     /* MULT_EQUAL_FUNC */
00557     {
00558       Item_equal *item_equal= (Item_equal *) func_item;
00559       Item_equal_iterator it(item_equal->begin());
00560       args[0]= it++;
00561       if (it++)
00562       {
00563         return 0;
00564       }
00565       if (! (args[1]= item_equal->get_const()))
00566       {
00567         return 0;
00568       }
00569     }
00570     break;
00571   case 1:
00572     /* field IS NULL */
00573     item= func_item->arguments()[0];
00574     if (item->type() != Item::FIELD_ITEM)
00575     {
00576       return 0;
00577     }
00578     args[0]= item;
00579     break;
00580   case 2:
00581     /* 'field op const' or 'const op field' */
00582     item= func_item->arguments()[0];
00583     if (item->type() == Item::FIELD_ITEM)
00584     {
00585       args[0]= item;
00586       item= func_item->arguments()[1];
00587       if (! item->const_item())
00588       {
00589         return 0;
00590       }
00591       args[1]= item;
00592     }
00593     else if (item->const_item())
00594     {
00595       args[1]= item;
00596       item= func_item->arguments()[1];
00597       if (item->type() != Item::FIELD_ITEM)
00598       {
00599         return 0;
00600       }
00601       args[0]= item;
00602       inv_order= true;
00603     }
00604     else
00605     {
00606       return 0;
00607     }
00608     break;
00609   case 3:
00610     /* field BETWEEN const AND const */
00611     item= func_item->arguments()[0];
00612     if (item->type() == Item::FIELD_ITEM)
00613     {
00614       args[0]= item;
00615       for (int i= 1 ; i <= 2; i++)
00616       {
00617         item= func_item->arguments()[i];
00618         if (! item->const_item())
00619         {
00620           return 0;
00621         }
00622         args[i]= item;
00623       }
00624     }
00625     else
00626     {
00627       return 0;
00628     }
00629   }
00630   return 1;
00631 }
00632 
00633 
00663 static bool matching_cond(bool max_fl,
00664                           table_reference_st *ref,
00665                           KeyInfo *keyinfo,
00666                           KeyPartInfo *field_part,
00667                           COND *cond,
00668                           key_part_map *key_part_used,
00669                           uint32_t *range_fl,
00670                           uint32_t *prefix_len)
00671 {
00672   if (! cond)
00673   {
00674     return 1;
00675   }
00676   Field *field= field_part->field;
00677 
00678   field->setWriteSet();
00679 
00680   if (! (cond->used_tables() & field->getTable()->map))
00681   {
00682     /* Condition doesn't restrict the used table */
00683     return 1;
00684   }
00685   if (cond->type() == Item::COND_ITEM)
00686   {
00687     if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
00688     {
00689       return 0;
00690     }
00691 
00692     /* AND */
00693     List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
00694     Item *item;
00695     while ((item= li++))
00696     {
00697       if (! matching_cond(max_fl,
00698                           ref,
00699                           keyinfo,
00700                           field_part,
00701                           item,
00702                           key_part_used,
00703                           range_fl,
00704                           prefix_len))
00705       {
00706         return 0;
00707       }
00708     }
00709     return 1;
00710   }
00711 
00712   if (cond->type() != Item::FUNC_ITEM)
00713   {
00714     return 0; // Not operator, can't optimize
00715   }
00716 
00717   bool eq_type= false; // =, <=> or IS NULL
00718   bool noeq_type= false; // < or >
00719   bool less_fl= false; // < or <=
00720   bool is_null= false;
00721   bool between= false;
00722 
00723   switch (((Item_func*) cond)->functype())
00724   {
00725   case Item_func::ISNULL_FUNC:
00726     is_null= 1;     /* fall through */
00727   case Item_func::EQ_FUNC:
00728   case Item_func::EQUAL_FUNC:
00729     eq_type= 1;
00730     break;
00731   case Item_func::LT_FUNC:
00732     noeq_type= 1;   /* fall through */
00733   case Item_func::LE_FUNC:
00734     less_fl= 1;
00735     break;
00736   case Item_func::GT_FUNC:
00737     noeq_type= 1;   /* fall through */
00738   case Item_func::GE_FUNC:
00739     break;
00740   case Item_func::BETWEEN:
00741     between= 1;
00742     break;
00743   case Item_func::MULT_EQUAL_FUNC:
00744     eq_type= 1;
00745     break;
00746   default:
00747     return 0; // Can't optimize function
00748   }
00749 
00750   Item *args[3];
00751   bool inv;
00752 
00753   /* Test if this is a comparison of a field and constant */
00754   if (! optimizer::simple_pred((Item_func*) cond, args, inv))
00755   {
00756     return 0;
00757   }
00758 
00759   if (inv && ! eq_type)
00760   {
00761     less_fl= 1 - less_fl; // Convert '<' -> '>' (etc)
00762   }
00763 
00764   /* Check if field is part of the tested partial key */
00765   unsigned char *key_ptr= ref->key_buff;
00766   KeyPartInfo *part= NULL;
00767   for (part= keyinfo->key_part; ; key_ptr+= part++->store_length)
00768 
00769   {
00770     if (part > field_part)
00771     {
00772       return 0;                     // Field is beyond the tested parts
00773     }
00774     if (part->field->eq(((Item_field*) args[0])->field))
00775     {
00776       break;                        // Found a part of the key for the field
00777     }
00778   }
00779 
00780   bool is_field_part= part == field_part;
00781   if (! (is_field_part || eq_type))
00782   {
00783     return 0;
00784   }
00785 
00786   key_part_map org_key_part_used= *key_part_used;
00787   if (eq_type || between || max_fl == less_fl)
00788   {
00789     uint32_t length= (key_ptr-ref->key_buff)+part->store_length;
00790     if (ref->key_length < length)
00791     {
00792     /* Ultimately ref->key_length will contain the length of the search key */
00793       ref->key_length= length;
00794       ref->key_parts= (part - keyinfo->key_part) + 1;
00795     }
00796     if (! *prefix_len && part + 1 == field_part)
00797     {
00798       *prefix_len= length;
00799     }
00800     if (is_field_part && eq_type)
00801     {
00802       *prefix_len= ref->key_length;
00803     }
00804 
00805     *key_part_used|= (key_part_map) 1 << (part - keyinfo->key_part);
00806   }
00807 
00808   if (org_key_part_used != *key_part_used ||
00809       (is_field_part &&
00810        (between || eq_type || max_fl == less_fl) && ! cond->val_int()))
00811   {
00812     /*
00813       It's the first predicate for this part or a predicate of the
00814       following form  that moves upper/lower bounds for max/min values:
00815       - field BETWEEN const AND const
00816       - field = const
00817       - field {<|<=} const, when searching for MAX
00818       - field {>|>=} const, when searching for MIN
00819     */
00820 
00821     if (is_null)
00822     {
00823       part->field->set_null();
00824       *key_ptr= (unsigned char) 1;
00825     }
00826     else
00827     {
00828       store_val_in_field(part->field, args[between && max_fl ? 2 : 1],
00829                          CHECK_FIELD_IGNORE);
00830       if (part->null_bit)
00831       {
00832         *key_ptr++= (unsigned char) test(part->field->is_null());
00833       }
00834       part->field->get_key_image(key_ptr, part->length);
00835     }
00836     if (is_field_part)
00837     {
00838       if (between || eq_type)
00839       {
00840         *range_fl&= ~(NO_MAX_RANGE | NO_MIN_RANGE);
00841       }
00842       else
00843       {
00844         *range_fl&= ~(max_fl ? NO_MAX_RANGE : NO_MIN_RANGE);
00845         if (noeq_type)
00846         {
00847           *range_fl|=  (max_fl ? NEAR_MAX : NEAR_MIN);
00848         }
00849         else
00850         {
00851           *range_fl&= ~(max_fl ? NEAR_MAX : NEAR_MIN);
00852         }
00853       }
00854     }
00855   }
00856   else if (eq_type)
00857   {
00858     if ((! is_null && !cond->val_int()) ||
00859         (is_null && !test(part->field->is_null())))
00860     {
00861      return 0;                       // Impossible test
00862     }
00863   }
00864   else if (is_field_part)
00865   {
00866     *range_fl&= ~(max_fl ? NO_MIN_RANGE : NO_MAX_RANGE);
00867   }
00868   return 1;
00869 }
00870 
00871 
00913 static bool find_key_for_maxmin(bool max_fl,
00914                                 table_reference_st *ref,
00915                                 Field* field,
00916                                 COND *cond,
00917                                 uint32_t *range_fl,
00918                                 uint32_t *prefix_len)
00919 {
00920   if (! (field->flags & PART_KEY_FLAG))
00921   {
00922     return 0; // Not key field
00923   }
00924 
00925   Table *table= field->getTable();
00926   uint32_t idx= 0;
00927 
00928   KeyInfo *keyinfo,*keyinfo_end= NULL;
00929   for (keyinfo= table->key_info, keyinfo_end= keyinfo+table->getShare()->sizeKeys();
00930        keyinfo != keyinfo_end;
00931        keyinfo++,idx++)
00932   {
00933     KeyPartInfo *part= NULL;
00934     KeyPartInfo *part_end= NULL;
00935     key_part_map key_part_to_use= 0;
00936     /*
00937       Perform a check if index is not disabled by ALTER Table
00938       or IGNORE INDEX.
00939     */
00940     if (! table->keys_in_use_for_query.test(idx))
00941     {
00942       continue;
00943     }
00944     uint32_t jdx= 0;
00945     *prefix_len= 0;
00946     for (part= keyinfo->key_part, part_end= part+keyinfo->key_parts;
00947          part != part_end;
00948          part++, jdx++, key_part_to_use= (key_part_to_use << 1) | 1)
00949     {
00950       if (! (table->index_flags(idx) & HA_READ_ORDER))
00951       {
00952         return 0;
00953       }
00954 
00955       /* Check whether the index component is partial */
00956       Field *part_field= table->getField(part->fieldnr-1);
00957       part_field->setWriteSet();
00958 
00959       if ((part_field->flags & BLOB_FLAG) ||
00960           part->length < part_field->key_length())
00961       {
00962         break;
00963       }
00964 
00965       if (field->eq(part->field))
00966       {
00967         ref->key= idx;
00968         ref->key_length= 0;
00969         ref->key_parts= 0;
00970         key_part_map key_part_used= 0;
00971         *range_fl= NO_MIN_RANGE | NO_MAX_RANGE;
00972         if (matching_cond(max_fl,
00973                           ref,
00974                           keyinfo,
00975                           part,
00976                           cond,
00977                           &key_part_used,
00978                           range_fl,
00979                           prefix_len) &&
00980             ! (key_part_to_use & ~key_part_used))
00981         {
00982           if (! max_fl && key_part_used == key_part_to_use && part->null_bit)
00983           {
00984             /*
00985               The query is on this form:
00986 
00987               SELECT MIN(key_part_k)
00988               FROM t1
00989               WHERE key_part_1 = const and ... and key_part_k-1 = const
00990 
00991               If key_part_k is nullable, we want to find the first matching row
00992               where key_part_k is not null. The key buffer is now {const, ...,
00993               NULL}. This will be passed to the handler along with a flag
00994               indicating open interval. If a tuple is read that does not match
00995               these search criteria, an attempt will be made to read an exact
00996               match for the key buffer.
00997             */
00998             /* Set the first byte of key_part_k to 1, that means NULL */
00999             ref->key_buff[ref->key_length]= 1;
01000             ref->key_length+= part->store_length;
01001             ref->key_parts++;
01002             assert(ref->key_parts == jdx+1);
01003             *range_fl&= ~NO_MIN_RANGE;
01004             *range_fl|= NEAR_MIN; // Open interval
01005           }
01006           /*
01007             The following test is false when the key in the key tree is
01008             converted (for example to upper case)
01009           */
01010           if (field->part_of_key.test(idx))
01011           {
01012             table->key_read= 1;
01013             table->cursor->extra(HA_EXTRA_KEYREAD);
01014           }
01015           return 1;
01016         }
01017       }
01018     }
01019   }
01020   return 0;
01021 }
01022 
01023 
01039 static int reckey_in_range(bool max_fl,
01040                            table_reference_st *ref,
01041                            Field* field,
01042                            COND *cond,
01043                            uint32_t range_fl,
01044                            uint32_t prefix_len)
01045 {
01046   if (key_cmp_if_same(field->getTable(), ref->key_buff, ref->key, prefix_len))
01047   {
01048     return 1;
01049   }
01050   if (! cond || (range_fl & (max_fl ? NO_MIN_RANGE : NO_MAX_RANGE)))
01051   {
01052     return 0;
01053   }
01054   return maxmin_in_range(max_fl, field, cond);
01055 }
01056 
01057 
01070 static int maxmin_in_range(bool max_fl, Field* field, COND *cond)
01071 {
01072   /* If AND/OR condition */
01073   if (cond->type() == Item::COND_ITEM)
01074   {
01075     List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
01076     while (Item* item= li++)
01077     {
01078       if (maxmin_in_range(max_fl, field, item))
01079         return 1;
01080     }
01081     return 0;
01082   }
01083 
01084   if (cond->used_tables() != field->getTable()->map)
01085   {
01086     return 0;
01087   }
01088   bool less_fl= false;
01089   switch (((Item_func*) cond)->functype())
01090   {
01091   case Item_func::BETWEEN:
01092     return cond->val_int() == 0;                // Return 1 if WHERE is false
01093   case Item_func::LT_FUNC:
01094   case Item_func::LE_FUNC:
01095     less_fl= 1;
01096   case Item_func::GT_FUNC:
01097   case Item_func::GE_FUNC:
01098   {
01099     Item *item= ((Item_func*) cond)->arguments()[1];
01100     /* In case of 'const op item' we have to swap the operator */
01101     if (! item->const_item())
01102     {
01103       less_fl= 1-less_fl;
01104     }
01105     /*
01106       We only have to check the expression if we are using an expression like
01107       SELECT MAX(b) FROM t1 WHERE a=const AND b>const
01108       not for
01109       SELECT MAX(b) FROM t1 WHERE a=const AND b<const
01110     */
01111     if (max_fl != less_fl)
01112     {
01113       return cond->val_int() == 0;                // Return 1 if WHERE is false
01114     }
01115     return 0;
01116   }
01117   case Item_func::EQ_FUNC:
01118   case Item_func::EQUAL_FUNC:
01119     break;
01120   default:
01121     ; // assert(false); // Impossible; Olaf: Not really, assert is hit. BUG?
01122   }
01123   return 0;
01124 }
01125 
01126 } /* namespace drizzled */
01127