1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* view.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* use rewrite rules to construct views
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2019-01-02 18:44:25 +01:00
|
|
|
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2002-09-02 04:13:02 +02:00
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/commands/view.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1999-07-16 01:04:24 +02:00
|
|
|
#include "postgres.h"
|
1996-11-06 09:21:43 +01:00
|
|
|
|
2019-01-21 19:18:20 +01:00
|
|
|
#include "access/relation.h"
|
2006-07-13 18:49:20 +02:00
|
|
|
#include "access/xact.h"
|
2002-03-29 20:06:29 +01:00
|
|
|
#include "catalog/namespace.h"
|
2006-07-02 04:23:23 +02:00
|
|
|
#include "commands/defrem.h"
|
2002-04-15 07:22:04 +02:00
|
|
|
#include "commands/tablecmds.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "commands/view.h"
|
2000-07-04 08:11:54 +02:00
|
|
|
#include "miscadmin.h"
|
2000-02-15 04:38:29 +01:00
|
|
|
#include "nodes/makefuncs.h"
|
2008-08-26 00:42:34 +02:00
|
|
|
#include "nodes/nodeFuncs.h"
|
2007-03-13 01:33:44 +01:00
|
|
|
#include "parser/analyze.h"
|
1999-07-16 01:04:24 +02:00
|
|
|
#include "parser/parse_relation.h"
|
|
|
|
#include "rewrite/rewriteDefine.h"
|
2013-07-18 23:10:16 +02:00
|
|
|
#include "rewrite/rewriteHandler.h"
|
2019-11-12 04:00:16 +01:00
|
|
|
#include "rewrite/rewriteManip.h"
|
2001-08-12 23:35:19 +02:00
|
|
|
#include "rewrite/rewriteSupport.h"
|
2002-09-02 04:13:02 +02:00
|
|
|
#include "utils/acl.h"
|
2008-12-16 01:56:12 +01:00
|
|
|
#include "utils/builtins.h"
|
2002-09-02 04:13:02 +02:00
|
|
|
#include "utils/lsyscache.h"
|
2008-06-19 02:46:06 +02:00
|
|
|
#include "utils/rel.h"
|
2011-12-22 22:15:57 +01:00
|
|
|
#include "utils/syscache.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2002-09-02 22:04:40 +02:00
|
|
|
static void checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc);
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*---------------------------------------------------------------------
|
|
|
|
* DefineVirtualRelation
|
|
|
|
*
|
2016-12-21 17:58:18 +01:00
|
|
|
* Create a view relation and use the rules system to store the query
|
|
|
|
* for the view.
|
2018-10-07 00:17:46 +02:00
|
|
|
*
|
|
|
|
* EventTriggerAlterTableStart must have been called already.
|
1996-07-09 08:22:35 +02:00
|
|
|
*---------------------------------------------------------------------
|
|
|
|
*/
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
static ObjectAddress
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
|
2016-12-21 17:58:18 +01:00
|
|
|
List *options, Query *viewParse)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
Fix bugs in relpersistence handling during table creation.
Unlike the relistemp field which it replaced, relpersistence must be
set correctly quite early during the table creation process, as we
rely on it quite early on for a number of purposes, including security
checks. Normally, this is set based on whether the user enters CREATE
TABLE, CREATE UNLOGGED TABLE, or CREATE TEMPORARY TABLE, but a
relation may also be made implicitly temporary by creating it in
pg_temp. This patch fixes the handling of that case, and also
disables creation of unlogged tables in temporary tablespace (such
table indeed skip WAL-logging, but we reject an explicit
specification) and creation of relations in the temporary schemas of
other sessions (which is not very sensible, and didn't work right
anyway).
Report by Amit Khandekar.
2011-07-03 23:34:47 +02:00
|
|
|
Oid viewOid;
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
LOCKMODE lockmode;
|
2000-09-29 20:21:41 +02:00
|
|
|
CreateStmt *createStmt = makeNode(CreateStmt);
|
2004-05-26 06:41:50 +02:00
|
|
|
List *attrList;
|
|
|
|
ListCell *t;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* create a list of ColumnDef nodes based on the names and types of the
|
|
|
|
* (non-junk) targetlist items from the view's SELECT list.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
|
|
|
attrList = NIL;
|
2002-09-04 22:31:48 +02:00
|
|
|
foreach(t, tlist)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2016-06-27 21:57:21 +02:00
|
|
|
TargetEntry *tle = (TargetEntry *) lfirst(t);
|
2000-09-29 20:21:41 +02:00
|
|
|
|
2005-04-06 18:34:07 +02:00
|
|
|
if (!tle->resjunk)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2016-06-27 21:57:21 +02:00
|
|
|
ColumnDef *def = makeColumnDef(tle->resname,
|
|
|
|
exprType((Node *) tle->expr),
|
|
|
|
exprTypmod((Node *) tle->expr),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
exprCollation((Node *) tle->expr));
|
2011-04-10 17:42:00 +02:00
|
|
|
|
Remove collation information from TypeName, where it does not belong.
The initial collations patch treated a COLLATE spec as part of a TypeName,
following what can only be described as brain fade on the part of the SQL
committee. It's a lot more reasonable to treat COLLATE as a syntactically
separate object, so that it can be added in only the productions where it
actually belongs, rather than needing to reject it in a boatload of places
where it doesn't belong (something the original patch mostly failed to do).
In addition this change lets us meet the spec's requirement to allow
COLLATE anywhere in the clauses of a ColumnDef, and it avoids unfriendly
behavior for constructs such as "foo::type COLLATE collation".
To do this, pull collation information out of TypeName and put it in
ColumnDef instead, thus reverting most of the collation-related changes in
parse_type.c's API. I made one additional structural change, which was to
use a ColumnDef as an intermediate node in AT_AlterColumnType AlterTableCmd
nodes. This provides enough room to get rid of the "transform" wart in
AlterTableCmd too, since the ColumnDef can carry the USING expression
easily enough.
Also fix some other minor bugs that have crept in in the same areas,
like failure to copy recently-added fields of ColumnDef in copyfuncs.c.
While at it, document the formerly secret ability to specify a collation
in ALTER TABLE ALTER COLUMN TYPE, ALTER TYPE ADD ATTRIBUTE, and
ALTER TYPE ALTER ATTRIBUTE TYPE; and correct some misstatements about
what the default collation selection will be when COLLATE is omitted.
BTW, the three-parameter form of format_type() should go away too,
since it just contributes to the confusion in this area; but I'll do
that in a separate patch.
2011-03-10 04:38:52 +01:00
|
|
|
/*
|
2011-03-20 01:29:08 +01:00
|
|
|
* It's possible that the column is of a collatable type but the
|
|
|
|
* collation could not be resolved, so double-check.
|
Remove collation information from TypeName, where it does not belong.
The initial collations patch treated a COLLATE spec as part of a TypeName,
following what can only be described as brain fade on the part of the SQL
committee. It's a lot more reasonable to treat COLLATE as a syntactically
separate object, so that it can be added in only the productions where it
actually belongs, rather than needing to reject it in a boatload of places
where it doesn't belong (something the original patch mostly failed to do).
In addition this change lets us meet the spec's requirement to allow
COLLATE anywhere in the clauses of a ColumnDef, and it avoids unfriendly
behavior for constructs such as "foo::type COLLATE collation".
To do this, pull collation information out of TypeName and put it in
ColumnDef instead, thus reverting most of the collation-related changes in
parse_type.c's API. I made one additional structural change, which was to
use a ColumnDef as an intermediate node in AT_AlterColumnType AlterTableCmd
nodes. This provides enough room to get rid of the "transform" wart in
AlterTableCmd too, since the ColumnDef can carry the USING expression
easily enough.
Also fix some other minor bugs that have crept in in the same areas,
like failure to copy recently-added fields of ColumnDef in copyfuncs.c.
While at it, document the formerly secret ability to specify a collation
in ALTER TABLE ALTER COLUMN TYPE, ALTER TYPE ADD ATTRIBUTE, and
ALTER TYPE ALTER ATTRIBUTE TYPE; and correct some misstatements about
what the default collation selection will be when COLLATE is omitted.
BTW, the three-parameter form of format_type() should go away too,
since it just contributes to the confusion in this area; but I'll do
that in a separate patch.
2011-03-10 04:38:52 +01:00
|
|
|
*/
|
|
|
|
if (type_is_collatable(exprType((Node *) tle->expr)))
|
2011-03-20 01:29:08 +01:00
|
|
|
{
|
|
|
|
if (!OidIsValid(def->collOid))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
2011-03-22 21:55:32 +01:00
|
|
|
errmsg("could not determine which collation to use for view column \"%s\"",
|
2011-03-20 01:29:08 +01:00
|
|
|
def->colname),
|
|
|
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
|
|
|
}
|
Remove collation information from TypeName, where it does not belong.
The initial collations patch treated a COLLATE spec as part of a TypeName,
following what can only be described as brain fade on the part of the SQL
committee. It's a lot more reasonable to treat COLLATE as a syntactically
separate object, so that it can be added in only the productions where it
actually belongs, rather than needing to reject it in a boatload of places
where it doesn't belong (something the original patch mostly failed to do).
In addition this change lets us meet the spec's requirement to allow
COLLATE anywhere in the clauses of a ColumnDef, and it avoids unfriendly
behavior for constructs such as "foo::type COLLATE collation".
To do this, pull collation information out of TypeName and put it in
ColumnDef instead, thus reverting most of the collation-related changes in
parse_type.c's API. I made one additional structural change, which was to
use a ColumnDef as an intermediate node in AT_AlterColumnType AlterTableCmd
nodes. This provides enough room to get rid of the "transform" wart in
AlterTableCmd too, since the ColumnDef can carry the USING expression
easily enough.
Also fix some other minor bugs that have crept in in the same areas,
like failure to copy recently-added fields of ColumnDef in copyfuncs.c.
While at it, document the formerly secret ability to specify a collation
in ALTER TABLE ALTER COLUMN TYPE, ALTER TYPE ADD ATTRIBUTE, and
ALTER TYPE ALTER ATTRIBUTE TYPE; and correct some misstatements about
what the default collation selection will be when COLLATE is omitted.
BTW, the three-parameter form of format_type() should go away too,
since it just contributes to the confusion in this area; but I'll do
that in a separate patch.
2011-03-10 04:38:52 +01:00
|
|
|
else
|
2011-03-20 01:29:08 +01:00
|
|
|
Assert(!OidIsValid(def->collOid));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
attrList = lappend(attrList, def);
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2000-09-29 20:21:41 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
* Look up, check permissions on, and lock the creation namespace; also
|
|
|
|
* check for a preexisting view with the same name. This will also set
|
|
|
|
* relation->relpersistence to RELPERSISTENCE_TEMP if the selected
|
|
|
|
* namespace is temporary.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
lockmode = replace ? AccessExclusiveLock : NoLock;
|
2012-01-18 10:22:54 +01:00
|
|
|
(void) RangeVarGetAndCheckCreationNamespace(relation, lockmode, &viewOid);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-09-02 04:13:02 +02:00
|
|
|
if (OidIsValid(viewOid) && replace)
|
|
|
|
{
|
|
|
|
Relation rel;
|
|
|
|
TupleDesc descriptor;
|
2011-12-22 22:15:57 +01:00
|
|
|
List *atcmds = NIL;
|
|
|
|
AlterTableCmd *atcmd;
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress address;
|
2002-09-02 04:13:02 +02:00
|
|
|
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
/* Relation is already locked, but we must build a relcache entry. */
|
|
|
|
rel = relation_open(viewOid, NoLock);
|
2002-09-02 04:13:02 +02:00
|
|
|
|
Prevent adding relations to a concurrently dropped schema.
In the previous coding, it was possible for a relation to be created
via CREATE TABLE, CREATE VIEW, CREATE SEQUENCE, CREATE FOREIGN TABLE,
etc. in a schema while that schema was meanwhile being concurrently
dropped. This led to a pg_class entry with an invalid relnamespace
value. The same problem could occur if a relation was moved using
ALTER .. SET SCHEMA while the target schema was being concurrently
dropped. This patch prevents both of those scenarios by locking the
schema to which the relation is being added using AccessShareLock,
which conflicts with the AccessExclusiveLock taken by DROP.
As a desirable side effect, this also prevents the use of CREATE OR
REPLACE VIEW to queue for an AccessExclusiveLock on a relation on which
you have no rights: that will now fail immediately with a permissions
error, before trying to obtain a lock.
We need similar protection for all other object types, but as everything
other than relations uses a slightly different set of code paths, I'm
leaving that for a separate commit.
Original complaint (as far as I could find) about CREATE by Nikhil
Sontakke; risk for ALTER .. SET SCHEMA pointed out by Tom Lane;
further details by Dan Farina; patch by me; review by Hitoshi Harada.
2012-01-16 15:34:21 +01:00
|
|
|
/* Make sure it *is* a view. */
|
2002-09-02 04:13:02 +02:00
|
|
|
if (rel->rd_rel->relkind != RELKIND_VIEW)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
errmsg("\"%s\" is not a view",
|
|
|
|
RelationGetRelationName(rel))));
|
2002-09-02 04:13:02 +02:00
|
|
|
|
2008-12-15 22:35:31 +01:00
|
|
|
/* Also check it's not in use already */
|
|
|
|
CheckTableNotInUse(rel, "CREATE OR REPLACE VIEW");
|
|
|
|
|
2005-02-02 07:36:02 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Due to the namespace visibility rules for temporary objects, we
|
|
|
|
* should only end up replacing a temporary view with another
|
2010-12-13 18:34:26 +01:00
|
|
|
* temporary view, and similarly for permanent views.
|
2005-02-02 07:36:02 +01:00
|
|
|
*/
|
2010-12-13 18:34:26 +01:00
|
|
|
Assert(relation->relpersistence == rel->rd_rel->relpersistence);
|
2005-02-02 07:36:02 +01:00
|
|
|
|
2008-12-07 00:22:46 +01:00
|
|
|
/*
|
2008-12-15 22:35:31 +01:00
|
|
|
* Create a tuple descriptor to compare against the existing view, and
|
|
|
|
* verify that the old column list is an initial prefix of the new
|
|
|
|
* column list.
|
|
|
|
*/
|
|
|
|
descriptor = BuildDescForRelation(attrList);
|
|
|
|
checkViewTupleDesc(descriptor, rel->rd_att);
|
|
|
|
|
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* If new attributes have been added, we must add pg_attribute entries
|
2008-12-15 22:35:31 +01:00
|
|
|
* for them. It is convenient (although overkill) to use the ALTER
|
|
|
|
* TABLE ADD COLUMN infrastructure for this.
|
2016-12-21 17:58:18 +01:00
|
|
|
*
|
|
|
|
* Note that we must do this before updating the query for the view,
|
|
|
|
* since the rules system requires that the correct view columns be in
|
|
|
|
* place when defining the new rules.
|
2008-12-15 22:35:31 +01:00
|
|
|
*/
|
|
|
|
if (list_length(attrList) > rel->rd_att->natts)
|
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
ListCell *c;
|
2008-12-07 00:22:46 +01:00
|
|
|
int skip = rel->rd_att->natts;
|
|
|
|
|
2008-12-15 22:35:31 +01:00
|
|
|
foreach(c, attrList)
|
|
|
|
{
|
|
|
|
if (skip > 0)
|
|
|
|
{
|
|
|
|
skip--;
|
2008-12-07 00:22:46 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
atcmd = makeNode(AlterTableCmd);
|
|
|
|
atcmd->subtype = AT_AddColumnToView;
|
2008-12-15 22:35:31 +01:00
|
|
|
atcmd->def = (Node *) lfirst(c);
|
2008-12-07 00:22:46 +01:00
|
|
|
atcmds = lappend(atcmds, atcmd);
|
|
|
|
}
|
2016-12-21 17:58:18 +01:00
|
|
|
|
2018-10-07 00:17:46 +02:00
|
|
|
/* EventTriggerAlterTableStart called by ProcessUtilitySlow */
|
2016-12-21 17:58:18 +01:00
|
|
|
AlterTableInternal(viewOid, atcmds, true);
|
|
|
|
|
|
|
|
/* Make the new view columns visible */
|
|
|
|
CommandCounterIncrement();
|
2008-12-07 00:22:46 +01:00
|
|
|
}
|
|
|
|
|
2016-12-21 17:58:18 +01:00
|
|
|
/*
|
|
|
|
* Update the query for the view.
|
|
|
|
*
|
|
|
|
* Note that we must do this before updating the view options, because
|
|
|
|
* the new options may not be compatible with the old view query (for
|
|
|
|
* example if we attempt to add the WITH CHECK OPTION, we require that
|
|
|
|
* the new view be automatically updatable, but the old view may not
|
|
|
|
* have been).
|
|
|
|
*/
|
|
|
|
StoreViewQuery(viewOid, viewParse, replace);
|
|
|
|
|
|
|
|
/* Make the new view query visible */
|
|
|
|
CommandCounterIncrement();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Finally update the view options.
|
|
|
|
*
|
|
|
|
* The new options list replaces the existing options list, even if
|
|
|
|
* it's empty.
|
|
|
|
*/
|
|
|
|
atcmd = makeNode(AlterTableCmd);
|
|
|
|
atcmd->subtype = AT_ReplaceRelOptions;
|
|
|
|
atcmd->def = (Node *) options;
|
|
|
|
atcmds = list_make1(atcmd);
|
|
|
|
|
2018-10-07 00:17:46 +02:00
|
|
|
/* EventTriggerAlterTableStart called by ProcessUtilitySlow */
|
2011-12-22 22:15:57 +01:00
|
|
|
AlterTableInternal(viewOid, atcmds, true);
|
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddressSet(address, RelationRelationId, viewOid);
|
|
|
|
|
2002-09-02 04:13:02 +02:00
|
|
|
/*
|
|
|
|
* Seems okay, so return the OID of the pre-existing view.
|
|
|
|
*/
|
2002-09-04 22:31:48 +02:00
|
|
|
relation_close(rel, NoLock); /* keep the lock! */
|
2002-09-02 04:13:02 +02:00
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
return address;
|
2002-09-02 04:13:02 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress address;
|
2010-07-26 01:21:22 +02:00
|
|
|
|
2002-09-02 04:13:02 +02:00
|
|
|
/*
|
2016-12-21 17:58:18 +01:00
|
|
|
* Set the parameters for keys/inheritance etc. All of these are
|
2005-10-15 04:49:52 +02:00
|
|
|
* uninteresting for views...
|
2002-09-02 04:13:02 +02:00
|
|
|
*/
|
2012-02-26 14:22:27 +01:00
|
|
|
createStmt->relation = relation;
|
2002-09-02 04:13:02 +02:00
|
|
|
createStmt->tableElts = attrList;
|
|
|
|
createStmt->inhRelations = NIL;
|
|
|
|
createStmt->constraints = NIL;
|
2011-12-22 22:15:57 +01:00
|
|
|
createStmt->options = options;
|
2002-11-11 23:19:25 +01:00
|
|
|
createStmt->oncommit = ONCOMMIT_NOOP;
|
2004-06-18 08:14:31 +02:00
|
|
|
createStmt->tablespacename = NULL;
|
2010-07-26 01:21:22 +02:00
|
|
|
createStmt->if_not_exists = false;
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2002-09-02 04:13:02 +02:00
|
|
|
/*
|
2016-12-21 17:58:18 +01:00
|
|
|
* Create the relation (this will error out if there's an existing
|
|
|
|
* view, so we don't need more code to complain if "replace" is
|
|
|
|
* false).
|
2002-09-02 04:13:02 +02:00
|
|
|
*/
|
Implement table partitioning.
Table partitioning is like table inheritance and reuses much of the
existing infrastructure, but there are some important differences.
The parent is called a partitioned table and is always empty; it may
not have indexes or non-inherited constraints, since those make no
sense for a relation with no data of its own. The children are called
partitions and contain all of the actual data. Each partition has an
implicit partitioning constraint. Multiple inheritance is not
allowed, and partitioning and inheritance can't be mixed. Partitions
can't have extra columns and may not allow nulls unless the parent
does. Tuples inserted into the parent are automatically routed to the
correct partition, so tuple-routing ON INSERT triggers are not needed.
Tuple routing isn't yet supported for partitions which are foreign
tables, and it doesn't handle updates that cross partition boundaries.
Currently, tables can be range-partitioned or list-partitioned. List
partitioning is limited to a single column, but range partitioning can
involve multiple columns. A partitioning "column" can be an
expression.
Because table partitioning is less general than table inheritance, it
is hoped that it will be easier to reason about properties of
partitions, and therefore that this will serve as a better foundation
for a variety of possible optimizations, including query planner
optimizations. The tuple routing based which this patch does based on
the implicit partitioning constraints is an example of this, but it
seems likely that many other useful optimizations are also possible.
Amit Langote, reviewed and tested by Robert Haas, Ashutosh Bapat,
Amit Kapila, Rajkumar Raghuwanshi, Corey Huinker, Jaime Casanova,
Rushabh Lathia, Erik Rijkers, among others. Minor revisions by me.
2016-12-07 19:17:43 +01:00
|
|
|
address = DefineRelation(createStmt, RELKIND_VIEW, InvalidOid, NULL,
|
|
|
|
NULL);
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
Assert(address.objectId != InvalidOid);
|
2016-12-21 17:58:18 +01:00
|
|
|
|
|
|
|
/* Make the new view relation visible */
|
|
|
|
CommandCounterIncrement();
|
|
|
|
|
|
|
|
/* Store the query for the view */
|
|
|
|
StoreViewQuery(address.objectId, viewParse, replace);
|
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
return address;
|
2002-09-02 04:13:02 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2002-09-02 22:04:40 +02:00
|
|
|
/*
|
|
|
|
* Verify that tupledesc associated with proposed new view definition
|
|
|
|
* matches tupledesc of old view. This is basically a cut-down version
|
|
|
|
* of equalTupleDescs(), with code added to generate specific complaints.
|
2008-12-15 22:35:31 +01:00
|
|
|
* Also, we allow the new tupledesc to have more columns than the old.
|
2002-09-02 22:04:40 +02:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2008-12-07 00:22:46 +01:00
|
|
|
if (newdesc->natts < olddesc->natts)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
2008-12-07 00:22:46 +01:00
|
|
|
errmsg("cannot drop columns from view")));
|
2002-09-02 22:04:40 +02:00
|
|
|
|
2008-12-07 00:22:46 +01:00
|
|
|
for (i = 0; i < olddesc->natts; i++)
|
2002-09-02 22:04:40 +02:00
|
|
|
{
|
2017-08-20 20:19:07 +02:00
|
|
|
Form_pg_attribute newattr = TupleDescAttr(newdesc, i);
|
|
|
|
Form_pg_attribute oldattr = TupleDescAttr(olddesc, i);
|
2002-09-02 22:04:40 +02:00
|
|
|
|
2008-12-16 01:56:12 +01:00
|
|
|
/* XXX msg not right, but we don't support DROP COL on view anyway */
|
2002-09-02 22:04:40 +02:00
|
|
|
if (newattr->attisdropped != oldattr->attisdropped)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
2008-12-07 00:22:46 +01:00
|
|
|
errmsg("cannot drop columns from view")));
|
2002-09-02 22:04:40 +02:00
|
|
|
|
|
|
|
if (strcmp(NameStr(newattr->attname), NameStr(oldattr->attname)) != 0)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("cannot change name of view column \"%s\" to \"%s\"",
|
|
|
|
NameStr(oldattr->attname),
|
|
|
|
NameStr(newattr->attname))));
|
2002-09-02 22:04:40 +02:00
|
|
|
/* XXX would it be safe to allow atttypmod to change? Not sure */
|
|
|
|
if (newattr->atttypid != oldattr->atttypid ||
|
|
|
|
newattr->atttypmod != oldattr->atttypmod)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
2008-12-16 01:56:12 +01:00
|
|
|
errmsg("cannot change data type of view column \"%s\" from %s to %s",
|
|
|
|
NameStr(oldattr->attname),
|
|
|
|
format_type_with_typemod(oldattr->atttypid,
|
|
|
|
oldattr->atttypmod),
|
|
|
|
format_type_with_typemod(newattr->atttypid,
|
|
|
|
newattr->atttypmod))));
|
2002-09-02 22:04:40 +02:00
|
|
|
/* We can ignore the remaining attributes of an attribute... */
|
|
|
|
}
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2002-09-02 22:04:40 +02:00
|
|
|
/*
|
|
|
|
* We ignore the constraint fields. The new view desc can't have any
|
|
|
|
* constraints, and the only ones that could be on the old view are
|
|
|
|
* defaults, which we are happy to leave in place.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
static void
|
2007-08-27 05:36:08 +02:00
|
|
|
DefineViewRules(Oid viewOid, Query *viewParse, bool replace)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2007-03-13 01:33:44 +01:00
|
|
|
/*
|
|
|
|
* Set up the ON SELECT rule. Since the query has already been through
|
|
|
|
* parse analysis, we use DefineQueryRewrite() directly.
|
|
|
|
*/
|
|
|
|
DefineQueryRewrite(pstrdup(ViewSelectRuleName),
|
2007-08-27 05:36:08 +02:00
|
|
|
viewOid,
|
2007-03-13 01:33:44 +01:00
|
|
|
NULL,
|
|
|
|
CMD_SELECT,
|
2009-01-27 13:40:15 +01:00
|
|
|
true,
|
2007-03-13 01:33:44 +01:00
|
|
|
replace,
|
|
|
|
list_make1(viewParse));
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2007-03-13 01:33:44 +01:00
|
|
|
/*
|
2009-01-27 13:40:15 +01:00
|
|
|
* Someday: automatic ON INSERT, etc
|
2007-03-13 01:33:44 +01:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*---------------------------------------------------------------
|
|
|
|
* UpdateRangeTableOfViewParse
|
|
|
|
*
|
|
|
|
* Update the range table of the given parsetree.
|
|
|
|
* This update consists of adding two new entries IN THE BEGINNING
|
|
|
|
* of the range table (otherwise the rule system will die a slow,
|
|
|
|
* horrible and painful death, and we do not want that now, do we?)
|
2000-06-12 21:40:58 +02:00
|
|
|
* one for the OLD relation and one for the NEW one (both of
|
1996-07-09 08:22:35 +02:00
|
|
|
* them refer in fact to the "view" relation).
|
|
|
|
*
|
|
|
|
* Of course we must also increase the 'varnos' of all the Var nodes
|
|
|
|
* by 2...
|
|
|
|
*
|
2000-12-21 18:36:15 +01:00
|
|
|
* These extra RT entries are not actually used in the query,
|
Create an RTE field to record the query's lock mode for each relation.
Add RangeTblEntry.rellockmode, which records the appropriate lock mode for
each RTE_RELATION rangetable entry (either AccessShareLock, RowShareLock,
or RowExclusiveLock depending on the RTE's role in the query).
This patch creates the field and makes all creators of RTE nodes fill it
in reasonably, but for the moment nothing much is done with it. The plan
is to replace assorted post-parser logic that re-determines the right
lockmode to use with simple uses of rte->rellockmode. For now, just add
Asserts in each of those places that the rellockmode matches what they are
computing today. (In some cases the match isn't perfect, so the Asserts
are weaker than you might expect; but this seems OK, as per discussion.)
This passes check-world for me, but it seems worth pushing in this state
to see if the buildfarm finds any problems in cases I failed to test.
catversion bump due to change of stored rules.
Amit Langote, reviewed by David Rowley and Jesper Pedersen,
and whacked around a bit more by me
Discussion: https://postgr.es/m/468c85d9-540e-66a2-1dde-fec2b741e688@lab.ntt.co.jp
2018-09-30 19:55:51 +02:00
|
|
|
* except for run-time locking and permission checking.
|
1996-07-09 08:22:35 +02:00
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
2000-12-21 18:36:15 +01:00
|
|
|
static Query *
|
2002-03-22 03:56:37 +01:00
|
|
|
UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2005-04-13 18:50:55 +02:00
|
|
|
Relation viewRel;
|
1997-09-08 04:41:22 +02:00
|
|
|
List *new_rt;
|
|
|
|
RangeTblEntry *rt_entry1,
|
|
|
|
*rt_entry2;
|
2015-03-11 20:26:43 +01:00
|
|
|
ParseState *pstate;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Make a copy of the given parsetree. It's not so much that we don't
|
2005-10-15 04:49:52 +02:00
|
|
|
* want to scribble on our input, it's that the parser has a bad habit of
|
|
|
|
* outputting multiple links to the same subtree for constructs like
|
|
|
|
* BETWEEN, and we mustn't have OffsetVarNodes increment the varno of a
|
2014-05-06 18:12:18 +02:00
|
|
|
* Var node twice. copyObject will expand any multiply-referenced subtree
|
2005-10-15 04:49:52 +02:00
|
|
|
* into multiple copies.
|
2000-12-21 18:36:15 +01:00
|
|
|
*/
|
2017-03-09 21:18:59 +01:00
|
|
|
viewParse = copyObject(viewParse);
|
2000-12-21 18:36:15 +01:00
|
|
|
|
2015-03-11 20:26:43 +01:00
|
|
|
/* Create a dummy ParseState for addRangeTableEntryForRelation */
|
|
|
|
pstate = make_parsestate(NULL);
|
|
|
|
|
2005-04-13 18:50:55 +02:00
|
|
|
/* need to open the rel for addRangeTableEntryForRelation */
|
|
|
|
viewRel = relation_open(viewOid, AccessShareLock);
|
|
|
|
|
2000-12-21 18:36:15 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Create the 2 new range table entries and form the new range table...
|
|
|
|
* OLD first, then NEW....
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2015-03-11 20:26:43 +01:00
|
|
|
rt_entry1 = addRangeTableEntryForRelation(pstate, viewRel,
|
Create an RTE field to record the query's lock mode for each relation.
Add RangeTblEntry.rellockmode, which records the appropriate lock mode for
each RTE_RELATION rangetable entry (either AccessShareLock, RowShareLock,
or RowExclusiveLock depending on the RTE's role in the query).
This patch creates the field and makes all creators of RTE nodes fill it
in reasonably, but for the moment nothing much is done with it. The plan
is to replace assorted post-parser logic that re-determines the right
lockmode to use with simple uses of rte->rellockmode. For now, just add
Asserts in each of those places that the rellockmode matches what they are
computing today. (In some cases the match isn't perfect, so the Asserts
are weaker than you might expect; but this seems OK, as per discussion.)
This passes check-world for me, but it seems worth pushing in this state
to see if the buildfarm finds any problems in cases I failed to test.
catversion bump due to change of stored rules.
Amit Langote, reviewed by David Rowley and Jesper Pedersen,
and whacked around a bit more by me
Discussion: https://postgr.es/m/468c85d9-540e-66a2-1dde-fec2b741e688@lab.ntt.co.jp
2018-09-30 19:55:51 +02:00
|
|
|
AccessShareLock,
|
2009-11-06 00:24:27 +01:00
|
|
|
makeAlias("old", NIL),
|
2002-03-22 03:56:37 +01:00
|
|
|
false, false);
|
2015-03-11 20:26:43 +01:00
|
|
|
rt_entry2 = addRangeTableEntryForRelation(pstate, viewRel,
|
Create an RTE field to record the query's lock mode for each relation.
Add RangeTblEntry.rellockmode, which records the appropriate lock mode for
each RTE_RELATION rangetable entry (either AccessShareLock, RowShareLock,
or RowExclusiveLock depending on the RTE's role in the query).
This patch creates the field and makes all creators of RTE nodes fill it
in reasonably, but for the moment nothing much is done with it. The plan
is to replace assorted post-parser logic that re-determines the right
lockmode to use with simple uses of rte->rellockmode. For now, just add
Asserts in each of those places that the rellockmode matches what they are
computing today. (In some cases the match isn't perfect, so the Asserts
are weaker than you might expect; but this seems OK, as per discussion.)
This passes check-world for me, but it seems worth pushing in this state
to see if the buildfarm finds any problems in cases I failed to test.
catversion bump due to change of stored rules.
Amit Langote, reviewed by David Rowley and Jesper Pedersen,
and whacked around a bit more by me
Discussion: https://postgr.es/m/468c85d9-540e-66a2-1dde-fec2b741e688@lab.ntt.co.jp
2018-09-30 19:55:51 +02:00
|
|
|
AccessShareLock,
|
2009-11-06 00:24:27 +01:00
|
|
|
makeAlias("new", NIL),
|
2002-03-22 03:56:37 +01:00
|
|
|
false, false);
|
2000-09-29 20:21:41 +02:00
|
|
|
/* Must override addRangeTableEntry's default access-check flags */
|
2004-01-15 00:01:55 +01:00
|
|
|
rt_entry1->requiredPerms = 0;
|
|
|
|
rt_entry2->requiredPerms = 0;
|
2000-09-29 20:21:41 +02:00
|
|
|
|
2000-09-12 23:07:18 +02:00
|
|
|
new_rt = lcons(rt_entry1, lcons(rt_entry2, viewParse->rtable));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
viewParse->rtable = new_rt;
|
2000-09-12 23:07:18 +02:00
|
|
|
|
|
|
|
/*
|
2000-12-21 18:36:15 +01:00
|
|
|
* Now offset all var nodes by 2, and jointree RT indexes too.
|
2000-09-12 23:07:18 +02:00
|
|
|
*/
|
|
|
|
OffsetVarNodes((Node *) viewParse, 2, 0);
|
2000-12-21 18:36:15 +01:00
|
|
|
|
2005-04-13 18:50:55 +02:00
|
|
|
relation_close(viewRel, AccessShareLock);
|
|
|
|
|
2000-12-21 18:36:15 +01:00
|
|
|
return viewParse;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2007-03-13 01:33:44 +01:00
|
|
|
/*
|
1996-07-09 08:22:35 +02:00
|
|
|
* DefineView
|
2007-03-13 01:33:44 +01:00
|
|
|
* Execute a CREATE VIEW command.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
DefineView(ViewStmt *stmt, const char *queryString,
|
|
|
|
int stmt_location, int stmt_len)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
RawStmt *rawstmt;
|
2007-03-13 01:33:44 +01:00
|
|
|
Query *viewParse;
|
|
|
|
RangeVar *view;
|
2013-07-18 23:10:16 +02:00
|
|
|
ListCell *cell;
|
|
|
|
bool check_option;
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
ObjectAddress address;
|
2007-03-13 01:33:44 +01:00
|
|
|
|
|
|
|
/*
|
2007-11-15 22:14:46 +01:00
|
|
|
* Run parse analysis to convert the raw parse tree to a Query. Note this
|
|
|
|
* also acquires sufficient locks on the source table(s).
|
2007-03-13 01:33:44 +01:00
|
|
|
*
|
|
|
|
* Since parse analysis scribbles on its input, copy the raw parse tree;
|
|
|
|
* this ensures we don't corrupt a prepared statement, for example.
|
|
|
|
*/
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
rawstmt = makeNode(RawStmt);
|
|
|
|
rawstmt->stmt = (Node *) copyObject(stmt->query);
|
|
|
|
rawstmt->stmt_location = stmt_location;
|
|
|
|
rawstmt->stmt_len = stmt_len;
|
|
|
|
|
2017-04-01 06:17:18 +02:00
|
|
|
viewParse = parse_analyze(rawstmt, queryString, NULL, 0, NULL);
|
2007-03-13 01:33:44 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The grammar should ensure that the result is a single SELECT Query.
|
Restructure SELECT INTO's parsetree representation into CreateTableAsStmt.
Making this operation look like a utility statement seems generally a good
idea, and particularly so in light of the desire to provide command
triggers for utility statements. The original choice of representing it as
SELECT with an IntoClause appendage had metastasized into rather a lot of
places, unfortunately, so that this patch is a great deal more complicated
than one might at first expect.
In particular, keeping EXPLAIN working for SELECT INTO and CREATE TABLE AS
subcommands required restructuring some EXPLAIN-related APIs. Add-on code
that calls ExplainOnePlan or ExplainOneUtility, or uses
ExplainOneQuery_hook, will need adjustment.
Also, the cases PREPARE ... SELECT INTO and CREATE RULE ... SELECT INTO,
which formerly were accepted though undocumented, are no longer accepted.
The PREPARE case can be replaced with use of CREATE TABLE AS EXECUTE.
The CREATE RULE case doesn't seem to have much real-world use (since the
rule would work only once before failing with "table already exists"),
so we'll not bother with that one.
Both SELECT INTO and CREATE TABLE AS still return a command tag of
"SELECT nnnn". There was some discussion of returning "CREATE TABLE nnnn",
but for the moment backwards compatibility wins the day.
Andres Freund and Tom Lane
2012-03-20 02:37:19 +01:00
|
|
|
* However, it doesn't forbid SELECT INTO, so we have to check for that.
|
2007-03-13 01:33:44 +01:00
|
|
|
*/
|
Restructure SELECT INTO's parsetree representation into CreateTableAsStmt.
Making this operation look like a utility statement seems generally a good
idea, and particularly so in light of the desire to provide command
triggers for utility statements. The original choice of representing it as
SELECT with an IntoClause appendage had metastasized into rather a lot of
places, unfortunately, so that this patch is a great deal more complicated
than one might at first expect.
In particular, keeping EXPLAIN working for SELECT INTO and CREATE TABLE AS
subcommands required restructuring some EXPLAIN-related APIs. Add-on code
that calls ExplainOnePlan or ExplainOneUtility, or uses
ExplainOneQuery_hook, will need adjustment.
Also, the cases PREPARE ... SELECT INTO and CREATE RULE ... SELECT INTO,
which formerly were accepted though undocumented, are no longer accepted.
The PREPARE case can be replaced with use of CREATE TABLE AS EXECUTE.
The CREATE RULE case doesn't seem to have much real-world use (since the
rule would work only once before failing with "table already exists"),
so we'll not bother with that one.
Both SELECT INTO and CREATE TABLE AS still return a command tag of
"SELECT nnnn". There was some discussion of returning "CREATE TABLE nnnn",
but for the moment backwards compatibility wins the day.
Andres Freund and Tom Lane
2012-03-20 02:37:19 +01:00
|
|
|
if (!IsA(viewParse, Query))
|
|
|
|
elog(ERROR, "unexpected parse analysis result");
|
|
|
|
if (viewParse->utilityStmt != NULL &&
|
|
|
|
IsA(viewParse->utilityStmt, CreateTableAsStmt))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("views must not contain SELECT INTO")));
|
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency of
representation of lists of statements. It's always been the case
that the output of parse analysis is a list of Query nodes, whatever
the types of the individual statements in the list. This patch brings
similar consistency to the outputs of raw parsing and planning steps:
* The output of raw parsing is now always a list of RawStmt nodes;
the statement-type-dependent nodes are one level down from that.
* The output of pg_plan_queries() is now always a list of PlannedStmt
nodes, even for utility statements. In the case of a utility statement,
"planning" just consists of wrapping a CMD_UTILITY PlannedStmt around
the utility node. This list representation is now used in Portal and
CachedPlan plan lists, replacing the former convention of intermixing
PlannedStmts with bare utility-statement nodes.
Now, every list of statements has a consistent head-node type depending
on how far along it is in processing. This allows changing many places
that formerly used generic "Node *" pointers to use a more specific
pointer type, thus reducing the number of IsA() tests and casts needed,
as well as improving code clarity.
Also, the post-parse-analysis representation of DECLARE CURSOR is changed
so that it looks more like EXPLAIN, PREPARE, etc. That is, the contained
SELECT remains a child of the DeclareCursorStmt rather than getting flipped
around to be the other way. It's now true for both Query and PlannedStmt
that utilityStmt is non-null if and only if commandType is CMD_UTILITY.
That allows simplifying a lot of places that were testing both fields.
(I think some of those were just defensive programming, but in many places,
it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)
Because PlannedStmt carries a canSetTag field, we're also able to get rid
of some ad-hoc rules about how to reconstruct canSetTag for a bare utility
statement; specifically, the assumption that a utility is canSetTag if and
only if it's the only one in its list. While I see no near-term need for
relaxing that restriction, it's nice to get rid of the ad-hocery.
The API of ProcessUtility() is changed so that what it's passed is the
wrapper PlannedStmt not just the bare utility statement. This will affect
all users of ProcessUtility_hook, but the changes are pretty trivial; see
the affected contrib modules for examples of the minimum change needed.
(Most compilers should give pointer-type-mismatch warnings for uncorrected
code.)
There's also a change in the API of ExplainOneQuery_hook, to pass through
cursorOptions instead of expecting hook functions to know what to pick.
This is needed because of the DECLARE CURSOR changes, but really should
have been done in 9.6; it's unlikely that any extant hook functions
know about using CURSOR_OPT_PARALLEL_OK.
Finally, teach gram.y to save statement boundary locations in RawStmt
nodes, and pass those through to Query and PlannedStmt nodes. This allows
more intelligent handling of cases where a source query string contains
multiple statements. This patch doesn't actually do anything with the
information, but a follow-on patch will. (Passing this information through
cleanly is the true motivation for these changes; while I think this is all
good cleanup, it's unlikely we'd have bothered without this end goal.)
catversion bump because addition of location fields to struct Query
affects stored rules.
This patch is by me, but it owes a good deal to Fabien Coelho who did
a lot of preliminary work on the problem, and also reviewed the patch.
Discussion: https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
2017-01-14 22:02:35 +01:00
|
|
|
if (viewParse->commandType != CMD_SELECT)
|
2007-03-13 01:33:44 +01:00
|
|
|
elog(ERROR, "unexpected parse analysis result");
|
|
|
|
|
2011-02-26 00:56:23 +01:00
|
|
|
/*
|
|
|
|
* Check for unsupported cases. These tests are redundant with ones in
|
2011-04-10 17:42:00 +02:00
|
|
|
* DefineQueryRewrite(), but that function will complain about a bogus ON
|
|
|
|
* SELECT rule, and we'd rather the message complain about a view.
|
2011-02-26 00:56:23 +01:00
|
|
|
*/
|
|
|
|
if (viewParse->hasModifyingCTE)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("views must not contain data-modifying statements in WITH")));
|
2011-02-26 00:56:23 +01:00
|
|
|
|
2013-07-18 23:10:16 +02:00
|
|
|
/*
|
|
|
|
* If the user specified the WITH CHECK OPTION, add it to the list of
|
|
|
|
* reloptions.
|
|
|
|
*/
|
|
|
|
if (stmt->withCheckOption == LOCAL_CHECK_OPTION)
|
|
|
|
stmt->options = lappend(stmt->options,
|
|
|
|
makeDefElem("check_option",
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(Node *) makeString("local"), -1));
|
2013-07-18 23:10:16 +02:00
|
|
|
else if (stmt->withCheckOption == CASCADED_CHECK_OPTION)
|
|
|
|
stmt->options = lappend(stmt->options,
|
|
|
|
makeDefElem("check_option",
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(Node *) makeString("cascaded"), -1));
|
2013-07-18 23:10:16 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that the view is auto-updatable if WITH CHECK OPTION was
|
|
|
|
* specified.
|
|
|
|
*/
|
|
|
|
check_option = false;
|
|
|
|
|
|
|
|
foreach(cell, stmt->options)
|
|
|
|
{
|
|
|
|
DefElem *defel = (DefElem *) lfirst(cell);
|
|
|
|
|
Avoid unnecessary use of pg_strcasecmp for already-downcased identifiers.
We have a lot of code in which option names, which from the user's
viewpoint are logically keywords, are passed through the grammar as plain
identifiers, and then matched to string literals during command execution.
This approach avoids making words into lexer keywords unnecessarily. Some
places matched these strings using plain strcmp, some using pg_strcasecmp.
But the latter should be unnecessary since identifiers would have been
downcased on their way through the parser. Aside from any efficiency
concerns (probably not a big factor), the lack of consistency in this area
creates a hazard of subtle bugs due to different places coming to different
conclusions about whether two option names are the same or different.
Hence, standardize on using strcmp() to match any option names that are
expected to have been fed through the parser.
This does create a user-visible behavioral change, which is that while
formerly all of these would work:
alter table foo set (fillfactor = 50);
alter table foo set (FillFactor = 50);
alter table foo set ("fillfactor" = 50);
alter table foo set ("FillFactor" = 50);
now the last case will fail because that double-quoted identifier is
different from the others. However, none of our documentation says that
you can use a quoted identifier in such contexts at all, and we should
discourage doing so since it would break if we ever decide to parse such
constructs as true lexer keywords rather than poor man's substitutes.
So this shouldn't create a significant compatibility issue for users.
Daniel Gustafsson, reviewed by Michael Paquier, small changes by me
Discussion: https://postgr.es/m/29405B24-564E-476B-98C0-677A29805B84@yesql.se
2018-01-27 00:25:02 +01:00
|
|
|
if (strcmp(defel->defname, "check_option") == 0)
|
2013-07-18 23:10:16 +02:00
|
|
|
check_option = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* If the check option is specified, look to see if the view is actually
|
|
|
|
* auto-updatable or not.
|
2013-07-18 23:10:16 +02:00
|
|
|
*/
|
|
|
|
if (check_option)
|
|
|
|
{
|
|
|
|
const char *view_updatable_error =
|
2014-05-06 18:12:18 +02:00
|
|
|
view_query_is_auto_updatable(viewParse, true);
|
2013-07-18 23:10:16 +02:00
|
|
|
|
|
|
|
if (view_updatable_error)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2014-10-12 07:02:56 +02:00
|
|
|
errmsg("WITH CHECK OPTION is supported only on automatically updatable views"),
|
2018-08-21 08:17:13 +02:00
|
|
|
errhint("%s", _(view_updatable_error))));
|
2013-07-18 23:10:16 +02:00
|
|
|
}
|
|
|
|
|
2007-03-13 01:33:44 +01:00
|
|
|
/*
|
|
|
|
* If a list of column names was given, run through and insert these into
|
|
|
|
* the actual query tree. - thomas 2000-03-08
|
|
|
|
*/
|
|
|
|
if (stmt->aliases != NIL)
|
|
|
|
{
|
|
|
|
ListCell *alist_item = list_head(stmt->aliases);
|
|
|
|
ListCell *targetList;
|
|
|
|
|
|
|
|
foreach(targetList, viewParse->targetList)
|
|
|
|
{
|
Improve castNode notation by introducing list-extraction-specific variants.
This extends the castNode() notation introduced by commit 5bcab1114 to
provide, in one step, extraction of a list cell's pointer and coercion to
a concrete node type. For example, "lfirst_node(Foo, lc)" is the same
as "castNode(Foo, lfirst(lc))". Almost half of the uses of castNode
that have appeared so far include a list extraction call, so this is
pretty widely useful, and it saves a few more keystrokes compared to the
old way.
As with the previous patch, back-patch the addition of these macros to
pg_list.h, so that the notation will be available when back-patching.
Patch by me, after an idea of Andrew Gierth's.
Discussion: https://postgr.es/m/14197.1491841216@sss.pgh.pa.us
2017-04-10 19:51:29 +02:00
|
|
|
TargetEntry *te = lfirst_node(TargetEntry, targetList);
|
2007-03-13 01:33:44 +01:00
|
|
|
|
|
|
|
/* junk columns don't get aliases */
|
|
|
|
if (te->resjunk)
|
|
|
|
continue;
|
|
|
|
te->resname = pstrdup(strVal(lfirst(alist_item)));
|
Represent Lists as expansible arrays, not chains of cons-cells.
Originally, Postgres Lists were a more or less exact reimplementation of
Lisp lists, which consist of chains of separately-allocated cons cells,
each having a value and a next-cell link. We'd hacked that once before
(commit d0b4399d8) to add a separate List header, but the data was still
in cons cells. That makes some operations -- notably list_nth() -- O(N),
and it's bulky because of the next-cell pointers and per-cell palloc
overhead, and it's very cache-unfriendly if the cons cells end up
scattered around rather than being adjacent.
In this rewrite, we still have List headers, but the data is in a
resizable array of values, with no next-cell links. Now we need at
most two palloc's per List, and often only one, since we can allocate
some values in the same palloc call as the List header. (Of course,
extending an existing List may require repalloc's to enlarge the array.
But this involves just O(log N) allocations not O(N).)
Of course this is not without downsides. The key difficulty is that
addition or deletion of a list entry may now cause other entries to
move, which it did not before.
For example, that breaks foreach() and sister macros, which historically
used a pointer to the current cons-cell as loop state. We can repair
those macros transparently by making their actual loop state be an
integer list index; the exposed "ListCell *" pointer is no longer state
carried across loop iterations, but is just a derived value. (In
practice, modern compilers can optimize things back to having just one
loop state value, at least for simple cases with inline loop bodies.)
In principle, this is a semantics change for cases where the loop body
inserts or deletes list entries ahead of the current loop index; but
I found no such cases in the Postgres code.
The change is not at all transparent for code that doesn't use foreach()
but chases lists "by hand" using lnext(). The largest share of such
code in the backend is in loops that were maintaining "prev" and "next"
variables in addition to the current-cell pointer, in order to delete
list cells efficiently using list_delete_cell(). However, we no longer
need a previous-cell pointer to delete a list cell efficiently. Keeping
a next-cell pointer doesn't work, as explained above, but we can improve
matters by changing such code to use a regular foreach() loop and then
using the new macro foreach_delete_current() to delete the current cell.
(This macro knows how to update the associated foreach loop's state so
that no cells will be missed in the traversal.)
There remains a nontrivial risk of code assuming that a ListCell *
pointer will remain good over an operation that could now move the list
contents. To help catch such errors, list.c can be compiled with a new
define symbol DEBUG_LIST_MEMORY_USAGE that forcibly moves list contents
whenever that could possibly happen. This makes list operations
significantly more expensive so it's not normally turned on (though it
is on by default if USE_VALGRIND is on).
There are two notable API differences from the previous code:
* lnext() now requires the List's header pointer in addition to the
current cell's address.
* list_delete_cell() no longer requires a previous-cell argument.
These changes are somewhat unfortunate, but on the other hand code using
either function needs inspection to see if it is assuming anything
it shouldn't, so it's not all bad.
Programmers should be aware of these significant performance changes:
* list_nth() and related functions are now O(1); so there's no
major access-speed difference between a list and an array.
* Inserting or deleting a list element now takes time proportional to
the distance to the end of the list, due to moving the array elements.
(However, it typically *doesn't* require palloc or pfree, so except in
long lists it's probably still faster than before.) Notably, lcons()
used to be about the same cost as lappend(), but that's no longer true
if the list is long. Code that uses lcons() and list_delete_first()
to maintain a stack might usefully be rewritten to push and pop at the
end of the list rather than the beginning.
* There are now list_insert_nth...() and list_delete_nth...() functions
that add or remove a list cell identified by index. These have the
data-movement penalty explained above, but there's no search penalty.
* list_concat() and variants now copy the second list's data into
storage belonging to the first list, so there is no longer any
sharing of cells between the input lists. The second argument is
now declared "const List *" to reflect that it isn't changed.
This patch just does the minimum needed to get the new implementation
in place and fix bugs exposed by the regression tests. As suggested
by the foregoing, there's a fair amount of followup work remaining to
do.
Also, the ENABLE_LIST_COMPAT macros are finally removed in this
commit. Code using those should have been gone a dozen years ago.
Patch by me; thanks to David Rowley, Jesper Pedersen, and others
for review.
Discussion: https://postgr.es/m/11587.1550975080@sss.pgh.pa.us
2019-07-15 19:41:58 +02:00
|
|
|
alist_item = lnext(stmt->aliases, alist_item);
|
2007-03-13 01:33:44 +01:00
|
|
|
if (alist_item == NULL)
|
|
|
|
break; /* done assigning aliases */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (alist_item != NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("CREATE VIEW specifies more column "
|
|
|
|
"names than columns")));
|
|
|
|
}
|
2002-03-22 03:56:37 +01:00
|
|
|
|
Fix bugs in relpersistence handling during table creation.
Unlike the relistemp field which it replaced, relpersistence must be
set correctly quite early during the table creation process, as we
rely on it quite early on for a number of purposes, including security
checks. Normally, this is set based on whether the user enters CREATE
TABLE, CREATE UNLOGGED TABLE, or CREATE TEMPORARY TABLE, but a
relation may also be made implicitly temporary by creating it in
pg_temp. This patch fixes the handling of that case, and also
disables creation of unlogged tables in temporary tablespace (such
table indeed skip WAL-logging, but we reject an explicit
specification) and creation of relations in the temporary schemas of
other sessions (which is not very sensible, and didn't work right
anyway).
Report by Amit Khandekar.
2011-07-03 23:34:47 +02:00
|
|
|
/* Unlogged views are not sensible. */
|
|
|
|
if (stmt->view->relpersistence == RELPERSISTENCE_UNLOGGED)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errmsg("views cannot be unlogged because they do not have storage")));
|
Fix bugs in relpersistence handling during table creation.
Unlike the relistemp field which it replaced, relpersistence must be
set correctly quite early during the table creation process, as we
rely on it quite early on for a number of purposes, including security
checks. Normally, this is set based on whether the user enters CREATE
TABLE, CREATE UNLOGGED TABLE, or CREATE TEMPORARY TABLE, but a
relation may also be made implicitly temporary by creating it in
pg_temp. This patch fixes the handling of that case, and also
disables creation of unlogged tables in temporary tablespace (such
table indeed skip WAL-logging, but we reject an explicit
specification) and creation of relations in the temporary schemas of
other sessions (which is not very sensible, and didn't work right
anyway).
Report by Amit Khandekar.
2011-07-03 23:34:47 +02:00
|
|
|
|
2005-02-02 07:36:02 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If the user didn't explicitly ask for a temporary view, check whether
|
2014-05-06 18:12:18 +02:00
|
|
|
* we need one implicitly. We allow TEMP to be inserted automatically as
|
2007-11-15 22:14:46 +01:00
|
|
|
* long as the CREATE command is consistent with that --- no explicit
|
2007-08-27 05:36:08 +02:00
|
|
|
* schema name.
|
2005-02-02 07:36:02 +01:00
|
|
|
*/
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
view = copyObject(stmt->view); /* don't corrupt original command */
|
2010-12-13 18:34:26 +01:00
|
|
|
if (view->relpersistence == RELPERSISTENCE_PERMANENT
|
2013-03-04 01:23:31 +01:00
|
|
|
&& isQueryUsingTempRelation(viewParse))
|
2005-02-02 07:36:02 +01:00
|
|
|
{
|
2010-12-13 18:34:26 +01:00
|
|
|
view->relpersistence = RELPERSISTENCE_TEMP;
|
2007-03-13 01:33:44 +01:00
|
|
|
ereport(NOTICE,
|
|
|
|
(errmsg("view \"%s\" will be a temporary view",
|
|
|
|
view->relname)));
|
2005-02-02 07:36:02 +01:00
|
|
|
}
|
2005-10-15 04:49:52 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
2002-03-22 03:56:37 +01:00
|
|
|
* Create the view relation
|
|
|
|
*
|
2005-11-22 19:17:34 +01:00
|
|
|
* NOTE: if it already exists and replace is false, the xact will be
|
|
|
|
* aborted.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
address = DefineVirtualRelation(view, viewParse->targetList,
|
2016-12-21 17:58:18 +01:00
|
|
|
stmt->replace, stmt->options, viewParse);
|
2013-03-04 01:23:31 +01:00
|
|
|
|
Change many routines to return ObjectAddress rather than OID
The changed routines are mostly those that can be directly called by
ProcessUtilitySlow; the intention is to make the affected object
information more precise, in support for future event trigger changes.
Originally it was envisioned that the OID of the affected object would
be enough, and in most cases that is correct, but upon actually
implementing the event trigger changes it turned out that ObjectAddress
is more widely useful.
Additionally, some command execution routines grew an output argument
that's an object address which provides further info about the executed
command. To wit:
* for ALTER DOMAIN / ADD CONSTRAINT, it corresponds to the address of
the new constraint
* for ALTER OBJECT / SET SCHEMA, it corresponds to the address of the
schema that originally contained the object.
* for ALTER EXTENSION {ADD, DROP} OBJECT, it corresponds to the address
of the object added to or dropped from the extension.
There's no user-visible change in this commit, and no functional change
either.
Discussion: 20150218213255.GC6717@tamriel.snowman.net
Reviewed-By: Stephen Frost, Andres Freund
2015-03-03 18:10:50 +01:00
|
|
|
return address;
|
2013-03-04 01:23:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Use the rules system to store the query for the view.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
StoreViewQuery(Oid viewOid, Query *viewParse, bool replace)
|
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* The range table of 'viewParse' does not contain entries for the "OLD"
|
|
|
|
* and "NEW" relations. So... add them!
|
2000-12-21 18:36:15 +01:00
|
|
|
*/
|
2002-03-22 03:56:37 +01:00
|
|
|
viewParse = UpdateRangeTableOfViewParse(viewOid, viewParse);
|
2000-12-21 18:36:15 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now create the rules associated with the view.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2013-03-04 01:23:31 +01:00
|
|
|
DefineViewRules(viewOid, viewParse, replace);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|