@@ -64,7 +64,7 @@ static void resetVariablesCache(void);
64
64
65
65
/* Functions to work with transactional objects */
66
66
static void createSavepoint (TransObject * object , TransObjectType type );
67
- static void releaseSavepoint (TransObject * object , TransObjectType type );
67
+ static void releaseSavepoint (TransObject * object , TransObjectType type , bool sub );
68
68
static void rollbackSavepoint (TransObject * object , TransObjectType type );
69
69
70
70
static void copyValue (VarState * src , VarState * dest , Variable * destVar );
@@ -2408,11 +2408,14 @@ rollbackSavepoint(TransObject *object, TransObjectType type)
2408
2408
* Remove previous state of object
2409
2409
*/
2410
2410
static void
2411
- releaseSavepoint (TransObject * object , TransObjectType type )
2411
+ releaseSavepoint (TransObject * object , TransObjectType type , bool sub )
2412
2412
{
2413
2413
dlist_head * states = & object -> states ;
2414
2414
2415
2415
Assert (GetActualState (object )-> levels .level == GetCurrentTransactionNestLevel ());
2416
+ #ifdef PGPRO_EE
2417
+ Assert (GetActualState (object )-> levels .atxlevel == getNestLevelATX ());
2418
+ #endif
2416
2419
2417
2420
/*
2418
2421
* If the object is not valid and does not exist at a higher level (or if
@@ -2438,6 +2441,15 @@ releaseSavepoint(TransObject *object, TransObjectType type)
2438
2441
2439
2442
nodeToDelete = dlist_next_node (states , dlist_head_node (states ));
2440
2443
stateToDelete = dlist_container (TransState , node , nodeToDelete );
2444
+ #ifdef PGPRO_EE
2445
+ /*
2446
+ * We can not delete package state inside autonomous transaction
2447
+ * because the state can be used in pgvRestoreContext().
2448
+ * Exception: the state was created within this autonomous transaction.
2449
+ */
2450
+ Assert (type != TRANS_PACKAGE || getNestLevelATX () == 0 ||
2451
+ stateToDelete -> levels .atxlevel == getNestLevelATX ());
2452
+ #endif
2441
2453
removeState (object , type , stateToDelete );
2442
2454
}
2443
2455
@@ -2450,6 +2462,12 @@ releaseSavepoint(TransObject *object, TransObjectType type)
2450
2462
2451
2463
/* Change subxact level due to release */
2452
2464
GetActualState (object )-> levels .level -- ;
2465
+
2466
+ #ifdef PGPRO_EE
2467
+ /* Change ATX level due to finish autonomous transaction */
2468
+ if (!sub && getNestLevelATX () > 0 )
2469
+ GetActualState (object )-> levels .atxlevel = 0 ;
2470
+ #endif
2453
2471
}
2454
2472
2455
2473
static void
@@ -2647,7 +2665,7 @@ typedef enum Action
2647
2665
* Apply savepoint actions on list of variables or packages.
2648
2666
*/
2649
2667
static void
2650
- applyAction (Action action , TransObjectType type , dlist_head * list )
2668
+ applyAction (Action action , TransObjectType type , dlist_head * list , bool sub )
2651
2669
{
2652
2670
dlist_iter iter ;
2653
2671
@@ -2677,7 +2695,7 @@ applyAction(Action action, TransObjectType type, dlist_head *list)
2677
2695
GetActualState (variable )-> is_valid = false;
2678
2696
}
2679
2697
2680
- releaseSavepoint (object , type );
2698
+ releaseSavepoint (object , type , sub );
2681
2699
break ;
2682
2700
}
2683
2701
}
@@ -2688,7 +2706,7 @@ applyAction(Action action, TransObjectType type, dlist_head *list)
2688
2706
* apply corresponding action on them
2689
2707
*/
2690
2708
static void
2691
- processChanges (Action action )
2709
+ processChanges (Action action , bool sub )
2692
2710
{
2693
2711
ChangesStackNode * bottom_list ;
2694
2712
@@ -2697,8 +2715,8 @@ processChanges(Action action)
2697
2715
bottom_list = dlist_container (ChangesStackNode , node ,
2698
2716
dlist_pop_head_node (changesStack ));
2699
2717
2700
- applyAction (action , TRANS_VARIABLE , bottom_list -> changedVarsList );
2701
- applyAction (action , TRANS_PACKAGE , bottom_list -> changedPacksList );
2718
+ applyAction (action , TRANS_VARIABLE , bottom_list -> changedVarsList , sub );
2719
+ applyAction (action , TRANS_PACKAGE , bottom_list -> changedPacksList , sub );
2702
2720
2703
2721
/* Remove changes list of current level */
2704
2722
MemoryContextDelete (bottom_list -> ctx );
@@ -2866,10 +2884,10 @@ pgvRestoreContext()
2866
2884
/* Remove all package states, generated in ATX transaction */
2867
2885
while ((state = GetActualState (object )) != context -> state )
2868
2886
{
2887
+ removeState (object , TRANS_PACKAGE , state );
2869
2888
if (dlist_is_empty (& object -> states ))
2870
2889
elog (ERROR , "pg_variables extension can not find "
2871
2890
"transaction state for package" );
2872
- removeState (object , TRANS_PACKAGE , state );
2873
2891
}
2874
2892
2875
2893
/*
@@ -2935,10 +2953,10 @@ pgvSubTransCallback(SubXactEvent event, SubTransactionId mySubid,
2935
2953
compatibility_check ();
2936
2954
break ;
2937
2955
case SUBXACT_EVENT_COMMIT_SUB :
2938
- processChanges (RELEASE_SAVEPOINT );
2956
+ processChanges (RELEASE_SAVEPOINT , true );
2939
2957
break ;
2940
2958
case SUBXACT_EVENT_ABORT_SUB :
2941
- processChanges (ROLLBACK_TO_SAVEPOINT );
2959
+ processChanges (ROLLBACK_TO_SAVEPOINT , true );
2942
2960
break ;
2943
2961
case SUBXACT_EVENT_PRE_COMMIT_SUB :
2944
2962
break ;
@@ -2965,16 +2983,16 @@ pgvTransCallback(XactEvent event, void *arg)
2965
2983
{
2966
2984
case XACT_EVENT_PRE_COMMIT :
2967
2985
compatibility_check ();
2968
- processChanges (RELEASE_SAVEPOINT );
2986
+ processChanges (RELEASE_SAVEPOINT , false );
2969
2987
break ;
2970
2988
case XACT_EVENT_ABORT :
2971
- processChanges (ROLLBACK_TO_SAVEPOINT );
2989
+ processChanges (ROLLBACK_TO_SAVEPOINT , false );
2972
2990
break ;
2973
2991
case XACT_EVENT_PARALLEL_PRE_COMMIT :
2974
- processChanges (RELEASE_SAVEPOINT );
2992
+ processChanges (RELEASE_SAVEPOINT , false );
2975
2993
break ;
2976
2994
case XACT_EVENT_PARALLEL_ABORT :
2977
- processChanges (ROLLBACK_TO_SAVEPOINT );
2995
+ processChanges (ROLLBACK_TO_SAVEPOINT , false );
2978
2996
break ;
2979
2997
default :
2980
2998
break ;
0 commit comments