*** a/doc/src/sgml/ref/alter_database.sgml
--- b/doc/src/sgml/ref/alter_database.sgml
***************
*** 28,33 **** ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <rep
--- 28,34 ----
      ALLOW_CONNECTIONS <replaceable class="PARAMETER">allowconn</replaceable>
      CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
      IS_TEMPLATE <replaceable class="PARAMETER">istemplate</replaceable>
+     CATALOG SECURITY <replaceable class="PARAMETER">catalog_security</replaceable>
  
  ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
  
***************
*** 139,144 **** ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RESET ALL
--- 140,157 ----
          </para>
         </listitem>
        </varlistentry>
+       
+      <varlistentry>
+        <term><replaceable class="parameter">catalog_security</replaceable></term>
+        <listitem>
+         <para>
+          If true, the row level security policies on system catalog tables are
+          applied to this database. These policies are used to provide multi-tenancy
+          under that database. If false, all the policies that are present on the
+          database are removed.
+         </para>
+        </listitem>
+      </varlistentry>
  
     <varlistentry>
      <term><replaceable>new_name</replaceable></term>
***************
*** 203,208 **** ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RESET ALL
--- 216,227 ----
     Role-specific settings override database-specific
     ones if there is a conflict.
    </para>
+   
+   <para>
+    The catalog_security option is not supported at <xref linkend="sql-createdatabase">
+    command. This is because of the limitation of creating row level security policies.
+    The policies can only be created on that database that is connected by the session.
+   </para>
   </refsect1>
  
   <refsect1>
*** a/src/backend/commands/dbcommands.c
--- b/src/backend/commands/dbcommands.c
***************
*** 42,47 ****
--- 42,48 ----
  #include "commands/dbcommands.h"
  #include "commands/dbcommands_xlog.h"
  #include "commands/defrem.h"
+ #include "commands/policy.h"
  #include "commands/seclabel.h"
  #include "commands/tablespace.h"
  #include "mb/pg_wchar.h"
***************
*** 226,231 **** createdb(const CreatedbStmt *stmt)
--- 227,239 ----
  					 errmsg("LOCATION is not supported anymore"),
  					 errhint("Consider using tablespaces instead.")));
  		}
+ 		else if (strcmp(defel->defname, "catalog_security") == 0)
+ 		{
+ 			ereport(ERROR,
+                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                     errmsg("catalog security is not supported with create database command."),
+                     errdetail("Enable catalog security using Alter database command.")));
+ 		}
  		else
  			ereport(ERROR,
  					(errcode(ERRCODE_SYNTAX_ERROR),
***************
*** 519,524 **** createdb(const CreatedbStmt *stmt)
--- 527,533 ----
  	new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid);
  	new_record[Anum_pg_database_datminmxid - 1] = TransactionIdGetDatum(src_minmxid);
  	new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace);
+ 	new_record[Anum_pg_database_datcatalogsecurity - 1] = BoolGetDatum(false);
  
  	/*
  	 * We deliberately set datacl to default (NULL), rather than copying it
***************
*** 1375,1385 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1384,1397 ----
  	ListCell   *option;
  	bool		dbistemplate = false;
  	bool		dballowconnections = true;
+ 	bool		dbcatalogsecurity = false;
  	int			dbconnlimit = -1;
  	DefElem    *distemplate = NULL;
  	DefElem    *dallowconnections = NULL;
  	DefElem    *dconnlimit = NULL;
  	DefElem    *dtablespace = NULL;
+ 	DefElem    *dcatalogsecurity = NULL;
+ 	Form_pg_database pg_database_tuple;
  	Datum		new_record[Natts_pg_database];
  	bool		new_record_nulls[Natts_pg_database];
  	bool		new_record_repl[Natts_pg_database];
***************
*** 1421,1426 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1433,1447 ----
  						 errmsg("conflicting or redundant options")));
  			dtablespace = defel;
  		}
+ 		else if (strcmp(defel->defname, "catalog_security") == 0)
+ 		{
+ 			if (dcatalogsecurity)
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_SYNTAX_ERROR),
+ 						errmsg("conflicting or redundant options")));
+ 
+ 			dcatalogsecurity = defel;
+ 		}
  		else
  			ereport(ERROR,
  					(errcode(ERRCODE_SYNTAX_ERROR),
***************
*** 1457,1462 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1478,1485 ----
  					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  					 errmsg("invalid connection limit: %d", dbconnlimit)));
  	}
+ 	if (dcatalogsecurity && dcatalogsecurity->arg)
+ 		dbcatalogsecurity = defGetBoolean(dcatalogsecurity);
  
  	/*
  	 * Get the old tuple.  We don't need a lock on the database per se,
***************
*** 1476,1487 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1499,1517 ----
  				(errcode(ERRCODE_UNDEFINED_DATABASE),
  				 errmsg("database \"%s\" does not exist", stmt->dbname)));
  
+ 	pg_database_tuple = (Form_pg_database)GETSTRUCT(tuple);
  	dboid = HeapTupleGetOid(tuple);
  
  	if (!pg_database_ownercheck(HeapTupleGetOid(tuple), GetUserId()))
  		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
  					   stmt->dbname);
  
+ 	if (dcatalogsecurity && (dboid != MyDatabaseId))
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 				errmsg("Enabling/disabling catalog security can be done"
+ 						" only to the connected database \"%s\"", stmt->dbname)));
+ 
  	/*
  	 * In order to avoid getting locked out and having to go through
  	 * standalone mode, we refuse to disallow connections to the database
***************
*** 1493,1498 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1523,1539 ----
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  				 errmsg("cannot disallow connections for current database")));
  
+ 	if (dcatalogsecurity && BoolGetDatum(dbcatalogsecurity) && !pg_database_tuple->datcatalogsecurity)
+ 	{
+ 		CreateCatalogPolicy();
+ 		CommandCounterIncrement();
+ 	}
+ 	else if (pg_database_tuple->datcatalogsecurity)
+ 	{
+ 		RemoveCatalogPolicy();
+ 		CommandCounterIncrement();
+ 	}
+ 
  	/*
  	 * Build an updated tuple, perusing the information just obtained
  	 */
***************
*** 1515,1520 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1556,1566 ----
  		new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
  		new_record_repl[Anum_pg_database_datconnlimit - 1] = true;
  	}
+ 	if (dcatalogsecurity)
+ 	{
+ 		new_record[Anum_pg_database_datcatalogsecurity - 1] = BoolGetDatum(dbcatalogsecurity);
+ 		new_record_repl[Anum_pg_database_datcatalogsecurity - 1] = true;
+ 	}
  
  	newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), new_record,
  								 new_record_nulls, new_record_repl);
*** a/src/backend/commands/policy.c
--- b/src/backend/commands/policy.c
***************
*** 22,31 ****
--- 22,75 ----
  #include "catalog/indexing.h"
  #include "catalog/namespace.h"
  #include "catalog/objectaccess.h"
+ #include "catalog/pg_aggregate.h"
+ #include "catalog/pg_am.h"
+ #include "catalog/pg_amop.h"
+ #include "catalog/pg_amproc.h"
+ #include "catalog/pg_attrdef.h"
+ #include "catalog/pg_attribute.h"
  #include "catalog/pg_authid.h"
+ #include "catalog/pg_cast.h"
+ #include "catalog/pg_class.h"
+ #include "catalog/pg_collation.h"
+ #include "catalog/pg_constraint.h"
+ #include "catalog/pg_conversion.h"
+ #include "catalog/pg_db_role_setting.h"
+ #include "catalog/pg_default_acl.h"
+ #include "catalog/pg_depend.h"
+ #include "catalog/pg_description.h"
+ #include "catalog/pg_enum.h"
+ #include "catalog/pg_event_trigger.h"
+ #include "catalog/pg_extension.h"
+ #include "catalog/pg_foreign_data_wrapper.h"
+ #include "catalog/pg_foreign_server.h"
+ #include "catalog/pg_foreign_table.h"
+ #include "catalog/pg_index.h"
+ #include "catalog/pg_inherits.h"
+ #include "catalog/pg_language.h"
+ #include "catalog/pg_largeobject.h"
+ #include "catalog/pg_largeobject_metadata.h"
+ #include "catalog/pg_namespace.h"
+ #include "catalog/pg_opclass.h"
+ #include "catalog/pg_operator.h"
+ #include "catalog/pg_opfamily.h"
  #include "catalog/pg_policy.h"
+ #include "catalog/pg_proc.h"
+ #include "catalog/pg_range.h"
+ #include "catalog/pg_rewrite.h"
+ #include "catalog/pg_seclabel.h"
+ #include "catalog/pg_statistic.h"
+ #include "catalog/pg_transform.h"
+ #include "catalog/pg_trigger.h"
+ #include "catalog/pg_ts_config.h"
+ #include "catalog/pg_ts_config_map.h"
+ #include "catalog/pg_ts_dict.h"
+ #include "catalog/pg_ts_parser.h"
+ #include "catalog/pg_ts_template.h"
  #include "catalog/pg_type.h"
+ #include "catalog/pg_user_mapping.h"
  #include "commands/policy.h"
+ #include "executor/spi.h"
  #include "miscadmin.h"
  #include "nodes/makefuncs.h"
  #include "nodes/pg_list.h"
***************
*** 44,56 ****
--- 88,109 ----
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
  #include "utils/rel.h"
+ #include "utils/snapmgr.h"
  #include "utils/syscache.h"
  
+ #define CATALOG_POLICY_STRING_SIZE 65535
+ 
  static void RangeVarCallbackForPolicy(const RangeVar *rv,
  						  Oid relid, Oid oldrelid, void *arg);
  static char parse_policy_command(const char *cmd_name);
  static Datum *policy_role_list_to_array(List *roles, int *num_roles);
  
+ static bool generate_catalog_create_policy_string(HeapTuple cache_tuple, char *buf);
+ static bool generate_catalog_drop_policy_string(HeapTuple cache_tuple, char *buf);
+ 
+ /* variable to identify whether pg_policy relcache is built is in progress or not? */
+ bool policyRelcacheBuiltInProgress = false;
+ 
  /*
   * Callback to RangeVarGetRelidExtended().
   *
***************
*** 195,200 **** RelationBuildRowSecurity(Relation relation)
--- 248,263 ----
  	RowSecurityDesc *volatile rsdesc = NULL;
  
  	/*
+ 	 * Build the row security descriptor of a relation, once all
+ 	 * the critical relations are built.
+ 	 */
+ 	if (!criticalRelcachesBuilt || !criticalSharedRelcachesBuilt)
+ 		return;
+ 
+ 	if (relation->rd_id == PolicyRelationId && policyRelcacheBuiltInProgress)
+ 		return;
+ 
+ 	/*
  	 * Create a memory context to hold everything associated with this
  	 * relation's row security policy.  This makes it easy to clean up during
  	 * a relcache flush.
***************
*** 216,221 **** RelationBuildRowSecurity(Relation relation)
--- 279,290 ----
  		SysScanDesc sscan;
  		HeapTuple	tuple;
  
+ 		if (relation->rd_id == PolicyRelationId)
+ 		{
+ 			Assert(policyRelcacheBuiltInProgress == false);
+ 			policyRelcacheBuiltInProgress = true;
+ 		}
+ 
  		rsdesc = MemoryContextAllocZero(rscxt, sizeof(RowSecurityDesc));
  		rsdesc->rscxt = rscxt;
  
***************
*** 325,334 **** RelationBuildRowSecurity(Relation relation)
--- 394,416 ----
  		/* Delete rscxt, first making sure it isn't active */
  		MemoryContextSwitchTo(oldcxt);
  		MemoryContextDelete(rscxt);
+ 		
+ 		if (relation->rd_id == PolicyRelationId)
+ 		{
+ 			Assert(policyRelcacheBuiltInProgress == true);
+ 			policyRelcacheBuiltInProgress = false;
+ 		}
+ 
  		PG_RE_THROW();
  	}
  	PG_END_TRY();
  
+ 	if (relation->rd_id == PolicyRelationId)
+ 	{
+ 		Assert(policyRelcacheBuiltInProgress == true);
+ 		policyRelcacheBuiltInProgress = false;
+ 	}
+ 
  	/* Success --- attach the policy descriptor to the relcache entry */
  	relation->rd_rsdesc = rsdesc;
  }
***************
*** 407,412 **** RemovePolicyById(Oid policy_id)
--- 489,1041 ----
  	heap_close(pg_policy_rel, RowExclusiveLock);
  }
  
