opt_sum.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:10k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. /* Optimizing of many different type of queries with GROUP functions */
  17. #include "mysql_priv.h"
  18. #include "sql_select.h"
  19. static bool find_range_key(TABLE_REF *ref, Field* field,COND *cond);
  20. /*****************************************************************************
  21. ** This function is only called for queries with sum functions and no
  22. ** GROUP BY part.
  23. ** This substitutes constants for some COUNT(), MIN() and MAX() functions.
  24. ** The function returns 1 if all items was resolved and -1 on impossible
  25. ** conditions
  26. ****************************************************************************/
  27. int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
  28. {
  29.   List_iterator<Item> it(all_fields);
  30.   int const_result=1;
  31.   bool recalc_const_item=0;
  32.   table_map removed_tables=0;
  33.   Item *item;
  34.   while ((item= it++))
  35.   {
  36.     if (item->type() == Item::SUM_FUNC_ITEM)
  37.     {
  38.       Item_sum *item_sum= (((Item_sum*) item));
  39.       switch (item_sum->sum_func()) {
  40.       case Item_sum::COUNT_FUNC:
  41. /*
  42.   If the expr in count(expr) can never be null we can change this
  43.   to the number of rows in the tables
  44. */
  45. if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null)
  46. {
  47.   longlong count=1;
  48.   TABLE_LIST *table;
  49.   for (table=tables; table ; table=table->next)
  50.   {
  51.     if (table->on_expr || (table->table->file->option_flag() &
  52.    HA_NOT_EXACT_COUNT))
  53.     {
  54.       const_result=0; // Can't optimize left join
  55.       break;
  56.     }
  57.     tables->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
  58.     count*= table->table->file->records;
  59.   }
  60.   if (!table)
  61.   {
  62.     ((Item_sum_count*) item)->make_const(count);
  63.     recalc_const_item=1;
  64.   }
  65. }
  66. else
  67.   const_result=0;
  68. break;
  69.       case Item_sum::MIN_FUNC:
  70.       {
  71. /*
  72.   If MIN(expr) is the first part of a key or if all previous
  73.   parts of the key is found in the COND, then we can use
  74.   indexes to find the key.
  75. */
  76. Item *expr=item_sum->args[0];
  77. if (expr->type() == Item::FIELD_ITEM)
  78. {
  79.   byte key_buff[MAX_KEY_LENGTH];
  80.   TABLE_REF ref;
  81.   ref.key_buff=key_buff;
  82.   if (!find_range_key(&ref, ((Item_field*) expr)->field,conds))
  83.   {
  84.     const_result=0;
  85.     break;
  86.   }
  87.   TABLE *table=((Item_field*) expr)->field->table;
  88.   bool error=table->file->index_init((uint) ref.key);
  89.   if (!ref.key_length)
  90.     error=table->file->index_first(table->record[0]) !=0;
  91.   else
  92.     error=table->file->index_read(table->record[0],key_buff,
  93.   ref.key_length,
  94.   HA_READ_KEY_OR_NEXT) ||
  95.       key_cmp(table, key_buff, ref.key, ref.key_length);
  96.   if (table->key_read)
  97.   {
  98.     table->key_read=0;
  99.     table->file->extra(HA_EXTRA_NO_KEYREAD);
  100.   }
  101.   table->file->index_end();
  102.   if (error)
  103.     return -1; // Impossible query
  104.   removed_tables|= table->map;
  105. }
  106. else if (!expr->const_item()) // This is VERY seldom false
  107. {
  108.   const_result=0;
  109.   break;
  110. }
  111. ((Item_sum_min*) item_sum)->reset();
  112. ((Item_sum_min*) item_sum)->make_const();
  113. recalc_const_item=1;
  114. break;
  115.       }
  116.       case Item_sum::MAX_FUNC:
  117.       {
  118. /*
  119.   If MAX(expr) is the first part of a key or if all previous
  120.   parts of the key is found in the COND, then we can use
  121.   indexes to find the key.
  122. */
  123. Item *expr=item_sum->args[0];
  124. if (expr->type() == Item::FIELD_ITEM)
  125. {
  126.   byte key_buff[MAX_KEY_LENGTH];
  127.   TABLE_REF ref;
  128.   ref.key_buff=key_buff;
  129.   if (!find_range_key(&ref, ((Item_field*) expr)->field,conds))
  130.   {
  131.     const_result=0;
  132.     break;
  133.   }
  134.   TABLE *table=((Item_field*) expr)->field->table;
  135.   if ((table->file->option_flag() & HA_NOT_READ_AFTER_KEY))
  136.   {
  137.     const_result=0;
  138.     break;
  139.   }
  140.   bool error=table->file->index_init((uint) ref.key);
  141.   if (!ref.key_length)
  142.     error=table->file->index_last(table->record[0]) !=0;
  143.   else
  144.   {
  145.     (void) table->file->index_read(table->record[0], key_buff,
  146.    ref.key_length,
  147.    HA_READ_AFTER_KEY);
  148.     error=table->file->index_prev(table->record[0]) ||
  149.       key_cmp(table,key_buff,ref.key,ref.key_length);
  150.   }
  151.   if (table->key_read)
  152.   {
  153.     table->key_read=0;
  154.     table->file->extra(HA_EXTRA_NO_KEYREAD);
  155.   }
  156.   table->file->index_end();
  157.   if (error)
  158.     return -1; // Impossible query
  159.   removed_tables|= table->map;
  160. }
  161. else if (!expr->const_item()) // This is VERY seldom false
  162. {
  163.   const_result=0;
  164.   break;
  165. }
  166. ((Item_sum_min*) item_sum)->reset();
  167. ((Item_sum_min*) item_sum)->make_const();
  168. recalc_const_item=1;
  169. break;
  170.       }
  171.       default:
  172. const_result=0;
  173. break;
  174.       }
  175.     }
  176.     else if (const_result)
  177.     {
  178.       if (recalc_const_item)
  179. item->update_used_tables();
  180.       if (!item->const_item())
  181. const_result=0;
  182.     }
  183.   }
  184.   if (conds && (conds->used_tables() & ~ removed_tables))
  185.     const_result=0;
  186.   return const_result;
  187. }
  188. /* Count in how many times table is used (up to MAX_KEY_PARTS+1) */
  189. uint count_table_entries(COND *cond,TABLE *table)
  190. {
  191.   if (cond->type() == Item::COND_ITEM)
  192.   {
  193.     if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
  194.       return (cond->used_tables() & table->map) ? MAX_REF_PARTS+1 : 0;
  195.     List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
  196.     Item *item;
  197.     uint count=0;
  198.     while ((item=li++))
  199.     {
  200.       if ((count+=count_table_entries(item,table)) > MAX_REF_PARTS)
  201. return MAX_REF_PARTS+1;
  202.     }
  203.     return count;
  204.   }
  205.   if (cond->type() == Item::FUNC_ITEM &&
  206.       (((Item_func*) cond)->functype() == Item_func::EQ_FUNC ||
  207.        (((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC)) &&
  208.       cond->used_tables() == table->map)
  209.   {
  210.     Item *left_item= ((Item_func*) cond)->arguments()[0];
  211.     Item *right_item= ((Item_func*) cond)->arguments()[1];
  212.     if (left_item->type() == Item::FIELD_ITEM)
  213.     {
  214.       if (!(((Item_field*) left_item)->field->flags & PART_KEY_FLAG) ||
  215.   !right_item->const_item())
  216. return MAX_REF_PARTS+1;
  217.       return 1;
  218.     }
  219.     if (right_item->type() == Item::FIELD_ITEM)
  220.     {
  221.       if (!(((Item_field*) right_item)->field->flags & PART_KEY_FLAG) ||
  222.   !left_item->const_item())
  223. return MAX_REF_PARTS+1;
  224.       return 1;
  225.     }
  226.   }
  227.   return (cond->used_tables() & table->map) ? MAX_REF_PARTS+1 : 0;
  228. }
  229. /* check that the field is usable as key part */
  230. bool part_of_cond(COND *cond,Field *field)
  231. {
  232.   if (cond->type() == Item::COND_ITEM)
  233.   {
  234.     if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
  235.       return 0; // Already checked
  236.     List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
  237.     Item *item;
  238.     while ((item=li++))
  239.     {
  240.       if (part_of_cond(item,field))
  241. return 1;
  242.     }
  243.     return 0;
  244.   }
  245.   if (cond->type() == Item::FUNC_ITEM &&
  246.       (((Item_func*) cond)->functype() == Item_func::EQ_FUNC ||
  247.        ((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC) &&
  248.       cond->used_tables() == field->table->map)
  249.   {
  250.     Item *left_item= ((Item_func*) cond)->arguments()[0];
  251.     Item *right_item= ((Item_func*) cond)->arguments()[1];
  252.     if (left_item->type() == Item::FIELD_ITEM)
  253.     {
  254.       if (((Item_field*) left_item)->field != field ||
  255.   !right_item->const_item())
  256. return 0;
  257.     }
  258.     else if (right_item->type() == Item::FIELD_ITEM)
  259.     {
  260.       if (((Item_field*) right_item)->field != field ||
  261.   !left_item->const_item())
  262. return 0;
  263.       right_item=left_item; // const item in right
  264.     }
  265.     store_val_in_field(field,right_item);
  266.     return 1;
  267.   }
  268.   return 0;
  269. }
  270. /* Check if we can get value for field by using a key */
  271. static bool find_range_key(TABLE_REF *ref, Field* field, COND *cond)
  272. {
  273.   if (!(field->flags & PART_KEY_FLAG))
  274.     return 0; // Not part of a key. Skipp it
  275.   TABLE *table=field->table;
  276.   if (table->file->option_flag() & HA_WRONG_ASCII_ORDER)
  277.     return(0); // Can't use key to find last row
  278.   uint idx=0;
  279.   /* Check if some key has field as first key part */
  280.   if (field->key_start && (! cond || ! (cond->used_tables() & table->map)))
  281.   {
  282.     for (key_map key=field->key_start ; !(key & 1) ; idx++)
  283.       key>>=1;
  284.     ref->key_length=0;
  285.     ref->key=idx;
  286.     if (field->part_of_key & ((table_map) 1 << idx))
  287.     {
  288.       table->key_read=1;
  289.       table->file->extra(HA_EXTRA_KEYREAD);
  290.     }
  291.     return 1; // Ok to use key
  292.   }
  293.   /*
  294.   ** Check if WHERE consist of exactly the previous key parts for some key
  295.   */
  296.   if (!cond)
  297.     return 0;
  298.   uint table_entries= count_table_entries(cond,table);
  299.   if (!table_entries || table_entries > MAX_REF_PARTS)
  300.     return 0;
  301.   KEY *keyinfo,*keyinfo_end;
  302.   for (keyinfo=table->key_info, keyinfo_end=keyinfo+table->keys ;
  303.        keyinfo != keyinfo_end;
  304.        keyinfo++,idx++)
  305.   {
  306.     if (table_entries < keyinfo->key_parts)
  307.     {
  308.       byte *key_ptr=ref->key_buff;
  309.       KEY_PART_INFO *part,*part_end;
  310.       int left_length=MAX_KEY_LENGTH;
  311.       for (part=keyinfo->key_part, part_end=part+table_entries ;
  312.    part != part_end ;
  313.    part++)
  314.       {
  315. if (!part_of_cond(cond,part->field) ||
  316.     left_length < part->store_length)
  317.   break;
  318. // Save found constant
  319. if (part->null_bit)
  320.   *key_ptr++= (byte) test(part->field->is_null());
  321. part->field->get_key_image((char*) key_ptr,part->length);
  322. key_ptr+=part->store_length - test(part->null_bit);
  323. left_length-=part->store_length;
  324.       }
  325.       if (part == part_end && part->field == field)
  326.       {
  327. ref->key_length= (uint) (key_ptr-ref->key_buff);
  328. ref->key=idx;
  329. if (field->part_of_key & ((table_map) 1 << idx))
  330. {
  331.   table->key_read=1;
  332.   table->file->extra(HA_EXTRA_KEYREAD);
  333. }
  334. return 1; // Ok to use key
  335.       }
  336.     }
  337.   }
  338.   return 0; // No possible key
  339. }