diff -Nrpc base/src/backend/catalog/namespace.c pgsec/src/backend/catalog/namespace.c
*** base/src/backend/catalog/namespace.c	Mon Nov  9 18:42:41 2009
--- pgsec/src/backend/catalog/namespace.c	Sat Dec 19 04:26:37 2009
*************** LookupExplicitNamespace(const char *nspn
*** 2366,2375 ****
  
  /*
   * LookupCreationNamespace
!  *		Look up the schema and verify we have CREATE rights on it.
   *
!  * This is just like LookupExplicitNamespace except for the different
!  * permission check, and that we are willing to create pg_temp if needed.
   *
   * Note: calling this may result in a CommandCounterIncrement operation,
   * if we have to create or clean out the temp namespace.
--- 2366,2375 ----
  
  /*
   * LookupCreationNamespace
!  *		Look up the schema on which caller tries to create an object
   *
!  * This is just like LookupExplicitNamespace except for we are willing
!  * to create pg_temp if needed.
   *
   * Note: calling this may result in a CommandCounterIncrement operation,
   * if we have to create or clean out the temp namespace.
*************** LookupCreationNamespace(const char *nspn
*** 2397,2407 ****
  				(errcode(ERRCODE_UNDEFINED_SCHEMA),
  				 errmsg("schema \"%s\" does not exist", nspname)));
  
- 	aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
- 	if (aclresult != ACLCHECK_OK)
- 		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
- 					   nspname);
- 
  	return namespaceId;
  }
  
--- 2397,2402 ----
diff -Nrpc base/src/backend/commands/dbcommands.c pgsec/src/backend/commands/dbcommands.c
*** base/src/backend/commands/dbcommands.c	Thu Nov 12 23:28:17 2009
--- pgsec/src/backend/commands/dbcommands.c	Sat Dec 19 04:10:11 2009
*************** createdb(const CreatedbStmt *stmt)
*** 103,109 ****
  	Oid			src_lastsysoid;
  	TransactionId src_frozenxid;
  	Oid			src_deftablespace;
! 	volatile Oid dst_deftablespace;
  	Relation	pg_database_rel;
  	HeapTuple	tuple;
  	Datum		new_record[Natts_pg_database];
--- 103,109 ----
  	Oid			src_lastsysoid;
  	TransactionId src_frozenxid;
  	Oid			src_deftablespace;
! 	volatile Oid dst_deftablespace = InvalidOid;
  	Relation	pg_database_rel;
  	HeapTuple	tuple;
  	Datum		new_record[Natts_pg_database];
*************** createdb(const CreatedbStmt *stmt)
*** 204,209 ****
--- 204,221 ----
  				 defel->defname);
  	}
  
+ 	if (dtablespacename && dtablespacename->arg)
+ 	{
+ 		char	   *tablespacename;
+ 
+ 		tablespacename = strVal(dtablespacename->arg);
+ 		dst_deftablespace = get_tablespace_oid(tablespacename);
+ 		if (!OidIsValid(dst_deftablespace))
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_UNDEFINED_OBJECT),
+ 					 errmsg("tablespace \"%s\" does not exist",
+ 							tablespacename)));
+ 	}
  	if (downer && downer->arg)
  		dbowner = strVal(downer->arg);
  	if (dtemplate && dtemplate->arg)
*************** createdb(const CreatedbStmt *stmt)
*** 258,277 ****
  		datdba = GetUserId();
  
  	/*
- 	 * To create a database, must have createdb privilege and must be able to
- 	 * become the target role (this does not imply that the target role itself
- 	 * must have createdb privilege).  The latter provision guards against
- 	 * "giveaway" attacks.	Note that a superuser will always have both of
- 	 * these privileges a fortiori.
- 	 */
- 	if (!have_createdb_privilege())
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 				 errmsg("permission denied to create database")));
- 
- 	check_is_member_of_role(GetUserId(), datdba);
- 
- 	/*
  	 * Lookup database (template) to be cloned, and obtain share lock on it.
  	 * ShareLock allows two CREATE DATABASEs to work from the same template
  	 * concurrently, while ensuring no one is busy dropping it in parallel
--- 270,275 ----
*************** createdb(const CreatedbStmt *stmt)
*** 294,299 ****
--- 292,311 ----
  						dbtemplate)));
  
  	/*
+ 	 * To create a database, must have createdb privilege and must be able to
+ 	 * become the target role (this does not imply that the target role itself
+ 	 * must have createdb privilege).  The latter provision guards against
+ 	 * "giveaway" attacks.	Note that a superuser will always have both of
+ 	 * these privileges a fortiori.
+ 	 */
+ 	if (!have_createdb_privilege())
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 				 errmsg("permission denied to create database")));
+ 
+ 	check_is_member_of_role(GetUserId(), datdba);
+ 
+ 	/*
  	 * Permission check: to copy a DB that's not marked datistemplate, you
  	 * must be superuser or the owner thereof.
  	 */
