From 273dae106985d139305fc79f7267ba8d8e8f507c Mon Sep 17 00:00:00 2001 From: Zhang Mingli Date: Mon, 25 Nov 2024 15:36:39 +0800 Subject: [PATCH] Avoid REFREH fast path if matview has foreign tables. Authored-by: Zhang Mingli avamingli@gmail.com --- src/backend/catalog/gp_matview_aux.c | 23 ++++++++++++-- src/backend/commands/matview.c | 1 + src/include/catalog/gp_matview_aux.h | 5 ++- src/test/regress/expected/aqumv.out | 46 ++++++++++++++++++++++++++++ src/test/regress/sql/aqumv.sql | 7 +++++ 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/backend/catalog/gp_matview_aux.c b/src/backend/catalog/gp_matview_aux.c index b3f666c72e3..f7b6e04879b 100644 --- a/src/backend/catalog/gp_matview_aux.c +++ b/src/backend/catalog/gp_matview_aux.c @@ -50,7 +50,7 @@ static void SetMatviewAuxStatus_guts(Oid mvoid, char status); * Return NIL if the query we think it's useless. */ List* -GetViewBaseRelids(const Query *viewQuery) +GetViewBaseRelids(const Query *viewQuery, bool *has_foreign) { List *relids = NIL; Node *mvjtnode; @@ -100,6 +100,9 @@ GetViewBaseRelids(const Query *viewQuery) relkind != RELKIND_FOREIGN_TABLE) return NIL; + if (has_foreign) + *has_foreign = relkind == RELKIND_FOREIGN_TABLE; + /* * inherit tables are not supported. * FIXME: left a door for partition table which will be supported soon. @@ -140,11 +143,12 @@ InsertMatviewAuxEntry(Oid mvoid, const Query *viewQuery, bool skipdata) Datum values[Natts_gp_matview_aux]; List *relids; NameData mvname; + bool has_foreign = false; Assert(OidIsValid(mvoid)); /* Empty relids means the view is not supported now. */ - relids = GetViewBaseRelids(viewQuery); + relids = GetViewBaseRelids(viewQuery, &has_foreign); if (relids == NIL) return; @@ -157,6 +161,8 @@ InsertMatviewAuxEntry(Oid mvoid, const Query *viewQuery, bool skipdata) namestrcpy(&mvname, get_rel_name(mvoid)); values[Anum_gp_matview_aux_mvname - 1] = NameGetDatum(&mvname); + + values[Anum_gp_matview_aux_has_foreign - 1] = BoolGetDatum(has_foreign); if (skipdata) values[Anum_gp_matview_aux_datastatus - 1] = CharGetDatum(MV_DATA_STATUS_EXPIRED); @@ -449,6 +455,19 @@ MatviewUsableForAppendAgg(Oid mvoid) (auxform->datastatus == MV_DATA_STATUS_EXPIRED_INSERT_ONLY)); } +bool +MatviewHasForeignTables(Oid mvoid) +{ + HeapTuple mvauxtup = SearchSysCacheCopy1(MVAUXOID, ObjectIdGetDatum(mvoid)); + + /* Not a candidate we recorded. */ + if (!HeapTupleIsValid(mvauxtup)) + return false; + + Form_gp_matview_aux auxform = (Form_gp_matview_aux) GETSTRUCT(mvauxtup); + return auxform->has_foreign; +} + /* * Is the view data up to date? * In most cases, we should use this function to check if view diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index 49cdce3b842..52e3936947d 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -482,6 +482,7 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, if (gp_enable_refresh_fast_path && !RelationIsIVM(matviewRel) && !stmt->skipData && + !MatviewHasForeignTables(matviewOid) && MatviewIsGeneralyUpToDate(matviewOid)) { table_close(matviewRel, NoLock); diff --git a/src/include/catalog/gp_matview_aux.h b/src/include/catalog/gp_matview_aux.h index 03f6a2300f6..fec4457dae8 100644 --- a/src/include/catalog/gp_matview_aux.h +++ b/src/include/catalog/gp_matview_aux.h @@ -27,6 +27,7 @@ CATALOG(gp_matview_aux,7153,GpMatviewAuxId) BKI_SHARED_RELATION { Oid mvoid; /* materialized view oid */ NameData mvname; /* materialized view name */ + bool has_foreign; /* view query has foreign tables? */ /* view's data status */ char datastatus; } FormData_gp_matview_aux; @@ -57,12 +58,14 @@ extern void InsertMatviewAuxEntry(Oid mvoid, const Query *viewQuery, bool skipda extern void RemoveMatviewAuxEntry(Oid mvoid); -extern List* GetViewBaseRelids(const Query *viewQuery); +extern List* GetViewBaseRelids(const Query *viewQuery, bool *has_foreign); extern void SetRelativeMatviewAuxStatus(Oid relid, char status); extern void SetMatviewAuxStatus(Oid mvoid, char status); +extern bool MatviewHasForeignTables(Oid mvoid); + extern bool MatviewUsableForAppendAgg(Oid mvoid); extern bool MatviewIsGeneralyUpToDate(Oid mvoid); diff --git a/src/test/regress/expected/aqumv.out b/src/test/regress/expected/aqumv.out index 552a4778687..ba4772e826d 100644 --- a/src/test/regress/expected/aqumv.out +++ b/src/test/regress/expected/aqumv.out @@ -2682,6 +2682,52 @@ select * from aqumv_ext_r where id = 5; 5 (1 row) +-- refresh matview has foreign tables should not go fast path. +select * from aqumv_ext_mv; + id +---- + 5 + 6 + 9 + 10 + 2 + 3 + 4 + 7 + 8 + 1 +(10 rows) + +INSERT INTO aqumv_ext_w SELECT * FROM generate_series(10, 15); +set local gp_enable_refresh_fast_path = on; +select datastatus from gp_matview_aux where mvoid = 'aqumv_ext_mv'::regclass::oid; + datastatus +------------ + u +(1 row) + +refresh materialized view aqumv_ext_mv; +select * from aqumv_ext_mv; + id +---- + 2 + 3 + 4 + 7 + 8 + 1 + 12 + 15 + 5 + 6 + 9 + 10 + 10 + 11 + 13 + 14 +(16 rows) + abort; -- -- End of test external table diff --git a/src/test/regress/sql/aqumv.sql b/src/test/regress/sql/aqumv.sql index 6fe19733556..8fee68f311c 100644 --- a/src/test/regress/sql/aqumv.sql +++ b/src/test/regress/sql/aqumv.sql @@ -669,6 +669,13 @@ explain (costs off, verbose) select * from aqumv_ext_r where id = 5; select * from aqumv_ext_r where id = 5; +-- refresh matview has foreign tables should not go fast path. +select * from aqumv_ext_mv; +INSERT INTO aqumv_ext_w SELECT * FROM generate_series(10, 15); +set local gp_enable_refresh_fast_path = on; +select datastatus from gp_matview_aux where mvoid = 'aqumv_ext_mv'::regclass::oid; +refresh materialized view aqumv_ext_mv; +select * from aqumv_ext_mv; abort; -- -- End of test external table