]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Get the ON CONFLICT DO NOTHING form of upsert working by mapping it
authordrh <drh@noemail.net>
Fri, 13 Apr 2018 15:14:33 +0000 (15:14 +0000)
committerdrh <drh@noemail.net>
Fri, 13 Apr 2018 15:14:33 +0000 (15:14 +0000)
into INSERT OR IGNORE.

FossilOrigin-Name: d07f05e98bb9ce0f9b46db159d9df161b7499d6face6a5299ecd2d00a94fb8d0

manifest
manifest.uuid
src/insert.c
src/sqliteInt.h
test/upsert1.test

index 17b93e92e935e503d5d8d4dcda6aa347dd62ad62..78a34e9019193648d713a8406dbecddf4b2fb7e1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Get\sthe\sconflict-target\sclause\sparsing\sworking\scorrectly,\swith\stest\ncases.\s\sThis\schange\sinvolves\san\senhancement\sto\ssqlite3ExprCompare()\swhich\nneeds\sto\sbe\sreviewed\son\strunk\sprior\sto\smerging.
-D 2018-04-13T14:27:01.434
+C Get\sthe\sON\sCONFLICT\sDO\sNOTHING\sform\sof\supsert\sworking\sby\smapping\sit\ninto\sINSERT\sOR\sIGNORE.
+D 2018-04-13T15:14:33.373
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439
@@ -452,7 +452,7 @@ F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
 F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 86652dd33f0b7b3402502e3bf6d03950e8695a0d6ca4cf9b7a40a9d4f1b95784
+F src/insert.c c98142d22fd01ff0202707f0303ebaec9130fc82ad0ea5ab80e680db3cdddb68
 F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
 F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302
 F src/main.c 1648fc7a9bcfdbfd9a9a04af96ff2796c3164b3f3c7e56ed63a3c51cd11d198d
@@ -496,7 +496,7 @@ F src/shell.c.in cc960721e56ebc1a78773bb5d2f5608b54275f945cbe49e4afe919d6888062a
 F src/sqlite.h.in e0be726ea6e4e6571724d39d242472ecd8bd1ba6f84ade88e1641bde98a6d02b
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d
-F src/sqliteInt.h 97119c8dcc755053fd65d4f5792c9a4f9e0de7e55f29e1ba7d87c7ce09cfe1ab
+F src/sqliteInt.h c1df61473de148aa8b54746820e7681baeec5ac8f7108a9fef6a5d7452114db8
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -1507,7 +1507,7 @@ F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
 F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
 F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
 F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e
-F test/upsert1.test 81966c8ef85a17dc3876df83ef79d7b52406ee5b65844b1712fab511fbff0e12
+F test/upsert1.test 3b4e8e5932516115bfffb2269a44c416c5c26d0d57cc7dd16954d0b77fbc4cd9
 F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
 F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
 F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
@@ -1719,7 +1719,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 98d32ba661f4ba662b639994b74352b695d53a33bc8a498bd09b9e02f794c81e
-R f8a0c129a96135656330bef5f8887505
+P 5bf704256206f84b3db7a5d8523215604eeb218ef8db86316d1e43ecd7248d6a
+R b55b644f71d34f63deccb0bd6658d5b2
 U drh
-Z 96fe68f62146018e2ed5b3343db81409
+Z ce27c0e93f96216c50bc25467b98e880
index 86d0f26f6a542ed23f18118ebe6f55165d65668d..d894ab539b730a127125c431fe492176595c561d 100644 (file)
@@ -1 +1 @@
-5bf704256206f84b3db7a5d8523215604eeb218ef8db86316d1e43ecd7248d6a
\ No newline at end of file
+d07f05e98bb9ce0f9b46db159d9df161b7499d6face6a5299ecd2d00a94fb8d0
\ No newline at end of file
index f399f141736c850e0955cdf427468a5813f48ae3..df2f3f6ea47de884dbf5f270704018dd99c3a8f4 100644 (file)
@@ -1396,6 +1396,15 @@ void sqlite3GenerateConstraintChecks(
       VdbeCoverage(v);
     }
 
