Commit 6020281e authored by unknown's avatar unknown

Fix bug#14186 select datefield is null not updated

Date field was declared as not null, thus expression 'datefield is null'
was always false. For SELECT special handling of such cases is used. 
There 'datefield is null' converted to 'datefield eq "0000-00-00"'.

In mysql_update() before creation of select added remove_eq_conds() call.
It makes some optimization of conds and in particular performs conversion
from 'is null' to 'eq'. 
Also remove_eq_conds() makes some evaluation of conds and if it founds that
conds is always false then update statement is not processed further.
All this allows to perform some update statements process faster due to
optimized conds, and not wasting resources if conds known to be false. 


sql/sql_select.cc:
  Fix bug#14186  select datefield is null not updated
  Remove static from remove_eq_conds()
sql/sql_select.h:
   Fix bug#14186  select datefield is null not updated
  Added remove_eq_conds() prototype.
mysql-test/r/update.result:
  Test case for  bug#14186  select datefield is null not updated
mysql-test/t/update.test:
  Test case for  bug#14186  select datefield is null not updated
sql/sql_update.cc:
  Fix bug#14186  select datefield is null not updated
  To mysql_update() added call to remove_eq_conds() to optimize conds and convert 'datefield is null' to 'datefield eq 0000-00-00'
parent fe90e567
...@@ -337,3 +337,11 @@ a b ...@@ -337,3 +337,11 @@ a b
22 3 22 3
23 3 23 3
drop table t1; drop table t1;
create table t1 (f1 date not null);
insert into t1 values('2000-01-01'),('0000-00-00');
update t1 set f1='2002-02-02' where f1 is null;
select * from t1;
f1
2000-01-01
2002-02-02
drop table t1;
...@@ -260,5 +260,14 @@ update t1 set a=a+11,b=2 order by a limit 3; ...@@ -260,5 +260,14 @@ update t1 set a=a+11,b=2 order by a limit 3;
update t1 set a=a+12,b=3 order by a limit 3; update t1 set a=a+12,b=3 order by a limit 3;
select * from t1 order by a; select * from t1 order by a;
drop table t1;
#
# Bug#14186 select datefield is null not updated
#
create table t1 (f1 date not null);
insert into t1 values('2000-01-01'),('0000-00-00');
update t1 set f1='2002-02-02' where f1 is null;
select * from t1;
drop table t1; drop table t1;
# End of 4.1 tests # End of 4.1 tests
...@@ -69,8 +69,6 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables, ...@@ -69,8 +69,6 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
SELECT_LEX_UNIT *unit); SELECT_LEX_UNIT *unit);
static COND *optimize_cond(THD *thd, COND *conds, static COND *optimize_cond(THD *thd, COND *conds,
Item::cond_result *cond_value); Item::cond_result *cond_value);
static COND *remove_eq_conds(THD *thd, COND *cond,
Item::cond_result *cond_value);
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool open_tmp_table(TABLE *table); static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
...@@ -4611,7 +4609,7 @@ optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value) ...@@ -4611,7 +4609,7 @@ optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value)
COND_FALSE always false ( 1 = 2 ) COND_FALSE always false ( 1 = 2 )
*/ */
static COND * COND *
remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
{ {
if (cond->type() == Item::COND_ITEM) if (cond->type() == Item::COND_ITEM)
......
...@@ -456,3 +456,4 @@ bool cp_buffer_from_ref(THD *thd, TABLE_REF *ref); ...@@ -456,3 +456,4 @@ bool cp_buffer_from_ref(THD *thd, TABLE_REF *ref);
bool error_if_full_join(JOIN *join); bool error_if_full_join(JOIN *join);
int report_error(TABLE *table, int error); int report_error(TABLE *table, int error);
int safe_index_read(JOIN_TAB *tab); int safe_index_read(JOIN_TAB *tab);
COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value);
...@@ -70,7 +70,7 @@ int mysql_update(THD *thd, ...@@ -70,7 +70,7 @@ int mysql_update(THD *thd,
ha_rows updated, found; ha_rows updated, found;
key_map old_used_keys; key_map old_used_keys;
TABLE *table; TABLE *table;
SQL_SELECT *select; SQL_SELECT *select= 0;
READ_RECORD info; READ_RECORD info;
TABLE_LIST *update_table_list= ((TABLE_LIST*) TABLE_LIST *update_table_list= ((TABLE_LIST*)
thd->lex->select_lex.table_list.first); thd->lex->select_lex.table_list.first);
...@@ -131,11 +131,19 @@ int mysql_update(THD *thd, ...@@ -131,11 +131,19 @@ int mysql_update(THD *thd,
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
} }
if (conds)
{
Item::cond_result cond_value;
conds= remove_eq_conds(thd, conds, &cond_value);
if (cond_value == Item::COND_FALSE)
limit= 0; // Impossible WHERE
}
// Don't count on usage of 'only index' when calculating which key to use // Don't count on usage of 'only index' when calculating which key to use
table->used_keys.clear_all(); table->used_keys.clear_all();
select=make_select(table,0,0,conds,&error); if (limit)
if (error || select=make_select(table,0,0,conds,&error);
(select && select->check_quick(thd, safe_update, limit)) || !limit) if (error || !limit ||
(select && select->check_quick(thd, safe_update, limit)))
{ {
delete select; delete select;
free_underlaid_joins(thd, &thd->lex->select_lex); free_underlaid_joins(thd, &thd->lex->select_lex);
......
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