diff options
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 123 |
1 files changed, 93 insertions, 30 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ed56191c32b..e0f560f0b3a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2013 Oracle and/or its affiliates. - Copyright (c) 2009, 2013 Monty Program Ab. +/* Copyright (c) 2000, 2015 Oracle and/or its affiliates. + Copyright (c) 2009, 2015 MariaDB 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 @@ -709,9 +709,7 @@ JOIN::prepare(Item ***rref_pointer_array, if (!(select_options & OPTION_SETUP_TABLES_DONE) && setup_tables_and_check_access(thd, &select_lex->context, join_list, tables_list, select_lex->leaf_tables, - FALSE, SELECT_ACL, SELECT_ACL, - (thd->lex->sql_command == - SQLCOM_UPDATE_MULTI))) + FALSE, SELECT_ACL, SELECT_ACL, FALSE)) DBUG_RETURN(-1); /* @@ -4958,7 +4956,18 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field) } -#define FT_KEYPART (MAX_REF_PARTS+10) +/* + A key part number that means we're using a fulltext scan. + + In order not to confuse it with regular equalities, we need to pick + a number that's greater than MAX_REF_PARTS. + + Hash Join code stores field->field_index in KEYUSE::keypart, so the + number needs to be bigger than MAX_FIELDS, also. + + CAUTION: sql_test.cc has its own definition of FT_KEYPART. +*/ +#define FT_KEYPART (MAX_FIELDS+10) static bool add_ft_keys(DYNAMIC_ARRAY *keyuse_array, @@ -6455,7 +6464,6 @@ choose_plan(JOIN *join, table_map join_tables) DBUG_ENTER("choose_plan"); join->cur_embedding_map= 0; - join->cur_dups_producing_tables= 0; reset_nj_counters(join, join->join_list); qsort2_cmp jtab_sort_func; @@ -7451,8 +7459,12 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, else fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1; if (keyuse->val->const_item()) - { - sel /= table->field[fldno]->cond_selectivity; + { + if (table->field[fldno]->cond_selectivity > 0) + { + sel /= table->field[fldno]->cond_selectivity; + set_if_smaller(sel, 1.0); + } /* TODO: we could do better here: 1. cond_selectivity might be =1 (the default) because quick @@ -7506,7 +7518,10 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, if (!(next_field->table->map & rem_tables) && next_field->table != table) { if (field->cond_selectivity > 0) + { sel/= field->cond_selectivity; + set_if_smaller(sel, 1.0); + } break; } } @@ -8660,7 +8675,8 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, { Field *field= table->field[keyuse->keypart]; uint fieldnr= keyuse->keypart+1; - table->create_key_part_by_field(keyinfo, key_part_info, field, fieldnr); + table->create_key_part_by_field(key_part_info, field, fieldnr); + keyinfo->key_length += key_part_info->store_length; key_part_info++; } } @@ -9720,10 +9736,24 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (!sel->quick_keys.is_subset(tab->checked_keys) || !sel->needed_reg.is_subset(tab->checked_keys)) { + /* + "Range checked for each record" is a "last resort" access method + that should only be used when the other option is a cross-product + join. + + We use the following condition (it's approximate): + 1. There are potential keys for (sel->needed_reg) + 2. There were no possible ways to construct a quick select, or + the quick select would be more expensive than the full table + scan. + */ tab->use_quick= (!sel->needed_reg.is_clear_all() && (sel->quick_keys.is_clear_all() || - (sel->quick && - (sel->quick->records >= 100L)))) ? + (sel->quick && + sel->quick->read_time > + tab->table->file->scan_time() + + tab->table->file->stats.records/TIME_FOR_COMPARE + ))) ? 2 : 1; sel->read_tables= used_tables & ~current_map; sel->quick_keys.clear_all(); @@ -15791,7 +15821,6 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, (int) distinct, (int) save_sum_fields, (ulong) rows_limit, MY_TEST(group))); - thd->inc_status_created_tmp_tables(); thd->query_plan_flags|= QPLAN_TMP_TABLE; if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES)) @@ -16745,14 +16774,19 @@ bool open_tmp_table(TABLE *table) HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE))) { - table->file->print_error(error,MYF(0)); /* purecov: inspected */ - table->db_stat=0; - return(1); + table->file->print_error(error, MYF(0)); /* purecov: inspected */ + table->db_stat= 0; + return 1; } table->db_stat= HA_OPEN_KEYFILE+HA_OPEN_RNDFILE; - (void) table->file->extra(HA_EXTRA_QUICK); /* Faster */ - table->created= TRUE; - return(0); + (void) table->file->extra(HA_EXTRA_QUICK); /* Faster */ + if (!table->created) + { + table->created= TRUE; + table->in_use->inc_status_created_tmp_tables(); + } + + return 0; } @@ -16809,7 +16843,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts); - if (keyinfo->key_length >= table->file->max_key_length() || + if (keyinfo->key_length > table->file->max_key_length() || keyinfo->user_defined_key_parts > table->file->max_key_parts() || share->uniques) { @@ -16919,8 +16953,10 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; } table->in_use->inc_status_created_tmp_disk_tables(); + table->in_use->inc_status_created_tmp_tables(); table->in_use->query_plan_flags|= QPLAN_TMP_DISK; share->db_record_offset= 1; + table->created= TRUE; DBUG_RETURN(0); err: DBUG_RETURN(1); @@ -16980,7 +17016,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts); - if (keyinfo->key_length >= table->file->max_key_length() || + if (keyinfo->key_length > table->file->max_key_length() || keyinfo->user_defined_key_parts > table->file->max_key_parts() || share->uniques) { @@ -17065,6 +17101,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; } table->in_use->inc_status_created_tmp_disk_tables(); + table->in_use->inc_status_created_tmp_tables(); table->in_use->query_plan_flags|= QPLAN_TMP_DISK; share->db_record_offset= 1; table->created= TRUE; @@ -21123,18 +21160,33 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length, for (;order;order=order->next,pos++) { - Item *item= order->item[0]->real_item(); + Item *const item= order->item[0], *const real_item= item->real_item(); pos->field= 0; pos->item= 0; - if (item->type() == Item::FIELD_ITEM) - pos->field= ((Item_field*) item)->field; - else if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item()) - pos->field= ((Item_sum*) item)->get_tmp_table_field(); - else if (item->type() == Item::COPY_STR_ITEM) - { // Blob patch - pos->item= ((Item_copy*) item)->get_item(); + if (real_item->type() == Item::FIELD_ITEM) + { + // Could be a field, or Item_direct_view_ref wrapping a field + DBUG_ASSERT(item->type() == Item::FIELD_ITEM || + (item->type() == Item::REF_ITEM && + static_cast<Item_ref*>(item)->ref_type() == + Item_ref::VIEW_REF)); + pos->field= static_cast<Item_field*>(real_item)->field; + } + else if (real_item->type() == Item::SUM_FUNC_ITEM && + !real_item->const_item()) + { + // Aggregate, or Item_aggregate_ref + DBUG_ASSERT(item->type() == Item::SUM_FUNC_ITEM || + (item->type() == Item::REF_ITEM && + static_cast<Item_ref*>(item)->ref_type() == + Item_ref::AGGREGATE_REF)); + pos->field= item->get_tmp_table_field(); + } + else if (real_item->type() == Item::COPY_STR_ITEM) + { // Blob patch + pos->item= static_cast<Item_copy*>(real_item)->get_item(); } else - pos->item= *order->item; + pos->item= item; pos->reverse=! order->asc; DBUG_ASSERT(pos->field != NULL || pos->item != NULL); } @@ -21378,6 +21430,17 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, uint el= all_fields.elements; all_fields.push_front(order_item); /* Add new field to field list. */ ref_pointer_array[el]= order_item; + /* + If the order_item is a SUM_FUNC_ITEM, when fix_fields is called + ref_by is set to order->item which is the address of order_item. + But this needs to be address of order_item in the all_fields list. + As a result, when it gets replaced with Item_aggregate_ref + object in Item::split_sum_func2, we will be able to retrieve the + newly created object. + */ + if (order_item->type() == Item::SUM_FUNC_ITEM) + ((Item_sum *)order_item)->ref_by= all_fields.head_ref(); + order->item= ref_pointer_array + el; return FALSE; } |