Skip to content

Commit 745ea14

Browse files
CherkashinSergeyza-arthur
authored andcommitted
Fix package removal in rollback
1 parent 89ac2ee commit 745ea14

File tree

3 files changed

+109
-18
lines changed

3 files changed

+109
-18
lines changed

expected/pg_variables_trans.out

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,6 +1962,49 @@ SELECT package FROM pgv_stats() ORDER BY package;
19621962
---------
19631963
(0 rows)
19641964

1965+
-- Package should exist after rollback if it contains regular variable
1966+
BEGIN;
1967+
SELECT pgv_set('vars', 'any1', 'some value'::text);
1968+
pgv_set
1969+
---------
1970+
1971+
(1 row)
1972+
1973+
ROLLBACK;
1974+
SELECT package FROM pgv_stats() ORDER BY package;
1975+
package
1976+
---------
1977+
vars
1978+
(1 row)
1979+
1980+
-- Package should not exist if it becomes empty in rolled back transaction
1981+
BEGIN;
1982+
SAVEPOINT comm2;
1983+
SELECT pgv_remove('vars');
1984+
pgv_remove
1985+
------------
1986+
1987+
(1 row)
1988+
1989+
ROLLBACK TO comm2;
1990+
SELECT pgv_exists('vars');
1991+
pgv_exists
1992+
------------
1993+
f
1994+
(1 row)
1995+
1996+
SELECT package FROM pgv_stats() ORDER BY package;
1997+
package
1998+
---------
1999+
vars
2000+
(1 row)
2001+
2002+
COMMIT;
2003+
SELECT package FROM pgv_stats() ORDER BY package;
2004+
package
2005+
---------
2006+
(0 rows)
2007+
19652008
SELECT pgv_free();
19662009
pgv_free
19672010
----------

pg_variables.c

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -961,13 +961,11 @@ removePackageInternal(Package *package)
961961
GetPackState(package)->trans_var_num = 0;
962962
}
963963

964+
/* Check if package has any valid variables */
964965
static bool
965966
isPackageEmpty(Package *package)
966967
{
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;
971969

972970
if (package->varHashRegular)
973971
var_num += hash_get_num_entries(package->varHashRegular);
@@ -1357,7 +1355,7 @@ initObjectHistory(TransObject *object, TransObjectType type)
13571355
VarState * varState = (VarState *) state;
13581356
ScalarVar *scalar = &(varState->value.scalar);
13591357

1360-
get_typlenbyval(variable->typid, &scalar->typlen,
1358+
get_typlenbyval(variable->typid, &scalar->typlen,
13611359
&scalar->typbyval);
13621360
varState->value.scalar.is_null = true;
13631361
}
@@ -1613,7 +1611,7 @@ createVariableInternal(Package *package, text *name, Oid typid, bool is_record,
16131611
(!found || !GetActualState(variable)->is_valid))
16141612
GetPackState(package)->trans_var_num++;
16151613
GetActualState(variable)->is_valid = true;
1616-
1614+
16171615
/* If it is necessary, put variable to changedVars */
16181616
if (is_transactional)
16191617
addToChangesStack(transObject, TRANS_VARIABLE);
@@ -1779,16 +1777,49 @@ rollbackSavepoint(TransObject *object, TransObjectType type)
17791777
state = GetActualState(object);
17801778
removeState(object, type, state);
17811779

1782-
if (dlist_is_empty(&object->states))
1780+
if (type == TRANS_PACKAGE)
17831781
{
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))
17851803
{
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);
17891813
addToChangesStackUpperLevel(object, type);
1814+
GetActualState(object)->level = GetCurrentTransactionNestLevel() - 1;
1815+
}
1816+
GetActualState(object)->is_valid = false;
17901817
}
1791-
else
1818+
}
1819+
else
1820+
{
1821+
if (dlist_is_empty(&object->states))
1822+
/* Remove a variable if it is no longer needed. */
17921823
removeObject(object, type);
17931824
}
17941825
}
@@ -1840,9 +1871,9 @@ addToChangesStackUpperLevel(TransObject *object, TransObjectType type)
18401871
ChangedObject *co_new;
18411872
ChangesStackNode *csn;
18421873
/*
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+
*/
18461877
csn = dlist_head_element(ChangesStackNode, node, changesStack);
18471878
co_new = makeChangedObject(object, csn->ctx);
18481879
dlist_push_head(type == TRANS_PACKAGE ? csn->changedPacksList :
@@ -1875,13 +1906,14 @@ isObjectChangedInUpperTrans(TransObject *object)
18751906
*prev_state;
18761907

18771908
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())
18791911
{
18801912
prev_state = dlist_container(TransState, node, cur_state->node.next);
18811913
return prev_state->level == GetCurrentTransactionNestLevel() - 1;
18821914
}
1883-
1884-
return false;
1915+
else
1916+
return cur_state->level == GetCurrentTransactionNestLevel() - 1;
18851917
}
18861918

18871919
/*

sql/pg_variables_trans.sql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,4 +509,20 @@ ROLLBACK TO sp_to_rollback;
509509
COMMIT;
510510
SELECT package FROM pgv_stats() ORDER BY package;
511511

512+
-- Package should exist after rollback if it contains regular variable
513+
BEGIN;
514+
SELECT pgv_set('vars', 'any1', 'some value'::text);
515+
ROLLBACK;
516+
SELECT package FROM pgv_stats() ORDER BY package;
517+
518+
-- Package should not exist if it becomes empty in rolled back transaction
519+
BEGIN;
520+
SAVEPOINT comm2;
521+
SELECT pgv_remove('vars');
522+
ROLLBACK TO comm2;
523+
SELECT pgv_exists('vars');
524+
SELECT package FROM pgv_stats() ORDER BY package;
525+
COMMIT;
526+
SELECT package FROM pgv_stats() ORDER BY package;
527+
512528
SELECT pgv_free();

0 commit comments

Comments
 (0)