summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <gkodinov/kgeorge@magare.gmz>2007-06-28 16:07:55 +0300
committerunknown <gkodinov/kgeorge@magare.gmz>2007-06-28 16:07:55 +0300
commitba4682ae10648d7341798eb628cfe2c1ce466a89 (patch)
treea2bf9e1b332e76cb81626a4f4952dfcd1f7eed99
parent28187da7747029ee380b5ddcea84cc0002b4ad5d (diff)
downloadmariadb-git-ba4682ae10648d7341798eb628cfe2c1ce466a89.tar.gz
Bug #29157: UPDATE, changed rows incorrect
Sometimes the number of really updated rows (with changed column values) cannot be determined at the server level alone (e.g. if the storage engine does not return enough column values to verify that). So the only dependable way in such cases is to let the storage engine return that information if possible. Fixed the bug at server level by providing a way for the storage engine to return information about wether it actually updated the row or the old and the new column values are the same. It can do that by returning HA_ERR_RECORD_IS_THE_SAME in ha_update_row(). Note that each storage engine may choose not to try to return this status code, so this behaviour remains storage engine specific. include/my_base.h: Bug #29157: handle the row not updated special return value sql/log_event.cc: Bug #29157: handle the row not updated special return value sql/sp.cc: Bug #29157: handle the row not updated special return value sql/sql_acl.cc: Bug #29157: handle the row not updated special return value sql/sql_insert.cc: Bug #29157: handle the row not updated special return value sql/sql_servers.cc: Bug #29157: handle the row not updated special return value sql/sql_update.cc: Bug #29157: handle the row not updated special return value
-rw-r--r--include/my_base.h4
-rw-r--r--sql/log_event.cc6
-rw-r--r--sql/sp.cc5
-rw-r--r--sql/sql_acl.cc45
-rw-r--r--sql/sql_insert.cc16
-rw-r--r--sql/sql_servers.cc6
-rw-r--r--sql/sql_update.cc23
7 files changed, 79 insertions, 26 deletions
diff --git a/include/my_base.h b/include/my_base.h
index 617cdb8c3f0..b2a8b4b6b67 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -396,7 +396,9 @@ enum ha_base_keytype {
#define HA_ERR_AUTOINC_READ_FAILED 166 /* Failed to get next autoinc value */
#define HA_ERR_AUTOINC_ERANGE 167 /* Failed to set row autoinc value */
#define HA_ERR_GENERIC 168 /* Generic error */
-#define HA_ERR_LAST 168 /*Copy last error nr.*/
+#define HA_ERR_RECORD_IS_THE_SAME 169 /* row not actually updated :
+ new values same as the old values */
+#define HA_ERR_LAST 169 /*Copy last error nr.*/
/* Add error numbers before HA_ERR_LAST and change it accordingly. */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 1f5013a8ef6..02d3a949cb3 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -7171,8 +7171,10 @@ replace_record(THD *thd, TABLE *table,
{
error=table->file->ha_update_row(table->record[1],
table->record[0]);
- if (error)
+ if (error && error != HA_ERR_RECORD_IS_THE_SAME)
table->file->print_error(error, MYF(0));
+ else
+ error= 0;
DBUG_RETURN(error);
}
else
@@ -7856,6 +7858,8 @@ int Update_rows_log_event::do_exec_row(TABLE *table)
database into the after image delivered from the master.
*/
error= table->file->ha_update_row(table->record[1], table->record[0]);
+ if (error == HA_ERR_RECORD_IS_THE_SAME)
+ error= 0;
return error;
}
diff --git a/sql/sp.cc b/sql/sp.cc
index 6e890f638d0..75ea9172c90 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -715,8 +715,11 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str,
chistics->comment.length,
system_charset_info);
- if ((table->file->ha_update_row(table->record[1],table->record[0])))
+ if ((ret= table->file->ha_update_row(table->record[1],table->record[0])) &&
+ ret != HA_ERR_RECORD_IS_THE_SAME)
ret= SP_WRITE_ROW_FAILED;
+ else
+ ret= 0;
}
if (ret == SP_OK)
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 8f0af8af3ed..67fa380d313 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1825,7 +1825,8 @@ static bool update_user_table(THD *thd, TABLE *table,
}
store_record(table,record[1]);
table->field[2]->store(new_password, new_password_len, system_charset_info);
- if ((error=table->file->ha_update_row(table->record[1],table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
{
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
DBUG_RETURN(1);
@@ -2041,12 +2042,18 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
We should NEVER delete from the user table, as a uses can still
use mysqld even if he doesn't have any privileges in the user table!
*/
- if (cmp_record(table,record[1]) &&
- (error=table->file->ha_update_row(table->record[1],table->record[0])))
- { // This should never happen
- table->file->print_error(error,MYF(0)); /* purecov: deadcode */
- error= -1; /* purecov: deadcode */
- goto end; /* purecov: deadcode */
+ if (cmp_record(table,record[1]))
+ {
+ if ((error=
+ table->file->ha_update_row(table->record[1],table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
+ { // This should never happen
+ table->file->print_error(error,MYF(0)); /* purecov: deadcode */
+ error= -1; /* purecov: deadcode */
+ goto end; /* purecov: deadcode */
+ }
+ else
+ error= 0;
}
}
else if ((error=table->file->ha_write_row(table->record[0]))) // insert
@@ -2161,7 +2168,8 @@ static int replace_db_table(TABLE *table, const char *db,
if (rights)
{
if ((error= table->file->ha_update_row(table->record[1],
- table->record[0])))
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
goto table_error; /* purecov: deadcode */
}
else /* must have been a revoke of all privileges */
@@ -2543,12 +2551,14 @@ static int replace_column_table(GRANT_TABLE *g_t,
error=table->file->ha_update_row(table->record[1],table->record[0]);
else
error=table->file->ha_delete_row(table->record[1]);
- if (error)
+ if (error && error != HA_ERR_RECORD_IS_THE_SAME)
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
result= -1; /* purecov: inspected */
goto end; /* purecov: inspected */
}
+ else
+ error= 0;
grant_column= column_hash_search(g_t, column->column.ptr(),
column->column.length());
if (grant_column) // Should always be true
@@ -2608,7 +2618,8 @@ static int replace_column_table(GRANT_TABLE *g_t,
{
int tmp_error;
if ((tmp_error=table->file->ha_update_row(table->record[1],
- table->record[0])))
+ table->record[0])) &&
+ tmp_error != HA_ERR_RECORD_IS_THE_SAME)
{ /* purecov: deadcode */
table->file->print_error(tmp_error,MYF(0)); /* purecov: deadcode */
result= -1; /* purecov: deadcode */
@@ -2730,7 +2741,9 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
{
if (store_table_rights || store_col_rights)
{
- if ((error=table->file->ha_update_row(table->record[1],table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
goto table_error; /* purecov: deadcode */
}
else if ((error = table->file->ha_delete_row(table->record[1])))
@@ -2848,7 +2861,9 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
{
if (store_proc_rights)
{
- if ((error=table->file->ha_update_row(table->record[1],table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
goto table_error;
}
else if ((error= table->file->ha_delete_row(table->record[1])))
@@ -4914,8 +4929,12 @@ static int modify_grant_table(TABLE *table, Field *host_field,
system_charset_info);
user_field->store(user_to->user.str, user_to->user.length,
system_charset_info);
- if ((error= table->file->ha_update_row(table->record[1], table->record[0])))
+ if ((error= table->file->ha_update_row(table->record[1],
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
table->file->print_error(error, MYF(0));
+ else
+ error= 0;
}
else
{
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 120187b3939..eeac5e7c4fe 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1423,7 +1423,8 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
compare_record(table))
{
if ((error=table->file->ha_update_row(table->record[1],
- table->record[0])))
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
{
if (info->ignore &&
!table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
@@ -1433,7 +1434,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
goto err;
}
- info->updated++;
+ if (error != HA_ERR_RECORD_IS_THE_SAME)
+ info->updated++;
+ else
+ error= 0;
/*
If ON DUP KEY UPDATE updates a row instead of inserting one, it's
like a regular UPDATE statement: it should not affect the value of a
@@ -1481,9 +1485,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
(!table->triggers || !table->triggers->has_delete_triggers()))
{
if ((error=table->file->ha_update_row(table->record[1],
- table->record[0])))
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
goto err;
- info->deleted++;
+ if (error != HA_ERR_RECORD_IS_THE_SAME)
+ info->deleted++;
+ else
+ error= 0;
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
/*
Since we pretend that we have done insert we should call
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index 195e6743a72..ac5ea6f4ac4 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -872,11 +872,15 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server)
/* ok, so we can update since the record exists in the table */
store_record(table,record[1]);
store_server_fields(table, server);
- if ((error=table->file->ha_update_row(table->record[1],table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
{
DBUG_PRINT("info",("problems with ha_update_row %d", error));
goto end;
}
+ else
+ error= 0;
}
end:
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 693ba779e5d..ef1f46bfdd2 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -548,9 +548,12 @@ int mysql_update(THD *thd,
error= table->file->ha_update_row(table->record[1],
table->record[0]);
}
- if (!error)
+ if (!error || error == HA_ERR_RECORD_IS_THE_SAME)
{
- updated++;
+ if (error != HA_ERR_RECORD_IS_THE_SAME)
+ updated++;
+ else
+ error= 0;
thd->no_trans_update.stmt= !transactional_table;
if (table->triggers &&
@@ -1524,7 +1527,8 @@ bool multi_update::send_data(List<Item> &not_used_values)
main_table->file->extra(HA_EXTRA_PREPARE_FOR_UPDATE);
}
if ((error=table->file->ha_update_row(table->record[1],
- table->record[0])))
+ table->record[0])) &&
+ error != HA_ERR_RECORD_IS_THE_SAME)
{
updated--;
if (!ignore ||
@@ -1542,6 +1546,11 @@ bool multi_update::send_data(List<Item> &not_used_values)
}
else
{
+ if (error == HA_ERR_RECORD_IS_THE_SAME)
+ {
+ error= 0;
+ updated--;
+ }
/* non-transactional or transactional table got modified */
/* either multi_update class' flag is raised in its branch */
if (table->file->has_transactions())
@@ -1768,13 +1777,17 @@ int multi_update::do_updates(bool from_send_error)
goto err;
}
if ((local_error=table->file->ha_update_row(table->record[1],
- table->record[0])))
+ table->record[0])) &&
+ local_error != HA_ERR_RECORD_IS_THE_SAME)
{
if (!ignore ||
table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY))
goto err;
}
- updated++;
+ if (local_error != HA_ERR_RECORD_IS_THE_SAME)
+ updated++;
+ else
+ local_error= 0;
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,