summaryrefslogtreecommitdiff
path: root/sql/opt_range.cc
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-07-17 21:24:29 +0200
committerSergei Golubchik <sergii@pisem.net>2013-07-17 21:24:29 +0200
commit97e640b9ae83e07b444fceede6b0524256c7a3cc (patch)
tree8f48fbfaf88ea7895ce59fd3ac2fbe6184334387 /sql/opt_range.cc
parent2f6a2494a5eb2cf3ab06fbedd2584eca85d90230 (diff)
parentc7973615e723b13c6457b494b72be2fac35bfd18 (diff)
downloadmariadb-git-97e640b9ae83e07b444fceede6b0524256c7a3cc.tar.gz
5.5 merge
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r--sql/opt_range.cc118
1 files changed, 76 insertions, 42 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index c6fbb579509..04ab4ced332 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
- Copyright (c) 2008-2011 Monty Program Ab
+/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2013, Monty Program Ab.
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
@@ -844,8 +844,17 @@ public:
/* Number of SEL_ARG objects allocated by SEL_ARG::clone_tree operations */
uint alloced_sel_args;
+
bool force_default_mrr;
KEY_PART *key[MAX_KEY]; /* First key parts of keys used in the query */
+
+ bool statement_should_be_aborted() const
+ {
+ return
+ thd->is_fatal_error ||
+ thd->is_error() ||
+ alloced_sel_args > SEL_ARG::MAX_SEL_ARGS;
+ }
};
class PARAM : public RANGE_OPT_PARAM
@@ -2074,30 +2083,16 @@ end:
org_key_read= head->key_read;
head->file= file;
head->key_read= 0;
+ head->mark_columns_used_by_index_no_reset(index, head->read_set);
+
if (!head->no_keyread)
{
doing_key_read= 1;
- head->mark_columns_used_by_index_no_reset(index, head->read_set);
head->enable_keyread();
}
head->prepare_for_position();
- if (head->no_keyread)
- {
- /*
- We can get here when doing multi-table delete and having index_merge
- condition on a table that we're deleting from. It probably doesn't make
- sense to use index_merge, but de-facto it is used.
-
- When it is used, we need to index columns to be read (before maria-5.3,
- read_multi_range_first() would set it).
- We shouldn't call mark_columns_used_by_index(), because it calls
- enable_keyread(), which is not allowed.
- */
- head->mark_columns_used_by_index_no_reset(index, head->read_set);
- }
-
head->file= org_file;
head->key_read= org_key_read;
@@ -5326,6 +5321,8 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
bzero((*changed_tree)->keys,
sizeof((*changed_tree)->keys[0])*param->keys);
(*changed_tree)->keys_map.clear_all();
+ key->incr_refs();
+ (*tree)->keys[key_idx]->incr_refs();
if (((*changed_tree)->keys[key_idx]=
key_or(param, key, (*tree)->keys[key_idx])))
(*changed_tree)->keys_map.set_bit(key_idx);
@@ -7531,6 +7528,34 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
{
new_interval->min_value= last_val->max_value;
new_interval->min_flag= NEAR_MIN;
+
+ /*
+ If the interval is over a partial keypart, the
+ interval must be "c_{i-1} <= X < c_i" instead of
+ "c_{i-1} < X < c_i". Reason:
+
+ Consider a table with a column "my_col VARCHAR(3)",
+ and an index with definition
+ "INDEX my_idx my_col(1)". If the table contains rows
+ with my_col values "f" and "foo", the index will not
+ distinguish the two rows.
+
+ Note that tree_or() below will effectively merge
+ this range with the range created for c_{i-1} and
+ we'll eventually end up with only one range:
+ "NULL < X".
+
+ Partitioning indexes are never partial.
+ */
+ if (param->using_real_indexes)
+ {
+ const KEY key=
+ param->table->key_info[param->real_keynr[idx]];
+ const KEY_PART_INFO *kpi= key.key_part + new_interval->part;
+
+ if (kpi->key_part_flag & HA_PART_KEY_SEG)
+ new_interval->min_flag= 0;
+ }
}
}
/*
@@ -7743,34 +7768,35 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
{
- tree=0;
+ tree= NULL;
Item *item;
while ((item=li++))
{
- SEL_TREE *new_tree=get_mm_tree(param,item);
- if (param->thd->is_fatal_error ||
- param->alloced_sel_args > SEL_ARG::MAX_SEL_ARGS)
- DBUG_RETURN(0); // out of memory
- tree=tree_and(param,tree,new_tree);
- if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
- break;
+ SEL_TREE *new_tree= get_mm_tree(param,item);
+ if (param->statement_should_be_aborted())
+ DBUG_RETURN(NULL);
+ tree= tree_and(param,tree,new_tree);
+ if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
+ break;
}
}
else
- { // COND OR
- tree=get_mm_tree(param,li++);
+ { // COND OR
+ tree= get_mm_tree(param,li++);
+ if (param->statement_should_be_aborted())
+ DBUG_RETURN(NULL);
if (tree)
{
- Item *item;
- while ((item=li++))
- {
- SEL_TREE *new_tree=get_mm_tree(param,item);
- if (!new_tree)
- DBUG_RETURN(0); // out of memory
- tree=tree_or(param,tree,new_tree);
- if (!tree || tree->type == SEL_TREE::ALWAYS)
- break;
- }
+ Item *item;
+ while ((item=li++))
+ {
+ SEL_TREE *new_tree=get_mm_tree(param,item);
+ if (new_tree == NULL || param->statement_should_be_aborted())
+ DBUG_RETURN(NULL);
+ tree= tree_or(param,tree,new_tree);
+ if (tree == NULL || tree->type == SEL_TREE::ALWAYS)
+ break;
+ }
}
}
DBUG_RETURN(tree);
@@ -8024,6 +8050,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
if (key_part->image_type == Field::itMBR)
{
+ // @todo: use is_spatial_operator() instead?
switch (type) {
case Item_func::SP_EQUALS_FUNC:
case Item_func::SP_DISJOINT_FUNC:
@@ -10993,12 +11020,13 @@ int read_keys_and_merge_scans(THD *thd,
Unique *unique= *unique_ptr;
handler *file= head->file;
bool with_cpk_filter= pk_quick_select != NULL;
-
+ bool enabled_keyread= 0;
DBUG_ENTER("read_keys_and_merge");
/* We're going to just read rowids. */
if (!head->key_read)
{
+ enabled_keyread= 1;
head->enable_keyread();
}
head->prepare_for_position();
@@ -11092,13 +11120,15 @@ int read_keys_and_merge_scans(THD *thd,
/*
index merge currently doesn't support "using index" at all
*/
- head->disable_keyread();
+ if (enabled_keyread)
+ head->disable_keyread();
if (init_read_record(read_record, thd, head, (SQL_SELECT*) 0, 1 , 1, TRUE))
result= 1;
DBUG_RETURN(result);
err:
- head->disable_keyread();
+ if (enabled_keyread)
+ head->disable_keyread();
DBUG_RETURN(1);
}
@@ -13584,7 +13614,11 @@ QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT()
DBUG_ASSERT(file == head->file);
if (doing_key_read)
head->disable_keyread();
- file->ha_index_end();
+ /*
+ There may be a code path when the same table was first accessed by index,
+ then the index is closed, and the table is scanned (order by + loose scan).
+ */
+ file->ha_index_or_rnd_end();
}
if (min_max_arg_part)
delete_dynamic(&min_max_ranges);