Commit f781e154 authored by igor@olga.mysql.com's avatar igor@olga.mysql.com

Merge olga.mysql.com:/home/igor/mysql-5.0-opt

into  olga.mysql.com:/home/igor/dev-opt/mysql-5.0-opt-bug27545
parents c04d3727 be5485ce
...@@ -1213,4 +1213,16 @@ a b ...@@ -1213,4 +1213,16 @@ a b
3 2 3 2
1 1 1 1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (id int, type char(6), d int, INDEX idx(id,d)) ENGINE=InnoDB;
INSERT INTO t1 VALUES
(191, 'member', 1), (NULL, 'member', 3), (NULL, 'member', 4), (201, 'member', 2);
EXPLAIN SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL idx NULL NULL NULL 3 Using where; Using filesort
SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d;
id type d
191 member 1
NULL member 3
NULL member 4
DROP TABLE t1;
End of 5.0 tests End of 5.0 tests
...@@ -505,4 +505,59 @@ select sum(a) from t1 group by convert(a, datetime); ...@@ -505,4 +505,59 @@ select sum(a) from t1 group by convert(a, datetime);
sum(a) sum(a)
NULL NULL
drop table t1; drop table t1;
create table t1 (id int(10) not null, cur_date datetime not null);
create table t2 (id int(10) not null, cur_date date not null);
insert into t1 (id, cur_date) values (1, '2007-04-25 18:30:22');
insert into t2 (id, cur_date) values (1, '2007-04-25');
explain extended
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1276 Field or reference 'test.t1.cur_date' of SELECT #2 was resolved in SELECT #1
Note 1003 select '1' AS `id`,'2007-04-25 18:30:22' AS `cur_date` from `test`.`t1` where <in_optimizer>('1',<exists>(select 1 AS `Not_used` from `test`.`t1` `x1` where 0))
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
id cur_date
explain extended
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1276 Field or reference 'test.t2.cur_date' of SELECT #2 was resolved in SELECT #1
Note 1003 select '1' AS `id`,'2007-04-25' AS `cur_date` from `test`.`t2` where <in_optimizer>('1',<exists>(select 1 AS `Not_used` from `test`.`t2` `x1` where 0))
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
id cur_date
insert into t1 (id, cur_date) values (2, '2007-04-26 18:30:22');
insert into t2 (id, cur_date) values (2, '2007-04-26');
explain extended
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY x1 ALL NULL NULL NULL NULL 2 Using where
Warnings:
Note 1276 Field or reference 'test.t1.cur_date' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`cur_date` AS `cur_date` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`id`,<exists>(select 1 AS `Not_used` from `test`.`t1` `x1` where ((`test`.`t1`.`cur_date` = 0) and (<cache>(`test`.`t1`.`id`) = `test`.`x1`.`id`))))
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
id cur_date
explain extended
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY x1 ALL NULL NULL NULL NULL 2 Using where
Warnings:
Note 1276 Field or reference 'test.t2.cur_date' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t2`.`id` AS `id`,`test`.`t2`.`cur_date` AS `cur_date` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 AS `Not_used` from `test`.`t2` `x1` where ((`test`.`t2`.`cur_date` = 0) and (<cache>(`test`.`t2`.`id`) = `test`.`x1`.`id`))))
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
id cur_date
drop table t1,t2;
End of 5.0 tests End of 5.0 tests
...@@ -960,4 +960,19 @@ SELECT * FROM t1 ORDER BY b DESC, a ASC; ...@@ -960,4 +960,19 @@ SELECT * FROM t1 ORDER BY b DESC, a ASC;
DROP TABLE t1; DROP TABLE t1;
#
# Bug #32815: query with ORDER BY and a possible ref_or_null access
#
CREATE TABLE t1 (id int, type char(6), d int, INDEX idx(id,d)) ENGINE=InnoDB;
INSERT INTO t1 VALUES
(191, 'member', 1), (NULL, 'member', 3), (NULL, 'member', 4), (201, 'member', 2);
EXPLAIN SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d;
SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d;
DROP TABLE t1;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -338,4 +338,41 @@ insert into t1 values (), (), (); ...@@ -338,4 +338,41 @@ insert into t1 values (), (), ();
select sum(a) from t1 group by convert(a, datetime); select sum(a) from t1 group by convert(a, datetime);
drop table t1; drop table t1;
#
# Bug #32694: NOT NULL table field in a subquery produces invalid results
#
create table t1 (id int(10) not null, cur_date datetime not null);
create table t2 (id int(10) not null, cur_date date not null);
insert into t1 (id, cur_date) values (1, '2007-04-25 18:30:22');
insert into t2 (id, cur_date) values (1, '2007-04-25');
explain extended
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
explain extended
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
insert into t1 (id, cur_date) values (2, '2007-04-26 18:30:22');
insert into t2 (id, cur_date) values (2, '2007-04-26');
explain extended
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
explain extended
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
drop table t1,t2;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
#include <m_ctype.h> #include <m_ctype.h>
#include "sql_select.h" #include "sql_select.h"
static bool convert_constant_item(THD *thd, Field *field, Item **item); static bool convert_constant_item(THD *thd, Item_field *field_item,
Item **item);
static Item_result item_store_type(Item_result a, Item *item, static Item_result item_store_type(Item_result a, Item *item,
my_bool unsigned_flag) my_bool unsigned_flag)
...@@ -317,7 +318,7 @@ longlong Item_func_nop_all::val_int() ...@@ -317,7 +318,7 @@ longlong Item_func_nop_all::val_int()
SYNOPSIS SYNOPSIS
convert_constant_item() convert_constant_item()
thd thread handle thd thread handle
field item will be converted using the type of this field field_item item will be converted using the type of this field
item [in/out] reference to the item to convert item [in/out] reference to the item to convert
DESCRIPTION DESCRIPTION
...@@ -340,30 +341,46 @@ longlong Item_func_nop_all::val_int() ...@@ -340,30 +341,46 @@ longlong Item_func_nop_all::val_int()
1 Item was replaced with an integer version of the item 1 Item was replaced with an integer version of the item
*/ */
static bool convert_constant_item(THD *thd, Field *field, Item **item) static bool convert_constant_item(THD *thd, Item_field *field_item,
Item **item)
{ {
Field *field= field_item->field;
int result= 0;
if (!(*item)->with_subselect && (*item)->const_item()) if (!(*item)->with_subselect && (*item)->const_item())
{ {
/* For comparison purposes allow invalid dates like 2000-01-32 */ /* For comparison purposes allow invalid dates like 2000-01-32 */
ulong orig_sql_mode= thd->variables.sql_mode; ulong orig_sql_mode= thd->variables.sql_mode;
enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields;
ulonglong orig_field_val; /* original field value if valid */
thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) | thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) |
MODE_INVALID_DATES; MODE_INVALID_DATES;
thd->count_cuted_fields= CHECK_FIELD_IGNORE; thd->count_cuted_fields= CHECK_FIELD_IGNORE;
/*
Store the value of the field if it references an outer field because
the call to save_in_field below overrides that value.
*/
if (field_item->depended_from)
orig_field_val= field->val_int();
if (!(*item)->is_null() && !(*item)->save_in_field(field, 1)) if (!(*item)->is_null() && !(*item)->save_in_field(field, 1))
{ {
Item *tmp=new Item_int_with_ref(field->val_int(), *item, Item *tmp=new Item_int_with_ref(field->val_int(), *item,
test(field->flags & UNSIGNED_FLAG)); test(field->flags & UNSIGNED_FLAG));
thd->variables.sql_mode= orig_sql_mode;
thd->count_cuted_fields= orig_count_cuted_fields;
if (tmp) if (tmp)
thd->change_item_tree(item, tmp); thd->change_item_tree(item, tmp);
return 1; // Item was replaced result= 1; // Item was replaced
}
/* Restore the original field value. */
if (field_item->depended_from)
{
result= field->store(orig_field_val, TRUE);
/* orig_field_val must be a valid value that can be restored back. */
DBUG_ASSERT(!result);
} }
thd->variables.sql_mode= orig_sql_mode; thd->variables.sql_mode= orig_sql_mode;
thd->count_cuted_fields= orig_count_cuted_fields; thd->count_cuted_fields= orig_count_cuted_fields;
} }
return 0; return result;
} }
...@@ -411,15 +428,14 @@ void Item_bool_func2::fix_length_and_dec() ...@@ -411,15 +428,14 @@ void Item_bool_func2::fix_length_and_dec()
thd= current_thd; thd= current_thd;
if (!thd->is_context_analysis_only()) if (!thd->is_context_analysis_only())
{ {
Item *arg_real_item= args[0]->real_item(); if (args[0]->real_item()->type() == FIELD_ITEM)
if (arg_real_item->type() == FIELD_ITEM)
{ {
Field *field=((Item_field*) arg_real_item)->field; Item_field *field_item= (Item_field*) (args[0]->real_item());
if (field->can_be_compared_as_longlong() && if (field_item->field->can_be_compared_as_longlong() &&
!(arg_real_item->is_datetime() && !(field_item->is_datetime() &&
args[1]->result_type() == STRING_RESULT)) args[1]->result_type() == STRING_RESULT))
{ {
if (convert_constant_item(thd, field,&args[1])) if (convert_constant_item(thd, field_item, &args[1]))
{ {
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types. INT_RESULT); // Works for all types.
...@@ -428,15 +444,14 @@ void Item_bool_func2::fix_length_and_dec() ...@@ -428,15 +444,14 @@ void Item_bool_func2::fix_length_and_dec()
} }
} }
} }
arg_real_item= args[1]->real_item(); if (args[1]->real_item()->type() == FIELD_ITEM)
if (arg_real_item->type() == FIELD_ITEM)
{ {
Field *field=((Item_field*) arg_real_item)->field; Item_field *field_item= (Item_field*) (args[1]->real_item());
if (field->can_be_compared_as_longlong() && if (field_item->field->can_be_compared_as_longlong() &&
!(arg_real_item->is_datetime() && !(field_item->is_datetime() &&
args[0]->result_type() == STRING_RESULT)) args[0]->result_type() == STRING_RESULT))
{ {
if (convert_constant_item(thd, field,&args[0])) if (convert_constant_item(thd, field_item, &args[0]))
{ {
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types. INT_RESULT); // Works for all types.
...@@ -1889,16 +1904,16 @@ void Item_func_between::fix_length_and_dec() ...@@ -1889,16 +1904,16 @@ void Item_func_between::fix_length_and_dec()
thd->lex->sql_command != SQLCOM_CREATE_VIEW && thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
thd->lex->sql_command != SQLCOM_SHOW_CREATE) thd->lex->sql_command != SQLCOM_SHOW_CREATE)
{ {
Field *field=((Item_field*) (args[0]->real_item()))->field; Item_field *field_item= (Item_field*) (args[0]->real_item());
if (field->can_be_compared_as_longlong()) if (field_item->field->can_be_compared_as_longlong())
{ {
/* /*
The following can't be recoded with || as convert_constant_item The following can't be recoded with || as convert_constant_item
changes the argument changes the argument
*/ */
if (convert_constant_item(thd, field,&args[1])) if (convert_constant_item(thd, field_item, &args[1]))
cmp_type=INT_RESULT; // Works for all types. cmp_type=INT_RESULT; // Works for all types.
if (convert_constant_item(thd, field,&args[2])) if (convert_constant_item(thd, field_item, &args[2]))
cmp_type=INT_RESULT; // Works for all types. cmp_type=INT_RESULT; // Works for all types.
} }
} }
...@@ -3491,13 +3506,13 @@ void Item_func_in::fix_length_and_dec() ...@@ -3491,13 +3506,13 @@ void Item_func_in::fix_length_and_dec()
thd->lex->sql_command != SQLCOM_SHOW_CREATE && thd->lex->sql_command != SQLCOM_SHOW_CREATE &&
cmp_type != INT_RESULT) cmp_type != INT_RESULT)
{ {
Field *field= ((Item_field*) (args[0]->real_item()))->field; Item_field *field_item= (Item_field*) (args[0]->real_item());
if (field->can_be_compared_as_longlong()) if (field_item->field->can_be_compared_as_longlong())
{ {
bool all_converted= TRUE; bool all_converted= TRUE;
for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++) for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
{ {
if (!convert_constant_item (thd, field, &arg[0])) if (!convert_constant_item (thd, field_item, &arg[0]))
all_converted= FALSE; all_converted= FALSE;
} }
if (all_converted) if (all_converted)
......
...@@ -3691,7 +3691,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, ...@@ -3691,7 +3691,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
found_eq_constant=0; found_eq_constant=0;
for (i=0 ; i < keyuse->elements-1 ; i++,use++) for (i=0 ; i < keyuse->elements-1 ; i++,use++)
{ {
if (!use->used_tables) if (!use->used_tables && use->optimize != KEY_OPTIMIZE_REF_OR_NULL)
use->table->const_key_parts[use->key]|= use->keypart_map; use->table->const_key_parts[use->key]|= use->keypart_map;
if (use->keypart != FT_KEYPART) if (use->keypart != FT_KEYPART)
{ {
......
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