@@ -961,13 +961,11 @@ removePackageInternal(Package *package)
961
961
GetPackState (package )-> trans_var_num = 0 ;
962
962
}
963
963
964
+ /* Check if package has any valid variables */
964
965
static bool
965
966
isPackageEmpty (Package * package )
966
967
{
967
- int var_num = 0 ;
968
-
969
- if (package -> varHashTransact )
970
- var_num += hash_get_num_entries (package -> varHashTransact );
968
+ int var_num = GetPackState (package )-> trans_var_num ;
971
969
972
970
if (package -> varHashRegular )
973
971
var_num += hash_get_num_entries (package -> varHashRegular );
@@ -1357,7 +1355,7 @@ initObjectHistory(TransObject *object, TransObjectType type)
1357
1355
VarState * varState = (VarState * ) state ;
1358
1356
ScalarVar * scalar = & (varState -> value .scalar );
1359
1357
1360
- get_typlenbyval (variable -> typid , & scalar -> typlen ,
1358
+ get_typlenbyval (variable -> typid , & scalar -> typlen ,
1361
1359
& scalar -> typbyval );
1362
1360
varState -> value .scalar .is_null = true;
1363
1361
}
@@ -1613,7 +1611,7 @@ createVariableInternal(Package *package, text *name, Oid typid, bool is_record,
1613
1611
(!found || !GetActualState (variable )-> is_valid ))
1614
1612
GetPackState (package )-> trans_var_num ++ ;
1615
1613
GetActualState (variable )-> is_valid = true;
1616
-
1614
+
1617
1615
/* If it is necessary, put variable to changedVars */
1618
1616
if (is_transactional )
1619
1617
addToChangesStack (transObject , TRANS_VARIABLE );
@@ -1779,16 +1777,49 @@ rollbackSavepoint(TransObject *object, TransObjectType type)
1779
1777
state = GetActualState (object );
1780
1778
removeState (object , type , state );
1781
1779
1782
- if (dlist_is_empty ( & object -> states ) )
1780
+ if (type == TRANS_PACKAGE )
1783
1781
{
1784
- if (type == TRANS_PACKAGE && numOfRegVars ((Package * )object ) > 0 )
1782
+ /* If there is no more states... */
1783
+ if (dlist_is_empty (& object -> states ))
1784
+ {
1785
+ /* ...but object is a package and has some regular variables... */
1786
+ if (numOfRegVars ((Package * )object ) > 0 )
1787
+ {
1788
+ /* ...create a new state to make package valid. */
1789
+ initObjectHistory (object , type );
1790
+ GetActualState (object )-> level = GetCurrentTransactionNestLevel () - 1 ;
1791
+ if (!dlist_is_empty (changesStack ))
1792
+ addToChangesStackUpperLevel (object , type );
1793
+ }
1794
+ else
1795
+ /* ...or remove an object if it is no longer needed. */
1796
+ removeObject (object , type );
1797
+ }
1798
+ /*
1799
+ * But if a package has more states, but hasn't valid variables,
1800
+ * mark it as not valid or remove at top level transaction.
1801
+ */
1802
+ else if (isPackageEmpty ((Package * )object ))
1785
1803
{
1786
- initObjectHistory (object , type );
1787
- GetActualState (object )-> level = GetCurrentTransactionNestLevel () - 1 ;
1788
- if (!dlist_is_empty (changesStack ))
1804
+ if (dlist_is_empty (changesStack ))
1805
+ {
1806
+ removeObject (object , type );
1807
+ return ;
1808
+ }
1809
+ else if (!isObjectChangedInUpperTrans (object ) &&
1810
+ !dlist_is_empty (changesStack ))
1811
+ {
1812
+ createSavepoint (object , type );
1789
1813
addToChangesStackUpperLevel (object , type );
1814
+ GetActualState (object )-> level = GetCurrentTransactionNestLevel () - 1 ;
1815
+ }
1816
+ GetActualState (object )-> is_valid = false;
1790
1817
}
1791
- else
1818
+ }
1819
+ else
1820
+ {
1821
+ if (dlist_is_empty (& object -> states ))
1822
+ /* Remove a variable if it is no longer needed. */
1792
1823
removeObject (object , type );
1793
1824
}
1794
1825
}
@@ -1840,9 +1871,9 @@ addToChangesStackUpperLevel(TransObject *object, TransObjectType type)
1840
1871
ChangedObject * co_new ;
1841
1872
ChangesStackNode * csn ;
1842
1873
/*
1843
- * Impossible to push in upper list existing node
1844
- * because it was created in another context
1845
- */
1874
+ * Impossible to push in upper list existing node
1875
+ * because it was created in another context
1876
+ */
1846
1877
csn = dlist_head_element (ChangesStackNode , node , changesStack );
1847
1878
co_new = makeChangedObject (object , csn -> ctx );
1848
1879
dlist_push_head (type == TRANS_PACKAGE ? csn -> changedPacksList :
@@ -1875,13 +1906,14 @@ isObjectChangedInUpperTrans(TransObject *object)
1875
1906
* prev_state ;
1876
1907
1877
1908
cur_state = GetActualState (object );
1878
- if (dlist_has_next (& object -> states , & cur_state -> node ))
1909
+ if (dlist_has_next (& object -> states , & cur_state -> node ) &&
1910
+ cur_state -> level == GetCurrentTransactionNestLevel ())
1879
1911
{
1880
1912
prev_state = dlist_container (TransState , node , cur_state -> node .next );
1881
1913
return prev_state -> level == GetCurrentTransactionNestLevel () - 1 ;
1882
1914
}
1883
-
1884
- return false ;
1915
+ else
1916
+ return cur_state -> level == GetCurrentTransactionNestLevel () - 1 ;
1885
1917
}
1886
1918
1887
1919
/*
0 commit comments