summaryrefslogtreecommitdiff
path: root/mysql-test/t/federated.test
diff options
context:
space:
mode:
authorunknown <dlenev@mysql.com>2006-07-02 01:51:10 +0400
committerunknown <dlenev@mysql.com>2006-07-02 01:51:10 +0400
commitae9724cce160c8d8351df3e2a232cc848b5c6fb8 (patch)
tree48bd251f4cb4e7758b735c1992085a65a6b54dd1 /mysql-test/t/federated.test
parent9d7799e7a89235d9799eb0e8acd8a52c79746107 (diff)
downloadmariadb-git-ae9724cce160c8d8351df3e2a232cc848b5c6fb8.tar.gz
Fix for bug#18437 "Wrong values inserted with a before update trigger on
NDB table". SQL-layer was not marking fields which were used in triggers as such. As result these fields were not always properly retrieved/stored by handler layer. So one might got wrong values or lost changes in triggers for NDB, Federated and possibly InnoDB tables. This fix solves the problem by marking fields used in triggers appropriately. Also this patch contains the following cleanup of ha_ndbcluster code: We no longer rely on reading LEX::sql_command value in handler in order to determine if we can enable optimization which allows us to handle REPLACE statement in more efficient way by doing replaces directly in write_row() method without reporting error to SQL-layer. Instead we rely on SQL-layer informing us whether this optimization applicable by calling handler::extra() method with HA_EXTRA_WRITE_CAN_REPLACE flag. As result we no longer apply this optimzation in cases when it should not be used (e.g. if we have on delete triggers on table) and use in some additional cases when it is applicable (e.g. for LOAD DATA REPLACE). Finally this patch includes fix for bug#20728 "REPLACE does not work correctly for NDB table with PK and unique index". This was yet another problem which was caused by improper field mark-up. During row replacement fields which weren't explicity used in REPLACE statement were not marked as fields to be saved (updated) so they have retained values from old row version. The fix is to mark all table fields as set for REPLACE statement. Note that in 5.1 we already solve this problem by notifying handler that it should save values from all fields only in case when real replacement happens. include/my_base.h: Added HA_EXTRA_WRITE_CAN_REPLACE, HA_EXTRA_WRITE_CANNOT_REPLACE - new parameters for ha_extra() method. We use them to inform handler that write_row() which tries to insert new row into the table and encounters some already existing row with same primary/unique key can replace old row with new row instead of reporting error. mysql-test/r/federated.result: Additional test for bug#18437 "Wrong values inserted with a before update trigger on NDB table". mysql-test/r/ndb_replace.result: Added test for bug #20728 "REPLACE does not work correctly for NDB table with PK and unique index". Updated wrong results from older test. mysql-test/t/federated.test: Additional test for bug#18437 "Wrong values inserted with a before update trigger on NDB table". mysql-test/t/ndb_replace.test: Added test for bug #20728 "REPLACE does not work correctly for NDB table with PK and unique index". sql/ha_ndbcluster.cc: We no longer rely on reading LEX::sql_command value in handler in order to determine if we can enable optimization which allows us to handle REPLACE statement in more efficient way by doing replaces directly in write_row() method without reporting error to SQL-layer. Instead we rely on SQL-layer informing us whether this optimization applicable by calling handler::extra() method with HA_EXTRA_WRITE_CAN_REPLACE flag. As result we no longer apply this optimization in cases when it should not be used (e.g. if we have on delete triggers on table) and use in some additional cases when it is applicable (e.g. for LOAD DATA REPLACE). sql/item.cc: Item_trigger_field::setup_field(): Added comment explaining why we don't set Field::query_id in this method. sql/mysql_priv.h: mysql_alter_table() function no longer takes handle_duplicates argument. Added declaration of mark_fields_used_by_triggers_for_insert_stmt() function. sql/sql_delete.cc: Mark fields which are used by ON DELETE triggers so handler will retrieve values for these fields. sql/sql_insert.cc: Explicitly inform handler that we are doing REPLACE (using ha_extra() method) in cases when it can promote insert operation done by write_row() to replace. Also when we do REPLACE we want to store values for all columns so we should inform handler about it. Finally we should mark fields used by ON UPDATE/ON DELETE triggers as such so handler can properly retrieve/restore values in these fields during execution of REPLACE and INSERT ... ON DUPLICATE KEY UPDATE statements. sql/sql_load.cc: Explicitly inform handler that we are doing LOAD DATA REPLACE (using ha_extra() method) in cases when it can promote insert operation done by write_row() to replace. Also when we do replace we want to save (replace) values for all columns so we should inform handler about it. Finally to properly execute LOAD DATA for table with triggers we should mark fields used by ON INSERT triggers as such so handler can properly store values for these fields. sql/sql_parse.cc: mysql_alter_table() function no longer takes handle_duplicates argument. sql/sql_table.cc: Got rid of handle_duplicates argument in mysql_alter_table() and copy_data_between_tables() functions. These functions were always called with handle_duplicates == DUP_ERROR and thus contained dead (and probably incorrect) code. sql/sql_trigger.cc: Added Table_triggers_list::mark_fields_used() method which is used to mark fields read/set by triggers as such so handlers will be able properly retrieve/store values in these fields. sql/sql_trigger.h: Table_triggers_list: Added mark_fields_used() method which is used to mark fields read/set by triggers as such so handlers will be able properly retrieve/store values in these fields. To implement this method added 'trigger_fields' member which is array of lists linking items for all fields used in triggers grouped by event and action time. sql/sql_update.cc: Mark fields which are used by ON UPDATE triggers so handler will retrieve and save values for these fields. mysql-test/r/ndb_trigger.result: Added test for bug#18437 "Wrong values inserted with a before update trigger on NDB table". mysql-test/t/ndb_trigger.test: Added test for bug#18437 "Wrong values inserted with a before update trigger on NDB table".
Diffstat (limited to 'mysql-test/t/federated.test')
-rw-r--r--mysql-test/t/federated.test42
1 files changed, 42 insertions, 0 deletions
diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test
index 80b31c610a2..6e53b1e3adb 100644
--- a/mysql-test/t/federated.test
+++ b/mysql-test/t/federated.test
@@ -1310,4 +1310,46 @@ connection slave;
DROP TABLE federated.bug_17377_table;
+#
+# Additional test for bug#18437 "Wrong values inserted with a before
+# update trigger on NDB table". SQL-layer didn't properly inform
+# handler about fields which were read and set in triggers. In some
+# cases this resulted in incorrect (garbage) values of OLD variables
+# and lost changes to NEW variables.
+# Since for federated engine only operation which is affected by wrong
+# fields mark-up is handler::write_row() this file constains coverage
+# for ON INSERT triggers only. Tests for other types of triggers reside
+# in ndb_trigger.test.
+#
+--disable_warnings
+drop table if exists federated.t1;
+--enable_warnings
+create table federated.t1 (a int, b int, c int);
+connection master;
+--disable_warnings
+drop table if exists federated.t1;
+drop table if exists federated.t2;
+--enable_warnings
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval create table federated.t1 (a int, b int, c int) engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+create trigger federated.t1_bi before insert on federated.t1 for each row set new.c= new.a * new.b;
+create table federated.t2 (a int, b int);
+insert into federated.t2 values (13, 17), (19, 23);
+# Each of three statements should correctly set values for all three fields
+# insert
+insert into federated.t1 (a, b) values (1, 2), (3, 5), (7, 11);
+select * from federated.t1;
+delete from federated.t1;
+# insert ... select
+insert into federated.t1 (a, b) select * from federated.t2;
+select * from federated.t1;
+delete from federated.t1;
+# load
+load data infile '../std_data_ln/loaddata5.dat' into table federated.t1 fields terminated by '' enclosed by '' ignore 1 lines (a, b);
+select * from federated.t1;
+drop tables federated.t1, federated.t2;
+
+connection slave;
+drop table federated.t1;
+
source include/federated_cleanup.inc;