Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 11035e7

Browse files
michail-nikolaevCommitfest Bot
authored and
Commitfest Bot
committed
Modify the infer_arbiter_indexes function to consider both indisvalid and indisready indexes. Ensure that at least one indisvalid index is still required.
The change ensures that all concurrent transactions utilize the same set of indexes as arbiters. This uniformity is required to avoid conditions that could lead to "duplicate key value violates unique constraint" errors during UPSERT operations. The patch resolves the issues in the following specs: * reindex_concurrently_upsert * index_concurrently_upsert * index_concurrently_upsert_predicate Despite the patch, the following specs are still affected: * reindex_concurrently_upsert_partitioned * reindex_concurrently_upsert_on_constraint
1 parent e621150 commit 11035e7

File tree

1 file changed

+13
-5
lines changed

1 file changed

+13
-5
lines changed

src/backend/optimizer/util/plancat.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,7 @@ infer_arbiter_indexes(PlannerInfo *root)
722722

723723
/* Results */
724724
List *results = NIL;
725+
bool foundValid = false;
725726

726727
/*
727728
* Quickly return NIL for ON CONFLICT DO NOTHING without an inference
@@ -815,7 +816,13 @@ infer_arbiter_indexes(PlannerInfo *root)
815816
idxRel = index_open(indexoid, rte->rellockmode);
816817
idxForm = idxRel->rd_index;
817818

818-
if (!idxForm->indisvalid)
819+
/*
820+
* We need to consider both indisvalid and indisready indexes because
821+
* them may become indisvalid before execution phase. It is required
822+
* to keep set of indexes used as arbiter to be the same for all
823+
* concurrent transactions.
824+
*/
825+
if (!idxForm->indisready)
819826
goto next;
820827

821828
/*
@@ -837,10 +844,9 @@ infer_arbiter_indexes(PlannerInfo *root)
837844
errmsg("ON CONFLICT DO UPDATE not supported with exclusion constraints")));
838845

839846
results = lappend_oid(results, idxForm->indexrelid);
840-
list_free(indexList);
847+
foundValid |= idxForm->indisvalid;
841848
index_close(idxRel, NoLock);
842-
table_close(relation, NoLock);
843-
return results;
849+
break;
844850
}
845851
else if (indexOidFromConstraint != InvalidOid)
846852
{
@@ -941,14 +947,16 @@ infer_arbiter_indexes(PlannerInfo *root)
941947
goto next;
942948

943949
results = lappend_oid(results, idxForm->indexrelid);
950+
foundValid |= idxForm->indisvalid;
944951
next:
945952
index_close(idxRel, NoLock);
946953
}
947954

948955
list_free(indexList);
949956
table_close(relation, NoLock);
950957

951-
if (results == NIL)
958+
/* It is required to have at least one indisvalid index during the planning. */
959+
if (results == NIL || !foundValid)
952960
ereport(ERROR,
953961
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
954962
errmsg("there is no unique or exclusion constraint matching the ON CONFLICT specification")));

0 commit comments

Comments
 (0)