@@ -621,7 +621,7 @@ variable_insert(PG_FUNCTION_ARGS)
621
621
errmsg ("variable \"%s\" already created as %sTRANSACTIONAL" ,
622
622
key , LastVariable -> is_transactional ? "" : "NOT " )));
623
623
}
624
- if (! isVarChangedInCurrentTrans ( variable ) && variable -> is_transactional )
624
+ if (variable -> is_transactional && ! isVarChangedInCurrentTrans ( variable ) )
625
625
{
626
626
createSavepoint (package , variable );
627
627
addToChangedVars (package , variable );
@@ -1030,7 +1030,6 @@ variable_select_by_values(PG_FUNCTION_ARGS)
1030
1030
static void
1031
1031
cleanVariableCurrentState (HashVariableEntry * variable )
1032
1032
{
1033
- ValueHistory * history ;
1034
1033
ValueHistoryEntry * historyEntryToDelete ;
1035
1034
1036
1035
if (variable -> typid == RECORDOID )
@@ -1043,8 +1042,7 @@ cleanVariableCurrentState(HashVariableEntry *variable)
1043
1042
pfree (DatumGetPointer (scalar -> value ));
1044
1043
}
1045
1044
1046
- history = & variable -> data ;
1047
- historyEntryToDelete = get_history_entry (dlist_pop_head_node (history ));
1045
+ historyEntryToDelete = get_history_entry (dlist_pop_head_node (& variable -> data ));
1048
1046
pfree (historyEntryToDelete );
1049
1047
}
1050
1048
@@ -1069,7 +1067,8 @@ variable_exists(PG_FUNCTION_ARGS)
1069
1067
{
1070
1068
text * package_name ;
1071
1069
text * var_name ;
1072
- HashPackageEntry * package ;
1070
+ HashPackageEntry * package ;
1071
+ HashVariableEntry * variable ;
1073
1072
char key [NAMEDATALEN ];
1074
1073
bool found ;
1075
1074
@@ -1089,12 +1088,13 @@ variable_exists(PG_FUNCTION_ARGS)
1089
1088
1090
1089
getKeyFromName (var_name , key );
1091
1090
1092
- hash_search (package -> variablesHash , key , HASH_FIND , & found );
1091
+ variable = (HashVariableEntry * ) hash_search (package -> variablesHash ,
1092
+ key , HASH_FIND , & found );
1093
1093
1094
1094
PG_FREE_IF_COPY (package_name , 0 );
1095
1095
PG_FREE_IF_COPY (var_name , 1 );
1096
1096
1097
- PG_RETURN_BOOL (found );
1097
+ PG_RETURN_BOOL (found ? get_actual_value ( variable ) -> is_valid : found );
1098
1098
}
1099
1099
1100
1100
/*
@@ -1141,16 +1141,29 @@ remove_variable(PG_FUNCTION_ARGS)
1141
1141
getKeyFromName (var_name , key );
1142
1142
1143
1143
variable = (HashVariableEntry * ) hash_search (package -> variablesHash ,
1144
- key , HASH_REMOVE , & found );
1144
+ key , HASH_FIND , & found );
1145
1145
if (!found )
1146
1146
ereport (ERROR ,
1147
1147
(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1148
- errmsg ("unrecognized variable \"%s\"" , key )));
1149
-
1150
- /* Remove variable from cache */
1151
- LastVariable = NULL ;
1152
-
1153
- cleanVariableAllStates (variable );
1148
+ errmsg ("unrecognized variable \"%s\"" , key )));
1149
+ else
1150
+ {
1151
+ if (variable -> is_transactional )
1152
+ {
1153
+ createSavepoint (package , variable );
1154
+ addToChangedVars (package , variable );
1155
+ get_actual_value (variable )-> is_valid = false;
1156
+ }
1157
+ else
1158
+ {
1159
+ /* Remove variable from package */
1160
+ hash_search (package -> variablesHash , key , HASH_REMOVE , & found );
1161
+ /* Free allocated memory */
1162
+ cleanVariableAllStates (variable );
1163
+ }
1164
+ /* Remove variable from cache */
1165
+ LastVariable = NULL ;
1166
+ }
1154
1167
1155
1168
PG_FREE_IF_COPY (package_name , 0 );
1156
1169
PG_FREE_IF_COPY (var_name , 1 );
@@ -1606,6 +1619,10 @@ getVariableInternal(HTAB *variables, text *name, Oid typid, bool strict)
1606
1619
errmsg ("variable \"%s\" requires \"%s\" value" ,
1607
1620
key , var_type )));
1608
1621
}
1622
+ if (!get_actual_value (variable )-> is_valid && strict )
1623
+ ereport (ERROR ,
1624
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1625
+ errmsg ("unrecognized variable \"%s\"" , key )));
1609
1626
}
1610
1627
else
1611
1628
{
@@ -1684,12 +1701,13 @@ createVariableInternal(HashPackageEntry *package, text *name, Oid typid,
1684
1701
dlist_push_head (& variable -> data , & historyEntry -> node );
1685
1702
if (typid != RECORDOID )
1686
1703
{
1687
- ScalarVar * scalar = get_actual_value_scalar ( variable );
1704
+ ScalarVar * scalar = & ( historyEntry -> value . scalar );
1688
1705
1689
1706
get_typlenbyval (variable -> typid , & scalar -> typlen ,
1690
1707
& scalar -> typbyval );
1691
- scalar -> is_null = true;
1708
+ historyEntry -> value . scalar . is_null = true;
1692
1709
}
1710
+ historyEntry -> is_valid = true;
1693
1711
}
1694
1712
}
1695
1713
/* If it is necessary, put variable to changedVars */
@@ -1734,7 +1752,7 @@ createSavepoint(HashPackageEntry *package, HashVariableEntry *variable)
1734
1752
}
1735
1753
else
1736
1754
scalar -> value = 0 ;
1737
-
1755
+ history_entry_new -> is_valid = history_entry_prev -> is_valid ;
1738
1756
dlist_push_head (history , & history_entry_new -> node );
1739
1757
MemoryContextSwitchTo (oldcxt );
1740
1758
}
@@ -1744,9 +1762,10 @@ createSavepoint(HashPackageEntry *package, HashVariableEntry *variable)
1744
1762
* Remove previous state of variable
1745
1763
*/
1746
1764
static void
1747
- releaseSavepoint (HashVariableEntry * variable )
1765
+ releaseSavepoint (HashPackageEntry * package , HashVariableEntry * variable )
1748
1766
{
1749
- ValueHistory * history ;
1767
+ ValueHistory * history ;
1768
+ ValueHistoryEntry * historyEntry ;
1750
1769
1751
1770
history = & variable -> data ;
1752
1771
if (dlist_has_next (history , dlist_head_node (history )))
@@ -1773,7 +1792,15 @@ releaseSavepoint(HashVariableEntry *variable)
1773
1792
* If variable was changed in subtransaction, so it is considered it
1774
1793
* was changed in parent transaction.
1775
1794
*/
1776
- (get_actual_value (variable )-> level )-- ;
1795
+ historyEntry = get_actual_value (variable );
1796
+ historyEntry -> level -- ;
1797
+ if (!historyEntry -> is_valid &&
1798
+ !dlist_has_next (history , dlist_head_node (history )))
1799
+ {
1800
+ bool found ;
1801
+
1802
+ hash_search (package -> variablesHash , variable -> name , HASH_REMOVE , & found );
1803
+ }
1777
1804
}
1778
1805
1779
1806
/*
@@ -1805,7 +1832,7 @@ isVarChangedInCurrentTrans(HashVariableEntry *variable)
1805
1832
return false;
1806
1833
1807
1834
var_state = get_actual_value (variable );
1808
- return ( var_state -> level == GetCurrentTransactionNestLevel () );
1835
+ return var_state -> level == GetCurrentTransactionNestLevel ();
1809
1836
}
1810
1837
1811
1838
/*
@@ -1822,7 +1849,7 @@ isVarChangedInUpperTrans(HashVariableEntry *variable)
1822
1849
if (dlist_has_next (& variable -> data , & var_state -> node ))
1823
1850
{
1824
1851
var_prev_state = get_history_entry (var_state -> node .next );
1825
- return ( var_prev_state -> level == (GetCurrentTransactionNestLevel () - 1 ) );
1852
+ return var_prev_state -> level == (GetCurrentTransactionNestLevel () - 1 );
1826
1853
}
1827
1854
return false;
1828
1855
}
@@ -1989,7 +2016,7 @@ levelUpOrRelease()
1989
2016
1990
2017
cvn_old = dlist_container (ChangedVarsNode , node , iter .cur );
1991
2018
if (isVarChangedInUpperTrans (cvn_old -> variable ))
1992
- releaseSavepoint (cvn_old -> variable );
2019
+ releaseSavepoint (cvn_old -> package , cvn_old -> variable );
1993
2020
else
1994
2021
{
1995
2022
ChangedVarsNode * cvn_new ;
@@ -2038,7 +2065,7 @@ applyActionOnChangedVars(Action action)
2038
2065
switch (action )
2039
2066
{
2040
2067
case RELEASE_SAVEPOINT :
2041
- releaseSavepoint (cvn -> variable );
2068
+ releaseSavepoint (cvn -> package , cvn -> variable );
2042
2069
break ;
2043
2070
case ROLLBACK_TO_SAVEPOINT :
2044
2071
rollbackSavepoint (cvn -> package , cvn -> variable );
0 commit comments