Datum pipeline_stream_insert(PG_FUNCTION_ARGS) { TriggerData *trigdata = (TriggerData *) fcinfo->context; Trigger *trig = trigdata->tg_trigger; HeapTuple tup; List *fdw_private; int i; ResultRelInfo rinfo; if (trig->tgnargs < 1) elog(ERROR, "pipeline_stream_insert: must be provided a stream name"); /* make sure it's called as a trigger */ if (!CALLED_AS_TRIGGER(fcinfo)) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("pipeline_stream_insert: must be called as trigger"))); /* and that it's called on update or insert */ if (!TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event) && !TRIGGER_FIRED_BY_INSERT(trigdata->tg_event)) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("pipeline_stream_insert: must be called on insert or update"))); /* and that it's called for each row */ if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("pipeline_stream_insert: must be called for each row"))); /* and that it's called after insert or update */ if (!TRIGGER_FIRED_AFTER(trigdata->tg_event)) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("pipeline_stream_insert: must be called after insert or update"))); if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) tup = trigdata->tg_newtuple; else tup = trigdata->tg_trigtuple; fdw_private = list_make1(RelationGetDescr(trigdata->tg_relation)); MemSet(&rinfo, 0, sizeof(ResultRelInfo)); rinfo.ri_RangeTableIndex = 1; /* dummy */ rinfo.ri_TrigDesc = NULL; for (i = 0; i < trig->tgnargs; i++) { RangeVar *stream; Relation rel; StreamInsertState *sis; stream = makeRangeVarFromNameList(textToQualifiedNameList(cstring_to_text(trig->tgargs[i]))); rel = heap_openrv(stream, AccessShareLock); rinfo.ri_RelationDesc = rel; BeginStreamModify(NULL, &rinfo, fdw_private, 0, 0); sis = (StreamInsertState *) rinfo.ri_FdwState; Assert(sis); if (sis->queries) { TupleTableSlot *slot = MakeSingleTupleTableSlot(RelationGetDescr(rel)); ExecStoreTuple(tup, slot, InvalidBuffer, false); ExecStreamInsert(NULL, &rinfo, slot, NULL); ExecClearTuple(slot); ExecDropSingleTupleTableSlot(slot); pgstat_report_streamstat(true); } EndStreamModify(NULL, &rinfo); heap_close(rel, AccessShareLock); } return PointerGetDatum(tup); }
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); } }