@ -24,8 +24,6 @@
# include "sp_head.h"
# include "sql_trigger.h"
static bool safe_update_on_fly ( JOIN_TAB * join_tab , List < Item > * fields ) ;
/* Return 0 if row hasn't changed */
static bool compare_record ( TABLE * table , query_id_t query_id )
@ -1040,27 +1038,73 @@ int multi_update::prepare(List<Item> ¬_used_values,
for ( i = 0 ; i < table_count ; i + + )
set_if_bigger ( max_fields , fields_for_table [ i ] - > elements ) ;
copy_field = new Copy_field [ max_fields ] ;
DBUG_RETURN ( thd - > is_fatal_error ! = 0 ) ;
}
/*
Mark all copies of tables that are updates to ensure that
init_read_record ( ) will not try to enable a cache on them
The problem is that for queries like
/*
Check if table is safe to update on fly
UPDATE t1 , t1 AS t2 SET t1 . b = t2 . c WHERE t1 . a = t2 . a ;
SYNOPSIS
safe_update_on_fly ( )
thd Thread handler
join_tab How table is used in join
all_tables List of tables
fields Fields that are updated
the row buffer may contain things that doesn ' t match what is on disk
which will cause an error when reading a row .
( This issue is mostly relevent for MyISAM tables )
*/
for ( table_ref = leaves ; table_ref ; table_ref = table_ref - > next_leaf )
{
TABLE * table = table_ref - > table ;
if ( ( tables_to_update & table - > map ) & &
unique_table ( thd , table_ref , update_tables ) )
table - > no_cache = 1 ; // Disable row cache
NOTES
We can update the first table in join on the fly if we know that
a row in this table will never be read twice . This is true under
the following conditions :
- We are doing a table scan and the data is in a separate file ( MyISAM ) or
if we don ' t update a clustered key .
- We are doing a range scan and we don ' t update the scan key or
the primary key for a clustered table handler .
- Table is not joined to itself .
When checking for above cases we also should take into account that
BEFORE UPDATE trigger potentially may change value of any field in row
being updated .
WARNING
This code is a bit dependent of how make_join_readinfo ( ) works .
RETURN
0 Not safe to update
1 Safe to update
*/
static bool safe_update_on_fly ( THD * thd , JOIN_TAB * join_tab ,
TABLE_LIST * table_ref , TABLE_LIST * all_tables ,
List < Item > * fields )
{
TABLE * table = join_tab - > table ;
if ( unique_table ( thd , table_ref , all_tables ) )
return 0 ;
switch ( join_tab - > type ) {
case JT_SYSTEM :
case JT_CONST :
case JT_EQ_REF :
return TRUE ; // At most one matching row
case JT_REF :
case JT_REF_OR_NULL :
return ! is_key_used ( table , join_tab - > ref . key , * fields ) ;
case JT_ALL :
/* If range search on index */
if ( join_tab - > quick )
return ! join_tab - > quick - > is_keys_used ( fields ) ;
/* If scanning in clustered key */
if ( ( table - > file - > table_flags ( ) & HA_PRIMARY_KEY_IN_READ_INDEX ) & &
table - > s - > primary_key < MAX_KEY )
return ! is_key_used ( table , table - > s - > primary_key , * fields ) ;
return TRUE ;
default :
break ; // Avoid compler warning
}
DBUG_RETURN ( thd - > is_fatal_error ! = 0 ) ;
return FALSE ;
}
@ -1098,7 +1142,8 @@ multi_update::initialize_tables(JOIN *join)
table - > file - > extra ( HA_EXTRA_IGNORE_DUP_KEY ) ;
if ( table = = main_table ) // First table in join
{
if ( safe_update_on_fly ( join - > join_tab , & temp_fields ) )
if ( safe_update_on_fly ( thd , join - > join_tab , table_ref , all_tables ,
& temp_fields ) )
{
table_to_update = main_table ; // Update table on the fly
continue ;
@ -1149,63 +1194,6 @@ multi_update::initialize_tables(JOIN *join)
DBUG_RETURN ( 0 ) ;
}
/*
Check if table is safe to update on fly
SYNOPSIS
safe_update_on_fly
join_tab How table is used in join
fields Fields that are updated
NOTES
We can update the first table in join on the fly if we know that
a row in this table will never be read twice . This is true under
the following conditions :
- We are doing a table scan and the data is in a separate file ( MyISAM ) or
if we don ' t update a clustered key .
- We are doing a range scan and we don ' t update the scan key or
the primary key for a clustered table handler .
When checking for above cases we also should take into account that
BEFORE UPDATE trigger potentially may change value of any field in row
being updated .
WARNING
This code is a bit dependent of how make_join_readinfo ( ) works .
RETURN
0 Not safe to update
1 Safe to update
*/
static bool safe_update_on_fly ( JOIN_TAB * join_tab , List < Item > * fields )
{
TABLE * table = join_tab - > table ;
switch ( join_tab - > type ) {
case JT_SYSTEM :
case JT_CONST :
case JT_EQ_REF :
return TRUE ; // At most one matching row
case JT_REF :
case JT_REF_OR_NULL :
return ! is_key_used ( table , join_tab - > ref . key , * fields ) ;
case JT_ALL :
/* If range search on index */
if ( join_tab - > quick )
return ! join_tab - > quick - > is_keys_used ( fields ) ;
/* If scanning in clustered key */
if ( ( table - > file - > table_flags ( ) & HA_PRIMARY_KEY_IN_READ_INDEX ) & &
table - > s - > primary_key < MAX_KEY )
return ! is_key_used ( table , table - > s - > primary_key , * fields ) ;
return TRUE ;
default :
break ; // Avoid compler warning
}
return FALSE ;
}
multi_update : : ~ multi_update ( )
{