diff --git a/doc/src/sgml/ref/alter_database.sgml b/doc/src/sgml/ref/alter_database.sgml
index cfc28cf..adc3326 100644
--- a/doc/src/sgml/ref/alter_database.sgml
+++ b/doc/src/sgml/ref/alter_database.sgml
@@ -28,6 +28,7 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <rep
     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,6 +140,18 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RESET ALL
         </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,6 +216,12 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RESET ALL
    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>
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index c1c0223..f7b7141 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -42,6 +42,7 @@
 #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,6 +227,13 @@ createdb(const CreatedbStmt *stmt)
 					 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,6 +527,7 @@ createdb(const CreatedbStmt *stmt)
 	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,11 +1384,14 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
 	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,6 +1433,15 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
 						 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,6 +1478,8 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
 					(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,12 +1499,19 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
 				(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,6 +1523,17 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
 				(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,6 +1556,11 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
 		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);
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index 6bd2a3b..8884b51 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -22,19 +22,62 @@
 #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_auth_members.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_database.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_pltemplate.h"
 #include "catalog/pg_policy.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_range.h"
 #include "catalog/pg_replication_origin.h"
+#include "catalog/pg_rewrite.h"
+#include "catalog/pg_seclabel.h"
 #include "catalog/pg_shdepend.h"
 #include "catalog/pg_shdescription.h"
 #include "catalog/pg_shseclabel.h"
+#include "catalog/pg_statistic.h"
 #include "catalog/pg_tablespace.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"
@@ -54,6 +97,7 @@
 #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 65536
@@ -514,6 +558,26 @@ get_catalog_policy_string(Oid relationid, Form_pg_class pg_class_tuple, char *bu
 
 	switch (relationid)
 	{
+			/*
+			 * Following catalog tables data is accessible to all roles. So
+			 * they doesn't need any specific RLS policies on them.
+			 */
+		case AccessMethodRelationId:
+		case AccessMethodOperatorRelationId:
+		case AccessMethodProcedureRelationId:
+		case AggregateRelationId:
+			policy_exist = false;
+			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);
+			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);
+			break;
 		case AuthIdRelationId:
 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
 					" (pg_has_role(oid, 'any'))",
@@ -524,6 +588,22 @@ get_catalog_policy_string(Oid relationid, Form_pg_class pg_class_tuple, char *bu
 			  " (pg_has_role(roleid, 'any') AND pg_has_role(member, 'any'))",
 				 pg_class_tuple->relname.data, pg_class_tuple->relname.data);
 			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);
+			break;
+		case CollationRelationId:
+			policy_exist = false;
+			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);
+			break;
+		case ConversionRelationId:
+			policy_exist = false;
+			break;
 		case DatabaseRelationId:
 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
 					" ((oid < 16384) OR has_database_privilege(oid,'any'))",
@@ -534,12 +614,175 @@ get_catalog_policy_string(Oid relationid, Form_pg_class pg_class_tuple, char *bu
 					" (pg_has_role(setrole, 'any') AND has_database_privilege(setdatabase,'any'))",
 				 pg_class_tuple->relname.data, pg_class_tuple->relname.data);
 			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);
+			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);
+			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);
+			break;
+		case EnumRelationId:
+		case EventTriggerRelationId:
+		case ExtensionRelationId:
+			policy_exist = false;
+			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);
+			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);
+			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);
+			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);
+			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);
+			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);
+			break;
+		case LargeObjectRelationId:
+		case LargeObjectMetadataRelationId:
+			policy_exist = false;
+			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);
+			break;
+		case OperatorClassRelationId:
+		case OperatorRelationId:
+		case OperatorFamilyRelationId:
 		case PLTemplateRelationId:
 			policy_exist = false;
 			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);
+			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);
+			break;
+		case RangeRelationId:
+			policy_exist = false;
+			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);
+			break;
 		case ReplicationOriginRelationId:
+		case RewriteRelationId:
 			policy_exist = false;
 			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);
+			break;
 		case SharedDependRelationId:
 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
 					" ((classid = (select oid from pg_class where relname = 'pg_database') AND has_database_privilege(objid, 'any'))"
@@ -561,11 +804,42 @@ get_catalog_policy_string(Oid relationid, Form_pg_class pg_class_tuple, char *bu
 					" 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);
 			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);
+			break;
 		case TableSpaceRelationId:
 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
 				  " ((oid < 16384) OR has_tablespace_privilege(oid, 'any'))",
 				 pg_class_tuple->relname.data, pg_class_tuple->relname.data);
 			break;
+		case TransformRelationId:
+			policy_exist = false;
+			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);
+			break;
+		case TSConfigRelationId:
+		case TSConfigMapRelationId:
+		case TSDictionaryRelationId:
+		case TSParserRelationId:
+		case TSTemplateRelationId:
+			policy_exist = false;
+			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);
+			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);
+			break;
 		default:
 			policy_exist = false;
 			break;