*************** createdb(const CreatedbStmt *stmt)
*** 306,311 ****
--- 318,338 ----
  							dbtemplate)));
  	}
  
+ 	/*
+ 	 * Permission check: to create object under explicitly given
+ 	 * tablespace, instead of the copied one from the source database
+ 	 */
+ 	if (OidIsValid(dst_deftablespace))
+ 	{
+ 		AclResult	aclresult;
+ 
+ 		aclresult = pg_tablespace_aclcheck(dst_deftablespace, GetUserId(),
+ 										   ACL_CREATE);
+ 		if (aclresult != ACLCHECK_OK)
+ 			aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
+ 						   get_tablespace_name(dst_deftablespace));
+ 	}
+ 
  	/* If encoding or locales are defaulted, use source's setting */
  	if (encoding < 0)
  		encoding = src_encoding;
*************** createdb(const CreatedbStmt *stmt)
*** 421,445 ****
  	}
  
  	/* Resolve default tablespace for new database */
! 	if (dtablespacename && dtablespacename->arg)
  	{
- 		char	   *tablespacename;
- 		AclResult	aclresult;
- 
- 		tablespacename = strVal(dtablespacename->arg);
- 		dst_deftablespace = get_tablespace_oid(tablespacename);
- 		if (!OidIsValid(dst_deftablespace))
- 			ereport(ERROR,
- 					(errcode(ERRCODE_UNDEFINED_OBJECT),
- 					 errmsg("tablespace \"%s\" does not exist",
- 							tablespacename)));
- 		/* check permissions */
- 		aclresult = pg_tablespace_aclcheck(dst_deftablespace, GetUserId(),
- 										   ACL_CREATE);
- 		if (aclresult != ACLCHECK_OK)
- 			aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
- 						   tablespacename);
- 
  		/* pg_global must never be the default tablespace */
  		if (dst_deftablespace == GLOBALTABLESPACE_OID)
  			ereport(ERROR,
--- 448,455 ----
  	}
  
  	/* Resolve default tablespace for new database */
! 	if (OidIsValid(dst_deftablespace))
  	{
  		/* pg_global must never be the default tablespace */
  		if (dst_deftablespace == GLOBALTABLESPACE_OID)
  			ereport(ERROR,
*************** createdb(const CreatedbStmt *stmt)
*** 471,477 ****
  				ereport(ERROR,
  						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  						 errmsg("cannot assign new default tablespace \"%s\"",
! 								tablespacename),
  						 errdetail("There is a conflict because database \"%s\" already has some tables in this tablespace.",
  								   dbtemplate)));
  			pfree(srcpath);
--- 481,487 ----
  				ereport(ERROR,
  						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  						 errmsg("cannot assign new default tablespace \"%s\"",
! 								get_tablespace_name(dst_deftablespace)),
  						 errdetail("There is a conflict because database \"%s\" already has some tables in this tablespace.",
  								   dbtemplate)));
  			pfree(srcpath);
*************** movedb(const char *dbname, const char *t
*** 1015,1027 ****
  							   AccessExclusiveLock);
  
  	/*
- 	 * Permission checks
- 	 */
- 	if (!pg_database_ownercheck(db_id, GetUserId()))
- 		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
- 					   dbname);
- 
- 	/*
  	 * Obviously can't move the tables of my own database
  	 */
  	if (db_id == MyDatabaseId)
--- 1025,1030 ----
*************** movedb(const char *dbname, const char *t
*** 1041,1046 ****
--- 1044,1053 ----
  	/*
  	 * Permission checks
  	 */
+ 	if (!pg_database_ownercheck(db_id, GetUserId()))
+ 		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
+ 					   dbname);
+ 
  	aclresult = pg_tablespace_aclcheck(dst_tblspcoid, GetUserId(),
  									   ACL_CREATE);
  	if (aclresult != ACLCHECK_OK)
