diff --git a/doc/src/sgml/ref/create_database.sgml b/doc/src/sgml/ref/create_database.sgml index b208f100eace36917ffdaa8582c020e23be506fc..2c87d215914b1497833918ebb7e33f0f9098a189 100644 --- a/doc/src/sgml/ref/create_database.sgml +++ b/doc/src/sgml/ref/create_database.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_database.sgml,v 1.23 2002/01/20 22:19:56 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_database.sgml,v 1.24 2002/02/24 20:20:18 tgl Exp $ PostgreSQL documentation --> @@ -24,9 +24,10 @@ PostgreSQL documentation </refsynopsisdivinfo> <synopsis> CREATE DATABASE <replaceable class="PARAMETER">name</replaceable> - [ WITH [ LOCATION = '<replaceable class="parameter">dbpath</replaceable>' ] - [ TEMPLATE = <replaceable class="parameter">template</replaceable> ] - [ ENCODING = <replaceable class="parameter">encoding</replaceable> ] ] + [ WITH [ OWNER [ = ] <replaceable class="parameter">dbowner</replaceable> ] + [ LOCATION [ = ] '<replaceable class="parameter">dbpath</replaceable>' ] + [ TEMPLATE [ = ] <replaceable class="parameter">template</replaceable> ] + [ ENCODING [ = ] <replaceable class="parameter">encoding</replaceable> ] ] </synopsis> <refsect2 id="R2-SQL-CREATEDATABASE-1"> @@ -47,6 +48,16 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable> </para> </listitem> </varlistentry> + <varlistentry> + <term><replaceable class="parameter">dbowner</replaceable></term> + <listitem> + <para> + Name of the database user who will own the new database, + or <literal>DEFAULT</literal> to use the default (namely, the + user executing the command). + </para> + </listitem> + </varlistentry> <varlistentry> <term><replaceable class="parameter">dbpath</replaceable></term> <listitem> @@ -171,7 +182,15 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable> <para> <command>CREATE DATABASE</command> creates a new <productname>PostgreSQL</productname> database. - The creator becomes the owner of the new database. + </para> + + <para> + Normally, the creator becomes the owner of the new database. + A different owner may be specified by using the <option>OWNER</> + clause (but only superusers may create databases on behalf of other users). + To create a database owned by oneself, either superuser privilege + or CREATEDB privilege is required. A superuser may create a database + for another user, even if that user has no special privileges himself. </para> <para> @@ -327,7 +346,8 @@ Type: \copyright for distribution terms </title> <para> There is no <command>CREATE DATABASE</command> statement in SQL92. - Databases are equivalent to catalogs whose creation is implementation-defined. + Databases are equivalent to catalogs, whose creation is + implementation-defined. </para> </refsect2> </refsect1> diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index fae659919de4cb44caf780163ceb0a11522de99d..edcdc9405aa42fa5733b3044bb5538b36b7fa9a0 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.117 2002/02/23 04:17:45 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.118 2002/02/24 20:20:19 tgl Exp $ --> <appendix id="release"> @@ -26,6 +26,7 @@ worries about funny characters. <literallayout><![CDATA[ Access privileges on functions Access privileges on procedural languages +CREATE DATABASE has OWNER option so superuser can create DB for someone else Kerberos 5 support now works with Heimdal ]]></literallayout> diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 142fefb60fb868636f272cc35776a1874ba39e7e..712df38ec51470e281feddbc60938f835452dad8 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.82 2002/02/23 20:55:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.83 2002/02/24 20:20:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,6 +34,7 @@ #include "storage/sinval.h" #include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" #ifdef MULTIBYTE @@ -55,8 +56,9 @@ static bool remove_dbdirs(const char *real_loc, const char *altloc); */ void -createdb(const char *dbname, const char *dbpath, - const char *dbtemplate, int encoding) +createdb(const char *dbname, const char *dbowner, + const char *dbpath, const char *dbtemplate, + int encoding) { char *nominal_loc; char *alt_loc; @@ -79,12 +81,31 @@ createdb(const char *dbname, const char *dbpath, Datum new_record[Natts_pg_database]; char new_record_nulls[Natts_pg_database]; Oid dboid; + int32 datdba; + /* obtain sysid of proposed owner */ + if (dbowner) + datdba = get_usesysid(dbowner); /* will elog if no such user */ + else + datdba = GetUserId(); + + /* check permission to create database */ if (!get_user_info(GetUserId(), &use_super, &use_createdb)) elog(ERROR, "current user name is invalid"); - if (!use_createdb && !use_super) - elog(ERROR, "CREATE DATABASE: permission denied"); + if (datdba == (int32) GetUserId()) + { + /* creating database for self: can be superuser or createdb */ + if (!use_createdb && !use_super) + elog(ERROR, "CREATE DATABASE: permission denied"); + } + else + { + /* creating database for someone else: must be superuser */ + /* note that the someone else need not have any permissions */ + if (!use_super) + elog(ERROR, "CREATE DATABASE: permission denied"); + } /* don't call this in a transaction block */ if (IsTransactionBlock()) @@ -254,7 +275,7 @@ createdb(const char *dbname, const char *dbpath, /* Form tuple */ new_record[Anum_pg_database_datname - 1] = DirectFunctionCall1(namein, CStringGetDatum(dbname)); - new_record[Anum_pg_database_datdba - 1] = Int32GetDatum(GetUserId()); + new_record[Anum_pg_database_datdba - 1] = Int32GetDatum(datdba); new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding); new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(false); new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(true); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 153d257d26c7e76950421523a0bf5d32f0f030eb..03ceb08eba2c6aded68543c4f4f3fd10b7c9cbe1 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.161 2002/02/18 23:11:14 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.162 2002/02/24 20:20:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2231,6 +2231,8 @@ _copyCreatedbStmt(CreatedbStmt *from) if (from->dbname) newnode->dbname = pstrdup(from->dbname); + if (from->dbowner) + newnode->dbowner = pstrdup(from->dbowner); if (from->dbpath) newnode->dbpath = pstrdup(from->dbpath); if (from->dbtemplate) diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 886963f8808a666910f81fc5c5f37b2480e39866..2ea41d6e522600cf7cf7690fa05a1d3a72f3ef90 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.109 2002/02/18 23:11:14 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.110 2002/02/24 20:20:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1099,6 +1099,8 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b) { if (!equalstr(a->dbname, b->dbname)) return false; + if (!equalstr(a->dbowner, b->dbowner)) + return false; if (!equalstr(a->dbpath, b->dbpath)) return false; if (!equalstr(a->dbtemplate, b->dbtemplate)) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index a23273c1a7d8440d26c8ae16d3f67b88428cdc01..37d9364eae8154dfa663bf576d07d7e828a71794 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.278 2002/02/18 23:11:17 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.279 2002/02/24 20:20:20 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -153,6 +153,7 @@ static void doNegateFloat(Value *v); %type <ival> drop_behavior %type <list> createdb_opt_list, createdb_opt_item +%type <boolean> opt_equal %type <ival> opt_lock, lock_type %type <boolean> opt_force, opt_or_replace @@ -733,6 +734,7 @@ CreateSchemaStmt: CREATE SCHEMA UserId /* for now, just make this the same as CREATE DATABASE */ CreatedbStmt *n = makeNode(CreatedbStmt); n->dbname = $3; + n->dbowner = NULL; n->dbpath = NULL; n->dbtemplate = NULL; n->encoding = -1; @@ -3049,6 +3051,7 @@ CreatedbStmt: CREATE DATABASE database_name WITH createdb_opt_list n->dbname = $3; /* set default options */ + n->dbowner = NULL; n->dbpath = NULL; n->dbtemplate = NULL; n->encoding = -1; @@ -3068,6 +3071,9 @@ CreatedbStmt: CREATE DATABASE database_name WITH createdb_opt_list case 3: n->encoding = lfirsti(lnext(optitem)); break; + case 4: + n->dbowner = (char *) lsecond(optitem); + break; } } $$ = (Node *)n; @@ -3076,6 +3082,7 @@ CreatedbStmt: CREATE DATABASE database_name WITH createdb_opt_list { CreatedbStmt *n = makeNode(CreatedbStmt); n->dbname = $3; + n->dbowner = NULL; n->dbpath = NULL; n->dbtemplate = NULL; n->encoding = -1; @@ -3093,23 +3100,23 @@ createdb_opt_list: createdb_opt_item * createdb_opt_item returns 2-element lists, with the first element * being an integer code to indicate which item was specified. */ -createdb_opt_item: LOCATION '=' Sconst +createdb_opt_item: LOCATION opt_equal Sconst { $$ = lconsi(1, makeList1($3)); } - | LOCATION '=' DEFAULT + | LOCATION opt_equal DEFAULT { $$ = lconsi(1, makeList1(NULL)); } - | TEMPLATE '=' name + | TEMPLATE opt_equal name { $$ = lconsi(2, makeList1($3)); } - | TEMPLATE '=' DEFAULT + | TEMPLATE opt_equal DEFAULT { $$ = lconsi(2, makeList1(NULL)); } - | ENCODING '=' Sconst + | ENCODING opt_equal Sconst { int encoding; #ifdef MULTIBYTE @@ -3123,7 +3130,7 @@ createdb_opt_item: LOCATION '=' Sconst #endif $$ = lconsi(3, makeListi1(encoding)); } - | ENCODING '=' Iconst + | ENCODING opt_equal Iconst { #ifdef MULTIBYTE if (!pg_get_enconv_by_encoding($3)) @@ -3134,12 +3141,23 @@ createdb_opt_item: LOCATION '=' Sconst #endif $$ = lconsi(3, makeListi1($3)); } - | ENCODING '=' DEFAULT + | ENCODING opt_equal DEFAULT { $$ = lconsi(3, makeListi1(-1)); } + | OWNER opt_equal name + { + $$ = lconsi(4, makeList1($3)); + } + | OWNER opt_equal DEFAULT + { + $$ = lconsi(4, makeList1(NULL)); + } ; +opt_equal: '=' { $$ = TRUE; } + | /*EMPTY*/ { $$ = FALSE; } + ; /***************************************************************************** * diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 766512ae59c96882a78c6dff62df6587fc7aa194..f80a6bdca44f75357e94f5be72a8ffb13c7efaa0 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.125 2002/02/07 00:27:30 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.126 2002/02/24 20:20:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -624,8 +624,9 @@ ProcessUtility(Node *parsetree, set_ps_display(commandTag = "CREATE DATABASE"); - createdb(stmt->dbname, stmt->dbpath, - stmt->dbtemplate, stmt->encoding); + createdb(stmt->dbname, stmt->dbowner, + stmt->dbpath, stmt->dbtemplate, + stmt->encoding); } break; diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h index 23c68d3c35054f29e56be90d1ae0a54dc3a8ca95..0636130c2e1c7fed6a4acf712910120a9c1ef4ba 100644 --- a/src/include/commands/dbcommands.h +++ b/src/include/commands/dbcommands.h @@ -7,15 +7,16 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: dbcommands.h,v 1.19 2001/11/05 17:46:33 momjian Exp $ + * $Id: dbcommands.h,v 1.20 2002/02/24 20:20:21 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef DBCOMMANDS_H #define DBCOMMANDS_H -extern void createdb(const char *dbname, const char *dbpath, - const char *dbtemplate, int encoding); +extern void createdb(const char *dbname, const char *dbowner, + const char *dbpath, const char *dbtemplate, + int encoding); extern void dropdb(const char *dbname); #endif /* DBCOMMANDS_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 252c509cc4620fc4e2efd8b2c2b355389ad36bdc..0b40fe99480f66f1a2ca1b8a8a53783855d01988 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.152 2002/02/18 23:11:41 petere Exp $ + * $Id: parsenodes.h,v 1.153 2002/02/24 20:20:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -679,6 +679,7 @@ typedef struct CreatedbStmt { NodeTag type; char *dbname; /* name of database to create */ + char *dbowner; /* name of owner (NULL = default) */ char *dbpath; /* location of database (NULL = default) */ char *dbtemplate; /* template to use (NULL = default) */ int encoding; /* MULTIBYTE encoding (-1 = use default) */