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

Commit 3c7afd5

Browse files
michail-nikolaevCommitfest Bot
authored and
Commitfest Bot
committed
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 77e7218 commit 3c7afd5

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
@@ -486,6 +486,48 @@ ExecFindPartition(ModifyTableState *mtstate,
486486
return rri;
487487
}
488488

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

700744
childIdxs = RelationGetIndexList(leaf_part_rri->ri_RelationDesc);
701745

@@ -706,23 +750,74 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
706750
ListCell *lc2;
707751

708752
ancestors = get_partition_ancestors(childIdx);
709-
foreach(lc2, rootResultRelInfo->ri_onConflictArbiterIndexes)
753+
if (ancestors)
710754
{
711-
if (list_member_oid(ancestors, lfirst_oid(lc2)))
712-
arbiterIndexes = lappend_oid(arbiterIndexes, childIdx);
755+
foreach(lc2, rootResultRelInfo->ri_onConflictArbiterIndexes)
756+
{
757+
if (list_member_oid(ancestors, lfirst_oid(lc2)))
758+
arbiterIndexes = lappend_oid(arbiterIndexes, childIdx);
759+
}
713760
}
761+
else /* No ancestor was found for that index. Save it for rechecking later. */
762+
nonAncestorIdxs = lappend_oid(nonAncestorIdxs, childIdx);
714763
list_free(ancestors);
715764
}
716-
}
717765

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

728823
/*

0 commit comments

Comments
 (0)