diff -Nrpc base/src/backend/commands/functioncmds.c pgsec/src/backend/commands/functioncmds.c
*** base/src/backend/commands/functioncmds.c	Mon Nov  9 18:42:41 2009
--- pgsec/src/backend/commands/functioncmds.c	Sat Dec 19 04:42:09 2009
*************** AlterFunctionNamespace(List *name, List 
*** 1874,1879 ****
--- 1874,1880 ----
  	HeapTuple	tup;
  	Relation	procRel;
  	Form_pg_proc proc;
+ 	AclResult	aclresult;
  
  	procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
  
*************** AlterFunctionNamespace(List *name, List 
*** 1897,1903 ****
  
  	oldNspOid = proc->pronamespace;
  
! 	/* get schema OID and check its permissions */
  	nspOid = LookupCreationNamespace(newschema);
  
  	if (oldNspOid == nspOid)
--- 1898,1904 ----
  
  	oldNspOid = proc->pronamespace;
  
! 	/* get schema OID */
  	nspOid = LookupCreationNamespace(newschema);
  
  	if (oldNspOid == nspOid)
*************** AlterFunctionNamespace(List *name, List 
*** 1907,1912 ****
--- 1908,1921 ----
  						NameListToString(name),
  						newschema)));
  
+ 	/*
+ 	 * check permissions on schema
+ 	 * XXX - to be consolidated with pg_proc_ownercheck() later
+ 	 */
+ 	aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
+ 	if (aclresult != ACLCHECK_OK)
+ 		aclcheck_error(aclresult, ACL_KIND_NAMESPACE, newschema);
+ 
  	/* disallow renaming into or out of temp schemas */
  	if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
  		ereport(ERROR,
diff -Nrpc base/src/backend/commands/tablecmds.c pgsec/src/backend/commands/tablecmds.c
*** base/src/backend/commands/tablecmds.c	Fri Dec 11 14:58:31 2009
--- pgsec/src/backend/commands/tablecmds.c	Sat Dec 19 04:42:26 2009
*************** AlterTableNamespace(RangeVar *relation, 
*** 7780,7785 ****
--- 7780,7786 ----
  	Oid			oldNspOid;
  	Oid			nspOid;
  	Relation	classRel;
+ 	AclResult	aclresult;
  
  	rel = relation_openrv(relation, AccessExclusiveLock);
  
*************** AlterTableNamespace(RangeVar *relation, 
*** 7856,7862 ****
  							RelationGetRelationName(rel))));
  	}
  
! 	/* get schema OID and check its permissions */
  	nspOid = LookupCreationNamespace(newschema);
  
  	if (oldNspOid == nspOid)
--- 7857,7863 ----
  							RelationGetRelationName(rel))));
  	}
  
! 	/* get schema OID */
  	nspOid = LookupCreationNamespace(newschema);
  
  	if (oldNspOid == nspOid)
*************** AlterTableNamespace(RangeVar *relation, 
*** 7866,7871 ****
--- 7867,7880 ----
  						RelationGetRelationName(rel),
  						newschema)));
  
+ 	/*
+ 	 * permission check on schema
+ 	 * XXX - to be consolidated with pg_class_ownercheck() later	 
+ 	 */
+ 	aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
+ 	if (aclresult != ACLCHECK_OK)
+ 		aclcheck_error(aclresult, ACL_KIND_NAMESPACE, newschema);
+ 
  	/* disallow renaming into or out of temp schemas */
  	if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
  		ereport(ERROR,
diff -Nrpc base/src/backend/commands/typecmds.c pgsec/src/backend/commands/typecmds.c
*** base/src/backend/commands/typecmds.c	Fri Dec 11 14:58:31 2009
--- pgsec/src/backend/commands/typecmds.c	Sat Dec 19 04:57:11 2009
*************** AlterTypeNamespace(List *names, const ch
*** 2690,2695 ****
--- 2690,2696 ----
  	Oid			typeOid;
  	Oid			nspOid;
  	Oid			elemOid;
+ 	AclResult	aclresult;
  
  	/* Make a TypeName so we can use standard type lookup machinery */
  	typename = makeTypeNameFromNameList(names);
*************** AlterTypeNamespace(List *names, const ch
*** 2700,2708 ****
  		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
  					   format_type_be(typeOid));
  
! 	/* get schema OID and check its permissions */
  	nspOid = LookupCreationNamespace(newschema);
  
  	/* don't allow direct alteration of array types */
  	elemOid = get_element_type(typeOid);
  	if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid)
--- 2701,2717 ----
  		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
  					   format_type_be(typeOid));
  
! 	/* get schema OID */
  	nspOid = LookupCreationNamespace(newschema);
  
+ 	/*
+ 	 * permission checks on schema
+ 	 * XXX - to be consolidated with pg_type_ownercheck() later
+ 	 */
+ 	aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
+ 	if (aclresult != ACLCHECK_OK)
+ 		aclcheck_error(aclresult, ACL_KIND_NAMESPACE, newschema);
+ 
  	/* don't allow direct alteration of array types */
  	elemOid = get_element_type(typeOid);
  	if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid)
