Commit fd9d58c4 authored by unknown's avatar unknown
Browse files

Fix for Bug #9691 UPDATE fails on attempt to update primary key

parent 56ea7702
Loading
Loading
Loading
Loading
+25 −5
Original line number Diff line number Diff line
@@ -2,12 +2,32 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (
pk1 INT NOT NULL PRIMARY KEY,
b INT NOT NULL,
c INT NOT NULL
c INT NOT NULL UNIQUE
) ENGINE=ndbcluster;
INSERT INTO t1 VALUES (0, 0, 1),(1,1,2),(2,2,3);
INSERT INTO t1 VALUES (0, 1, 0),(1,2,1),(2,3,2);
UPDATE t1 set b = c;
select * from t1 order by pk1;
pk1	b	c
0	1	1
1	2	2
2	3	3
0	0	0
1	1	1
2	2	2
UPDATE t1 set pk1 = 4 where pk1 = 1;
select * from t1 order by pk1;
pk1	b	c
0	0	0
2	2	2
4	1	1
UPDATE t1 set pk1 = 1, c = 2 where pk1 = 4;
ERROR 23000: Duplicate entry '1' for key 1
select * from t1 order by pk1;
pk1	b	c
0	0	0
2	2	2
4	1	1
UPDATE t1 set pk1 = pk1 + 10;
select * from t1 order by pk1;
pk1	b	c
10	0	0
12	2	2
14	1	1
DROP TABLE IF EXISTS t1;
+13 −2
Original line number Diff line number Diff line
@@ -14,9 +14,20 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (
  pk1 INT NOT NULL PRIMARY KEY,
  b INT NOT NULL,
  c INT NOT NULL
  c INT NOT NULL UNIQUE
) ENGINE=ndbcluster;

INSERT INTO t1 VALUES (0, 0, 1),(1,1,2),(2,2,3);
INSERT INTO t1 VALUES (0, 1, 0),(1,2,1),(2,3,2);
UPDATE t1 set b = c;
select * from t1 order by pk1;
UPDATE t1 set pk1 = 4 where pk1 = 1;
select * from t1 order by pk1;
-- error 1062
UPDATE t1 set pk1 = 1, c = 2 where pk1 = 4;
select * from t1 order by pk1;
UPDATE t1 set pk1 = pk1 + 10;
select * from t1 order by pk1;

--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
+24 −15
Original line number Diff line number Diff line
@@ -1863,7 +1863,9 @@ int ha_ndbcluster::write_row(byte *record)
      m_skip_auto_increment= !auto_increment_column_changed;
    }

    if ((res= set_primary_key(op)))
    if ((res= (m_primary_key_update ?
               set_primary_key_from_old_data(op, record)
               : set_primary_key(op))))
      return res;  
  }

@@ -2001,7 +2003,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
  {
    int read_res, insert_res, delete_res;

    DBUG_PRINT("info", ("primary key update, doing pk read+insert+delete"));
    DBUG_PRINT("info", ("primary key update, doing pk read+delete+insert"));
    // Get all old fields, since we optimize away fields not in query
    read_res= complemented_pk_read(old_data, new_data);
    if (read_res)
@@ -2009,15 +2011,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
      DBUG_PRINT("info", ("pk read failed"));
      DBUG_RETURN(read_res);
    }
    // Insert new row
    insert_res= write_row(new_data);
    if (insert_res)
    {
      DBUG_PRINT("info", ("insert failed"));
      DBUG_RETURN(insert_res);
    }
    // Delete old row
    DBUG_PRINT("info", ("insert succeded"));
    m_primary_key_update= TRUE;
    delete_res= delete_row(old_data);
    m_primary_key_update= FALSE;
@@ -2025,9 +2019,23 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
    {
      DBUG_PRINT("info", ("delete failed"));
      // Undo write_row(new_data)
      DBUG_RETURN(delete_row(new_data));
      DBUG_RETURN(delete_res);
    }     
    // Insert new row
    DBUG_PRINT("info", ("delete succeded"));
    insert_res= write_row(new_data);
    if (insert_res)
    {
      DBUG_PRINT("info", ("insert failed"));
      if (trans->commitStatus() == NdbConnection::Started)
      {
        m_primary_key_update= TRUE;
        insert_res= write_row((byte *)old_data);
        m_primary_key_update= FALSE;
      }
      DBUG_RETURN(insert_res);
    }
    DBUG_PRINT("info", ("insert+delete succeeded"));
    DBUG_PRINT("info", ("delete+insert succeeded"));
    DBUG_RETURN(0);
  }

@@ -2125,6 +2133,7 @@ int ha_ndbcluster::delete_row(const byte *record)

    no_uncommitted_rows_update(-1);

    if (!m_primary_key_update)
      // If deleting from cursor, NoCommit will be handled in next_result
      DBUG_RETURN(0);
  }