mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
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.
278 lines
6.6 KiB
C
278 lines
6.6 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* alter.c
|
|
* Drivers for generic alter commands
|
|
*
|
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.29 2008/06/15 01:25:53 tgl Exp $
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#include "postgres.h"
|
|
|
|
#include "catalog/namespace.h"
|
|
#include "commands/alter.h"
|
|
#include "commands/conversioncmds.h"
|
|
#include "commands/dbcommands.h"
|
|
#include "commands/defrem.h"
|
|
#include "commands/proclang.h"
|
|
#include "commands/schemacmds.h"
|
|
#include "commands/tablecmds.h"
|
|
#include "commands/tablespace.h"
|
|
#include "commands/trigger.h"
|
|
#include "commands/typecmds.h"
|
|
#include "commands/user.h"
|
|
#include "miscadmin.h"
|
|
#include "parser/parse_clause.h"
|
|
#include "tcop/utility.h"
|
|
#include "utils/acl.h"
|
|
#include "utils/lsyscache.h"
|
|
|
|
|
|
/*
|
|
* Executes an ALTER OBJECT / RENAME TO statement. Based on the object
|
|
* type, the function appropriate to that type is executed.
|
|
*/
|
|
void
|
|
ExecRenameStmt(RenameStmt *stmt)
|
|
{
|
|
switch (stmt->renameType)
|
|
{
|
|
case OBJECT_AGGREGATE:
|
|
RenameAggregate(stmt->object, stmt->objarg, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_CONVERSION:
|
|
RenameConversion(stmt->object, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_DATABASE:
|
|
RenameDatabase(stmt->subname, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_FUNCTION:
|
|
RenameFunction(stmt->object, stmt->objarg, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_LANGUAGE:
|
|
RenameLanguage(stmt->subname, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_OPCLASS:
|
|
RenameOpClass(stmt->object, stmt->subname, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_OPFAMILY:
|
|
RenameOpFamily(stmt->object, stmt->subname, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_ROLE:
|
|
RenameRole(stmt->subname, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_SCHEMA:
|
|
RenameSchema(stmt->subname, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_TABLESPACE:
|
|
RenameTableSpace(stmt->subname, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_TABLE:
|
|
case OBJECT_SEQUENCE:
|
|
case OBJECT_VIEW:
|
|
case OBJECT_INDEX:
|
|
case OBJECT_COLUMN:
|
|
case OBJECT_TRIGGER:
|
|
{
|
|
Oid relid;
|
|
|
|
CheckRelationOwnership(stmt->relation, true);
|
|
|
|
relid = RangeVarGetRelid(stmt->relation, false);
|
|
|
|
switch (stmt->renameType)
|
|
{
|
|
case OBJECT_TABLE:
|
|
case OBJECT_SEQUENCE:
|
|
case OBJECT_VIEW:
|
|
case OBJECT_INDEX:
|
|
{
|
|
/*
|
|
* RENAME TABLE requires that we (still) hold
|
|
* CREATE rights on the containing namespace, as
|
|
* well as ownership of the table.
|
|
*/
|
|
Oid namespaceId = get_rel_namespace(relid);
|
|
AclResult aclresult;
|
|
|
|
aclresult = pg_namespace_aclcheck(namespaceId,
|
|
GetUserId(),
|
|
ACL_CREATE);
|
|
if (aclresult != ACLCHECK_OK)
|
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
|
get_namespace_name(namespaceId));
|
|
|
|
RenameRelation(relid, stmt->newname, stmt->renameType);
|
|
break;
|
|
}
|
|
case OBJECT_COLUMN:
|
|
renameatt(relid,
|
|
stmt->subname, /* old att name */
|
|
stmt->newname, /* new att name */
|
|
interpretInhOption(stmt->relation->inhOpt), /* recursive? */
|
|
false); /* recursing already? */
|
|
break;
|
|
case OBJECT_TRIGGER:
|
|
renametrig(relid,
|
|
stmt->subname, /* old att name */
|
|
stmt->newname); /* new att name */
|
|
break;
|
|
default:
|
|
/* can't happen */ ;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case OBJECT_TSPARSER:
|
|
RenameTSParser(stmt->object, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_TSDICTIONARY:
|
|
RenameTSDictionary(stmt->object, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_TSTEMPLATE:
|
|
RenameTSTemplate(stmt->object, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_TSCONFIGURATION:
|
|
RenameTSConfiguration(stmt->object, stmt->newname);
|
|
break;
|
|
|
|
case OBJECT_TYPE:
|
|
RenameType(stmt->object, stmt->newname);
|
|
break;
|
|
|
|
default:
|
|
elog(ERROR, "unrecognized rename stmt type: %d",
|
|
(int) stmt->renameType);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Executes an ALTER OBJECT / SET SCHEMA statement. Based on the object
|
|
* type, the function appropriate to that type is executed.
|
|
*/
|
|
void
|
|
ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
|
|
{
|
|
switch (stmt->objectType)
|
|
{
|
|
case OBJECT_AGGREGATE:
|
|
AlterFunctionNamespace(stmt->object, stmt->objarg, true,
|
|
stmt->newschema);
|
|
break;
|
|
|
|
case OBJECT_FUNCTION:
|
|
AlterFunctionNamespace(stmt->object, stmt->objarg, false,
|
|
stmt->newschema);
|
|
break;
|
|
|
|
case OBJECT_SEQUENCE:
|
|
case OBJECT_TABLE:
|
|
case OBJECT_VIEW:
|
|
CheckRelationOwnership(stmt->relation, true);
|
|
AlterTableNamespace(stmt->relation, stmt->newschema,
|
|
stmt->objectType);
|
|
break;
|
|
|
|
case OBJECT_TYPE:
|
|
case OBJECT_DOMAIN:
|
|
AlterTypeNamespace(stmt->object, stmt->newschema);
|
|
break;
|
|
|
|
default:
|
|
elog(ERROR, "unrecognized AlterObjectSchemaStmt type: %d",
|
|
(int) stmt->objectType);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Executes an ALTER OBJECT / OWNER TO statement. Based on the object
|
|
* type, the function appropriate to that type is executed.
|
|
*/
|
|
void
|
|
ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
|
|
{
|
|
Oid newowner = get_roleid_checked(stmt->newowner);
|
|
|
|
switch (stmt->objectType)
|
|
{
|
|
case OBJECT_AGGREGATE:
|
|
AlterAggregateOwner(stmt->object, stmt->objarg, newowner);
|
|
break;
|
|
|
|
case OBJECT_CONVERSION:
|
|
AlterConversionOwner(stmt->object, newowner);
|
|
break;
|
|
|
|
case OBJECT_DATABASE:
|
|
AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner);
|
|
break;
|
|
|
|
case OBJECT_FUNCTION:
|
|
AlterFunctionOwner(stmt->object, stmt->objarg, newowner);
|
|
break;
|
|
|
|
case OBJECT_LANGUAGE:
|
|
AlterLanguageOwner(strVal(linitial(stmt->object)), newowner);
|
|
break;
|
|
|
|
case OBJECT_OPERATOR:
|
|
Assert(list_length(stmt->objarg) == 2);
|
|
AlterOperatorOwner(stmt->object,
|
|
(TypeName *) linitial(stmt->objarg),
|
|
(TypeName *) lsecond(stmt->objarg),
|
|
newowner);
|
|
break;
|
|
|
|
case OBJECT_OPCLASS:
|
|
AlterOpClassOwner(stmt->object, stmt->addname, newowner);
|
|
break;
|
|
|
|
case OBJECT_OPFAMILY:
|
|
AlterOpFamilyOwner(stmt->object, stmt->addname, newowner);
|
|
break;
|
|
|
|
case OBJECT_SCHEMA:
|
|
AlterSchemaOwner(strVal(linitial(stmt->object)), newowner);
|
|
break;
|
|
|
|
case OBJECT_TABLESPACE:
|
|
AlterTableSpaceOwner(strVal(linitial(stmt->object)), newowner);
|
|
break;
|
|
|
|
case OBJECT_TYPE:
|
|
case OBJECT_DOMAIN: /* same as TYPE */
|
|
AlterTypeOwner(stmt->object, newowner);
|
|
break;
|
|
|
|
case OBJECT_TSDICTIONARY:
|
|
AlterTSDictionaryOwner(stmt->object, newowner);
|
|
break;
|
|
|
|
case OBJECT_TSCONFIGURATION:
|
|
AlterTSConfigurationOwner(stmt->object, newowner);
|
|
break;
|
|
|
|
default:
|
|
elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
|
|
(int) stmt->objectType);
|
|
}
|
|
}
|