]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid corrupting indices when doing a REPLACE on a table with an
authordrh <drh@noemail.net>
Wed, 4 Jun 2003 12:23:30 +0000 (12:23 +0000)
committerdrh <drh@noemail.net>
Wed, 4 Jun 2003 12:23:30 +0000 (12:23 +0000)
INTEGER PRIMARY KEY that also has another index.  Ticket #334. (CVS 999)

FossilOrigin-Name: e813faae0e4086571d13c769f793add7f1f979af

manifest
manifest.uuid
src/insert.c
test/insert.test

index 2492b327491db5066244939e51993323fbaba950..af58a13bf365ca488e17ecfb22a460ba839eb9f3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Additional\stesting\sof\sthe\sATTACH\scommand\swith\sbug\sfixes\sfor\sthe\snew\sproblems\nthat\sthe\stests\sfound.\s(CVS\s998)
-D 2003-06-03T01:47:11
+C Avoid\scorrupting\sindices\swhen\sdoing\sa\sREPLACE\son\sa\stable\swith\san\nINTEGER\sPRIMARY\sKEY\sthat\salso\shas\sanother\sindex.\s\sTicket\s#334.\s(CVS\s999)
+D 2003-06-04T12:23:31
 F Makefile.in 1ff85c27d4350c74118341024e8a4fb2a04a3a43
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -32,7 +32,7 @@ F src/expr.c ebdb0f3ee039c8030de25935ce2df030966540a6
 F src/func.c 33bbce6acaf9578ac99aa1f689968ccaf2ce43a2
 F src/hash.c 058f077c1f36f266581aa16f907a3903abf64aa3
 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
-F src/insert.c e34301f41a69cf59c4d75962b2ca5e1af427b5f0
+F src/insert.c 6a61c6d1ef17396d0e87e555806653fddab0b084
 F src/main.c 945f9b6855007b28a6c910584d1ca5adff92d821
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
 F src/os.c 080238f03015057879cdf53bc4af9e497f2ba724
@@ -83,7 +83,7 @@ F test/format3.test b05cb2968841553698290f2833f72894f156024e
 F test/func.test 000515779001ac6899eec4b54e65c6e2501279d4
 F test/in.test 22de8a3eb27265aab723adc513bea0e76bef70c6
 F test/index.test 90ef4c426865f15937858bd433cc82b9c11af913
-F test/insert.test 5697ba098e4d8a6f0151f281b7e39dec9c439e05
+F test/insert.test e73709f2fee30e003ce131e7ca66ad3dcfac662a
 F test/insert2.test c288375a64dad3295044714f0dfed4a193cf067f
 F test/intpkey.test 39f49fd993350f7f3ab255e5cfbf9a09d8f8800e
 F test/ioerr.test 5dbaf09f96b56ee01cf3edd762b96eb4ad2c9ca4
@@ -165,7 +165,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be
 F www/sqlite.tcl 4bd1729e320f5fa9125f0022b281fbe839192125
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P daf7b94017f03638da1ef65830f3762be030b93c
-R 64dc9487d2ea82a1f70ee389c18ab473
+P 3e8889d7ce5e99fc855526fc1bb62ddbe282bfc5
+R 9165bb0816719b739dc59ff58a777b66
 U drh