@@ -575,6 +849,163 @@ get_catalog_policy_string(Oid relationid, Form_pg_class pg_class_tuple, char *bu
 }
 
 /*
+ * 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)
+		{
+			HeapTuple	cache_tuple;
+			Form_pg_class pg_class_tuple;
+			bool		policy_exist;
+
+			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));
+
+			pg_class_tuple = (Form_pg_class) GETSTRUCT(cache_tuple);
+			policy_exist = get_catalog_policy_string(HeapTupleGetOid(tuple), pg_class_tuple, buf);
+			if (!policy_exist)
+			{
+				heap_freetuple(cache_tuple);
+				continue;
+			}
+
+			pg_class_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)
+		{
+			HeapTuple	cache_tuple;
+
+			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));
+
+			pg_class_tuple = (Form_pg_class) GETSTRUCT(cache_tuple);
+			if (!pg_class_tuple->relrowsecurity)
+				continue;
+
+			pg_class_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();
+}
+
+/*
  * RemoveRoleFromObjectPolicy -
  *	 remove a role from a policy by its OID.  If the role is not a member of
  *	 the policy then an error is raised.  False is returned to indicate that
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index edf4516..2469453 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -8948,6 +8948,7 @@ createdb_opt_name:
 			| OWNER							{ $$ = pstrdup($1); }
 			| TABLESPACE					{ $$ = pstrdup($1); }
 			| TEMPLATE						{ $$ = pstrdup($1); }
+			| CATALOG_P SECURITY				{ $$ = pstrdup("catalog_security"); }
 		;
 
 /*
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 059a220..e22baf6 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -17,12 +17,20 @@
 #include <ctype.h>
 
 #include "access/htup_details.h"
+#include "access/sysattr.h"
 #include "catalog/catalog.h"
+#include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_auth_members.h"
-#include "catalog/pg_type.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"
@@ -32,6 +40,7 @@
 #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"
@@ -2033,10 +2042,10 @@ convert_table_priv_string(text *priv_type_text)
 		{"TRIGGER", ACL_TRIGGER},
 		{"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
 		{"ANY", ACL_SELECT | ACL_GRANT_OPTION_FOR(ACL_SELECT) |
-				ACL_INSERT | ACL_GRANT_OPTION_FOR(ACL_INSERT) | ACL_UPDATE |
-				ACL_GRANT_OPTION_FOR(ACL_UPDATE) | ACL_DELETE | ACL_GRANT_OPTION_FOR(ACL_DELETE) |
-				ACL_TRUNCATE | ACL_GRANT_OPTION_FOR(ACL_TRUNCATE) | ACL_REFERENCES |
-				ACL_GRANT_OPTION_FOR(ACL_REFERENCES) | ACL_TRIGGER | ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
+			ACL_INSERT | ACL_GRANT_OPTION_FOR(ACL_INSERT) | ACL_UPDATE |
+			ACL_GRANT_OPTION_FOR(ACL_UPDATE) | ACL_DELETE | ACL_GRANT_OPTION_FOR(ACL_DELETE) |
+			ACL_TRUNCATE | ACL_GRANT_OPTION_FOR(ACL_TRUNCATE) | ACL_REFERENCES |
+		ACL_GRANT_OPTION_FOR(ACL_REFERENCES) | ACL_TRIGGER | ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
 		{"RULE", 0},			/* ignore old RULE privileges */
 		{"RULE WITH GRANT OPTION", 0},
 		{NULL, 0}
@@ -2866,8 +2875,8 @@ convert_column_priv_string(text *priv_type_text)
 		{"REFERENCES", ACL_REFERENCES},
 		{"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
 		{"ANY", ACL_SELECT | ACL_GRANT_OPTION_FOR(ACL_SELECT) | ACL_INSERT |
-				ACL_GRANT_OPTION_FOR(ACL_INSERT) | ACL_GRANT_OPTION_FOR(ACL_INSERT) | ACL_UPDATE |
-				ACL_GRANT_OPTION_FOR(ACL_UPDATE) | ACL_REFERENCES | ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
+			ACL_GRANT_OPTION_FOR(ACL_INSERT) | ACL_GRANT_OPTION_FOR(ACL_INSERT) | ACL_UPDATE |
+		ACL_GRANT_OPTION_FOR(ACL_UPDATE) | ACL_REFERENCES | ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
 		{NULL, 0}
 	};
 
@@ -3066,8 +3075,8 @@ convert_database_priv_string(text *priv_type_text)
 		{"CONNECT", ACL_CONNECT},
 		{"CONNECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CONNECT)},
 		{"ANY", ACL_CREATE | ACL_GRANT_OPTION_FOR(ACL_CREATE) |
-									ACL_CREATE_TEMP | ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP) | ACL_CREATE_TEMP |
-									ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP) | ACL_CONNECT | ACL_GRANT_OPTION_FOR(ACL_CONNECT)},
+			ACL_CREATE_TEMP | ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP) | ACL_CREATE_TEMP |
+		ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP) | ACL_CONNECT | ACL_GRANT_OPTION_FOR(ACL_CONNECT)},
 		{NULL, 0}
 	};
 
