*** a/src/backend/commands/dbcommands.c
--- b/src/backend/commands/dbcommands.c
***************
*** 42,47 ****
--- 42,48 ----
  #include "commands/dbcommands.h"
  #include "commands/dbcommands_xlog.h"
  #include "commands/defrem.h"
+ #include "commands/policy.h"
  #include "commands/seclabel.h"
  #include "commands/tablespace.h"
  #include "mb/pg_wchar.h"
***************
*** 128,133 **** createdb(const CreatedbStmt *stmt)
--- 129,135 ----
  	DefElem    *distemplate = NULL;
  	DefElem    *dallowconnections = NULL;
  	DefElem    *dconnlimit = NULL;
+ 	DefElem    *drowlevelsecurity = NULL;
  	char	   *dbname = stmt->dbname;
  	char	   *dbowner = NULL;
  	const char *dbtemplate = NULL;
***************
*** 137,142 **** createdb(const CreatedbStmt *stmt)
--- 139,145 ----
  	int			encoding = -1;
  	bool		dbistemplate = false;
  	bool		dballowconnections = true;
+ 	bool		dbrowlevelsecurity = false;
  	int			dbconnlimit = -1;
  	int			notherbackends;
  	int			npreparedxacts;
***************
*** 226,231 **** createdb(const CreatedbStmt *stmt)
--- 229,242 ----
  					 errmsg("LOCATION is not supported anymore"),
  					 errhint("Consider using tablespaces instead.")));
  		}
+ 		else if (strcmp(defel->defname, "row_level_security") == 0)
+ 		{
+ 			if (drowlevelsecurity)
+ 				ereport(ERROR,
+ 					(errcode(ERRCODE_SYNTAX_ERROR),
+ 					errmsg("conflicting or redundant options")));
+ 			drowlevelsecurity = defel;
+ 		}
  		else
  			ereport(ERROR,
  					(errcode(ERRCODE_SYNTAX_ERROR),
***************
*** 278,283 **** createdb(const CreatedbStmt *stmt)
--- 289,296 ----
  					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  					 errmsg("invalid connection limit: %d", dbconnlimit)));
  	}
+ 	if (drowlevelsecurity && drowlevelsecurity->arg)
+ 		dbrowlevelsecurity = defGetBoolean(drowlevelsecurity);
  
  	/* obtain OID of proposed owner */
  	if (dbowner)
***************
*** 519,524 **** createdb(const CreatedbStmt *stmt)
--- 532,538 ----
  	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_datrowlevelsecurity - 1] = BoolGetDatum(dbrowlevelsecurity);
  
  	/*
  	 * We deliberately set datacl to default (NULL), rather than copying it
***************
*** 563,568 **** createdb(const CreatedbStmt *stmt)
--- 577,585 ----
  	RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT
  					  | CHECKPOINT_FLUSH_ALL);
  
+ 	if (dbrowlevelsecurity)
+ 		CreateCatalogPolicy();
+ 
  	/*
  	 * Once we start copying subdirectories, we need to be able to clean 'em
  	 * up if we fail.  Use an ENSURE block to make sure this happens.  (This
***************
*** 1375,1385 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1392,1405 ----
  	ListCell   *option;
  	bool		dbistemplate = false;
  	bool		dballowconnections = true;
+ 	bool		dbrowlevelsecurity = false;
  	int			dbconnlimit = -1;
  	DefElem    *distemplate = NULL;
  	DefElem    *dallowconnections = NULL;
  	DefElem    *dconnlimit = NULL;
  	DefElem    *dtablespace = NULL;
+ 	DefElem    *drowlevelsecurity = NULL;
+ 	Form_pg_database pg_database_tuple;
  	Datum		new_record[Natts_pg_database];
  	bool		new_record_nulls[Natts_pg_database];
  	bool		new_record_repl[Natts_pg_database];
***************
*** 1421,1426 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1441,1455 ----
  						 errmsg("conflicting or redundant options")));
  			dtablespace = defel;
  		}
+ 		else if (strcmp(defel->defname, "row_level_security") == 0)
+ 		{
+ 			if (drowlevelsecurity)
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_SYNTAX_ERROR),
+ 						errmsg("conflicting or redundant options")));
+ 
+ 			drowlevelsecurity = defel;
+ 		}
  		else
  			ereport(ERROR,
  					(errcode(ERRCODE_SYNTAX_ERROR),
***************
*** 1457,1462 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1486,1493 ----
  					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  					 errmsg("invalid connection limit: %d", dbconnlimit)));
  	}
+ 	if (drowlevelsecurity && drowlevelsecurity->arg)
+ 		dbrowlevelsecurity = defGetBoolean(drowlevelsecurity);
  
  	/*
  	 * Get the old tuple.  We don't need a lock on the database per se,
***************
*** 1476,1481 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1507,1513 ----
  				(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()))
***************
*** 1493,1498 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1525,1539 ----
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  				 errmsg("cannot disallow connections for current database")));
  
+ 	if (dbrowlevelsecurity)
+ 	{
+ 		CreateCatalogPolicy();
+ 	}
+ 	else if (pg_database_tuple->datrowlevelsecurity)
+ 	{
+ 		RemoveCatalogPolicy();
+ 	}
+ 
  	/*
  	 * Build an updated tuple, perusing the information just obtained
  	 */
