Commit cf3b913d authored by unknown's avatar unknown

Merge rkalimullin@bk-internal.mysql.com:/home/bk/mysql-4.1

into gw.mysql.r18.ru:/usr/home/ram/work/4.1.b2419


sql/opt_range.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
parents 41946dc6 02fbe775
...@@ -541,3 +541,50 @@ s2 CHAR(5) COLLATE latin1_swedish_ci); ...@@ -541,3 +541,50 @@ s2 CHAR(5) COLLATE latin1_swedish_ci);
SELECT * FROM t1 WHERE s1 = s2; SELECT * FROM t1 WHERE s1 = s2;
ERROR HY000: Illegal mix of collations (latin1_german1_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation '=' ERROR HY000: Illegal mix of collations (latin1_german1_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation '='
DROP TABLE t1; DROP TABLE t1;
SET NAMES latin1;
CREATE TABLE t1
(s1 char(10) COLLATE latin1_german1_ci,
s2 char(10) COLLATE latin1_swedish_ci,
KEY(s1),
KEY(s2));
INSERT INTO t1 VALUES ('a','a');
INSERT INTO t1 VALUES ('b','b');
INSERT INTO t1 VALUES ('c','c');
INSERT INTO t1 VALUES ('d','d');
INSERT INTO t1 VALUES ('e','e');
INSERT INTO t1 VALUES ('f','f');
INSERT INTO t1 VALUES ('g','g');
INSERT INTO t1 VALUES ('h','h');
INSERT INTO t1 VALUES ('i','i');
INSERT INTO t1 VALUES ('j','j');
EXPLAIN SELECT * FROM t1 WHERE s1='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref s1 s1 11 const 1 Using where
EXPLAIN SELECT * FROM t1 WHERE s2='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref s2 s2 11 const 1 Using where
EXPLAIN SELECT * FROM t1 WHERE s1='a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref s1 s1 11 const 1 Using where
EXPLAIN SELECT * FROM t1 WHERE s2='a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
EXPLAIN SELECT * FROM t1 WHERE s1 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range s1 s1 11 NULL 2 Using where
EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
EXPLAIN SELECT * FROM t1 WHERE s1 IN ('a','b' COLLATE latin1_german1_ci);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range s1 s1 11 NULL 2 Using where
EXPLAIN SELECT * FROM t1 WHERE s2 IN ('a','b' COLLATE latin1_german1_ci);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range s1 s1 11 NULL 1 Using where
EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
DROP TABLE t1;
...@@ -100,7 +100,7 @@ p i a ...@@ -100,7 +100,7 @@ p i a
4 3 zzzz 4 3 zzzz
update t1 set p=2 where p=1; update t1 set p=2 where p=1;
update t2 set i=2 where i=1; update t2 set i=2 where i=1;
cache index t1 keys (`primary`) in keycache1; cache index t1 key (`primary`) in keycache1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 assign_to_keycache status OK test.t1 assign_to_keycache status OK
explain select p from t1; explain select p from t1;
...@@ -177,7 +177,7 @@ yyyy ...@@ -177,7 +177,7 @@ yyyy
zzzz zzzz
cache index t1 in unknown_key_cache; cache index t1 in unknown_key_cache;
ERROR HY000: Unknown key cache 'unknown_key_cache' ERROR HY000: Unknown key cache 'unknown_key_cache'
cache index t1 keys (unknown_key) in keycache1; cache index t1 key (unknown_key) in keycache1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 assign_to_keycache error Key column 'unknown_key' doesn't exist in table test.t1 assign_to_keycache error Key column 'unknown_key' doesn't exist in table
test.t1 assign_to_keycache status Operation failed test.t1 assign_to_keycache status Operation failed
......
...@@ -117,7 +117,7 @@ set session preload_buffer_size=1*1024; ...@@ -117,7 +117,7 @@ set session preload_buffer_size=1*1024;
select @@preload_buffer_size; select @@preload_buffer_size;
@@preload_buffer_size @@preload_buffer_size
1024 1024
load index into cache t1, t2 keys (primary,b) ignore leaves; load index into cache t1, t2 key (primary,b) ignore leaves;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 preload_keys status OK test.t1 preload_keys status OK
test.t2 preload_keys status OK test.t2 preload_keys status OK
...@@ -141,7 +141,7 @@ show status like "key_read%"; ...@@ -141,7 +141,7 @@ show status like "key_read%";
Variable_name Value Variable_name Value
Key_read_requests 0 Key_read_requests 0
Key_reads 0 Key_reads 0
load index into cache t3, t2 keys (primary,b) ; load index into cache t3, t2 key (primary,b) ;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t3 preload_keys error Table 'test.t3' doesn't exist test.t3 preload_keys error Table 'test.t3' doesn't exist
test.t2 preload_keys status OK test.t2 preload_keys status OK
...@@ -155,7 +155,7 @@ show status like "key_read%"; ...@@ -155,7 +155,7 @@ show status like "key_read%";
Variable_name Value Variable_name Value
Key_read_requests 0 Key_read_requests 0
Key_reads 0 Key_reads 0
load index into cache t3 keys (b), t2 keys (c) ; load index into cache t3 key (b), t2 key (c) ;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t3 preload_keys error Table 'test.t3' doesn't exist test.t3 preload_keys error Table 'test.t3' doesn't exist
test.t2 preload_keys error Key column 'c' doesn't exist in table test.t2 preload_keys error Key column 'c' doesn't exist in table
......
...@@ -156,3 +156,41 @@ CREATE TABLE t1 ...@@ -156,3 +156,41 @@ CREATE TABLE t1
--error 1266 --error 1266
SELECT * FROM t1 WHERE s1 = s2; SELECT * FROM t1 WHERE s1 = s2;
DROP TABLE t1; DROP TABLE t1;
#
# Test that optimizer doesn't use indexes with wrong collation
#
SET NAMES latin1;
CREATE TABLE t1
(s1 char(10) COLLATE latin1_german1_ci,
s2 char(10) COLLATE latin1_swedish_ci,
KEY(s1),
KEY(s2));
INSERT INTO t1 VALUES ('a','a');
INSERT INTO t1 VALUES ('b','b');
INSERT INTO t1 VALUES ('c','c');
INSERT INTO t1 VALUES ('d','d');
INSERT INTO t1 VALUES ('e','e');
INSERT INTO t1 VALUES ('f','f');
INSERT INTO t1 VALUES ('g','g');
INSERT INTO t1 VALUES ('h','h');
INSERT INTO t1 VALUES ('i','i');
INSERT INTO t1 VALUES ('j','j');
EXPLAIN SELECT * FROM t1 WHERE s1='a';
EXPLAIN SELECT * FROM t1 WHERE s2='a';
EXPLAIN SELECT * FROM t1 WHERE s1='a' COLLATE latin1_german1_ci;
EXPLAIN SELECT * FROM t1 WHERE s2='a' COLLATE latin1_german1_ci;
EXPLAIN SELECT * FROM t1 WHERE s1 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
EXPLAIN SELECT * FROM t1 WHERE s1 IN ('a','b' COLLATE latin1_german1_ci);
EXPLAIN SELECT * FROM t1 WHERE s2 IN ('a','b' COLLATE latin1_german1_ci);
EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci;
EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci;
DROP TABLE t1;
...@@ -75,7 +75,7 @@ select * from t2; ...@@ -75,7 +75,7 @@ select * from t2;
update t1 set p=2 where p=1; update t1 set p=2 where p=1;
update t2 set i=2 where i=1; update t2 set i=2 where i=1;
cache index t1 keys (`primary`) in keycache1; cache index t1 key (`primary`) in keycache1;
explain select p from t1; explain select p from t1;
select p from t1; select p from t1;
...@@ -101,7 +101,7 @@ select a from t2; ...@@ -101,7 +101,7 @@ select a from t2;
# Test some error conditions # Test some error conditions
--error 1283 --error 1283
cache index t1 in unknown_key_cache; cache index t1 in unknown_key_cache;
cache index t1 keys (unknown_key) in keycache1; cache index t1 key (unknown_key) in keycache1;
select @@keycache2.key_buffer_size; select @@keycache2.key_buffer_size;
select @@keycache2.key_cache_block_size; select @@keycache2.key_cache_block_size;
......
...@@ -81,7 +81,7 @@ flush tables; flush status; ...@@ -81,7 +81,7 @@ flush tables; flush status;
show status like "key_read%"; show status like "key_read%";
set session preload_buffer_size=1*1024; set session preload_buffer_size=1*1024;
select @@preload_buffer_size; select @@preload_buffer_size;
load index into cache t1, t2 keys (primary,b) ignore leaves; load index into cache t1, t2 key (primary,b) ignore leaves;
show status like "key_read%"; show status like "key_read%";
select count(*) from t1 where b = 'test1'; select count(*) from t1 where b = 'test1';
select count(*) from t2 where b = 'test1'; select count(*) from t2 where b = 'test1';
...@@ -89,12 +89,12 @@ show status like "key_read%"; ...@@ -89,12 +89,12 @@ show status like "key_read%";
flush tables; flush status; flush tables; flush status;
show status like "key_read%"; show status like "key_read%";
load index into cache t3, t2 keys (primary,b) ; load index into cache t3, t2 key (primary,b) ;
show status like "key_read%"; show status like "key_read%";
flush tables; flush status; flush tables; flush status;
show status like "key_read%"; show status like "key_read%";
load index into cache t3 keys (b), t2 keys (c) ; load index into cache t3 key (b), t2 key (c) ;
show status like "key_read%"; show status like "key_read%";
drop table t1, t2; drop table t1, t2;
...@@ -204,6 +204,7 @@ class Item { ...@@ -204,6 +204,7 @@ class Item {
virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); } virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
CHARSET_INFO *default_charset() const; CHARSET_INFO *default_charset() const;
virtual CHARSET_INFO *compare_collation() { return NULL; }
virtual bool walk(Item_processor processor, byte *arg) virtual bool walk(Item_processor processor, byte *arg)
{ {
......
...@@ -191,6 +191,7 @@ class Item_bool_func2 :public Item_int_func ...@@ -191,6 +191,7 @@ class Item_bool_func2 :public Item_int_func
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; } bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
void print(String *str) { Item_func::print_op(str); } void print(String *str) { Item_func::print_op(str); }
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); } bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
friend class Arg_comparator; friend class Arg_comparator;
}; };
...@@ -340,6 +341,7 @@ class Item_func_between :public Item_int_func ...@@ -340,6 +341,7 @@ class Item_func_between :public Item_int_func
const char *func_name() const { return "between"; } const char *func_name() const { return "between"; }
void fix_length_and_dec(); void fix_length_and_dec();
void print(String *str); void print(String *str);
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
}; };
...@@ -479,6 +481,7 @@ class Item_func_case :public Item_func ...@@ -479,6 +481,7 @@ class Item_func_case :public Item_func
const char *func_name() const { return "case"; } const char *func_name() const { return "case"; }
void print(String *str); void print(String *str);
Item *find_item(String *str); Item *find_item(String *str);
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
}; };
...@@ -726,6 +729,7 @@ class Item_func_in :public Item_int_func ...@@ -726,6 +729,7 @@ class Item_func_in :public Item_int_func
enum Functype functype() const { return IN_FUNC; } enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; } const char *func_name() const { return " IN "; }
bool nulls_in_row(); bool nulls_in_row();
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
}; };
/* Functions used by where clause */ /* Functions used by where clause */
...@@ -766,6 +770,7 @@ class Item_func_isnull :public Item_bool_func ...@@ -766,6 +770,7 @@ class Item_func_isnull :public Item_bool_func
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
optimize_type select_optimize() const { return OPTIMIZE_NULL; } optimize_type select_optimize() const { return OPTIMIZE_NULL; }
Item *neg_transformer(); Item *neg_transformer();
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
}; };
/* Functions used by HAVING for rewriting IN subquery */ /* Functions used by HAVING for rewriting IN subquery */
...@@ -800,6 +805,7 @@ class Item_func_isnotnull :public Item_bool_func ...@@ -800,6 +805,7 @@ class Item_func_isnotnull :public Item_bool_func
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
Item *neg_transformer(); Item *neg_transformer();
void print(String *str); void print(String *str);
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
}; };
...@@ -854,6 +860,7 @@ class Item_func_regex :public Item_bool_func ...@@ -854,6 +860,7 @@ class Item_func_regex :public Item_bool_func
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
const char *func_name() const { return "regexp"; } const char *func_name() const { return "regexp"; }
void print(String *str) { print_op(str); } void print(String *str) { print_op(str); }
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
}; };
#else #else
......
...@@ -291,10 +291,11 @@ typedef struct st_qsel_param { ...@@ -291,10 +291,11 @@ typedef struct st_qsel_param {
bool quick; // Don't calulate possible keys bool quick; // Don't calulate possible keys
} PARAM; } PARAM;
static SEL_TREE * get_mm_parts(PARAM *param,Field *field, static SEL_TREE * get_mm_parts(PARAM *param,COND *cond_func,Field *field,
Item_func::Functype type,Item *value, Item_func::Functype type,Item *value,
Item_result cmp_type); Item_result cmp_type);
static SEL_ARG *get_mm_leaf(PARAM *param,Field *field,KEY_PART *key_part, static SEL_ARG *get_mm_leaf(PARAM *param,COND *cond_func,Field *field,
KEY_PART *key_part,
Item_func::Functype type,Item *value); Item_func::Functype type,Item *value);
static SEL_TREE *get_mm_tree(PARAM *param,COND *cond); static SEL_TREE *get_mm_tree(PARAM *param,COND *cond);
static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree); static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree);
...@@ -834,10 +835,10 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) ...@@ -834,10 +835,10 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
Field *field=((Item_field*) (cond_func->arguments()[0]))->field; Field *field=((Item_field*) (cond_func->arguments()[0]))->field;
Item_result cmp_type=field->cmp_type(); Item_result cmp_type=field->cmp_type();
DBUG_RETURN(tree_and(param, DBUG_RETURN(tree_and(param,
get_mm_parts(param, field, get_mm_parts(param, cond_func, field,
Item_func::GE_FUNC, Item_func::GE_FUNC,
cond_func->arguments()[1], cmp_type), cond_func->arguments()[1], cmp_type),
get_mm_parts(param, field, get_mm_parts(param, cond_func, field,
Item_func::LE_FUNC, Item_func::LE_FUNC,
cond_func->arguments()[2], cmp_type))); cond_func->arguments()[2], cmp_type)));
} }
...@@ -850,13 +851,14 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) ...@@ -850,13 +851,14 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
{ {
Field *field=((Item_field*) (func->key_item()))->field; Field *field=((Item_field*) (func->key_item()))->field;
Item_result cmp_type=field->cmp_type(); Item_result cmp_type=field->cmp_type();
tree= get_mm_parts(param,field,Item_func::EQ_FUNC, tree= get_mm_parts(param,cond_func,field,Item_func::EQ_FUNC,
func->arguments()[1],cmp_type); func->arguments()[1],cmp_type);
if (!tree) if (!tree)
DBUG_RETURN(tree); // Not key field DBUG_RETURN(tree); // Not key field
for (uint i=2 ; i < func->argument_count(); i++) for (uint i=2 ; i < func->argument_count(); i++)
{ {
SEL_TREE *new_tree=get_mm_parts(param,field,Item_func::EQ_FUNC, SEL_TREE *new_tree=get_mm_parts(param,cond_func,field,
Item_func::EQ_FUNC,
func->arguments()[i],cmp_type); func->arguments()[i],cmp_type);
tree=tree_or(param,tree,new_tree); tree=tree_or(param,tree,new_tree);
} }
...@@ -875,7 +877,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) ...@@ -875,7 +877,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
/* btw, ft_func's arguments()[0] isn't FIELD_ITEM. SerG*/ /* btw, ft_func's arguments()[0] isn't FIELD_ITEM. SerG*/
if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM) if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
{ {
tree= get_mm_parts(param, tree= get_mm_parts(param, cond_func,
((Item_field*) (cond_func->arguments()[0]))->field, ((Item_field*) (cond_func->arguments()[0]))->field,
cond_func->functype(), cond_func->functype(),
cond_func->arg_count > 1 ? cond_func->arguments()[1] : cond_func->arg_count > 1 ? cond_func->arguments()[1] :
...@@ -888,7 +890,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) ...@@ -888,7 +890,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
cond_func->have_rev_func() && cond_func->have_rev_func() &&
cond_func->arguments()[1]->type() == Item::FIELD_ITEM) cond_func->arguments()[1]->type() == Item::FIELD_ITEM)
{ {
DBUG_RETURN(get_mm_parts(param, DBUG_RETURN(get_mm_parts(param, cond_func,
((Item_field*) ((Item_field*)
(cond_func->arguments()[1]))->field, (cond_func->arguments()[1]))->field,
((Item_bool_func2*) cond_func)->rev_functype(), ((Item_bool_func2*) cond_func)->rev_functype(),
...@@ -902,7 +904,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) ...@@ -902,7 +904,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
static SEL_TREE * static SEL_TREE *
get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, get_mm_parts(PARAM *param, COND *cond_func, Field *field,
Item_func::Functype type,
Item *value, Item_result cmp_type) Item *value, Item_result cmp_type)
{ {
bool ne_func= FALSE; bool ne_func= FALSE;
...@@ -931,7 +934,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, ...@@ -931,7 +934,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
DBUG_RETURN(0); // OOM DBUG_RETURN(0); // OOM
if (!value || !(value->used_tables() & ~param->read_tables)) if (!value || !(value->used_tables() & ~param->read_tables))
{ {
sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value); sel_arg=get_mm_leaf(param,cond_func,
key_part->field,key_part,type,value);
if (!sel_arg) if (!sel_arg)
continue; continue;
if (sel_arg->type == SEL_ARG::IMPOSSIBLE) if (sel_arg->type == SEL_ARG::IMPOSSIBLE)
...@@ -953,7 +957,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, ...@@ -953,7 +957,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
if (ne_func) if (ne_func)
{ {
SEL_TREE *tree2= get_mm_parts(param, field, Item_func::GT_FUNC, SEL_TREE *tree2= get_mm_parts(param, cond_func,
field, Item_func::GT_FUNC,
value, cmp_type); value, cmp_type);
if (tree2) if (tree2)
tree= tree_or(param,tree,tree2); tree= tree_or(param,tree,tree2);
...@@ -963,7 +968,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, ...@@ -963,7 +968,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
static SEL_ARG * static SEL_ARG *
get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
Item_func::Functype type,Item *value) Item_func::Functype type,Item *value)
{ {
uint maybe_null=(uint) field->real_maybe_null(), copies; uint maybe_null=(uint) field->real_maybe_null(), copies;
...@@ -972,6 +977,32 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, ...@@ -972,6 +977,32 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
char *str, *str2; char *str, *str2;
DBUG_ENTER("get_mm_leaf"); DBUG_ENTER("get_mm_leaf");
if (!value) // IS NULL or IS NOT NULL
{
if (field->table->outer_join) // Can't use a key on this
DBUG_RETURN(0);
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::ISNOTNULL_FUNC)
{
tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */
tree->max_flag=NO_MAX_RANGE;
}
DBUG_RETURN(tree);
}
/*
We can't use an index when comparing stings of
different collations
*/
if (field->result_type() == STRING_RESULT &&
value->result_type() == STRING_RESULT &&
key_part->image_type == Field::itRAW &&
((Field_str*)field)->charset() != conf_func->compare_collation())
DBUG_RETURN(0);
if (type == Item_func::LIKE_FUNC) if (type == Item_func::LIKE_FUNC)
{ {
bool like_error; bool like_error;
...@@ -1035,22 +1066,6 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, ...@@ -1035,22 +1066,6 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
DBUG_RETURN(new SEL_ARG(field,min_str,max_str)); DBUG_RETURN(new SEL_ARG(field,min_str,max_str));
} }
if (!value) // IS NULL or IS NOT NULL
{
if (field->table->outer_join) // Can't use a key on this
DBUG_RETURN(0);
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::ISNOTNULL_FUNC)
{
tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */
tree->max_flag=NO_MAX_RANGE;
}
DBUG_RETURN(tree);
}
if (!field->optimize_range(param->real_keynr[key_part->key]) && if (!field->optimize_range(param->real_keynr[key_part->key]) &&
type != Item_func::EQ_FUNC && type != Item_func::EQ_FUNC &&
type != Item_func::EQUAL_FUNC) type != Item_func::EQUAL_FUNC)
...@@ -1064,7 +1079,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, ...@@ -1064,7 +1079,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
value->result_type() != STRING_RESULT && value->result_type() != STRING_RESULT &&
field->cmp_type() != value->result_type()) field->cmp_type() != value->result_type())
DBUG_RETURN(0); DBUG_RETURN(0);
if (value->save_in_field(field, 1) > 0) if (value->save_in_field(field, 1) > 0)
{ {
/* This happens when we try to insert a NULL field in a not null column */ /* This happens when we try to insert a NULL field in a not null column */
......
...@@ -2133,7 +2133,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, ...@@ -2133,7 +2133,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
*/ */
static void static void
add_key_field(KEY_FIELD **key_fields,uint and_level, add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond,
Field *field,bool eq_func,Item **value, uint num_values, Field *field,bool eq_func,Item **value, uint num_values,
table_map usable_tables) table_map usable_tables)
{ {
...@@ -2200,6 +2200,17 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, ...@@ -2200,6 +2200,17 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
(*value)->result_type() != STRING_RESULT && (*value)->result_type() != STRING_RESULT &&
field->cmp_type() != (*value)->result_type()) field->cmp_type() != (*value)->result_type())
return; return;
/*
We can't use indexes if the effective collation
of the operation differ from the field collation.
*/
if (field->result_type() == STRING_RESULT &&
(*value)->result_type() == STRING_RESULT &&
field->cmp_type() == STRING_RESULT &&
((Field_str*)field)->charset() != cond->compare_collation())
return;
} }
} }
DBUG_ASSERT(num_values == 1); DBUG_ASSERT(num_values == 1);
...@@ -2263,7 +2274,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, ...@@ -2263,7 +2274,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
// BETWEEN or IN // BETWEEN or IN
if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM && if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT)) !(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
add_key_field(key_fields,*and_level, add_key_field(key_fields,*and_level,cond_func,
((Item_field*) (cond_func->key_item()->real_item()))-> ((Item_field*) (cond_func->key_item()->real_item()))->
field, 0, field, 0,
cond_func->arguments()+1, cond_func->argument_count()-1, cond_func->arguments()+1, cond_func->argument_count()-1,
...@@ -2277,7 +2288,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, ...@@ -2277,7 +2288,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM && if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT)) !(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
{ {
add_key_field(key_fields,*and_level, add_key_field(key_fields,*and_level,cond_func,
((Item_field*) (cond_func->arguments()[0])->real_item()) ((Item_field*) (cond_func->arguments()[0])->real_item())
->field, ->field,
equal_func, equal_func,
...@@ -2287,7 +2298,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, ...@@ -2287,7 +2298,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
cond_func->functype() != Item_func::LIKE_FUNC && cond_func->functype() != Item_func::LIKE_FUNC &&
!(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT)) !(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT))
{ {
add_key_field(key_fields,*and_level, add_key_field(key_fields,*and_level,cond_func,
((Item_field*) (cond_func->arguments()[1])->real_item()) ((Item_field*) (cond_func->arguments()[1])->real_item())
->field, ->field,
equal_func, equal_func,
...@@ -2303,7 +2314,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, ...@@ -2303,7 +2314,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
Item *tmp=new Item_null; Item *tmp=new Item_null;
if (!tmp) // Should never be true if (!tmp) // Should never be true
return; return;
add_key_field(key_fields,*and_level, add_key_field(key_fields,*and_level,cond_func,
((Item_field*) (cond_func->arguments()[0])->real_item()) ((Item_field*) (cond_func->arguments()[0])->real_item())
->field, ->field,
cond_func->functype() == Item_func::ISNULL_FUNC, cond_func->functype() == Item_func::ISNULL_FUNC,
......
...@@ -1615,11 +1615,6 @@ opt_key_or_index: ...@@ -1615,11 +1615,6 @@ opt_key_or_index:
| key_or_index | key_or_index
; ;
opt_keys_or_index:
/* empty */ {}
| keys_or_index
;
keys_or_index: keys_or_index:
KEYS {} KEYS {}
| INDEX {} | INDEX {}
...@@ -2120,7 +2115,7 @@ cache_keys_spec: ...@@ -2120,7 +2115,7 @@ cache_keys_spec:
cache_key_list_or_empty: cache_key_list_or_empty:
/* empty */ { Lex->select_lex.use_index_ptr= 0; } /* empty */ { Lex->select_lex.use_index_ptr= 0; }
| opt_keys_or_index '(' key_usage_list2 ')' | opt_key_or_index '(' key_usage_list2 ')'
{ {
SELECT_LEX *sel= &Lex->select_lex; SELECT_LEX *sel= &Lex->select_lex;
sel->use_index_ptr= &sel->use_index; sel->use_index_ptr= &sel->use_index;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment