@@ -131,7 +131,6 @@ static void SetReindexProcessing(Oid heapOid, Oid indexOid);
131
131
static void ResetReindexProcessing (void );
132
132
static void SetReindexPending (List * indexes );
133
133
static void RemoveReindexPending (Oid indexOid );
134
- static void ResetReindexPending (void );
135
134
136
135
137
136
/*
@@ -1543,8 +1542,8 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
1543
1542
newIndexForm -> indisclustered = oldIndexForm -> indisclustered ;
1544
1543
1545
1544
/*
1546
- * Mark the new index as valid, and the old index as invalid similarly
1547
- * to what index_set_state_flags() does.
1545
+ * Mark the new index as valid, and the old index as invalid similarly to
1546
+ * what index_set_state_flags() does.
1548
1547
*/
1549
1548
newIndexForm -> indisvalid = true;
1550
1549
oldIndexForm -> indisvalid = false;
@@ -3525,25 +3524,18 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
3525
3524
indexInfo -> ii_ExclusionStrats = NULL ;
3526
3525
}
3527
3526
3528
- /* ensure SetReindexProcessing state isn't leaked */
3529
- PG_TRY ();
3530
- {
3531
- /* Suppress use of the target index while rebuilding it */
3532
- SetReindexProcessing (heapId , indexId );
3527
+ /* Suppress use of the target index while rebuilding it */
3528
+ SetReindexProcessing (heapId , indexId );
3533
3529
3534
- /* Create a new physical relation for the index */
3535
- RelationSetNewRelfilenode (iRel , persistence );
3530
+ /* Create a new physical relation for the index */
3531
+ RelationSetNewRelfilenode (iRel , persistence );
3536
3532
3537
- /* Initialize the index and rebuild */
3538
- /* Note: we do not need to re-establish pkey setting */
3539
- index_build (heapRelation , iRel , indexInfo , true, true);
3540
- }
3541
- PG_FINALLY ();
3542
- {
3543
- /* Make sure flag gets cleared on error exit */
3544
- ResetReindexProcessing ();
3545
- }
3546
- PG_END_TRY ();
3533
+ /* Initialize the index and rebuild */
3534
+ /* Note: we do not need to re-establish pkey setting */
3535
+ index_build (heapRelation , iRel , indexInfo , true, true);
3536
+
3537
+ /* Re-allow use of target index */
3538
+ ResetReindexProcessing ();
3547
3539
3548
3540
/*
3549
3541
* If the index is marked invalid/not-ready/dead (ie, it's from a failed
@@ -3680,7 +3672,9 @@ reindex_relation(Oid relid, int flags, int options)
3680
3672
Relation rel ;
3681
3673
Oid toast_relid ;
3682
3674
List * indexIds ;
3675
+ char persistence ;
3683
3676
bool result ;
3677
+ ListCell * indexId ;
3684
3678
int i ;
3685
3679
3686
3680
/*
@@ -3715,77 +3709,65 @@ reindex_relation(Oid relid, int flags, int options)
3715
3709
*/
3716
3710
indexIds = RelationGetIndexList (rel );
3717
3711
3718
- PG_TRY ();
3712
+ if ( flags & REINDEX_REL_SUPPRESS_INDEX_USE )
3719
3713
{
3720
- ListCell * indexId ;
3721
- char persistence ;
3714
+ /* Suppress use of all the indexes until they are rebuilt */
3715
+ SetReindexPending ( indexIds ) ;
3722
3716
3723
- if (flags & REINDEX_REL_SUPPRESS_INDEX_USE )
3724
- {
3725
- /* Suppress use of all the indexes until they are rebuilt */
3726
- SetReindexPending (indexIds );
3717
+ /*
3718
+ * Make the new heap contents visible --- now things might be
3719
+ * inconsistent!
3720
+ */
3721
+ CommandCounterIncrement ();
3722
+ }
3727
3723
3728
- /*
3729
- * Make the new heap contents visible --- now things might be
3730
- * inconsistent!
3731
- */
3732
- CommandCounterIncrement ();
3733
- }
3724
+ /*
3725
+ * Compute persistence of indexes: same as that of owning rel, unless
3726
+ * caller specified otherwise.
3727
+ */
3728
+ if (flags & REINDEX_REL_FORCE_INDEXES_UNLOGGED )
3729
+ persistence = RELPERSISTENCE_UNLOGGED ;
3730
+ else if (flags & REINDEX_REL_FORCE_INDEXES_PERMANENT )
3731
+ persistence = RELPERSISTENCE_PERMANENT ;
3732
+ else
3733
+ persistence = rel -> rd_rel -> relpersistence ;
3734
+
3735
+ /* Reindex all the indexes. */
3736
+ i = 1 ;
3737
+ foreach (indexId , indexIds )
3738
+ {
3739
+ Oid indexOid = lfirst_oid (indexId );
3740
+ Oid indexNamespaceId = get_rel_namespace (indexOid );
3734
3741
3735
3742
/*
3736
- * Compute persistence of indexes: same as that of owning rel, unless
3737
- * caller specified otherwise.
3743
+ * Skip any invalid indexes on a TOAST table. These can only be
3744
+ * duplicate leftovers from a failed REINDEX CONCURRENTLY, and if
3745
+ * rebuilt it would not be possible to drop them anymore.
3738
3746
*/
3739
- if (flags & REINDEX_REL_FORCE_INDEXES_UNLOGGED )
3740
- persistence = RELPERSISTENCE_UNLOGGED ;
3741
- else if (flags & REINDEX_REL_FORCE_INDEXES_PERMANENT )
3742
- persistence = RELPERSISTENCE_PERMANENT ;
3743
- else
3744
- persistence = rel -> rd_rel -> relpersistence ;
3745
-
3746
- /* Reindex all the indexes. */
3747
- i = 1 ;
3748
- foreach (indexId , indexIds )
3747
+ if (IsToastNamespace (indexNamespaceId ) &&
3748
+ !get_index_isvalid (indexOid ))
3749
3749
{
3750
- Oid indexOid = lfirst_oid (indexId );
3751
- Oid indexNamespaceId = get_rel_namespace (indexOid );
3752
-
3753
- /*
3754
- * Skip any invalid indexes on a TOAST table. These can only be
3755
- * duplicate leftovers from a failed REINDEX CONCURRENTLY, and if
3756
- * rebuilt it would not be possible to drop them anymore.
3757
- */
3758
- if (IsToastNamespace (indexNamespaceId ) &&
3759
- !get_index_isvalid (indexOid ))
3760
- {
3761
- ereport (WARNING ,
3762
- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
3763
- errmsg ("cannot reindex invalid index \"%s.%s\" on TOAST table, skipping" ,
3764
- get_namespace_name (indexNamespaceId ),
3765
- get_rel_name (indexOid ))));
3766
- continue ;
3767
- }
3750
+ ereport (WARNING ,
3751
+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
3752
+ errmsg ("cannot reindex invalid index \"%s.%s\" on TOAST table, skipping" ,
3753
+ get_namespace_name (indexNamespaceId ),
3754
+ get_rel_name (indexOid ))));
3755
+ continue ;
3756
+ }
3768
3757
3769
- reindex_index (indexOid , !(flags & REINDEX_REL_CHECK_CONSTRAINTS ),
3770
- persistence , options );
3758
+ reindex_index (indexOid , !(flags & REINDEX_REL_CHECK_CONSTRAINTS ),
3759
+ persistence , options );
3771
3760
3772
- CommandCounterIncrement ();
3761
+ CommandCounterIncrement ();
3773
3762
3774
- /* Index should no longer be in the pending list */
3775
- Assert (!ReindexIsProcessingIndex (indexOid ));
3763
+ /* Index should no longer be in the pending list */
3764
+ Assert (!ReindexIsProcessingIndex (indexOid ));
3776
3765
3777
- /* Set index rebuild count */
3778
- pgstat_progress_update_param (PROGRESS_CLUSTER_INDEX_REBUILD_COUNT ,
3779
- i );
3780
- i ++ ;
3781
- }
3766
+ /* Set index rebuild count */
3767
+ pgstat_progress_update_param (PROGRESS_CLUSTER_INDEX_REBUILD_COUNT ,
3768
+ i );
3769
+ i ++ ;
3782
3770
}
3783
- PG_FINALLY ();
3784
- {
3785
- /* Make sure list gets cleared on error exit */
3786
- ResetReindexPending ();
3787
- }
3788
- PG_END_TRY ();
3789
3771
3790
3772
/*
3791
3773
* Close rel, but continue to hold the lock.
@@ -3819,6 +3801,7 @@ reindex_relation(Oid relid, int flags, int options)
3819
3801
static Oid currentlyReindexedHeap = InvalidOid ;
3820
3802
static Oid currentlyReindexedIndex = InvalidOid ;
3821
3803
static List * pendingReindexedIndexes = NIL ;
3804
+ static int reindexingNestLevel = 0 ;
3822
3805
3823
3806
/*
3824
3807
* ReindexIsProcessingHeap
@@ -3855,8 +3838,6 @@ ReindexIsProcessingIndex(Oid indexOid)
3855
3838
/*
3856
3839
* SetReindexProcessing
3857
3840
* Set flag that specified heap/index are being reindexed.
3858
- *
3859
- * NB: caller must use a PG_TRY block to ensure ResetReindexProcessing is done.
3860
3841
*/
3861
3842
static void
3862
3843
SetReindexProcessing (Oid heapOid , Oid indexOid )
@@ -3869,6 +3850,8 @@ SetReindexProcessing(Oid heapOid, Oid indexOid)
3869
3850
currentlyReindexedIndex = indexOid ;
3870
3851
/* Index is no longer "pending" reindex. */
3871
3852
RemoveReindexPending (indexOid );
3853
+ /* This may have been set already, but in case it isn't, do so now. */
3854
+ reindexingNestLevel = GetCurrentTransactionNestLevel ();
3872
3855
}
3873
3856
3874
3857
/*
@@ -3878,17 +3861,16 @@ SetReindexProcessing(Oid heapOid, Oid indexOid)
3878
3861
static void
3879
3862
ResetReindexProcessing (void )
3880
3863
{
3881
- /* This may be called in leader error path */
3882
3864
currentlyReindexedHeap = InvalidOid ;
3883
3865
currentlyReindexedIndex = InvalidOid ;
3866
+ /* reindexingNestLevel remains set till end of (sub)transaction */
3884
3867
}
3885
3868
3886
3869
/*
3887
3870
* SetReindexPending
3888
3871
* Mark the given indexes as pending reindex.
3889
3872
*
3890
- * NB: caller must use a PG_TRY block to ensure ResetReindexPending is done.
3891
- * Also, we assume that the current memory context stays valid throughout.
3873
+ * NB: we assume that the current memory context stays valid throughout.
3892
3874
*/
3893
3875
static void
3894
3876
SetReindexPending (List * indexes )
@@ -3899,6 +3881,7 @@ SetReindexPending(List *indexes)
3899
3881
if (IsInParallelMode ())
3900
3882
elog (ERROR , "cannot modify reindex state during a parallel operation" );
3901
3883
pendingReindexedIndexes = list_copy (indexes );
3884
+ reindexingNestLevel = GetCurrentTransactionNestLevel ();
3902
3885
}
3903
3886
3904
3887
/*
@@ -3915,14 +3898,32 @@ RemoveReindexPending(Oid indexOid)
3915
3898
}
3916
3899
3917
3900
/*
3918
- * ResetReindexPending
3919
- * Unset reindex-pending status .
3901
+ * ResetReindexState
3902
+ * Clear all reindexing state during (sub)transaction abort .
3920
3903
*/
3921
- static void
3922
- ResetReindexPending ( void )
3904
+ void
3905
+ ResetReindexState ( int nestLevel )
3923
3906
{
3924
- /* This may be called in leader error path */
3925
- pendingReindexedIndexes = NIL ;
3907
+ /*
3908
+ * Because reindexing is not re-entrant, we don't need to cope with nested
3909
+ * reindexing states. We just need to avoid messing up the outer-level
3910
+ * state in case a subtransaction fails within a REINDEX. So checking the
3911
+ * current nest level against that of the reindex operation is sufficient.
3912
+ */
3913
+ if (reindexingNestLevel >= nestLevel )
3914
+ {
3915
+ currentlyReindexedHeap = InvalidOid ;
3916
+ currentlyReindexedIndex = InvalidOid ;
3917
+
3918
+ /*
3919
+ * We needn't try to release the contents of pendingReindexedIndexes;
3920
+ * that list should be in a transaction-lifespan context, so it will
3921
+ * go away automatically.
3922
+ */
3923
+ pendingReindexedIndexes = NIL ;
3924
+
3925
+ reindexingNestLevel = 0 ;
3926
+ }
3926
3927
}
3927
3928
3928
3929
/*
@@ -3975,4 +3976,7 @@ RestoreReindexState(void *reindexstate)
3975
3976
lappend_oid (pendingReindexedIndexes ,
3976
3977
sistate -> pendingReindexedIndexes [c ]);
3977
3978
MemoryContextSwitchTo (oldcontext );
3979
+
3980
+ /* Note the worker has its own transaction nesting level */
3981
+ reindexingNestLevel = GetCurrentTransactionNestLevel ();
3978
3982
}
0 commit comments