From a257e3b9a0c363f341771282bf115a7dbc22d580 Mon Sep 17 00:00:00 2001 From: sqyyeah <948885883@qq.com> Date: Thu, 27 Aug 2020 09:56:01 +0800 Subject: [PATCH] adapt matviews to global temp table: matviews can not be created on local/global temp table --- src/common/backend/parser/analyze.cpp | 5 ++ src/common/backend/parser/parse_relation.cpp | 38 +++++++++++- src/include/parser/parse_relation.h | 3 + src/test/regress/expected/matview.out | 63 +++++++++++++++++++- src/test/regress/sql/matview.sql | 37 ++++++++++++ 5 files changed, 144 insertions(+), 2 deletions(-) diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index 338693cfee..e1a858dce2 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -3039,6 +3039,11 @@ static Query* transformCreateTableAsStmt(ParseState* pstate, CreateTableAsStmt* if (isQueryUsingTempRelation(query)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("materialized views must not use temporary tables or views"))); + + if (is_query_using_gtt(query)) + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("materialized views must not use global temporary tables or views"))); + /* * A materialized view would either need to save parameters for use in * maintaining/loading the data or prohibit them entirely. The latter diff --git a/src/common/backend/parser/parse_relation.cpp b/src/common/backend/parser/parse_relation.cpp index cc2c863b43..c109f01b56 100755 --- a/src/common/backend/parser/parse_relation.cpp +++ b/src/common/backend/parser/parse_relation.cpp @@ -576,7 +576,7 @@ static bool isQueryUsingTempRelation_walker(Node* node, void* context) char relpersistence = rel->rd_rel->relpersistence; heap_close(rel, AccessShareLock); - if (relpersistence == RELPERSISTENCE_TEMP || relpersistence == RELPERSISTENCE_GLOBAL_TEMP) + if (relpersistence == RELPERSISTENCE_TEMP) return true; } } @@ -587,6 +587,42 @@ static bool isQueryUsingTempRelation_walker(Node* node, void* context) return expression_tree_walker(node, (bool (*)())isQueryUsingTempRelation_walker, context); } +/* check if the query uses global temp table */ +static bool is_query_using_gtt_walker(Node* node, void* context) +{ + if (node == NULL) + return false; + + if (IsA(node, Query)) { + Query* query = (Query*)node; + ListCell* rtable; + + foreach(rtable, query->rtable) { + RangeTblEntry* rte = (RangeTblEntry*)lfirst(rtable); + + if (rte->rtekind == RTE_RELATION) { + Relation rel = relation_open(rte->relid, AccessShareLock); + char relpersistence = rel->rd_rel->relpersistence; + + relation_close(rel, AccessShareLock); + if (relpersistence == RELPERSISTENCE_GLOBAL_TEMP) + return true; + } + } + + return query_tree_walker(query, (bool (*)())is_query_using_gtt_walker, context, QTW_IGNORE_JOINALIASES); + } + + return expression_tree_walker(node, (bool (*)())is_query_using_gtt_walker, context); +} + +/* check if the query uses global temp table */ +bool is_query_using_gtt(Query* query) +{ + return is_query_using_gtt_walker((Node*) query, NULL); +} + + /* * colNameToVar * Search for an unqualified column name. diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index 7db2ffa4ee..8c8cab5afb 100755 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -55,6 +55,9 @@ extern Name attnumAttName(Relation rd, int attid); extern Oid attnumTypeId(Relation rd, int attid); extern Oid attnumCollationId(Relation rd, int attid); extern bool isQueryUsingTempRelation(Query* query); +/* global temp table check */ +extern bool is_query_using_gtt(Query* query); + #ifdef PGXC extern int specialAttNum(const char* attname); #endif diff --git a/src/test/regress/expected/matview.out b/src/test/regress/expected/matview.out index 553c9ad5ce..9484a869f3 100644 --- a/src/test/regress/expected/matview.out +++ b/src/test/regress/expected/matview.out @@ -551,4 +551,65 @@ SELECT * FROM mvtest2; --- (0 rows) -ROLLBACK; \ No newline at end of file +ROLLBACK; +-- make sure that materialized view can not be created on temp table (local or global) +drop TABLE if exists simple_table_g cascade; +NOTICE: table "simple_table_g" does not exist, skipping +drop TABLE if exists simple_table_t cascade; +NOTICE: table "simple_table_t" does not exist, skipping +create GLOBAL TEMP TABLE class_global +( + class_id int primary key, + class_name varchar(10) not null +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "class_global_pkey" for table "class_global" +create TEMP TABLE student_tmp +( + id int primary key, + name varchar(10) not null, + class_id int +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "student_tmp_pkey" for table "student_tmp" +insert into class_global values (101, '1-1'); +insert into class_global values (102, '1-2'); +insert into class_global values (104, '1-4'); +insert into student_tmp values (1, 'aaa', 101); +insert into student_tmp values (2, 'bbb', 101); +insert into student_tmp values (3, 'ccc', 102); +insert into student_tmp values (4, 'ddd', 102); +insert into student_tmp values (5, 'eee', 102); +insert into student_tmp values (6, 'fff', 103); +CREATE TABLE simple_table_g AS SELECT * FROM class_global; +CREATE TABLE simple_table_t AS SELECT * FROM student_tmp; +CREATE MATERIALIZED VIEW mvtest_g AS SELECT * FROM class_global; --error +ERROR: materialized views must not use global temporary tables or views +CREATE MATERIALIZED VIEW mvtest_t AS SELECT * FROM student_tmp; --error +ERROR: materialized views must not use temporary tables or views +CREATE MATERIALIZED VIEW mvtest_mv_g AS SELECT * FROM student_tmp where class_id in (select class_id from class_global); --error +ERROR: materialized views must not use temporary tables or views +CREATE MATERIALIZED VIEW mvtest_mv_g AS SELECT * FROM class_global where class_id in (select class_id from student_tmp); --error +ERROR: materialized views must not use temporary tables or views +CREATE MATERIALIZED VIEW mvtest_s_g AS SELECT * FROM simple_table_g; --ok +CREATE MATERIALIZED VIEW mvtest_s_t AS SELECT * FROM simple_table_t; --ok +select * from mvtest_s_g; + class_id | class_name +----------+------------ + 101 | 1-1 + 102 | 1-2 + 104 | 1-4 +(3 rows) + +select * from mvtest_s_t; + id | name | class_id +----+------+---------- + 1 | aaa | 101 + 2 | bbb | 101 + 3 | ccc | 102 + 4 | ddd | 102 + 5 | eee | 102 + 6 | fff | 103 +(6 rows) + +drop MATERIALIZED VIEW mvtest_s_g cascade; +drop MATERIALIZED VIEW mvtest_s_t cascade; +drop Table class_global cascade; diff --git a/src/test/regress/sql/matview.sql b/src/test/regress/sql/matview.sql index 4a501a37a2..cbfe3fbb31 100644 --- a/src/test/regress/sql/matview.sql +++ b/src/test/regress/sql/matview.sql @@ -216,3 +216,40 @@ SELECT mvtest_func(); SELECT * FROM mvtest1; SELECT * FROM mvtest2; ROLLBACK; + +-- make sure that materialized view can not be created on temp table (local or global) +drop TABLE if exists simple_table_g cascade; +drop TABLE if exists simple_table_t cascade; +create GLOBAL TEMP TABLE class_global +( + class_id int primary key, + class_name varchar(10) not null +); +create TEMP TABLE student_tmp +( + id int primary key, + name varchar(10) not null, + class_id int +); +insert into class_global values (101, '1-1'); +insert into class_global values (102, '1-2'); +insert into class_global values (104, '1-4'); +insert into student_tmp values (1, 'aaa', 101); +insert into student_tmp values (2, 'bbb', 101); +insert into student_tmp values (3, 'ccc', 102); +insert into student_tmp values (4, 'ddd', 102); +insert into student_tmp values (5, 'eee', 102); +insert into student_tmp values (6, 'fff', 103); +CREATE TABLE simple_table_g AS SELECT * FROM class_global; +CREATE TABLE simple_table_t AS SELECT * FROM student_tmp; +CREATE MATERIALIZED VIEW mvtest_g AS SELECT * FROM class_global; --error +CREATE MATERIALIZED VIEW mvtest_t AS SELECT * FROM student_tmp; --error +CREATE MATERIALIZED VIEW mvtest_mv_g AS SELECT * FROM student_tmp where class_id in (select class_id from class_global); --error +CREATE MATERIALIZED VIEW mvtest_mv_g AS SELECT * FROM class_global where class_id in (select class_id from student_tmp); --error +CREATE MATERIALIZED VIEW mvtest_s_g AS SELECT * FROM simple_table_g; --ok +CREATE MATERIALIZED VIEW mvtest_s_t AS SELECT * FROM simple_table_t; --ok +select * from mvtest_s_g; +select * from mvtest_s_t; +drop MATERIALIZED VIEW mvtest_s_g cascade; +drop MATERIALIZED VIEW mvtest_s_t cascade; +drop Table class_global cascade; -- Gitee