@@ -742,7 +742,12 @@ ENRAddUncommittedTupleData(EphemeralNamedRelation enr, Oid catoid, ENRTupleOpera
742
742
if (op == ENR_OP_UPDATE && * list_ptr != NIL )
743
743
return ;
744
744
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 );
746
751
}
747
752
748
753
/*
@@ -775,7 +780,7 @@ ENRDeleteUncommittedTupleData(EphemeralNamedRelation enr)
775
780
* Return true if the asked operation is done.
776
781
* Return false if the asked operation is not possible.
777
782
*/
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 )
779
784
{
780
785
EphemeralNamedRelation enr = NULL ;
781
786
HeapTuple oldtup , newtup ;
@@ -1025,7 +1030,8 @@ static bool _ENR_tuple_operation(Relation catalog_rel, HeapTuple tup, ENRTupleOp
1025
1030
case ENR_OP_DROP :
1026
1031
if (enr -> md .is_committed && !enr -> md .is_table_variable )
1027
1032
ENRAddUncommittedTupleData (enr , catalog_oid , op , tup );
1028
- CacheInvalidateHeapTuple (catalog_rel , tup , NULL );
1033
+ if (!skip_cache_inval )
1034
+ CacheInvalidateHeapTuple (catalog_rel , tup , NULL );
1029
1035
tmp = lfirst (lc );
1030
1036
* list_ptr = list_delete_ptr (* list_ptr , tmp );
1031
1037
heap_freetuple (tmp );
@@ -1047,7 +1053,7 @@ static bool _ENR_tuple_operation(Relation catalog_rel, HeapTuple tup, ENRTupleOp
1047
1053
*/
1048
1054
bool ENRaddTuple (Relation rel , HeapTuple tup )
1049
1055
{
1050
- return _ENR_tuple_operation (rel , tup , ENR_OP_ADD );
1056
+ return _ENR_tuple_operation (rel , tup , ENR_OP_ADD , false );
1051
1057
}
1052
1058
1053
1059
/*
@@ -1062,15 +1068,15 @@ bool ENRdropTuple(Relation rel, HeapTuple tup)
1062
1068
*/
1063
1069
if (ENRTupleIsDropped (rel , tup ))
1064
1070
return true;
1065
- return _ENR_tuple_operation (rel , tup , ENR_OP_DROP );
1071
+ return _ENR_tuple_operation (rel , tup , ENR_OP_DROP , false );
1066
1072
}
1067
1073
1068
1074
/*
1069
1075
* Update tuple of an ENR.
1070
1076
*/
1071
1077
bool ENRupdateTuple (Relation rel , HeapTuple tup )
1072
1078
{
1073
- return _ENR_tuple_operation (rel , tup , ENR_OP_UPDATE );
1079
+ return _ENR_tuple_operation (rel , tup , ENR_OP_UPDATE , false );
1074
1080
}
1075
1081
1076
1082
/*
@@ -1376,23 +1382,37 @@ ENRRollbackChanges(QueryEnvironment *queryEnv)
1376
1382
foreach (lc2 , uncommitted_cattups )
1377
1383
{
1378
1384
ENRUncommittedTuple uncommitted_tup = (ENRUncommittedTuple ) lfirst (lc2 );
1385
+ bool skip_cache_inval = false;
1379
1386
1380
1387
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
+ }
1382
1402
1383
1403
rel = relation_open (uncommitted_tup -> catalog_oid , AccessExclusiveLock );
1384
1404
1385
1405
switch (uncommitted_tup -> optype )
1386
1406
{
1387
1407
/* Peform the opposite operation as the saved optype. */
1388
1408
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 );
1390
1410
break ;
1391
1411
case ENR_OP_UPDATE :
1392
1412
ENRupdateTuple (rel , uncommitted_tup -> tup );
1393
1413
break ;
1394
1414
case ENR_OP_DROP :
1395
- ENRaddTuple (rel , uncommitted_tup -> tup );
1415
+ _ENR_tuple_operation (rel , uncommitted_tup -> tup , ENR_OP_ADD , skip_cache_inval );
1396
1416
break ;
1397
1417
}
1398
1418
relation_close (rel , AccessExclusiveLock );
0 commit comments