diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index d884764..c0c228f 100644 *** a/src/backend/commands/copy.c --- b/src/backend/commands/copy.c *************** CopyFrom(CopyState cstate) *** 1875,1886 **** CHECK_FOR_INTERRUPTS(); - /* Reset the per-tuple exprcontext */ - ResetPerTupleExprContext(estate); - - /* Switch into its memory context */ - MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); - done = !NextCopyFrom(cstate, values, nulls, &loaded_oid); if (done) break; --- 1875,1880 ---- *************** CopyFrom(CopyState cstate) *** 1891,1899 **** if (loaded_oid != InvalidOid) HeapTupleSetOid(tuple, loaded_oid); - /* Triggers and stuff need to be invoked in query context. */ - MemoryContextSwitchTo(oldcontext); - skip_tuple = false; /* BEFORE ROW INSERT Triggers */ --- 1885,1890 ---- *************** CopyFrom(CopyState cstate) *** 1918,1924 **** List *recheckIndexes = NIL; /* Place tuple in tuple slot */ ! ExecStoreTuple(tuple, slot, InvalidBuffer, false); /* Check the constraints of the tuple */ if (cstate->rel->rd_att->constr) --- 1909,1915 ---- List *recheckIndexes = NIL; /* Place tuple in tuple slot */ ! ExecStoreTuple(tuple, slot, InvalidBuffer, true); /* Check the constraints of the tuple */ if (cstate->rel->rd_att->constr) *************** BeginCopyFrom(Relation rel, *** 2170,2179 **** --- 2161,2173 ---- * valus and nulls arrays must be the same length as columns of the * relation passed to BeginCopyFrom. Oid of the tuple is returned with * tupleOid separately. + * + * We do everything in per-tuple context and it would be reset in the head. */ bool NextCopyFrom(CopyState cstate, Datum *values, bool *nulls, Oid *tupleOid) { + MemoryContext oldcontext = CurrentMemoryContext; TupleDesc tupDesc; Form_pg_attribute *attr; AttrNumber num_phys_attrs, *************** NextCopyFrom(CopyState cstate, Datum *va *** 2190,2201 **** --- 2184,2202 ---- ExprState **defexprs = cstate->defexprs; ExprContext *econtext; /* used for ExecEvalExpr for default atts */ + /* Reset the per-tuple exprcontext and switch into its memory context */ + ResetPerTupleExprContext(cstate->estate); + MemoryContextSwitchTo(GetPerTupleMemoryContext(cstate->estate)); + /* on input just throw the header line away */ if (cstate->cur_lineno == 0 && cstate->header_line) { cstate->cur_lineno++; if (CopyReadLine(cstate)) + { + MemoryContextSwitchTo(oldcontext); return false; /* done */ + } } tupDesc = RelationGetDescr(cstate->rel); *************** NextCopyFrom(CopyState cstate, Datum *va *** 2228,2234 **** --- 2229,2238 ---- * EOF, ie, process the line and then exit loop on next iteration. */ if (done && cstate->line_buf.len == 0) + { + MemoryContextSwitchTo(oldcontext); return false; + } /* Parse the line into de-escaped field values */ if (cstate->csv_mode) *************** NextCopyFrom(CopyState cstate, Datum *va *** 2316,2321 **** --- 2320,2326 ---- if (!CopyGetInt16(cstate, &fld_count)) { /* EOF detected (end of file, or protocol-level EOF) */ + MemoryContextSwitchTo(oldcontext); return false; } *************** NextCopyFrom(CopyState cstate, Datum *va *** 2340,2345 **** --- 2345,2351 ---- ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("received copy data after EOF marker"))); + MemoryContextSwitchTo(oldcontext); return false; } *************** NextCopyFrom(CopyState cstate, Datum *va *** 2400,2405 **** --- 2406,2412 ---- &nulls[defmap[i]], NULL); } + MemoryContextSwitchTo(oldcontext); return true; }