@@ -5306,3 +5315,293 @@ check_rolespec_name(const Node *node, const char *detail_msg)
 							role->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));
+}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 8d2ad01..6d7deb2 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -2109,6 +2109,8 @@ RelationClearRelation(Relation relation, bool rebuild)
 	 */
 	if (relation->rd_isnailed)
 	{
+		HeapTuple	pg_class_tuple;
+
 		RelationInitPhysicalAddr(relation);
 
 		if (relation->rd_rel->relkind == RELKIND_INDEX)
@@ -2117,6 +2119,28 @@ RelationClearRelation(Relation relation, bool rebuild)
 			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;
 	}
 
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index 6ae1b40..1816d8b 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -43,7 +43,7 @@ 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 */
-
+	bool		datcatalogsecurity; /* catalog security is enabled? */
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
 	aclitem		datacl[1];		/* access permissions */
 #endif
@@ -60,22 +60,23 @@ 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
+#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 _null_));
+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
 
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index d92c05e..9bc4c96 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3624,6 +3624,19 @@ DESCR("current user privilege on role by role name");
 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 = 3343 (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 = 3344 (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 = 3345 (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 = 3346 (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 = 3347 (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 = 3348 (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_ ));
diff --git a/src/include/commands/policy.h b/src/include/commands/policy.h
index dbf7824..453d335 100644
--- a/src/include/commands/policy.h
+++ b/src/include/commands/policy.h
@@ -35,4 +35,7 @@ extern ObjectAddress rename_policy(RenameStmt *stmt);
 
 extern bool relation_has_policies(Relation rel);
 
+extern void CreateCatalogPolicy(void);
+extern void RemoveCatalogPolicy(void);
+
 #endif   /* POLICY_H */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 01976a1..dc255a7 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -107,6 +107,12 @@ extern Datum pg_has_role_id_name(PG_FUNCTION_ARGS);
 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);
diff --git a/src/test/regress/expected/multitenancy.out b/src/test/regress/expected/multitenancy.out
new file mode 100644
index 0000000..cbdb1fa
--- /dev/null
+++ b/src/test/regress/expected/multitenancy.out
@@ -0,0 +1,644 @@
+-- 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;
+alter schema tenancy_user1 owner to tenancy_user1;
+create schema tenancy_user2;
+alter schema tenancy_user2 owner 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;
+ALTER SERVER tenancy_server OWNER 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 from pg_namespace where nspname = 'tenancy_user1';
+    nspname    
+---------------
+ tenancy_user1
+(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_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 from pg_namespace where nspname = 'tenancy_user1';
+ nspname 
+---------
+(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_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
+drop schema tenancy_user1;
+RESET ROLE;
+SET SESSION ROLE tenancy_user2;
+DROP FUNCTION tenancy_user2_tenancytestfunc(text);
+DROP FOREIGN TABLE tenancy_user2_ft1;
+DROP LANGUAGE tenancy_lang1;
+drop schema tenancy_user2;
+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 role tenancy_user1;
+drop role tenancy_user2;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 4ebad04..557c215 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -60,7 +60,7 @@ 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 create_am
+test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views rolenames roleattributes create_am multitenancy
 
 # ----------
 # sanity_check does a vacuum, affecting the sort order of SELECT *
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 5c7038d..f4e1839 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -166,4 +166,5 @@ test: largeobject
 test: with
 test: xml
 test: event_trigger
+test: multitenancy
 test: stats
diff --git a/src/test/regress/sql/multitenancy.sql b/src/test/regress/sql/multitenancy.sql
new file mode 100644
index 0000000..0b774a5
--- /dev/null
+++ b/src/test/regress/sql/multitenancy.sql
@@ -0,0 +1,297 @@
+-- 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;
+alter schema tenancy_user1 owner to tenancy_user1;
+
+create schema tenancy_user2;
+alter schema tenancy_user2 owner 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;
+ALTER SERVER tenancy_server OWNER 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 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_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 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_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;
+drop schema tenancy_user1;
+
+RESET ROLE;
+
+SET SESSION ROLE tenancy_user2;
+
+DROP FUNCTION tenancy_user2_tenancytestfunc(text);
+DROP FOREIGN TABLE tenancy_user2_ft1;
+DROP LANGUAGE tenancy_lang1;
+drop schema tenancy_user2;
+
+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 role tenancy_user1;
+drop role tenancy_user2;
