Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 22a4cc1

Browse files
The removal of a variable can be undone on rollback
1 parent bf7c420 commit 22a4cc1

File tree

5 files changed

+126
-26
lines changed

5 files changed

+126
-26
lines changed

expected/pg_variables_trans.out

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,7 @@ SELECT pgv_free();
13921392

13931393
(1 row)
13941394

1395-
--Additional tests
1395+
-- Additional tests
13961396
SELECT pgv_insert('vars3', 'r1', tab, true) FROM tab;
13971397
pgv_insert
13981398
------------
@@ -1598,3 +1598,58 @@ BEGIN;
15981598
SELECT pgv_set('vars', 'any1', 'wrong type'::varchar, true);
15991599
ERROR: variable "any1" requires "text" value
16001600
COMMIT;
1601+
-- THE REMOVAL OF THE VARIABLE MUST BE CANCELED ON ROLLBACK
1602+
SELECT pgv_set('vars', 'any1', 'variable exists'::text, true);
1603+
pgv_set
1604+
---------
1605+
1606+
(1 row)
1607+
1608+
BEGIN;
1609+
SELECT pgv_remove('vars', 'any1');
1610+
pgv_remove
1611+
------------
1612+
1613+
(1 row)
1614+
1615+
SELECT pgv_exists('vars', 'any1');
1616+
pgv_exists
1617+
------------
1618+
f
1619+
(1 row)
1620+
1621+
ROLLBACK;
1622+
SELECT pgv_exists('vars', 'any1');
1623+
pgv_exists
1624+
------------
1625+
t
1626+
(1 row)
1627+
1628+
SELECT pgv_get('vars', 'any1',NULL::text);
1629+
pgv_get
1630+
-----------------
1631+
variable exists
1632+
(1 row)
1633+
1634+
BEGIN;
1635+
SELECT pgv_remove('vars', 'any1');
1636+
pgv_remove
1637+
------------
1638+
1639+
(1 row)
1640+
1641+
SELECT pgv_exists('vars', 'any1');
1642+
pgv_exists
1643+
------------
1644+
f
1645+
(1 row)
1646+
1647+
COMMIT;
1648+
SELECT pgv_exists('vars', 'any1');
1649+
pgv_exists
1650+
------------
1651+
f
1652+
(1 row)
1653+
1654+
SELECT pgv_get('vars', 'any1',NULL::text);
1655+
ERROR: unrecognized variable "any1"

pg_variables.c

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ variable_insert(PG_FUNCTION_ARGS)
621621
errmsg("variable \"%s\" already created as %sTRANSACTIONAL",
622622
key, LastVariable->is_transactional ? "" : "NOT ")));
623623
}
624-
if (!isVarChangedInCurrentTrans(variable) && variable->is_transactional)
624+
if (variable->is_transactional && !isVarChangedInCurrentTrans(variable))
625625
{
626626
createSavepoint(package, variable);
627627
addToChangedVars(package, variable);
@@ -1030,7 +1030,6 @@ variable_select_by_values(PG_FUNCTION_ARGS)
10301030
static void
10311031
cleanVariableCurrentState(HashVariableEntry *variable)
10321032
{
1033-
ValueHistory *history;
10341033
ValueHistoryEntry *historyEntryToDelete;
10351034

10361035
if (variable->typid == RECORDOID)
@@ -1043,8 +1042,7 @@ cleanVariableCurrentState(HashVariableEntry *variable)
10431042
pfree(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));
10481046
pfree(historyEntryToDelete);
10491047
}
10501048

