From 549dae0352a06a43ec664dc158556e12ec2d30e5 Mon Sep 17 00:00:00 2001 From: Kevin Grittner Date: Fri, 22 Mar 2013 13:27:34 -0500 Subject: [PATCH] Fix problems with incomplete attempt to prohibit OIDS with MVs. Problem with assertion failure in restoring from pg_dump output reported by Joachim Wieland. Review and suggestions by Tom Lane and Robert Haas. --- doc/src/sgml/ref/create_materialized_view.sgml | 7 ++++++- src/backend/commands/createas.c | 6 +++++- src/backend/commands/tablecmds.c | 2 +- src/backend/parser/parse_clause.c | 17 ++++++++++++++++- src/backend/parser/parse_utilcmd.c | 4 +++- src/include/parser/parse_clause.h | 2 +- 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/ref/create_materialized_view.sgml b/doc/src/sgml/ref/create_materialized_view.sgml index ed3bb4d3ae..a7e4e210ee 100644 --- a/doc/src/sgml/ref/create_materialized_view.sgml +++ b/doc/src/sgml/ref/create_materialized_view.sgml @@ -44,6 +44,9 @@ CREATE [ UNLOGGED ] MATERIALIZED VIEW table_name CREATE MATERIALIZED VIEW is similar to CREATE TABLE AS, except that it also remembers the query used to initialize the view, so that it can be refreshed later upon demand. + A materialized view has many of the same properties as a table, but there + is no support for temporary materialized views or automatic generation of + OIDs. @@ -88,7 +91,9 @@ CREATE [ UNLOGGED ] MATERIALIZED VIEW table_name This clause specifies optional storage parameters for the new materialized view; see for more - information. + information. All parameters supported for CREATE + TABLE are also supported for CREATE MATERIALIZED + VIEW with the exception of OIDS. See for more information. diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index a3ff1d56c8..06bbae5cc5 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -218,11 +218,15 @@ GetIntoRelEFlags(IntoClause *intoClause) * because it doesn't have enough information to do so itself (since we * can't build the target relation until after ExecutorStart). */ - if (interpretOidsOption(intoClause->options)) + if (interpretOidsOption(intoClause->options, intoClause->relkind)) flags = EXEC_FLAG_WITH_OIDS; else flags = EXEC_FLAG_WITHOUT_OIDS; + Assert(intoClause->relkind != RELKIND_MATVIEW || + (flags & (EXEC_FLAG_WITH_OIDS | EXEC_FLAG_WITHOUT_OIDS)) == + EXEC_FLAG_WITHOUT_OIDS); + if (intoClause->skipData) flags |= EXEC_FLAG_WITH_NO_DATA; diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 57cf0a07b5..536d232dd4 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -559,7 +559,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) */ descriptor = BuildDescForRelation(schema); - localHasOids = interpretOidsOption(stmt->options); + localHasOids = interpretOidsOption(stmt->options, relkind); descriptor->tdhasoid = (localHasOids || parentOidCount > 0); /* diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index b9655954cd..78a4f13c71 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -243,9 +243,14 @@ interpretInhOption(InhOption inhOpt) * table/result set should be created with OIDs. This needs to be done after * parsing the query string because the return value can depend upon the * default_with_oids GUC var. + * + * Materialized views are handled here rather than reloptions.c because that + * code explicitly punts checking for oids to here. We prohibit any explicit + * specification of the oids option for a materialized view, and indicate that + * oids are not needed if we don't get an error. */ bool -interpretOidsOption(List *defList) +interpretOidsOption(List *defList, char relkind) { ListCell *cell; @@ -256,9 +261,19 @@ interpretOidsOption(List *defList) if (def->defnamespace == NULL && pg_strcasecmp(def->defname, "oids") == 0) + { + if (relkind == RELKIND_MATVIEW) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unrecognized parameter \"%s\"", "oids"))); + return defGetBoolean(def); + } } + if (relkind == RELKIND_MATVIEW) + return false; + /* OIDS option was not specified, so use default. */ return default_with_oids; } diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 4fdcf180fa..0d2802a576 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -199,11 +199,14 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) { cxt.stmtType = "CREATE FOREIGN TABLE"; cxt.isforeign = true; + cxt.hasoids = interpretOidsOption(stmt->options, + RELKIND_FOREIGN_TABLE); } else { cxt.stmtType = "CREATE TABLE"; cxt.isforeign = false; + cxt.hasoids = interpretOidsOption(stmt->options, RELKIND_RELATION); } cxt.relation = stmt->relation; cxt.rel = NULL; @@ -217,7 +220,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) cxt.blist = NIL; cxt.alist = NIL; cxt.pkey = NULL; - cxt.hasoids = interpretOidsOption(stmt->options); Assert(!stmt->ofTypename || !stmt->inhRelations); /* grammar enforces */ diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h index 36318d125d..0bccb1cd64 100644 --- a/src/include/parser/parse_clause.h +++ b/src/include/parser/parse_clause.h @@ -20,7 +20,7 @@ extern void transformFromClause(ParseState *pstate, List *frmList); extern int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource, AclMode requiredPerms); extern bool interpretInhOption(InhOption inhOpt); -extern bool interpretOidsOption(List *defList); +extern bool interpretOidsOption(List *defList, char relkind); extern Node *transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName);