aboutsummaryrefslogtreecommitdiff
path: root/src/upsert.c
diff options
context:
space:
mode:
authordrh <>2024-03-08 14:01:48 +0000
committerdrh <>2024-03-08 14:01:48 +0000
commit926fb60b05be799ff6e9f0013d2a0f393cfd380c (patch)
treec0da63211be0e1ec778187ea194e0917acccfc43 /src/upsert.c
parentb89aa10cd0d980563df54b5ad0fb2214f06c7c80 (diff)
downloadsqlite-926fb60b05be799ff6e9f0013d2a0f393cfd380c.tar.gz
sqlite-926fb60b05be799ff6e9f0013d2a0f393cfd380c.zip
Silently ignore redundant ON CONFLICT clauses in an UPSERT. Only the first
ON CONFLICT for each index is active. Do not issue an error, since that might break legacy queries. But ignore the redundant ON CONFLICT clauses to prevent problems such as described in [forum:/forumpost/919c6579c8|forum post 919c6579c8]. FossilOrigin-Name: d0ea6b6ba64dba9d68c2b391ccf1171ea96fcdd7409dafdb2b697accb00246b8
Diffstat (limited to 'src/upsert.c')
-rw-r--r--src/upsert.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/upsert.c b/src/upsert.c
index be0d0550d..f74d4fabf 100644
--- a/src/upsert.c
+++ b/src/upsert.c
@@ -90,7 +90,8 @@ Upsert *sqlite3UpsertNew(
int sqlite3UpsertAnalyzeTarget(
Parse *pParse, /* The parsing context */
SrcList *pTabList, /* Table into which we are inserting */
- Upsert *pUpsert /* The ON CONFLICT clauses */
+ Upsert *pUpsert, /* The ON CONFLICT clauses */
+ Upsert *pAll /* Complete list of all ON CONFLICT clauses */
){
Table *pTab; /* That table into which we are inserting */
int rc; /* Result code */
@@ -193,6 +194,14 @@ int sqlite3UpsertAnalyzeTarget(
continue;
}
pUpsert->pUpsertIdx = pIdx;
+ if( sqlite3UpsertOfIndex(pAll,pIdx)!=pUpsert ){
+ /* Really this should be an error. The isDup ON CONFLICT clause will
+ ** never fire. But this problem was not discovered until three years
+ ** after multi-CONFLICT upsert was added, and so we silently ignore
+ ** the problem to prevent breaking applications that might actually
+ ** have redundant ON CONFLICT clauses. */
+ pUpsert->isDup = 1;
+ }
break;
}
if( pUpsert->pUpsertIdx==0 ){
@@ -219,9 +228,13 @@ int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
Upsert *pNext;
if( NEVER(pUpsert==0) ) return 0;
pNext = pUpsert->pNextUpsert;
- if( pNext==0 ) return 1;
- if( pNext->pUpsertTarget==0 ) return 1;
- if( pNext->pUpsertIdx==0 ) return 1;
+ while( 1 /*exit-by-return*/ ){
+ if( pNext==0 ) return 1;
+ if( pNext->pUpsertTarget==0 ) return 1;
+ if( pNext->pUpsertIdx==0 ) return 1;
+ if( !pNext->isDup ) return 0;
+ pNext = pNext->pNextUpsert;
+ }
return 0;
}