]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Unless the destination table is completely empty, disable the xfer optimization for...
authordan <dan@noemail.net>
Tue, 5 Nov 2013 16:39:31 +0000 (16:39 +0000)
committerdan <dan@noemail.net>
Tue, 5 Nov 2013 16:39:31 +0000 (16:39 +0000)
FossilOrigin-Name: 3877c9f50582b51817dcf3cd75d836891a34e590

manifest
manifest.uuid
src/insert.c
test/tester.tcl
test/without_rowid1.test

index 6a2b3611951fdb61a2bde09f1be50f18604d17f7..a63c3a21799df592b53f618067a0a54aaa3dbbc9 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Updates\sto\sthe\sbackcompat.test\stest\sscript\sso\sthat\sit\sworks\swith\sreally\sold\s(3.6.*)\sversions.
-D 2013-11-05T15:02:39.443
+C Unless\sthe\sdestination\stable\sis\scompletely\sempty,\sdisable\sthe\sxfer\soptimization\sfor\sWITHOUT\sROWID\stables.
+D 2013-11-05T16:39:31.103
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -182,7 +182,7 @@ F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c 37bbaf90c077a8a8a6a5831d66c223b66e8272ae
+F src/insert.c 7559252147d3aad55951ecd5fadf8350729cb901
 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
 F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
@@ -831,7 +831,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
 F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
 F test/temptrigger.test 0a48d94222d50e6e50d72ac103606c4f8e7cbb81
-F test/tester.tcl 901258f2825cb712be4093bcd9317082d26a9901
+F test/tester.tcl b95c4e385003665c729bed9dbd385c42c80daeef
 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1078,7 +1078,7 @@ F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
 F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
 F test/win32longpath.test e2aafc07e6990fe86c69be22a3d1a0e210cd329b
-F test/without_rowid1.test 0b349aa31554afcee213ccabf4d259f4ff13a86a
+F test/without_rowid1.test ba137a86e4dcd23c72b6fce8ee4cee98cbf27784
 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
 F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0
 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
@@ -1133,7 +1133,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 99b1fa4b1664a79eae1dddce2b9a848384cdb1d7
-R 9237f8c5de7d66fb8a3d16e086790bd9
+P ace7e7b64261aeabc9525d5d0cfebe0275c9ddf5
+R 69c353523dfa3ba1b61ddb6b7043eeaf
 U dan