-Z 95bab4cd51ed3d170690377c2faf1c26
+Z 94bfab46c8d22deaac737964000d29aa
index d8d624a7659258c00e8bc41479f3c50bc6b99590..790a33f06d6282668a08b05931d3fb0468a32bc1 100644 (file)
@@ -1 +1 @@
-3e8889d7ce5e99fc855526fc1bb62ddbe282bfc5
\ No newline at end of file
+e813faae0e4086571d13c769f793add7f1f979af
\ No newline at end of file
index 53178374e65678676bfaf9eb14bdfbd197ba0936..98fc76cff9cf1ea89e81dd0a7164fc468a7e508a 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.86 2003/06/01 01:10:33 drh Exp $
+** $Id: insert.c,v 1.87 2003/06/04 12:23:31 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -715,10 +715,8 @@ void sqliteGenerateConstraintChecks(
   /* If we have an INTEGER PRIMARY KEY, make sure the primary key
   ** of the new record does not previously exist.  Except, if this
   ** is an UPDATE and the primary key is not changing, that is OK.
-  ** Also, if the conflict resolution policy is REPLACE, then we
-  ** can skip this test.
   */
-  if( /* (recnoChng || !isUpdate) && pTab->iPKey>=0 */ recnoChng ){
+  if( recnoChng ){
     onError = pTab->keyConf;
     if( overrideError!=OE_Default ){
       onError = overrideError;
@@ -728,40 +726,48 @@ void sqliteGenerateConstraintChecks(
       onError = OE_Abort;
     }
     
-    if( onError!=OE_Replace ){
-      if( isUpdate ){
-        sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
-        sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
-        jumpInst1 = sqliteVdbeAddOp(v, OP_Eq, 0, 0);
+    if( isUpdate ){
+      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
+      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
+      jumpInst1 = sqliteVdbeAddOp(v, OP_Eq, 0, 0);
+    }
+    sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
+    jumpInst2 = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
+    switch( onError ){
+      default: {
+        onError = OE_Abort;
+        /* Fall thru into the next case */
       }
-      sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
-      jumpInst2 = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
-      switch( onError ){
-        default: {
-          onError = OE_Abort;
-          /* Fall thru into the next case */
-        }
-        case OE_Rollback:
-        case OE_Abort:
-        case OE_Fail: {
-          sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
-          sqliteVdbeChangeP3(v, -1, "PRIMARY KEY must be unique", P3_STATIC);
-          break;
-        }
-        case OE_Ignore: {
-          sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
-          sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
-          break;
+      case OE_Rollback:
+      case OE_Abort:
+      case OE_Fail: {
+        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
+        sqliteVdbeChangeP3(v, -1, "PRIMARY KEY must be unique", P3_STATIC);
+        break;
+      }
+      case OE_Replace: {
+        sqliteGenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
+        if( isUpdate ){
+          sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
+          sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
         }
+        seenReplace = 1;
+        break;
       }
-      contAddr = sqliteVdbeCurrentAddr(v);
-      sqliteVdbeChangeP2(v, jumpInst2, contAddr);
-      if( isUpdate ){
-        sqliteVdbeChangeP2(v, jumpInst1, contAddr);
-        sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
-        sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
+      case OE_Ignore: {
+        assert( seenReplace==0 );
+        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
+        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
+        break;
       }
     }
+    contAddr = sqliteVdbeCurrentAddr(v);
+    sqliteVdbeChangeP2(v, jumpInst2, contAddr);
+    if( isUpdate ){
+      sqliteVdbeChangeP2(v, jumpInst1, contAddr);
+      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
+      sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
+    }
   }
 
   /* Test all UNIQUE constraints by creating entries for each UNIQUE
@@ -796,6 +802,11 @@ void sqliteGenerateConstraintChecks(
     }else if( onError==OE_Default ){
       onError = OE_Abort;
     }
+    if( seenReplace ){
+      if( onError==OE_Ignore ) onError = OE_Replace;
+      else if( onError==OE_Fail ) onError = OE_Abort;
+    }
+    
 
     /* Check to see if the new index entry will be unique */
     sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
index f551e4e4ae6b7da48d8e79255942c5a9d6d2834e..4dbe19191abec828c6f46df46c0adfeff696564e 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing the INSERT statement.
 #
-# $Id: insert.test,v 1.12 2003/04/03 01:50:48 drh Exp $
+# $Id: insert.test,v 1.13 2003/06/04 12:23:32 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -253,5 +253,21 @@ do_test insert-5.7 {
   expr {[lsearch $x OpenTemp]>0}
 } {0}
 
+# Ticket #334:  REPLACE statement corrupting indices.
+#
+do_test insert-6.1 {
+  execsql {
+    CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
+    INSERT INTO t1 VALUES(1,2);
+    INSERT INTO t1 VALUES(2,3);
+    SELECT b FROM t1 WHERE b=2;
+  }
+} {2}
+do_test insert-6.2 {
+  execsql {
+    REPLACE INTO t1 VALUES(1,4);
+    SELECT b FROM t1 WHERE b=2;
+  }
+} {}
 
 finish_test