/* * CopyIntoStream * * COPY events to a stream from an input source */ void CopyIntoStream(Relation rel, TupleDesc desc, HeapTuple *tuples, int ntuples) { bool snap = ActiveSnapshotSet(); ResultRelInfo rinfo; StreamInsertState *sis; MemSet(&rinfo, 0, sizeof(ResultRelInfo)); rinfo.ri_RangeTableIndex = 1; /* dummy */ rinfo.ri_TrigDesc = NULL; rinfo.ri_RelationDesc = rel; if (snap) PopActiveSnapshot(); BeginStreamModify(NULL, &rinfo, list_make1(desc), 0, 0); sis = (StreamInsertState *) rinfo.ri_FdwState; Assert(sis); if (sis->queries) { TupleTableSlot *slot = MakeSingleTupleTableSlot(RelationGetDescr(rel)); int i; for (i = 0; i < ntuples; i++) { ExecStoreTuple(tuples[i], slot, InvalidBuffer, false); ExecStreamInsert(NULL, &rinfo, slot, NULL); ExecClearTuple(slot); } ExecDropSingleTupleTableSlot(slot); Assert(sis->ntups == ntuples); pgstat_increment_cq_write(ntuples, sis->nbytes); } EndStreamModify(NULL, &rinfo); if (snap) PushActiveSnapshot(GetTransactionSnapshot()); }
static void pipeline_stream_insert_batch(TransformState *t) { int i; if (t->ntups == 0) return; Assert(t->tg_rel); for (i = 0; i < t->cont_query->tgnargs; i++) { RangeVar *rv = makeRangeVarFromNameList(stringToQualifiedNameList(t->cont_query->tgargs[i])); Relation rel = heap_openrv(rv, AccessShareLock); Size size; if (t->acks) { int i; for (i = 0; i < t->nacks; i++) { InsertBatchAck *ack = &t->acks[i]; InsertBatchIncrementNumWTuples(ack->batch, t->ntups); } } size = SendTuplesToContWorkers(rel, RelationGetDescr(t->tg_rel), t->tups, t->ntups, t->acks, t->nacks); heap_close(rel, NoLock); if (size) { pgstat_increment_cq_write(t->ntups, size); pgstat_report_streamstat(false); } } if (t->acks) { pfree(t->acks); t->acks = NULL; t->nacks = 0; } if (t->ntups) { for (i = 0; i < t->ntups; i++) heap_freetuple(t->tups[i]); pfree(t->tups); t->tups = NULL; t->ntups = 0; t->nmaxtups = 0; } else { Assert(t->tups == NULL); Assert(t->nmaxtups == 0); } }