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); } /*