From b256f2426433c56b4bea3a8102757749885b81ba Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 27 Jun 2003 14:45:32 +0000 Subject: [PATCH] First batch of object rename commands. --- doc/src/sgml/ref/allfiles.sgml | 39 +----- doc/src/sgml/ref/alter_aggregate.sgml | 128 ++++++++++++++++++ doc/src/sgml/ref/alter_conversion.sgml | 117 ++++++++++++++++ doc/src/sgml/ref/alter_database.sgml | 42 ++++-- doc/src/sgml/ref/alter_function.sgml | 127 +++++++++++++++++ doc/src/sgml/ref/alter_group.sgml | 39 ++++-- doc/src/sgml/ref/alter_language.sgml | 107 +++++++++++++++ doc/src/sgml/ref/alter_opclass.sgml | 116 ++++++++++++++++ doc/src/sgml/ref/alter_schema.sgml | 108 +++++++++++++++ doc/src/sgml/ref/alter_user.sgml | 21 ++- doc/src/sgml/ref/create_aggregate.sgml | 19 +-- doc/src/sgml/ref/create_conversion.sgml | 11 +- doc/src/sgml/ref/create_function.sgml | 3 +- doc/src/sgml/ref/create_language.sgml | 21 ++- doc/src/sgml/ref/create_opclass.sgml | 21 ++- doc/src/sgml/ref/create_schema.sgml | 16 ++- doc/src/sgml/ref/drop_aggregate.sgml | 3 +- doc/src/sgml/ref/drop_conversion.sgml | 3 +- doc/src/sgml/ref/drop_function.sgml | 3 +- doc/src/sgml/ref/drop_language.sgml | 4 +- doc/src/sgml/ref/drop_opclass.sgml | 3 +- doc/src/sgml/ref/drop_schema.sgml | 3 +- doc/src/sgml/reference.sgml | 8 +- src/backend/catalog/aclchk.c | 39 +++++- src/backend/catalog/namespace.c | 10 +- src/backend/commands/Makefile | 4 +- src/backend/commands/aggregatecmds.c | 75 +++++++++- src/backend/commands/alter.c | 159 ++++++++++++++++++++++ src/backend/commands/analyze.c | 4 +- src/backend/commands/comment.c | 40 +++--- src/backend/commands/conversioncmds.c | 62 ++++++++- src/backend/commands/dbcommands.c | 157 ++++++++++++++++----- src/backend/commands/functioncmds.c | 68 +++++++++- src/backend/commands/indexcmds.c | 7 +- src/backend/commands/opclasscmds.c | 95 ++++++++++++- src/backend/commands/proclang.c | 46 ++++++- src/backend/commands/schemacmds.c | 60 +++++++- src/backend/commands/user.c | 108 ++++++++++++++- src/backend/commands/vacuum.c | 4 +- src/backend/nodes/copyfuncs.c | 6 +- src/backend/nodes/equalfuncs.c | 6 +- src/backend/parser/gram.y | 164 ++++++++++++++++------ src/backend/parser/parse_expr.c | 4 +- src/backend/parser/parse_target.c | 4 +- src/backend/tcop/utility.c | 173 +++++++++++------------- src/backend/utils/adt/misc.c | 5 +- src/backend/utils/init/globals.c | 4 +- src/backend/utils/init/miscinit.c | 18 +-- src/backend/utils/init/postinit.c | 6 +- src/backend/utils/misc/superuser.c | 17 +-- src/include/commands/alter.h | 21 +++ src/include/commands/conversioncmds.h | 3 +- src/include/commands/dbcommands.h | 7 +- src/include/commands/defrem.h | 6 +- src/include/commands/proclang.h | 1 + src/include/commands/schemacmds.h | 4 +- src/include/commands/user.h | 4 +- src/include/miscadmin.h | 6 +- src/include/nodes/parsenodes.h | 98 ++++++-------- src/include/utils/acl.h | 3 +- 60 files changed, 2018 insertions(+), 442 deletions(-) create mode 100644 doc/src/sgml/ref/alter_aggregate.sgml create mode 100644 doc/src/sgml/ref/alter_conversion.sgml create mode 100644 doc/src/sgml/ref/alter_function.sgml create mode 100644 doc/src/sgml/ref/alter_language.sgml create mode 100644 doc/src/sgml/ref/alter_opclass.sgml create mode 100644 doc/src/sgml/ref/alter_schema.sgml create mode 100644 src/backend/commands/alter.c create mode 100644 src/include/commands/alter.h diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml index a922e933e1..b40f82246e 100644 --- a/doc/src/sgml/ref/allfiles.sgml +++ b/doc/src/sgml/ref/allfiles.sgml @@ -1,45 +1,20 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/doc/src/sgml/ref/alter_aggregate.sgml b/doc/src/sgml/ref/alter_aggregate.sgml new file mode 100644 index 0000000000..972accd756 --- /dev/null +++ b/doc/src/sgml/ref/alter_aggregate.sgml @@ -0,0 +1,128 @@ + + + + + ALTER AGGREGATE + SQL - Language Statements + + + + ALTER AGGREGATE + change the definition of an aggregate function + + + + +ALTER AGGREGATE name ( type ) RENAME TO newname + + + + + Description + + + ALTER AGGREGATE changes the definition of an + aggregate function. The only functionality is to rename the + aggregate function. + + + + + Parameters + + + + name + + + The name (optionally schema-qualified) of an existing aggregate function. + + + + + + type + + + The argument data type of the aggregate function, or + * if the function accepts any data type. + + + + + + newname + + + The new name of the aggregate function. + + + + + + + + Diagnostics + + + + ALTER AGGREGATE + + + Message returned if the command was successful. + + + + + + + + Examples + + + To rename the aggregate function myavg for type + integer to my_average: + +ALTER AGGREGATE myavg(integer) RENAME TO my_average; + + + + + + Compatibility + + + There is no ALTER AGGREGATE statement in the SQL + standard. + + + + + See Also + + + + + + + + + diff --git a/doc/src/sgml/ref/alter_conversion.sgml b/doc/src/sgml/ref/alter_conversion.sgml new file mode 100644 index 0000000000..b2767405ca --- /dev/null +++ b/doc/src/sgml/ref/alter_conversion.sgml @@ -0,0 +1,117 @@ + + + + + ALTER CONVERSION + SQL - Language Statements + + + + ALTER CONVERSION + change the definition of a conversion + + + + +ALTER CONVERSION name RENAME TO newname + + + + + Description + + + ALTER CONVERSION changes the definition of a + conversion. The only functionality is to rename the conversion. + + + + + Parameters + + + + name + + + The name (optionally schema-qualified) of an existing conversion. + + + + + + newname + + + The new name of the conversion. + + + + + + + + Diagnostics + + + + ALTER CONVERSION + + + Message returned if the command was successful. + + + + + + + + Examples + + + To rename the conversion iso_8859_1_to_utf_8 to + latin1_to_unicode: + +ALTER CONVERSION iso_8859_1_to_utf_8 RENAME TO latin1_to_unicode; + + + + + + Compatibility + + + There is no ALTER CONVERSION statement in the SQL + standard. + + + + + See Also + + + + + + + + + diff --git a/doc/src/sgml/ref/alter_database.sgml b/doc/src/sgml/ref/alter_database.sgml index 326f784918..12447d6b0a 100644 --- a/doc/src/sgml/ref/alter_database.sgml +++ b/doc/src/sgml/ref/alter_database.sgml @@ -1,5 +1,5 @@ @@ -18,6 +18,8 @@ PostgreSQL documentation ALTER DATABASE name SET variable { TO | = } { value | DEFAULT } ALTER DATABASE name RESET variable + +ALTER DATABASE name RENAME TO newname @@ -25,20 +27,29 @@ ALTER DATABASE name RESET Description - ALTER DATABASE is used to change the session - default of a run-time configuration variable for a - PostgreSQL database. Whenever a new - session is subsequently started in that database, the specified - value becomes the session default value. - The database-specific default - overrides whatever setting is present in postgresql.conf - or has been received from the postmaster command line. + ALTER DATABASE is used to change the attributes + of a database. - Only the database owner or a superuser can change the session defaults for a + The first two forms change the session default of a run-time + configuration variable for a PostgreSQL + database. Whenever a new session is subsequently started in that + database, the specified value becomes the session default value. + The database-specific default overrides whatever setting is present + in postgresql.conf or has been received from the + postmaster command line. Only the database + owner or a superuser can change the session defaults for a database. + + + The third form changes the name of the database. Only the database + owner can rename a database, and only if he has the + CREATEDB privilege. The current database cannot + be renamed. (Connect to a different database if you need to do + that.) + @@ -76,7 +87,16 @@ ALTER DATABASE name RESET - + + + newname + + + The new name of the database. + + + + diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml new file mode 100644 index 0000000000..621350980b --- /dev/null +++ b/doc/src/sgml/ref/alter_function.sgml @@ -0,0 +1,127 @@ + + + + + ALTER FUNCTION + SQL - Language Statements + + + + ALTER FUNCTION + change the definition of a function + + + + +ALTER FUNCTION name ( [ type [, ...] ] ) RENAME TO newname + + + + + Description + + + ALTER FUNCTION changes the definition of a + function. The only functionality is to rename the function. + + + + + Parameters + + + + name + + + The name (optionally schema-qualified) of an existing function. + + + + + + type + + + The data type of an argument of the function. + + + + + + newname + + + The new name of the function. + + + + + + + + Diagnostics + + + + ALTER FUNCTION + + + Message returned if the command was successful. + + + + + + + + Examples + + + To rename the function sqrt for type + integer to square_root: + +ALTER FUNCTION sqrt(integer) RENAME TO square_root; + + + + + + Compatibility + + + There is an ALTER FUNCTION statement in the SQL + standard, but it does not provide the option to rename the + function. + + + + + See Also + + + + + + + + + diff --git a/doc/src/sgml/ref/alter_group.sgml b/doc/src/sgml/ref/alter_group.sgml index f036916a46..6d0695b938 100644 --- a/doc/src/sgml/ref/alter_group.sgml +++ b/doc/src/sgml/ref/alter_group.sgml @@ -1,5 +1,5 @@ @@ -11,13 +11,15 @@ PostgreSQL documentation ALTER GROUP - add users to a group or remove users from a group + change a user group ALTER GROUP groupname ADD USER username [, ... ] ALTER GROUP groupname DROP USER username [, ... ] + +ALTER GROUP groupname RENAME TO newname @@ -25,16 +27,16 @@ ALTER GROUP groupname DROP USER Description - ALTER GROUP is used to add or remove users from a - group. Only database superusers can use this command. - Adding a user to a group does not create the user. Similarly, removing - a user from a group does not drop the user itself. + ALTER GROUP is used to change a user group. The + first two variants add or remove users from a group. Only database + superusers can use this command. Adding a user to a group does not + create the user. Similarly, removing a user from a group does not + drop the user itself. - Use - to create a new group and to remove a group. + The third variant changes the name of the group. Only a database + superuser can rename groups. @@ -60,6 +62,15 @@ ALTER GROUP groupname DROP USER + + + newname + + + The new name of the group. + + + @@ -104,6 +115,16 @@ ALTER GROUP workers DROP USER beth; standard. The concept of roles is similar. + + + See Also + + + + + + + + + + + ALTER LANGUAGE + SQL - Language Statements + + + + ALTER LANGUAGE + change the definition of a procedural language + + + + +ALTER LANGUAGE name RENAME TO newname + + + + + Description + + + ALTER LANGUAGE changes the definition of a + language. The only functionality is to rename the language. Only + a superuser can rename languages. + + + + + Parameter + + + + name + + + Name of a language + + + + + + newname + + + The new name of the language + + + + + + + + Diagnostics + + + + ALTER LANGUAGE + + + Message returned if the alteration was successful. + + + + + + + + Compatibility + + + There is no ALTER LANGUAGE statement in the SQL + standard. + + + + + See Also + + + + + + + + + + diff --git a/doc/src/sgml/ref/alter_opclass.sgml b/doc/src/sgml/ref/alter_opclass.sgml new file mode 100644 index 0000000000..5a9694c73a --- /dev/null +++ b/doc/src/sgml/ref/alter_opclass.sgml @@ -0,0 +1,116 @@ + + + + + ALTER OPERATOR CLASS + SQL - Language Statements + + + + ALTER OPERATOR CLASS + change the definition of an operator class + + + + +ALTER OPERATOR CLASS name USING index_method RENAME TO newname + + + + + Description + + + ALTER OPERATOR CLASS changes the definition of + an operator class. The only functionality is to rename the + operator class. + + + + + Parameters + + + + name + + + The name (optionally schema-qualified) of an existing operator + class. + + + + + + index_method + + + The name of the index method this operator class is for. + + + + + + newname + + + The new name of the operator class. + + + + + + + + Diagnostics + + + + ALTER OPERATOR CLASS + + + Message returned if the command was successful. + + + + + + + + Compatibility + + + There is no ALTER OPERATOR CLASS statement in + the SQL standard. + + + + + See Also + + + + + + + + + diff --git a/doc/src/sgml/ref/alter_schema.sgml b/doc/src/sgml/ref/alter_schema.sgml new file mode 100644 index 0000000000..6e3c78c9c7 --- /dev/null +++ b/doc/src/sgml/ref/alter_schema.sgml @@ -0,0 +1,108 @@ + + + + + ALTER SCHEMA + SQL - Schema Statements + + + + ALTER SCHEMA + change the definition of a schema + + + + +ALTER SCHEMA name RENAME TO newname + + + + + Description + + + ALTER SCHEMA changes the definition of a schema. + The only functionality is to rename the schema. To rename a schema + you must own the schema and have the privilege + CREATE for the database. + + + + + Parameter + + + + name + + + Name of a schema + + + + + + newname + + + The new name of the schema + + + + + + + + Diagnostics + + + + ALTER SCHEMA + + + Message returned if the alteration was successful. + + + + + + + + Compatibility + + + There is no ALTER SCHEMA statement in the SQL + standard. + + + + + See Also + + + + + + + + + + diff --git a/doc/src/sgml/ref/alter_user.sgml b/doc/src/sgml/ref/alter_user.sgml index 121b4253ac..95de7a592d 100644 --- a/doc/src/sgml/ref/alter_user.sgml +++ b/doc/src/sgml/ref/alter_user.sgml @@ -1,5 +1,5 @@ @@ -25,6 +25,8 @@ where option can be: | CREATEUSER | NOCREATEUSER | VALID UNTIL 'abstime' +ALTER USER username RENAME TO newname + ALTER USER username SET variable { TO | = } { value | DEFAULT } ALTER USER username RESET variable @@ -48,7 +50,13 @@ ALTER USER username RESET - The second and the third variant change a user's session default for + The second variant changes the name of the user. Only a database + superuser can rename user accounts. The session user cannot be + renamed. (Connect as a different user if you need to do that.) + + + + The third and the fourth variant change a user's session default for a specified configuration variable. Whenever the user subsequently starts a new session, the specified value becomes the session default, overriding whatever setting is present in postgresql.conf @@ -130,6 +138,15 @@ ALTER USER username RESET + + newname + + + The new name of the user. + + + + variable value diff --git a/doc/src/sgml/ref/create_aggregate.sgml b/doc/src/sgml/ref/create_aggregate.sgml index 940343efde..2aff063671 100644 --- a/doc/src/sgml/ref/create_aggregate.sgml +++ b/doc/src/sgml/ref/create_aggregate.sgml @@ -1,5 +1,5 @@ @@ -230,14 +230,6 @@ CREATE AGGREGATE name ( - - Notes - - - Use DROP AGGREGATE to drop aggregate functions. - - - Examples @@ -255,6 +247,15 @@ CREATE AGGREGATE name ( standard does not provide for user-defined aggregate function. + + + See Also + + + + + + + @@ -171,10 +171,11 @@ CREATE CONVERSION myconv FOR 'UNICODE' TO 'LATIN1' FROM myfunc; See Also - - , - - + + + + + diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml index c4b26ac3b4..4e1978c6ee 100644 --- a/doc/src/sgml/ref/create_function.sgml +++ b/doc/src/sgml/ref/create_function.sgml @@ -1,5 +1,5 @@ @@ -404,6 +404,7 @@ CREATE FUNCTION add(integer, integer) RETURNS integer See Also + , , , , diff --git a/doc/src/sgml/ref/create_language.sgml b/doc/src/sgml/ref/create_language.sgml index 12e34365b9..d26eb48911 100644 --- a/doc/src/sgml/ref/create_language.sgml +++ b/doc/src/sgml/ref/create_language.sgml @@ -1,5 +1,5 @@ @@ -238,16 +238,15 @@ CREATE LANGUAGE plsample See Also - - - - - - - - - - + + + + + + + + + diff --git a/doc/src/sgml/ref/create_opclass.sgml b/doc/src/sgml/ref/create_opclass.sgml index 0891edc9ad..eddb8e7128 100644 --- a/doc/src/sgml/ref/create_opclass.sgml +++ b/doc/src/sgml/ref/create_opclass.sgml @@ -1,5 +1,5 @@ @@ -216,16 +216,6 @@ CREATE OPERATOR CLASS name [ DEFAUL - - Notes - - - Refer to - - to delete user-defined operator classes from a database. - - - Examples @@ -263,6 +253,15 @@ CREATE OPERATOR CLASS gist__int_ops standard. + + + See Also + + + + + + @@ -123,10 +123,6 @@ CREATE SCHEMA AUTHORIZATION username - - - Use DROP SCHEMA to remove a schema. - @@ -196,6 +192,16 @@ CREATE VIEW hollywood.winners AS CREATE privilege on his schema to someone else. + + + See Also + + + + + + + @@ -124,6 +124,7 @@ DROP AGGREGATE myavg(integer); See Also + diff --git a/doc/src/sgml/ref/drop_conversion.sgml b/doc/src/sgml/ref/drop_conversion.sgml index 6e785a84a8..d9c795c445 100644 --- a/doc/src/sgml/ref/drop_conversion.sgml +++ b/doc/src/sgml/ref/drop_conversion.sgml @@ -1,4 +1,4 @@ - + @@ -79,6 +79,7 @@ DROP CONVERSION myname; See Also + diff --git a/doc/src/sgml/ref/drop_function.sgml b/doc/src/sgml/ref/drop_function.sgml index 10504630ff..1a62a00f48 100644 --- a/doc/src/sgml/ref/drop_function.sgml +++ b/doc/src/sgml/ref/drop_function.sgml @@ -1,5 +1,5 @@ @@ -126,6 +126,7 @@ DROP FUNCTION sqrt(integer); + diff --git a/doc/src/sgml/ref/drop_language.sgml b/doc/src/sgml/ref/drop_language.sgml index 5e7a77f8cf..ad67a95d44 100644 --- a/doc/src/sgml/ref/drop_language.sgml +++ b/doc/src/sgml/ref/drop_language.sgml @@ -1,5 +1,5 @@ @@ -118,7 +118,9 @@ DROP LANGUAGE plsample; See Also + + diff --git a/doc/src/sgml/ref/drop_opclass.sgml b/doc/src/sgml/ref/drop_opclass.sgml index 3e54959a48..cb0aebd710 100644 --- a/doc/src/sgml/ref/drop_opclass.sgml +++ b/doc/src/sgml/ref/drop_opclass.sgml @@ -1,5 +1,5 @@ @@ -116,6 +116,7 @@ DROP OPERATOR CLASS widget_ops USING btree; See Also + diff --git a/doc/src/sgml/ref/drop_schema.sgml b/doc/src/sgml/ref/drop_schema.sgml index 5411b25799..b8f706b0c7 100644 --- a/doc/src/sgml/ref/drop_schema.sgml +++ b/doc/src/sgml/ref/drop_schema.sgml @@ -1,5 +1,5 @@ @@ -120,6 +120,7 @@ DROP SCHEMA mystuff CASCADE; See Also + diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml index 9799489b77..b7d2cf1c30 100644 --- a/doc/src/sgml/reference.sgml +++ b/doc/src/sgml/reference.sgml @@ -1,5 +1,5 @@ @@ -38,9 +38,15 @@ PostgreSQL Reference Manual &abort; + &alterAggregate; + &alterConversion; &alterDatabase; &alterDomain; + &alterFunction; &alterGroup; + &alterLanguage; + &alterOperatorClass; + &alterSchema; &alterSequence; &alterTable; &alterTrigger; diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 21a2ee271a..162b134faf 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.81 2003/05/27 17:49:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.82 2003/06/27 14:45:26 petere Exp $ * * NOTES * See acl.h. @@ -1327,3 +1327,40 @@ pg_opclass_ownercheck(Oid opc_oid, AclId userid) return userid == owner_id; } + + +/* + * Ownership check for database (specified as OID) + */ +bool +pg_database_ownercheck(Oid db_oid, AclId userid) +{ + Relation pg_database; + ScanKeyData entry[1]; + HeapScanDesc scan; + HeapTuple dbtuple; + int32 dba; + + /* Superusers bypass all permission checking. */ + if (superuser_arg(userid)) + return true; + + /* There's no syscache for pg_database, so must look the hard way */ + pg_database = heap_openr(DatabaseRelationName, AccessShareLock); + ScanKeyEntryInitialize(&entry[0], 0x0, + ObjectIdAttributeNumber, F_OIDEQ, + ObjectIdGetDatum(db_oid)); + scan = heap_beginscan(pg_database, SnapshotNow, 1, entry); + + dbtuple = heap_getnext(scan, ForwardScanDirection); + + if (!HeapTupleIsValid(dbtuple)) + elog(ERROR, "database %u does not exist", db_oid); + + dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba; + + heap_endscan(scan); + heap_close(pg_database, AccessShareLock); + + return userid == dba; +} diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index b19fdca069..97c0011b4b 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.51 2003/05/14 03:26:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.52 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -160,7 +160,7 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK) */ if (relation->catalogname) { - if (strcmp(relation->catalogname, DatabaseName) != 0) + if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0) elog(ERROR, "Cross-database references are not implemented"); } @@ -207,7 +207,7 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation) */ if (newRelation->catalogname) { - if (strcmp(newRelation->catalogname, DatabaseName) != 0) + if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0) elog(ERROR, "Cross-database references are not implemented"); } @@ -1146,7 +1146,7 @@ DeconstructQualifiedName(List *names, /* * We check the catalog name and then ignore it. */ - if (strcmp(catalogname, DatabaseName) != 0) + if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0) elog(ERROR, "Cross-database references are not implemented"); break; default: @@ -1596,7 +1596,7 @@ InitTempTableNamespace(void) if (pg_database_aclcheck(MyDatabaseId, GetSessionUserId(), ACL_CREATE_TEMP) != ACLCHECK_OK) elog(ERROR, "%s: not authorized to create temp tables", - DatabaseName); + get_database_name(MyDatabaseId)); snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId); diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile index db91bf1d0e..2a0bf0ec83 100644 --- a/src/backend/commands/Makefile +++ b/src/backend/commands/Makefile @@ -4,7 +4,7 @@ # Makefile for backend/commands # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.31 2002/08/27 04:55:07 tgl Exp $ +# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.32 2003/06/27 14:45:27 petere Exp $ # #------------------------------------------------------------------------- @@ -12,7 +12,7 @@ subdir = src/backend/commands top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -OBJS = aggregatecmds.o analyze.o async.o cluster.o comment.o \ +OBJS = aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o \ conversioncmds.o copy.o \ dbcommands.o define.o explain.o functioncmds.o \ indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o \ diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index bee50e686f..1ea31a6a5a 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.7 2003/06/25 21:30:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.8 2003/06/27 14:45:27 petere Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -25,6 +25,7 @@ #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/dependency.h" +#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_proc.h" @@ -193,3 +194,75 @@ RemoveAggregate(RemoveAggrStmt *stmt) performDeletion(&object, stmt->behavior); } + + +void +RenameAggregate(List *name, TypeName *basetype, const char *newname) +{ + Oid basetypeOid; + Oid procOid; + Oid namespaceOid; + Oid oid_array[FUNC_MAX_ARGS]; + HeapTuple tup; + Relation rel; + AclResult aclresult; + + /* + * if a basetype is passed in, then attempt to find an aggregate for + * that specific type. + * + * else attempt to find an aggregate with a basetype of ANYOID. This + * means that the aggregate is to apply to all basetypes (eg, COUNT). + */ + if (basetype) + basetypeOid = typenameTypeId(basetype); + else + basetypeOid = ANYOID; + + rel = heap_openr(ProcedureRelationName, RowExclusiveLock); + + procOid = find_aggregate_func("RenameAggregate", name, basetypeOid); + + tup = SearchSysCacheCopy(PROCOID, + ObjectIdGetDatum(procOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "RenameAggregate: couldn't find pg_proc tuple for %s", + NameListToString(name)); + + namespaceOid = ((Form_pg_proc) GETSTRUCT(tup))->pronamespace; + + /* make sure the new name doesn't exist */ + MemSet(oid_array, 0, sizeof(oid_array)); + oid_array[0] = basetypeOid; + if (SearchSysCacheExists(PROCNAMENSP, + CStringGetDatum(newname), + Int16GetDatum(1), + PointerGetDatum(oid_array), + ObjectIdGetDatum(namespaceOid))) + { + if (basetypeOid == ANYOID) + elog(ERROR, "function %s(*) already exists in schema %s", + newname, get_namespace_name(namespaceOid)); + else + elog(ERROR, "function %s(%s) already exists in schema %s", + newname, format_type_be(basetypeOid), get_namespace_name(namespaceOid)); + } + + /* must be owner */ + if (!pg_proc_ownercheck(procOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name)); + + /* must have CREATE privilege on namespace */ + aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceOid)); + + /* rename */ + namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c new file mode 100644 index 0000000000..65b27f5def --- /dev/null +++ b/src/backend/commands/alter.c @@ -0,0 +1,159 @@ +/*------------------------------------------------------------------------- + * + * alter.c + * Drivers for generic alter commands + * + * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/commands/alter.c,v 1.1 2003/06/27 14:45:27 petere Exp $ + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/htup.h" +#include "catalog/catalog.h" +#include "catalog/namespace.h" +#include "catalog/pg_class.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/trigger.h" +#include "commands/user.h" +#include "miscadmin.h" +#include "parser/parse_clause.h" +#include "utils/acl.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" + + +static void +CheckOwnership(RangeVar *rel, bool noCatalogs) +{ + Oid relOid; + HeapTuple tuple; + + relOid = RangeVarGetRelid(rel, false); + tuple = SearchSysCache(RELOID, + ObjectIdGetDatum(relOid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "Relation \"%s\" does not exist", rel->relname); + + if (!pg_class_ownercheck(relOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname); + + if (noCatalogs) + { + if (!allowSystemTableMods && + IsSystemClass((Form_pg_class) GETSTRUCT(tuple))) + elog(ERROR, "relation \"%s\" is a system catalog", + rel->relname); + } + + ReleaseSysCache(tuple); +} + + +void +ExecRenameStmt(RenameStmt *stmt) +{ + switch (stmt->renameType) + { + case OBJECT_AGGREGATE: + RenameAggregate(stmt->object, (TypeName *) lfirst(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_GROUP: + RenameGroup(stmt->subname, 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_SCHEMA: + RenameSchema(stmt->subname, stmt->newname); + break; + + case OBJECT_USER: + RenameUser(stmt->subname, stmt->newname); + break; + + case OBJECT_TABLE: + case OBJECT_COLUMN: + case OBJECT_TRIGGER: + { + Oid relid; + + CheckOwnership(stmt->relation, true); + + relid = RangeVarGetRelid(stmt->relation, false); + + switch (stmt->renameType) + { + case OBJECT_TABLE: + { + /* + * 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, + get_namespace_name(namespaceId)); + + renamerel(relid, stmt->newname); + 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; + } + + default: + elog(ERROR, "invalid object type for RenameStmt: %d", stmt->renameType); + } +} diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index ad70a47753..70d147f120 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.54 2003/05/27 17:49:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.55 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -192,7 +192,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) onerel = relation_open(relid, AccessShareLock); if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) || - (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared))) + (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) { /* No need for a WARNING if we already complained during VACUUM */ if (!vacstmt->vacuum) diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 4176cf3cfd..53974f396b 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1996-2001, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.62 2003/03/10 22:28:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.63 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -71,40 +71,40 @@ CommentObject(CommentStmt *stmt) { switch (stmt->objtype) { - case COMMENT_ON_INDEX: - case COMMENT_ON_SEQUENCE: - case COMMENT_ON_TABLE: - case COMMENT_ON_VIEW: + case OBJECT_INDEX: + case OBJECT_SEQUENCE: + case OBJECT_TABLE: + case OBJECT_VIEW: CommentRelation(stmt->objtype, stmt->objname, stmt->comment); break; - case COMMENT_ON_COLUMN: + case OBJECT_COLUMN: CommentAttribute(stmt->objname, stmt->comment); break; - case COMMENT_ON_DATABASE: + case OBJECT_DATABASE: CommentDatabase(stmt->objname, stmt->comment); break; - case COMMENT_ON_RULE: + case OBJECT_RULE: CommentRule(stmt->objname, stmt->comment); break; - case COMMENT_ON_TYPE: + case OBJECT_TYPE: CommentType(stmt->objname, stmt->comment); break; - case COMMENT_ON_AGGREGATE: + case OBJECT_AGGREGATE: CommentAggregate(stmt->objname, stmt->objargs, stmt->comment); break; - case COMMENT_ON_FUNCTION: + case OBJECT_FUNCTION: CommentProc(stmt->objname, stmt->objargs, stmt->comment); break; - case COMMENT_ON_OPERATOR: + case OBJECT_OPERATOR: CommentOperator(stmt->objname, stmt->objargs, stmt->comment); break; - case COMMENT_ON_TRIGGER: + case OBJECT_TRIGGER: CommentTrigger(stmt->objname, stmt->comment); break; - case COMMENT_ON_SCHEMA: + case OBJECT_SCHEMA: CommentNamespace(stmt->objname, stmt->comment); break; - case COMMENT_ON_CONSTRAINT: + case OBJECT_CONSTRAINT: CommentConstraint(stmt->objname, stmt->comment); break; default: @@ -301,22 +301,22 @@ CommentRelation(int objtype, List *relname, char *comment) switch (objtype) { - case COMMENT_ON_INDEX: + case OBJECT_INDEX: if (relation->rd_rel->relkind != RELKIND_INDEX) elog(ERROR, "relation \"%s\" is not an index", RelationGetRelationName(relation)); break; - case COMMENT_ON_SEQUENCE: + case OBJECT_SEQUENCE: if (relation->rd_rel->relkind != RELKIND_SEQUENCE) elog(ERROR, "relation \"%s\" is not a sequence", RelationGetRelationName(relation)); break; - case COMMENT_ON_TABLE: + case OBJECT_TABLE: if (relation->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "relation \"%s\" is not a table", RelationGetRelationName(relation)); break; - case COMMENT_ON_VIEW: + case OBJECT_VIEW: if (relation->rd_rel->relkind != RELKIND_VIEW) elog(ERROR, "relation \"%s\" is not a view", RelationGetRelationName(relation)); @@ -410,7 +410,7 @@ CommentDatabase(List *qualname, char *comment) /* Allow if the user matches the database dba or is a superuser */ - if (!(superuser() || is_dbadmin(oid))) + if (!pg_database_ownercheck(oid, GetUserId())) elog(ERROR, "you are not permitted to comment on database \"%s\"", database); diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c index 6115b0e12e..2d2fd66c4b 100644 --- a/src/backend/commands/conversioncmds.c +++ b/src/backend/commands/conversioncmds.c @@ -8,14 +8,17 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.5 2002/11/02 02:33:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.6 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "catalog/pg_conversion.h" +#include "access/heapam.h" #include "catalog/catalog.h" +#include "catalog/catname.h" +#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_type.h" #include "mb/pg_wchar.h" @@ -23,7 +26,9 @@ #include "miscadmin.h" #include "parser/parse_func.h" #include "utils/acl.h" +#include "utils/builtins.h" #include "utils/lsyscache.h" +#include "utils/syscache.h" /* @@ -98,3 +103,58 @@ DropConversionCommand(List *name, DropBehavior behavior) ConversionDrop(conversionOid, behavior); } + +/* + * Rename conversion + */ +void +RenameConversion(List *name, const char *newname) +{ + Oid conversionOid; + Oid namespaceOid; + HeapTuple tup; + Relation rel; + AclResult aclresult; + + rel = heap_openr(ConversionRelationName, RowExclusiveLock); + + conversionOid = FindConversionByName(name); + if (!OidIsValid(conversionOid)) + elog(ERROR, "conversion %s not found", NameListToString(name)); + + tup = SearchSysCacheCopy(CONOID, + ObjectIdGetDatum(conversionOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "couldn't find pg_conversion tuple for %s", + NameListToString(name)); + + namespaceOid = ((Form_pg_conversion) GETSTRUCT(tup))->connamespace; + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(CONNAMENSP, + CStringGetDatum(newname), + ObjectIdGetDatum(namespaceOid), + 0, 0)) + { + elog(ERROR, "conversion %s already exists in schema %s", + newname, get_namespace_name(namespaceOid)); + } + + /* must be owner */ + if (!superuser() && ((Form_pg_conversion) GETSTRUCT(tup))->conowner != GetUserId()) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name)); + + /* must have CREATE privilege on namespace */ + aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceOid)); + + /* rename */ + namestrcpy(&(((Form_pg_conversion) GETSTRUCT(tup))->conname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index bd43687818..55f44f9d8c 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.115 2003/05/15 17:59:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.116 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ #include #include +#include "access/genam.h" #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/catalog.h" @@ -31,6 +32,7 @@ #include "miscadmin.h" #include "storage/freespace.h" #include "storage/sinval.h" +#include "utils/acl.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -402,13 +404,13 @@ dropdb(const char *dbname) char *nominal_loc; char dbpath[MAXPGPATH]; Relation pgdbrel; - HeapScanDesc pgdbscan; + SysScanDesc pgdbscan; ScanKeyData key; HeapTuple tup; AssertArg(dbname); - if (strcmp(dbname, DatabaseName) == 0) + if (strcmp(dbname, get_database_name(MyDatabaseId)) == 0) elog(ERROR, "DROP DATABASE: cannot be executed on the currently open database"); PreventTransactionChain((void *) dbname, "DROP DATABASE"); @@ -454,9 +456,9 @@ dropdb(const char *dbname) ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber, F_OIDEQ, ObjectIdGetDatum(db_id)); - pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key); + pgdbscan = systable_beginscan(pgdbrel, DatabaseOidIndex, true, SnapshotNow, 1, &key); - tup = heap_getnext(pgdbscan, ForwardScanDirection); + tup = systable_getnext(pgdbscan); if (!HeapTupleIsValid(tup)) { /* @@ -470,7 +472,7 @@ dropdb(const char *dbname) /* Remove the database's tuple from pg_database */ simple_heap_delete(pgdbrel, &tup->t_self); - heap_endscan(pgdbscan); + systable_endscan(pgdbscan); /* * Delete any comments associated with the database @@ -513,6 +515,94 @@ dropdb(const char *dbname) } +/* + * Rename database + */ +void +RenameDatabase(const char *oldname, const char *newname) +{ + HeapTuple tup, newtup; + Relation rel; + SysScanDesc scan, scan2; + ScanKeyData key, key2; + + /* + * Obtain AccessExclusiveLock so that no new session gets started + * while the rename is in progress. + */ + rel = heap_openr(DatabaseRelationName, AccessExclusiveLock); + + ScanKeyEntryInitialize(&key, 0, Anum_pg_database_datname, + F_NAMEEQ, NameGetDatum(oldname)); + scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key); + + tup = systable_getnext(scan); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("database \"%s\" does not exist", oldname))); + + /* + * XXX Client applications probably store the current database + * somewhere, so renaming it could cause confusion. On the other + * hand, there may not be an actual problem besides a little + * confusion, so think about this and decide. + */ + if (HeapTupleGetOid(tup) == MyDatabaseId) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("current database may not be renamed"))); + + /* + * Make sure the database does not have active sessions. Might + * not be necessary, but it's consistent with other database + * operations. + */ + if (DatabaseHasActiveBackends(HeapTupleGetOid(tup), false)) + elog(ERROR, "database \"%s\" is being accessed by other users", oldname); + + /* make sure the new name doesn't exist */ + ScanKeyEntryInitialize(&key2, 0, Anum_pg_database_datname, + F_NAMEEQ, NameGetDatum(newname)); + scan2 = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key2); + if (HeapTupleIsValid(systable_getnext(scan2))) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("database \"%s\" already exists", newname))); + } + systable_endscan(scan2); + + /* must be owner */ + if (!pg_database_ownercheck(HeapTupleGetOid(tup), GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, oldname); + + /* must have createdb */ + if (!have_createdb_privilege()) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("permission denied"))); + } + + /* rename */ + newtup = heap_copytuple(tup); + namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname); + simple_heap_update(rel, &tup->t_self, newtup); + CatalogUpdateIndexes(rel, newtup); + + systable_endscan(scan); + heap_close(rel, NoLock); + + /* + * Force dirty buffers out to disk, so that newly-connecting + * backends will see the renamed database in pg_database right + * away. (They'll see an uncommitted tuple, but they don't care; + * see GetRawDatabaseInfo.) + */ + BufferSync(); +} + /* * ALTER DATABASE name SET ... @@ -525,7 +615,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) newtuple; Relation rel; ScanKeyData scankey; - HeapScanDesc scan; + SysScanDesc scan; Datum repl_val[Natts_pg_database]; char repl_null[Natts_pg_database]; char repl_repl[Natts_pg_database]; @@ -535,8 +625,8 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) rel = heap_openr(DatabaseRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname, F_NAMEEQ, NameGetDatum(stmt->dbname)); - scan = heap_beginscan(rel, SnapshotNow, 1, &scankey); - tuple = heap_getnext(scan, ForwardScanDirection); + scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &scankey); + tuple = systable_getnext(scan); if (!HeapTupleIsValid(tuple)) elog(ERROR, "database \"%s\" does not exist", stmt->dbname); @@ -583,7 +673,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) /* Update indexes */ CatalogUpdateIndexes(rel, newtuple); - heap_endscan(scan); + systable_endscan(scan); heap_close(rel, RowExclusiveLock); } @@ -601,7 +691,7 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, { Relation relation; ScanKeyData scanKey; - HeapScanDesc scan; + SysScanDesc scan; HeapTuple tuple; bool gottuple; @@ -613,9 +703,9 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname, F_NAMEEQ, NameGetDatum(name)); - scan = heap_beginscan(relation, SnapshotNow, 1, &scanKey); + scan = systable_beginscan(relation, DatabaseNameIndex, true, SnapshotNow, 1, &scanKey); - tuple = heap_getnext(scan, ForwardScanDirection); + tuple = systable_getnext(scan); gottuple = HeapTupleIsValid(tuple); if (gottuple) @@ -667,7 +757,7 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, } } - heap_endscan(scan); + systable_endscan(scan); heap_close(relation, AccessShareLock); return gottuple; @@ -790,7 +880,7 @@ get_database_oid(const char *dbname) { Relation pg_database; ScanKeyData entry[1]; - HeapScanDesc scan; + SysScanDesc scan; HeapTuple dbtuple; Oid oid; @@ -799,9 +889,9 @@ get_database_oid(const char *dbname) ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_database_datname, F_NAMEEQ, CStringGetDatum(dbname)); - scan = heap_beginscan(pg_database, SnapshotNow, 1, entry); + scan = systable_beginscan(pg_database, DatabaseNameIndex, true, SnapshotNow, 1, entry); - dbtuple = heap_getnext(scan, ForwardScanDirection); + dbtuple = systable_getnext(scan); /* We assume that there can be at most one matching tuple */ if (HeapTupleIsValid(dbtuple)) @@ -809,45 +899,46 @@ get_database_oid(const char *dbname) else oid = InvalidOid; - heap_endscan(scan); + systable_endscan(scan); heap_close(pg_database, AccessShareLock); return oid; } + /* - * get_database_owner - given a database OID, fetch the owner's usesysid. + * get_database_name - given a database OID, look up the name * - * Errors out if database not found. + * Returns InvalidOid if database name not found. * * This is not actually used in this file, but is exported for use elsewhere. */ -Oid -get_database_owner(Oid dbid) +char * +get_database_name(Oid dbid) { Relation pg_database; ScanKeyData entry[1]; - HeapScanDesc scan; + SysScanDesc scan; HeapTuple dbtuple; - int32 dba; + char *result; /* There's no syscache for pg_database, so must look the hard way */ pg_database = heap_openr(DatabaseRelationName, AccessShareLock); ScanKeyEntryInitialize(&entry[0], 0x0, ObjectIdAttributeNumber, F_OIDEQ, ObjectIdGetDatum(dbid)); - scan = heap_beginscan(pg_database, SnapshotNow, 1, entry); + scan = systable_beginscan(pg_database, DatabaseOidIndex, true, SnapshotNow, 1, entry); - dbtuple = heap_getnext(scan, ForwardScanDirection); + dbtuple = systable_getnext(scan); - if (!HeapTupleIsValid(dbtuple)) - elog(ERROR, "database %u does not exist", dbid); + /* We assume that there can be at most one matching tuple */ + if (HeapTupleIsValid(dbtuple)) + result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname)); + else + result = NULL; - dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba; - - heap_endscan(scan); + systable_endscan(scan); heap_close(pg_database, AccessShareLock); - /* XXX some confusion about whether userids are OID or int4 ... */ - return (Oid) dba; + return result; } diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index a0943993c1..47ac67b9dc 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.25 2003/02/01 22:09:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.26 2003/06/27 14:45:27 petere Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -591,6 +591,72 @@ RemoveFunctionById(Oid funcOid) } +/* + * Rename function + */ +void +RenameFunction(List *name, List *argtypes, const char *newname) +{ + Oid procOid; + Oid namespaceOid; + Oid oid_array[FUNC_MAX_ARGS]; + HeapTuple tup; + Relation rel; + AclResult aclresult; + int16 nargs; + + rel = heap_openr(ProcedureRelationName, RowExclusiveLock); + + procOid = LookupFuncNameTypeNames(name, argtypes, "RenameFunction"); + + tup = SearchSysCacheCopy(PROCOID, + ObjectIdGetDatum(procOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "RenameFunction: couldn't find pg_proc tuple for %s", + NameListToString(name)); + + if (((Form_pg_proc) GETSTRUCT(tup))->proisagg) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("%s is an aggregate function", NameListToString(name)), + errhint("Use ALTER AGGREGATE to rename aggregate functions."))); + + namespaceOid = ((Form_pg_proc) GETSTRUCT(tup))->pronamespace; + + /* make sure the new name doesn't exist */ + nargs = compute_parameter_types(argtypes, ((Form_pg_proc) GETSTRUCT(tup))->prolang, oid_array); + if (SearchSysCacheExists(PROCNAMENSP, + CStringGetDatum(newname), + Int16GetDatum(nargs), + PointerGetDatum(oid_array), + ObjectIdGetDatum(namespaceOid))) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("function %s with the same argument types already exists in schema %s", + newname, get_namespace_name(namespaceOid)))); + } + + /* must be owner */ + if (!pg_proc_ownercheck(procOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name)); + + /* must have CREATE privilege on namespace */ + aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceOid)); + + /* rename */ + namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} + + /* * SetFunctionReturnType - change declared return type of a function * diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 4186a14579..151183c645 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.100 2003/05/28 16:03:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.101 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -24,6 +24,7 @@ #include "catalog/namespace.h" #include "catalog/pg_opclass.h" #include "catalog/pg_proc.h" +#include "commands/dbcommands.h" #include "commands/defrem.h" #include "commands/tablecmds.h" #include "executor/executor.h" @@ -644,10 +645,10 @@ ReindexDatabase(const char *dbname, bool force, bool all) AssertArg(dbname); - if (strcmp(dbname, DatabaseName) != 0) + if (strcmp(dbname, get_database_name(MyDatabaseId)) != 0) elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database."); - if (!(superuser() || is_dbadmin(MyDatabaseId))) + if (!pg_database_ownercheck(MyDatabaseId, GetUserId())) elog(ERROR, "REINDEX DATABASE: Permission denied."); if (!allowSystemTableMods) diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index f67a1a6e81..9b90698a26 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.9 2002/11/13 00:39:46 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.10 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -550,7 +550,7 @@ RemoveOpClassById(Oid opclassOid) ObjectIdGetDatum(opclassOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "RemoveOpClassById: couldn't find pg_class entry %u", + elog(ERROR, "RemoveOpClassById: couldn't find pg_opclass entry %u", opclassOid); simple_heap_delete(rel, &tup->t_self); @@ -595,3 +595,94 @@ RemoveOpClassById(Oid opclassOid) systable_endscan(scan); heap_close(rel, RowExclusiveLock); } + + +/* + * Rename opclass + */ +void +RenameOpClass(List *name, const char *access_method, const char *newname) +{ + Oid opcOid; + Oid amOid; + Oid namespaceOid; + char *schemaname; + char *opcname; + HeapTuple tup; + Relation rel; + AclResult aclresult; + + amOid = GetSysCacheOid(AMNAME, + CStringGetDatum(access_method), + 0, 0, 0); + if (!OidIsValid(amOid)) + elog(ERROR, "access method \"%s\" not found", access_method); + + rel = heap_openr(OperatorClassRelationName, RowExclusiveLock); + + /* + * Look up the opclass + */ + DeconstructQualifiedName(name, &schemaname, &opcname); + + if (schemaname) + { + namespaceOid = LookupExplicitNamespace(schemaname); + + tup = SearchSysCacheCopy(CLAAMNAMENSP, + ObjectIdGetDatum(amOid), + PointerGetDatum(opcname), + ObjectIdGetDatum(namespaceOid), + 0); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist", + opcname, access_method); + + opcOid = HeapTupleGetOid(tup); + } + else + { + opcOid = OpclassnameGetOpcid(amOid, opcname); + if (!OidIsValid(opcOid)) + elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist", + opcname, access_method); + + tup = SearchSysCacheCopy(CLAOID, + ObjectIdGetDatum(opcOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "couldn't find pg_opclass tuple for %u", opcOid); + + namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace; + } + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(CLAAMNAMENSP, + ObjectIdGetDatum(amOid), + CStringGetDatum(newname), + ObjectIdGetDatum(namespaceOid), + 0)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"", + newname, access_method, get_namespace_name(namespaceOid)))); + } + + /* must be owner */ + if (!pg_opclass_ownercheck(opcOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name)); + + /* must have CREATE privilege on namespace */ + aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceOid)); + + /* rename */ + namestrcpy(&(((Form_pg_opclass) GETSTRUCT(tup))->opcname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 03d022f1f4..1e93c07fec 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.43 2002/09/21 18:39:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.44 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -231,3 +231,47 @@ DropProceduralLanguageById(Oid langOid) heap_close(rel, RowExclusiveLock); } + +/* + * Rename language + */ +void +RenameLanguage(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + + rel = heap_openr(ShadowRelationName, RowExclusiveLock); + + tup = SearchSysCacheCopy(LANGNAME, + CStringGetDatum(oldname), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("language \"%s\" does not exist", oldname))); + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(LANGNAME, + CStringGetDatum(newname), + 0, 0, 0)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("language \"%s\" already exists", newname))); + } + + /* must be superuser */ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("permission denied"))); + + /* rename */ + namestrcpy(&(((Form_pg_language) GETSTRUCT(tup))->lanname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 282fb19a85..1d71f65845 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.9 2003/05/06 20:26:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.10 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -18,8 +18,10 @@ #include "catalog/catalog.h" #include "catalog/catname.h" #include "catalog/dependency.h" +#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_namespace.h" +#include "commands/dbcommands.h" #include "commands/schemacmds.h" #include "miscadmin.h" #include "parser/analyze.h" @@ -86,7 +88,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) */ aclresult = pg_database_aclcheck(MyDatabaseId, saved_userid, ACL_CREATE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, DatabaseName); + aclcheck_error(aclresult, get_database_name(MyDatabaseId)); if (!allowSystemTableMods && IsReservedName(schemaName)) elog(ERROR, "CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system schemas", @@ -212,3 +214,57 @@ RemoveSchemaById(Oid schemaOid) heap_close(relation, RowExclusiveLock); } + + +/* + * Rename schema + */ +void +RenameSchema(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + AclResult aclresult; + + rel = heap_openr(NamespaceRelationName, RowExclusiveLock); + + tup = SearchSysCacheCopy(NAMESPACENAME, + CStringGetDatum(oldname), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("schema \"%s\" does not exist", oldname))); + + /* make sure the new name doesn't exist */ + if (HeapTupleIsValid( + SearchSysCache(NAMESPACENAME, + CStringGetDatum(newname), + 0, 0, 0))) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("schema \"%s\" already exists", newname))); + } + + /* must be owner */ + if (!pg_namespace_ownercheck(HeapTupleGetOid(tup), GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, oldname); + + /* must have CREATE privilege on database */ + aclresult = pg_database_aclcheck(MyDatabaseId, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_database_name(MyDatabaseId)); + + if (!allowSystemTableMods && IsReservedName(newname)) + elog(ERROR, "illegal schema name: \"%s\" -- pg_ is reserved for system schemas", + newname); + + /* rename */ + namestrcpy(&(((Form_pg_namespace) GETSTRUCT(tup))->nspname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index d31690aa24..be588b0863 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.117 2003/05/12 23:08:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.118 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -1091,6 +1091,64 @@ DropUser(DropUserStmt *stmt) } +/* + * Rename user + */ +void +RenameUser(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + + /* ExclusiveLock because we need to update the password file */ + rel = heap_openr(ShadowRelationName, ExclusiveLock); + + tup = SearchSysCacheCopy(SHADOWNAME, + CStringGetDatum(oldname), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("user \"%s\" does not exist", oldname))); + + /* + * XXX Client applications probably store the session user + * somewhere, so renaming it could cause confusion. On the other + * hand, there may not be an actual problem besides a little + * confusion, so think about this and decide. + */ + if (((Form_pg_shadow) GETSTRUCT(tup))->usesysid == GetSessionUserId()) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("session user may not be renamed"))); + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(SHADOWNAME, + CStringGetDatum(newname), + 0, 0, 0)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("user \"%s\" already exists", newname))); + } + + /* must be superuser */ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("permission denied"))); + + /* rename */ + namestrcpy(&(((Form_pg_shadow) GETSTRUCT(tup))->usename), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); + + user_file_update_needed = true; +} + /* * CheckPgUserAclNotNull @@ -1566,3 +1624,51 @@ DropGroup(DropGroupStmt *stmt) */ group_file_update_needed = true; } + + +/* + * Rename group + */ +void +RenameGroup(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + + /* ExclusiveLock because we need to update the flat group file */ + rel = heap_openr(GroupRelationName, ExclusiveLock); + + tup = SearchSysCacheCopy(GRONAME, + CStringGetDatum(oldname), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("group \"%s\" does not exist", oldname))); + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(GRONAME, + CStringGetDatum(newname), + 0, 0, 0)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("a group \"%s\" already exists", newname))); + } + + /* must be superuser */ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("permission denied"))); + + /* rename */ + namestrcpy(&(((Form_pg_group) GETSTRUCT(tup))->groname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); + + group_file_update_needed = true; +} diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 93701b611e..5c4faa5da2 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.255 2003/05/28 16:03:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.256 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -771,7 +771,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) onerel = relation_open(relid, lmode); if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) || - (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared))) + (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) { elog(WARNING, "Skipping \"%s\" --- only table or database owner can VACUUM it", RelationGetRelationName(onerel)); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 8f81f1953c..b1884bb0d2 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.256 2003/06/25 21:30:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.257 2003/06/27 14:45:28 petere Exp $ * *------------------------------------------------------------------------- */ @@ -1881,7 +1881,9 @@ _copyRenameStmt(RenameStmt *from) RenameStmt *newnode = makeNode(RenameStmt); COPY_NODE_FIELD(relation); - COPY_STRING_FIELD(oldname); + COPY_NODE_FIELD(object); + COPY_NODE_FIELD(objarg); + COPY_STRING_FIELD(subname); COPY_STRING_FIELD(newname); COPY_SCALAR_FIELD(renameType); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index a56b01429e..6f30c8fabd 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.199 2003/06/25 21:30:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.200 2003/06/27 14:45:28 petere Exp $ * *------------------------------------------------------------------------- */ @@ -909,7 +909,9 @@ static bool _equalRenameStmt(RenameStmt *a, RenameStmt *b) { COMPARE_NODE_FIELD(relation); - COMPARE_STRING_FIELD(oldname); + COMPARE_NODE_FIELD(object); + COMPARE_NODE_FIELD(objarg); + COMPARE_STRING_FIELD(subname); COMPARE_STRING_FIELD(newname); COMPARE_SCALAR_FIELD(renameType); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index b24e00b9a5..d3d9b4a5e3 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.421 2003/06/25 21:30:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.422 2003/06/27 14:45:28 petere Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -111,6 +111,7 @@ static void doNegateFloat(Value *v); Node *node; Value *value; ColumnRef *columnref; + ObjectType objtype; TypeName *typnam; DefElem *defelt; @@ -250,8 +251,8 @@ static void doNegateFloat(Value *v); %type copy_from opt_hold -%type reindex_type drop_type fetch_count - opt_column event comment_type cursor_options +%type fetch_count opt_column event cursor_options +%type reindex_type drop_type comment_type %type fetch_direction select_limit_value select_offset_value @@ -2227,7 +2228,7 @@ DropTrigStmt: n->relation = $5; n->property = $3; n->behavior = $6; - n->removeType = DROP_TRIGGER; + n->removeType = OBJECT_TRIGGER; $$ = (Node *) n; } ; @@ -2265,7 +2266,7 @@ DropAssertStmt: n->relation = NULL; n->property = $3; n->behavior = $4; - n->removeType = DROP_TRIGGER; /* XXX */ + n->removeType = OBJECT_TRIGGER; /* XXX */ elog(ERROR, "DROP ASSERTION is not yet supported"); $$ = (Node *) n; } @@ -2283,7 +2284,7 @@ DefineStmt: CREATE AGGREGATE func_name definition { DefineStmt *n = makeNode(DefineStmt); - n->kind = DEFINE_STMT_AGGREGATE; + n->kind = OBJECT_AGGREGATE; n->defnames = $3; n->definition = $4; $$ = (Node *)n; @@ -2291,7 +2292,7 @@ DefineStmt: | CREATE OPERATOR any_operator definition { DefineStmt *n = makeNode(DefineStmt); - n->kind = DEFINE_STMT_OPERATOR; + n->kind = OBJECT_OPERATOR; n->defnames = $3; n->definition = $4; $$ = (Node *)n; @@ -2299,7 +2300,7 @@ DefineStmt: | CREATE TYPE_P any_name definition { DefineStmt *n = makeNode(DefineStmt); - n->kind = DEFINE_STMT_TYPE; + n->kind = OBJECT_TYPE; n->defnames = $3; n->definition = $4; $$ = (Node *)n; @@ -2469,14 +2470,14 @@ DropStmt: DROP drop_type any_name_list opt_drop_behavior } ; -drop_type: TABLE { $$ = DROP_TABLE; } - | SEQUENCE { $$ = DROP_SEQUENCE; } - | VIEW { $$ = DROP_VIEW; } - | INDEX { $$ = DROP_INDEX; } - | TYPE_P { $$ = DROP_TYPE; } - | DOMAIN_P { $$ = DROP_DOMAIN; } - | CONVERSION_P { $$ = DROP_CONVERSION; } - | SCHEMA { $$ = DROP_SCHEMA; } +drop_type: TABLE { $$ = OBJECT_TABLE; } + | SEQUENCE { $$ = OBJECT_SEQUENCE; } + | VIEW { $$ = OBJECT_VIEW; } + | INDEX { $$ = OBJECT_INDEX; } + | TYPE_P { $$ = OBJECT_TYPE; } + | DOMAIN_P { $$ = OBJECT_DOMAIN; } + | CONVERSION_P { $$ = OBJECT_CONVERSION; } + | SCHEMA { $$ = OBJECT_SCHEMA; } ; any_name_list: @@ -2531,7 +2532,7 @@ CommentStmt: IS comment_text { CommentStmt *n = makeNode(CommentStmt); - n->objtype = COMMENT_ON_AGGREGATE; + n->objtype = OBJECT_AGGREGATE; n->objname = $4; n->objargs = makeList1($6); n->comment = $9; @@ -2540,7 +2541,7 @@ CommentStmt: | COMMENT ON FUNCTION func_name func_args IS comment_text { CommentStmt *n = makeNode(CommentStmt); - n->objtype = COMMENT_ON_FUNCTION; + n->objtype = OBJECT_FUNCTION; n->objname = $4; n->objargs = $5; n->comment = $7; @@ -2550,7 +2551,7 @@ CommentStmt: IS comment_text { CommentStmt *n = makeNode(CommentStmt); - n->objtype = COMMENT_ON_OPERATOR; + n->objtype = OBJECT_OPERATOR; n->objname = $4; n->objargs = $6; n->comment = $9; @@ -2559,7 +2560,7 @@ CommentStmt: | COMMENT ON CONSTRAINT name ON any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); - n->objtype = COMMENT_ON_CONSTRAINT; + n->objtype = OBJECT_CONSTRAINT; n->objname = lappend($6, makeString($4)); n->objargs = NIL; n->comment = $8; @@ -2568,7 +2569,7 @@ CommentStmt: | COMMENT ON RULE name ON any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); - n->objtype = COMMENT_ON_RULE; + n->objtype = OBJECT_RULE; n->objname = lappend($6, makeString($4)); n->objargs = NIL; n->comment = $8; @@ -2578,7 +2579,7 @@ CommentStmt: { /* Obsolete syntax supported for awhile for compatibility */ CommentStmt *n = makeNode(CommentStmt); - n->objtype = COMMENT_ON_RULE; + n->objtype = OBJECT_RULE; n->objname = makeList1(makeString($4)); n->objargs = NIL; n->comment = $6; @@ -2587,7 +2588,7 @@ CommentStmt: | COMMENT ON TRIGGER name ON any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); - n->objtype = COMMENT_ON_TRIGGER; + n->objtype = OBJECT_TRIGGER; n->objname = lappend($6, makeString($4)); n->objargs = NIL; n->comment = $8; @@ -2596,15 +2597,15 @@ CommentStmt: ; comment_type: - COLUMN { $$ = COMMENT_ON_COLUMN; } - | DATABASE { $$ = COMMENT_ON_DATABASE; } - | SCHEMA { $$ = COMMENT_ON_SCHEMA; } - | INDEX { $$ = COMMENT_ON_INDEX; } - | SEQUENCE { $$ = COMMENT_ON_SEQUENCE; } - | TABLE { $$ = COMMENT_ON_TABLE; } - | DOMAIN_P { $$ = COMMENT_ON_TYPE; } - | TYPE_P { $$ = COMMENT_ON_TYPE; } - | VIEW { $$ = COMMENT_ON_VIEW; } + COLUMN { $$ = OBJECT_COLUMN; } + | DATABASE { $$ = OBJECT_DATABASE; } + | SCHEMA { $$ = OBJECT_SCHEMA; } + | INDEX { $$ = OBJECT_INDEX; } + | SEQUENCE { $$ = OBJECT_SEQUENCE; } + | TABLE { $$ = OBJECT_TABLE; } + | DOMAIN_P { $$ = OBJECT_TYPE; } + | TYPE_P { $$ = OBJECT_TYPE; } + | VIEW { $$ = OBJECT_VIEW; } ; comment_text: @@ -3317,7 +3318,7 @@ ReindexStmt: | REINDEX DATABASE name opt_force { ReindexStmt *n = makeNode(ReindexStmt); - n->kind = REINDEX_DATABASE; + n->kind = OBJECT_DATABASE; n->name = $3; n->relation = NULL; n->force = $4; @@ -3326,8 +3327,8 @@ ReindexStmt: ; reindex_type: - INDEX { $$ = REINDEX_INDEX; } - | TABLE { $$ = REINDEX_TABLE; } + INDEX { $$ = OBJECT_INDEX; } + | TABLE { $$ = OBJECT_TABLE; } ; opt_force: FORCE { $$ = TRUE; } @@ -3337,31 +3338,104 @@ opt_force: FORCE { $$ = TRUE; } /***************************************************************************** * - * QUERY: - * rename in [*] to - * rename to + * ALTER THING name RENAME TO newname * *****************************************************************************/ -RenameStmt: ALTER TABLE relation_expr RENAME opt_column opt_name TO name +RenameStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_AGGREGATE; + n->object = $3; + n->objarg = makeList1($5); + n->newname = $9; + $$ = (Node *)n; + } + | ALTER CONVERSION_P any_name RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_CONVERSION; + n->object = $3; + n->newname = $6; + $$ = (Node *)n; + } + | ALTER DATABASE database_name RENAME TO database_name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_DATABASE; + n->subname = $3; + n->newname = $6; + $$ = (Node *)n; + } + | ALTER FUNCTION func_name func_args RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_FUNCTION; + n->object = $3; + n->objarg = $4; + n->newname = $7; + $$ = (Node *)n; + } + | ALTER GROUP_P UserId RENAME TO UserId + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_GROUP; + n->subname = $3; + n->newname = $6; + $$ = (Node *)n; + } + | ALTER LANGUAGE name RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_LANGUAGE; + n->subname = $3; + n->newname = $6; + $$ = (Node *)n; + } + | ALTER OPERATOR CLASS any_name USING access_method RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_OPCLASS; + n->object = $4; + n->subname = $6; + n->newname = $9; + $$ = (Node *)n; + } + | ALTER SCHEMA name RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_SCHEMA; + n->subname = $3; + n->newname = $6; + $$ = (Node *)n; + } + | ALTER TABLE relation_expr RENAME opt_column opt_name TO name { RenameStmt *n = makeNode(RenameStmt); n->relation = $3; - n->oldname = $6; + n->subname = $6; n->newname = $8; if ($6 == NULL) - n->renameType = RENAME_TABLE; + n->renameType = OBJECT_TABLE; else - n->renameType = RENAME_COLUMN; + n->renameType = OBJECT_COLUMN; $$ = (Node *)n; } | ALTER TRIGGER name ON relation_expr RENAME TO name { RenameStmt *n = makeNode(RenameStmt); n->relation = $5; - n->oldname = $3; + n->subname = $3; n->newname = $8; - n->renameType = RENAME_TRIGGER; + n->renameType = OBJECT_TRIGGER; + $$ = (Node *)n; + } + | ALTER USER UserId RENAME TO UserId + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_USER; + n->subname = $3; + n->newname = $6; $$ = (Node *)n; } ; @@ -3454,7 +3528,7 @@ DropRuleStmt: n->relation = $5; n->property = $3; n->behavior = $6; - n->removeType = DROP_RULE; + n->removeType = OBJECT_RULE; $$ = (Node *) n; } ; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 415242bc7a..4cb213199c 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.151 2003/06/27 00:33:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.152 2003/06/27 14:45:29 petere Exp $ * *------------------------------------------------------------------------- */ @@ -1077,7 +1077,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) /* * We check the catalog name and then ignore it. */ - if (strcmp(name1, DatabaseName) != 0) + if (strcmp(name1, get_database_name(MyDatabaseId)) != 0) elog(ERROR, "Cross-database references are not implemented"); /* Whole-row reference? */ diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 91726df7aa..bfa4a4b15f 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.103 2003/06/25 04:19:24 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.104 2003/06/27 14:45:29 petere Exp $ * *------------------------------------------------------------------------- */ @@ -144,7 +144,7 @@ transformTargetList(ParseState *pstate, List *targetlist) * We check the catalog name and then ignore * it. */ - if (strcmp(name1, DatabaseName) != 0) + if (strcmp(name1, get_database_name(MyDatabaseId)) != 0) elog(ERROR, "Cross-database references are not implemented"); schemaname = strVal(lsecond(fields)); relname = strVal(lthird(fields)); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 5f015f4636..be47708d4b 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.200 2003/05/06 21:51:41 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.201 2003/06/27 14:45:30 petere Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_shadow.h" +#include "commands/alter.h" #include "commands/async.h" #include "commands/cluster.h" #include "commands/comment.h" @@ -362,56 +363,51 @@ ProcessUtility(Node *parsetree, switch (stmt->removeType) { - case DROP_TABLE: + case OBJECT_TABLE: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_RELATION); RemoveRelation(rel, stmt->behavior); break; - case DROP_SEQUENCE: + case OBJECT_SEQUENCE: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_SEQUENCE); RemoveRelation(rel, stmt->behavior); break; - case DROP_VIEW: + case OBJECT_VIEW: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_VIEW); RemoveView(rel, stmt->behavior); break; - case DROP_INDEX: + case OBJECT_INDEX: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_INDEX); RemoveIndex(rel, stmt->behavior); break; - case DROP_TYPE: + case OBJECT_TYPE: /* RemoveType does its own permissions checks */ RemoveType(names, stmt->behavior); break; - case DROP_DOMAIN: - - /* - * RemoveDomain does its own permissions - * checks - */ + case OBJECT_DOMAIN: + /* RemoveDomain does its own permissions checks */ RemoveDomain(names, stmt->behavior); break; - case DROP_CONVERSION: + case OBJECT_CONVERSION: DropConversionCommand(names, stmt->behavior); break; - case DROP_SCHEMA: - - /* - * RemoveSchema does its own permissions - * checks - */ + case OBJECT_SCHEMA: + /* RemoveSchema does its own permissions checks */ RemoveSchema(names, stmt->behavior); break; + + default: + elog(ERROR, "invalid object type for DropStmt: %d", stmt->removeType); } /* @@ -454,57 +450,7 @@ ProcessUtility(Node *parsetree, * schema */ case T_RenameStmt: - { - RenameStmt *stmt = (RenameStmt *) parsetree; - Oid relid; - - CheckOwnership(stmt->relation, true); - - relid = RangeVarGetRelid(stmt->relation, false); - - switch (stmt->renameType) - { - case RENAME_TABLE: - { - /* - * 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, - get_namespace_name(namespaceId)); - - renamerel(relid, stmt->newname); - break; - } - case RENAME_COLUMN: - renameatt(relid, - stmt->oldname, /* old att name */ - stmt->newname, /* new att name */ - interpretInhOption(stmt->relation->inhOpt), /* recursive? */ - false); /* recursing already? */ - break; - case RENAME_TRIGGER: - renametrig(relid, - stmt->oldname, /* old att name */ - stmt->newname); /* new att name */ - break; - case RENAME_RULE: - elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d", - stmt->renameType); - break; - default: - elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d", - stmt->renameType); - } - } + ExecRenameStmt((RenameStmt *) parsetree); break; /* various Alter Table forms */ @@ -694,15 +640,17 @@ ProcessUtility(Node *parsetree, switch (stmt->kind) { - case DEFINE_STMT_AGGREGATE: + case OBJECT_AGGREGATE: DefineAggregate(stmt->defnames, stmt->definition); break; - case DEFINE_STMT_OPERATOR: + case OBJECT_OPERATOR: DefineOperator(stmt->defnames, stmt->definition); break; - case DEFINE_STMT_TYPE: + case OBJECT_TYPE: DefineType(stmt->defnames, stmt->definition); break; + default: + elog(ERROR, "invalid object type for DefineStmt: %d", stmt->kind); } } break; @@ -906,16 +854,18 @@ ProcessUtility(Node *parsetree, switch (stmt->removeType) { - case DROP_RULE: + case OBJECT_RULE: /* RemoveRewriteRule checks permissions */ RemoveRewriteRule(relId, stmt->property, stmt->behavior); break; - case DROP_TRIGGER: + case OBJECT_TRIGGER: /* DropTrigger checks permissions */ DropTrigger(relId, stmt->property, stmt->behavior); break; + default: + elog(ERROR, "invalid object type for DropPropertyStmt: %d", stmt->removeType); } } break; @@ -986,17 +936,19 @@ ProcessUtility(Node *parsetree, switch (stmt->kind) { - case REINDEX_INDEX: + case OBJECT_INDEX: CheckOwnership(stmt->relation, false); ReindexIndex(stmt->relation, stmt->force); break; - case REINDEX_TABLE: + case OBJECT_TABLE: CheckOwnership(stmt->relation, false); ReindexTable(stmt->relation, stmt->force); break; - case REINDEX_DATABASE: + case OBJECT_DATABASE: ReindexDatabase(stmt->name, stmt->force, false); break; + default: + elog(ERROR, "invalid object type for ReindexStmt: %d", stmt->kind); } break; } @@ -1238,28 +1190,28 @@ CreateCommandTag(Node *parsetree) case T_DropStmt: switch (((DropStmt *) parsetree)->removeType) { - case DROP_TABLE: + case OBJECT_TABLE: tag = "DROP TABLE"; break; - case DROP_SEQUENCE: + case OBJECT_SEQUENCE: tag = "DROP SEQUENCE"; break; - case DROP_VIEW: + case OBJECT_VIEW: tag = "DROP VIEW"; break; - case DROP_INDEX: + case OBJECT_INDEX: tag = "DROP INDEX"; break; - case DROP_TYPE: + case OBJECT_TYPE: tag = "DROP TYPE"; break; - case DROP_DOMAIN: + case OBJECT_DOMAIN: tag = "DROP DOMAIN"; break; - case DROP_CONVERSION: + case OBJECT_CONVERSION: tag = "DROP CONVERSION"; break; - case DROP_SCHEMA: + case OBJECT_SCHEMA: tag = "DROP SCHEMA"; break; default: @@ -1280,10 +1232,41 @@ CreateCommandTag(Node *parsetree) break; case T_RenameStmt: - if (((RenameStmt *) parsetree)->renameType == RENAME_TRIGGER) - tag = "ALTER TRIGGER"; - else - tag = "ALTER TABLE"; + switch (((RenameStmt *) parsetree)->renameType) + { + case OBJECT_AGGREGATE: + tag = "ALTER AGGREGATE"; + break; + case OBJECT_CONVERSION: + tag = "ALTER CONVERSION"; + break; + case OBJECT_DATABASE: + tag = "ALTER DATABASE"; + break; + case OBJECT_FUNCTION: + tag = "ALTER FUNCTION"; + break; + case OBJECT_GROUP: + tag = "ALTER GROUP"; + break; + case OBJECT_LANGUAGE: + tag = "ALTER LANGUAGE"; + break; + case OBJECT_OPCLASS: + tag = "ALTER OPERATOR CLASS"; + break; + case OBJECT_SCHEMA: + tag = "ALTER SCHEMA"; + break; + case OBJECT_TRIGGER: + tag = "ALTER TRIGGER"; + break; + case OBJECT_USER: + tag = "ALTER USER"; + break; + default: + tag = "ALTER TABLE"; + } break; case T_AlterTableStmt: @@ -1305,13 +1288,13 @@ CreateCommandTag(Node *parsetree) case T_DefineStmt: switch (((DefineStmt *) parsetree)->kind) { - case DEFINE_STMT_AGGREGATE: + case OBJECT_AGGREGATE: tag = "CREATE AGGREGATE"; break; - case DEFINE_STMT_OPERATOR: + case OBJECT_OPERATOR: tag = "CREATE OPERATOR"; break; - case DEFINE_STMT_TYPE: + case OBJECT_TYPE: tag = "CREATE TYPE"; break; default: @@ -1421,10 +1404,10 @@ CreateCommandTag(Node *parsetree) case T_DropPropertyStmt: switch (((DropPropertyStmt *) parsetree)->removeType) { - case DROP_TRIGGER: + case OBJECT_TRIGGER: tag = "DROP TRIGGER"; break; - case DROP_RULE: + case OBJECT_RULE: tag = "DROP RULE"; break; default: diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 1f85e4f499..24d7964c90 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/misc.c,v 1.28 2003/02/13 05:24:02 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/misc.c,v 1.29 2003/06/27 14:45:30 petere Exp $ * *------------------------------------------------------------------------- */ @@ -54,7 +54,6 @@ current_database(PG_FUNCTION_ARGS) db = (Name) palloc(NAMEDATALEN); - namestrcpy(db, DatabaseName); - + namestrcpy(db, get_database_name(MyDatabaseId)); PG_RETURN_NAME(db); } diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 0a53556ec3..2a7a372fa6 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.71 2003/05/28 18:19:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.72 2003/06/27 14:45:30 petere Exp $ * * NOTES * Globals used all over the place should be declared here and not @@ -52,9 +52,7 @@ char pg_pathname[MAXPGPATH]; /* full path to postgres BackendId MyBackendId; -char *DatabaseName = NULL; char *DatabasePath = NULL; - Oid MyDatabaseId = InvalidOid; /* these are initialized for the bootstrap/standalone case: */ diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 6ffd1e01b9..c3dc38f387 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.102 2003/04/04 20:42:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.103 2003/06/27 14:45:30 petere Exp $ * *------------------------------------------------------------------------- */ @@ -105,22 +105,6 @@ SetDatabasePath(const char *path) } } -void -SetDatabaseName(const char *name) -{ - if (DatabaseName) - { - free(DatabaseName); - DatabaseName = NULL; - } - /* use strdup since this is done before memory contexts are set up */ - if (name) - { - DatabaseName = strdup(name); - AssertState(DatabaseName); - } -} - /* * Set data directory, but make sure it's an absolute path. Use this, * never set DataDir directly. diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 8fda5d185e..48194071e5 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.121 2003/05/14 03:26:02 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.122 2003/06/27 14:45:30 petere Exp $ * * *------------------------------------------------------------------------- @@ -228,13 +228,11 @@ InitPostgres(const char *dbname, const char *username) bool bootstrap = IsBootstrapProcessingMode(); /* - * Set up the global variables holding database name, id, and path. + * Set up the global variables holding database id and path. * * We take a shortcut in the bootstrap case, otherwise we have to look up * the db name in pg_database. */ - SetDatabaseName(dbname); - if (bootstrap) { MyDatabaseId = TemplateDbOid; diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c index dee8da747d..e398d8d001 100644 --- a/src/backend/utils/misc/superuser.c +++ b/src/backend/utils/misc/superuser.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.25 2002/12/05 04:04:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.26 2003/06/27 14:45:31 petere Exp $ * *------------------------------------------------------------------------- */ @@ -58,18 +58,3 @@ superuser_arg(AclId userid) } return result; } - - -/* - * The Postgres user running this command is the owner of the specified - * database. - */ -bool -is_dbadmin(Oid dbid) -{ - AclId dba; - - dba = get_database_owner(dbid); - - return (GetUserId() == dba); -} diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h new file mode 100644 index 0000000000..e3b59af1af --- /dev/null +++ b/src/include/commands/alter.h @@ -0,0 +1,21 @@ +/*------------------------------------------------------------------------- + * + * alter.h + * prototypes for alter.h + * + * + * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $Id: alter.h,v 1.1 2003/06/27 14:45:31 petere Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef ALTER_H +#define ALTER_H + +#include "nodes/parsenodes.h" + +extern void ExecRenameStmt(RenameStmt *stmt); + +#endif /* ALTER_H */ diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h index eedc2608ef..babb9f56e1 100644 --- a/src/include/commands/conversioncmds.h +++ b/src/include/commands/conversioncmds.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: conversioncmds.h,v 1.3 2002/09/04 20:31:42 momjian Exp $ + * $Id: conversioncmds.h,v 1.4 2003/06/27 14:45:31 petere Exp $ * *------------------------------------------------------------------------- */ @@ -19,5 +19,6 @@ extern void CreateConversionCommand(CreateConversionStmt *parsetree); extern void DropConversionCommand(List *conversion_name, DropBehavior behavior); +extern void RenameConversion(List *name, const char *newname); #endif /* CONVERSIONCMDS_H */ diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h index a1a2a8da53..037859973b 100644 --- a/src/include/commands/dbcommands.h +++ b/src/include/commands/dbcommands.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: dbcommands.h,v 1.26 2002/09/05 00:43:07 tgl Exp $ + * $Id: dbcommands.h,v 1.27 2003/06/27 14:45:31 petere Exp $ * *------------------------------------------------------------------------- */ @@ -18,9 +18,10 @@ extern void createdb(const CreatedbStmt *stmt); extern void dropdb(const char *dbname); +extern void RenameDatabase(const char *oldname, const char *newname); extern void AlterDatabaseSet(AlterDatabaseSetStmt *stmt); -extern Oid get_database_oid(const char *dbname); -extern Oid get_database_owner(Oid dbid); +extern Oid get_database_oid(const char *dbname); +extern char * get_database_name(Oid dbid); #endif /* DBCOMMANDS_H */ diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 2c2ace6805..5fe7a6c5da 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: defrem.h,v 1.50 2002/12/10 16:12:52 tgl Exp $ + * $Id: defrem.h,v 1.51 2003/06/27 14:45:31 petere Exp $ * *------------------------------------------------------------------------- */ @@ -38,6 +38,7 @@ extern void RemoveFunction(RemoveFuncStmt *stmt); extern void RemoveFunctionById(Oid funcOid); extern void SetFunctionReturnType(Oid funcOid, Oid newRetType); extern void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType); +extern void RenameFunction(List *name, List *argtypes, const char *newname); extern void CreateCast(CreateCastStmt *stmt); extern void DropCast(DropCastStmt *stmt); extern void DropCastById(Oid castOid); @@ -50,12 +51,13 @@ extern void RemoveOperatorById(Oid operOid); /* commands/aggregatecmds.c */ extern void DefineAggregate(List *names, List *parameters); extern void RemoveAggregate(RemoveAggrStmt *stmt); +extern void RenameAggregate(List *name, TypeName *basetype, const char *newname); /* commands/opclasscmds.c */ extern void DefineOpClass(CreateOpClassStmt *stmt); extern void RemoveOpClass(RemoveOpClassStmt *stmt); extern void RemoveOpClassById(Oid opclassOid); - +extern void RenameOpClass(List *name, const char *access_method, const char *newname); /* support routines in commands/define.c */ diff --git a/src/include/commands/proclang.h b/src/include/commands/proclang.h index f4fde9b108..a446773cd4 100644 --- a/src/include/commands/proclang.h +++ b/src/include/commands/proclang.h @@ -14,5 +14,6 @@ extern void CreateProceduralLanguage(CreatePLangStmt *stmt); extern void DropProceduralLanguage(DropPLangStmt *stmt); extern void DropProceduralLanguageById(Oid langOid); +extern void RenameLanguage(const char *oldname, const char *newname); #endif /* PROCLANG_H */ diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h index b7538d013f..b50ace5c12 100644 --- a/src/include/commands/schemacmds.h +++ b/src/include/commands/schemacmds.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: schemacmds.h,v 1.3 2002/09/04 20:31:42 momjian Exp $ + * $Id: schemacmds.h,v 1.4 2003/06/27 14:45:31 petere Exp $ * *------------------------------------------------------------------------- */ @@ -22,4 +22,6 @@ extern void CreateSchemaCommand(CreateSchemaStmt *parsetree); extern void RemoveSchema(List *names, DropBehavior behavior); extern void RemoveSchemaById(Oid schemaOid); +extern void RenameSchema(const char *oldname, const char *newname); + #endif /* SCHEMACMDS_H */ diff --git a/src/include/commands/user.h b/src/include/commands/user.h index 8748140988..85e93dc118 100644 --- a/src/include/commands/user.h +++ b/src/include/commands/user.h @@ -4,7 +4,7 @@ * Commands for manipulating users and groups. * * - * $Id: user.h,v 1.20 2002/10/21 19:46:45 tgl Exp $ + * $Id: user.h,v 1.21 2003/06/27 14:45:31 petere Exp $ * *------------------------------------------------------------------------- */ @@ -22,10 +22,12 @@ extern void CreateUser(CreateUserStmt *stmt); extern void AlterUser(AlterUserStmt *stmt); extern void AlterUserSet(AlterUserSetStmt *stmt); extern void DropUser(DropUserStmt *stmt); +extern void RenameUser(const char *oldname, const char *newname); extern void CreateGroup(CreateGroupStmt *stmt); extern void AlterGroup(AlterGroupStmt *stmt, const char *tag); extern void DropGroup(DropGroupStmt *stmt); +extern void RenameGroup(const char *oldname, const char *newname); extern Datum update_pg_pwd_and_pg_group(PG_FUNCTION_ARGS); diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 1ea326e197..f88b983504 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: miscadmin.h,v 1.123 2003/05/28 18:19:09 tgl Exp $ + * $Id: miscadmin.h,v 1.124 2003/06/27 14:45:31 petere Exp $ * * NOTES * some of the information in this file should be moved to @@ -192,7 +192,6 @@ extern char *VirtualHost; * POSTGRES directory path definitions. * *****************************************************************************/ -extern char *DatabaseName; extern char *DatabasePath; /* in utils/misc/database.c */ @@ -200,7 +199,6 @@ extern void GetRawDatabaseInfo(const char *name, Oid *db_id, char *path); extern char *ExpandDatabasePath(const char *path); /* now in utils/init/miscinit.c */ -extern void SetDatabaseName(const char *name); extern void SetDatabasePath(const char *path); extern char *GetUserNameFromId(AclId userid); @@ -226,8 +224,6 @@ extern char *convertstr(unsigned char *buff, int len, int dest); /* in utils/misc/superuser.c */ extern bool superuser(void); /* current user is superuser */ extern bool superuser_arg(AclId userid); /* given user is superuser */ -extern bool is_dbadmin(Oid dbid); /* current user is owner of - * database */ /***************************************************************************** diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 2e6e1559fa..527c56b9ed 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.240 2003/06/25 04:19:24 momjian Exp $ + * $Id: parsenodes.h,v 1.241 2003/06/27 14:45:31 petere Exp $ * *------------------------------------------------------------------------- */ @@ -668,6 +668,36 @@ typedef struct SetOperationStmt * field in Query. *****************************************************************************/ +/* + * When a command can act on several kinds of objects with only one + * parse structure required, use these constants to designate the + * object type. + */ + +typedef enum ObjectType { + OBJECT_AGGREGATE, + OBJECT_CAST, + OBJECT_COLUMN, + OBJECT_CONSTRAINT, + OBJECT_CONVERSION, + OBJECT_DATABASE, + OBJECT_DOMAIN, + OBJECT_FUNCTION, + OBJECT_GROUP, + OBJECT_INDEX, + OBJECT_LANGUAGE, + OBJECT_OPCLASS, + OBJECT_OPERATOR, + OBJECT_RULE, + OBJECT_SCHEMA, + OBJECT_SEQUENCE, + OBJECT_TABLE, + OBJECT_TRIGGER, + OBJECT_TYPE, + OBJECT_USER, + OBJECT_VIEW +} ObjectType; + /* ---------------------- * Create Schema Statement * @@ -1076,17 +1106,10 @@ typedef struct AlterSeqStmt * Create {Aggregate|Operator|Type} Statement * ---------------------- */ -typedef enum DefineStmtKind -{ - DEFINE_STMT_AGGREGATE, - DEFINE_STMT_OPERATOR, - DEFINE_STMT_TYPE -} DefineStmtKind; - typedef struct DefineStmt { NodeTag type; - DefineStmtKind kind; /* see above */ + ObjectType kind; /* aggregate, operator, type */ List *defnames; /* qualified name (list of Value strings) */ List *definition; /* a list of DefElem */ } DefineStmt; @@ -1139,20 +1162,11 @@ typedef struct CreateOpClassItem * ---------------------- */ -#define DROP_TABLE 1 -#define DROP_SEQUENCE 2 -#define DROP_VIEW 3 -#define DROP_INDEX 4 -#define DROP_TYPE 5 -#define DROP_DOMAIN 6 -#define DROP_CONVERSION 7 -#define DROP_SCHEMA 8 - typedef struct DropStmt { NodeTag type; List *objects; /* list of sublists of names (as Values) */ - int removeType; /* see #defines above */ + ObjectType removeType; /* object type */ DropBehavior behavior; /* RESTRICT or CASCADE behavior */ } DropStmt; @@ -1164,15 +1178,12 @@ typedef struct DropStmt * ---------------------- */ -#define DROP_RULE 100 -#define DROP_TRIGGER 101 - typedef struct DropPropertyStmt { NodeTag type; RangeVar *relation; /* owning relation */ char *property; /* name of rule, trigger, etc */ - int removeType; /* see #defines above */ + ObjectType removeType; /* OBJECT_RULE or OBJECT_TRIGGER */ DropBehavior behavior; /* RESTRICT or CASCADE behavior */ } DropPropertyStmt; @@ -1190,25 +1201,10 @@ typedef struct TruncateStmt * Comment On Statement * ---------------------- */ -#define COMMENT_ON_AGGREGATE 100 -#define COMMENT_ON_COLUMN 101 -#define COMMENT_ON_CONSTRAINT 102 -#define COMMENT_ON_DATABASE 103 -#define COMMENT_ON_FUNCTION 104 -#define COMMENT_ON_INDEX 105 -#define COMMENT_ON_OPERATOR 106 -#define COMMENT_ON_RULE 107 -#define COMMENT_ON_SCHEMA 108 -#define COMMENT_ON_SEQUENCE 109 -#define COMMENT_ON_TABLE 110 -#define COMMENT_ON_TRIGGER 111 -#define COMMENT_ON_TYPE 112 -#define COMMENT_ON_VIEW 113 - typedef struct CommentStmt { NodeTag type; - int objtype; /* Object's type, see codes above */ + ObjectType objtype; /* Object's type */ List *objname; /* Qualified name of the object */ List *objargs; /* Arguments if needed (eg, for functions) */ char *comment; /* Comment to insert, or NULL to remove */ @@ -1352,21 +1348,16 @@ typedef struct RemoveOpClassStmt /* ---------------------- * Alter Object Rename Statement * ---------------------- - * Currently supports renaming tables, table columns, and triggers. - * If renaming a table, oldname is ignored. */ -#define RENAME_TABLE 110 -#define RENAME_COLUMN 111 -#define RENAME_TRIGGER 112 -#define RENAME_RULE 113 - typedef struct RenameStmt { NodeTag type; - RangeVar *relation; /* owning relation */ - char *oldname; /* name of rule, trigger, etc */ + RangeVar *relation; /* in case it's a table */ + List *object; /* in case it's some other object */ + List *objarg; /* argument types, if applicable */ + char *subname; /* name of contained object (column, rule, trigger, etc) */ char *newname; /* the new name */ - int renameType; /* RENAME_TABLE, RENAME_COLUMN, etc */ + ObjectType renameType; /* OBJECT_TABLE, OBJECT_COLUMN, etc */ } RenameStmt; /* ---------------------- @@ -1614,17 +1605,10 @@ typedef struct ConstraintsSetStmt * REINDEX Statement * ---------------------- */ -typedef enum ReindexStmtKind -{ - REINDEX_INDEX, - REINDEX_TABLE, - REINDEX_DATABASE -} ReindexStmtKind; - typedef struct ReindexStmt { NodeTag type; - ReindexStmtKind kind; /* see above */ + ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, OBJECT_DATABASE */ RangeVar *relation; /* Table or index to reindex */ const char *name; /* name of database to reindex */ bool force; diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 8352f8180e..7decac38fd 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: acl.h,v 1.55 2003/06/27 00:33:26 tgl Exp $ + * $Id: acl.h,v 1.56 2003/06/27 14:45:32 petere Exp $ * * NOTES * For backward-compatibility purposes we have to allow there @@ -216,5 +216,6 @@ extern bool pg_oper_ownercheck(Oid oper_oid, AclId userid); extern bool pg_proc_ownercheck(Oid proc_oid, AclId userid); extern bool pg_namespace_ownercheck(Oid nsp_oid, AclId userid); extern bool pg_opclass_ownercheck(Oid opc_oid, AclId userid); +extern bool pg_database_ownercheck(Oid db_oid, AclId userid); #endif /* ACL_H */