bdr: Fix issues with transaction local state used in ddl queues processing.
authorAndres Freund <[email protected]>
Wed, 9 Apr 2014 12:33:17 +0000 (14:33 +0200)
committerAndres Freund <[email protected]>
Thu, 3 Jul 2014 15:55:24 +0000 (17:55 +0200)
Otherwise CONCURRENTLY commands fails because resources will be freed
twice and because tupledescs et al. are still referenced.

contrib/bdr/bdr_apply.c

index 34ed64968c8dd3cf61bf1d3a61d7bb5b58f13c9d..6058f52b49281668be274e52c331bc6f450903ad 100644 (file)
@@ -575,17 +575,30 @@ process_remote_insert(StringInfo s)
 
    check_sequencer_wakeup(rel);
 
-   heap_close(rel, NoLock);
-
    /* execute DDL if insertion was into the ddl command queue */
-   if (RelationGetRelid(rel) == QueuedDDLCommandsRelid)
+   if (RelationGetRelid(rel) == QueuedDDLCommandsRelid ||
+       RelationGetRelid(rel) == QueuedDropsRelid)
    {
+       HeapTuple ht;
        LockRelId   lockid = rel->rd_lockInfo.lockRelId;
        TransactionId oldxid = GetTopTransactionId();
 
+       /*
+        * Release transaction bound resources for CONCURRENTLY support.
+        */
+       MemoryContextSwitchTo(MessageContext);
+       ht = heap_copytuple(slot->tts_tuple);
+
        LockRelationIdForSession(&lockid, RowExclusiveLock);
+       heap_close(rel, NoLock);
+
+       ExecResetTupleTable(estate->es_tupleTable, true);
+       FreeExecutorState(estate);
 
-       process_queued_ddl_command(slot->tts_tuple, started_tx);
+       if (RelationGetRelid(rel) == QueuedDDLCommandsRelid)
+           process_queued_ddl_command(ht, started_tx);
+       if (RelationGetRelid(rel) == QueuedDropsRelid)
+           process_queued_drop(ht);
 
        rel = heap_open(QueuedDDLCommandsRelid, RowExclusiveLock);
 
@@ -599,11 +612,12 @@ process_remote_insert(StringInfo s)
            started_transaction = false;
        }
    }
-   else if (RelationGetRelid(rel) == QueuedDropsRelid)
-       process_queued_drop(slot->tts_tuple);
-
-   ExecResetTupleTable(estate->es_tupleTable, true);
-   FreeExecutorState(estate);
+   else
+   {
+       heap_close(rel, NoLock);
+       ExecResetTupleTable(estate->es_tupleTable, true);
+       FreeExecutorState(estate);
+   }
 
    CommandCounterIncrement();
 }