OSDN Git Service

Add OWNER option to CREATE DATABASE, so superusers can create databases
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 24 Feb 2002 20:20:21 +0000 (20:20 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 24 Feb 2002 20:20:21 +0000 (20:20 +0000)
on behalf of unprivileged users.  Also, make '=' optional in CREATE
DATABASE syntax.  From Gavin Sherry, with kibitzing and docs by Tom Lane.

doc/src/sgml/ref/create_database.sgml
doc/src/sgml/release.sgml
src/backend/commands/dbcommands.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/include/commands/dbcommands.h
src/include/nodes/parsenodes.h

index b208f10..2c87d21 100644 (file)
@@ -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>
index fae6599..edcdc94 100644 (file)
@@ -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>
 
index 142fefb..712df38 100644 (file)
@@ -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);
index 153d257..03ceb08 100644 (file)
@@ -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)
index 886963f..2ea41d6 100644 (file)
@@ -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))
index a23273c..37d9364 100644 (file)
@@ -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; }
+               ;
 
 /*****************************************************************************
  *
index 766512a..f80a6bd 100644 (file)
@@ -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;
 
index 23c68d3..0636130 100644 (file)
@@ -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 */
index 252c509..0b40fe9 100644 (file)
@@ -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) */