00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
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
00138
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
00150 {
00151 outer_tables|= tl->table->map;
00152
00153
00154
00155
00156
00157
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
00169
00170
00171
00172
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;
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
00194
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
00207
00208
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
00218 const_result= 0;
00219 continue;
00220 }
00221 is_exact_count= 1;
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
00235
00236
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
00251
00252
00253
00254
00255
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
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 if (! (range_fl & NEAR_MIN))
00302 {
00303
00304
00305
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
00316
00317
00318
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
00326
00327
00328
00329
00330
00331
00332
00333 if (item_field->field->real_maybe_null() &&
00334 ref.key_buff[prefix_len] == 1 &&
00335
00336
00337
00338
00339
00340
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
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;
00375 }
00376
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
00386
00387
00388
00389
00390
00391
00392
00393 const_result= 0;
00394 break;
00395 }
00396 if (! count)
00397 {
00398
00399 ((Item_sum_min*) item_sum)->clear();
00400 }
00401 else
00402 {
00403 ((Item_sum_min*) item_sum)->reset();
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
00413
00414
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
00429
00430
00431
00432
00433
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;
00483 }
00484
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
00494
00495
00496
00497
00498
00499
00500
00501 const_result= 0;
00502 break;
00503 }
00504 if (! count)
00505 {
00506
00507 ((Item_sum_max*) item_sum)->clear();
00508 }
00509 else
00510 {
00511 ((Item_sum_max*) item_sum)->reset();
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
00536
00537
00538
00539
00540
00541 if (removed_tables && used_tables != removed_tables)
00542 {
00543 const_result= 0;
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
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
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
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
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
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
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;
00715 }
00716
00717 bool eq_type= false;
00718 bool noeq_type= false;
00719 bool less_fl= false;
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;
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;
00733 case Item_func::LE_FUNC:
00734 less_fl= 1;
00735 break;
00736 case Item_func::GT_FUNC:
00737 noeq_type= 1;
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;
00748 }
00749
00750 Item *args[3];
00751 bool inv;
00752
00753
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;
00762 }
00763
00764
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;
00773 }
00774 if (part->field->eq(((Item_field*) args[0])->field))
00775 {
00776 break;
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
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
00814
00815
00816
00817
00818
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;
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;
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
00938
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
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
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
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;
01005 }
01006
01007
01008
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
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;
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
01101 if (! item->const_item())
01102 {
01103 less_fl= 1-less_fl;
01104 }
01105
01106
01107
01108
01109
01110
01111 if (max_fl != less_fl)
01112 {
01113 return cond->val_int() == 0;
01114 }
01115 return 0;
01116 }
01117 case Item_func::EQ_FUNC:
01118 case Item_func::EQUAL_FUNC:
01119 break;
01120 default:
01121 ;
01122 }
01123 return 0;
01124 }
01125
01126 }
01127