Skip to content

Commit d7ca028

Browse files
michail-nikolaevCommitfest Bot
authored andcommitted
Modify the ExecInitPartitionInfo function to consider partitioned indexes that are potentially processed by REINDEX CONCURRENTLY as arbiters as well.
This is necessary to ensure that all concurrent transactions use the same set of arbiter indexes. The patch resolves the issues in the following specs: * reindex_concurrently_upsert_partitioned
1 parent 2516006 commit d7ca028

File tree

1 file changed

+107
-12
lines changed

1 file changed

+107
-12
lines changed

src/backend/executor/execPartition.c

Lines changed: 107 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,48 @@ ExecFindPartition(ModifyTableState *mtstate,
490490
return rri;
491491
}
492492

493+
/*
494+
* IsIndexCompatibleAsArbiter
495+
* Checks if the indexes are identical in terms of being used
496+
* as arbiters for the INSERT ON CONFLICT operation by comparing
497+
* them to the provided arbiter index.
498+
*
499+
* Returns the true if indexes are compatible.
500+
*/
501+
static bool
502+
IsIndexCompatibleAsArbiter(Relation arbiterIndexRelation,
503+
IndexInfo *arbiterIndexInfo,
504+
Relation indexRelation,
505+
IndexInfo *indexInfo)
506+
{
507+
int i;
508+
509+
if (arbiterIndexInfo->ii_Unique != indexInfo->ii_Unique)
510+
return false;
511+
/* it is not supported for cases of exclusion constraints. */
512+
if (arbiterIndexInfo->ii_ExclusionOps != NULL || indexInfo->ii_ExclusionOps != NULL)
513+
return false;
514+
if (arbiterIndexRelation->rd_index->indnkeyatts != indexRelation->rd_index->indnkeyatts)
515+
return false;
516+
517+
for (i = 0; i < indexRelation->rd_index->indnkeyatts; i++)
518+
{
519+
int arbiterAttoNo = arbiterIndexRelation->rd_index->indkey.values[i];
520+
int attoNo = indexRelation->rd_index->indkey.values[i];
521+
if (arbiterAttoNo != attoNo)
522+
return false;
523+
}
524+
525+
if (list_difference(RelationGetIndexExpressions(arbiterIndexRelation),
526+
RelationGetIndexExpressions(indexRelation)) != NIL)
527+
return false;
528+
529+
if (list_difference(RelationGetIndexPredicate(arbiterIndexRelation),
530+
RelationGetIndexPredicate(indexRelation)) != NIL)
531+
return false;
532+
return true;
533+
}
534+
493535
/*
494536
* ExecInitPartitionInfo
495537
* Lock the partition and initialize ResultRelInfo. Also setup other
@@ -701,6 +743,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
701743
if (rootResultRelInfo->ri_onConflictArbiterIndexes != NIL)
702744
{
703745
List *childIdxs;
746+
List *nonAncestorIdxs = NIL;
747+
int i, j, additional_arbiters = 0;
704748

705749
childIdxs = RelationGetIndexList(leaf_part_rri->ri_RelationDesc);
706750

@@ -711,23 +755,74 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
711755
ListCell *lc2;
712756

713757
ancestors = get_partition_ancestors(childIdx);
714-
foreach(lc2, rootResultRelInfo->ri_onConflictArbiterIndexes)
758+
if (ancestors)
715759
{
716-
if (list_member_oid(ancestors, lfirst_oid(lc2)))
717-
arbiterIndexes = lappend_oid(arbiterIndexes, childIdx);
760+
foreach(lc2, rootResultRelInfo->ri_onConflictArbiterIndexes)
761+
{
762+
if (list_member_oid(ancestors, lfirst_oid(lc2)))
763+
arbiterIndexes = lappend_oid(arbiterIndexes, childIdx);
764+
}
718765
}
766+
else /* No ancestor was found for that index. Save it for rechecking later. */
767+
nonAncestorIdxs = lappend_oid(nonAncestorIdxs, childIdx);
719768
list_free(ancestors);
720769
}
721-
}
722770

723-
/*
724-
* If the resulting lists are of inequal length, something is wrong.
725-
* (This shouldn't happen, since arbiter index selection should not
726-
* pick up an invalid index.)
727-
*/
728-
if (list_length(rootResultRelInfo->ri_onConflictArbiterIndexes) !=
729-
list_length(arbiterIndexes))
730-
elog(ERROR, "invalid arbiter index list");
771+
/*
772+
* If any non-ancestor indexes are found, we need to compare them with other
773+
* indexes of the relation that will be used as arbiters. This is necessary
774+
* when a partitioned index is processed by REINDEX CONCURRENTLY. Both indexes
775+
* must be considered as arbiters to ensure that all concurrent transactions
776+
* use the same set of arbiters.
777+
*/
778+
if (nonAncestorIdxs)
779+
{
780+
for (i = 0; i < leaf_part_rri->ri_NumIndices; i++)
781+
{
782+
if (list_member_oid(nonAncestorIdxs, leaf_part_rri->ri_IndexRelationDescs[i]->rd_index->indexrelid))
783+
{
784+
Relation nonAncestorIndexRelation = leaf_part_rri->ri_IndexRelationDescs[i];
785+
IndexInfo *nonAncestorIndexInfo = leaf_part_rri->ri_IndexRelationInfo[i];
786+
Assert(!list_member_oid(arbiterIndexes, nonAncestorIndexRelation->rd_index->indexrelid));
787+
788+
/* It is too early to us non-ready indexes as arbiters */
789+
if (!nonAncestorIndexInfo->ii_ReadyForInserts)
790+
continue;
791+
792+
for (j = 0; j < leaf_part_rri->ri_NumIndices; j++)
793+
{
794+
if (list_member_oid(arbiterIndexes,
795+
leaf_part_rri->ri_IndexRelationDescs[j]->rd_index->indexrelid))
796+
{
797+
Relation arbiterIndexRelation = leaf_part_rri->ri_IndexRelationDescs[j];
798+
IndexInfo *arbiterIndexInfo = leaf_part_rri->ri_IndexRelationInfo[j];
799+
800+
/* If non-ancestor index are compatible to arbiter - use it as arbiter too. */
801+
if (IsIndexCompatibleAsArbiter(arbiterIndexRelation, arbiterIndexInfo,
802+
nonAncestorIndexRelation, nonAncestorIndexInfo))
803+
{
804+
arbiterIndexes = lappend_oid(arbiterIndexes,
805+
nonAncestorIndexRelation->rd_index->indexrelid);
806+
additional_arbiters++;
807+
}
808+
}
809+
}
810+
}
811+
}
812+
}
813+
list_free(nonAncestorIdxs);
814+
815+
/*
816+
* If the resulting lists are of inequal length, something is wrong.
817+
* (This shouldn't happen, since arbiter index selection should not
818+
* pick up a non-ready index.)
819+
*
820+
* But we need to consider an additional arbiter indexes also.
821+
*/
822+
if (list_length(rootResultRelInfo->ri_onConflictArbiterIndexes) !=
823+
list_length(arbiterIndexes) - additional_arbiters)
824+
elog(ERROR, "invalid arbiter index list");
825+
}
731826
leaf_part_rri->ri_onConflictArbiterIndexes = arbiterIndexes;
732827

733828
/*

0 commit comments

Comments
 (0)