Skip to content

Commit 3ba58cf

Browse files
committed
Fix index drop issue and rollback order
Signed-off-by: Tim Chang <[email protected]>
1 parent 750012c commit 3ba58cf

File tree

2 files changed

+31
-9
lines changed

2 files changed

+31
-9
lines changed

src/backend/utils/misc/queryenvironment.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,12 @@ ENRAddUncommittedTupleData(EphemeralNamedRelation enr, Oid catoid, ENRTupleOpera
742742
if (op == ENR_OP_UPDATE && *list_ptr != NIL)
743743
return;
744744

745-
*list_ptr = lappend(*list_ptr, uncommitted_tup);
745+
/*
746+
* lcons here takes the length of the list, so it is less efficient than lappend.
747+
* However, we want the uncommitted_tup order to behave more like a stack to
748+
* process ROLLBACK in the right order of operations.
749+
*/
750+
*list_ptr = lcons(uncommitted_tup, *list_ptr);
746751
}
747752

748753
/*
@@ -775,7 +780,7 @@ ENRDeleteUncommittedTupleData(EphemeralNamedRelation enr)
775780
* Return true if the asked operation is done.
776781
* Return false if the asked operation is not possible.
777782
*/
778-
static bool _ENR_tuple_operation(Relation catalog_rel, HeapTuple tup, ENRTupleOperationType op)
783+
static bool _ENR_tuple_operation(Relation catalog_rel, HeapTuple tup, ENRTupleOperationType op, bool skip_cache_inval)
779784
{
780785
EphemeralNamedRelation enr = NULL;
781786
HeapTuple oldtup, newtup;
@@ -1025,7 +1030,8 @@ static bool _ENR_tuple_operation(Relation catalog_rel, HeapTuple tup, ENRTupleOp
10251030
case ENR_OP_DROP:
10261031
if (enr->md.is_committed && !enr->md.is_table_variable)
10271032
ENRAddUncommittedTupleData(enr, catalog_oid, op, tup);
1028-
CacheInvalidateHeapTuple(catalog_rel, tup, NULL);
1033+
if (!skip_cache_inval)
1034+
CacheInvalidateHeapTuple(catalog_rel, tup, NULL);
10291035
tmp = lfirst(lc);
10301036
*list_ptr = list_delete_ptr(*list_ptr, tmp);
10311037
heap_freetuple(tmp);
@@ -1047,7 +1053,7 @@ static bool _ENR_tuple_operation(Relation catalog_rel, HeapTuple tup, ENRTupleOp
10471053
*/
10481054
bool ENRaddTuple(Relation rel, HeapTuple tup)
10491055
{
1050-
return _ENR_tuple_operation(rel, tup, ENR_OP_ADD);
1056+
return _ENR_tuple_operation(rel, tup, ENR_OP_ADD, false);
10511057
}
10521058

10531059
/*
@@ -1062,15 +1068,15 @@ bool ENRdropTuple(Relation rel, HeapTuple tup)
10621068
*/
10631069
if (ENRTupleIsDropped(rel, tup))
10641070
return true;
1065-
return _ENR_tuple_operation(rel, tup, ENR_OP_DROP);
1071+
return _ENR_tuple_operation(rel, tup, ENR_OP_DROP, false);
10661072
}
10671073

10681074
/*
10691075
* Update tuple of an ENR.
10701076
*/
10711077
bool ENRupdateTuple(Relation rel, HeapTuple tup)
10721078
{
1073-
return _ENR_tuple_operation(rel, tup, ENR_OP_UPDATE);
1079+
return _ENR_tuple_operation(rel, tup, ENR_OP_UPDATE, false);
10741080
}
10751081

10761082
/*
@@ -1376,23 +1382,37 @@ ENRRollbackChanges(QueryEnvironment *queryEnv)
13761382
foreach(lc2, uncommitted_cattups)
13771383
{
13781384
ENRUncommittedTuple uncommitted_tup = (ENRUncommittedTuple) lfirst(lc2);
1385+
bool skip_cache_inval = false;
13791386

13801387
if (!OidIsValid(uncommitted_tup->catalog_oid) || !HeapTupleIsValid(uncommitted_tup->tup))
1381-
elog(ERROR, "ROLLBACK failed! Invalid temp table entries were found.");
1388+
elog(ERROR, "ROLLBACK failed! Invalid temp table entries were found.");
1389+
1390+
if (uncommitted_tup->catalog_oid == IndexRelationId && uncommitted_tup->optype == ENR_OP_ADD)
1391+
{
1392+
/*
1393+
* We skip invalidating IndexRelationId on drop (ie committed table, index created in transaction)
1394+
* because it will be taken care of when the index itself is dropped - otherwise we risk
1395+
* throwing an error because the entry is already wiped away.
1396+
*/
1397+
Form_pg_index idx_form = (Form_pg_index) GETSTRUCT(uncommitted_tup->tup);
1398+
EphemeralNamedRelation tmp_enr = get_ENR_withoid(queryEnv, idx_form->indrelid, ENR_TSQL_TEMP);
1399+
if (tmp_enr && tmp_enr->md.is_committed)
1400+
skip_cache_inval = true;
1401+
}
13821402

13831403
rel = relation_open(uncommitted_tup->catalog_oid, AccessExclusiveLock);
13841404

13851405
switch(uncommitted_tup->optype)
13861406
{
13871407
/* Peform the opposite operation as the saved optype. */
13881408
case ENR_OP_ADD:
1389-
_ENR_tuple_operation(rel, uncommitted_tup->tup, ENR_OP_DROP);
1409+
_ENR_tuple_operation(rel, uncommitted_tup->tup, ENR_OP_DROP, skip_cache_inval);
13901410
break;
13911411
case ENR_OP_UPDATE:
13921412
ENRupdateTuple(rel, uncommitted_tup->tup);
13931413
break;
13941414
case ENR_OP_DROP:
1395-
ENRaddTuple(rel, uncommitted_tup->tup);
1415+
_ENR_tuple_operation(rel, uncommitted_tup->tup, ENR_OP_ADD, skip_cache_inval);
13961416
break;
13971417
}
13981418
relation_close(rel, AccessExclusiveLock);

src/include/utils/queryenvironment.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ typedef struct EphemeralNamedRelationMetadataData
8787

8888
/* We must ignore transaction semantics for table variables. */
8989
bool is_table_variable;
90+
/* is index */
91+
bool is_index;
9092
/* We don't need to track uncommitted ENRs as they would be dropped entirely on ROLLBACK. */
9193
bool is_committed;
9294
/* If this ENR is currently being rolled back, don't track changes to it. */

0 commit comments

Comments
 (0)