mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge
BitKeeper/etc/logging_ok: auto-union BUILD/autorun.sh: Auto merged BitKeeper/etc/config: Auto merged Makefile.am: Auto merged include/my_bitmap.h: Auto merged libmysqld/Makefile.am: Auto merged mysql-test/mysql-test-run.pl: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/grant.result: Auto merged mysql-test/r/ps_6bdb.result: Auto merged mysql-test/r/ps_7ndb.result: Auto merged mysys/Makefile.am: Auto merged mysys/default.c: Auto merged scripts/mysql_create_system_tables.sh: Auto merged scripts/mysql_fix_privilege_tables.sql: Auto merged sql/Makefile.am: Auto merged sql/field.cc: Auto merged sql/field.h: Auto merged sql/ha_ndbcluster.h: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/item.cc: Auto merged sql/log_event.cc: Auto merged sql/mysql_priv.h: Auto merged sql/opt_range.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_acl.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_delete.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_udf.cc: Auto merged sql/sql_yacc.yy: Auto merged storage/heap/Makefile.am: Auto merged storage/heap/hp_hash.c: Auto merged storage/innobase/btr/btr0btr.c: Auto merged storage/innobase/btr/btr0cur.c: Auto merged storage/innobase/configure.in: Auto merged storage/innobase/fil/fil0fil.c: Auto merged storage/innobase/ibuf/ibuf0ibuf.c: Auto merged storage/innobase/include/os0file.h: Auto merged storage/innobase/include/page0cur.h: Auto merged storage/innobase/include/row0mysql.h: Auto merged storage/innobase/include/srv0srv.h: Auto merged storage/innobase/include/trx0trx.h: Auto merged storage/innobase/include/trx0trx.ic: Auto merged storage/innobase/lock/lock0lock.c: Auto merged storage/innobase/log/log0recv.c: Auto merged storage/innobase/os/os0file.c: Auto merged storage/innobase/page/page0cur.c: Auto merged storage/innobase/page/page0page.c: Auto merged storage/innobase/rem/rem0rec.c: Auto merged storage/innobase/row/row0mysql.c: Auto merged storage/innobase/row/row0sel.c: Auto merged storage/innobase/row/row0upd.c: Auto merged storage/innobase/srv/srv0srv.c: Auto merged storage/innobase/trx/trx0trx.c: Auto merged storage/innobase/trx/trx0undo.c: Auto merged storage/myisam/Makefile.am: Auto merged storage/myisam/mi_create.c: Auto merged storage/myisam/mi_open.c: Auto merged storage/myisam/mi_packrec.c: Auto merged storage/myisam/mi_unique.c: Auto merged storage/myisam/myisampack.c: Auto merged storage/myisammrg/Makefile.am: Auto merged storage/ndb/include/mgmcommon/ConfigRetriever.hpp: Auto merged storage/ndb/include/transporter/TransporterDefinitions.hpp: Auto merged storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp: Auto merged storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: Auto merged storage/ndb/src/mgmsrv/main.cpp: Auto merged storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp: Auto merged storage/ndb/test/ndbapi/create_tab.cpp: Auto merged storage/ndb/test/ndbapi/testBlobs.cpp: Auto merged strings/ctype-big5.c: Auto merged strings/ctype-ucs2.c: Auto merged support-files/mysql.spec.sh: Auto merged configure.in: merge mysql-test/t/disabled.def: merge mysys/my_bitmap.c: SCCS merged sql/ha_federated.cc: merge sql/ha_innodb.cc: merge sql/ha_ndbcluster.cc: merge sql/mysqld.cc: e merge sql/sql_insert.cc: merge sql/sql_lex.h: merge sql/sql_load.cc: merge sql/sql_select.cc: merge e C sql/sql_update.cc: merge sql/table.cc: merge
This commit is contained in:
148
sql/opt_range.cc
148
sql/opt_range.cc
@ -325,7 +325,7 @@ typedef struct st_qsel_param {
|
||||
TABLE *table;
|
||||
KEY_PART *key_parts,*key_parts_end;
|
||||
KEY_PART *key[MAX_KEY]; /* First key parts of keys used in the query */
|
||||
MEM_ROOT *mem_root;
|
||||
MEM_ROOT *mem_root, *old_root;
|
||||
table_map prev_tables,read_tables,current_table;
|
||||
uint baseflag, max_key_part, range_count;
|
||||
|
||||
@ -1669,7 +1669,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
keys_to_use.intersect(head->keys_in_use_for_query);
|
||||
if (!keys_to_use.is_clear_all())
|
||||
{
|
||||
MEM_ROOT *old_root,alloc;
|
||||
MEM_ROOT alloc;
|
||||
SEL_TREE *tree= NULL;
|
||||
KEY_PART *key_parts;
|
||||
KEY *key_info;
|
||||
@ -1684,6 +1684,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
param.table=head;
|
||||
param.keys=0;
|
||||
param.mem_root= &alloc;
|
||||
param.old_root= thd->mem_root;
|
||||
param.needed_reg= &needed_reg;
|
||||
param.imerge_cost_buff_size= 0;
|
||||
|
||||
@ -1699,7 +1700,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
DBUG_RETURN(0); // Can't use range
|
||||
}
|
||||
key_parts= param.key_parts;
|
||||
old_root= thd->mem_root;
|
||||
thd->mem_root= &alloc;
|
||||
|
||||
/*
|
||||
@ -1849,7 +1849,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
}
|
||||
}
|
||||
|
||||
thd->mem_root= old_root;
|
||||
thd->mem_root= param.old_root;
|
||||
|
||||
/* If we got a read plan, create a quick select from it. */
|
||||
if (best_trp)
|
||||
@ -1864,7 +1864,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
|
||||
free_mem:
|
||||
free_root(&alloc,MYF(0)); // Return memory & allocator
|
||||
thd->mem_root= old_root;
|
||||
thd->mem_root= param.old_root;
|
||||
thd->no_errors=0;
|
||||
}
|
||||
|
||||
@ -3533,15 +3533,12 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
|
||||
{
|
||||
/* Optimize NOT BETWEEN and NOT IN */
|
||||
Item *arg= cond_func->arguments()[0];
|
||||
if (arg->type() == Item::FUNC_ITEM)
|
||||
{
|
||||
cond_func= (Item_func*) arg;
|
||||
if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
|
||||
DBUG_RETURN(0);
|
||||
inv= TRUE;
|
||||
}
|
||||
else
|
||||
if (arg->type() != Item::FUNC_ITEM)
|
||||
DBUG_RETURN(0);
|
||||
cond_func= (Item_func*) arg;
|
||||
if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
|
||||
DBUG_RETURN(0);
|
||||
inv= TRUE;
|
||||
}
|
||||
else if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
|
||||
DBUG_RETURN(0);
|
||||
@ -3586,15 +3583,16 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
|
||||
DBUG_RETURN(ftree);
|
||||
}
|
||||
default:
|
||||
if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
|
||||
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
field_item= (Item_field*) (cond_func->arguments()[0]);
|
||||
field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
|
||||
value= cond_func->arg_count > 1 ? cond_func->arguments()[1] : 0;
|
||||
}
|
||||
else if (cond_func->have_rev_func() &&
|
||||
cond_func->arguments()[1]->type() == Item::FIELD_ITEM)
|
||||
cond_func->arguments()[1]->real_item()->type() ==
|
||||
Item::FIELD_ITEM)
|
||||
{
|
||||
field_item= (Item_field*) (cond_func->arguments()[1]);
|
||||
field_item= (Item_field*) (cond_func->arguments()[1]->real_item());
|
||||
value= cond_func->arguments()[0];
|
||||
}
|
||||
else
|
||||
@ -3615,7 +3613,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
|
||||
|
||||
for (uint i= 0; i < cond_func->arg_count; i++)
|
||||
{
|
||||
Item *arg= cond_func->arguments()[i];
|
||||
Item *arg= cond_func->arguments()[i]->real_item();
|
||||
if (arg != field_item)
|
||||
ref_tables|= arg->used_tables();
|
||||
}
|
||||
@ -3700,24 +3698,38 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
||||
{
|
||||
uint maybe_null=(uint) field->real_maybe_null();
|
||||
bool optimize_range;
|
||||
SEL_ARG *tree;
|
||||
SEL_ARG *tree= 0;
|
||||
MEM_ROOT *alloc= param->mem_root;
|
||||
char *str;
|
||||
DBUG_ENTER("get_mm_leaf");
|
||||
|
||||
/*
|
||||
We need to restore the runtime mem_root of the thread in this
|
||||
function because it evaluates the value of its argument, while
|
||||
the argument can be any, e.g. a subselect. The subselect
|
||||
items, in turn, assume that all the memory allocated during
|
||||
the evaluation has the same life span as the item itself.
|
||||
TODO: opt_range.cc should not reset thd->mem_root at all.
|
||||
*/
|
||||
param->thd->mem_root= param->old_root;
|
||||
if (!value) // IS NULL or IS NOT NULL
|
||||
{
|
||||
if (field->table->maybe_null) // Can't use a key on this
|
||||
DBUG_RETURN(0);
|
||||
goto end;
|
||||
if (!maybe_null) // Not null field
|
||||
DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0);
|
||||
if (!(tree=new SEL_ARG(field,is_null_string,is_null_string)))
|
||||
DBUG_RETURN(0); // out of memory
|
||||
{
|
||||
if (type == Item_func::ISNULL_FUNC)
|
||||
tree= &null_element;
|
||||
goto end;
|
||||
}
|
||||
if (!(tree= new (alloc) SEL_ARG(field,is_null_string,is_null_string)))
|
||||
goto end; // out of memory
|
||||
if (type == Item_func::ISNOTNULL_FUNC)
|
||||
{
|
||||
tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */
|
||||
tree->max_flag=NO_MAX_RANGE;
|
||||
}
|
||||
DBUG_RETURN(tree);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3737,7 +3749,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
||||
key_part->image_type == Field::itRAW &&
|
||||
((Field_str*)field)->charset() != conf_func->compare_collation() &&
|
||||
!(conf_func->compare_collation()->state & MY_CS_BINSORT))
|
||||
DBUG_RETURN(0);
|
||||
goto end;
|
||||
|
||||
optimize_range= field->optimize_range(param->real_keynr[key_part->key],
|
||||
key_part->part);
|
||||
@ -3751,9 +3763,12 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
||||
uint field_length= field->pack_length()+maybe_null;
|
||||
|
||||
if (!optimize_range)
|
||||
DBUG_RETURN(0); // Can't optimize this
|
||||
goto end;
|
||||
if (!(res= value->val_str(&tmp)))
|
||||
DBUG_RETURN(&null_element);
|
||||
{
|
||||
tree= &null_element;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
TODO:
|
||||
@ -3766,7 +3781,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
||||
res= &tmp;
|
||||
}
|
||||
if (field->cmp_type() != STRING_RESULT)
|
||||
DBUG_RETURN(0); // Can only optimize strings
|
||||
goto end; // Can only optimize strings
|
||||
|
||||
offset=maybe_null;
|
||||
length=key_part->store_length;
|
||||
@ -3791,8 +3806,8 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
||||
field_length= length;
|
||||
}
|
||||
length+=offset;
|
||||
if (!(min_str= (char*) alloc_root(param->mem_root, length*2)))
|
||||
DBUG_RETURN(0);
|
||||
if (!(min_str= (char*) alloc_root(alloc, length*2)))
|
||||
goto end;
|
||||
|
||||
max_str=min_str+length;
|
||||
if (maybe_null)
|
||||
@ -3807,20 +3822,21 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
||||
min_str+offset, max_str+offset,
|
||||
&min_length, &max_length);
|
||||
if (like_error) // Can't optimize with LIKE
|
||||
DBUG_RETURN(0);
|
||||
goto end;
|
||||
|
||||
if (offset != maybe_null) // BLOB or VARCHAR
|
||||
{
|
||||
int2store(min_str+maybe_null,min_length);
|
||||
int2store(max_str+maybe_null,max_length);
|
||||
}
|
||||
DBUG_RETURN(new SEL_ARG(field,min_str,max_str));
|
||||
tree= new (alloc) SEL_ARG(field, min_str, max_str);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!optimize_range &&
|
||||
type != Item_func::EQ_FUNC &&
|
||||
type != Item_func::EQUAL_FUNC)
|
||||
DBUG_RETURN(0); // Can't optimize this
|
||||
goto end; // Can't optimize this
|
||||
|
||||
/*
|
||||
We can't always use indexes when comparing a string index to a number
|
||||
@ -3829,21 +3845,53 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
||||
if (field->result_type() == STRING_RESULT &&
|
||||
value->result_type() != STRING_RESULT &&
|
||||
field->cmp_type() != value->result_type())
|
||||
DBUG_RETURN(0);
|
||||
goto end;
|
||||
|
||||
if (value->save_in_field_no_warnings(field, 1) < 0)
|
||||
{
|
||||
/* This happens when we try to insert a NULL field in a not null column */
|
||||
DBUG_RETURN(&null_element); // cmp with NULL is never TRUE
|
||||
tree= &null_element; // cmp with NULL is never TRUE
|
||||
goto end;
|
||||
}
|
||||
str= (char*) alloc_root(param->mem_root, key_part->store_length+1);
|
||||
str= (char*) alloc_root(alloc, key_part->store_length+1);
|
||||
if (!str)
|
||||
DBUG_RETURN(0);
|
||||
goto end;
|
||||
if (maybe_null)
|
||||
*str= (char) field->is_real_null(); // Set to 1 if null
|
||||
field->get_key_image(str+maybe_null, key_part->length, key_part->image_type);
|
||||
if (!(tree=new SEL_ARG(field,str,str)))
|
||||
DBUG_RETURN(0); // out of memory
|
||||
if (!(tree= new (alloc) SEL_ARG(field, str, str)))
|
||||
goto end; // out of memory
|
||||
|
||||
/*
|
||||
Check if we are comparing an UNSIGNED integer with a negative constant.
|
||||
In this case we know that:
|
||||
(a) (unsigned_int [< | <=] negative_constant) == FALSE
|
||||
(b) (unsigned_int [> | >=] negative_constant) == TRUE
|
||||
In case (a) the condition is false for all values, and in case (b) it
|
||||
is true for all values, so we can avoid unnecessary retrieval and condition
|
||||
testing, and we also get correct comparison of unsinged integers with
|
||||
negative integers (which otherwise fails because at query execution time
|
||||
negative integers are cast to unsigned if compared with unsigned).
|
||||
*/
|
||||
if (field->result_type() == INT_RESULT &&
|
||||
value->result_type() == INT_RESULT &&
|
||||
((Field_num*)field)->unsigned_flag && !((Item_int*)value)->unsigned_flag)
|
||||
{
|
||||
longlong item_val= value->val_int();
|
||||
if (item_val < 0)
|
||||
{
|
||||
if (type == Item_func::LT_FUNC || type == Item_func::LE_FUNC)
|
||||
{
|
||||
tree->type= SEL_ARG::IMPOSSIBLE;
|
||||
goto end;
|
||||
}
|
||||
if (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC)
|
||||
{
|
||||
tree= 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case Item_func::LT_FUNC:
|
||||
@ -3904,6 +3952,9 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
param->thd->mem_root= alloc;
|
||||
DBUG_RETURN(tree);
|
||||
}
|
||||
|
||||
@ -5997,7 +6048,10 @@ int QUICK_RANGE_SELECT::reset()
|
||||
next=0;
|
||||
range= NULL;
|
||||
cur_range= (QUICK_RANGE**) ranges.buffer;
|
||||
|
||||
|
||||
if (file->inited == handler::NONE && (error= file->ha_index_init(index)))
|
||||
DBUG_RETURN(error);
|
||||
|
||||
/* Do not allocate the buffers twice. */
|
||||
if (multi_range_length)
|
||||
{
|
||||
@ -8126,7 +8180,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next()
|
||||
(have_max && have_min && (max_res == 0)));
|
||||
}
|
||||
/*
|
||||
If this is a just a GROUP BY or DISTINCT without MIN or MAX and there
|
||||
If this is just a GROUP BY or DISTINCT without MIN or MAX and there
|
||||
are equality predicates for the key parts after the group, find the
|
||||
first sub-group with the extended prefix.
|
||||
*/
|
||||
@ -8529,23 +8583,21 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
|
||||
|
||||
if ((result == HA_ERR_KEY_NOT_FOUND) && (cur_range->flag & EQ_RANGE))
|
||||
continue; /* Check the next range. */
|
||||
else if (result)
|
||||
if (result)
|
||||
{
|
||||
/*
|
||||
In no key was found with this upper bound, there certainly are no keys
|
||||
in the ranges to the left.
|
||||
*/
|
||||
return result;
|
||||
|
||||
}
|
||||
/* A key was found. */
|
||||
if (cur_range->flag & EQ_RANGE)
|
||||
return result; /* No need to perform the checks below for equal keys. */
|
||||
return 0; /* No need to perform the checks below for equal keys. */
|
||||
|
||||
/* Check if record belongs to the current group. */
|
||||
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
|
||||
{
|
||||
result = HA_ERR_KEY_NOT_FOUND;
|
||||
continue;
|
||||
}
|
||||
continue; // Row not found
|
||||
|
||||
/* If there is a lower limit, check if the found key is in the range. */
|
||||
if ( !(cur_range->flag & NO_MIN_RANGE) )
|
||||
|
Reference in New Issue
Block a user