summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2015-06-24 07:16:08 +0300
committerJan Lindström <jan.lindstrom@mariadb.com>2015-06-24 07:16:08 +0300
commit2e4984c185ddcd2da789017cd147338846ff409a (patch)
tree0293831900c860600efbaa747ea886d9d1cbf5bd /sql/sql_select.cc
parent792b53e80806df893ee62c9a1c1bd117114c8c6d (diff)
parenta6087e7dc1ef3561d8189c8db15e9591d0f9b520 (diff)
downloadmariadb-git-10.0-FusionIO.tar.gz
Merge tag 'mariadb-10.0.20' into 10.0-FusionIO10.0-FusionIO
Conflicts: storage/innobase/os/os0file.cc storage/xtradb/os/os0file.cc storage/xtradb/srv/srv0start.cc
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc123
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;
}