@@ -71,8 +71,14 @@ static bool isObjectChangedInCurrentTrans(TransObject *object);
7171static bool isObjectChangedInUpperTrans (TransObject * object );
7272
7373static void addToChangesStack (TransObject * object , TransObjectType type );
74+ static void addToChangesStackUpperLevel (TransObject * object ,
75+ TransObjectType type );
7476static void pushChangesStack (void );
7577
78+ static int numOfRegVars (Package * package );
79+ /* Debug function */
80+ static int _numOfTransVars (Package * package );
81+
7682/* Constructors */
7783static void makePackHTAB (Package * package , bool is_trans );
7884static inline ChangedObject * makeChangedObject (TransObject * object ,
@@ -892,10 +898,13 @@ remove_variable(PG_FUNCTION_ARGS)
892898 addToChangesStack (transObject , TRANS_VARIABLE );
893899 }
894900 GetActualState (variable )-> is_valid = false;
901+ numOfTransVars (package )-- ;
895902 }
896903 else
897904 removeObject (& variable -> transObject , TRANS_VARIABLE );
898905
906+ Assert (numOfTransVars (package ) == _numOfTransVars (package ));
907+
899908 resetVariablesCache (false);
900909
901910 PG_FREE_IF_COPY (package_name , 0 );
@@ -950,6 +959,7 @@ removePackageInternal(Package *package)
950959 addToChangesStack (transObject , TRANS_PACKAGE );
951960 }
952961 GetActualState (package )-> is_valid = false;
962+ numOfTransVars (package ) = 0 ;
953963}
954964
955965static bool
@@ -1338,7 +1348,8 @@ getPackage(text *name, bool strict)
13381348 {
13391349 package = (Package * ) hash_search (packagesHash , key , HASH_FIND , & found );
13401350
1341- if (found && GetActualState (package )-> is_valid )
1351+ if (found && GetActualState (package )-> is_valid &&
1352+ numOfTransVars (package ) + numOfRegVars (package ))
13421353 return package ;
13431354 }
13441355 /* Package not found or it's current state is "invalid" */
@@ -1410,17 +1421,15 @@ createPackage(text *name, bool is_trans)
14101421 packState = MemoryContextAllocZero (ModuleContext , sizeof (PackState ));
14111422 dlist_push_head (GetStateStorage (package ), & (packState -> state .node ));
14121423 packState -> state .is_valid = true;
1424+ packState -> trans_var_num = 0 ;
1425+ /* Add to changes list */
1426+ if (!isObjectChangedInCurrentTrans (& package -> transObject ))
1427+ addToChangesStack (& package -> transObject , TRANS_PACKAGE );
14131428 }
14141429
14151430 /* Create corresponding HTAB if not exists */
14161431 if (!pack_htab (package , is_trans ))
14171432 makePackHTAB (package , is_trans );
1418- /* Add to changes list */
1419- if (!isObjectChangedInCurrentTrans (& package -> transObject ))
1420- {
1421- createSavepoint (& package -> transObject , TRANS_PACKAGE );
1422- addToChangesStack (& package -> transObject , TRANS_PACKAGE );
1423- }
14241433
14251434 return package ;
14261435}
@@ -1586,7 +1595,13 @@ createVariableInternal(Package *package, text *name, Oid typid, bool is_record,
15861595 }
15871596 }
15881597
1598+ if (is_transactional &&
1599+ (!found || !GetActualState (variable )-> is_valid ))
1600+ numOfTransVars (package )++ ;
15891601 GetActualState (variable )-> is_valid = true;
1602+
1603+ Assert (numOfTransVars (package ) == _numOfTransVars (package ));
1604+
15901605 /* If it is necessary, put variable to changedVars */
15911606 if (is_transactional )
15921607 addToChangesStack (transObject , TRANS_VARIABLE );
@@ -1715,8 +1730,11 @@ createSavepoint(TransObject *object, TransObjectType type)
17151730
17161731 prevState = GetActualState (object );
17171732 if (type == TRANS_PACKAGE )
1733+ {
17181734 newState = (TransState * ) MemoryContextAllocZero (ModuleContext ,
17191735 sizeof (PackState ));
1736+ ((PackState * )newState )-> trans_var_num = ((PackState * )prevState )-> trans_var_num ;
1737+ }
17201738 else
17211739 {
17221740 Variable * var = (Variable * ) object ;
@@ -1729,6 +1747,15 @@ createSavepoint(TransObject *object, TransObjectType type)
17291747 newState -> is_valid = prevState -> is_valid ;
17301748}
17311749
1750+ static int
1751+ numOfRegVars (Package * package )
1752+ {
1753+ if (package -> varHashRegular )
1754+ return hash_get_num_entries (package -> varHashRegular );
1755+ else
1756+ return 0 ;
1757+ }
1758+
17321759/*
17331760 * Rollback object to its previous state
17341761 */
@@ -1738,32 +1765,27 @@ rollbackSavepoint(TransObject *object, TransObjectType type)
17381765 TransState * state ;
17391766
17401767 state = GetActualState (object );
1741- if (type == TRANS_PACKAGE )
1768+ removeState (object , type , state );
1769+
1770+ if (dlist_is_empty (& object -> states ))
17421771 {
1743- if (! state -> is_valid && ! isPackageEmpty ((Package * )object ))
1772+ if (type == TRANS_PACKAGE && numOfRegVars ((Package * )object ))
17441773 {
1745- if (dlist_has_next (& object -> states , & state -> node ))
1774+ PackState * packState ;
1775+
1776+ packState = MemoryContextAllocZero (ModuleContext , sizeof (PackState ));
1777+ dlist_push_head (& object -> states , & (packState -> state .node ));
1778+ packState -> state .is_valid = true;
1779+ packState -> state .level = GetCurrentTransactionNestLevel () - 1 ;
1780+ packState -> trans_var_num = 0 ;
1781+
1782+ if (!dlist_is_empty (changesStack ))
17461783 {
1747- dlist_pop_head_node (& object -> states );
1748- pfree (state );
1784+ addToChangesStackUpperLevel (object , type );
17491785 }
1750- else
1751- state -> is_valid = true;
1752- /* Restore regular vars HTAB */
1753- makePackHTAB ((Package * ) object , false);
17541786 }
17551787 else
1756- /* Pass current state to parent level */
1757- releaseSavepoint (object , TRANS_PACKAGE );
1758- }
1759- else
1760- {
1761- /* Remove current state */
1762- removeState (object , TRANS_VARIABLE , state );
1763-
1764- /* Remove variable if it was created in rolled back transaction */
1765- if (dlist_is_empty (& object -> states ))
1766- removeObject (object , TRANS_VARIABLE );
1788+ removeObject (object , type );
17671789 }
17681790}
17691791
@@ -1802,21 +1824,31 @@ releaseSavepoint(TransObject *object, TransObjectType type)
18021824 /* If the object does not yet have a record in previous level changesStack,
18031825 * create it. */
18041826 else if (!dlist_is_empty (changesStack ))
1805- {
1806- ChangedObject * co_new ;
1807- ChangesStackNode * csn ;
1808- /*
1809- * Impossible to push in upper list existing node
1810- * because it was created in another context
1811- */
1812- csn = dlist_head_element (ChangesStackNode , node , changesStack );
1813- co_new = makeChangedObject (object , csn -> ctx );
1814- dlist_push_head (type == TRANS_PACKAGE ? csn -> changedPacksList :
1815- csn -> changedVarsList ,
1816- & co_new -> node );
1817- }
1827+ addToChangesStackUpperLevel (object , type );
1828+
18181829 /* Change subxact level due to release */
18191830 GetActualState (object )-> level -- ;
1831+ if (type == TRANS_PACKAGE )
1832+ {
1833+ Package * package = (Package * )object ;
1834+ Assert (numOfTransVars (package ) == _numOfTransVars (package ));
1835+ }
1836+ }
1837+
1838+ static void
1839+ addToChangesStackUpperLevel (TransObject * object , TransObjectType type )
1840+ {
1841+ ChangedObject * co_new ;
1842+ ChangesStackNode * csn ;
1843+ /*
1844+ * Impossible to push in upper list existing node
1845+ * because it was created in another context
1846+ */
1847+ csn = dlist_head_element (ChangesStackNode , node , changesStack );
1848+ co_new = makeChangedObject (object , csn -> ctx );
1849+ dlist_push_head (type == TRANS_PACKAGE ? csn -> changedPacksList :
1850+ csn -> changedVarsList ,
1851+ & co_new -> node );
18201852}
18211853
18221854/*
@@ -2136,3 +2168,25 @@ _PG_fini(void)
21362168 UnregisterSubXactCallback (pgvSubTransCallback , NULL );
21372169 ExecutorEnd_hook = prev_ExecutorEnd ;
21382170}
2171+
2172+ /* Get exact count of valid variables in package. For debug only. */
2173+ static int
2174+ _numOfTransVars (Package * package )
2175+ {
2176+ HASH_SEQ_STATUS vstat ;
2177+ Variable * variable ;
2178+ unsigned long res = 0 ;
2179+
2180+ if (package -> varHashTransact )
2181+ {
2182+ hash_seq_init (& vstat , package -> varHashTransact );
2183+ while ((variable = (Variable * ) hash_seq_search (& vstat )) != NULL )
2184+ {
2185+ if (GetActualState (variable )-> is_valid &&
2186+ GetActualState (package )-> is_valid )
2187+ res ++ ;
2188+ }
2189+ }
2190+
2191+ return res ;
2192+ }
0 commit comments