1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

Add OWNER option to CREATE DATABASE, so superusers can create databases

on behalf of unprivileged users.  Also, make '=' optional in CREATE
DATABASE syntax.  From Gavin Sherry, with kibitzing and docs by Tom Lane.
This commit is contained in:
Tom Lane
2002-02-24 20:20:21 +00:00
parent f66f7a542f
commit a833c441fd
9 changed files with 97 additions and 30 deletions

View 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);

View 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)

View 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))

View 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; }
;
/*****************************************************************************
*

View 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;