Hi!

On Wed, Dec 26, 2018 at 4:38 AM Alvaro Herrera <alvhe...@2ndquadrant.com> wrote:
> Sounds like you could do this by fixing concurrent refresh to also work
> when the MV is WITH NO DATA.

Yes, I do not think this would be too hard to fix. I could do this nevertheless.

> > Ah, yes. I could just do TRUNCATE and INSERT, instead of heap swap.
> > That would then generate reasonable trigger calls.
>
> Right.

I have tested this yesterday and performance is 2x worse that heap
swap on the benchmark I made. So I do not think this is a viable
approach.

I am now looking into simply triggering TRUNCATE and INSERT triggers
after heap swap simulating the above. I made AFTER STATEMENT triggers
and it looks like it is working, only NEW table is not populated for
some reason. Any suggestions? See attached patch.


Mitar

-- 
http://mitar.tnode.com/
https://twitter.com/mitar_m
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index e583989e1d..b79b9be687 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -882,8 +882,54 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 static void
 refresh_by_heap_swap(Oid matviewOid, Oid OIDNewHeap, char relpersistence)
 {
+	Relation	matviewRel;
+	EState		*estate;
+	ResultRelInfo resultRelInfo;
+	TransitionCaptureState *transition_capture;
+
 	finish_heap_swap(matviewOid, OIDNewHeap, false, false, true, true,
 					 RecentXmin, ReadNextMultiXactId(), relpersistence);
+
+	matviewRel = heap_open(matviewOid, NoLock);
+
+	/* Prepare to catch AFTER triggers. */
+	AfterTriggerBeginQuery();
+
+	/*
+	 * To fire triggers, we'll need an EState as well as a ResultRelInfo.
+	 */
+	estate = CreateExecutorState();
+
+	InitResultRelInfo(&resultRelInfo,
+					  matviewRel,
+					  0,	/* dummy rangetable index */
+					  NULL,
+					  0);
+	estate->es_result_relations = &resultRelInfo;
+	estate->es_num_result_relations = 1;
+	estate->es_result_relation_info = &resultRelInfo;
+
+	/* Execute AFTER STATEMENT truncate triggers */
+	ExecASTruncateTriggers(estate, &resultRelInfo);
+
+	transition_capture =
+		MakeTransitionCaptureState(matviewRel->trigdesc,
+								   RelationGetRelid(matviewRel),
+								   CMD_INSERT);
+
+	/* Execute AFTER STATEMENT insertion triggers */
+	ExecASInsertTriggers(estate, &resultRelInfo, transition_capture);
+
+	/* Handle queued AFTER triggers */
+	AfterTriggerEndQuery(estate);
+
+	/* Close any trigger target relations */
+	ExecCleanUpTriggerState(estate);
+
+	/* We can clean up the EState now */
+	FreeExecutorState(estate);
+
+	heap_close(matviewRel, NoLock);
 }
 
 /*

Reply via email to