Skip to content

Commit

Permalink
Avoid REFREH fast path if matview has foreign tables.
Browse files Browse the repository at this point in the history
For matview has foreign tables, we never know the data
status.
Since we usually create a matview has read external tables,
the initial data status is Up-to-date.
That will make REFRESH fail to do the real thing with
fast path feature, the worst case is we never try to get
the external data during REFRESH.

Authored-by: Zhang Mingli avamingli@gmail.com
  • Loading branch information
avamingli authored and my-ship-it committed Dec 4, 2024
1 parent 7be4f7f commit 47f626c
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 4 deletions.
23 changes: 21 additions & 2 deletions src/backend/catalog/gp_matview_aux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/backend/commands/matview.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
if (gp_enable_refresh_fast_path &&
!RelationIsIVM(matviewRel) &&
!stmt->skipData &&
MatviewIsUpToDate(matviewOid))
MatviewIsUpToDate(matviewOid) &&
!MatviewHasForeignTables(matviewOid))
{
table_close(matviewRel, NoLock);

Expand Down
5 changes: 4 additions & 1 deletion src/include/catalog/gp_matview_aux.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
46 changes: 46 additions & 0 deletions src/test/regress/expected/aqumv.out
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions src/test/regress/sql/aqumv.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 47f626c

Please sign in to comment.