@@ -1069,7 +1067,8 @@ variable_exists(PG_FUNCTION_ARGS)
10691067
{
10701068
text *package_name;
10711069
text *var_name;
1072-
HashPackageEntry *package;
1070+
HashPackageEntry *package;
1071+
HashVariableEntry *variable;
10731072
char key[NAMEDATALEN];
10741073
bool found;
10751074

@@ -1089,12 +1088,13 @@ variable_exists(PG_FUNCTION_ARGS)
10891088

10901089
getKeyFromName(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

10941094
PG_FREE_IF_COPY(package_name, 0);
10951095
PG_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)
11411141
getKeyFromName(var_name, key);
11421142

11431143
variable = (HashVariableEntry *) hash_search(package->variablesHash,
1144-
key, HASH_REMOVE, &found);
1144+
key, HASH_FIND, &found);
11451145
if (!found)
11461146
ereport(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

11551168
PG_FREE_IF_COPY(package_name, 0);
11561169
PG_FREE_IF_COPY(var_name, 1);
@@ -1606,6 +1619,10 @@ getVariableInternal(HTAB *variables, text *name, Oid typid, bool strict)
16061619
errmsg("variable \"%s\" requires \"%s\" value",
16071620
key, 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
}
16101627
else
16111628
{
@@ -1684,12 +1701,13 @@ createVariableInternal(HashPackageEntry *package, text *name, Oid typid,
16841701
dlist_push_head(&variable->data, &historyEntry->node);
16851702
if (typid != RECORDOID)
16861703
{
1687-
ScalarVar *scalar = get_actual_value_scalar(variable);
1704+
ScalarVar *scalar = &(historyEntry->value.scalar);
16881705

16891706
get_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
}
17351753
else
17361754
scalar->value = 0;
1737-
1755+
history_entry_new->is_valid = history_entry_prev->is_valid;
17381756
dlist_push_head(history, &history_entry_new->node);
17391757
MemoryContextSwitchTo(oldcxt);
17401758
}
@@ -1744,9 +1762,10 @@ createSavepoint(HashPackageEntry *package, HashVariableEntry *variable)
17441762
* Remove previous state of variable
17451763
*/
17461764
static void
1747-
releaseSavepoint(HashVariableEntry *variable)
1765+
releaseSavepoint(HashPackageEntry *package, HashVariableEntry *variable)
17481766
{
1749-
ValueHistory *history;
1767+
ValueHistory *history;
1768+
ValueHistoryEntry *historyEntry;
17501769

17511770
history = &variable->data;
17521771
if (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)
18051832
return false;
18061833

18071834
var_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)
18221849
if(dlist_has_next(&variable->data, &var_state->node))
18231850
{
18241851
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);
18261853
}
18271854
return false;
18281855
}
@@ -1989,7 +2016,7 @@ levelUpOrRelease()
19892016

19902017
cvn_old = dlist_container(ChangedVarsNode, node, iter.cur);
19912018
if (isVarChangedInUpperTrans(cvn_old->variable))
1992-
releaseSavepoint(cvn_old->variable);
2019+
releaseSavepoint(cvn_old->package, cvn_old->variable);
19932020
else
19942021
{
19952022
ChangedVarsNode *cvn_new;
@@ -2038,7 +2065,7 @@ applyActionOnChangedVars(Action action)
20382065
switch(action)
20392066
{
20402067
case RELEASE_SAVEPOINT:
2041-
releaseSavepoint(cvn->variable);
2068+
releaseSavepoint(cvn->package, cvn->variable);
20422069
break;
20432070
case ROLLBACK_TO_SAVEPOINT:
20442071
rollbackSavepoint(cvn->package, cvn->variable);

pg_variables.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ typedef struct ValueHistoryEntry{
7070
} value;
7171
/* Transaction nest level of current entry */
7272
int level;
73+
bool is_valid;
7374
} ValueHistoryEntry;
7475

7576
typedef dlist_head ValueHistory;

pg_variables_record.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ insert_savepoint(HashVariableEntry *variable, MemoryContext packageContext)
367367
record_prev = get_actual_value_record(variable);
368368
oldcxt = MemoryContextSwitchTo(packageContext);
369369
history_entry_new = palloc0(sizeof(ValueHistoryEntry));
370+
history_entry_new->is_valid = true;
370371
record_new = &(history_entry_new->value.record);
371372
dlist_push_head(&variable->data, &history_entry_new->node);
372373
init_attributes(variable, record_prev->tupdesc, packageContext);

sql/pg_variables_trans.sql

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ SELECT pgv_get('vars2', 'any1',NULL::text);
339339

340340
SELECT pgv_free();
341341

342-
--Additional tests
342+
-- Additional tests
343343
SELECT pgv_insert('vars3', 'r1', tab, true) FROM tab;
344344
BEGIN;
345345
SELECT pgv_insert('vars3', 'r1', row(5 :: integer, 'before savepoint sp1' :: varchar),true);
@@ -393,3 +393,19 @@ SELECT pgv_get('vars', 'any1',NULL::text);
393393
BEGIN;
394394
SELECT pgv_set('vars', 'any1', 'wrong type'::varchar, true);
395395
COMMIT;
396+
397+
-- THE REMOVAL OF THE VARIABLE MUST BE CANCELED ON ROLLBACK
398+
SELECT pgv_set('vars', 'any1', 'variable exists'::text, true);
399+
BEGIN;
400+
SELECT pgv_remove('vars', 'any1');
401+
SELECT pgv_exists('vars', 'any1');
402+
ROLLBACK;
403+
SELECT pgv_exists('vars', 'any1');
404+
SELECT pgv_get('vars', 'any1',NULL::text);
405+
406+
BEGIN;
407+
SELECT pgv_remove('vars', 'any1');
408+
SELECT pgv_exists('vars', 'any1');
409+
COMMIT;
410+
SELECT pgv_exists('vars', 'any1');
411+
SELECT pgv_get('vars', 'any1',NULL::text);

0 commit comments

Comments
 (0)