mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04: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:
		
							parent
							
								
									f66f7a542f
								
							
						
					
					
						commit
						a833c441fd
					
				| @ -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> | ||||
|  | ||||
| @ -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> | ||||
| 
 | ||||
|  | ||||
| @ -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 (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); | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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)) | ||||
|  | ||||
| @ -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; } | ||||
| 		; | ||||
| 
 | ||||
| /***************************************************************************** | ||||
|  * | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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) */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user