+ static bool 
+ generate_catalog_create_policy_string(HeapTuple tuple, char *buf)
+ {
+ 	bool can_create_policy = false;
+ 	Form_pg_class pg_class_tuple;
+ 	Oid	relationid;
+ 
+ 	pg_class_tuple = (Form_pg_class)GETSTRUCT(tuple);
+ 	relationid = HeapTupleGetOid(tuple);
+ 
+ 	if (IsSharedRelation(relationid))
+ 		return can_create_policy;
+ 
+ 	switch (relationid)
+ 	{
+ 		/*
+ 		 * Following catalog tables data is accessible to all roles. 
+ 		 * So they doesn't need any speicific RLS policies on them.
+ 		 */ 
+ 		case AggregateRelationId:
+ 		case AccessMethodRelationId:
+ 		case AccessMethodOperatorRelationId:
+ 		case AccessMethodProcedureRelationId:
+ 			break;
+ 		case AttrDefaultRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" (has_column_privilege(adrelid, adnum,'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case AttributeRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" (has_column_privilege(attrelid, attnum,'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case CastRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_cast_privilege(oid, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case RelationRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_table_privilege(oid,'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case CollationRelationId:
+ 			/*sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR (pg_get_userbyid(collowner) = current_user))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;*/
+ 			break;
+ 		case ConstraintRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_constraint_privilege(oid,'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case ConversionRelationId:
+ 			/*sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR (pg_get_userbyid(conowner) = current_user))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;*/
+ 			break;
+ 		case DefaultAclRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" (pg_get_userbyid(defaclrole) = current_user)",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case DependRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((classid = (select oid from pg_class where relname = 'pg_aggregate'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_cast') AND has_cast_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_collation'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_attribute') AND has_column_privilege(objid, objsubid::smallint, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_constraint') AND has_constraint_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_conversion'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_type') AND has_type_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_extension'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_event_trigger'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_foreign_data_wrapper') AND has_foreign_data_wrapper_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_class') AND has_table_privilege(objid,'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_proc') AND has_function_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_am'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_amop'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_amproc'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_attdef') AND has_column_default_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_language') AND has_language_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_largeobject'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_opclass'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_operator'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_opfamily'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_enum'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_event_trigger'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_extension'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_policy') AND has_policy_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_rewrite'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_namespace') AND has_schema_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_foreign_server') AND has_server_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_tablespace') AND has_tablespace_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_ts_dict'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_ts_parser'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_ts_config'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_ts_template'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_transform'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_trigger') AND has_trigger_privilege(objid, 'any'))"
+ 				" OR (classid = (select oid from pg_class where relname = 'pg_user_mapping') AND has_user_mapping_privilege(objid, 'any')))", 
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case DescriptionRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((classoid = (select oid from pg_class where relname = 'pg_aggregate'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_cast') AND has_cast_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_collation'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_attribute') AND has_column_privilege(objoid, objsubid::smallint, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_constraint') AND has_constraint_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_conversion'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_type') AND has_type_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_extension'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_event_trigger'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_foreign_data_wrapper') AND has_foreign_data_wrapper_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_class') AND has_table_privilege(objoid,'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_proc') AND has_function_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_largeobject'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_opclass'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_operator'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_opfamily'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_largeobject_metadata'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_policy') AND has_policy_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_rewrite'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_namespace') AND has_schema_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_foreign_server') AND has_server_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_tablespace') AND has_tablespace_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_range'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_ts_dict'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_ts_parser'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_ts_config'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_ts_template'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_transform'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_trigger') AND has_trigger_privilege(objoid, 'any')))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case EnumRelationId:
+ 			break;
+ 		case EventTriggerRelationId:
+ 			break;
+ 		case ExtensionRelationId:
+ 			break;
+ 		case ForeignDataWrapperRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_foreign_data_wrapper_privilege(oid,'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case ForeignServerRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_server_privilege(oid,'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case ForeignTableRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" (has_table_privilege(ftrelid, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case IndexRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" (has_table_privilege(indrelid, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case InheritsRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" (has_table_privilege(inhrelid, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case LanguageRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_language_privilege(oid, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case LargeObjectRelationId:
+ 			break;
+ 		case LargeObjectMetadataRelationId:
+ 			break;
+ 		case NamespaceRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_schema_privilege(oid, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case OperatorClassRelationId:
+ 			/*sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR (pg_get_userbyid(opcowner) = current_user))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;*/
+ 			break;
+ 		case OperatorRelationId:
+ 			/*sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR (pg_get_userbyid(oprowner) = current_user))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;*/
+ 			break;
+ 		case OperatorFamilyRelationId:
+ 			/*sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR (pg_get_userbyid(opfowner) = current_user))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;*/
+ 			break;
+ 		case PolicyRelationId:
+ 			/*
+ 			 * Only user with bypass rls or owner of the table can view the
+ 			 * policies on the table, unless the forcesecurity is specified
+ 			 * for the owners also.
+ 			 */
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" (false)",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case ProcedureRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_function_privilege(oid, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case RangeRelationId:
+ 			break;
+ 		case RewriteRelationId:
+ 			break;
+ 		case SecLabelRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((classoid = (select oid from pg_class where relname = 'pg_aggregate'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_attribute') AND has_column_privilege(objoid, objsubid::smallint, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_type') AND has_type_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_class') AND has_table_privilege(objoid,'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_proc') AND has_function_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_language') AND has_language_privilege(objoid, 'any'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_largeobject'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_event_trigger'))"
+ 				" OR (classoid = (select oid from pg_class where relname = 'pg_tablespace') AND has_tablespace_privilege(objoid, 'any')))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case StatisticRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((starelid < 16384) OR has_column_privilege(starelid, staattnum, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case TransformRelationId:
+ 			break;
+ 		case TriggerRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_table_privilege(tgrelid, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case TSConfigRelationId:
+ 			break;
+ 		case TSConfigMapRelationId:
+ 			break;
+ 		case TSDictionaryRelationId:
+ 			break;
+ 		case TSParserRelationId:
+ 			break;
+ 		case TSTemplateRelationId:
+ 			break;
+ 		case TypeRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR has_type_privilege(oid, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		case UserMappingRelationId:
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR pg_has_role(umuser, 'any')"
+ 				" OR has_server_privilege(umserver, 'any'))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 			can_create_policy = true;
+ 			break;
+ 		default:
+ 			can_create_policy = false;
+ 			break;
+ 	}
+ 
+ 	return can_create_policy;
+ }
+ 
+ static bool
+ generate_catalog_drop_policy_string(HeapTuple tuple, char *buf)
+ {
+ 	bool can_create_policy = false;
+ 	Form_pg_class pg_class_tuple;
+ 	Oid	relationid;
+ 
+ 	pg_class_tuple = (Form_pg_class)GETSTRUCT(tuple);
+ 	relationid = HeapTupleGetOid(tuple);
+ 
+ 	if (IsSharedRelation(relationid))
+ 		return can_create_policy;
+ 
+ 	switch (relationid)
+ 	{
+ 		/*
+ 		* Following catalog tables data is accessible to all roles.
+ 		* So they doesn't need any speicific RLS policies on them.
+ 		*/
+ 	case AggregateRelationId:
+ 	case AccessMethodRelationId:
+ 	case AccessMethodOperatorRelationId:
+ 	case AccessMethodProcedureRelationId:
+ 	case CollationRelationId:
+ 	case ConversionRelationId:
+ 	case EnumRelationId:
+ 	case EventTriggerRelationId:
+ 	case ExtensionRelationId:
+ 	case LargeObjectRelationId:
+ 	case LargeObjectMetadataRelationId:
+ 	case OperatorClassRelationId:
+ 	case OperatorRelationId:
+ 	case OperatorFamilyRelationId:
+ 	case RangeRelationId:
+ 	case RewriteRelationId:
+ 	case TransformRelationId:
+ 	case TSConfigRelationId:
+ 	case TSConfigMapRelationId:
+ 	case TSDictionaryRelationId:
+ 	case TSParserRelationId:
+ 	case TSTemplateRelationId:
+ 		break;
+ 
+ 	case AttrDefaultRelationId:
+ 	case AttributeRelationId:
+ 	case CastRelationId:
+ 	case RelationRelationId:
+ 	case ConstraintRelationId:
+ 	case DefaultAclRelationId:
+ 	case DependRelationId:
+ 	case DescriptionRelationId:
+ 	case ForeignDataWrapperRelationId:
+ 	case ForeignServerRelationId:
+ 	case ForeignTableRelationId:
+ 	case IndexRelationId:
+ 	case InheritsRelationId:
+ 	case LanguageRelationId:
+ 	case NamespaceRelationId:
+ 	case PolicyRelationId:
+ 	case ProcedureRelationId:
+ 	case SecLabelRelationId:
+ 	case StatisticRelationId:
+ 	case TriggerRelationId:
+ 	case TypeRelationId:
+ 	case UserMappingRelationId:
+ 		sprintf(buf, "drop policy %s_read_own_data on %s",
+ 			pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 		can_create_policy = true;
+ 		break;
+ 
+ 	default:
+ 		can_create_policy = false;
+ 		break;
+ 	}
+ 
+ 	return can_create_policy;
+ }
+ 
+ /*
+  * CreateCatalogPolicy -
+  *	 handles the execution of the ALTER DATBASE ROW LEVEL SECUTIRY = TRUE command.
+  */
+ void
+ CreateCatalogPolicy()
+ {
+ 	Relation	rel;
+ 	ScanKeyData scankey;
+ 	SysScanDesc scan;
+ 	HeapTuple	tuple;
+ 	bool allow_sytem_table_mods_old;
+ 	char *buf;
+ 
+ 	/*
+ 	 * Get all catalog relations from pg_class system table and
+ 	 * enable the row level security along with the catalog policy
+ 	 * command.
+ 	 */
+ 	SPI_connect();
+ 	PushActiveSnapshot(GetTransactionSnapshot());
+ 
+ 	rel = heap_open(RelationRelationId, RowExclusiveLock);
+ 	ScanKeyInit(&scankey,
+ 				ObjectIdAttributeNumber,
+ 				BTLessStrategyNumber, F_OIDLT,
+ 				ObjectIdGetDatum(FirstNormalObjectId));
+ 	scan = systable_beginscan(rel, ClassOidIndexId, true,
+ 								NULL, 1, &scankey);
+ 
+ 	buf = palloc(CATALOG_POLICY_STRING_SIZE);
+ 	allow_sytem_table_mods_old = allowSystemTableMods;
+ 	allowSystemTableMods = true;
+ 
+ 	PG_TRY();
+ 	{
+ 		while ((tuple = systable_getnext(scan)) != NULL)
+ 		{
+ 			int			ret;
+ 			HeapTuple	cache_tuple;
+ 			Form_pg_class pg_class_tuple;
+ 			bool can_create_policy;
+ 
+ 			pg_class_tuple = (Form_pg_class)GETSTRUCT(tuple);
+ 			if (pg_class_tuple->relkind != RELKIND_RELATION)
+ 				continue;
+ 				
+ 			cache_tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(HeapTupleGetOid(tuple)));
+ 
+ 			if (!HeapTupleIsValid(cache_tuple))
+ 				elog(ERROR, "cache lookup failed for relation %u", HeapTupleGetOid(tuple));
+ 
+ 			can_create_policy = generate_catalog_create_policy_string(cache_tuple, buf);
+ 			if (!can_create_policy)
+ 			{
+ 				heap_freetuple(cache_tuple);
+ 				continue;
+ 			}
+ 	
+ 			ret = SPI_execute(buf, false, 0);
+ 			if (ret != SPI_OK_UTILITY)
+ 				elog(ERROR, "Creating policy failed : error code %d", ret);
+ 
+ 			((Form_pg_class)GETSTRUCT(cache_tuple))->relrowsecurity = true;
+ 			heap_inplace_update(rel, cache_tuple);
+ 
+ 			heap_freetuple(cache_tuple);
+ 		}
+ 	}
+ 	PG_CATCH();
+ 	{
+ 		allowSystemTableMods = allow_sytem_table_mods_old;
+ 		PG_RE_THROW();
+ 	}
+ 	PG_END_TRY();
+ 
+ 	allowSystemTableMods = allow_sytem_table_mods_old;
+ 	pfree(buf);
+ 
+ 	systable_endscan(scan);
+ 	heap_close(rel, NoLock);
+ 
+ 	SPI_finish();
+ 	PopActiveSnapshot();
+ }
+ 
+ /*
+  * RemoveCatalogPolicy -
+  *	 handles the execution of the ALTER DATBASE ROW LEVEL SECUTIRY = FALSE command.
+  */
+ void
+ RemoveCatalogPolicy()
+ {
+ 	Relation	rel;
+ 	ScanKeyData scankey;
+ 	SysScanDesc scan;
+ 	HeapTuple	tuple;
+ 	Form_pg_class pg_class_tuple;
+ 	bool allow_sytem_table_mods_old;
+ 	char		 *buf;
+ 
+ 	/*
+ 	* Get all catalog relations from pg_class system table and
+ 	* enable the row level security along with the catalog policy
+ 	* command.
+ 	*/
+ 	SPI_connect();
+ 	PushActiveSnapshot(GetTransactionSnapshot());
+ 
+ 	rel = heap_open(RelationRelationId, RowExclusiveLock);
+ 	ScanKeyInit(&scankey,
+ 		ObjectIdAttributeNumber,
+ 		BTLessStrategyNumber, F_OIDLT,
+ 		ObjectIdGetDatum(FirstNormalObjectId));
+ 	scan = systable_beginscan(rel, ClassOidIndexId, true,
+ 		NULL, 1, &scankey);
+ 
+ 	buf = palloc(CATALOG_POLICY_STRING_SIZE);
+ 
+ 	allow_sytem_table_mods_old = allowSystemTableMods;
+ 	allowSystemTableMods = true;
+ 
+ 	PG_TRY();
+ 	{
+ 		while ((tuple = systable_getnext(scan)) != NULL)
+ 		{
+ 			int			ret;
+ 			HeapTuple	cache_tuple;
+ 			bool		can_drop_policy;
+ 
+ 			pg_class_tuple = (Form_pg_class)GETSTRUCT(tuple);
+ 			if (pg_class_tuple->relkind != RELKIND_RELATION)
+ 				continue;
+ 
+ 			cache_tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(HeapTupleGetOid(tuple)));
+ 			if (!HeapTupleIsValid(cache_tuple))
+ 				elog(ERROR, "cache lookup failed for relation %u", HeapTupleGetOid(tuple));
+ 
+ 			can_drop_policy = generate_catalog_drop_policy_string(cache_tuple, buf);
+ 			if (!can_drop_policy)
+ 			{
+ 				heap_freetuple(cache_tuple);
+ 				continue;
+ 			}			
+ 
+ 			ret = SPI_execute(buf, false, 0);
+ 			if (ret != SPI_OK_UTILITY)
+ 				elog(ERROR, "Creating policy failed : error code %d", ret);
+ 
+ 			((Form_pg_class)GETSTRUCT(cache_tuple))->relrowsecurity = false;
+ 			heap_inplace_update(rel, cache_tuple);
+ 
+ 			heap_freetuple(cache_tuple);
+ 		}
+ 	}
+ 	PG_CATCH();
+ 	{
+ 		allowSystemTableMods = allow_sytem_table_mods_old;
+ 		PG_RE_THROW();
+ 	}
+ 	PG_END_TRY();
+ 
+ 	allowSystemTableMods = allow_sytem_table_mods_old;
+ 
+ 	pfree(buf);
+ 	systable_endscan(scan);
+ 	heap_close(rel, NoLock);
+ 
+ 	SPI_finish();
+ 	PopActiveSnapshot();
+ }
+ 
  /*
   * CreatePolicy -
   *	 handles the execution of the CREATE POLICY command.
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 8871,8876 **** createdb_opt_name:
--- 8871,8877 ----
  			| OWNER							{ $$ = pstrdup($1); }
  			| TABLESPACE					{ $$ = pstrdup($1); }
  			| TEMPLATE						{ $$ = pstrdup($1); }
+ 			| CATALOG_P SECURITY				{ $$ = pstrdup("catalog_security"); }
  		;
  
  /*
*** a/src/backend/utils/adt/acl.c
--- b/src/backend/utils/adt/acl.c
***************
*** 17,27 ****
  #include <ctype.h>
  
  #include "access/htup_details.h"
  #include "catalog/namespace.h"
  #include "catalog/pg_authid.h"
  #include "catalog/pg_auth_members.h"
! #include "catalog/pg_type.h"
  #include "catalog/pg_class.h"
  #include "commands/dbcommands.h"
  #include "commands/proclang.h"
  #include "commands/tablespace.h"
--- 17,35 ----
  #include <ctype.h>
  
  #include "access/htup_details.h"
+ #include "access/sysattr.h"
+ #include "catalog/indexing.h"
  #include "catalog/namespace.h"
  #include "catalog/pg_authid.h"
  #include "catalog/pg_auth_members.h"
! #include "catalog/pg_attrdef.h"
! #include "catalog/pg_cast.h"
  #include "catalog/pg_class.h"
+ #include "catalog/pg_constraint.h"
+ #include "catalog/pg_policy.h"
+ #include "catalog/pg_trigger.h"
+ #include "catalog/pg_type.h"
+ #include "catalog/pg_user_mapping.h"
  #include "commands/dbcommands.h"
  #include "commands/proclang.h"
  #include "commands/tablespace.h"
***************
*** 31,36 ****
--- 39,45 ----
  #include "utils/acl.h"
  #include "utils/builtins.h"
  #include "utils/catcache.h"
+ #include "utils/fmgroids.h"
  #include "utils/inval.h"
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
***************
*** 5267,5269 **** get_rolespec_name(const Node *node)
--- 5276,5568 ----
  
  	return rolename;
  }
+ 
+ /*
+  * has_cast_privilege_id
+  *		Check user privileges on a cast given
+  *		cast oid, and text priv name.
+  */
+ Datum
+ has_cast_privilege_id(PG_FUNCTION_ARGS)
+ {
+ 	Oid			castoid = PG_GETARG_OID(0);
+ 	text	   *priv_type_text = PG_GETARG_TEXT_P(1);
+ 	Oid			roleid;
+ 	AclMode		mode;
+ 	AclResult	aclresult1;
+ 	AclResult	aclresult2;
+ 	Relation	castDesc;
+ 	ScanKeyData skey[1];
+ 	SysScanDesc rcscan;
+ 	HeapTuple	tup;
+ 	Form_pg_cast castForm;
+ 
+ 	roleid = GetUserId();
+ 	mode = convert_server_priv_string(priv_type_text);
+ 
+ 	castDesc = heap_open(CastRelationId, AccessShareLock);
+ 
+ 	ScanKeyInit(&skey[0],
+ 		ObjectIdAttributeNumber,
+ 		BTEqualStrategyNumber, F_OIDEQ,
+ 		ObjectIdGetDatum(castoid));
+ 
+ 	rcscan = systable_beginscan(castDesc, CastOidIndexId, true,
+ 		NULL, 1, skey);
+ 
+ 	tup = systable_getnext(rcscan);
+ 
+ 	if (!HeapTupleIsValid(tup))
+ 	{
+ 		systable_endscan(rcscan);
+ 		heap_close(castDesc, AccessShareLock);
+ 		PG_RETURN_NULL();
+ 	}
+ 
+ 	castForm = (Form_pg_cast)GETSTRUCT(tup);
+ 
+ 	aclresult1 = pg_type_aclcheck(castForm->castsource, roleid, mode);
+ 	aclresult2 = pg_type_aclcheck(castForm->casttarget, roleid, mode);
+ 
+ 	systable_endscan(rcscan);
+ 	heap_close(castDesc, AccessShareLock);
+ 	PG_RETURN_BOOL((aclresult1 == ACLCHECK_OK) || (aclresult2 == ACLCHECK_OK));
+ }
+ 
+ /*
+  * has_constraint_privilege_id
+  *		Check user privileges on a constraint given
+  *		constraint oid, and text priv name.
+  */
+ Datum
+ has_constraint_privilege_id(PG_FUNCTION_ARGS)
+ {
+ 	Oid			constraintoid = PG_GETARG_OID(0);
+ 	text	   *priv_type_text = PG_GETARG_TEXT_P(1);
+ 	Oid			roleid;
+ 	AclMode		mode;
+ 	AclResult	aclresult;
+ 	Relation	constraintDesc;
+ 	ScanKeyData skey[1];
+ 	SysScanDesc rcscan;
+ 	HeapTuple	tup;
+ 	Form_pg_constraint constraintForm;
+ 
+ 	roleid = GetUserId();
+ 	mode = convert_server_priv_string(priv_type_text);
+ 
+ 	constraintDesc = heap_open(ConstraintRelationId, AccessShareLock);
+ 
+ 	ScanKeyInit(&skey[0],
+ 		ObjectIdAttributeNumber,
+ 		BTEqualStrategyNumber, F_OIDEQ,
+ 		ObjectIdGetDatum(constraintoid));
+ 
+ 	rcscan = systable_beginscan(constraintDesc, ConstraintOidIndexId, true,
+ 		NULL, 1, skey);
+ 
+ 	tup = systable_getnext(rcscan);
+ 
+ 	if (!HeapTupleIsValid(tup))
+ 	{
+ 		systable_endscan(rcscan);
+ 		heap_close(constraintDesc, AccessShareLock);
+ 		PG_RETURN_NULL();
+ 	}
+ 
+ 	constraintForm = (Form_pg_constraint)GETSTRUCT(tup);
+ 
+ 	if (constraintForm->contypid)
+ 		aclresult = pg_type_aclcheck(constraintForm->contypid, roleid, mode);
+ 	else
+ 		aclresult = pg_class_aclcheck(constraintForm->conrelid, roleid, mode);
+ 			
+ 	systable_endscan(rcscan);
+ 	heap_close(constraintDesc, AccessShareLock);
+ 	PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+ 
+ /*
+  * has_column_default_privilege_id
+  *		Check user privileges on a column default given
+  *		attrdefault oid, and text priv name.
+  */
+ Datum
+ has_column_default_privilege_id(PG_FUNCTION_ARGS)
+ {
+ 	Oid			attrdefaulttoid = PG_GETARG_OID(0);
+ 	text	   *priv_type_text = PG_GETARG_TEXT_P(1);
+ 	Oid			roleid;
+ 	AclMode		mode;
+ 	int			privresult;
+ 	Relation	attrDefaultDesc;
+ 	ScanKeyData skey[1];
+ 	SysScanDesc rcscan;
+ 	HeapTuple	tup;
+ 	Form_pg_attrdef attrDefForm;
+ 
+ 	roleid = GetUserId();
+ 	mode = convert_server_priv_string(priv_type_text);
+ 
+ 	attrDefaultDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
+ 
+ 	ScanKeyInit(&skey[0],
+ 		ObjectIdAttributeNumber,
+ 		BTEqualStrategyNumber, F_OIDEQ,
+ 		ObjectIdGetDatum(attrdefaulttoid));
+ 
+ 	rcscan = systable_beginscan(attrDefaultDesc, AttrDefaultOidIndexId, true,
+ 		NULL, 1, skey);
+ 
+ 	tup = systable_getnext(rcscan);
+ 
+ 	if (!HeapTupleIsValid(tup))
+ 	{
+ 		systable_endscan(rcscan);
+ 		heap_close(attrDefaultDesc, AccessShareLock);
+ 		PG_RETURN_NULL();
+ 	}
+ 
+ 	attrDefForm = (Form_pg_attrdef)GETSTRUCT(tup);
+ 
+ 	privresult = column_privilege_check(attrDefForm->adrelid, attrDefForm->adnum, roleid, mode);
+ 	
+ 	systable_endscan(rcscan);
+ 	heap_close(attrDefaultDesc, AccessShareLock);
+ 
+ 	if (privresult < 0)
+ 		PG_RETURN_NULL();
+ 	PG_RETURN_BOOL(privresult);
+ }
+ 
+ /*
+  * has_policy_privilege_id
+  *		Check user privileges on a policy given
+  *		policy oid, and text priv name.
+  */
+ Datum
+ has_policy_privilege_id(PG_FUNCTION_ARGS)
+ {
+ 	Oid			policyoid = PG_GETARG_OID(0);
+ 	text	   *priv_type_text = PG_GETARG_TEXT_P(1);
+ 	Oid			roleid;
+ 	AclMode		mode;
+ 	AclResult	aclresult;
+ 	Relation	policyDesc;
+ 	ScanKeyData skey[1];
+ 	SysScanDesc rcscan;
+ 	HeapTuple	tup;
+ 	Form_pg_policy policyForm;
+ 
+ 	roleid = GetUserId();
+ 	mode = convert_server_priv_string(priv_type_text);
+ 
+ 	policyDesc = heap_open(PolicyRelationId, AccessShareLock);
+ 
+ 	ScanKeyInit(&skey[0],
+ 		ObjectIdAttributeNumber,
+ 		BTEqualStrategyNumber, F_OIDEQ,
+ 		ObjectIdGetDatum(policyoid));
+ 
+ 	rcscan = systable_beginscan(policyDesc, PolicyOidIndexId, true,
+ 		NULL, 1, skey);
+ 
+ 	tup = systable_getnext(rcscan);
+ 
+ 	if (!HeapTupleIsValid(tup))
+ 	{
+ 		systable_endscan(rcscan);
+ 		heap_close(policyDesc, AccessShareLock);
+ 		PG_RETURN_NULL();
+ 	}
+ 
+ 	policyForm = (Form_pg_policy)GETSTRUCT(tup);
+ 
+ 	aclresult = pg_class_aclcheck(policyForm->polrelid, roleid, mode);
+ 
+ 	systable_endscan(rcscan);
+ 	heap_close(policyDesc, AccessShareLock);
+ 	PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+ 
+ /*
+  * has_trigger_privilege_id
+  *		Check user privileges on a trigger given
+  *		trigger oid, and text priv name.
+  */
+ Datum
+ has_trigger_privilege_id(PG_FUNCTION_ARGS)
+ {
+ 	Oid			triggeroid = PG_GETARG_OID(0);
+ 	text	   *priv_type_text = PG_GETARG_TEXT_P(1);
+ 	Oid			roleid;
+ 	AclMode		mode;
+ 	AclResult	aclresult;
+ 	Relation	triggerDesc;
+ 	ScanKeyData skey[1];
+ 	SysScanDesc rcscan;
+ 	HeapTuple	tup;
+ 	Form_pg_trigger triggerForm;
+ 
+ 	roleid = GetUserId();
+ 	mode = convert_server_priv_string(priv_type_text);
+ 
+ 	triggerDesc = heap_open(PolicyRelationId, AccessShareLock);
+ 
+ 	ScanKeyInit(&skey[0],
+ 		ObjectIdAttributeNumber,
+ 		BTEqualStrategyNumber, F_OIDEQ,
+ 		ObjectIdGetDatum(triggeroid));
+ 
+ 	rcscan = systable_beginscan(triggerDesc, PolicyOidIndexId, true,
+ 		NULL, 1, skey);
+ 
+ 	tup = systable_getnext(rcscan);
+ 
+ 	if (!HeapTupleIsValid(tup))
+ 	{
+ 		systable_endscan(rcscan);
+ 		heap_close(triggerDesc, AccessShareLock);
+ 		PG_RETURN_NULL();
+ 	}
+ 
+ 	triggerForm = (Form_pg_trigger)GETSTRUCT(tup);
+ 
+ 	aclresult = pg_class_aclcheck(triggerForm->tgrelid, roleid, mode);
+ 
+ 	systable_endscan(rcscan);
+ 	heap_close(triggerDesc, AccessShareLock);
+ 	PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+ 
+ /*
+ * has_user_mapping_privilege_id
+ *		Check user privileges on a user mapping given
+ *		user_mapping oid, and text priv name.
+ */
+ Datum
+ has_user_mapping_privilege_id(PG_FUNCTION_ARGS)
+ {
+ 	Oid			usermapoid = PG_GETARG_OID(0);
+ 	text	   *priv_type_text = PG_GETARG_TEXT_P(1);
+ 	Oid			roleid;
+ 	AclMode		mode;
+ 	AclResult	aclresult1;
+ 	AclResult	aclresult2;
+ 	HeapTuple	tup;
+ 	Form_pg_user_mapping usermapForm;
+ 
+ 	roleid = GetUserId();
+ 	mode = convert_server_priv_string(priv_type_text);
+ 
+ 	tup = SearchSysCache1(USERMAPPINGOID, usermapoid);
+ 	if (!HeapTupleIsValid(tup))
+ 		PG_RETURN_NULL();
+ 
+ 	usermapForm = (Form_pg_user_mapping)GETSTRUCT(tup);
+ 
+ 	aclresult1 = pg_role_aclcheck(usermapForm->umuser, roleid, mode);
+ 	aclresult2 = pg_foreign_server_aclcheck(usermapForm->umserver, roleid, mode);
+ 		
+ 	PG_RETURN_BOOL((aclresult1 == ACLCHECK_OK) || (aclresult2 == ACLCHECK_OK));
+ }
*** a/src/backend/utils/cache/relcache.c
--- b/src/backend/utils/cache/relcache.c
***************
*** 2076,2081 **** RelationClearRelation(Relation relation, bool rebuild)
--- 2076,2083 ----
  	 */
  	if (relation->rd_isnailed)
  	{
+ 		HeapTuple pg_class_tuple;
+ 
  		RelationInitPhysicalAddr(relation);
  
  		if (relation->rd_rel->relkind == RELKIND_INDEX)
***************
*** 2084,2089 **** RelationClearRelation(Relation relation, bool rebuild)
--- 2086,2112 ----
  			if (relation->rd_refcnt > 1 && IsTransactionState())
  				RelationReloadIndexInfo(relation);
  		}
+ 
+ 		/* 
+ 		 * A nailed-in system relation never ever blow away from rel cache, because
+ 		 * we'd be unable to recover. So for such relations, we will update the
+ 		 * row security descriptor if it is enabled. Usually this happens during
+ 		 * RelationBuildDesc function, but for nailed-in system relations, we will 
+ 		 * do it here.
+ 		 */
+ 		if (criticalRelcachesBuilt 
+ 			&& criticalSharedRelcachesBuilt
+ 			&& IsTransactionState())
+ 		{
+ 			/*
+ 			 * find the tuple in pg_class corresponding to the given relation id
+ 			 */
+ 			pg_class_tuple = ScanPgRelation(RelationGetRelid(relation), true, false);
+ 
+ 			if (((Form_pg_class)GETSTRUCT(pg_class_tuple))->relrowsecurity)
+ 				RelationBuildRowSecurity(relation);
+ 			heap_freetuple(pg_class_tuple);
+ 		}
  		return;
  	}
  
*** a/src/include/catalog/pg_database.h
--- b/src/include/catalog/pg_database.h
***************
*** 43,49 **** CATALOG(pg_database,1262) BKI_SHARED_RELATION BKI_ROWTYPE_OID(1248) BKI_SCHEMA_M
  	TransactionId datfrozenxid; /* all Xids < this are frozen in this DB */
  	TransactionId datminmxid;	/* all multixacts in the DB are >= this */
  	Oid			dattablespace;	/* default table space for this DB */
! 
  #ifdef CATALOG_VARLEN			/* variable-length fields start here */
  	aclitem		datacl[1];		/* access permissions */
  #endif
--- 43,49 ----
  	TransactionId datfrozenxid; /* all Xids < this are frozen in this DB */
  	TransactionId datminmxid;	/* all multixacts in the DB are >= this */
  	Oid			dattablespace;	/* default table space for this DB */
! 	bool		datcatalogsecurity; /* catalog security is enabled? */
  #ifdef CATALOG_VARLEN			/* variable-length fields start here */
  	aclitem		datacl[1];		/* access permissions */
  #endif
***************
*** 60,81 **** typedef FormData_pg_database *Form_pg_database;
   *		compiler constants for pg_database
   * ----------------
   */
! #define Natts_pg_database				13
! #define Anum_pg_database_datname		1
! #define Anum_pg_database_datdba			2
! #define Anum_pg_database_encoding		3
! #define Anum_pg_database_datcollate		4
! #define Anum_pg_database_datctype		5
! #define Anum_pg_database_datistemplate	6
! #define Anum_pg_database_datallowconn	7
! #define Anum_pg_database_datconnlimit	8
! #define Anum_pg_database_datlastsysoid	9
! #define Anum_pg_database_datfrozenxid	10
! #define Anum_pg_database_datminmxid		11
! #define Anum_pg_database_dattablespace	12
! #define Anum_pg_database_datacl			13
  
! DATA(insert OID = 1 (  template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1 1663 _null_));
  SHDESCR("default template for new databases");
  #define TemplateDbOid			1
  
--- 60,82 ----
   *		compiler constants for pg_database
   * ----------------
   */
! #define Natts_pg_database						14
! #define Anum_pg_database_datname				1
! #define Anum_pg_database_datdba					2
! #define Anum_pg_database_encoding				3
! #define Anum_pg_database_datcollate				4
! #define Anum_pg_database_datctype				5
! #define Anum_pg_database_datistemplate			6
! #define Anum_pg_database_datallowconn			7
! #define Anum_pg_database_datconnlimit			8
! #define Anum_pg_database_datlastsysoid			9
! #define Anum_pg_database_datfrozenxid			10
! #define Anum_pg_database_datminmxid				11
! #define Anum_pg_database_dattablespace			12
! #define Anum_pg_database_datcatalogsecurity	13
! #define Anum_pg_database_datacl					14
  
! DATA(insert OID = 1 (  template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1 1663 f _null_));
  SHDESCR("default template for new databases");
  #define TemplateDbOid			1
  
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 3642,3647 **** DESCR("current user privilege on role by role name");
--- 3642,3665 ----
  DATA(insert OID = 2710 (  pg_has_role		PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ pg_has_role_id _null_ _null_ _null_ ));
  DESCR("current user privilege on role by role oid");
  
+ DATA(insert OID = 3315 (has_cast_privilege		PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_cast_privilege_id _null_ _null_ _null_));
+ DESCR("current user privilege on cast by cast oid");
+ 
+ DATA(insert OID = 3316 (has_constraint_privilege		PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_constraint_privilege_id _null_ _null_ _null_));
+ DESCR("current user privilege on contrainst by constraint oid");
+ 
+ DATA(insert OID = 3317 (has_column_default_privilege		PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_column_default_privilege_id _null_ _null_ _null_));
+ DESCR("current user privilege on attrdefault by attrdefault oid");
+ 
+ DATA(insert OID = 3318 (has_policy_privilege		PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_policy_privilege_id _null_ _null_ _null_));
+ DESCR("current user privilege on policy by policy oid");
+ 
+ DATA(insert OID = 3319 (has_trigger_privilege		PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_trigger_privilege_id _null_ _null_ _null_));
+ DESCR("current user privilege on trigger by trigger oid");
+ 
+ DATA(insert OID = 3320 (has_user_mapping_privilege		PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_user_mapping_privilege_id _null_ _null_ _null_));
+ DESCR("current user privilege on user mapping by user_mapping oid");
+ 
  DATA(insert OID = 1269 (  pg_column_size		PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 23 "2276" _null_ _null_ _null_ _null_ _null_	pg_column_size _null_ _null_ _null_ ));
  DESCR("bytes required to store the value, perhaps with compression");
  DATA(insert OID = 2322 ( pg_tablespace_size		PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 20 "26" _null_ _null_ _null_ _null_ _null_ pg_tablespace_size_oid _null_ _null_ _null_ ));
*** a/src/include/commands/policy.h
--- b/src/include/commands/policy.h
***************
*** 33,36 **** extern ObjectAddress rename_policy(RenameStmt *stmt);
--- 33,39 ----
  
  extern bool relation_has_policies(Relation rel);
  
+ extern void CreateCatalogPolicy(void);
+ extern void RemoveCatalogPolicy(void);
+ 
  #endif   /* POLICY_H */
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
***************
*** 106,111 **** extern Datum pg_has_role_id_name(PG_FUNCTION_ARGS);
--- 106,117 ----
  extern Datum pg_has_role_id_id(PG_FUNCTION_ARGS);
  extern Datum pg_has_role_name(PG_FUNCTION_ARGS);
  extern Datum pg_has_role_id(PG_FUNCTION_ARGS);
+ extern Datum has_cast_privilege_id(PG_FUNCTION_ARGS);
+ extern Datum has_constraint_privilege_id(PG_FUNCTION_ARGS);
+ extern Datum has_column_default_privilege_id(PG_FUNCTION_ARGS);
+ extern Datum has_policy_privilege_id(PG_FUNCTION_ARGS);
+ extern Datum has_trigger_privilege_id(PG_FUNCTION_ARGS);
+ extern Datum has_user_mapping_privilege_id(PG_FUNCTION_ARGS);
  
  /* bool.c */
  extern Datum boolin(PG_FUNCTION_ARGS);
*** /dev/null
--- b/src/test/regress/expected/multitenancy.out
***************
*** 0 ****
--- 1,657 ----
+ -- Create roles that are used by the following tests
+ create role tenancy_user1 login createdb;
+ create role tenancy_user2 login createdb;
+ create schema tenancy_user1;
+ grant all on schema tenancy_user1 to tenancy_user1;
+ create schema tenancy_user2;
+ grant all on schema tenancy_user2 to tenancy_user2;
+ -- Create a type to test
+ CREATE TYPE tenancytesttype;
+ CREATE FUNCTION tenancytesttype_in(cstring)
+    RETURNS tenancytesttype
+    AS 'textin'
+    LANGUAGE internal STRICT IMMUTABLE;
+ NOTICE:  return type tenancytesttype is only a shell
+ CREATE FUNCTION tenancytesttype_out(tenancytesttype)
+    RETURNS cstring
+    AS 'textout'
+    LANGUAGE internal STRICT IMMUTABLE;
+ NOTICE:  argument type tenancytesttype is only a shell
+ CREATE TYPE tenancytesttype (
+    internallength = variable,
+    input = tenancytesttype_in,
+    output = tenancytesttype_out,
+    alignment = int4
+ );
+ COMMENT ON TYPE tenancytesttype IS 'tenancytesttype';
+ REVOKE ALL ON FUNCTION tenancytesttype_in(cstring) FROM public;
+ REVOKE ALL ON FUNCTION tenancytesttype_out(tenancytesttype) FROM public;
+ GRANT ALL ON FUNCTION tenancytesttype_in(cstring) TO tenancy_user2;
+ GRANT ALL ON FUNCTION tenancytesttype_out(tenancytesttype) TO tenancy_user2;
+ REVOKE ALL ON TYPE tenancytesttype FROM public;
+ GRANT ALL ON TYPE tenancytesttype TO tenancy_user2;
+ -- Temp Language create with owner as tenancy_user2
+ CREATE TRUSTED LANGUAGE tenancy_lang1 HANDLER plpgsql_call_handler;
+ REVOKE ALL ON LANGUAGE tenancy_lang1 FROM public;
+ ALTER LANGUAGE tenancy_lang1 OWNER TO tenancy_user2;
+ --Foriegn data wrapper, server and user mapping creation for user tenancy_user2
+ CREATE FOREIGN DATA WRAPPER tenancy_wrapper;
+ CREATE SERVER tenancy_server FOREIGN DATA WRAPPER tenancy_wrapper;
+ CREATE USER MAPPING FOR tenancy_user2 SERVER tenancy_server;
+ REVOKE ALL ON FOREIGN DATA WRAPPER tenancy_wrapper FROM public;
+ REVOKE ALL ON FOREIGN SERVER tenancy_server FROM public;
+ GRANT ALL ON FOREIGN DATA WRAPPER tenancy_wrapper To tenancy_user2;
+ GRANT ALL ON FOREIGN SERVER tenancy_server To tenancy_user2;
+ alter database regression with catalog security = true;
+ -- create objects realted to tenacy_user1
+ SET SESSION ROLE tenancy_user1;
+ create table public.tenancy_user1_tbl1 (tenancy_user1_tbl1_column1 serial,
+ 								tenancy_user1_tbl1_column2 char(10) default 'FUJITSU',
+ 								tenancy_user1_tbl1_column3 int);
+ create index tenancy_user1_tbl1_idx on tenancy_user1_tbl1 (tenancy_user1_tbl1_column3);
+ insert into tenancy_user1_tbl1(tenancy_user1_tbl1_column3) values(1);
+ create table tenancy_user1.tenancy_user1_tbl2 (tenancy_user1_tbl2_column1 serial,
+ 								tenancy_user1_tbl2_column2 char(10) default 'FUJITSU',
+ 								tenancy_user1_tbl2_column3 int);
+ ALTER TABLE tenancy_user1.tenancy_user1_tbl2 ADD CONSTRAINT tenancy_user1_tbl2_constraint UNIQUE (tenancy_user1_tbl2_column3);								
+ CREATE FUNCTION tenancy_user1_trigger_func() RETURNS trigger LANGUAGE plpgsql AS '
+ BEGIN
+ 	RAISE NOTICE ''tenancy_user1_trigger_func(%) called: action = %, when = %, level = %'', TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
+ 	RETURN NULL;
+ END;';
+ CREATE TRIGGER tenancy_user1_tbl1_before_ins_stmt_trig BEFORE INSERT ON tenancy_user1_tbl1
+ FOR EACH STATEMENT EXECUTE PROCEDURE tenancy_user1_trigger_func('before_ins_stmt');
+ CREATE TABLE tenancy_user1_main_table (aa TEXT);
+ CREATE TABLE tenancy_user1_child_table (bb TEXT) INHERITS (tenancy_user1_main_table);
+ create view public.tenancy_user1_view1 as select * from tenancy_user1_tbl1;
+ create materialized view public.tenancy_user1_matview1 as select * from tenancy_user1_tbl1;
+ select * from tenancy_user1_tbl1;
+  tenancy_user1_tbl1_column1 | tenancy_user1_tbl1_column2 | tenancy_user1_tbl1_column3 
+ ----------------------------+----------------------------+----------------------------
+                           1 | FUJITSU                    |                          1
+ (1 row)
+ 
+ select * from tenancy_user1_view1;
+  tenancy_user1_tbl1_column1 | tenancy_user1_tbl1_column2 | tenancy_user1_tbl1_column3 
+ ----------------------------+----------------------------+----------------------------
+                           1 | FUJITSU                    |                          1
+ (1 row)
+ 
+ select * from tenancy_user1_matview1;
+  tenancy_user1_tbl1_column1 | tenancy_user1_tbl1_column2 | tenancy_user1_tbl1_column3 
+ ----------------------------+----------------------------+----------------------------
+                           1 | FUJITSU                    |                          1
+ (1 row)
+ 
+ 								
+ -- verify all system catalogs related to the objects created by tenancy_user1
+ select relname from pg_class where relname = 'tenancy_user1_tbl1';
+       relname       
+ --------------------
+  tenancy_user1_tbl1
+ (1 row)
+ 
+ select relname from pg_class where relname = 'tenancy_user1_tbl1_idx';
+         relname         
+ ------------------------
+  tenancy_user1_tbl1_idx
+ (1 row)
+ 
+ select relname from pg_class where relname = 'tenancy_user1_view1';
+        relname       
+ ---------------------
+  tenancy_user1_view1
+ (1 row)
+ 
+ select relname from pg_class where relname = 'tenancy_user1_matview1';
+         relname         
+ ------------------------
+  tenancy_user1_matview1
+ (1 row)
+ 
+ select relname from pg_class where relname = 'tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq';
+                       relname                      
+ ---------------------------------------------------
+  tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq
+ (1 row)
+ 
+ select attname from pg_attribute where attname = 'tenancy_user1_tbl1_column1';
+           attname           
+ ----------------------------
+  tenancy_user1_tbl1_column1
+  tenancy_user1_tbl1_column1
+  tenancy_user1_tbl1_column1
+ (3 rows)
+ 
+ select adnum, adsrc from pg_attrdef where adrelid in (select oid from pg_class where relname = 'tenancy_user1_tbl1');
+  adnum |                                 adsrc                                  
+ -------+------------------------------------------------------------------------
+      1 | nextval('tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq'::regclass)
+      2 | 'FUJITSU'::bpchar
+ (2 rows)
+ 
+ select indnatts, indkey from pg_index where indrelid in (select oid from pg_class where relname = 'tenancy_user1_tbl1');
+  indnatts | indkey 
+ ----------+--------
+         1 | 3
+ (1 row)
+ 
+ select nspname, nspowner from pg_namespace where nspname = 'tenancy_user1';
+     nspname    | nspowner 
+ ---------------+----------
+  tenancy_user1 |       10
+ (1 row)
+ 
+ select conname from pg_constraint where conname = 'tenancy_user1_tbl2_constraint';
+             conname            
+ -------------------------------
+  tenancy_user1_tbl2_constraint
+ (1 row)
+ 
+ select classid::regclass, objid::regclass, deptype from pg_depend 
+ 	where classid = (select oid from pg_class where relname = 'pg_class')
+ 	and objid = (select oid from pg_class where relname = 'tenancy_user1_tbl2');
+  classid  |       objid        | deptype 
+ ----------+--------------------+---------
+  pg_class | tenancy_user1_tbl2 | n
+ (1 row)
+ 
+ select inhrelid::regclass, inhparent::regclass from pg_inherits
+ 	where inhrelid = (select oid from pg_class where relname = 'tenancy_user1_child_table');
+          inhrelid          |        inhparent         
+ ---------------------------+--------------------------
+  tenancy_user1_child_table | tenancy_user1_main_table
+ (1 row)
+ 
+ 	
+ --pg_class policy view, is shouldn't be visible to normal users
+ select polname from pg_policy where polrelid = (select oid from pg_class where relname = 'pg_class');
+  polname 
+ ---------
+ (0 rows)
+ 
+ select tgname, tgtype from pg_trigger where tgname = 'tenancy_user1_tbl1_before_ins_stmt_trig';
+                  tgname                  | tgtype 
+ -----------------------------------------+--------
+  tenancy_user1_tbl1_before_ins_stmt_trig |      6
+ (1 row)
+ 
+ 		
+ -- verify all system views related to the objects created by tenancy_user1
+ select schemaname, relname from pg_stat_all_tables where relname = 'tenancy_user1_tbl1';
+  schemaname |      relname       
+ ------------+--------------------
+  public     | tenancy_user1_tbl1
+ (1 row)
+ 
+ select schemaname, relname from pg_stat_all_tables where relname = 'tenancy_user1_tbl2' and schemaname = 'tenancy_user1';
+   schemaname   |      relname       
+ ---------------+--------------------
+  tenancy_user1 | tenancy_user1_tbl2
+ (1 row)
+ 
+ --works only when the shared catalog security is enabled
+ --select rolname, rolsuper from pg_roles where rolname like 'tenancy_user%';
+ select schemaname, tablename from pg_policies where tablename = 'pg_class';
+  schemaname | tablename 
+ ------------+-----------
+ (0 rows)
+ 
+ select schemaname, viewname from pg_views where viewname = 'tenancy_user1_view1';
+  schemaname |      viewname       
+ ------------+---------------------
+  public     | tenancy_user1_view1
+ (1 row)
+ 
+ select schemaname, tablename from pg_tables where tablename = 'tenancy_user1_tbl2';
+   schemaname   |     tablename      
+ ---------------+--------------------
+  tenancy_user1 | tenancy_user1_tbl2
+ (1 row)
+ 
+ select schemaname, matviewname from pg_matviews where matviewname = 'tenancy_user1_matview1';
+  schemaname |      matviewname       
+ ------------+------------------------
+  public     | tenancy_user1_matview1
+ (1 row)
+ 
+ select schemaname, tablename, indexname from pg_indexes where indexname = 'tenancy_user1_tbl1_idx';
+  schemaname |     tablename      |       indexname        
+ ------------+--------------------+------------------------
+  public     | tenancy_user1_tbl1 | tenancy_user1_tbl1_idx
+ (1 row)
+ 
+ select schemaname, relname from pg_statio_all_tables where relname = 'tenancy_user1_tbl1';
+  schemaname |      relname       
+ ------------+--------------------
+  public     | tenancy_user1_tbl1
+ (1 row)
+ 
+ select schemaname, relname, indexrelname from pg_stat_all_indexes where indexrelname = 'tenancy_user1_tbl1_idx';
+  schemaname |      relname       |      indexrelname      
+ ------------+--------------------+------------------------
+  public     | tenancy_user1_tbl1 | tenancy_user1_tbl1_idx
+ (1 row)
+ 
+ --information_schema views
+ select * from information_schema.table_constraints where constraint_name = 'tenancy_user1_tbl2_constraint';
+  constraint_catalog | constraint_schema |        constraint_name        | table_catalog | table_schema  |     table_name     | constraint_type | is_deferrable | initially_deferred 
+ --------------------+-------------------+-------------------------------+---------------+---------------+--------------------+-----------------+---------------+--------------------
+  regression         | tenancy_user1     | tenancy_user1_tbl2_constraint | regression    | tenancy_user1 | tenancy_user1_tbl2 | UNIQUE          | NO            | NO
+ (1 row)
+ 
+ select catalog_name, schema_name from information_schema.schemata where schema_name = 'tenancy_user1';
+  catalog_name |  schema_name  
+ --------------+---------------
+  regression   | tenancy_user1
+ (1 row)
+ 
+ select sequence_catalog, sequence_schema, sequence_name from information_schema.sequences
+ 			where sequence_name = 'tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq';
+  sequence_catalog | sequence_schema |                   sequence_name                   
+ ------------------+-----------------+---------------------------------------------------
+  regression       | public          | tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq
+ (1 row)
+ 
+ select * from information_schema.tables where table_name = 'tenancy_user1_tbl1';
+  table_catalog | table_schema |     table_name     | table_type | self_referencing_column_name | reference_generation | user_defined_type_catalog | user_defined_type_schema | user_defined_type_name | is_insertable_into | is_typed | commit_action 
+ ---------------+--------------+--------------------+------------+------------------------------+----------------------+---------------------------+--------------------------+------------------------+--------------------+----------+---------------
+  regression    | public       | tenancy_user1_tbl1 | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
+ (1 row)
+ 
+ select * from information_schema.triggers where trigger_name = 'tenancy_user1_tbl1_before_ins_stmt_trig';
+  trigger_catalog | trigger_schema |              trigger_name               | event_manipulation | event_object_catalog | event_object_schema | event_object_table | action_order | action_condition |                        action_statement                         | action_orientation | action_timing | action_reference_old_table | action_reference_new_table | action_reference_old_row | action_reference_new_row | created 
+ -----------------+----------------+-----------------------------------------+--------------------+----------------------+---------------------+--------------------+--------------+------------------+-----------------------------------------------------------------+--------------------+---------------+----------------------------+----------------------------+--------------------------+--------------------------+---------
+  regression      | public         | tenancy_user1_tbl1_before_ins_stmt_trig | INSERT             | regression           | public              | tenancy_user1_tbl1 |              |                  | EXECUTE PROCEDURE tenancy_user1_trigger_func('before_ins_stmt') | STATEMENT          | BEFORE        |                            |                            |                          |                          | 
+ (1 row)
+ 
+ select * from information_schema.views where table_name = 'tenancy_user1_view1';
+  table_catalog | table_schema |     table_name      |                    view_definition                     | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
+ ---------------+--------------+---------------------+--------------------------------------------------------+--------------+--------------+--------------------+----------------------+----------------------+----------------------------
+  regression    | public       | tenancy_user1_view1 |  SELECT tenancy_user1_tbl1.tenancy_user1_tbl1_column1,+| NONE         | YES          | YES                | NO                   | NO                   | NO
+                |              |                     |     tenancy_user1_tbl1.tenancy_user1_tbl1_column2,    +|              |              |                    |                      |                      | 
+                |              |                     |     tenancy_user1_tbl1.tenancy_user1_tbl1_column3     +|              |              |                    |                      |                      | 
+                |              |                     |    FROM tenancy_user1_tbl1;                            |              |              |                    |                      |                      | 
+ (1 row)
+ 
+ RESET ROLE;
+ -- create objects realted to tenacy_user2
+ SET SESSION ROLE tenancy_user2;
+ CREATE FOREIGN TABLE tenancy_user2_ft1 (
+ 	tenancy_user2_c1 integer OPTIONS ("param 1" 'val1') NOT NULL,
+ 	tenancy_user2_c2 text OPTIONS (param2 'val2', param3 'val3') CHECK (tenancy_user2_c2 <> ''),
+ 	tenancy_user2_c3 date,
+ 	CHECK (tenancy_user2_c3 BETWEEN '1994-01-01'::date AND '1994-01-31'::date)
+ ) SERVER tenancy_server OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
+ -- a dummy function to test the new type
+ CREATE FUNCTION tenancy_user2_tenancytestfunc(text) RETURNS int4 LANGUAGE SQL AS
+ $$ SELECT 1; $$;
+ SELECT tenancy_user2_tenancytestfunc('foo'::text);
+  tenancy_user2_tenancytestfunc 
+ -------------------------------
+                              1
+ (1 row)
+ 
+ --verify system catalogs to view the details of type, function and cast.
+ select proname from pg_proc where proname = 'tenancy_user2_tenancytestfunc';
+             proname            
+ -------------------------------
+  tenancy_user2_tenancytestfunc
+ (1 row)
+ 
+ select proname, pronamespace from pg_proc where proname = 'tenancytesttype_in';
+       proname       | pronamespace 
+ --------------------+--------------
+  tenancytesttype_in |         2200
+ (1 row)
+ 
+ select proname, pronamespace from pg_proc where proname = 'tenancytesttype_out';
+        proname       | pronamespace 
+ ---------------------+--------------
+  tenancytesttype_out |         2200
+ (1 row)
+ 
+ --select the description of casttesttype
+ select description from pg_description where classoid = (select oid from pg_class where relname = 'pg_type') 
+ 	and objoid = (select oid from pg_type where typname = 'tenancytesttype');
+    description   
+ -----------------
+  tenancytesttype
+ (1 row)
+ 
+ 	
+ --select the language that is owned by the tenancy_user2
+ select lanname, lanispl from pg_language where lanname = 'tenancy_lang1';
+     lanname    | lanispl 
+ ---------------+---------
+  tenancy_lang1 | t
+ (1 row)
+ 
+ --Foriegn data wrapper, server and foreign table details
+ SELECT fdwname, fdwhandler::regproc, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+      fdwname     | fdwhandler | fdwvalidator | fdwoptions 
+ -----------------+------------+--------------+------------
+  tenancy_wrapper | -          | -            | 
+ (1 row)
+ 
+ SELECT srvname, srvoptions FROM pg_foreign_server;
+     srvname     | srvoptions 
+ ----------------+------------
+  tenancy_server | 
+ (1 row)
+ 
+ Select srvname FROM pg_user_mappings where srvname = 'tenancy_server';
+     srvname     
+ ----------------
+  tenancy_server
+ (1 row)
+ 
+ SELECT relname, relkind from pg_class where relname = 'tenancy_user2_ft1';
+       relname      | relkind 
+ -------------------+---------
+  tenancy_user2_ft1 | f
+ (1 row)
+ 
+ 	
+ --information_schema views
+ select foreign_data_wrapper_catalog, foreign_data_wrapper_name from information_schema.foreign_data_wrappers
+ 		where foreign_data_wrapper_name = 'tenancy_wrapper';
+  foreign_data_wrapper_catalog | foreign_data_wrapper_name 
+ ------------------------------+---------------------------
+  regression                   | tenancy_wrapper
+ (1 row)
+ 
+ select foreign_server_catalog, foreign_server_name, foreign_data_wrapper_catalog, foreign_data_wrapper_name
+ 		from information_schema.foreign_servers where foreign_server_name = 'tenancy_server';
+  foreign_server_catalog | foreign_server_name | foreign_data_wrapper_catalog | foreign_data_wrapper_name 
+ ------------------------+---------------------+------------------------------+---------------------------
+  regression             | tenancy_server      | regression                   | tenancy_wrapper
+ (1 row)
+ 
+ select * from information_schema.foreign_tables where foreign_table_name = 'tenancy_user2_ft1';
+  foreign_table_catalog | foreign_table_schema | foreign_table_name | foreign_server_catalog | foreign_server_name 
+ -----------------------+----------------------+--------------------+------------------------+---------------------
+  regression            | tenancy_user2        | tenancy_user2_ft1  | regression             | tenancy_server
+ (1 row)
+ 
+ select * from information_schema.user_mappings where foreign_server_name = 'tenancy_server';
+  authorization_identifier | foreign_server_catalog | foreign_server_name 
+ --------------------------+------------------------+---------------------
+  tenancy_user2            | regression             | tenancy_server
+ (1 row)
+ 
+ RESET ROLE;
+ -- Try to get the objects created by tenancy_user1 from tenancy_user2
+ SET SESSION ROLE tenancy_user2;
+ select * from tenancy_user1_tbl1;
+ ERROR:  permission denied for relation tenancy_user1_tbl1
+ select * from tenancy_user1_view1;
+ ERROR:  permission denied for relation tenancy_user1_view1
+ select * from tenancy_user1_matview1;
+ ERROR:  permission denied for relation tenancy_user1_matview1
+ select * from tenancy_user1.tenancy_user1_tbl2;
+ ERROR:  permission denied for schema tenancy_user1
+ LINE 1: select * from tenancy_user1.tenancy_user1_tbl2;
+                       ^
+ -- verify all system catalogs related to the objects created by tenancy_user1
+ select relname from pg_class where relname = 'tenancy_user1_tbl1';
+  relname 
+ ---------
+ (0 rows)
+ 
+ select relname from pg_class where relname = 'tenancy_user1_tbl1_idx';
+  relname 
+ ---------
+ (0 rows)
+ 
+ select relname from pg_class where relname = 'tenancy_user1_view1';
+  relname 
+ ---------
+ (0 rows)
+ 
+ select relname from pg_class where relname = 'tenancy_user1_matview1';
+  relname 
+ ---------
+ (0 rows)
+ 
+ select relname from pg_class where relname = 'tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq';
+  relname 
+ ---------
+ (0 rows)
+ 
+ select attname from pg_attribute where attname = 'tenancy_user1_tbl1_column1';
+  attname 
+ ---------
+ (0 rows)
+ 
+ select adnum, adsrc from pg_attrdef where adrelid in (select oid from pg_class where relname = 'tenancy_user1_tbl1');
+  adnum | adsrc 
+ -------+-------
+ (0 rows)
+ 
+ select indnatts, indkey from pg_index where indrelid in (select oid from pg_class where relname = 'tenancy_user1_tbl1');
+  indnatts | indkey 
+ ----------+--------
+ (0 rows)
+ 
+ select nspname, nspowner from pg_namespace where nspname = 'tenancy_user1';
+  nspname | nspowner 
+ ---------+----------
+ (0 rows)
+ 
+ select conname from pg_constraint where conname = 'tenancy_user1_tbl2_constraint';
+  conname 
+ ---------
+ (0 rows)
+ 
+ select classid::regclass, objid::regclass, deptype from pg_depend 
+ 	where classid = (select oid from pg_class where relname = 'pg_class')
+ 	and objid = (select oid from pg_class where relname = 'tenancy_user1_tbl2');
+  classid | objid | deptype 
+ ---------+-------+---------
+ (0 rows)
+ 
+ select inhrelid::regclass, inhparent::regclass from pg_inherits
+ 	where inhrelid = (select oid from pg_class where relname = 'tenancy_user1_child_table');
+  inhrelid | inhparent 
+ ----------+-----------
+ (0 rows)
+ 
+ 	
+ --pg_class policy view, is shouldn't be visible to normal users
+ select polname from pg_policy where polrelid = (select oid from pg_class where relname = 'pg_class');
+  polname 
+ ---------
+ (0 rows)
+ 
+ select tgname, tgtype from pg_trigger where tgname = 'tenancy_user1_tbl1_before_ins_stmt_trig';
+  tgname | tgtype 
+ --------+--------
+ (0 rows)
+ 
+ -- verify all system views related to the objects created by tenancy_user1
+ select schemaname, relname from pg_stat_all_tables where relname = 'tenancy_user1_tbl1';
+  schemaname | relname 
+ ------------+---------
+ (0 rows)
+ 
+ select schemaname, relname from pg_stat_all_tables where relname = 'tenancy_user1_tbl2' and schemaname = 'tenancy_user1';
+  schemaname | relname 
+ ------------+---------
+ (0 rows)
+ 
+ --works only when the shared catalog security is enabled
+ --select rolname, rolsuper from pg_roles where rolname like 'tenancy_user%';
+ select schemaname, tablename from pg_policies where tablename = 'pg_class';
+  schemaname | tablename 
+ ------------+-----------
+ (0 rows)
+ 
+ select schemaname, viewname from pg_views where viewname = 'tenancy_user1_view1';
+  schemaname | viewname 
+ ------------+----------
+ (0 rows)
+ 
+ select schemaname, tablename from pg_tables where tablename = 'tenancy_user1_tbl2';
+  schemaname | tablename 
+ ------------+-----------
+ (0 rows)
+ 
+ select schemaname, matviewname from pg_matviews where matviewname = 'tenancy_user1_matview1';
+  schemaname | matviewname 
+ ------------+-------------
+ (0 rows)
+ 
+ select schemaname, tablename, indexname from pg_indexes where indexname = 'tenancy_user1_tbl1_idx';
+  schemaname | tablename | indexname 
+ ------------+-----------+-----------
+ (0 rows)
+ 
+ select schemaname, relname from pg_statio_all_tables where relname = 'tenancy_user1_tbl1';
+  schemaname | relname 
+ ------------+---------
+ (0 rows)
+ 
+ select schemaname, relname, indexrelname from pg_stat_all_indexes where indexrelname = 'tenancy_user1_tbl1_idx';
+  schemaname | relname | indexrelname 
+ ------------+---------+--------------
+ (0 rows)
+ 
+ --information_schema views
+ select * from information_schema.table_constraints where constraint_name = 'tenancy_user1_tbl2_constraint';
+  constraint_catalog | constraint_schema | constraint_name | table_catalog | table_schema | table_name | constraint_type | is_deferrable | initially_deferred 
+ --------------------+-------------------+-----------------+---------------+--------------+------------+-----------------+---------------+--------------------
+ (0 rows)
+ 
+ select catalog_name, schema_name from information_schema.schemata where schema_name = 'tenancy_user1';
+  catalog_name | schema_name 
+ --------------+-------------
+ (0 rows)
+ 
+ select sequence_catalog, sequence_schema, sequence_name from information_schema.sequences
+ 			where sequence_name = 'tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq';
+  sequence_catalog | sequence_schema | sequence_name 
+ ------------------+-----------------+---------------
+ (0 rows)
+ 
+ select * from information_schema.tables where table_name = 'tenancy_user1_tbl1';
+  table_catalog | table_schema | table_name | table_type | self_referencing_column_name | reference_generation | user_defined_type_catalog | user_defined_type_schema | user_defined_type_name | is_insertable_into | is_typed | commit_action 
+ ---------------+--------------+------------+------------+------------------------------+----------------------+---------------------------+--------------------------+------------------------+--------------------+----------+---------------
+ (0 rows)
+ 
+ select * from information_schema.triggers where trigger_name = 'tenancy_user1_tbl1_before_ins_stmt_trig';
+  trigger_catalog | trigger_schema | trigger_name | event_manipulation | event_object_catalog | event_object_schema | event_object_table | action_order | action_condition | action_statement | action_orientation | action_timing | action_reference_old_table | action_reference_new_table | action_reference_old_row | action_reference_new_row | created 
+ -----------------+----------------+--------------+--------------------+----------------------+---------------------+--------------------+--------------+------------------+------------------+--------------------+---------------+----------------------------+----------------------------+--------------------------+--------------------------+---------
+ (0 rows)
+ 
+ select * from information_schema.views where table_name = 'tenancy_user1_view1';
+  table_catalog | table_schema | table_name | view_definition | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
+ ---------------+--------------+------------+-----------------+--------------+--------------+--------------------+----------------------+----------------------+----------------------------
+ (0 rows)
+ 
+ RESET ROLE;
+ -- Try to get the objects created by tenancy_user2 from tenancy_user1
+ SET SESSION ROLE tenancy_user1;
+ --verify system catalogs to view the details of type, function and cast.
+ select proname from pg_proc where proname = 'tenancy_user2_tenancytestfunc';
+             proname            
+ -------------------------------
+  tenancy_user2_tenancytestfunc
+ (1 row)
+ 
+ select proname, pronamespace from pg_proc where proname = 'tenancytesttype_in';
+  proname | pronamespace 
+ ---------+--------------
+ (0 rows)
+ 
+ select proname, pronamespace from pg_proc where proname = 'tenancytesttype_out';
+  proname | pronamespace 
+ ---------+--------------
+ (0 rows)
+ 
+ --select the description of casttesttype
+ select description from pg_description where classoid = (select oid from pg_class where relname = 'pg_type') 
+ 	and objoid = (select oid from pg_type where typname = 'tenancytesttype');
+  description 
+ -------------
+ (0 rows)
+ 
+ --select the language that is owned by the tenancy_user2
+ select lanname, lanispl from pg_language where lanname = 'tenancy_lang1';
+  lanname | lanispl 
+ ---------+---------
+ (0 rows)
+ 
+ --Foriegn data wrapper, server and foreign table details
+ SELECT fdwname, fdwhandler::regproc, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+  fdwname | fdwhandler | fdwvalidator | fdwoptions 
+ ---------+------------+--------------+------------
+ (0 rows)
+ 
+ SELECT srvname, srvoptions FROM pg_foreign_server;
+  srvname | srvoptions 
+ ---------+------------
+ (0 rows)
+ 
+ Select srvname FROM pg_user_mappings where srvname = 'tenancy_server';
+  srvname 
+ ---------
+ (0 rows)
+ 
+ SELECT relname, relkind from pg_class where relname = 'tenancy_user2_ft1';
+  relname | relkind 
+ ---------+---------
+ (0 rows)
+ 
+ --information_schema views
+ select foreign_data_wrapper_catalog, foreign_data_wrapper_name from information_schema.foreign_data_wrappers
+ 		where foreign_data_wrapper_name = 'tenancy_wrapper';
+  foreign_data_wrapper_catalog | foreign_data_wrapper_name 
+ ------------------------------+---------------------------
+ (0 rows)
+ 
+ select foreign_server_catalog, foreign_server_name, foreign_data_wrapper_catalog, foreign_data_wrapper_name
+ 		from information_schema.foreign_servers where foreign_server_name = 'tenancy_server';
+  foreign_server_catalog | foreign_server_name | foreign_data_wrapper_catalog | foreign_data_wrapper_name 
+ ------------------------+---------------------+------------------------------+---------------------------
+ (0 rows)
+ 
+ select * from information_schema.foreign_tables where foreign_table_name = 'tenancy_user2_ft1';
+  foreign_table_catalog | foreign_table_schema | foreign_table_name | foreign_server_catalog | foreign_server_name 
+ -----------------------+----------------------+--------------------+------------------------+---------------------
+ (0 rows)
+ 
+ select * from information_schema.user_mappings where foreign_server_name = 'tenancy_server';
+  authorization_identifier | foreign_server_catalog | foreign_server_name 
+ --------------------------+------------------------+---------------------
+ (0 rows)
+ 
+ RESET ROLE;
+ -- Delete the roles and it's associated objects.
+ SET SESSION ROLE tenancy_user1;
+ DROP TABLE tenancy_user1_tbl1 cascade;
+ NOTICE:  drop cascades to 2 other objects
+ DETAIL:  drop cascades to view tenancy_user1_view1
+ drop cascades to materialized view tenancy_user1_matview1
+ DROP TABLE tenancy_user1_tbl2 cascade;
+ DROP FUNCTION tenancy_user1_trigger_func() cascade;
+ DROP TABLE tenancy_user1_main_table cascade;
+ NOTICE:  drop cascades to table tenancy_user1_child_table
+ RESET ROLE;
+ SET SESSION ROLE tenancy_user2;
+ DROP FUNCTION tenancy_user2_tenancytestfunc(text);
+ DROP FOREIGN TABLE tenancy_user2_ft1;
+ DROP LANGUAGE tenancy_lang1;
+ RESET ROLE;
+ DROP TYPE tenancytesttype cascade;
+ NOTICE:  drop cascades to 2 other objects
+ DETAIL:  drop cascades to function tenancytesttype_in(cstring)
+ drop cascades to function tenancytesttype_out(tenancytesttype)
+ DROP USER MAPPING FOR tenancy_user2 SERVER tenancy_server;
+ DROP SERVER tenancy_server;
+ DROP FOREIGN DATA WRAPPER tenancy_wrapper;
+ alter database regression with catalog security = false;
+ drop schema tenancy_user1;
+ drop schema tenancy_user2;
+ drop role tenancy_user1;
+ drop role tenancy_user2;
*** a/src/test/regress/parallel_schedule
--- b/src/test/regress/parallel_schedule
***************
*** 60,66 **** test: create_index create_view
  # ----------
  # Another group of parallel tests
  # ----------
! test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views rolenames roleattributes
  
  # ----------
  # sanity_check does a vacuum, affecting the sort order of SELECT *
--- 60,66 ----
  # ----------
  # Another group of parallel tests
  # ----------
! test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views rolenames roleattributes multitenancy
  
  # ----------
  # sanity_check does a vacuum, affecting the sort order of SELECT *
*** a/src/test/regress/serial_schedule
--- b/src/test/regress/serial_schedule
***************
*** 158,161 **** test: largeobject
--- 158,162 ----
  test: with
  test: xml
  test: event_trigger
+ test: multitenancy
  test: stats
*** /dev/null
--- b/src/test/regress/sql/multitenancy.sql
***************
*** 0 ****
--- 1,304 ----
+ -- Create roles that are used by the following tests
+ create role tenancy_user1 login createdb;
+ create role tenancy_user2 login createdb;
+ 
+ create schema tenancy_user1;
+ grant all on schema tenancy_user1 to tenancy_user1;
+ 
+ create schema tenancy_user2;
+ grant all on schema tenancy_user2 to tenancy_user2;
+ 
+ -- Create a type to test
+ CREATE TYPE tenancytesttype;
+ 
+ CREATE FUNCTION tenancytesttype_in(cstring)
+    RETURNS tenancytesttype
+    AS 'textin'
+    LANGUAGE internal STRICT IMMUTABLE;
+ CREATE FUNCTION tenancytesttype_out(tenancytesttype)
+    RETURNS cstring
+    AS 'textout'
+    LANGUAGE internal STRICT IMMUTABLE;
+ 
+ CREATE TYPE tenancytesttype (
+    internallength = variable,
+    input = tenancytesttype_in,
+    output = tenancytesttype_out,
+    alignment = int4
+ );
+ 
+ COMMENT ON TYPE tenancytesttype IS 'tenancytesttype';
+ 
+ REVOKE ALL ON FUNCTION tenancytesttype_in(cstring) FROM public;
+ REVOKE ALL ON FUNCTION tenancytesttype_out(tenancytesttype) FROM public;
+ GRANT ALL ON FUNCTION tenancytesttype_in(cstring) TO tenancy_user2;
+ GRANT ALL ON FUNCTION tenancytesttype_out(tenancytesttype) TO tenancy_user2;
+ 
+ REVOKE ALL ON TYPE tenancytesttype FROM public;
+ GRANT ALL ON TYPE tenancytesttype TO tenancy_user2;
+ 
+ -- Temp Language create with owner as tenancy_user2
+ CREATE TRUSTED LANGUAGE tenancy_lang1 HANDLER plpgsql_call_handler;
+ REVOKE ALL ON LANGUAGE tenancy_lang1 FROM public;
+ ALTER LANGUAGE tenancy_lang1 OWNER TO tenancy_user2;
+ 
+ --Foriegn data wrapper, server and user mapping creation for user tenancy_user2
+ CREATE FOREIGN DATA WRAPPER tenancy_wrapper;
+ CREATE SERVER tenancy_server FOREIGN DATA WRAPPER tenancy_wrapper;
+ CREATE USER MAPPING FOR tenancy_user2 SERVER tenancy_server;
+ 
+ REVOKE ALL ON FOREIGN DATA WRAPPER tenancy_wrapper FROM public;
+ REVOKE ALL ON FOREIGN SERVER tenancy_server FROM public;
+ GRANT ALL ON FOREIGN DATA WRAPPER tenancy_wrapper To tenancy_user2;
+ GRANT ALL ON FOREIGN SERVER tenancy_server To tenancy_user2;
+ 
+ alter database regression with catalog security = true;
+ 
+ -- create objects realted to tenacy_user1
+ SET SESSION ROLE tenancy_user1;
+ 
+ create table public.tenancy_user1_tbl1 (tenancy_user1_tbl1_column1 serial,
+ 								tenancy_user1_tbl1_column2 char(10) default 'FUJITSU',
+ 								tenancy_user1_tbl1_column3 int);
+ create index tenancy_user1_tbl1_idx on tenancy_user1_tbl1 (tenancy_user1_tbl1_column3);
+ 
+ insert into tenancy_user1_tbl1(tenancy_user1_tbl1_column3) values(1);
+ 
+ create table tenancy_user1.tenancy_user1_tbl2 (tenancy_user1_tbl2_column1 serial,
+ 								tenancy_user1_tbl2_column2 char(10) default 'FUJITSU',
+ 								tenancy_user1_tbl2_column3 int);
+ ALTER TABLE tenancy_user1.tenancy_user1_tbl2 ADD CONSTRAINT tenancy_user1_tbl2_constraint UNIQUE (tenancy_user1_tbl2_column3);								
+ 
+ CREATE FUNCTION tenancy_user1_trigger_func() RETURNS trigger LANGUAGE plpgsql AS '
+ BEGIN
+ 	RAISE NOTICE ''tenancy_user1_trigger_func(%) called: action = %, when = %, level = %'', TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
+ 	RETURN NULL;
+ END;';
+ 
+ CREATE TRIGGER tenancy_user1_tbl1_before_ins_stmt_trig BEFORE INSERT ON tenancy_user1_tbl1
+ FOR EACH STATEMENT EXECUTE PROCEDURE tenancy_user1_trigger_func('before_ins_stmt');
+ 
+ CREATE TABLE tenancy_user1_main_table (aa TEXT);
+ CREATE TABLE tenancy_user1_child_table (bb TEXT) INHERITS (tenancy_user1_main_table);
+ 
+ create view public.tenancy_user1_view1 as select * from tenancy_user1_tbl1;
+ create materialized view public.tenancy_user1_matview1 as select * from tenancy_user1_tbl1;
+ 
+ select * from tenancy_user1_tbl1;
+ select * from tenancy_user1_view1;
+ select * from tenancy_user1_matview1;
+ 								
+ 
+ -- verify all system catalogs related to the objects created by tenancy_user1
+ select relname from pg_class where relname = 'tenancy_user1_tbl1';
+ select relname from pg_class where relname = 'tenancy_user1_tbl1_idx';
+ select relname from pg_class where relname = 'tenancy_user1_view1';
+ select relname from pg_class where relname = 'tenancy_user1_matview1';
+ select relname from pg_class where relname = 'tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq';
+ 
+ select attname from pg_attribute where attname = 'tenancy_user1_tbl1_column1';
+ select adnum, adsrc from pg_attrdef where adrelid in (select oid from pg_class where relname = 'tenancy_user1_tbl1');
+ select indnatts, indkey from pg_index where indrelid in (select oid from pg_class where relname = 'tenancy_user1_tbl1');
+ select nspname, nspowner from pg_namespace where nspname = 'tenancy_user1';
+ select conname from pg_constraint where conname = 'tenancy_user1_tbl2_constraint';
+ select classid::regclass, objid::regclass, deptype from pg_depend 
+ 	where classid = (select oid from pg_class where relname = 'pg_class')
+ 	and objid = (select oid from pg_class where relname = 'tenancy_user1_tbl2');
+ select inhrelid::regclass, inhparent::regclass from pg_inherits
+ 	where inhrelid = (select oid from pg_class where relname = 'tenancy_user1_child_table');
+ 	
+ --pg_class policy view, is shouldn't be visible to normal users
+ select polname from pg_policy where polrelid = (select oid from pg_class where relname = 'pg_class');
+ 
+ select tgname, tgtype from pg_trigger where tgname = 'tenancy_user1_tbl1_before_ins_stmt_trig';
+ 		
+ -- verify all system views related to the objects created by tenancy_user1
+ select schemaname, relname from pg_stat_all_tables where relname = 'tenancy_user1_tbl1';
+ select schemaname, relname from pg_stat_all_tables where relname = 'tenancy_user1_tbl2' and schemaname = 'tenancy_user1';
+ --works only when the shared catalog security is enabled
+ --select rolname, rolsuper from pg_roles where rolname like 'tenancy_user%';
+ select schemaname, tablename from pg_policies where tablename = 'pg_class';
+ select schemaname, viewname from pg_views where viewname = 'tenancy_user1_view1';
+ select schemaname, tablename from pg_tables where tablename = 'tenancy_user1_tbl2';
+ select schemaname, matviewname from pg_matviews where matviewname = 'tenancy_user1_matview1';
+ select schemaname, tablename, indexname from pg_indexes where indexname = 'tenancy_user1_tbl1_idx';
+ select schemaname, relname from pg_statio_all_tables where relname = 'tenancy_user1_tbl1';
+ select schemaname, relname, indexrelname from pg_stat_all_indexes where indexrelname = 'tenancy_user1_tbl1_idx';
+ 
+ --information_schema views
+ select * from information_schema.table_constraints where constraint_name = 'tenancy_user1_tbl2_constraint';
+ select catalog_name, schema_name from information_schema.schemata where schema_name = 'tenancy_user1';
+ select sequence_catalog, sequence_schema, sequence_name from information_schema.sequences
+ 			where sequence_name = 'tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq';
+ select * from information_schema.tables where table_name = 'tenancy_user1_tbl1';
+ select * from information_schema.triggers where trigger_name = 'tenancy_user1_tbl1_before_ins_stmt_trig';
+ select * from information_schema.views where table_name = 'tenancy_user1_view1';
+ 
+ 
+ RESET ROLE;
+ 
+ 
+ -- create objects realted to tenacy_user2
+ SET SESSION ROLE tenancy_user2;
+ 
+ CREATE FOREIGN TABLE tenancy_user2_ft1 (
+ 	tenancy_user2_c1 integer OPTIONS ("param 1" 'val1') NOT NULL,
+ 	tenancy_user2_c2 text OPTIONS (param2 'val2', param3 'val3') CHECK (tenancy_user2_c2 <> ''),
+ 	tenancy_user2_c3 date,
+ 	CHECK (tenancy_user2_c3 BETWEEN '1994-01-01'::date AND '1994-01-31'::date)
+ ) SERVER tenancy_server OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
+ 
+ -- a dummy function to test the new type
+ CREATE FUNCTION tenancy_user2_tenancytestfunc(text) RETURNS int4 LANGUAGE SQL AS
+ $$ SELECT 1; $$;
+ 
+ SELECT tenancy_user2_tenancytestfunc('foo'::text);
+ 
+ --verify system catalogs to view the details of type, function and cast.
+ select proname from pg_proc where proname = 'tenancy_user2_tenancytestfunc';
+ select proname, pronamespace from pg_proc where proname = 'tenancytesttype_in';
+ select proname, pronamespace from pg_proc where proname = 'tenancytesttype_out';
+ 
+ --select the description of casttesttype
+ select description from pg_description where classoid = (select oid from pg_class where relname = 'pg_type') 
+ 	and objoid = (select oid from pg_type where typname = 'tenancytesttype');
+ 	
+ --select the language that is owned by the tenancy_user2
+ select lanname, lanispl from pg_language where lanname = 'tenancy_lang1';
+ 
+ --Foriegn data wrapper, server and foreign table details
+ SELECT fdwname, fdwhandler::regproc, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+ SELECT srvname, srvoptions FROM pg_foreign_server;
+ Select srvname FROM pg_user_mappings where srvname = 'tenancy_server';
+ 
+ SELECT relname, relkind from pg_class where relname = 'tenancy_user2_ft1';
+ 	
+ --information_schema views
+ select foreign_data_wrapper_catalog, foreign_data_wrapper_name from information_schema.foreign_data_wrappers
+ 		where foreign_data_wrapper_name = 'tenancy_wrapper';
+ select foreign_server_catalog, foreign_server_name, foreign_data_wrapper_catalog, foreign_data_wrapper_name
+ 		from information_schema.foreign_servers where foreign_server_name = 'tenancy_server';
+ select * from information_schema.foreign_tables where foreign_table_name = 'tenancy_user2_ft1';
+ select * from information_schema.user_mappings where foreign_server_name = 'tenancy_server';
+ 
+ RESET ROLE;
+ 
+ -- Try to get the objects created by tenancy_user1 from tenancy_user2
+ SET SESSION ROLE tenancy_user2;
+ 
+ select * from tenancy_user1_tbl1;
+ select * from tenancy_user1_view1;
+ select * from tenancy_user1_matview1;
+ 
+ select * from tenancy_user1.tenancy_user1_tbl2;
+ 
+ -- verify all system catalogs related to the objects created by tenancy_user1
+ select relname from pg_class where relname = 'tenancy_user1_tbl1';
+ select relname from pg_class where relname = 'tenancy_user1_tbl1_idx';
+ select relname from pg_class where relname = 'tenancy_user1_view1';
+ select relname from pg_class where relname = 'tenancy_user1_matview1';
+ select relname from pg_class where relname = 'tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq';
+ 
+ select attname from pg_attribute where attname = 'tenancy_user1_tbl1_column1';
+ select adnum, adsrc from pg_attrdef where adrelid in (select oid from pg_class where relname = 'tenancy_user1_tbl1');
+ select indnatts, indkey from pg_index where indrelid in (select oid from pg_class where relname = 'tenancy_user1_tbl1');
+ select nspname, nspowner from pg_namespace where nspname = 'tenancy_user1';
+ select conname from pg_constraint where conname = 'tenancy_user1_tbl2_constraint';
+ select classid::regclass, objid::regclass, deptype from pg_depend 
+ 	where classid = (select oid from pg_class where relname = 'pg_class')
+ 	and objid = (select oid from pg_class where relname = 'tenancy_user1_tbl2');
+ select inhrelid::regclass, inhparent::regclass from pg_inherits
+ 	where inhrelid = (select oid from pg_class where relname = 'tenancy_user1_child_table');
+ 	
+ --pg_class policy view, is shouldn't be visible to normal users
+ select polname from pg_policy where polrelid = (select oid from pg_class where relname = 'pg_class');
+ 
+ select tgname, tgtype from pg_trigger where tgname = 'tenancy_user1_tbl1_before_ins_stmt_trig';
+ 
+ -- verify all system views related to the objects created by tenancy_user1
+ select schemaname, relname from pg_stat_all_tables where relname = 'tenancy_user1_tbl1';
+ select schemaname, relname from pg_stat_all_tables where relname = 'tenancy_user1_tbl2' and schemaname = 'tenancy_user1';
+ --works only when the shared catalog security is enabled
+ --select rolname, rolsuper from pg_roles where rolname like 'tenancy_user%';
+ select schemaname, tablename from pg_policies where tablename = 'pg_class';
+ select schemaname, viewname from pg_views where viewname = 'tenancy_user1_view1';
+ select schemaname, tablename from pg_tables where tablename = 'tenancy_user1_tbl2';
+ select schemaname, matviewname from pg_matviews where matviewname = 'tenancy_user1_matview1';
+ select schemaname, tablename, indexname from pg_indexes where indexname = 'tenancy_user1_tbl1_idx';
+ select schemaname, relname from pg_statio_all_tables where relname = 'tenancy_user1_tbl1';
+ select schemaname, relname, indexrelname from pg_stat_all_indexes where indexrelname = 'tenancy_user1_tbl1_idx';
+ 
+ --information_schema views
+ select * from information_schema.table_constraints where constraint_name = 'tenancy_user1_tbl2_constraint';
+ select catalog_name, schema_name from information_schema.schemata where schema_name = 'tenancy_user1';
+ select sequence_catalog, sequence_schema, sequence_name from information_schema.sequences
+ 			where sequence_name = 'tenancy_user1_tbl1_tenancy_user1_tbl1_column1_seq';
+ select * from information_schema.tables where table_name = 'tenancy_user1_tbl1';
+ select * from information_schema.triggers where trigger_name = 'tenancy_user1_tbl1_before_ins_stmt_trig';
+ select * from information_schema.views where table_name = 'tenancy_user1_view1';
+ 
+ RESET ROLE;
+ 
+ -- Try to get the objects created by tenancy_user2 from tenancy_user1
+ SET SESSION ROLE tenancy_user1;
+ 
+ --verify system catalogs to view the details of type, function and cast.
+ select proname from pg_proc where proname = 'tenancy_user2_tenancytestfunc';
+ select proname, pronamespace from pg_proc where proname = 'tenancytesttype_in';
+ select proname, pronamespace from pg_proc where proname = 'tenancytesttype_out';
+ 
+ --select the description of casttesttype
+ select description from pg_description where classoid = (select oid from pg_class where relname = 'pg_type') 
+ 	and objoid = (select oid from pg_type where typname = 'tenancytesttype');
+ 
+ --select the language that is owned by the tenancy_user2
+ select lanname, lanispl from pg_language where lanname = 'tenancy_lang1';
+ 
+ --Foriegn data wrapper, server and foreign table details
+ SELECT fdwname, fdwhandler::regproc, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+ SELECT srvname, srvoptions FROM pg_foreign_server;
+ Select srvname FROM pg_user_mappings where srvname = 'tenancy_server';
+ 
+ SELECT relname, relkind from pg_class where relname = 'tenancy_user2_ft1';
+ 
+ --information_schema views
+ select foreign_data_wrapper_catalog, foreign_data_wrapper_name from information_schema.foreign_data_wrappers
+ 		where foreign_data_wrapper_name = 'tenancy_wrapper';
+ select foreign_server_catalog, foreign_server_name, foreign_data_wrapper_catalog, foreign_data_wrapper_name
+ 		from information_schema.foreign_servers where foreign_server_name = 'tenancy_server';
+ select * from information_schema.foreign_tables where foreign_table_name = 'tenancy_user2_ft1';
+ select * from information_schema.user_mappings where foreign_server_name = 'tenancy_server';
+ 
+ RESET ROLE;
+ 
+ 
+ -- Delete the roles and it's associated objects.
+ SET SESSION ROLE tenancy_user1;
+ 
+ DROP TABLE tenancy_user1_tbl1 cascade;
+ DROP TABLE tenancy_user1_tbl2 cascade;
+ DROP FUNCTION tenancy_user1_trigger_func() cascade;
+ DROP TABLE tenancy_user1_main_table cascade;
+ 
+ RESET ROLE;
+ 
+ SET SESSION ROLE tenancy_user2;
+ 
+ DROP FUNCTION tenancy_user2_tenancytestfunc(text);
+ DROP FOREIGN TABLE tenancy_user2_ft1;
+ DROP LANGUAGE tenancy_lang1;
+ 
+ RESET ROLE;
+ 
+ DROP TYPE tenancytesttype cascade;
+ DROP USER MAPPING FOR tenancy_user2 SERVER tenancy_server;
+ DROP SERVER tenancy_server;
+ DROP FOREIGN DATA WRAPPER tenancy_wrapper;
+ 
+ alter database regression with catalog security = false;
+ 
+ drop schema tenancy_user1;
+ drop schema tenancy_user2;
+ 
+ drop role tenancy_user1;
+ drop role tenancy_user2;
