WIP: Don't reset context across table_scan_getnextslot() calls.
authorAndres Freund <andres@anarazel.de>
Thu, 6 Dec 2018 01:28:49 +0000 (17:28 -0800)
committerAndres Freund <andres@anarazel.de>
Tue, 11 Dec 2018 01:36:57 +0000 (17:36 -0800)
That currently crashes zheap, but I'm doubtful this is the right fix.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:

src/backend/commands/tablecmds.c
src/backend/partitioning/partbounds.c

index 959b824e8815d5aeaede81eb2ae9614049080562..03a9d221624c0fe56fdf02328829ea3400e9b855 100644 (file)
@@ -4726,16 +4726,17 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
        snapshot = RegisterSnapshot(GetLatestSnapshot());
        scan = table_beginscan(oldrel, snapshot, 0, NULL);
 
-       /*
-        * Switch to per-tuple memory context and reset it for each tuple
-        * produced, so we don't leak memory.
-        */
-       oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
 
        while (table_scan_getnextslot(scan, ForwardScanDirection, oldslot))
        {
            TupleTableSlot *insertslot;
 
+           /*
+            * Switch to per-tuple memory context and reset it for each tuple
+            * produced, so we don't leak memory.
+            */
+           oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
+
            if (tab->rewrite > 0)
            {
                /* Extract data from old tuple */
@@ -4846,11 +4847,11 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
                table_insert(newrel, insertslot, mycid, hi_options, bistate);
 
            ResetExprContext(econtext);
+           MemoryContextSwitchTo(oldCxt);
 
            CHECK_FOR_INTERRUPTS();
        }
 
-       MemoryContextSwitchTo(oldCxt);
        table_endscan(scan);
        UnregisterSnapshot(snapshot);
 
@@ -8412,14 +8413,15 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
    snapshot = RegisterSnapshot(GetLatestSnapshot());
    scan = table_beginscan(rel, snapshot, 0, NULL);
 
-   /*
-    * Switch to per-tuple memory context and reset it for each tuple
-    * produced, so we don't leak memory.
-    */
-   oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
 
    while (table_scan_getnextslot(scan, ForwardScanDirection, slot))
    {
+       /*
+        * Switch to per-tuple memory context and reset it for each tuple
+        * produced, so we don't leak memory.
+        */
+       oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
+
        if (!ExecCheck(exprstate, econtext))
            ereport(ERROR,
                    (errcode(ERRCODE_CHECK_VIOLATION),
@@ -8428,9 +8430,9 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
                     errtableconstraint(rel, NameStr(constrForm->conname))));
 
        ResetExprContext(econtext);
+       MemoryContextSwitchTo(oldcxt);
    }
 
-   MemoryContextSwitchTo(oldcxt);
    table_endscan(scan);
    UnregisterSnapshot(snapshot);
    ExecDropSingleTupleTableSlot(slot);
index cb9e252f417ceaa22ffe46cff5cadef0d1bdb6a9..4b54b2d58fd7548a3f308aad574252fdd819bd3e 100644 (file)
@@ -1265,14 +1265,14 @@ check_default_partition_contents(Relation parent, Relation default_rel,
        scan = table_beginscan(part_rel, snapshot, 0, NULL);
        tupslot = table_gimmegimmeslot(parent, &estate->es_tupleTable);
 
-       /*
-        * Switch to per-tuple memory context and reset it for each tuple
-        * produced, so we don't leak memory.
-        */
-       oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
-
        while (table_scan_getnextslot(scan, ForwardScanDirection, tupslot))
        {
+           /*
+            * Switch to per-tuple memory context and reset it for each tuple
+            * produced, so we don't leak memory.
+            */
+           oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
+
            econtext->ecxt_scantuple = tupslot;
 
            if (!ExecCheck(partqualstate, econtext))
@@ -1282,10 +1282,10 @@ check_default_partition_contents(Relation parent, Relation default_rel,
                                RelationGetRelationName(default_rel))));
 
            ResetExprContext(econtext);
+           MemoryContextSwitchTo(oldCxt);
            CHECK_FOR_INTERRUPTS();
        }
 
-       MemoryContextSwitchTo(oldCxt);
        table_endscan(scan);
        UnregisterSnapshot(snapshot);
        ExecDropSingleTupleTableSlot(tupslot);