diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/analyze.c | 27 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 181 | ||||
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 6 |
3 files changed, 207 insertions, 7 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 240faca72aa..d34fca54666 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -190,6 +190,7 @@ transformTopLevelStmt(ParseState *pstate, Node *parseTree) ctas->query = parseTree; ctas->into = stmt->intoClause; + ctas->relkind = OBJECT_TABLE; ctas->is_select_into = true; /* @@ -324,6 +325,11 @@ analyze_requires_snapshot(Node *parseTree) result = true; break; + case T_RefreshMatViewStmt: + /* yes, because the SELECT from pg_rewrite must be analyzed */ + result = true; + break; + default: /* other utility statements don't have any real parse analysis */ result = false; @@ -2117,7 +2123,8 @@ transformExplainStmt(ParseState *pstate, ExplainStmt *stmt) /* * transformCreateTableAsStmt - - * transform a CREATE TABLE AS (or SELECT ... INTO) Statement + * transform a CREATE TABLE AS, SELECT ... INTO, or CREATE MATERIALIZED VIEW + * Statement * * As with EXPLAIN, transform the contained statement now. */ @@ -2126,6 +2133,24 @@ transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt) { Query *result; + /* + * Set relkind in IntoClause based on statement relkind. These are + * different types, because the parser users the ObjectType enumeration + * and the executor uses RELKIND_* defines. + */ + switch (stmt->relkind) + { + case (OBJECT_TABLE): + stmt->into->relkind = RELKIND_RELATION; + break; + case (OBJECT_MATVIEW): + stmt->into->relkind = RELKIND_MATVIEW; + break; + default: + elog(ERROR, "unrecognized object relkind: %d", + (int) stmt->relkind); + } + /* transform contained query */ stmt->query = (Node *) transformStmt(pstate, stmt->query); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index d3009b67b41..0787d2f5061 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -121,6 +121,13 @@ typedef struct PrivTarget #define CAS_NOT_VALID 0x10 #define CAS_NO_INHERIT 0x20 +/* + * In the IntoClause structure there is a char value which will eventually be + * set to RELKIND_RELATION or RELKIND_MATVIEW based on the relkind field in + * the statement-level structure, which is an ObjectType. Define the default + * here, which should always be overridden later. + */ +#define INTO_CLAUSE_RELKIND_DEFAULT '\0' #define parser_yyerror(msg) scanner_yyerror(msg, yyscanner) #define parser_errposition(pos) scanner_errposition(pos, yyscanner) @@ -248,6 +255,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); DeallocateStmt PrepareStmt ExecuteStmt DropOwnedStmt ReassignOwnedStmt AlterTSConfigurationStmt AlterTSDictionaryStmt + CreateMatViewStmt RefreshMatViewStmt %type <node> select_no_parens select_with_parens select_clause simple_select values_clause @@ -351,7 +359,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <defelt> fdw_option %type <range> OptTempTableName -%type <into> into_clause create_as_target +%type <into> into_clause create_as_target create_mv_target %type <defelt> createfunc_opt_item common_func_opt_item dostmt_opt_item %type <fun_param> func_arg func_arg_with_default table_func_column @@ -360,6 +368,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <boolean> opt_trusted opt_restart_seqs %type <ival> OptTemp +%type <ival> OptNoLog %type <oncommit> OnCommitOption %type <ival> for_locking_strength @@ -557,7 +566,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P - MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE + MAPPING MATCH MATERIALIZED MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NONE NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF @@ -572,7 +581,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); QUOTE - RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REINDEX + RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROW ROWS RULE @@ -745,6 +754,7 @@ stmt : | CreateForeignTableStmt | CreateFunctionStmt | CreateGroupStmt + | CreateMatViewStmt | CreateOpClassStmt | CreateOpFamilyStmt | AlterOpFamilyStmt @@ -790,6 +800,7 @@ stmt : | IndexStmt | InsertStmt | ListenStmt + | RefreshMatViewStmt | LoadStmt | LockStmt | NotifyStmt @@ -1704,9 +1715,9 @@ DiscardStmt: /***************************************************************************** * - * ALTER [ TABLE | INDEX | SEQUENCE | VIEW ] variations + * ALTER [ TABLE | INDEX | SEQUENCE | VIEW | MATERIALIZED VIEW ] variations * - * Note: we accept all subcommands for each of the four variants, and sort + * Note: we accept all subcommands for each of the five variants, and sort * out what's really legal at execution time. *****************************************************************************/ @@ -1783,6 +1794,24 @@ AlterTableStmt: n->missing_ok = true; $$ = (Node *)n; } + | ALTER MATERIALIZED VIEW qualified_name alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $4; + n->cmds = $5; + n->relkind = OBJECT_MATVIEW; + n->missing_ok = false; + $$ = (Node *)n; + } + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $6; + n->cmds = $7; + n->relkind = OBJECT_MATVIEW; + n->missing_ok = true; + $$ = (Node *)n; + } ; alter_table_cmds: @@ -3186,6 +3215,7 @@ CreateAsStmt: CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt); ctas->query = $6; ctas->into = $4; + ctas->relkind = OBJECT_TABLE; ctas->is_select_into = false; /* cram additional flags into the IntoClause */ $4->rel->relpersistence = $2; @@ -3204,6 +3234,7 @@ create_as_target: $$->onCommit = $4; $$->tableSpaceName = $5; $$->skipData = false; /* might get changed later */ + $$->relkind = INTO_CLAUSE_RELKIND_DEFAULT; } ; @@ -3217,6 +3248,65 @@ opt_with_data: /***************************************************************************** * * QUERY : + * CREATE MATERIALIZED VIEW relname AS SelectStmt + * + *****************************************************************************/ + +CreateMatViewStmt: + CREATE OptNoLog MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data + { + CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt); + ctas->query = $7; + ctas->into = $5; + ctas->relkind = OBJECT_MATVIEW; + ctas->is_select_into = false; + /* cram additional flags into the IntoClause */ + $5->rel->relpersistence = $2; + $5->skipData = !($8); + $$ = (Node *) ctas; + } + ; + +create_mv_target: + qualified_name opt_column_list opt_reloptions OptTableSpace + { + $$ = makeNode(IntoClause); + $$->rel = $1; + $$->colNames = $2; + $$->options = $3; + $$->onCommit = ONCOMMIT_NOOP; + $$->tableSpaceName = $4; + $$->skipData = false; /* might get changed later */ + $$->relkind = INTO_CLAUSE_RELKIND_DEFAULT; + } + ; + +OptNoLog: UNLOGGED { $$ = RELPERSISTENCE_UNLOGGED; } + | /*EMPTY*/ { $$ = RELPERSISTENCE_PERMANENT; } + ; + + +/***************************************************************************** + * + * QUERY : + * REFRESH MATERIALIZED VIEW qualified_name + * + *****************************************************************************/ + +RefreshMatViewStmt: + REFRESH MATERIALIZED VIEW qualified_name opt_with_data + { + RefreshMatViewStmt *n = makeNode(RefreshMatViewStmt); + n->relation = $4; + n->skipData = !($5); + $$ = (Node *) n; + } + ; + + +/***************************************************************************** + * + * QUERY : * CREATE SEQUENCE seqname * ALTER SEQUENCE seqname * @@ -3731,6 +3821,15 @@ AlterExtensionContentsStmt: n->objname = $6; $$ = (Node *)n; } + | ALTER EXTENSION name add_drop MATERIALIZED VIEW any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_MATVIEW; + n->objname = $7; + $$ = (Node *)n; + } | ALTER EXTENSION name add_drop FOREIGN TABLE any_name { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); @@ -5057,6 +5156,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior drop_type: TABLE { $$ = OBJECT_TABLE; } | SEQUENCE { $$ = OBJECT_SEQUENCE; } | VIEW { $$ = OBJECT_VIEW; } + | MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; } | INDEX { $$ = OBJECT_INDEX; } | FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; } | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; } @@ -5123,7 +5223,8 @@ opt_restart_seqs: * EXTENSION | ROLE | TEXT SEARCH PARSER | * TEXT SEARCH DICTIONARY | TEXT SEARCH TEMPLATE | * TEXT SEARCH CONFIGURATION | FOREIGN TABLE | - * FOREIGN DATA WRAPPER | SERVER | EVENT TRIGGER ] <objname> | + * FOREIGN DATA WRAPPER | SERVER | EVENT TRIGGER | + * MATERIALIZED VIEW] <objname> | * AGGREGATE <aggname> (arg1, ...) | * FUNCTION <funcname> (arg1, arg2, ...) | * OPERATOR <op> (leftoperand_typ, rightoperand_typ) | @@ -5297,6 +5398,7 @@ comment_type: | DOMAIN_P { $$ = OBJECT_DOMAIN; } | TYPE_P { $$ = OBJECT_TYPE; } | VIEW { $$ = OBJECT_VIEW; } + | MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; } | COLLATION { $$ = OBJECT_COLLATION; } | CONVERSION_P { $$ = OBJECT_CONVERSION; } | TABLESPACE { $$ = OBJECT_TABLESPACE; } @@ -5398,6 +5500,7 @@ security_label_type: | TABLESPACE { $$ = OBJECT_TABLESPACE; } | TYPE_P { $$ = OBJECT_TYPE; } | VIEW { $$ = OBJECT_VIEW; } + | MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; } ; security_label: Sconst { $$ = $1; } @@ -6940,6 +7043,26 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->missing_ok = true; $$ = (Node *)n; } + | ALTER MATERIALIZED VIEW qualified_name RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_MATVIEW; + n->relation = $4; + n->subname = NULL; + n->newname = $7; + n->missing_ok = false; + $$ = (Node *)n; + } + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_MATVIEW; + n->relation = $6; + n->subname = NULL; + n->newname = $9; + n->missing_ok = true; + $$ = (Node *)n; + } | ALTER INDEX qualified_name RENAME TO name { RenameStmt *n = makeNode(RenameStmt); @@ -7002,6 +7125,28 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->missing_ok = true; $$ = (Node *)n; } + | ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_COLUMN; + n->relationType = OBJECT_MATVIEW; + n->relation = $4; + n->subname = $7; + n->newname = $9; + n->missing_ok = false; + $$ = (Node *)n; + } + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_COLUMN; + n->relationType = OBJECT_MATVIEW; + n->relation = $6; + n->subname = $9; + n->newname = $11; + n->missing_ok = true; + $$ = (Node *)n; + } | ALTER TABLE relation_expr RENAME CONSTRAINT name TO name { RenameStmt *n = makeNode(RenameStmt); @@ -7357,6 +7502,24 @@ AlterObjectSchemaStmt: n->missing_ok = true; $$ = (Node *)n; } + | ALTER MATERIALIZED VIEW qualified_name SET SCHEMA name + { + AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); + n->objectType = OBJECT_MATVIEW; + n->relation = $4; + n->newschema = $7; + n->missing_ok = false; + $$ = (Node *)n; + } + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name SET SCHEMA name + { + AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); + n->objectType = OBJECT_MATVIEW; + n->relation = $6; + n->newschema = $9; + n->missing_ok = true; + $$ = (Node *)n; + } | ALTER FOREIGN TABLE relation_expr SET SCHEMA name { AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); @@ -8535,6 +8698,8 @@ ExplainableStmt: | DeleteStmt | DeclareCursorStmt | CreateAsStmt + | CreateMatViewStmt + | RefreshMatViewStmt | ExecuteStmt /* by default all are $$=$1 */ ; @@ -8619,6 +8784,7 @@ ExecuteStmt: EXECUTE name execute_param_clause n->params = $8; ctas->query = (Node *) n; ctas->into = $4; + ctas->relkind = OBJECT_TABLE; ctas->is_select_into = false; /* cram additional flags into the IntoClause */ $4->rel->relpersistence = $2; @@ -9166,6 +9332,7 @@ into_clause: $$->onCommit = ONCOMMIT_NOOP; $$->tableSpaceName = NULL; $$->skipData = false; + $$->relkind = INTO_CLAUSE_RELKIND_DEFAULT; } | /*EMPTY*/ { $$ = NULL; } @@ -12652,6 +12819,7 @@ unreserved_keyword: | LOCK_P | MAPPING | MATCH + | MATERIALIZED | MAXVALUE | MINUTE_P | MINVALUE @@ -12697,6 +12865,7 @@ unreserved_keyword: | RECHECK | RECURSIVE | REF + | REFRESH | REINDEX | RELATIVE_P | RELEASE diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 10a3be59c0b..8a1876c8a39 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -646,6 +646,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla if (relation->rd_rel->relkind != RELKIND_RELATION && relation->rd_rel->relkind != RELKIND_VIEW && + relation->rd_rel->relkind != RELKIND_MATVIEW && relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE && relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE) ereport(ERROR, @@ -1999,6 +2000,11 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString, */ rel = heap_openrv(stmt->relation, AccessExclusiveLock); + if (rel->rd_rel->relkind == RELKIND_MATVIEW) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("rules on materialized views are not supported"))); + /* Set up pstate */ pstate = make_parsestate(NULL); pstate->p_sourcetext = queryString; |