***************
*** 1515,1520 **** AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
--- 1556,1566 ----
  		new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
  		new_record_repl[Anum_pg_database_datconnlimit - 1] = true;
  	}
+ 	if (drowlevelsecurity)
+ 	{
+ 		new_record[Anum_pg_database_datrowlevelsecurity - 1] = BoolGetDatum(dbrowlevelsecurity);
+ 		new_record_repl[Anum_pg_database_datrowlevelsecurity - 1] = true;
+ 	}
  
  	newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), new_record,
  								 new_record_nulls, new_record_repl);
*** a/src/backend/commands/policy.c
--- b/src/backend/commands/policy.c
***************
*** 26,31 ****
--- 26,32 ----
  #include "catalog/pg_policy.h"
  #include "catalog/pg_type.h"
  #include "commands/policy.h"
+ #include "executor/spi.h"
  #include "miscadmin.h"
  #include "nodes/makefuncs.h"
  #include "nodes/pg_list.h"
***************
*** 44,49 ****
--- 45,51 ----
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
  #include "utils/rel.h"
+ #include "utils/snapmgr.h"
  #include "utils/syscache.h"
  
  static void RangeVarCallbackForPolicy(const RangeVar *rv,
***************
*** 449,454 **** RemovePolicyById(Oid policy_id)
--- 451,619 ----
  }
  
  /*
+  * CreateCatalogPolicy -
+  *	 handles the execution of the ALTER DATBASE ROW LEVEL SECUTIRY = TRUE command.
+  */
+ void
+ CreateCatalogPolicy()
+ {
+ 	Relation	rel;
+ 	ScanKeyData scankey;
+ 	SysScanDesc scan;
+ 	HeapTuple	tuple;
+ 	Form_pg_class pg_class_tuple;
+ 	bool allow_sytem_table_mods_old;
+ 
+ 	/*
+ 	 * 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);
+ 
+ 	allow_sytem_table_mods_old = allowSystemTableMods;
+ 	allowSystemTableMods = true;
+ 
+ 	PG_TRY();
+ 	{
+ 		while ((tuple = systable_getnext(scan)) != NULL)
+ 		{
+ 			int			ret;
+ 			char		buf[200];
+ 			HeapTuple	cache_tuple;
+ 
+ 			pg_class_tuple = (Form_pg_class)GETSTRUCT(tuple);
+ 			if ((pg_class_tuple->relkind != RELKIND_RELATION)
+ 				|| (HeapTupleGetOid(tuple) != RelationRelationId))
+ 				continue;
+ 				
+ 			cache_tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(HeapTupleGetOid(tuple)));
+ 
+ 			if (!HeapTupleIsValid(cache_tuple))
+ 				elog(ERROR, "cache lookup failed for relation %u", HeapTupleGetOid(tuple));
+ 
+ 			sprintf(buf, "create policy %s_read_own_data on %s for select using"
+ 				" ((oid < 16384) OR (pg_get_userbyid(relowner) = current_user))",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 		
+ 			ret = SPI_execute(buf, false, 0);
+ 			if (ret != SPI_OK_UTILITY)
+ 				elog(ERROR, "Creating policy failed : error code %d", ret);
+ 
+ 			((Form_pg_class)GETSTRUCT(cache_tuple))->relrowsecurity = true;
+ 			simple_heap_update(rel, &cache_tuple->t_self, cache_tuple);
+ 
+ 			/* keep catalog indexes current */
+ 			CatalogUpdateIndexes(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;
+ 	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;
+ 
+ 	/*
+ 	* 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);
+ 
+ 	allow_sytem_table_mods_old = allowSystemTableMods;
+ 	allowSystemTableMods = true;
+ 
+ 	PG_TRY();
+ 	{
+ 		while ((tuple = systable_getnext(scan)) != NULL)
+ 		{
+ 			int			ret;
+ 			char		buf[200];
+ 			HeapTuple	cache_tuple;
+ 
+ 			pg_class_tuple = (Form_pg_class)GETSTRUCT(tuple);
+ 			if ((pg_class_tuple->relkind != RELKIND_RELATION)
+ 				|| (HeapTupleGetOid(tuple) != RelationRelationId))
+ 				continue;
+ 
+ 			cache_tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(HeapTupleGetOid(tuple)));
+ 
+ 			if (!HeapTupleIsValid(cache_tuple))
+ 				elog(ERROR, "cache lookup failed for relation %u", HeapTupleGetOid(tuple));
+ 
+ 			sprintf(buf, "Drop policy %s_read_own_data on %s",
+ 				pg_class_tuple->relname.data, pg_class_tuple->relname.data);
+ 
+ 			ret = SPI_execute(buf, false, 0);
+ 			if (ret != SPI_OK_UTILITY)
+ 				elog(ERROR, "Creating policy failed : error code %d", ret);
+ 
+ 			((Form_pg_class)GETSTRUCT(cache_tuple))->relrowsecurity = false;
+ 			simple_heap_update(rel, &cache_tuple->t_self, cache_tuple);
+ 
+ 			/* keep catalog indexes current */
+ 			CatalogUpdateIndexes(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;
+ 	systable_endscan(scan);
+ 	heap_close(rel, NoLock);
+ 
+ 	SPI_finish();
+ 	PopActiveSnapshot();
+ }
+ 
+ /*
   * CreatePolicy -
   *	 handles the execution of the CREATE POLICY command.
   *
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 8859,8864 **** createdb_opt_name:
--- 8859,8865 ----
  			| OWNER							{ $$ = pstrdup($1); }
  			| TABLESPACE					{ $$ = pstrdup($1); }
  			| TEMPLATE						{ $$ = pstrdup($1); }
+ 			| ROW LEVEL SECURITY			{ $$ = pstrdup("row_level_security"); }
  		;
  
  /*
*** a/src/backend/utils/misc/rls.c
--- b/src/backend/utils/misc/rls.c
***************
*** 60,68 **** check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
  	Oid			user_id = checkAsUser ? checkAsUser : GetUserId();
  
  	/* Nothing to do for built-in relations */
  	if (relid < FirstNormalObjectId)
  		return RLS_NONE;
! 
  	/*
  	 * Check if we have been told to explicitly skip RLS (perhaps because this
  	 * is a foreign key check)
--- 60,69 ----
  	Oid			user_id = checkAsUser ? checkAsUser : GetUserId();
  
  	/* Nothing to do for built-in relations */
+ #if 0
  	if (relid < FirstNormalObjectId)
  		return RLS_NONE;
! #endif
  	/*
  	 * Check if we have been told to explicitly skip RLS (perhaps because this
  	 * is a foreign key check)
*** a/src/include/catalog/pg_database.h
--- b/src/include/catalog/pg_database.h
***************
*** 43,49 **** CATALOG(pg_database,1262) BKI_SHARED_RELATION BKI_ROWTYPE_OID(1248) BKI_SCHEMA_M
  	TransactionId datfrozenxid; /* all Xids < this are frozen in this DB */
  	TransactionId datminmxid;	/* all multixacts in the DB are >= this */
  	Oid			dattablespace;	/* default table space for this DB */
! 
  #ifdef CATALOG_VARLEN			/* variable-length fields start here */
  	aclitem		datacl[1];		/* access permissions */
  #endif
--- 43,49 ----
  	TransactionId datfrozenxid; /* all Xids < this are frozen in this DB */
  	TransactionId datminmxid;	/* all multixacts in the DB are >= this */
  	Oid			dattablespace;	/* default table space for this DB */
! 	bool		datrowlevelsecurity; /* row level security is enabled? */
  #ifdef CATALOG_VARLEN			/* variable-length fields start here */
  	aclitem		datacl[1];		/* access permissions */
  #endif
***************
*** 60,81 **** typedef FormData_pg_database *Form_pg_database;
   *		compiler constants for pg_database
   * ----------------
   */
! #define Natts_pg_database				13
! #define Anum_pg_database_datname		1
! #define Anum_pg_database_datdba			2
! #define Anum_pg_database_encoding		3
! #define Anum_pg_database_datcollate		4
! #define Anum_pg_database_datctype		5
! #define Anum_pg_database_datistemplate	6
! #define Anum_pg_database_datallowconn	7
! #define Anum_pg_database_datconnlimit	8
! #define Anum_pg_database_datlastsysoid	9
! #define Anum_pg_database_datfrozenxid	10
! #define Anum_pg_database_datminmxid		11
! #define Anum_pg_database_dattablespace	12
! #define Anum_pg_database_datacl			13
  
! DATA(insert OID = 1 (  template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1 1663 _null_));
  SHDESCR("default template for new databases");
  #define TemplateDbOid			1
  
--- 60,82 ----
   *		compiler constants for pg_database
   * ----------------
   */
! #define Natts_pg_database						14
! #define Anum_pg_database_datname				1
! #define Anum_pg_database_datdba					2
! #define Anum_pg_database_encoding				3
! #define Anum_pg_database_datcollate				4
! #define Anum_pg_database_datctype				5
! #define Anum_pg_database_datistemplate			6
! #define Anum_pg_database_datallowconn			7
! #define Anum_pg_database_datconnlimit			8
! #define Anum_pg_database_datlastsysoid			9
! #define Anum_pg_database_datfrozenxid			10
! #define Anum_pg_database_datminmxid				11
! #define Anum_pg_database_dattablespace			12
! #define Anum_pg_database_datrowlevelsecurity	13
! #define Anum_pg_database_datacl					14
  
! DATA(insert OID = 1 (  template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1 1663 f _null_));
  SHDESCR("default template for new databases");
  #define TemplateDbOid			1
  
*** a/src/include/commands/policy.h
--- b/src/include/commands/policy.h
***************
*** 33,36 **** extern ObjectAddress rename_policy(RenameStmt *stmt);
--- 33,39 ----
  
  extern bool relation_has_policies(Relation rel);
  
+ extern void CreateCatalogPolicy(void);
+ extern void RemoveCatalogPolicy(void);
+ 
  #endif   /* POLICY_H */
