adapt matviews to global temp table: matviews can not be created on local/global temp table

This commit is contained in:
sqyyeah 2020-08-27 09:56:01 +08:00
parent cc928a2e1b
commit a257e3b9a0
5 changed files with 144 additions and 2 deletions

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -551,4 +551,65 @@ SELECT * FROM mvtest2;
---
(0 rows)
ROLLBACK;
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;

View File

@ -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;