From: Tom Lane Date: Sun, 15 Jun 2008 01:25:54 +0000 (+0000) Subject: Rearrange ALTER TABLE syntax processing as per my recent proposal: the X-Git-Tag: REL8_4_BETA1~1282 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a0b012a1ab85ae115f30e5e4fe09922b4885fdad;p=postgresql Rearrange ALTER TABLE syntax processing as per my recent proposal: the grammar allows ALTER TABLE/INDEX/SEQUENCE/VIEW interchangeably for all subforms of those commands, and then we sort out what's really legal at execution time. This allows the ALTER SEQUENCE/VIEW reference pages to fully document all the ALTER forms available for sequences and views respectively, and eliminates a longstanding cause of confusion for users. The net effect is that the following forms are allowed that weren't before: ALTER SEQUENCE OWNER TO ALTER VIEW ALTER COLUMN SET/DROP DEFAULT ALTER VIEW OWNER TO ALTER VIEW SET SCHEMA (There's no actual functionality gain here, but formerly you had to say ALTER TABLE instead.) Interestingly, the grammar tables actually get smaller, probably because there are fewer special cases to keep track of. I did not disallow using ALTER TABLE for these operations. Perhaps we should, but there's a backwards-compatibility issue if we do; in fact it would break existing pg_dump scripts. I did however tighten up ALTER SEQUENCE and ALTER VIEW to reject non-sequences and non-views in the new cases as well as a couple of cases where they didn't before. The patch doesn't change pg_dump to use the new syntaxes, either. --- 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 + + + 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 name of the view. + 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,