diff --git a/doc/src/sgml/ref/alter_sequence.sgml b/doc/src/sgml/ref/alter_sequence.sgml index 7cf69e9ea3..739f3ec0f8 100644 --- a/doc/src/sgml/ref/alter_sequence.sgml +++ b/doc/src/sgml/ref/alter_sequence.sgml @@ -1,5 +1,5 @@ @@ -30,6 +30,7 @@ ALTER SEQUENCE name [ INCREMENT [ B [ RESTART [ [ WITH ] restart ] ] [ CACHE cache ] [ [ NO ] CYCLE ] [ OWNED BY { table.column | NONE } ] +ALTER SEQUENCE name OWNER TO new_owner ALTER SEQUENCE name RENAME TO new_name ALTER SEQUENCE name SET SCHEMA new_schema @@ -48,6 +49,11 @@ ALTER SEQUENCE name SET SCHEMA ALTER SEQUENCE. To change a sequence's schema, you must also have CREATE privilege on the new schema. + To alter the owner, you must also be a direct or indirect member of the new + owning role, and that role must have CREATE privilege on + the sequence's schema. (These restrictions enforce that altering the owner + doesn't do anything you couldn't do by dropping and recreating the sequence. + However, a superuser can alter ownership of any sequence anyway.) @@ -205,6 +211,15 @@ ALTER SEQUENCE name SET SCHEMA + + new_owner + + + The user name of the new owner of the sequence. + + + + new_name @@ -233,9 +248,9 @@ ALTER SEQUENCE name SET SCHEMA To avoid blocking of concurrent transactions that obtain numbers from the same sequence, ALTER SEQUENCE's effects on the sequence - generation parameters are never rolled back; - those changes take effect immediately and are not reversible. However, - the OWNED BY, RENAME, and SET SCHEMA + generation parameters are never rolled back; those changes take effect + immediately and are not reversible. However, the OWNED BY, + OWNER TO, RENAME TO, and SET SCHEMA clauses cause ordinary catalog updates that can be rolled back. @@ -255,9 +270,9 @@ ALTER SEQUENCE name SET SCHEMA - Some variants of ALTER TABLE can be used with - sequences as well; for example, to rename a sequence it is also - possible to use ALTER TABLE RENAME. + For historical reasons, ALTER TABLE can be used with + sequences too; but the only variants of ALTER TABLE + that are allowed with sequences are equivalent to the forms shown above. @@ -278,7 +293,7 @@ ALTER SEQUENCE serial RESTART WITH 105; ALTER SEQUENCE conforms to the SQL standard, except for the START WITH, - OWNED BY, RENAME, and + OWNED BY, OWNER TO, RENAME TO, and SET SCHEMA clauses, which are PostgreSQL extensions. diff --git a/doc/src/sgml/ref/alter_view.sgml b/doc/src/sgml/ref/alter_view.sgml index 7dd052cc12..4c3d9a2479 100644 --- a/doc/src/sgml/ref/alter_view.sgml +++ b/doc/src/sgml/ref/alter_view.sgml @@ -1,5 +1,5 @@ @@ -20,7 +20,11 @@ PostgreSQL documentation -ALTER VIEW name RENAME TO newname +ALTER VIEW name ALTER [ COLUMN ] column SET DEFAULT expression +ALTER VIEW name ALTER [ COLUMN ] column DROP DEFAULT +ALTER VIEW name OWNER TO new_owner +ALTER VIEW name RENAME TO new_name +ALTER VIEW name SET SCHEMA new_schema @@ -28,9 +32,20 @@ ALTER VIEW name RENAME TO newnameDescription - ALTER VIEW changes the definition of a view. - The only currently available functionality is to rename the view. - To execute this command you must be the owner of the view. + ALTER VIEW changes various auxiliary properties + of a view. (If you want to modify the view's defining query, + use CREATE OR REPLACE VIEW.) + + + + You must own the view to use ALTER VIEW. + To change a view's schema, you must also have CREATE + privilege on the new schema. + To alter the owner, you must also be a direct or indirect member of the new + owning role, and that role must have CREATE privilege on + the view's schema. (These restrictions enforce that altering the owner + doesn't do anything you couldn't do by dropping and recreating the view. + However, a superuser can alter ownership of any view anyway.) @@ -48,10 +63,41 @@ ALTER VIEW name RENAME TO newname - newname + SET/DROP DEFAULT - The new name of the view. + These forms set or remove the default value for a column. + A default value associated with a view column is + inserted into INSERT statements on the view before + the view's ON INSERT rule is applied, if + the INSERT does not specify a value for the column. + + + + + + new_owner + + + The user name of the new owner of the view. + + + + + + new_name + + + The new name for the view. + + + + + + new_schema + + + The new schema for the view. @@ -62,11 +108,9 @@ ALTER VIEW name RENAME TO newnameNotes - Some variants of ALTER TABLE can be used with - views as well; for example, to rename a view it is also - possible to use ALTER TABLE RENAME. To change - the schema or owner of a view, you currently must use ALTER - TABLE. + For historical reasons, ALTER TABLE can be used with + views too; but the only variants of ALTER TABLE + that are allowed with views are equivalent to the ones shown above. diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 63acefa527..fce328bcc4 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.28 2008/03/19 18:38:30 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.29 2008/06/15 01:25:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -185,8 +185,10 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) case OBJECT_SEQUENCE: case OBJECT_TABLE: + case OBJECT_VIEW: CheckRelationOwnership(stmt->relation, true); - AlterTableNamespace(stmt->relation, stmt->newschema); + AlterTableNamespace(stmt->relation, stmt->newschema, + stmt->objectType); break; case OBJECT_TYPE: diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 7f7102858b..b3d21875b2 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.256 2008/06/14 18:04:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.257 2008/06/15 01:25:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2175,6 +2175,44 @@ AlterTable(AlterTableStmt *stmt) CheckTableNotInUse(rel, "ALTER TABLE"); + /* Check relation type against type specified in the ALTER command */ + switch (stmt->relkind) + { + case OBJECT_TABLE: + /* + * For mostly-historical reasons, we allow ALTER TABLE to apply + * to all relation types. + */ + break; + + case OBJECT_INDEX: + if (rel->rd_rel->relkind != RELKIND_INDEX) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not an index", + RelationGetRelationName(rel)))); + break; + + case OBJECT_SEQUENCE: + if (rel->rd_rel->relkind != RELKIND_SEQUENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a sequence", + RelationGetRelationName(rel)))); + break; + + case OBJECT_VIEW: + if (rel->rd_rel->relkind != RELKIND_VIEW) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a view", + RelationGetRelationName(rel)))); + break; + + default: + elog(ERROR, "unrecognized object type: %d", (int) stmt->relkind); + } + ATController(rel, stmt->cmds, interpretInhOption(stmt->relation->inhOpt)); } @@ -7191,7 +7229,8 @@ ATExecDropInherit(Relation rel, RangeVar *parent) * Note: caller must have checked ownership of the relation already */ void -AlterTableNamespace(RangeVar *relation, const char *newschema) +AlterTableNamespace(RangeVar *relation, const char *newschema, + ObjectType stmttype) { Relation rel; Oid relid; @@ -7204,6 +7243,36 @@ AlterTableNamespace(RangeVar *relation, const char *newschema) relid = RelationGetRelid(rel); oldNspOid = RelationGetNamespace(rel); + /* Check relation type against type specified in the ALTER command */ + switch (stmttype) + { + case OBJECT_TABLE: + /* + * For mostly-historical reasons, we allow ALTER TABLE to apply + * to all relation types. + */ + break; + + case OBJECT_SEQUENCE: + if (rel->rd_rel->relkind != RELKIND_SEQUENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a sequence", + RelationGetRelationName(rel)))); + break; + + case OBJECT_VIEW: + if (rel->rd_rel->relkind != RELKIND_VIEW) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a view", + RelationGetRelationName(rel)))); + break; + + default: + elog(ERROR, "unrecognized object type: %d", (int) stmttype); + } + /* Can we change the schema of this tuple? */ switch (rel->rd_rel->relkind) { diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 591920d6f6..4e59e37da9 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.615 2008/05/16 23:36:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.616 2008/06/15 01:25:54 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -185,8 +185,8 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) %type alter_column_default opclass_item opclass_drop alter_using %type add_drop opt_asc_desc opt_nulls_order -%type alter_table_cmd alter_rel_cmd -%type alter_table_cmds alter_rel_cmds +%type alter_table_cmd +%type alter_table_cmds %type opt_drop_behavior @@ -291,8 +291,8 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) %type fetch_direction select_limit_value select_offset_value -%type OptSeqList -%type OptSeqElem +%type OptSeqOptList SeqOptList +%type SeqOptElem %type insert_rest @@ -1391,8 +1391,10 @@ DiscardStmt: /***************************************************************************** * - * ALTER [ TABLE | INDEX ] variations + * ALTER [ TABLE | INDEX | SEQUENCE | VIEW ] variations * + * Note: we accept all subcommands for each of the four variants, and sort + * out what's really legal at execution time. *****************************************************************************/ AlterTableStmt: @@ -1404,7 +1406,7 @@ AlterTableStmt: n->relkind = OBJECT_TABLE; $$ = (Node *)n; } - | ALTER INDEX relation_expr alter_rel_cmds + | ALTER INDEX relation_expr alter_table_cmds { AlterTableStmt *n = makeNode(AlterTableStmt); n->relation = $3; @@ -1412,6 +1414,22 @@ AlterTableStmt: n->relkind = OBJECT_INDEX; $$ = (Node *)n; } + | ALTER SEQUENCE relation_expr alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = $4; + n->relkind = OBJECT_SEQUENCE; + $$ = (Node *)n; + } + | ALTER VIEW relation_expr alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = $4; + n->relkind = OBJECT_VIEW; + $$ = (Node *)n; + } ; alter_table_cmds: @@ -1419,9 +1437,8 @@ alter_table_cmds: | alter_table_cmds ',' alter_table_cmd { $$ = lappend($1, $3); } ; -/* Subcommands that are for ALTER TABLE only */ alter_table_cmd: - /* ALTER TABLE ADD [COLUMN] */ + /* ALTER TABLE ADD [COLUMN] */ ADD_P opt_column columnDef { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1429,7 +1446,7 @@ alter_table_cmd: n->def = $3; $$ = (Node *)n; } - /* ALTER TABLE ALTER [COLUMN] {SET DEFAULT |DROP DEFAULT} */ + /* ALTER TABLE ALTER [COLUMN] {SET DEFAULT |DROP DEFAULT} */ | ALTER opt_column ColId alter_column_default { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1438,7 +1455,7 @@ alter_table_cmd: n->def = $4; $$ = (Node *)n; } - /* ALTER TABLE ALTER [COLUMN] DROP NOT NULL */ + /* ALTER TABLE ALTER [COLUMN] DROP NOT NULL */ | ALTER opt_column ColId DROP NOT NULL_P { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1446,7 +1463,7 @@ alter_table_cmd: n->name = $3; $$ = (Node *)n; } - /* ALTER TABLE ALTER [COLUMN] SET NOT NULL */ + /* ALTER TABLE ALTER [COLUMN] SET NOT NULL */ | ALTER opt_column ColId SET NOT NULL_P { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1454,7 +1471,7 @@ alter_table_cmd: n->name = $3; $$ = (Node *)n; } - /* ALTER TABLE ALTER [COLUMN] SET STATISTICS */ + /* ALTER TABLE ALTER [COLUMN] SET STATISTICS */ | ALTER opt_column ColId SET STATISTICS IntegerOnly { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1463,7 +1480,7 @@ alter_table_cmd: n->def = (Node *) $6; $$ = (Node *)n; } - /* ALTER TABLE ALTER [COLUMN] SET STORAGE */ + /* ALTER TABLE ALTER [COLUMN] SET STORAGE */ | ALTER opt_column ColId SET STORAGE ColId { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1472,7 +1489,7 @@ alter_table_cmd: n->def = (Node *) makeString($6); $$ = (Node *)n; } - /* ALTER TABLE DROP [COLUMN] [RESTRICT|CASCADE] */ + /* ALTER TABLE DROP [COLUMN] [RESTRICT|CASCADE] */ | DROP opt_column ColId opt_drop_behavior { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1482,7 +1499,7 @@ alter_table_cmd: $$ = (Node *)n; } /* - * ALTER TABLE ALTER [COLUMN] TYPE + * ALTER TABLE ALTER [COLUMN] TYPE * [ USING ] */ | ALTER opt_column ColId TYPE_P Typename alter_using @@ -1494,7 +1511,7 @@ alter_table_cmd: n->transform = $6; $$ = (Node *)n; } - /* ALTER TABLE ADD CONSTRAINT ... */ + /* ALTER TABLE ADD CONSTRAINT ... */ | ADD_P TableConstraint { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1502,7 +1519,7 @@ alter_table_cmd: n->def = $2; $$ = (Node *)n; } - /* ALTER TABLE DROP CONSTRAINT [RESTRICT|CASCADE] */ + /* ALTER TABLE DROP CONSTRAINT [RESTRICT|CASCADE] */ | DROP CONSTRAINT name opt_drop_behavior { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1511,7 +1528,7 @@ alter_table_cmd: n->behavior = $4; $$ = (Node *)n; } - /* ALTER TABLE SET WITHOUT OIDS */ + /* ALTER TABLE SET WITHOUT OIDS */ | SET WITHOUT OIDS { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1642,28 +1659,15 @@ alter_table_cmd: n->def = (Node *) $3; $$ = (Node *)n; } - | alter_rel_cmd - { - $$ = $1; - } - ; - -alter_rel_cmds: - alter_rel_cmd { $$ = list_make1($1); } - | alter_rel_cmds ',' alter_rel_cmd { $$ = lappend($1, $3); } - ; - -/* Subcommands that are for ALTER TABLE or ALTER INDEX */ -alter_rel_cmd: - /* ALTER [TABLE|INDEX] OWNER TO RoleId */ - OWNER TO RoleId + /* ALTER TABLE OWNER TO RoleId */ + | OWNER TO RoleId { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_ChangeOwner; n->name = $3; $$ = (Node *)n; } - /* ALTER [TABLE|INDEX] SET TABLESPACE */ + /* ALTER TABLE SET TABLESPACE */ | SET TABLESPACE name { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1671,7 +1675,7 @@ alter_rel_cmd: n->name = $3; $$ = (Node *)n; } - /* ALTER [TABLE|INDEX] SET (...) */ + /* ALTER TABLE SET (...) */ | SET definition { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -1679,7 +1683,7 @@ alter_rel_cmd: n->def = (Node *)$2; $$ = (Node *)n; } - /* ALTER [TABLE|INDEX] RESET (...) */ + /* ALTER TABLE RESET (...) */ | RESET definition { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -2425,7 +2429,7 @@ CreateAsElement: *****************************************************************************/ CreateSeqStmt: - CREATE OptTemp SEQUENCE qualified_name OptSeqList + CREATE OptTemp SEQUENCE qualified_name OptSeqOptList { CreateSeqStmt *n = makeNode(CreateSeqStmt); $4->istemp = $2; @@ -2436,7 +2440,7 @@ CreateSeqStmt: ; AlterSeqStmt: - ALTER SEQUENCE qualified_name OptSeqList + ALTER SEQUENCE relation_expr SeqOptList { AlterSeqStmt *n = makeNode(AlterSeqStmt); n->sequence = $3; @@ -2445,11 +2449,15 @@ AlterSeqStmt: } ; -OptSeqList: OptSeqList OptSeqElem { $$ = lappend($1, $2); } +OptSeqOptList: SeqOptList { $$ = $1; } | /*EMPTY*/ { $$ = NIL; } ; -OptSeqElem: CACHE NumericOnly +SeqOptList: SeqOptElem { $$ = list_make1($1); } + | SeqOptList SeqOptElem { $$ = lappend($1, $2); } + ; + +SeqOptElem: CACHE NumericOnly { $$ = makeDefElem("cache", (Node *)$2); } @@ -4802,6 +4810,14 @@ AlterObjectSchemaStmt: n->newschema = $6; $$ = (Node *)n; } + | ALTER TABLE relation_expr SET SCHEMA name + { + AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); + n->objectType = OBJECT_TABLE; + n->relation = $3; + n->newschema = $6; + $$ = (Node *)n; + } | ALTER SEQUENCE relation_expr SET SCHEMA name { AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); @@ -4810,10 +4826,10 @@ AlterObjectSchemaStmt: n->newschema = $6; $$ = (Node *)n; } - | ALTER TABLE relation_expr SET SCHEMA name + | ALTER VIEW relation_expr SET SCHEMA name { AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); - n->objectType = OBJECT_TABLE; + n->objectType = OBJECT_VIEW; n->relation = $3; n->newschema = $6; $$ = (Node *)n; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 6c839650b4..1922ffc960 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.293 2008/06/14 18:04:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.294 2008/06/15 01:25:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1454,6 +1454,9 @@ CreateCommandTag(Node *parsetree) case OBJECT_TSCONFIGURATION: tag = "ALTER TEXT SEARCH CONFIGURATION"; break; + case OBJECT_VIEW: + tag = "ALTER VIEW"; + break; default: tag = "???"; break; @@ -1512,19 +1515,23 @@ CreateCommandTag(Node *parsetree) break; case T_AlterTableStmt: + switch (((AlterTableStmt *) parsetree)->relkind) { - AlterTableStmt *stmt = (AlterTableStmt *) parsetree; - - /* - * We might be supporting ALTER INDEX here, so set the - * completion tag appropriately. Catch all other possibilities - * with ALTER TABLE - */ - - if (stmt->relkind == OBJECT_INDEX) - tag = "ALTER INDEX"; - else + case OBJECT_TABLE: tag = "ALTER TABLE"; + break; + case OBJECT_INDEX: + tag = "ALTER INDEX"; + break; + case OBJECT_SEQUENCE: + tag = "ALTER SEQUENCE"; + break; + case OBJECT_VIEW: + tag = "ALTER VIEW"; + break; + default: + tag = "???"; + break; } break; diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index cdb8024016..d9e1a56372 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.39 2008/06/14 18:04:34 tgl Exp $ + * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.40 2008/06/15 01:25:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,7 +28,8 @@ extern void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing); extern void AlterTableInternal(Oid relid, List *cmds, bool recurse); -extern void AlterTableNamespace(RangeVar *relation, const char *newschema); +extern void AlterTableNamespace(RangeVar *relation, const char *newschema, + ObjectType stmttype); extern void AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid,