aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/ref/create_database.sgml32
-rw-r--r--doc/src/sgml/release.sgml3
-rw-r--r--src/backend/commands/dbcommands.c33
-rw-r--r--src/backend/nodes/copyfuncs.c4
-rw-r--r--src/backend/nodes/equalfuncs.c4
-rw-r--r--src/backend/parser/gram.y34
-rw-r--r--src/backend/tcop/utility.c7
-rw-r--r--src/include/commands/dbcommands.h7
-rw-r--r--src/include/nodes/parsenodes.h3
9 files changed, 97 insertions, 30 deletions
diff --git a/doc/src/sgml/ref/create_database.sgml b/doc/src/sgml/ref/create_database.sgml
index b208f100eac..2c87d215914 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">
@@ -48,6 +49,16 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable>
</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>
<para>
@@ -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 fae659919de..edcdc9405aa 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 142fefb60fb..712df38ec51 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 153d257d26c..03ceb08eba2 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 886963f8808..2ea41d6e522 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 a23273c1a7d..37d9364eae8 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 766512ae59c..f80a6bdca44 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 23c68d3c350..0636130c2e1 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 252c509cc46..0b40fe99480 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) */