@@ -621,7 +621,7 @@ variable_insert(PG_FUNCTION_ARGS)
621621errmsg ("variable \"%s\" already created as %sTRANSACTIONAL" ,
622622key ,LastVariable -> is_transactional ?"" :"NOT " )));
623623}
624- if (! isVarChangedInCurrentTrans ( variable ) && variable -> is_transactional )
624+ if (variable -> is_transactional && ! isVarChangedInCurrentTrans ( variable ) )
625625{
626626createSavepoint (package ,variable );
627627addToChangedVars (package ,variable );
@@ -1030,7 +1030,6 @@ variable_select_by_values(PG_FUNCTION_ARGS)
10301030static void
10311031cleanVariableCurrentState (HashVariableEntry * variable )
10321032{
1033- ValueHistory * history ;
10341033ValueHistoryEntry * historyEntryToDelete ;
10351034
10361035if (variable -> typid == RECORDOID )
@@ -1043,8 +1042,7 @@ cleanVariableCurrentState(HashVariableEntry *variable)
10431042pfree (DatumGetPointer (scalar -> value ));
10441043}
10451044
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 ));
10481046pfree (historyEntryToDelete );
10491047}
10501048
@@ -1069,7 +1067,8 @@ variable_exists(PG_FUNCTION_ARGS)
10691067{
10701068text * package_name ;
10711069text * var_name ;
1072- HashPackageEntry * package ;
1070+ HashPackageEntry * package ;
1071+ HashVariableEntry * variable ;
10731072char key [NAMEDATALEN ];
10741073bool found ;
10751074
@@ -1089,12 +1088,13 @@ variable_exists(PG_FUNCTION_ARGS)
10891088
10901089getKeyFromName (var_name ,key );
10911090
1092- hash_search (package -> variablesHash ,key ,HASH_FIND ,& found );
1091+ variable = (HashVariableEntry * )hash_search (package -> variablesHash ,
1092+ key ,HASH_FIND ,& found );
10931093
10941094PG_FREE_IF_COPY (package_name ,0 );
10951095PG_FREE_IF_COPY (var_name ,1 );
10961096
1097- PG_RETURN_BOOL (found );
1097+ PG_RETURN_BOOL (found ? get_actual_value ( variable ) -> is_valid : found );
10981098}
10991099
11001100/*
@@ -1141,16 +1141,29 @@ remove_variable(PG_FUNCTION_ARGS)
11411141getKeyFromName (var_name ,key );
11421142
11431143variable = (HashVariableEntry * )hash_search (package -> variablesHash ,
1144- key ,HASH_REMOVE ,& found );
1144+ key ,HASH_FIND ,& found );
11451145if (!found )
11461146ereport (ERROR ,
11471147(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+ }
11541167
11551168PG_FREE_IF_COPY (package_name ,0 );
11561169PG_FREE_IF_COPY (var_name ,1 );
@@ -1606,6 +1619,10 @@ getVariableInternal(HTAB *variables, text *name, Oid typid, bool strict)
16061619errmsg ("variable \"%s\" requires \"%s\" value" ,
16071620key ,var_type )));
16081621}
1622+ if (!get_actual_value (variable )-> is_valid && strict )
1623+ ereport (ERROR ,
1624+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1625+ errmsg ("unrecognized variable \"%s\"" ,key )));
16091626}
16101627else
16111628{
@@ -1684,12 +1701,13 @@ createVariableInternal(HashPackageEntry *package, text *name, Oid typid,
16841701dlist_push_head (& variable -> data ,& historyEntry -> node );
16851702if (typid != RECORDOID )
16861703{
1687- ScalarVar * scalar = get_actual_value_scalar ( variable );
1704+ ScalarVar * scalar = & ( historyEntry -> value . scalar );
16881705
16891706get_typlenbyval (variable -> typid ,& scalar -> typlen ,
16901707& scalar -> typbyval );
1691- scalar -> is_null = true;
1708+ historyEntry -> value . scalar . is_null = true;
16921709}
1710+ historyEntry -> is_valid = true;
16931711}
16941712}
16951713/* If it is necessary, put variable to changedVars */
@@ -1734,7 +1752,7 @@ createSavepoint(HashPackageEntry *package, HashVariableEntry *variable)
17341752}
17351753else
17361754scalar -> value = 0 ;
1737-
1755+ history_entry_new -> is_valid = history_entry_prev -> is_valid ;
17381756dlist_push_head (history ,& history_entry_new -> node );
17391757MemoryContextSwitchTo (oldcxt );
17401758}
@@ -1744,9 +1762,10 @@ createSavepoint(HashPackageEntry *package, HashVariableEntry *variable)
17441762 * Remove previous state of variable
17451763 */
17461764static void
1747- releaseSavepoint (HashVariableEntry * variable )
1765+ releaseSavepoint (HashPackageEntry * package , HashVariableEntry * variable )
17481766{
1749- ValueHistory * history ;
1767+ ValueHistory * history ;
1768+ ValueHistoryEntry * historyEntry ;
17501769
17511770history = & variable -> data ;
17521771if (dlist_has_next (history ,dlist_head_node (history )))
@@ -1773,7 +1792,15 @@ releaseSavepoint(HashVariableEntry *variable)
17731792 * If variable was changed in subtransaction, so it is considered it
17741793 * was changed in parent transaction.
17751794 */
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+ }
17771804}
17781805
17791806/*
@@ -1805,7 +1832,7 @@ isVarChangedInCurrentTrans(HashVariableEntry *variable)
18051832return false;
18061833
18071834var_state = get_actual_value (variable );
1808- return ( var_state -> level == GetCurrentTransactionNestLevel () );
1835+ return var_state -> level == GetCurrentTransactionNestLevel ();
18091836}
18101837
18111838/*
@@ -1822,7 +1849,7 @@ isVarChangedInUpperTrans(HashVariableEntry *variable)
18221849if (dlist_has_next (& variable -> data ,& var_state -> node ))
18231850{
18241851var_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 );
18261853}
18271854return false;
18281855}
@@ -1989,7 +2016,7 @@ levelUpOrRelease()
19892016
19902017cvn_old = dlist_container (ChangedVarsNode ,node ,iter .cur );
19912018if (isVarChangedInUpperTrans (cvn_old -> variable ))
1992- releaseSavepoint (cvn_old -> variable );
2019+ releaseSavepoint (cvn_old -> package , cvn_old -> variable );
19932020else
19942021{
19952022ChangedVarsNode * cvn_new ;
@@ -2038,7 +2065,7 @@ applyActionOnChangedVars(Action action)
20382065switch (action )
20392066{
20402067case RELEASE_SAVEPOINT :
2041- releaseSavepoint (cvn -> variable );
2068+ releaseSavepoint (cvn -> package , cvn -> variable );
20422069break ;
20432070case ROLLBACK_TO_SAVEPOINT :
20442071rollbackSavepoint (cvn -> package ,cvn -> variable );