From: drh Date: Thu, 19 Apr 2018 23:52:39 +0000 (+0000) Subject: Fix the handling of "PRAGMA count_changes=ON" with UPSERT. Also improved X-Git-Tag: version-3.24.0~133 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=796369131419dac03306ee3d2275cf68dab4b1b8;p=thirdparty%2Fsqlite.git Fix the handling of "PRAGMA count_changes=ON" with UPSERT. Also improved the implementation of count_changes in other places, without changing the behavior. FossilOrigin-Name: c6f71115eb933c2aee295bc31e5139112463c28e15a3b3ea242fd9bac168aed9 --- diff --git a/manifest b/manifest index dd60c0f688..333a1c93ac 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\ssimplification\sto\sthe\supsert\slogic. -D 2018-04-19T21:29:52.191 +C Fix\sthe\shandling\sof\s"PRAGMA\scount_changes=ON"\swith\sUPSERT.\s\sAlso\simproved\nthe\simplementation\sof\scount_changes\sin\sother\splaces,\swithout\schanging\sthe\nbehavior. +D 2018-04-19T23:52:39.113 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -443,7 +443,7 @@ F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48 F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 -F src/delete.c 20c8788451dc737a967c87ea53ad43544d617f5b57d32ccce8bd52a0daf9e89b +F src/delete.c 333aca5587c690bbc460c9b2e6842e7080b1f7abac0e6ca4d3f82c2aea328def F src/expr.c 53df437b3a4a404f039645919b2d6a56a2f59b9883e858940cd2a8858a25cd3d F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 @@ -453,7 +453,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 b382941c8f86cda8aa91452e80d02cea2c2631d52ab7cf7523314ee46bab7f39 +F src/insert.c 87b1854f48145d1db15b97128922348d90fbb2a0bd317e4d0ad6eee1361f4b66 F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302 F src/main.c 10e3897f5d78cef6bcbd1eedc8ccc3fe9e9783d07e052d9d70e57364ded19274 @@ -557,7 +557,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 5b0c661a85f783d35b9883830736eeb63be4aefc4f6b7d9cd081d48782c041e2 F src/treeview.c 14d5d1254702ec96876aa52642cb31548612384134970409fae333b25b39d6bb F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995 -F src/update.c 5787acf0a12a20cf31c0c50db644a667590f720e404b3616bc2efeb9bd5bbc06 +F src/update.c cc691c8b63b22be9e00d6fa2d1c5d561a5cee871f4ed5c456762398c6c991d05 F src/upsert.c ee5c9e44fac181e86a561c2d315c28f4c0f94e9d3283544bd39aa0e201b0c61c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 @@ -1509,7 +1509,7 @@ F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97 F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8 F test/update.test 1148de8d913e9817717990603aadeca07aab9ddbb10a30f167cbfd8d3a3ccb60 F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e -F test/upsert1.test 3b4e8e5932516115bfffb2269a44c416c5c26d0d57cc7dd16954d0b77fbc4cd9 +F test/upsert1.test 934315888a04b4e119ebb6abf558d92bf01d9f94fc8ff0bbc1c7c6015005340f F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09 F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c F test/upsert4.test 83b37a92f315217c9319f320966c044ddccf8bc525501fa09e2ee47779e3920b @@ -1724,7 +1724,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 893e6089c875e947ddadb23f031a81bc36da8b060d2212363098992ddb90378b -R 55c8d974783bb4b8502a146618675105 +P e657c1d60f5fca9464e9bcab24bc328855bec9986e0a029877f639355da4b201 +R 7cdcf758f67dbc731422788f5f4662ec U drh -Z 7c8bbf0c90fa7ebf24724a77ea4ecc1b +Z 0ab3e82b91f879d52dd2122af2ad30bf diff --git a/manifest.uuid b/manifest.uuid index 08b688798f..0a2e181274 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e657c1d60f5fca9464e9bcab24bc328855bec9986e0a029877f639355da4b201 \ No newline at end of file +c6f71115eb933c2aee295bc31e5139112463c28e15a3b3ea242fd9bac168aed9 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index 2b69e4763a..7a33fcf6cd 100644 --- a/src/delete.c +++ b/src/delete.c @@ -238,7 +238,7 @@ void sqlite3DeleteFrom( AuthContext sContext; /* Authorization context */ NameContext sNC; /* Name context to resolve expressions in */ int iDb; /* Database number */ - int memCnt = -1; /* Memory cell used for change counting */ + int memCnt = 0; /* Memory cell used for change counting */ int rcauth; /* Value returned by authorization callback */ int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ @@ -371,7 +371,10 @@ void sqlite3DeleteFrom( /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ - if( db->flags & SQLITE_CountRows ){ + if( (db->flags & SQLITE_CountRows)!=0 + && !pParse->nested + && !pParse->pTriggerTab + ){ memCnt = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); } @@ -399,7 +402,7 @@ void sqlite3DeleteFrom( assert( !isView ); sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); if( HasRowid(pTab) ){ - sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, + sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1, pTab->zName, P4_STATIC); } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ @@ -446,7 +449,7 @@ void sqlite3DeleteFrom( assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); /* Keep track of the number of rows to be deleted */ - if( db->flags & SQLITE_CountRows ){ + if( memCnt ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); } @@ -589,7 +592,7 @@ void sqlite3DeleteFrom( ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ - if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ + if( memCnt ){ sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); diff --git a/src/insert.c b/src/insert.c index e522d4664f..b3a313836e 100644 --- a/src/insert.c +++ b/src/insert.c @@ -784,7 +784,10 @@ void sqlite3Insert( /* Initialize the count of rows to be inserted */ - if( db->flags & SQLITE_CountRows ){ + if( (db->flags & SQLITE_CountRows)!=0 + && !pParse->nested + && !pParse->pTriggerTab + ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } @@ -1040,7 +1043,7 @@ void sqlite3Insert( /* Update the count of rows that are inserted */ - if( (db->flags & SQLITE_CountRows)!=0 ){ + if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } @@ -1077,7 +1080,7 @@ insert_end: ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ - if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ + if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); diff --git a/src/update.c b/src/update.c index 4da63a98ec..c817153e8e 100644 --- a/src/update.c +++ b/src/update.c @@ -384,7 +384,11 @@ void sqlite3Update( #endif /* Initialize the count of updated rows */ - if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ + if( (db->flags&SQLITE_CountRows)!=0 + && !pParse->pTriggerTab + && !pParse->nested + && !pUpsert + ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } @@ -699,7 +703,7 @@ void sqlite3Update( /* Increment the row counter */ - if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ + if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } @@ -731,11 +735,10 @@ void sqlite3Update( } /* - ** Return the number of rows that were changed. If this routine is - ** generating code because of a call to sqlite3NestedParse(), do not - ** invoke the callback function. + ** Return the number of rows that were changed, if we are tracking + ** that information. */ - if( (db->flags&SQLITE_CountRows) && !pParse->pTriggerTab && !pParse->nested ){ + if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); diff --git a/test/upsert1.test b/test/upsert1.test index 8b53fe0c15..c9139f1163 100644 --- a/test/upsert1.test +++ b/test/upsert1.test @@ -89,4 +89,19 @@ do_execsql_test upsert1-320 { SELECT *, 'x' FROM t1 ORDER BY b, a; } {1 2 0 x 3 2 0 x 4 20 0 x} +# Upsert works with count_changes=on; +do_execsql_test upsert1-400 { + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(a TEXT UNIQUE, b INT DEFAULT 1); + INSERT INTO t2(a) VALUES('one'),('two'),('three'); + PRAGMA count_changes=ON; + INSERT INTO t2(a) VALUES('one'),('one'),('three'),('four') + ON CONFLICT(a) DO UPDATE SET b=b+1; +} {1} +do_execsql_test upsert1-410 { + PRAGMA count_changes=OFF; + SELECT a, b FROM t2 ORDER BY a; +} {four 1 one 3 three 2 two 1} + + finish_test