diff --git a/doc/src/sgml/ref/alter_database.sgml b/doc/src/sgml/ref/alter_database.sgml index aa34fac9f05c2f24049a82fccc433b1ec51ca6ac..86093712f888d42fa77d6a4b7640e215a276816e 100644 --- a/doc/src/sgml/ref/alter_database.sgml +++ b/doc/src/sgml/ref/alter_database.sgml @@ -1,5 +1,5 @@ @@ -23,6 +23,8 @@ PostgreSQL documentation ALTER DATABASE name SET parameter { TO | = } { value | DEFAULT } ALTER DATABASE name RESET parameter +ALTER DATABASE name OWNER TO new_owner + ALTER DATABASE name RENAME TO newname @@ -54,6 +56,11 @@ ALTER DATABASE name RENAME TO + + + The fourth form changes the owner of the database. Only a superuser + can change the database's owner. + diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 9114983e75de93856286663ed2738bf34f55381a..02c1bf8e2042a9441486593ba0229765eab049fc 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.133 2004/05/26 04:41:10 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.134 2004/05/26 13:56:45 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -776,6 +776,52 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) } +/* + * ALTER DATABASE name OWNER TO newowner + */ +void +AlterDatabaseOwner(const char *dbname, const char *newowner) +{ + AclId newdatdba; + HeapTuple tuple, + newtuple; + Relation rel; + ScanKeyData scankey; + SysScanDesc scan; + + rel = heap_openr(DatabaseRelationName, RowExclusiveLock); + ScanKeyInit(&scankey, + Anum_pg_database_datname, + BTEqualStrategyNumber, F_NAMEEQ, + NameGetDatum(dbname)); + scan = systable_beginscan(rel, DatabaseNameIndex, true, + SnapshotNow, 1, &scankey); + tuple = systable_getnext(scan); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%s\" does not exist", dbname))); + + /* obtain sysid of proposed owner */ + newdatdba = get_usesysid(newowner); /* will ereport if no such user */ + + /* changing owner's database for someone else: must be superuser */ + /* note that the someone else need not have any permissions */ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to change owner's database for another user"))); + + /* change owner */ + newtuple = heap_copytuple(tuple); + ((Form_pg_database) GETSTRUCT(newtuple))->datdba = newdatdba; + simple_heap_update(rel, &tuple->t_self, newtuple); + CatalogUpdateIndexes(rel, newtuple); + + systable_endscan(scan); + heap_close(rel, NoLock); +} + /* * Helper functions diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 21cef8879221dd90ebc3f3da22473784f88e3205..a7ba5d048208ba4a62d7094f3fee549916250d2b 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 - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.282 2004/05/26 04:41:18 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.283 2004/05/26 13:56:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2068,6 +2068,17 @@ _copyCreatedbStmt(CreatedbStmt *from) return newnode; } +static AlterDbOwnerStmt * +_copyAlterDbOwnerStmt(AlterDbOwnerStmt *from) +{ + AlterDbOwnerStmt *newnode = makeNode(AlterDbOwnerStmt); + + COPY_STRING_FIELD(dbname); + COPY_STRING_FIELD(uname); + + return newnode; +} + static AlterDatabaseSetStmt * _copyAlterDatabaseSetStmt(AlterDatabaseSetStmt *from) { @@ -2860,6 +2871,9 @@ copyObject(void *from) case T_CreatedbStmt: retval = _copyCreatedbStmt(from); break; + case T_AlterDbOwnerStmt: + retval = _copyAlterDbOwnerStmt(from); + break; case T_AlterDatabaseSetStmt: retval = _copyAlterDatabaseSetStmt(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 236061eee2a461bfe2653913f253c878fa5b5f83..97701a02a1e9d0e2da024b4303f9abae1a178e4f 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 - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.221 2004/05/26 04:41:19 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.222 2004/05/26 13:56:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1099,6 +1099,15 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b) return true; } +static bool +_equalAlterDbOwnerStmt(AlterDbOwnerStmt *a, AlterDbOwnerStmt *b) +{ + COMPARE_STRING_FIELD(dbname); + COMPARE_STRING_FIELD(uname); + + return true; +} + static bool _equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b) { @@ -2005,6 +2014,9 @@ equal(void *a, void *b) case T_CreatedbStmt: retval = _equalCreatedbStmt(a, b); break; + case T_AlterDbOwnerStmt: + retval = _equalAlterDbOwnerStmt(a, b); + break; case T_AlterDatabaseSetStmt: retval = _equalAlterDatabaseSetStmt(a, b); break; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 654341ddfe816f3fe773b79b4d9ab99f448cc31d..b20f92ba7b26d65308de7c9649543c76bbab570d 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.455 2004/05/26 04:41:29 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.456 2004/05/26 13:56:51 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -152,6 +152,7 @@ static void doNegateFloat(Value *v); VariableResetStmt VariableSetStmt VariableShowStmt ViewStmt CheckPointStmt CreateConversionStmt DeallocateStmt PrepareStmt ExecuteStmt + AlterDbOwnerStmt %type select_no_parens select_with_parens select_clause simple_select @@ -486,7 +487,8 @@ stmtmulti: stmtmulti ';' stmt ; stmt : - AlterDatabaseSetStmt + AlterDbOwnerStmt + | AlterDatabaseSetStmt | AlterDomainStmt | AlterGroupStmt | AlterSeqStmt @@ -3918,6 +3920,15 @@ opt_equal: '=' {} * *****************************************************************************/ +AlterDbOwnerStmt: ALTER DATABASE database_name OWNER TO UserId + { + AlterDbOwnerStmt *n = makeNode(AlterDbOwnerStmt); + n->dbname = $3; + n->uname = $6; + $$ = (Node *)n; + } + ; + AlterDatabaseSetStmt: ALTER DATABASE database_name SET set_rest { diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index fd9427c203d4f415978eb32f848625afe2452239..39b69c6248c2e6fb34eacaf49c9e8da99a22d37d 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.216 2004/05/26 04:41:35 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.217 2004/05/26 13:56:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -234,6 +234,7 @@ check_xact_readonly(Node *parsetree) switch (nodeTag(parsetree)) { case T_AlterDatabaseSetStmt: + case T_AlterDbOwnerStmt: case T_AlterDomainStmt: case T_AlterGroupStmt: case T_AlterSeqStmt: @@ -675,6 +676,13 @@ ProcessUtility(Node *parsetree, createdb((CreatedbStmt *) parsetree); break; + case T_AlterDbOwnerStmt: + { + AlterDbOwnerStmt *stmt = (AlterDbOwnerStmt *) parsetree; + AlterDatabaseOwner(stmt->dbname, stmt->uname); + } + break; + case T_AlterDatabaseSetStmt: AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree); break; @@ -1303,6 +1311,10 @@ CreateCommandTag(Node *parsetree) tag = "CREATE DATABASE"; break; + case T_AlterDbOwnerStmt: + tag = "ALTER DATABASE"; + break; + case T_AlterDatabaseSetStmt: tag = "ALTER DATABASE"; break; diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 2eb2f19f09f84c0ebba38d5913dcba49743e043d..f26c3e7533762dcb91a2c17c593a042535383dc4 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2003, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.106 2004/05/12 13:38:46 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.107 2004/05/26 13:56:55 momjian Exp $ */ /*---------------------------------------------------------------------- @@ -642,7 +642,7 @@ psql_completion(char *text, int start, int end) pg_strcasecmp(prev2_wd, "DATABASE") == 0) { static const char *const list_ALTERDATABASE[] = - {"RESET", "SET", "RENAME TO", NULL}; + {"RESET", "SET", "OWNER TO", "RENAME TO", NULL}; COMPLETE_WITH_LIST(list_ALTERDATABASE); } diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h index 6cb47f6772f23fbb367416b71c7ed173a5dd2e16..30b73d4daf1c585d7f2816e445081bce2922a7c4 100644 --- a/src/include/commands/dbcommands.h +++ b/src/include/commands/dbcommands.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.30 2003/11/29 22:40:59 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.31 2004/05/26 13:56:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ 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 void AlterDatabaseOwner(const char *dbname, const char *uname); extern Oid get_database_oid(const char *dbname); extern char *get_database_name(Oid dbid); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 6c37048229ab68b5479d3f58b8a46548f68a58e3..6feedf6762c9895fe75986355b1bcffe86f53379 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.155 2004/05/26 04:41:45 neilc Exp $ + * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.156 2004/05/26 13:57:02 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -266,6 +266,7 @@ typedef enum NodeTag T_ExecuteStmt, T_DeallocateStmt, T_DeclareCursorStmt, + T_AlterDbOwnerStmt, T_A_Expr = 800, T_ColumnRef, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 8eceb6e59cba3e9db547d4e4ff6831fb11e1593c..2943d0e9e08f762b4b8907950178fd3d65165bb4 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.255 2004/05/05 04:48:47 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.256 2004/05/26 13:57:02 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1523,6 +1523,13 @@ typedef struct CreatedbStmt * Alter Database * ---------------------- */ +typedef struct AlterDbOwnerStmt +{ + NodeTag type; + char *dbname; + char *uname; +} AlterDbOwnerStmt; + typedef struct AlterDatabaseSetStmt { NodeTag type; diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index d12576f80358bceea15bdc87c89086bc0879e43f..7656521adbd9b19971ae68eaafb763e6449832c8 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.283 2004/05/21 13:50:12 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.284 2004/05/26 13:57:04 momjian Exp $ */ /* Copyright comment */ %{ @@ -519,7 +519,6 @@ add_additional_variables(char *name, bool insert) %type CharacterWithoutLength BitWithLength BitWithoutLength %type ConstBit GenericType TableFuncElementList opt_analyze %type opt_sort_clause transaction_access_mode subquery_Op - %type ECPGWhenever ECPGConnect connection_target ECPGOpen %type indicator ECPGExecute ECPGPrepare ecpg_using ecpg_into %type storage_declaration storage_clause opt_initializer c_anything @@ -544,6 +543,7 @@ add_additional_variables(char *name, bool insert) %type inf_val_list inf_col_list using_descriptor into_descriptor %type ecpg_into_using prepared_name struct_union_type_with_symbol %type ECPGunreserved ECPGunreserved_interval cvariable +%type AlterDatabaseOwnerStmt %type s_struct_union_symbol @@ -594,6 +594,7 @@ opt_at: AT connection_target }; stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } + | AlterDatabaseOwnerStmt { output_statement($1, 0, connection); } | AlterDomainStmt { output_statement($1, 0, connection); } | AlterGroupStmt { output_statement($1, 0, connection); } | AlterSeqStmt { output_statement($1, 0, connection); } @@ -2535,6 +2536,8 @@ opt_equal: '=' { $$ = make_str("="); } * *****************************************************************************/ +AlterDatabaseOwnerStmt: ALTER DATABASE database_name OWNER TO UserId + { $$ = cat_str(4, make_str("alter database"), $3, make_str("owner to"), $6); } AlterDatabaseSetStmt: ALTER DATABASE database_name SET set_rest { $$ = cat_str(4, make_str("alter database"), $3, make_str("set"), $5); } | ALTER DATABASE database_name VariableResetStmt