summaryrefslogtreecommitdiff
path: root/sql/sql_update.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_update.cc')
-rw-r--r--sql/sql_update.cc70
1 files changed, 46 insertions, 24 deletions
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 24199df9b84..277a6b3bf37 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -15,8 +15,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Update of records
- Multi-table updates were introduced by Monty and Sinisa <sinisa@mysql.com>
+/*
+ Single table and multi table updates of tables.
+ Multi-table updates were introduced by Sinisa & Monty
*/
#include "mysql_priv.h"
@@ -94,7 +95,7 @@ int mysql_update(THD *thd,
tables.table= table;
tables.alias= table_list->alias;
- if (setup_tables(update_table_list, 0) ||
+ if (setup_tables(update_table_list) ||
setup_conds(thd,update_table_list,&conds) ||
thd->lex->select_lex.setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
@@ -119,7 +120,6 @@ int mysql_update(THD *thd,
{
timestamp_query_id=table->timestamp_field->query_id;
table->timestamp_field->query_id=thd->query_id-1;
- table->time_stamp= table->timestamp_field->offset() +1;
}
/* Check the fields we are going to modify */
@@ -132,7 +132,7 @@ int mysql_update(THD *thd,
{
// Don't set timestamp column if this is modified
if (table->timestamp_field->query_id == thd->query_id)
- table->time_stamp=0;
+ table->timestamp_on_update_now= 0;
else
table->timestamp_field->query_id=timestamp_query_id;
}
@@ -272,6 +272,8 @@ int mysql_update(THD *thd,
}
}
}
+ if (thd->killed && !error)
+ error= 1; // Aborted
limit= tmp_limit;
end_read_record(&info);
/* Change select to use tempfile */
@@ -344,6 +346,8 @@ int mysql_update(THD *thd,
table->file->unlock_row();
thd->row_count++;
}
+ if (thd->killed && !error)
+ error= 1; // Aborted
end_read_record(&info);
free_io_cache(table); // If ORDER BY
thd->proc_info="end";
@@ -436,17 +440,31 @@ int mysql_multi_update(THD *thd,
int res;
multi_update *result;
TABLE_LIST *tl;
+ table_map item_tables= 0, derived_tables= 0;
DBUG_ENTER("mysql_multi_update");
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege=(SELECT_ACL & ~table_list->grant.privilege);
-#endif
- if ((res=open_and_lock_tables(thd,table_list)))
+ if ((res=open_and_lock_tables(thd,table_list)))
DBUG_RETURN(res);
select_lex->select_limit= HA_POS_ERROR;
- table_map item_tables= 0, derived_tables= 0;
+ /*
+ Ensure that we have update privilege for all tables and columns in the
+ SET part
+ */
+ for (tl= table_list ; tl ; tl=tl->next)
+ {
+ TABLE *table= tl->table;
+ /*
+ Update of derived tables is checked later
+ We don't check privileges here, becasue then we would get error
+ "UPDATE command denided .. for column N" instead of
+ "Target table ... is not updatable"
+ */
+ if (!tl->derived)
+ table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege);
+ }
+
if (thd->lex->derived_tables)
{
// Assign table map values to check updatability of derived tables
@@ -477,13 +495,14 @@ int mysql_multi_update(THD *thd,
for (tl= select_lex->get_table_list() ; tl ; tl= tl->next)
{
TABLE *table= tl->table;
- if (table->timestamp_field)
- {
- table->time_stamp=0;
- // Only set timestamp column if this is not modified
- if (table->timestamp_field->query_id != thd->query_id)
- table->time_stamp= table->timestamp_field->offset() +1;
- }
+
+ /* We only need SELECT privilege for columns in the values list */
+ table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
+ // Only set timestamp column if this is not modified
+ if (table->timestamp_field &&
+ table->timestamp_field->query_id == thd->query_id)
+ table->timestamp_on_update_now= 0;
+
if (tl->derived)
derived_tables|= table->map;
}
@@ -680,7 +699,7 @@ multi_update::initialize_tables(JOIN *join)
{
TABLE *table=table_ref->table;
uint cnt= table_ref->shared;
- Item_field *If;
+ Item_field *ifield;
List<Item> temp_fields= *fields_for_table[cnt];
ORDER group;
@@ -704,10 +723,10 @@ multi_update::initialize_tables(JOIN *join)
/* ok to be on stack as this is not referenced outside of this func */
Field_string offset(table->file->ref_length, 0, "offset",
table, &my_charset_bin);
- if (!(If=new Item_field(((Field *) &offset))))
+ if (!(ifield= new Item_field(((Field *) &offset))))
DBUG_RETURN(1);
- If->maybe_null=0;
- if (temp_fields.push_front(If))
+ ifield->maybe_null= 0;
+ if (temp_fields.push_front(ifield))
DBUG_RETURN(1);
/* Make an unique key over the first field to avoid duplicated updates */
@@ -950,14 +969,16 @@ int multi_update::do_updates(bool from_send_error)
DBUG_RETURN(0);
for (cur_table= update_tables; cur_table ; cur_table= cur_table->next)
{
+ byte *ref_pos;
+ TABLE *tmp_table;
+
table = cur_table->table;
if (table == table_to_update)
continue; // Already updated
-
org_updated= updated;
- byte *ref_pos;
- TABLE *tmp_table= tmp_tables[cur_table->shared];
+ tmp_table= tmp_tables[cur_table->shared];
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
+ (void) table->file->rnd_init(0);
table->file->extra(HA_EXTRA_NO_CACHE);
/*
@@ -1024,6 +1045,7 @@ int multi_update::do_updates(bool from_send_error)
else
trans_safe= 0; // Can't do safe rollback
}
+ (void) table->file->rnd_end();
}
DBUG_RETURN(0);