56 #include <drizzled/sql_select.h>
57 #include <drizzled/item/sum.h>
58 #include <drizzled/item/cmpfunc.h>
59 #include <drizzled/optimizer/sum.h>
60 #include <drizzled/plugin/storage_engine.h>
61 #include <drizzled/table_list.h>
62 #include <drizzled/key.h>
63 #include <drizzled/error.h>
69 table_reference_st *ref,
73 uint32_t *key_prefix_length);
76 table_reference_st *ref,
100 static uint64_t get_exact_record_count(TableList *tables)
103 for (TableList *tl= tables; tl; tl= tl->next_leaf)
105 ha_rows tmp= tl->table->cursor->records();
106 if ((tmp == HA_POS_ERROR))
116 int optimizer::sum_query(TableList *tables, List<Item> &all_fields, COND *conds)
118 List<Item>::iterator it(all_fields.begin());
120 bool recalc_const_item=
false;
122 bool is_exact_count=
true;
123 bool maybe_exact_count=
true;
124 table_map removed_tables= 0;
125 table_map outer_tables= 0;
126 table_map used_tables= 0;
127 table_map where_tables= 0;
133 where_tables= conds->used_tables();
140 for (TableList *tl= tables; tl; tl= tl->next_leaf)
142 TableList *embedded= NULL;
143 for (embedded= tl; embedded; embedded= embedded->getEmbedding())
145 if (embedded->on_expr)
151 outer_tables|= tl->table->map;
159 if (tl->table->map & where_tables)
164 used_tables|= tl->table->map;
174 if (! (tl->table->cursor->getEngine()->check_flag(HTON_BIT_STATS_RECORDS_IS_EXACT)))
176 maybe_exact_count&= test(tl->table->cursor->getEngine()->check_flag(HTON_BIT_HAS_RECORDS));
177 is_exact_count=
false;
182 error= tl->table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
185 tl->table->print_error(error, MYF(ME_FATALERROR));
188 count*= tl->table->cursor->stats.records;
199 if (item->type() == Item::SUM_FUNC_ITEM)
201 Item_sum *item_sum= (((Item_sum*) item));
202 switch (item_sum->sum_func())
204 case Item_sum::COUNT_FUNC:
210 if (! conds && ! ((Item_sum_count*) item)->args[0]->maybe_null &&
211 ! outer_tables && maybe_exact_count)
213 if (! is_exact_count)
215 if ((count= get_exact_record_count(tables)) == UINT64_MAX)
223 ((Item_sum_count*) item)->make_const_count((int64_t) count);
224 recalc_const_item= 1;
231 case Item_sum::MIN_FUNC:
238 Item *expr=item_sum->args[0];
239 if (expr->real_item()->type() == Item::FIELD_ITEM)
241 unsigned char key_buff[MAX_KEY_LENGTH];
242 table_reference_st ref;
243 uint32_t range_fl, prefix_len;
245 ref.key_buff= key_buff;
246 Item_field *item_field= (Item_field*) (expr->real_item());
247 Table *table= item_field->field->getTable();
257 if (table->cursor->inited ||
258 (outer_tables & table->map) ||
269 error= table->cursor->startIndexScan(static_cast<uint32_t>(ref.key), 1);
275 table->cursor->extra(HA_EXTRA_NO_KEYREAD);
277 table->print_error(error, MYF(0));
281 if (! ref.key_length)
283 error= table->cursor->index_first(table->record[0]);
301 if (! (range_fl & NEAR_MIN))
307 error= table->cursor->index_read_map(table->record[0],
309 make_prev_keypart_map(ref.key_parts),
310 HA_READ_KEY_OR_NEXT);
320 error= table->cursor->index_read_map(table->record[0],
322 make_prev_keypart_map(ref.key_parts),
333 if (item_field->field->real_maybe_null() &&
334 ref.key_buff[prefix_len] == 1 &&
342 (error == HA_ERR_KEY_NOT_FOUND ||
345 assert(item_field->field->real_maybe_null());
346 error= table->cursor->index_read_map(table->record[0],
348 make_prev_keypart_map(ref.key_parts),
362 error= HA_ERR_KEY_NOT_FOUND;
367 table->cursor->extra(HA_EXTRA_NO_KEYREAD);
369 table->cursor->endIndexScan();
372 if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
374 return HA_ERR_KEY_NOT_FOUND;
377 table->print_error(error, MYF(0));
380 removed_tables|= table->map;
382 else if (! expr->const_item() || ! is_exact_count)
399 ((Item_sum_min*) item_sum)->clear();
403 ((Item_sum_min*) item_sum)->reset();
405 ((Item_sum_min*) item_sum)->make_const();
406 recalc_const_item= 1;
409 case Item_sum::MAX_FUNC:
416 Item *expr= item_sum->args[0];
417 if (expr->real_item()->type() == Item::FIELD_ITEM)
419 unsigned char key_buff[MAX_KEY_LENGTH];
420 table_reference_st ref;
421 uint32_t range_fl, prefix_len;
423 ref.key_buff= key_buff;
424 Item_field *item_field= (Item_field*) (expr->real_item());
425 Table *table= item_field->field->getTable();
435 if (table->cursor->inited ||
436 (outer_tables & table->map) ||
447 error= table->cursor->startIndexScan(static_cast<uint32_t>(ref.key), 1);
449 if (! ref.key_length)
451 error= table->cursor->index_last(table->record[0]);
455 error= table->cursor->index_read_map(table->record[0],
457 make_prev_keypart_map(ref.key_parts),
458 range_fl & NEAR_MAX ?
460 HA_READ_PREFIX_LAST_OR_PREV);
470 error= HA_ERR_KEY_NOT_FOUND;
475 table->cursor->extra(HA_EXTRA_NO_KEYREAD);
477 table->cursor->endIndexScan();
480 if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
482 return HA_ERR_KEY_NOT_FOUND;
485 table->print_error(error, MYF(ME_FATALERROR));
488 removed_tables|= table->map;
490 else if (! expr->const_item() || ! is_exact_count)
507 ((Item_sum_max*) item_sum)->clear();
511 ((Item_sum_max*) item_sum)->reset();
513 ((Item_sum_max*) item_sum)->make_const();
514 recalc_const_item= 1;
522 else if (const_result)
524 if (recalc_const_item)
526 item->update_used_tables();
528 if (! item->const_item())
541 if (removed_tables && used_tables != removed_tables)
549 bool optimizer::simple_pred(Item_func *func_item, Item **args,
bool &inv_order)
553 switch (func_item->argument_count())
558 Item_equal *item_equal= (Item_equal *) func_item;
559 Item_equal_iterator it(item_equal->begin());
565 if (! (args[1]= item_equal->get_const()))
573 item= func_item->arguments()[0];
574 if (item->type() != Item::FIELD_ITEM)
582 item= func_item->arguments()[0];
583 if (item->type() == Item::FIELD_ITEM)
586 item= func_item->arguments()[1];
587 if (! item->const_item())
593 else if (item->const_item())
596 item= func_item->arguments()[1];
597 if (item->type() != Item::FIELD_ITEM)
611 item= func_item->arguments()[0];
612 if (item->type() == Item::FIELD_ITEM)
615 for (
int i= 1 ; i <= 2; i++)
617 item= func_item->arguments()[i];
618 if (! item->const_item())
668 key_part_map *key_part_used,
670 uint32_t *prefix_len)
676 Field *field= field_part->field;
678 field->setWriteSet();
685 if (cond->type() == Item::COND_ITEM)
687 if (((
Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
712 if (cond->type() != Item::FUNC_ITEM)
718 bool noeq_type=
false;
725 case Item_func::ISNULL_FUNC:
727 case Item_func::EQ_FUNC:
728 case Item_func::EQUAL_FUNC:
731 case Item_func::LT_FUNC:
733 case Item_func::LE_FUNC:
736 case Item_func::GT_FUNC:
738 case Item_func::GE_FUNC:
740 case Item_func::BETWEEN:
743 case Item_func::MULT_EQUAL_FUNC:
754 if (! optimizer::simple_pred((
Item_func*) cond, args, inv))
759 if (inv && ! eq_type)
761 less_fl= 1 - less_fl;
765 unsigned char *key_ptr= ref->
key_buff;
767 for (part= keyinfo->key_part; ; key_ptr+= part++->store_length)
770 if (part > field_part)
774 if (part->field->eq(((
Item_field*) args[0])->field))
780 bool is_field_part= part == field_part;
781 if (! (is_field_part || eq_type))
786 key_part_map org_key_part_used= *key_part_used;
787 if (eq_type || between || max_fl == less_fl)
789 uint32_t length= (key_ptr-ref->
key_buff)+part->store_length;
794 ref->
key_parts= (part - keyinfo->key_part) + 1;
796 if (! *prefix_len && part + 1 == field_part)
800 if (is_field_part && eq_type)
805 *key_part_used|= (key_part_map) 1 << (part - keyinfo->key_part);
808 if (org_key_part_used != *key_part_used ||
810 (between || eq_type || max_fl == less_fl) && ! cond->
val_int()))
823 part->field->set_null();
824 *key_ptr= (
unsigned char) 1;
832 *key_ptr++= (
unsigned char) test(part->field->is_null());
838 if (between || eq_type)
840 *range_fl&= ~(NO_MAX_RANGE | NO_MIN_RANGE);
844 *range_fl&= ~(max_fl ? NO_MAX_RANGE : NO_MIN_RANGE);
847 *range_fl|= (max_fl ? NEAR_MAX : NEAR_MIN);
851 *range_fl&= ~(max_fl ? NEAR_MAX : NEAR_MIN);
858 if ((! is_null && !cond->
val_int()) ||
859 (is_null && !test(part->field->is_null())))
864 else if (is_field_part)
866 *range_fl&= ~(max_fl ? NO_MIN_RANGE : NO_MAX_RANGE);
918 uint32_t *prefix_len)
920 if (! (field->flags & PART_KEY_FLAG))
925 Table *table= field->getTable();
928 KeyInfo *keyinfo,*keyinfo_end= NULL;
929 for (keyinfo= table->
key_info, keyinfo_end= keyinfo+table->getShare()->sizeKeys();
930 keyinfo != keyinfo_end;
935 key_part_map key_part_to_use= 0;
940 if (! table->keys_in_use_for_query.test(idx))
946 for (part= keyinfo->key_part, part_end= part+keyinfo->key_parts;
948 part++, jdx++, key_part_to_use= (key_part_to_use << 1) | 1)
950 if (! (table->index_flags(idx) & HA_READ_ORDER))
956 Field *part_field= table->getField(part->fieldnr-1);
957 part_field->setWriteSet();
959 if ((part_field->flags & BLOB_FLAG) ||
960 part->length < part_field->key_length())
965 if (field->eq(part->field))
970 key_part_map key_part_used= 0;
971 *range_fl= NO_MIN_RANGE | NO_MAX_RANGE;
980 ! (key_part_to_use & ~key_part_used))
982 if (! max_fl && key_part_used == key_part_to_use && part->null_bit)
1003 *range_fl&= ~NO_MIN_RANGE;
1004 *range_fl|= NEAR_MIN;
1010 if (field->part_of_key.test(idx))
1013 table->
cursor->extra(HA_EXTRA_KEYREAD);
1044 uint32_t prefix_len)
1050 if (! cond || (range_fl & (max_fl ? NO_MIN_RANGE : NO_MAX_RANGE)))
1073 if (cond->type() == Item::COND_ITEM)
1076 while (
Item* item= li++)
1088 bool less_fl=
false;
1089 switch (((
Item_func*) cond)->functype())
1091 case Item_func::BETWEEN:
1093 case Item_func::LT_FUNC:
1094 case Item_func::LE_FUNC:
1096 case Item_func::GT_FUNC:
1097 case Item_func::GE_FUNC:
1111 if (max_fl != less_fl)
1117 case Item_func::EQ_FUNC:
1118 case Item_func::EQUAL_FUNC:
virtual bool const_item() const
table_map map
ID bit of table (1,2,4,8,16...)
virtual int64_t val_int()=0
virtual uint32_t get_key_image(unsigned char *buff, uint32_t length)
TODO: Rename this file - func.h is stupid.
bool store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
static bool matching_cond(bool max_fl, table_reference_st *ref, KeyInfo *keyinfo, KeyPartInfo *field_part, COND *cond, key_part_map *key_part_used, uint32_t *range_fl, uint32_t *prefix_len)
static int reckey_in_range(bool max_fl, table_reference_st *ref, Field *field, COND *cond, uint32_t range_fl, uint32_t prefix_len)
virtual table_map used_tables() const
static int maxmin_in_range(bool max_fl, Field *field, COND *cond)
static bool find_key_for_maxmin(bool max_fl, table_reference_st *ref, Field *field, COND *cond, uint32_t *range_fl, uint32_t *key_prefix_length)
bool key_cmp_if_same(Table *table, const unsigned char *key, uint32_t idx, uint32_t key_length)