+    /* figure out whether or not upsert applies in this case */
+    if( pUpsert && (pUpsert->pUpsertTarget==0 || pUpsert->pUpsertIdx==0) ){
+      if( pUpsert->pUpsertSet==0 ){
+        onError = OE_Ignore;  /* DO NOTHING is the same as INSERT OR IGNORE */
+      }else{
+        onError = OE_Update;  /* DO UPDATE */
+      }
+    }
+
     /* If the response to a rowid conflict is REPLACE but the response
     ** to some other UNIQUE constraint is FAIL or IGNORE, then we need
     ** to defer the running of the rowid conflict checking until after
@@ -1415,7 +1424,6 @@ void sqlite3GenerateConstraintChecks(
     sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
     VdbeCoverage(v);
 
-    /* Generate code that deals with a rowid collision */
     switch( onError ){
       default: {
         onError = OE_Abort;
@@ -1478,7 +1486,6 @@ void sqlite3GenerateConstraintChecks(
         break;
       }
       case OE_Ignore: {
-        /*assert( seenReplace==0 );*/
         sqlite3VdbeGoto(v, ignoreDest);
         break;
       }
@@ -1569,6 +1576,15 @@ void sqlite3GenerateConstraintChecks(
       onError = OE_Abort;
     }
 
+    /* Figure out if the upsert clause applies to this index */
+    if( pUpsert && (pUpsert->pUpsertTarget==0 || pUpsert->pUpsertIdx==pIdx) ){
+      if( pUpsert->pUpsertSet==0 ){
+        onError = OE_Ignore;  /* DO NOTHING is the same as INSERT OR IGNORE */
+      }else{
+        onError = OE_Update;  /* DO UPDATE */
+      }
+    }
+
     /* Collision detection may be omitted if all of the following are true:
     **   (1) The conflict resolution algorithm is REPLACE
     **   (2) The table is a WITHOUT ROWID table
index 7bbe255bcff58b4546a0529275d3e58fbc461ed2..d611f49135458e8ca2f7077b081f4b594c8c94a3 100644 (file)
@@ -2047,13 +2047,12 @@ struct FKey {
 #define OE_Fail     3   /* Stop the operation but leave all prior changes */
 #define OE_Ignore   4   /* Ignore the error. Do not do the INSERT or UPDATE */
 #define OE_Replace  5   /* Delete existing record, then do INSERT or UPDATE */
-
-#define OE_Restrict 6   /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
-#define OE_SetNull  7   /* Set the foreign key value to NULL */
-#define OE_SetDflt  8   /* Set the foreign key value to its default */
-#define OE_Cascade  9   /* Cascade the changes */
-
-#define OE_Default  10  /* Do whatever the default action is */
+#define OE_Update   6   /* Process as a DO UPDATE in an upsert */
+#define OE_Restrict 7   /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
+#define OE_SetNull  8   /* Set the foreign key value to NULL */
+#define OE_SetDflt  9   /* Set the foreign key value to its default */
+#define OE_Cascade  10  /* Cascade the changes */
+#define OE_Default  11  /* Do whatever the default action is */
 
 
 /*
index e94b00c9bfb847aa97b1eb9a249c8a0e6812d179..8b53fe0c15bfb79fc00acfb4565524db08533c5b 100644 (file)
@@ -19,16 +19,19 @@ do_execsql_test upsert1-100 {
   CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c DEFAULT 0);
   CREATE UNIQUE INDEX t1x1 ON t1(b);
   INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT DO NOTHING;
+  INSERT INTO t1(a,b) VALUES(1,99),(99,2) ON CONFLICT DO NOTHING;
   SELECT * FROM t1;
 } {1 2 0}
 do_execsql_test upsert1-101 {
   DELETE FROM t1;
   INSERT INTO t1(a,b) VALUES(2,3) ON CONFLICT(a) DO NOTHING;
+  INSERT INTO t1(a,b) VALUES(2,99) ON CONFLICT(a) DO NOTHING;
   SELECT * FROM t1;
 } {2 3 0}
 do_execsql_test upsert1-102 {
   DELETE FROM t1;
   INSERT INTO t1(a,b) VALUES(3,4) ON CONFLICT(b) DO NOTHING;
+  INSERT INTO t1(a,b) VALUES(99,4) ON CONFLICT(b) DO NOTHING;
   SELECT * FROM t1;
 } {3 4 0}
 do_catchsql_test upsert1-110 {
@@ -51,15 +54,19 @@ do_execsql_test upsert1-140 {
 } {5 6 0}
 
 do_catchsql_test upsert1-200 {
-  DROP INDEX t1x1;
-  DELETE FROM t1;
-  CREATE UNIQUE INDEX t1x1 ON t1(a||b);
-  INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(a||b) DO NOTHING;
+  DROP TABLE t1;
+  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c DEFAULT 0);
+  CREATE UNIQUE INDEX t1x1 ON t1(a+b);
+  INSERT INTO t1(a,b) VALUES(7,8) ON CONFLICT(a+b) DO NOTHING;
+  INSERT INTO t1(a,b) VALUES(8,7),(9,6) ON CONFLICT(a+b) DO NOTHING;
   SELECT * FROM t1;
-} {0 {5 6 0}}
+} {0 {7 8 0}}
+do_catchsql_test upsert1-201 {
+  INSERT INTO t1(a,b) VALUES(8,7),(9,6) ON CONFLICT(a) DO NOTHING;
+} {1 {UNIQUE constraint failed: index 't1x1'}}
 do_catchsql_test upsert1-210 {
   DELETE FROM t1;
-  INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(a||+b) DO NOTHING;
+  INSERT INTO t1(a,b) VALUES(9,10) ON CONFLICT(a+(+b)) DO NOTHING;
   SELECT * FROM t1;
 } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}}
 
@@ -67,18 +74,19 @@ do_catchsql_test upsert1-300 {
   DROP INDEX t1x1;
   DELETE FROM t1;
   CREATE UNIQUE INDEX t1x1 ON t1(b) WHERE b>10;
-  INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(b) DO NOTHING;
+  INSERT INTO t1(a,b) VALUES(1,2),(3,2) ON CONFLICT(b) DO NOTHING;
   SELECT * FROM t1;
 } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}}
 do_catchsql_test upsert1-310 {
   DELETE FROM t1;
-  INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(b) WHERE b!=10 DO NOTHING;
+  INSERT INTO t1(a,b) VALUES(1,2),(3,2) ON CONFLICT(b) WHERE b!=10 DO NOTHING;
   SELECT * FROM t1;
 } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}}
 do_execsql_test upsert1-320 {
   DELETE FROM t1;
-  INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(b) WHERE b>10 DO NOTHING;
-  SELECT * FROM t1;
-} {5 6 0}
+  INSERT INTO t1(a,b) VALUES(1,2),(3,2),(4,20),(5,20)
+         ON CONFLICT(b) WHERE b>10 DO NOTHING;
+  SELECT *, 'x' FROM t1 ORDER BY b, a;
+} {1 2 0 x 3 2 0 x 4 20 0 x}
 
 finish_test