Hi!
On Wed, Dec 26, 2018 at 4:38 AM Alvaro Herrera <[email protected]> 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);
}
/*