summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2015-08-12 17:28:45 +0400
committerAlexander Barkov <bar@mariadb.org>2015-08-12 17:28:45 +0400
commit9d884fd3d3fadd5ad31ecfee915877b98258e546 (patch)
tree717a99115c7d9516dd65c38ef8804edf9cad107c
parent6e091dc7ff06f9ff0bbe834f6be338f5b695ed81 (diff)
downloadmariadb-git-9d884fd3d3fadd5ad31ecfee915877b98258e546.tar.gz
MDEV-8599 "WHERE varchar_field LIKE temporal_const" does not use range optimizer
-rw-r--r--mysql-test/r/func_like.result25
-rw-r--r--mysql-test/t/func_like.test19
-rw-r--r--sql/item_cmpfunc.h14
-rw-r--r--sql/opt_range.cc351
-rw-r--r--sql/opt_range.h4
5 files changed, 243 insertions, 170 deletions
diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result
index 2fdcf1226b7..9c8e9727d16 100644
--- a/mysql-test/r/func_like.result
+++ b/mysql-test/r/func_like.result
@@ -227,5 +227,30 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 10.0) and (`test`.`t1`.`a` like 10.00))
DROP TABLE t1;
#
+# MDEV-8599 "WHERE varchar_field LIKE temporal_const" does not use range optimizer
+#
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('00:00:00');
+INSERT INTO t1 VALUES ('00:00:01');
+INSERT INTO t1 VALUES ('00:00:02');
+INSERT INTO t1 VALUES ('00:00:03');
+INSERT INTO t1 VALUES ('00:00:04');
+INSERT INTO t1 VALUES ('00:00:05');
+INSERT INTO t1 VALUES ('00:00:06');
+INSERT INTO t1 VALUES ('00:00:07');
+EXPLAIN SELECT * FROM t1 WHERE a LIKE '00:00:00';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 13 NULL 1 Using where; Using index
+EXPLAIN SELECT * FROM t1 WHERE a LIKE TIME'00:00:00';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 13 NULL 1 Using where; Using index
+SELECT * FROM t1 WHERE a LIKE '00:00:00';
+a
+00:00:00
+SELECT * FROM t1 WHERE a LIKE TIME'00:00:00';
+a
+00:00:00
+DROP TABLE t1;
+#
# End of 10.1 tests
#
diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test
index aab3c7fe43b..d1b9b170a3b 100644
--- a/mysql-test/t/func_like.test
+++ b/mysql-test/t/func_like.test
@@ -164,5 +164,24 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10.0 AND a LIKE 10.00;
DROP TABLE t1;
--echo #
+--echo # MDEV-8599 "WHERE varchar_field LIKE temporal_const" does not use range optimizer
+--echo #
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES ('00:00:00');
+INSERT INTO t1 VALUES ('00:00:01');
+INSERT INTO t1 VALUES ('00:00:02');
+INSERT INTO t1 VALUES ('00:00:03');
+INSERT INTO t1 VALUES ('00:00:04');
+INSERT INTO t1 VALUES ('00:00:05');
+INSERT INTO t1 VALUES ('00:00:06');
+INSERT INTO t1 VALUES ('00:00:07');
+EXPLAIN SELECT * FROM t1 WHERE a LIKE '00:00:00';
+EXPLAIN SELECT * FROM t1 WHERE a LIKE TIME'00:00:00';
+SELECT * FROM t1 WHERE a LIKE '00:00:00';
+SELECT * FROM t1 WHERE a LIKE TIME'00:00:00';
+DROP TABLE t1;
+
+
+--echo #
--echo # End of 10.1 tests
--echo #
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index f0ef596ff8c..b4f5d2dd963 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -120,6 +120,10 @@ public:
friend class Item_func;
};
+
+class SEL_ARG;
+struct KEY_PART;
+
class Item_bool_func :public Item_int_func
{
protected:
@@ -147,6 +151,9 @@ protected:
SEL_TREE *get_ne_mm_tree(RANGE_OPT_PARAM *param,
Field *field, Item *lt_value, Item *gt_value,
Item_result cmp_type);
+ virtual SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
+ KEY_PART *key_part,
+ Item_func::Functype type, Item *value);
public:
Item_bool_func() :Item_int_func() {}
Item_bool_func(Item *a) :Item_int_func(a) {}
@@ -1437,6 +1444,9 @@ protected:
DBUG_ENTER("Item_func_null_predicate::get_func_mm_tree");
DBUG_RETURN(get_mm_parts(param, field, functype(), value, cmp_type));
}
+ SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
+ KEY_PART *key_part,
+ Item_func::Functype type, Item *value);
public:
Item_func_null_predicate(Item *a) :Item_bool_func(a) { }
void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
@@ -1552,6 +1562,10 @@ class Item_func_like :public Item_bool_func2
DTCollation cmp_collation;
String cmp_value1, cmp_value2;
bool with_sargable_pattern() const;
+protected:
+ SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
+ KEY_PART *key_part,
+ Item_func::Functype type, Item *value);
public:
int escape;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index afb9dc6458c..3ff73bccaba 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -945,10 +945,6 @@ class TABLE_READ_PLAN;
struct st_index_scan_info;
struct st_ror_scan_info;
-static SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param,COND *cond_func,Field *field,
- KEY_PART *key_part,
- Item_func::Functype type,Item *value);
-
static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts);
static ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
SEL_ARG *tree, bool update_tbl_stats,
@@ -8235,7 +8231,19 @@ Item_bool_func::get_mm_parts(RANGE_OPT_PARAM *param, Field *field,
DBUG_RETURN(0); // OOM
if (!value || !(value->used_tables() & ~param->read_tables))
{
- sel_arg= get_mm_leaf(param,this,key_part->field,key_part,type,value);
+ /*
+ 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.
+ */
+ MEM_ROOT *tmp_root= param->mem_root;
+ param->thd->mem_root= param->old_root;
+ sel_arg= get_mm_leaf(param, key_part->field, key_part, type, value);
+ param->thd->mem_root= tmp_root;
+
if (!sel_arg)
continue;
if (sel_arg->type == SEL_ARG::IMPOSSIBLE)
@@ -8263,53 +8271,144 @@ Item_bool_func::get_mm_parts(RANGE_OPT_PARAM *param, Field *field,
}
-static SEL_ARG *
-get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
- KEY_PART *key_part, Item_func::Functype type,Item *value)
+SEL_ARG *
+Item_func_null_predicate::get_mm_leaf(RANGE_OPT_PARAM *param,
+ Field *field, KEY_PART *key_part,
+ Item_func::Functype type,
+ Item *value)
{
- uint maybe_null=(uint) field->real_maybe_null();
- bool optimize_range;
- SEL_ARG *tree= 0;
MEM_ROOT *alloc= param->mem_root;
- uchar *str;
- int err;
- DBUG_ENTER("get_mm_leaf");
+ DBUG_ENTER("Item_func_null_predicate::get_mm_leaf");
+ DBUG_ASSERT(!value);
+ /*
+ No check for field->table->maybe_null. It's perfecly fine to use range
+ access for cases like
+
+ SELECT * FROM t1 LEFT JOIN t2 ON t2.key IS [NOT] NULL
+
+ ON expression is evaluated before considering NULL-complemented rows, so
+ IS [NOT] NULL has regular semantics.
+ */
+ if (!field->real_maybe_null())
+ DBUG_RETURN(type == ISNULL_FUNC ? &null_element : NULL);
+ SEL_ARG *tree;
+ if (!(tree= new (alloc) SEL_ARG(field, is_null_string, is_null_string)))
+ DBUG_RETURN(0);
+ 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);
+}
+
+
+SEL_ARG *
+Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param,
+ Field *field, KEY_PART *key_part,
+ Item_func::Functype type, Item *value)
+{
+ DBUG_ENTER("Item_func_like::get_mm_leaf");
+ DBUG_ASSERT(value);
+
+ if (key_part->image_type != Field::itRAW)
+ DBUG_RETURN(0);
+
+ if (param->using_real_indexes &&
+ !field->optimize_range(param->real_keynr[key_part->key],
+ key_part->part))
+ DBUG_RETURN(0);
+
+ if (field->result_type() == STRING_RESULT &&
+ field->charset() != compare_collation())
+ DBUG_RETURN(0);
+
+ StringBuffer<MAX_FIELD_WIDTH> tmp(value->collation.collation);
+ String *res;
+
+ if (!(res= value->val_str(&tmp)))
+ DBUG_RETURN(&null_element);
+
+ if (field->cmp_type() != STRING_RESULT)
+ DBUG_RETURN(0);
/*
- 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.
+ TODO:
+ Check if this was a function. This should have be optimized away
+ in the sql_select.cc
*/
- param->thd->mem_root= param->old_root;
- if (!value) // IS NULL or IS NOT NULL
+ if (res != &tmp)
{
- /*
- No check for field->table->maybe_null. It's perfecly fine to use range
- access for cases like
+ tmp.copy(*res); // Get own copy
+ res= &tmp;
+ }
- SELECT * FROM t1 LEFT JOIN t2 ON t2.key IS [NOT] NULL
+ uint maybe_null= (uint) field->real_maybe_null();
+ uint field_length= field->pack_length() + maybe_null;
+ size_t offset= maybe_null;
+ size_t length= key_part->store_length;
- ON expression is evaluated before considering NULL-complemented rows, so
- IS [NOT] NULL has regular semantics.
- */
- if (!maybe_null) // Not null field
- {
- 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)
+ if (length != key_part->length + maybe_null)
+ {
+ /* key packed with length prefix */
+ offset+= HA_KEY_BLOB_LENGTH;
+ field_length= length - HA_KEY_BLOB_LENGTH;
+ }
+ else
+ {
+ if (unlikely(length < field_length))
{
- tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */
- tree->max_flag=NO_MAX_RANGE;
+ /*
+ This can only happen in a table created with UNIREG where one key
+ overlaps many fields
+ */
+ length= field_length;
}
- goto end;
+ else
+ field_length= length;
}
+ length+= offset;
+ uchar *min_str,*max_str;
+ if (!(min_str= (uchar*) alloc_root(param->mem_root, length*2)))
+ DBUG_RETURN(0);
+ max_str= min_str + length;
+ if (maybe_null)
+ max_str[0]= min_str[0]=0;
+
+ size_t min_length, max_length;
+ field_length-= maybe_null;
+ if (my_like_range(field->charset(),
+ res->ptr(), res->length(),
+ escape, wild_one, wild_many,
+ field_length,
+ (char*) min_str + offset,
+ (char*) max_str + offset,
+ &min_length, &max_length))
+ DBUG_RETURN(0); // Can't optimize with LIKE
+
+ if (offset != maybe_null) // BLOB or VARCHAR
+ {
+ int2store(min_str + maybe_null, min_length);
+ int2store(max_str + maybe_null, max_length);
+ }
+ SEL_ARG *tree= new (param->mem_root) SEL_ARG(field, min_str, max_str);
+ DBUG_RETURN(tree);
+}
+
+
+SEL_ARG *
+Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
+ Field *field, KEY_PART *key_part,
+ Item_func::Functype type, Item *value)
+{
+ uint maybe_null=(uint) field->real_maybe_null();
+ SEL_ARG *tree= 0;
+ MEM_ROOT *alloc= param->mem_root;
+ uchar *str;
+ int err;
+ DBUG_ENTER("Item_bool_func::get_mm_leaf");
+
+ DBUG_ASSERT(value); // IS NULL and IS NOT NULL are handled separately
/*
1. Usually we can't use an index if the column collation
@@ -8327,9 +8426,9 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
field->match_collation_to_optimize_range() &&
value->result_type() == STRING_RESULT &&
key_part->image_type == Field::itRAW &&
- field->charset() != conf_func->compare_collation() &&
- !((type == Item_func::EQUAL_FUNC || type == Item_func::EQ_FUNC) &&
- conf_func->compare_collation()->state & MY_CS_BINSORT))
+ field->charset() != compare_collation() &&
+ !((type == EQUAL_FUNC || type == EQ_FUNC) &&
+ compare_collation()->state & MY_CS_BINSORT))
goto end;
if (value->cmp_type() == TIME_RESULT && field->cmp_type() != TIME_RESULT)
goto end;
@@ -8338,14 +8437,14 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
{
// @todo: use is_spatial_operator() instead?
switch (type) {
- case Item_func::SP_EQUALS_FUNC:
- case Item_func::SP_DISJOINT_FUNC:
- case Item_func::SP_INTERSECTS_FUNC:
- case Item_func::SP_TOUCHES_FUNC:
- case Item_func::SP_CROSSES_FUNC:
- case Item_func::SP_WITHIN_FUNC:
- case Item_func::SP_CONTAINS_FUNC:
- case Item_func::SP_OVERLAPS_FUNC:
+ case SP_EQUALS_FUNC:
+ case SP_DISJOINT_FUNC:
+ case SP_INTERSECTS_FUNC:
+ case SP_TOUCHES_FUNC:
+ case SP_CROSSES_FUNC:
+ case SP_WITHIN_FUNC:
+ case SP_CONTAINS_FUNC:
+ case SP_OVERLAPS_FUNC:
break;
default:
/*
@@ -8356,95 +8455,11 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
}
}
- if (param->using_real_indexes)
- optimize_range= field->optimize_range(param->real_keynr[key_part->key],
- key_part->part);
- else
- optimize_range= TRUE;
-
- if (type == Item_func::LIKE_FUNC)
- {
- bool like_error;
- char buff1[MAX_FIELD_WIDTH];
- uchar *min_str,*max_str;
- String tmp(buff1,sizeof(buff1),value->collation.collation),*res;
- size_t length, offset, min_length, max_length;
- uint field_length= field->pack_length()+maybe_null;
-
- if (!optimize_range)
- goto end;
- if (!(res= value->val_str(&tmp)))
- {
- tree= &null_element;
- goto end;
- }
-
- /*
- TODO:
- Check if this was a function. This should have be optimized away
- in the sql_select.cc
- */
- if (res != &tmp)
- {
- tmp.copy(*res); // Get own copy
- res= &tmp;
- }
- if (field->cmp_type() != STRING_RESULT)
- goto end; // Can only optimize strings
-
- offset=maybe_null;
- length=key_part->store_length;
-
- if (length != key_part->length + maybe_null)
- {
- /* key packed with length prefix */
- offset+= HA_KEY_BLOB_LENGTH;
- field_length= length - HA_KEY_BLOB_LENGTH;
- }
- else
- {
- if (unlikely(length < field_length))
- {
- /*
- This can only happen in a table created with UNIREG where one key
- overlaps many fields
- */
- length= field_length;
- }
- else
- field_length= length;
- }
- length+=offset;
- if (!(min_str= (uchar*) alloc_root(alloc, length*2)))
- goto end;
-
- max_str=min_str+length;
- if (maybe_null)
- max_str[0]= min_str[0]=0;
-
- field_length-= maybe_null;
- like_error= my_like_range(field->charset(),
- res->ptr(), res->length(),
- ((Item_func_like*)(conf_func))->escape,
- wild_one, wild_many,
- field_length,
- (char*) min_str+offset, (char*) max_str+offset,
- &min_length, &max_length);
- if (like_error) // Can't optimize with LIKE
- goto end;
-
- if (offset != maybe_null) // BLOB or VARCHAR
- {
- int2store(min_str+maybe_null,min_length);
- int2store(max_str+maybe_null,max_length);
- }
- 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)
+ if (param->using_real_indexes &&
+ !field->optimize_range(param->real_keynr[key_part->key],
+ key_part->part) &&
+ type != EQ_FUNC &&
+ type != EQUAL_FUNC)
goto end; // Can't optimize this
/*
@@ -8456,7 +8471,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
err= value->save_in_field_no_warnings(field, 1);
if (err == 2 && field->cmp_type() == STRING_RESULT)
{
- if (type == Item_func::EQ_FUNC)
+ if (type == EQ_FUNC)
{
tree= new (alloc) SEL_ARG(field, 0, 0);
tree->type= SEL_ARG::IMPOSSIBLE;
@@ -8469,7 +8484,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
{
if (field->cmp_type() != value->result_type())
{
- if ((type == Item_func::EQ_FUNC || type == Item_func::EQUAL_FUNC) &&
+ if ((type == EQ_FUNC || type == EQUAL_FUNC) &&
value->result_type() == item_cmp_type(field->result_type(),
value->result_type()))
{
@@ -8485,8 +8500,8 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
*/
tree= 0;
if (err == 3 && field->type() == FIELD_TYPE_DATE &&
- (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC ||
- type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) )
+ (type == GT_FUNC || type == GE_FUNC ||
+ type == LT_FUNC || type == LE_FUNC) )
{
/*
We were saving DATETIME into a DATE column, the conversion went ok
@@ -8519,14 +8534,14 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
*/
else if (err == 1 && field->result_type() == INT_RESULT)
{
- if (type == Item_func::LT_FUNC && (value->val_int() > 0))
- type = Item_func::LE_FUNC;
- else if (type == Item_func::GT_FUNC &&
+ if (type == LT_FUNC && (value->val_int() > 0))
+ type= LE_FUNC;
+ else if (type == GT_FUNC &&
(field->type() != FIELD_TYPE_BIT) &&
!((Field_num*)field)->unsigned_flag &&
!((Item_int*)value)->unsigned_flag &&
(value->val_int() < 0))
- type = Item_func::GE_FUNC;
+ type= GE_FUNC;
}
}
else if (err < 0)
@@ -8540,7 +8555,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
Any sargable predicate except "<=>" involving NULL as a constant is always
FALSE
*/
- if (type != Item_func::EQUAL_FUNC && field->is_real_null())
+ if (type != EQUAL_FUNC && field->is_real_null())
{
tree= &null_element;
goto end;
@@ -8576,12 +8591,12 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
longlong item_val= value->val_int();
if (item_val < 0)
{
- if (type == Item_func::LT_FUNC || type == Item_func::LE_FUNC)
+ if (type == LT_FUNC || type == LE_FUNC)
{
tree->type= SEL_ARG::IMPOSSIBLE;
goto end;
}
- if (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC)
+ if (type == GT_FUNC || type == GE_FUNC)
{
tree= 0;
goto end;
@@ -8590,11 +8605,11 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
}
switch (type) {
- case Item_func::LT_FUNC:
+ case LT_FUNC:
if (stored_field_cmp_to_item(param->thd, field, value) == 0)
tree->max_flag=NEAR_MAX;
/* fall through */
- case Item_func::LE_FUNC:
+ case LE_FUNC:
if (!maybe_null)
tree->min_flag=NO_MIN_RANGE; /* From start */
else
@@ -8603,61 +8618,61 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
tree->min_flag=NEAR_MIN;
}
break;
- case Item_func::GT_FUNC:
+ case GT_FUNC:
/* Don't use open ranges for partial key_segments */
if ((!(key_part->flag & HA_PART_KEY_SEG)) &&
(stored_field_cmp_to_item(param->thd, field, value) <= 0))
tree->min_flag=NEAR_MIN;
tree->max_flag= NO_MAX_RANGE;
break;
- case Item_func::GE_FUNC:
+ case GE_FUNC:
/* Don't use open ranges for partial key_segments */
if ((!(key_part->flag & HA_PART_KEY_SEG)) &&
(stored_field_cmp_to_item(param->thd, field, value) < 0))
tree->min_flag= NEAR_MIN;
tree->max_flag=NO_MAX_RANGE;
break;
- case Item_func::SP_EQUALS_FUNC:
+ case SP_EQUALS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_EQUAL;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
- case Item_func::SP_DISJOINT_FUNC:
+ case SP_DISJOINT_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_DISJOINT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
- case Item_func::SP_INTERSECTS_FUNC:
+ case SP_INTERSECTS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
- case Item_func::SP_TOUCHES_FUNC:
+ case SP_TOUCHES_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
-
- case Item_func::SP_CROSSES_FUNC:
+ case SP_CROSSES_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
- case Item_func::SP_WITHIN_FUNC:
+ case SP_WITHIN_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_WITHIN;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
-
- case Item_func::SP_CONTAINS_FUNC:
+ case SP_CONTAINS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_CONTAIN;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
- case Item_func::SP_OVERLAPS_FUNC:
+ case SP_OVERLAPS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
-
+ case EQ_FUNC:
+ case EQUAL_FUNC:
+ break;
default:
+ DBUG_ASSERT(0);
break;
}
end:
- param->thd->mem_root= alloc;
DBUG_RETURN(tree);
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index c29b09a6359..2f108c1f6b5 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -38,7 +38,7 @@
class JOIN;
class Item_sum;
-typedef struct st_key_part {
+struct KEY_PART {
uint16 key,part;
/* See KEY_PART_INFO for meaning of the next two: */
uint16 store_length, length;
@@ -50,7 +50,7 @@ typedef struct st_key_part {
uint8 flag;
Field *field;
Field::imagetype image_type;
-} KEY_PART;
+};
class Explain_quick_select;
/*