diff options
author | unknown <svoj@mysql.com/april.(none)> | 2006-12-20 20:01:31 +0400 |
---|---|---|
committer | unknown <svoj@mysql.com/april.(none)> | 2006-12-20 20:01:31 +0400 |
commit | 2efb6576008acd580680849e1e618da021b57c7e (patch) | |
tree | 07b49f1420b38586b00555274fbede619a469630 /sql/sql_update.cc | |
parent | 76da582ca5f8a93ae5ff7e7fdea1991d47658196 (diff) | |
parent | 9d094c56bc6f15d16f51d4b0bcf9de3cd4674d7f (diff) | |
download | mariadb-git-2efb6576008acd580680849e1e618da021b57c7e.tar.gz |
Merge mysql.com:/home/svoj/devel/mysql/BUG21310/mysql-4.1-engines
into mysql.com:/home/svoj/devel/mysql/BUG21310/mysql-5.0-engines
sql/lock.cc:
Use local.
mysql-test/r/myisam.result:
Manual merge.
mysql-test/t/myisam.test:
Manual merge.
sql/sql_update.cc:
Manual merge.
Diffstat (limited to 'sql/sql_update.cc')
-rw-r--r-- | sql/sql_update.cc | 138 |
1 files changed, 62 insertions, 76 deletions
diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 3b6aa5f1aa2..5b7b7f594da 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -25,8 +25,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) @@ -1041,27 +1039,72 @@ 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 *all_tables, List<Item> *fields) +{ + TABLE *table= join_tab->table; + if (unique_table(thd, table, 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; } @@ -1099,7 +1142,7 @@ 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, all_tables, &temp_fields)) { table_to_update= main_table; // Update table on the fly continue; @@ -1150,63 +1193,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() { |