summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorV Narayanan <v.narayanan@sun.com>2009-12-03 16:48:02 +0530
committerV Narayanan <v.narayanan@sun.com>2009-12-03 16:48:02 +0530
commit21aaf8dded17341805afd72539bc7606ebb0b46a (patch)
treebe9cb37a33ba0768627bad6cd8993618a017ac7a
parent40ec012c905be0262ba5c36bbccfa0db0105e31f (diff)
downloadmariadb-git-21aaf8dded17341805afd72539bc7606ebb0b46a.tar.gz
WL#4454 change sql_insert.cc::last_uniq_key to match keys in any order
Introduce a flag that will enable the REPLACE command to work correctly with an underlying storage engine that does not report unique key conflicts in the ascending order. sql/handler.h: WL#4454 change sql_insert.cc::last_uniq_key to match keys in any order Adds the flag that will be set by a SE that does not report unique key conflicts in the ascending order. sql/sql_insert.cc: WL#4454 change sql_insert.cc::last_uniq_key to match keys in any order modifies the function used for a last row replace optimization to check for the HA_DUPLICATE_KEY_NOT_IN_ORDER flag.
-rw-r--r--sql/handler.h23
-rw-r--r--sql/sql_insert.cc17
2 files changed, 40 insertions, 0 deletions
diff --git a/sql/handler.h b/sql/handler.h
index 05a9e13653c..8e8f417739e 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -127,6 +127,29 @@
*/
#define HA_BINLOG_ROW_CAPABLE (LL(1) << 34)
#define HA_BINLOG_STMT_CAPABLE (LL(1) << 35)
+/*
+ When a multiple key conflict happens in a REPLACE command mysql
+ expects the conflicts to be reported in the ascending order of
+ key names.
+
+ For e.g.
+
+ CREATE TABLE t1 (a INT, UNIQUE (a), b INT NOT NULL, UNIQUE (b), c INT NOT
+ NULL, INDEX(c));
+
+ REPLACE INTO t1 VALUES (1,1,1),(2,2,2),(2,1,3);
+
+ MySQL expects the conflict with 'a' to be reported before the conflict with
+ 'b'.
+
+ If the underlying storage engine does not report the conflicting keys in
+ ascending order, it causes unexpected errors when the REPLACE command is
+ executed.
+
+ This flag helps the underlying SE to inform the server that the keys are not
+ ordered.
+*/
+#define HA_DUPLICATE_KEY_NOT_IN_ORDER (LL(1) << 36)
/*
Set of all binlog flags. Currently only contain the capabilities
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index b1c7c7f647e..988c91e3168 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1322,6 +1322,23 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
static int last_uniq_key(TABLE *table,uint keynr)
{
+ /*
+ When an underlying storage engine informs that the unique key
+ conflicts are not reported in the ascending order by setting
+ the HA_DUPLICATE_KEY_NOT_IN_ORDER flag, we cannot rely on this
+ information to determine the last key conflict.
+
+ The information about the last key conflict will be used to
+ do a replace of the new row on the conflicting row, rather
+ than doing a delete (of old row) + insert (of new row).
+
+ Hence check for this flag and disable replacing the last row
+ by returning 0 always. Returning 0 will result in doing
+ a delete + insert always.
+ */
+ if (table->file->ha_table_flags() & HA_DUPLICATE_KEY_NOT_IN_ORDER)
+ return 0;
+
while (++keynr < table->s->keys)
if (table->key_info[keynr].flags & HA_NOSAME)
return 0;