-Z e1e8e8d809370991b491bb9af478a65e
+Z b3aef9b0bbf6405eadeabac5f2f1c980
index 6efb4b3dac0239347faf897b4d76f2e3555c190d..fdbe26a0d124ca31d807a8cd1ab0996af2f9696d 100644 (file)
@@ -1 +1 @@
-ace7e7b64261aeabc9525d5d0cfebe0275c9ddf5
\ No newline at end of file
+3877c9f50582b51817dcf3cd75d836891a34e590
\ No newline at end of file
index 90752033a5d1bf7eabbc09bcb680027306dc745a..d65c49ed58e0d2525c9cfa7b4c87d26977a3d701 100644 (file)
@@ -1897,9 +1897,6 @@ static int xferOptimization(
   if( pDest->iPKey!=pSrc->iPKey ){
     return 0;   /* Both tables must have the same INTEGER PRIMARY KEY */
   }
-  if( HasRowid(pDest)!=HasRowid(pSrc) ){
-    return 0;   /* source and destination must both be WITHOUT ROWID or not */
-  }
   for(i=0; i<pDest->nCol; i++){
     if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){
       return 0;    /* Affinity must be the same on all columns */
@@ -1958,32 +1955,31 @@ static int xferOptimization(
   regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
   regData = sqlite3GetTempReg(pParse);
   regRowid = sqlite3GetTempReg(pParse);
+  sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
+  assert( HasRowid(pDest) || destHasUniqueIdx );
+  if( (pDest->iPKey<0 && pDest->pIndex!=0)          /* (1) */
+   || destHasUniqueIdx                              /* (2) */
+   || (onError!=OE_Abort && onError!=OE_Rollback)   /* (3) */
+  ){
+    /* In some circumstances, we are able to run the xfer optimization
+    ** only if the destination table is initially empty.  This code makes
+    ** that determination.  Conditions under which the destination must
+    ** be empty:
+    **
+    ** (1) There is no INTEGER PRIMARY KEY but there are indices.
+    **     (If the destination is not initially empty, the rowid fields
+    **     of index entries might need to change.)
+    **
+    ** (2) The destination has a unique index.  (The xfer optimization 
+    **     is unable to test uniqueness.)
+    **
+    ** (3) onError is something other than OE_Abort and OE_Rollback.
+    */
+    addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0);
+    emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
+    sqlite3VdbeJumpHere(v, addr1);
+  }
   if( HasRowid(pSrc) ){
-    sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
-    if( (pDest->iPKey<0 && pDest->pIndex!=0)          /* (1) */
-     || destHasUniqueIdx                              /* (2) */
-     || (onError!=OE_Abort && onError!=OE_Rollback)   /* (3) */
-    ){
-      /* In some circumstances, we are able to run the xfer optimization
-      ** only if the destination table is initially empty.  This code makes
-      ** that determination.  Conditions under which the destination must
-      ** be empty:
-      **
-      ** (1) There is no INTEGER PRIMARY KEY but there are indices.
-      **     (If the destination is not initially empty, the rowid fields
-      **     of index entries might need to change.)
-      **
-      ** (2) The destination has a unique index.  (The xfer optimization 
-      **     is unable to test uniqueness.)
-      **
-      ** (3) onError is something other than OE_Abort and OE_Rollback.
-      */
-      addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0);
-      emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
-      sqlite3VdbeJumpHere(v, addr1);
-    }else{
-      emptyDestTest = 0;
-    }
     sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
     emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
     if( pDest->iPKey>=0 ){
index 3b65127084b4edb217f77841e33c29214eba40d7..27aa08dbe1c90aff8c960dc527fa18743d1b3e47 100644 (file)
@@ -1028,14 +1028,15 @@ proc explain_i {sql {db db}} {
   puts "addr  opcode        p1      p2      p3      p4                p5  #"
   puts "----  ------------  ------  ------  ------  ----------------  --  -"
 
-  set addrTail 0
 
+  set bSeenGoto 0
   $db eval "explain $sql" {} {
     set x($addr) 0
     set op($addr) $opcode
 
-    if {$opcode == "Goto" && $addrTail==0} {
-      set addrTail $p2
+    if {$opcode == "Goto" && ($bSeenGoto==0 || ($p2 > $addr+10))} {
+      set linebreak($p2) 1
+      set bSeenGoto 1
     }
 
     if {$opcode == "Next"} {
@@ -1049,20 +1050,20 @@ proc explain_i {sql {db db}} {
         incr x($i) 2
       }
     }
+
+    if {$opcode == "Halt" && $comment == "End of coroutine"} {
+      set linebreak([expr $addr+1]) 1
+    }
   }
 
   $db eval "explain $sql" {} {
-    if {$addr == $addrTail} {
+    if {[info exists linebreak($addr)]} {
       puts ""
     }
     set I [string repeat " " $x($addr)]
     puts [format {%-4d  %s%-12.12s  %-6d  %-6d  %-6d  % -17s %s  %s} \
       $addr $I $opcode $p1 $p2 $p3 $p4 $p5 $comment
     ]
-
-    if {$opcode == "Halt" && $comment == "End of coroutine"} {
-      puts ""
-    }
   }
   puts "----  ------------  ------  ------  ------  ----------------  --  -"
 }
index 5a50941857a828fa05a54c6df3351e7f4585a11a..1da8c3c3d6d800f48108fd0ae86ec341df3a03d6 100644 (file)
@@ -153,6 +153,55 @@ do_execsql_test 2.4.2 {
   SELECT * FROM t6 ORDER BY c;
 } {ABC def ghi ABC def ghi}
 
+#-------------------------------------------------------------------------
+# Unless the destination table is completely empty, the xfer optimization 
+# is disabled for WITHOUT ROWID tables. The following tests check for
+# some problems that might occur if this were not the case.
+#
+reset_db
+do_execsql_test 3.1.1 {
+  CREATE TABLE t1(a, b, PRIMARY KEY(a)) WITHOUT ROWID;
+  CREATE UNIQUE INDEX i1 ON t1(b);
+
+  CREATE TABLE t2(a, b, PRIMARY KEY(a)) WITHOUT ROWID;
+  CREATE UNIQUE INDEX i2 ON t2(b);
+
+  INSERT INTO t1 VALUES('one', 'two');
+  INSERT INTO t2 VALUES('three', 'two');
+}
+
+do_execsql_test 3.1.2 {
+  INSERT OR REPLACE INTO t1 SELECT * FROM t2;
+  SELECT * FROM t1;
+} {three two}
+
+do_execsql_test 3.1.3 {
+  DELETE FROM t1;
+  INSERT INTO t1 SELECT * FROM t2;
+  SELECT * FROM t1;
+} {three two}
+
+do_catchsql_test 3.1.4 {
+  INSERT INTO t2 VALUES('four', 'four');
+  INSERT INTO t2 VALUES('six', 'two');
+  INSERT INTO t1 SELECT * FROM t2;
+} {1 {UNIQUE constraint failed: t2.b}}
+
+do_execsql_test 3.1.5 {
+  CREATE TABLE t3(a PRIMARY KEY);
+  CREATE TABLE t4(a PRIMARY KEY);
+
+  INSERT INTO t4 VALUES('i');
+  INSERT INTO t4 VALUES('ii');
+  INSERT INTO t4 VALUES('iii');
+
+  INSERT INTO t3 SELECT * FROM t4;
+  SELECT * FROM t3;
+} {i ii iii}
+  
+  explain_i {
+  INSERT INTO t3 SELECT * FROM t4;
+  }
 
 finish_test