*** 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 *************** *** 22,31 **** --- 22,83 ---- #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_auth_members.h" #include "catalog/pg_authid.h" + #include "catalog/pg_cast.h" + #include "catalog/pg_class.h" + #include "catalog/pg_collation.h" + #include "catalog/pg_constraint.h" + #include "catalog/pg_conversion.h" + #include "catalog/pg_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" *************** *** 44,49 **** --- 96,102 ---- #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, *************** *** 197,202 **** RelationBuildRowSecurity(Relation relation) --- 250,259 ---- MemoryContext oldcxt = CurrentMemoryContext; RowSecurityDesc *volatile rsdesc = NULL; + /* */ + if (!criticalRelcachesBuilt || !criticalSharedRelcachesBuilt || relation->rd_id == PolicyRelationId) + return; + /* * Create a memory context to hold everything associated with this * relation's row security policy. This makes it easy to clean up during *************** *** 448,453 **** RemovePolicyById(Oid policy_id) --- 505,926 ---- heap_close(pg_policy_rel, RowExclusiveLock); } + static bool + generate_catalog_policy_string(HeapTuple tuple, char *buf) + { + bool can_create_policy = false; + Form_pg_class pg_class_tuple; + + pg_class_tuple = (Form_pg_class)GETSTRUCT(tuple); + + switch (HeapTupleGetOid(tuple)) + { + /* + * Following catalog tables data is accessible to all roles. + * So they doesn't need any speicific RLS policies on them. + */ + case AggregateRelationId: + case AccessMethodRelationId: + case AccessMethodOperatorRelationId: + case AccessMethodProcedureRelationId: + break; + case AttrDefaultRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (has_column_privilege(adrelid, adnum,'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case AttributeRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (has_column_privilege(attrelid, attnum,'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case AuthMemRelationId: + break; + case AuthIdRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR pg_has_role(oid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case CastRelationId: + break; + case RelationRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_table_privilege(oid,'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case CollationRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR (pg_get_userbyid(collowner) = current_user))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case ConstraintRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_table_privilege(conrelid,'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case ConversionRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR (pg_get_userbyid(conowner) = current_user))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case DatabaseRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_database_privilege(oid,'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case DbRoleSettingRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (pg_get_userbyid(setrole) = current_user)", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case DefaultAclRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (pg_get_userbyid(defaclrole) = current_user)", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case DependRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (has_table_privilege(objid,'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case DescriptionRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (has_table_privilege(objoid,'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case EnumRelationId: + break; + case EventTriggerRelationId: + break; + case ExtensionRelationId: + break; + case ForeignDataWrapperRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_foreign_data_wrapper_privilege(oid,'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case ForeignServerRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_server_privilege(oid,'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case ForeignTableRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (has_table_privilege(ftrelid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case IndexRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (has_table_privilege(indrelid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case InheritsRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (has_table_privilege(inhrelid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case LanguageRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_language_privilege(oid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case LargeObjectRelationId: + break; + case LargeObjectMetadataRelationId: + break; + case NamespaceRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_schema_privilege(oid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case OperatorClassRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR (pg_get_userbyid(opcowner) = current_user))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case OperatorRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR (pg_get_userbyid(oprowner) = current_user))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case OperatorFamilyRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR (pg_get_userbyid(opfowner) = current_user))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case PLTemplateRelationId: + break; + case PolicyRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_table_privilege(polrelid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case ProcedureRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_function_privilege(oid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case RangeRelationId: + break; + case ReplicationOriginRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " (pg_has_role(roident, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case RewriteRelationId: + break; + case SecLabelRelationId: + break; + case SharedDependRelationId: + break; + case SharedDescriptionRelationId: + break; + case SharedSecLabelRelationId: + break; + case StatisticRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((starelid < 16384) OR has_table_privilege(starelid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + 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); + can_create_policy = true; + break; + case TransformRelationId: + break; + case TriggerRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_table_privilege(tgrelid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case TSConfigRelationId: + break; + case TSConfigMapRelationId: + break; + case TSDictionaryRelationId: + break; + case TSParserRelationId: + break; + case TSTemplateRelationId: + break; + case TypeRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR has_type_privilege(oid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + case UserMappingRelationId: + sprintf(buf, "create policy %s_read_own_data on %s for select using" + " ((oid < 16384) OR pg_has_role(oid, 'any'))", + pg_class_tuple->relname.data, pg_class_tuple->relname.data); + can_create_policy = true; + break; + default: + can_create_policy = false; + break; + } + + return can_create_policy; + } + + /* + * 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(200); + allow_sytem_table_mods_old = allowSystemTableMods; + allowSystemTableMods = true; + + PG_TRY(); + { + while ((tuple = systable_getnext(scan)) != NULL) + { + int ret; + HeapTuple cache_tuple; + Form_pg_class pg_class_tuple; + bool can_create_policy; + + pg_class_tuple = (Form_pg_class)GETSTRUCT(tuple); + if (pg_class_tuple->relkind != RELKIND_RELATION) + continue; + + cache_tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(HeapTupleGetOid(tuple))); + + if (!HeapTupleIsValid(cache_tuple)) + elog(ERROR, "cache lookup failed for relation %u", HeapTupleGetOid(tuple)); + + can_create_policy = generate_catalog_policy_string(cache_tuple, buf); + if (!can_create_policy) + { + heap_freetuple(cache_tuple); + continue; + } + + ret = SPI_execute(buf, false, 0); + if (ret != SPI_OK_UTILITY) + elog(ERROR, "Creating policy failed : error code %d", ret); + + ((Form_pg_class)GETSTRUCT(cache_tuple))->relrowsecurity = true; + 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; + 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; + + /* + * 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 */