*** ./doc/src/sgml/ref/alter_database.sgml.orig 2004-03-28 16:10:19.000000000 -0300
--- ./doc/src/sgml/ref/alter_database.sgml 2004-03-28 16:56:27.000000000 -0300
***************
*** 23,28 ****
--- 23,30 ----
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,59 ****
--- 56,67 ----
be renamed. (Connect to a different database if you need to do
that.)
+
+
+ The fourth form changes the owner of the database. Only a superuser
+ can change the database's owner. The new owner does not need any
+ privilege.
+
*** ./src/backend/commands/dbcommands.c.orig 2004-03-28 16:10:36.000000000 -0300
--- ./src/backend/commands/dbcommands.c 2004-03-28 16:56:27.000000000 -0300
***************
*** 774,779 ****
--- 774,825 ----
}
+ /*
+ * 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
*** ./src/backend/nodes/copyfuncs.c.orig 2004-03-28 16:10:57.000000000 -0300
--- ./src/backend/nodes/copyfuncs.c 2004-03-29 23:04:18.000000000 -0300
***************
*** 2118,2123 ****
--- 2118,2134 ----
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)
{
***************
*** 2872,2877 ****
--- 2883,2891 ----
case T_CreatedbStmt:
retval = _copyCreatedbStmt(from);
break;
+ case T_AlterDbOwnerStmt:
+ retval = _copyAlterDbOwnerStmt(from);
+ break;
case T_AlterDatabaseSetStmt:
retval = _copyAlterDatabaseSetStmt(from);
break;
*** ./src/backend/nodes/equalfuncs.c.orig 2004-03-28 16:11:25.000000000 -0300
--- ./src/backend/nodes/equalfuncs.c 2004-03-29 23:05:06.000000000 -0300
***************
*** 1085,1090 ****
--- 1085,1099 ----
}
static bool
+ _equalAlterDbOwnerStmt(AlterDbOwnerStmt *a, AlterDbOwnerStmt *b)
+ {
+ COMPARE_STRING_FIELD(dbname);
+ COMPARE_STRING_FIELD(uname);
+
+ return true;
+ }
+
+ static bool
_equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
{
COMPARE_STRING_FIELD(dbname);
***************
*** 1945,1950 ****
--- 1954,1962 ----
case T_CreatedbStmt:
retval = _equalCreatedbStmt(a, b);
break;
+ case T_AlterDbOwnerStmt:
+ retval = _equalAlterDbOwnerStmt(a, b);
+ break;
case T_AlterDatabaseSetStmt:
retval = _equalAlterDatabaseSetStmt(a, b);
break;
*** ./src/backend/parser/gram.y.orig 2004-03-28 16:11:41.000000000 -0300
--- ./src/backend/parser/gram.y 2004-03-29 22:55:35.000000000 -0300
***************
*** 154,159 ****
--- 154,160 ----
VariableResetStmt VariableSetStmt VariableShowStmt
ViewStmt CheckPointStmt CreateConversionStmt
DeallocateStmt PrepareStmt ExecuteStmt
+ AlterDbOwnerStmt
%type select_no_parens select_with_parens select_clause
simple_select
***************
*** 483,489 ****
;
stmt :
! AlterDatabaseSetStmt
| AlterDomainStmt
| AlterGroupStmt
| AlterSeqStmt
--- 484,491 ----
;
stmt :
! AlterDbOwnerStmt
! | AlterDatabaseSetStmt
| AlterDomainStmt
| AlterGroupStmt
| AlterSeqStmt
***************
*** 3877,3882 ****
--- 3879,3893 ----
*
*****************************************************************************/
+ 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
{
*** ./src/backend/tcop/utility.c.orig 2004-03-28 16:11:59.000000000 -0300
--- ./src/backend/tcop/utility.c 2004-03-29 22:58:43.000000000 -0300
***************
*** 217,222 ****
--- 217,223 ----
switch (nodeTag(parsetree))
{
case T_AlterDatabaseSetStmt:
+ case T_AlterDbOwnerStmt:
case T_AlterDomainStmt:
case T_AlterGroupStmt:
case T_AlterSeqStmt:
***************
*** 775,780 ****
--- 776,788 ----
createdb((CreatedbStmt *) parsetree);
break;
+ case T_AlterDbOwnerStmt:
+ {
+ AlterDbOwnerStmt *stmt = (AlterDbOwnerStmt *) parsetree;
+ AlterDatabaseOwner(stmt->dbname, stmt->uname);
+ }
+ break;
+
case T_AlterDatabaseSetStmt:
AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
break;
***************
*** 1403,1408 ****
--- 1411,1420 ----
tag = "CREATE DATABASE";
break;
+ case T_AlterDbOwnerStmt:
+ tag = "ALTER DATABASE";
+ break;
+
case T_AlterDatabaseSetStmt:
tag = "ALTER DATABASE";
break;
*** ./src/bin/psql/tab-complete.c.orig 2004-03-28 16:12:48.000000000 -0300
--- ./src/bin/psql/tab-complete.c 2004-03-28 16:56:27.000000000 -0300
***************
*** 642,648 ****
strcasecmp(prev2_wd, "DATABASE") == 0)
{
static const char *const list_ALTERDATABASE[] =
! {"RESET", "SET", "RENAME TO", NULL};
COMPLETE_WITH_LIST(list_ALTERDATABASE);
}
--- 642,648 ----
strcasecmp(prev2_wd, "DATABASE") == 0)
{
static const char *const list_ALTERDATABASE[] =
! {"RESET", "SET", "OWNER TO", "RENAME TO", NULL};
COMPLETE_WITH_LIST(list_ALTERDATABASE);
}
*** ./src/include/commands/dbcommands.h.orig 2004-03-28 16:13:07.000000000 -0300
--- ./src/include/commands/dbcommands.h 2004-03-28 16:56:27.000000000 -0300
***************
*** 20,25 ****
--- 20,26 ----
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);
*** ./src/include/nodes/nodes.h.orig 2004-03-28 16:13:30.000000000 -0300
--- ./src/include/nodes/nodes.h 2004-03-29 23:00:46.000000000 -0300
***************
*** 260,265 ****
--- 260,266 ----
T_ExecuteStmt,
T_DeallocateStmt,
T_DeclareCursorStmt,
+ T_AlterDbOwnerStmt,
T_A_Expr = 800,
T_ColumnRef,
*** ./src/include/nodes/parsenodes.h.orig 2004-03-28 16:13:47.000000000 -0300
--- ./src/include/nodes/parsenodes.h 2004-03-29 23:02:26.000000000 -0300
***************
*** 1506,1511 ****
--- 1506,1518 ----
* Alter Database
* ----------------------
*/
+ typedef struct AlterDbOwnerStmt
+ {
+ NodeTag type;
+ char *dbname;
+ char *uname;
+ } AlterDbOwnerStmt;
+
typedef struct AlterDatabaseSetStmt
{
NodeTag type;
*** ./src/interfaces/ecpg/preproc/preproc.y.orig 2004-03-28 16:56:15.000000000 -0300
--- ./src/interfaces/ecpg/preproc/preproc.y 2004-03-29 22:17:00.000000000 -0300
***************
*** 516,522 ****
%type iso_level type_list CharacterWithLength ConstCharacter
%type CharacterWithoutLength BitWithLength BitWithoutLength
%type ConstBit GenericType TableFuncElementList opt_analyze
! %type opt_sort_clause transaction_access_mode
%type ECPGWhenever ECPGConnect connection_target ECPGOpen
%type indicator ECPGExecute ECPGPrepare ecpg_using ecpg_into
--- 516,522 ----
%type iso_level type_list CharacterWithLength ConstCharacter
%type CharacterWithoutLength BitWithLength BitWithoutLength
%type ConstBit GenericType TableFuncElementList opt_analyze
! %type opt_sort_clause transaction_access_mode AlterDatabaseOwnerStmt
%type ECPGWhenever ECPGConnect connection_target ECPGOpen
%type indicator ECPGExecute ECPGPrepare ecpg_using ecpg_into
***************
*** 592,597 ****
--- 592,598 ----
};
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); }
***************
*** 2495,2500 ****
--- 2496,2503 ----
*
*****************************************************************************/
+ 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