aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/Makefile2
-rw-r--r--src/backend/catalog/dependency.c11
-rw-r--r--src/backend/catalog/objectaddress.c58
-rw-r--r--src/backend/catalog/system_views.sql18
-rw-r--r--src/backend/commands/copy.c48
-rw-r--r--src/backend/commands/event_trigger.c2
-rw-r--r--src/backend/commands/functioncmds.c6
-rw-r--r--src/backend/commands/policy.c317
-rw-r--r--src/backend/commands/tablecmds.c19
-rw-r--r--src/backend/executor/execMain.c2
-rw-r--r--src/backend/optimizer/path/allpaths.c2
-rw-r--r--src/backend/optimizer/plan/planner.c6
-rw-r--r--src/backend/optimizer/plan/setrefs.c8
-rw-r--r--src/backend/parser/gram.y11
-rw-r--r--src/backend/rewrite/rewriteHandler.c4
-rw-r--r--src/backend/rewrite/rowsecurity.c14
-rw-r--r--src/backend/utils/cache/plancache.c8
-rw-r--r--src/backend/utils/cache/relcache.c4
-rw-r--r--src/bin/pg_dump/common.c4
-rw-r--r--src/bin/pg_dump/pg_backup_archiver.c1
-rw-r--r--src/bin/pg_dump/pg_dump.c185
-rw-r--r--src/bin/pg_dump/pg_dump.h26
-rw-r--r--src/bin/pg_dump/pg_dump_sort.c12
-rw-r--r--src/bin/psql/describe.c44
-rw-r--r--src/bin/psql/tab-complete.c2
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/dependency.h2
-rw-r--r--src/include/catalog/indexing.h8
-rw-r--r--src/include/catalog/pg_class.h2
-rw-r--r--src/include/catalog/pg_policy.h53
-rw-r--r--src/include/catalog/pg_rowsecurity.h53
-rw-r--r--src/include/nodes/parsenodes.h2
-rw-r--r--src/include/nodes/plannodes.h2
-rw-r--r--src/include/nodes/relation.h2
-rw-r--r--src/include/rewrite/rowsecurity.h6
-rw-r--r--src/include/utils/plancache.h4
-rw-r--r--src/include/utils/rel.h2
-rw-r--r--src/test/regress/expected/rowsecurity.out54
-rw-r--r--src/test/regress/expected/rules.out18
-rw-r--r--src/test/regress/expected/sanity_check.out2
-rw-r--r--src/test/regress/sql/rowsecurity.sql16
41 files changed, 557 insertions, 485 deletions
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index b257b02ff5c..a403c643600 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -39,7 +39,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \
pg_ts_parser.h pg_ts_template.h pg_extension.h \
pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
- pg_foreign_table.h pg_rowsecurity.h \
+ pg_foreign_table.h pg_policy.h \
pg_default_acl.h pg_seclabel.h pg_shseclabel.h pg_collation.h pg_range.h \
toasting.h indexing.h \
)
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index f338acf827d..8ba5123c101 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -43,9 +43,9 @@
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
+#include "catalog/pg_policy.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_rewrite.h"
-#include "catalog/pg_rowsecurity.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_ts_config.h"
@@ -156,7 +156,8 @@ static const Oid object_classes[MAX_OCLASS] = {
UserMappingRelationId, /* OCLASS_USER_MAPPING */
DefaultAclRelationId, /* OCLASS_DEFACL */
ExtensionRelationId, /* OCLASS_EXTENSION */
- EventTriggerRelationId /* OCLASS_EVENT_TRIGGER */
+ EventTriggerRelationId, /* OCLASS_EVENT_TRIGGER */
+ PolicyRelationId /* OCLASS_POLICY */
};
@@ -1251,7 +1252,7 @@ doDeletion(const ObjectAddress *object, int flags)
RemoveEventTriggerById(object->objectId);
break;
- case OCLASS_ROWSECURITY:
+ case OCLASS_POLICY:
RemovePolicyById(object->objectId);
break;
@@ -2361,8 +2362,8 @@ getObjectClass(const ObjectAddress *object)
case EventTriggerRelationId:
return OCLASS_EVENT_TRIGGER;
- case RowSecurityRelationId:
- return OCLASS_ROWSECURITY;
+ case PolicyRelationId:
+ return OCLASS_POLICY;
}
/* shouldn't get here */
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index b69b75bcc2e..e261307e9d5 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -42,7 +42,7 @@
#include "catalog/pg_opfamily.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
-#include "catalog/pg_rowsecurity.h"
+#include "catalog/pg_policy.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
@@ -346,11 +346,11 @@ static const ObjectPropertyType ObjectProperty[] =
false
},
{
- RowSecurityRelationId,
- RowSecurityOidIndexId,
+ PolicyRelationId,
+ PolicyOidIndexId,
-1,
-1,
- Anum_pg_rowsecurity_rsecpolname,
+ Anum_pg_policy_polname,
InvalidAttrNumber,
InvalidAttrNumber,
InvalidAttrNumber,
@@ -998,7 +998,7 @@ get_object_address_relobject(ObjectType objtype, List *objname,
address.objectSubId = 0;
break;
case OBJECT_POLICY:
- address.classId = RowSecurityRelationId;
+ address.classId = PolicyRelationId;
address.objectId = relation ?
get_relation_policy_oid(reloid, depname, missing_ok) :
InvalidOid;
@@ -2189,38 +2189,38 @@ getObjectDescription(const ObjectAddress *object)
break;
}
- case OCLASS_ROWSECURITY:
+ case OCLASS_POLICY:
{
- Relation rsec_rel;
+ Relation policy_rel;
ScanKeyData skey[1];
SysScanDesc sscan;
HeapTuple tuple;
- Form_pg_rowsecurity form_rsec;
+ Form_pg_policy form_policy;
- rsec_rel = heap_open(RowSecurityRelationId, AccessShareLock);
+ policy_rel = heap_open(PolicyRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(object->objectId));
- sscan = systable_beginscan(rsec_rel, RowSecurityOidIndexId,
+ sscan = systable_beginscan(policy_rel, PolicyOidIndexId,
true, NULL, 1, skey);
tuple = systable_getnext(sscan);
if (!HeapTupleIsValid(tuple))
- elog(ERROR, "cache lookup failed for row-security relation %u",
+ elog(ERROR, "cache lookup failed for policy %u",
object->objectId);
- form_rsec = (Form_pg_rowsecurity) GETSTRUCT(tuple);
+ form_policy = (Form_pg_policy) GETSTRUCT(tuple);
appendStringInfo(&buffer, _("policy %s on "),
- NameStr(form_rsec->rsecpolname));
- getRelationDescription(&buffer, form_rsec->rsecrelid);
+ NameStr(form_policy->polname));
+ getRelationDescription(&buffer, form_policy->polrelid);
systable_endscan(sscan);
- heap_close(rsec_rel, AccessShareLock);
+ heap_close(policy_rel, AccessShareLock);
break;
}
@@ -2635,6 +2635,10 @@ getObjectTypeDescription(const ObjectAddress *object)
appendStringInfoString(&buffer, "event trigger");
break;
+ case OCLASS_POLICY:
+ appendStringInfoString(&buffer, "policy");
+ break;
+
default:
appendStringInfo(&buffer, "unrecognized %u", object->classId);
break;
@@ -3119,6 +3123,30 @@ getObjectIdentity(const ObjectAddress *object)
break;
}
+ case OCLASS_POLICY:
+ {
+ Relation polDesc;
+ HeapTuple tup;
+ Form_pg_policy policy;
+
+ polDesc = heap_open(PolicyRelationId, AccessShareLock);
+
+ tup = get_catalog_object_by_oid(polDesc, object->objectId);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for policy %u",
+ object->objectId);
+
+ policy = (Form_pg_policy) GETSTRUCT(tup);
+
+ appendStringInfo(&buffer, "%s on ",
+ quote_identifier(NameStr(policy->polname)));
+ getRelationIdentity(&buffer, policy->polrelid);
+
+ heap_close(polDesc, AccessShareLock);
+ break;
+ }
+
case OCLASS_SCHEMA:
{
char *nspname;
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index a819952c75d..22b8ceef622 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -67,30 +67,30 @@ CREATE VIEW pg_policies AS
SELECT
N.nspname AS schemaname,
C.relname AS tablename,
- rs.rsecpolname AS policyname,
+ pol.polname AS policyname,
CASE
- WHEN rs.rsecroles = '{0}' THEN
+ WHEN pol.polroles = '{0}' THEN
string_to_array('public', '')
ELSE
ARRAY
(
SELECT rolname
FROM pg_catalog.pg_authid
- WHERE oid = ANY (rs.rsecroles) ORDER BY 1
+ WHERE oid = ANY (pol.polroles) ORDER BY 1
)
END AS roles,
- CASE WHEN rs.rseccmd IS NULL THEN 'ALL' ELSE
- CASE rs.rseccmd
+ CASE WHEN pol.polcmd IS NULL THEN 'ALL' ELSE
+ CASE pol.polcmd
WHEN 'r' THEN 'SELECT'
WHEN 'a' THEN 'INSERT'
WHEN 'u' THEN 'UPDATE'
WHEN 'd' THEN 'DELETE'
END
END AS cmd,
- pg_catalog.pg_get_expr(rs.rsecqual, rs.rsecrelid) AS qual,
- pg_catalog.pg_get_expr(rs.rsecwithcheck, rs.rsecrelid) AS with_check
- FROM pg_catalog.pg_rowsecurity rs
- JOIN pg_catalog.pg_class C ON (C.oid = rs.rsecrelid)
+ pg_catalog.pg_get_expr(pol.polqual, pol.polrelid) AS qual,
+ pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid) AS with_check
+ FROM pg_catalog.pg_policy pol
+ JOIN pg_catalog.pg_class C ON (C.oid = pol.polrelid)
LEFT JOIN pg_catalog.pg_namespace N ON (N.oid = C.relnamespace);
CREATE VIEW pg_rules AS
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 83e8f891222..08abe141f41 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -282,12 +282,13 @@ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
/* non-export function prototypes */
static CopyState BeginCopy(bool is_from, Relation rel, Node *raw_query,
- const char *queryString, List *attnamelist, List *options);
+ const char *queryString, const Oid queryRelId, List *attnamelist,
+ List *options);
static void EndCopy(CopyState cstate);
static void ClosePipeToProgram(CopyState cstate);
static CopyState BeginCopyTo(Relation rel, Node *query, const char *queryString,
- const char *filename, bool is_program, List *attnamelist,
- List *options);
+ const Oid queryRelId, const char *filename, bool is_program,
+ List *attnamelist, List *options);
static void EndCopyTo(CopyState cstate);
static uint64 DoCopyTo(CopyState cstate);
static uint64 CopyTo(CopyState cstate);
@@ -843,7 +844,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
ExecCheckRTPerms(list_make1(rte), true);
/*
- * Permission check for row security.
+ * Permission check for row security policies.
*
* check_enable_rls will ereport(ERROR) if the user has requested
* something invalid and will otherwise indicate if we should enable
@@ -866,7 +867,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
if (is_from)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("COPY FROM not supported with row security."),
+ errmsg("COPY FROM not supported with row level security."),
errhint("Use direct INSERT statements instead.")));
/* Build target list */
@@ -886,7 +887,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
target->location = 1;
/* Build FROM clause */
- from = makeRangeVar(NULL, RelationGetRelationName(rel), 1);
+ from = stmt->relation;
/* Build query */
select = makeNode(SelectStmt);
@@ -895,8 +896,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
query = (Node*) select;
- relid = InvalidOid;
-
/* Close the handle to the relation as it is no longer needed. */
heap_close(rel, (is_from ? RowExclusiveLock : AccessShareLock));
rel = NULL;
@@ -926,7 +925,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString, uint64 *processed)
}
else
{
- cstate = BeginCopyTo(rel, query, queryString,
+ cstate = BeginCopyTo(rel, query, queryString, relid,
stmt->filename, stmt->is_program,
stmt->attlist, stmt->options);
*processed = DoCopyTo(cstate); /* copy from database to file */
@@ -1304,6 +1303,7 @@ BeginCopy(bool is_from,
Relation rel,
Node *raw_query,
const char *queryString,
+ const Oid queryRelId,
List *attnamelist,
List *options)
{
@@ -1395,6 +1395,30 @@ BeginCopy(bool is_from,
plan = planner(query, 0, NULL);
/*
+ * If we were passed in a relid, make sure we got the same one back
+ * after planning out the query. It's possible that it changed between
+ * when we checked the policies on the table and decided to use a query
+ * and now.
+ */
+ if (queryRelId != InvalidOid)
+ {
+ Oid relid = linitial_oid(plan->relationOids);
+
+ /*
+ * There should only be one relationOid in this case, since we will
+ * only get here when we have changed the command for the user from
+ * a "COPY relation TO" to "COPY (SELECT * FROM relation) TO", to
+ * allow row level security policies to be applied.
+ */
+ Assert(list_length(plan->relationOids) == 1);
+
+ if (relid != queryRelId)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("relation referenced by COPY statement has changed")));
+ }
+
+ /*
* Use a snapshot with an updated command ID to ensure this query sees
* results of any previously executed queries.
*/
@@ -1595,6 +1619,7 @@ static CopyState
BeginCopyTo(Relation rel,
Node *query,
const char *queryString,
+ const Oid queryRelId,
const char *filename,
bool is_program,
List *attnamelist,
@@ -1636,7 +1661,8 @@ BeginCopyTo(Relation rel,
RelationGetRelationName(rel))));
}
- cstate = BeginCopy(false, rel, query, queryString, attnamelist, options);
+ cstate = BeginCopy(false, rel, query, queryString, queryRelId, attnamelist,
+ options);
oldcontext = MemoryContextSwitchTo(cstate->copycontext);
if (pipe)
@@ -2565,7 +2591,7 @@ BeginCopyFrom(Relation rel,
MemoryContext oldcontext;
bool volatile_defexprs;
- cstate = BeginCopy(true, rel, NULL, NULL, attnamelist, options);
+ cstate = BeginCopy(true, rel, NULL, NULL, InvalidOid, attnamelist, options);
oldcontext = MemoryContextSwitchTo(cstate->copycontext);
/* Initialize state variables */
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 1b8c94bcfdf..6a3002f5268 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -997,7 +997,7 @@ EventTriggerSupportsObjectClass(ObjectClass objclass)
case OCLASS_USER_MAPPING:
case OCLASS_DEFACL:
case OCLASS_EXTENSION:
- case OCLASS_ROWSECURITY:
+ case OCLASS_POLICY:
return true;
case MAX_OCLASS:
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 470db5705cc..d3a59aa3567 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -904,9 +904,9 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
ReleaseSysCache(languageTuple);
/*
- * Only superuser is allowed to create leakproof functions because it
- * possibly allows unprivileged users to reference invisible tuples to be
- * filtered out using views for row-level security.
+ * Only superuser is allowed to create leakproof functions because leakproof
+ * functions can see tuples which have not yet been filtered out by security
+ * barrier views or row level security policies.
*/
if (isLeakProof && !superuser())
ereport(ERROR,
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index 10d230ef431..290c826a680 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -22,7 +22,7 @@
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
-#include "catalog/pg_rowsecurity.h"
+#include "catalog/pg_policy.h"
#include "catalog/pg_type.h"
#include "commands/policy.h"
#include "miscadmin.h"
@@ -46,8 +46,8 @@
static void RangeVarCallbackForPolicy(const RangeVar *rv,
Oid relid, Oid oldrelid, void *arg);
-static char parse_row_security_command(const char *cmd_name);
-static ArrayType* rls_role_list_to_array(List *roles);
+static char parse_policy_command(const char *cmd_name);
+static ArrayType* policy_role_list_to_array(List *roles);
/*
* Callback to RangeVarGetRelidExtended().
@@ -95,7 +95,7 @@ RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid,
}
/*
- * parse_row_security_command -
+ * parse_policy_command -
* helper function to convert full command strings to their char
* representation.
*
@@ -104,7 +104,7 @@ RangeVarCallbackForPolicy(const RangeVar *rv, Oid relid, Oid oldrelid,
*
*/
static char
-parse_row_security_command(const char *cmd_name)
+parse_policy_command(const char *cmd_name)
{
char cmd;
@@ -128,7 +128,7 @@ parse_row_security_command(const char *cmd_name)
}
/*
- * rls_role_list_to_array
+ * policy_role_list_to_array
* helper function to convert a list of role names in to an array of
* role ids.
*
@@ -138,7 +138,7 @@ parse_row_security_command(const char *cmd_name)
* roles - the list of role names to convert.
*/
static ArrayType *
-rls_role_list_to_array(List *roles)
+policy_role_list_to_array(List *roles)
{
ArrayType *role_ids;
Datum *temp_array;
@@ -190,7 +190,7 @@ rls_role_list_to_array(List *roles)
}
/*
- * Load row-security policy from the catalog, and keep it in
+ * Load row security policy from the catalog, and keep it in
* the relation cache.
*/
void
@@ -204,14 +204,14 @@ RelationBuildRowSecurity(Relation relation)
MemoryContext rscxt = NULL;
RowSecurityDesc *rsdesc = NULL;
- catalog = heap_open(RowSecurityRelationId, AccessShareLock);
+ catalog = heap_open(PolicyRelationId, AccessShareLock);
ScanKeyInit(&skey,
- Anum_pg_rowsecurity_rsecrelid,
+ Anum_pg_policy_polrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation)));
- sscan = systable_beginscan(catalog, RowSecurityRelidPolnameIndexId, true,
+ sscan = systable_beginscan(catalog, PolicyPolrelidPolnameIndexId, true,
NULL, 1, &skey);
PG_TRY();
{
@@ -221,7 +221,7 @@ RelationBuildRowSecurity(Relation relation)
* default-deny policy is created.
*/
rscxt = AllocSetContextCreate(CacheMemoryContext,
- "Row-security descriptor",
+ "row security descriptor",
ALLOCSET_SMALL_MINSIZE,
ALLOCSET_SMALL_INITSIZE,
ALLOCSET_SMALL_MAXSIZE);
@@ -229,7 +229,7 @@ RelationBuildRowSecurity(Relation relation)
rsdesc->rscxt = rscxt;
/*
- * Loop through the row-level security entries for this relation, if
+ * Loop through the row level security policies for this relation, if
* any.
*/
while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
@@ -249,7 +249,7 @@ RelationBuildRowSecurity(Relation relation)
oldcxt = MemoryContextSwitchTo(rscxt);
/* Get policy command */
- value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rseccmd,
+ value_datum = heap_getattr(tuple, Anum_pg_policy_polcmd,
RelationGetDescr(catalog), &isnull);
if (isnull)
cmd_value = 0;
@@ -257,19 +257,19 @@ RelationBuildRowSecurity(Relation relation)
cmd_value = DatumGetChar(value_datum);
/* Get policy name */
- value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rsecpolname,
+ value_datum = heap_getattr(tuple, Anum_pg_policy_polname,
RelationGetDescr(catalog), &isnull);
Assert(!isnull);
policy_name_value = DatumGetCString(value_datum);
/* Get policy roles */
- value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rsecroles,
+ value_datum = heap_getattr(tuple, Anum_pg_policy_polroles,
RelationGetDescr(catalog), &isnull);
Assert(!isnull);
roles = DatumGetArrayTypeP(value_datum);
/* Get policy qual */
- value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rsecqual,
+ value_datum = heap_getattr(tuple, Anum_pg_policy_polqual,
RelationGetDescr(catalog), &isnull);
if (!isnull)
{
@@ -280,7 +280,7 @@ RelationBuildRowSecurity(Relation relation)
qual_expr = NULL;
/* Get WITH CHECK qual */
- value_datum = heap_getattr(tuple, Anum_pg_rowsecurity_rsecwithcheck,
+ value_datum = heap_getattr(tuple, Anum_pg_policy_polwithcheck,
RelationGetDescr(catalog), &isnull);
if (!isnull)
@@ -295,7 +295,7 @@ RelationBuildRowSecurity(Relation relation)
policy = palloc0(sizeof(RowSecurityPolicy));
policy->policy_name = policy_name_value;
- policy->rsecid = policy_id;
+ policy->policy_id = policy_id;
policy->cmd = cmd_value;
policy->roles = roles;
policy->qual = copyObject(qual_expr);
@@ -317,7 +317,7 @@ RelationBuildRowSecurity(Relation relation)
/*
* Check if no policies were added
*
- * If no policies exist in pg_rowsecurity for this relation, then we
+ * If no policies exist in pg_policy for this relation, then we
* need to create a single default-deny policy. We use InvalidOid for
* the Oid to indicate that this is the default-deny policy (we may
* decide to ignore the default policy if an extension adds policies).
@@ -333,7 +333,7 @@ RelationBuildRowSecurity(Relation relation)
policy = palloc0(sizeof(RowSecurityPolicy));
policy->policy_name = pstrdup("default-deny policy");
- policy->rsecid = InvalidOid;
+ policy->policy_id = InvalidOid;
policy->cmd = '\0';
policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true,
'i');
@@ -364,22 +364,22 @@ RelationBuildRowSecurity(Relation relation)
/*
* RemovePolicyById -
- * remove a row-security policy by its OID. If a policy does not exist with
- * the provided oid, then an error is raised.
+ * remove a policy by its OID. If a policy does not exist with the provided
+ * oid, then an error is raised.
*
- * policy_id - the oid of the row-security policy.
+ * policy_id - the oid of the policy.
*/
void
RemovePolicyById(Oid policy_id)
{
- Relation pg_rowsecurity_rel;
+ Relation pg_policy_rel;
SysScanDesc sscan;
ScanKeyData skey[1];
HeapTuple tuple;
Oid relid;
Relation rel;
- pg_rowsecurity_rel = heap_open(RowSecurityRelationId, RowExclusiveLock);
+ pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
/*
* Find the policy to delete.
@@ -389,19 +389,19 @@ RemovePolicyById(Oid policy_id)
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(policy_id));
- sscan = systable_beginscan(pg_rowsecurity_rel, RowSecurityOidIndexId, true,
+ sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
NULL, 1, skey);
tuple = systable_getnext(sscan);
/* If the policy exists, then remove it, otherwise raise an error. */
if (!HeapTupleIsValid(tuple))
- elog(ERROR, "could not find tuple for row-security %u", policy_id);
+ elog(ERROR, "could not find tuple for policy %u", policy_id);
/*
* Open and exclusive-lock the relation the policy belong to.
*/
- relid = ((Form_pg_rowsecurity) GETSTRUCT(tuple))->rsecrelid;
+ relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
rel = heap_open(relid, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
@@ -416,7 +416,7 @@ RemovePolicyById(Oid policy_id)
errmsg("permission denied: \"%s\" is a system catalog",
RelationGetRelationName(rel))));
- simple_heap_delete(pg_rowsecurity_rel, &tuple->t_self);
+ simple_heap_delete(pg_policy_rel, &tuple->t_self);
systable_endscan(sscan);
heap_close(rel, AccessExclusiveLock);
@@ -424,9 +424,8 @@ RemovePolicyById(Oid policy_id)
/*
* Note that, unlike some of the other flags in pg_class, relrowsecurity
* is not just an indication of if policies exist. When relrowsecurity
- * is set (which can be done directly by the user or indirectly by creating
- * a policy on the table), then all access to the relation must be through
- * a policy. If no policy is defined for the relation then a default-deny
+ * is set by a user, then all access to the relation must be through a
+ * policy. If no policy is defined for the relation then a default-deny
* policy is created and all records are filtered (except for queries from
* the owner).
*/
@@ -434,7 +433,7 @@ RemovePolicyById(Oid policy_id)
CacheInvalidateRelcache(rel);
/* Clean up */
- heap_close(pg_rowsecurity_rel, RowExclusiveLock);
+ heap_close(pg_policy_rel, RowExclusiveLock);
}
/*
@@ -446,11 +445,11 @@ RemovePolicyById(Oid policy_id)
Oid
CreatePolicy(CreatePolicyStmt *stmt)
{
- Relation pg_rowsecurity_rel;
- Oid rowsec_id;
+ Relation pg_policy_rel;
+ Oid policy_id;
Relation target_table;
Oid table_id;
- char rseccmd;
+ char polcmd;
ArrayType *role_ids;
ParseState *qual_pstate;
ParseState *with_check_pstate;
@@ -459,19 +458,19 @@ CreatePolicy(CreatePolicyStmt *stmt)
Node *with_check_qual;
ScanKeyData skey[2];
SysScanDesc sscan;
- HeapTuple rsec_tuple;
- Datum values[Natts_pg_rowsecurity];
- bool isnull[Natts_pg_rowsecurity];
+ HeapTuple policy_tuple;
+ Datum values[Natts_pg_policy];
+ bool isnull[Natts_pg_policy];
ObjectAddress target;
ObjectAddress myself;
/* Parse command */
- rseccmd = parse_row_security_command(stmt->cmd);
+ polcmd = parse_policy_command(stmt->cmd);
/*
* If the command is SELECT or DELETE then WITH CHECK should be NULL.
*/
- if ((rseccmd == ACL_SELECT_CHR || rseccmd == ACL_DELETE_CHR)
+ if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
&& stmt->with_check != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -481,14 +480,14 @@ CreatePolicy(CreatePolicyStmt *stmt)
* If the command is INSERT then WITH CHECK should be the only expression
* provided.
*/
- if (rseccmd == ACL_INSERT_CHR && stmt->qual != NULL)
+ if (polcmd == ACL_INSERT_CHR && stmt->qual != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("only WITH CHECK expression allowed for INSERT")));
/* Collect role ids */
- role_ids = rls_role_list_to_array(stmt->roles);
+ role_ids = policy_role_list_to_array(stmt->roles);
/* Parse the supplied clause */
qual_pstate = make_parsestate(NULL);
@@ -527,74 +526,74 @@ CreatePolicy(CreatePolicyStmt *stmt)
EXPR_KIND_WHERE,
"POLICY");
- /* Open pg_rowsecurity catalog */
- pg_rowsecurity_rel = heap_open(RowSecurityRelationId, RowExclusiveLock);
+ /* Open pg_policy catalog */
+ pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
- /* Set key - row security relation id. */
+ /* Set key - policy's relation id. */
ScanKeyInit(&skey[0],
- Anum_pg_rowsecurity_rsecrelid,
+ Anum_pg_policy_polrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(table_id));
- /* Set key - row security policy name. */
+ /* Set key - policy's name. */
ScanKeyInit(&skey[1],
- Anum_pg_rowsecurity_rsecpolname,
+ Anum_pg_policy_polname,
BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum(stmt->policy_name));
- sscan = systable_beginscan(pg_rowsecurity_rel,
- RowSecurityRelidPolnameIndexId, true, NULL, 2,
+ sscan = systable_beginscan(pg_policy_rel,
+ PolicyPolrelidPolnameIndexId, true, NULL, 2,
skey);
- rsec_tuple = systable_getnext(sscan);
+ policy_tuple = systable_getnext(sscan);
/* Complain if the policy name already exists for the table */
- if (HeapTupleIsValid(rsec_tuple))
+ if (HeapTupleIsValid(policy_tuple))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("policy \"%s\" for relation \"%s\" already exists",
stmt->policy_name, RelationGetRelationName(target_table))));
- values[Anum_pg_rowsecurity_rsecrelid - 1] = ObjectIdGetDatum(table_id);
- values[Anum_pg_rowsecurity_rsecpolname - 1]
+ values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id);
+ values[Anum_pg_policy_polname - 1]
= DirectFunctionCall1(namein, CStringGetDatum(stmt->policy_name));
- if (rseccmd)
- values[Anum_pg_rowsecurity_rseccmd - 1] = CharGetDatum(rseccmd);
+ if (polcmd)
+ values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd);
else
- isnull[Anum_pg_rowsecurity_rseccmd - 1] = true;
+ isnull[Anum_pg_policy_polcmd - 1] = true;
- values[Anum_pg_rowsecurity_rsecroles - 1] = PointerGetDatum(role_ids);
+ values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
/* Add qual if present. */
if (qual)
- values[Anum_pg_rowsecurity_rsecqual - 1]
+ values[Anum_pg_policy_polqual - 1]
= CStringGetTextDatum(nodeToString(qual));
else
- isnull[Anum_pg_rowsecurity_rsecqual - 1] = true;
+ isnull[Anum_pg_policy_polqual - 1] = true;
/* Add WITH CHECK qual if present */
if (with_check_qual)
- values[Anum_pg_rowsecurity_rsecwithcheck - 1]
+ values[Anum_pg_policy_polwithcheck - 1]
= CStringGetTextDatum(nodeToString(with_check_qual));
else
- isnull[Anum_pg_rowsecurity_rsecwithcheck - 1] = true;
+ isnull[Anum_pg_policy_polwithcheck - 1] = true;
- rsec_tuple = heap_form_tuple(RelationGetDescr(pg_rowsecurity_rel), values,
- isnull);
+ policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values,
+ isnull);
- rowsec_id = simple_heap_insert(pg_rowsecurity_rel, rsec_tuple);
+ policy_id = simple_heap_insert(pg_policy_rel, policy_tuple);
/* Update Indexes */
- CatalogUpdateIndexes(pg_rowsecurity_rel, rsec_tuple);
+ CatalogUpdateIndexes(pg_policy_rel, policy_tuple);
/* Record Dependencies */
target.classId = RelationRelationId;
target.objectId = table_id;
target.objectSubId = 0;
- myself.classId = RowSecurityRelationId;
- myself.objectId = rowsec_id;
+ myself.classId = PolicyRelationId;
+ myself.objectId = policy_id;
myself.objectSubId = 0;
recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
@@ -609,14 +608,14 @@ CreatePolicy(CreatePolicyStmt *stmt)
CacheInvalidateRelcache(target_table);
/* Clean up. */
- heap_freetuple(rsec_tuple);
+ heap_freetuple(policy_tuple);
free_parsestate(qual_pstate);
free_parsestate(with_check_pstate);
systable_endscan(sscan);
relation_close(target_table, NoLock);
- heap_close(pg_rowsecurity_rel, RowExclusiveLock);
+ heap_close(pg_policy_rel, RowExclusiveLock);
- return rowsec_id;
+ return policy_id;
}
/*
@@ -628,8 +627,8 @@ CreatePolicy(CreatePolicyStmt *stmt)
Oid
AlterPolicy(AlterPolicyStmt *stmt)
{
- Relation pg_rowsecurity_rel;
- Oid rowsec_id;
+ Relation pg_policy_rel;
+ Oid policy_id;
Relation target_table;
Oid table_id;
ArrayType *role_ids = NULL;
@@ -639,20 +638,20 @@ AlterPolicy(AlterPolicyStmt *stmt)
Node *with_check_qual = NULL;
ScanKeyData skey[2];
SysScanDesc sscan;
- HeapTuple rsec_tuple;
+ HeapTuple policy_tuple;
HeapTuple new_tuple;
- Datum values[Natts_pg_rowsecurity];
- bool isnull[Natts_pg_rowsecurity];
- bool replaces[Natts_pg_rowsecurity];
+ Datum values[Natts_pg_policy];
+ bool isnull[Natts_pg_policy];
+ bool replaces[Natts_pg_policy];
ObjectAddress target;
ObjectAddress myself;
Datum cmd_datum;
- char rseccmd;
- bool rseccmd_isnull;
+ char polcmd;
+ bool polcmd_isnull;
/* Parse role_ids */
if (stmt->roles != NULL)
- role_ids = rls_role_list_to_array(stmt->roles);
+ role_ids = policy_role_list_to_array(stmt->roles);
/* Get id of table. Also handles permissions checks. */
table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock,
@@ -662,7 +661,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
target_table = relation_open(table_id, NoLock);
- /* Parse the row-security clause */
+ /* Parse the using policy clause */
if (stmt->qual)
{
RangeTblEntry *rte;
@@ -675,13 +674,13 @@ AlterPolicy(AlterPolicyStmt *stmt)
qual = transformWhereClause(qual_pstate, copyObject(stmt->qual),
EXPR_KIND_WHERE,
- "ROW SECURITY");
+ "POLICY");
qual_parse_rtable = qual_pstate->p_rtable;
free_parsestate(qual_pstate);
}
- /* Parse the with-check row-security clause */
+ /* Parse the with-check policy clause */
if (stmt->with_check)
{
RangeTblEntry *rte;
@@ -695,7 +694,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
with_check_qual = transformWhereClause(with_check_pstate,
copyObject(stmt->with_check),
EXPR_KIND_WHERE,
- "ROW SECURITY");
+ "POLICY");
with_check_parse_rtable = with_check_pstate->p_rtable;
free_parsestate(with_check_pstate);
@@ -707,28 +706,28 @@ AlterPolicy(AlterPolicyStmt *stmt)
memset(isnull, 0, sizeof(isnull));
/* Find policy to update. */
- pg_rowsecurity_rel = heap_open(RowSecurityRelationId, RowExclusiveLock);
+ pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
- /* Set key - row security relation id. */
+ /* Set key - policy's relation id. */
ScanKeyInit(&skey[0],
- Anum_pg_rowsecurity_rsecrelid,
+ Anum_pg_policy_polrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(table_id));
- /* Set key - row security policy name. */
+ /* Set key - policy's name. */
ScanKeyInit(&skey[1],
- Anum_pg_rowsecurity_rsecpolname,
+ Anum_pg_policy_polname,
BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum(stmt->policy_name));
- sscan = systable_beginscan(pg_rowsecurity_rel,
- RowSecurityRelidPolnameIndexId, true, NULL, 2,
+ sscan = systable_beginscan(pg_policy_rel,
+ PolicyPolrelidPolnameIndexId, true, NULL, 2,
skey);
- rsec_tuple = systable_getnext(sscan);
+ policy_tuple = systable_getnext(sscan);
/* Check that the policy is found, raise an error if not. */
- if (!HeapTupleIsValid(rsec_tuple))
+ if (!HeapTupleIsValid(policy_tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("policy \"%s\" on table \"%s\" does not exist",
@@ -736,18 +735,18 @@ AlterPolicy(AlterPolicyStmt *stmt)
RelationGetRelationName(target_table))));
/* Get policy command */
- cmd_datum = heap_getattr(rsec_tuple, Anum_pg_rowsecurity_rseccmd,
- RelationGetDescr(pg_rowsecurity_rel),
- &rseccmd_isnull);
- if (rseccmd_isnull)
- rseccmd = 0;
+ cmd_datum = heap_getattr(policy_tuple, Anum_pg_policy_polcmd,
+ RelationGetDescr(pg_policy_rel),
+ &polcmd_isnull);
+ if (polcmd_isnull)
+ polcmd = 0;
else
- rseccmd = DatumGetChar(cmd_datum);
+ polcmd = DatumGetChar(cmd_datum);
/*
* If the command is SELECT or DELETE then WITH CHECK should be NULL.
*/
- if ((rseccmd == ACL_SELECT_CHR || rseccmd == ACL_DELETE_CHR)
+ if ((polcmd == ACL_SELECT_CHR || polcmd == ACL_DELETE_CHR)
&& stmt->with_check != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -757,52 +756,52 @@ AlterPolicy(AlterPolicyStmt *stmt)
* If the command is INSERT then WITH CHECK should be the only
* expression provided.
*/
- if ((rseccmd == ACL_INSERT_CHR)
+ if ((polcmd == ACL_INSERT_CHR)
&& stmt->qual != NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("only WITH CHECK expression allowed for INSERT")));
- rowsec_id = HeapTupleGetOid(rsec_tuple);
+ policy_id = HeapTupleGetOid(policy_tuple);
if (role_ids != NULL)
{
- replaces[Anum_pg_rowsecurity_rsecroles - 1] = true;
- values[Anum_pg_rowsecurity_rsecroles - 1] = PointerGetDatum(role_ids);
+ replaces[Anum_pg_policy_polroles - 1] = true;
+ values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids);
}
if (qual != NULL)
{
- replaces[Anum_pg_rowsecurity_rsecqual - 1] = true;
- values[Anum_pg_rowsecurity_rsecqual - 1]
+ replaces[Anum_pg_policy_polqual - 1] = true;
+ values[Anum_pg_policy_polqual - 1]
= CStringGetTextDatum(nodeToString(qual));
}
if (with_check_qual != NULL)
{
- replaces[Anum_pg_rowsecurity_rsecwithcheck - 1] = true;
- values[Anum_pg_rowsecurity_rsecwithcheck - 1]
+ replaces[Anum_pg_policy_polwithcheck - 1] = true;
+ values[Anum_pg_policy_polwithcheck - 1]
= CStringGetTextDatum(nodeToString(with_check_qual));
}
- new_tuple = heap_modify_tuple(rsec_tuple,
- RelationGetDescr(pg_rowsecurity_rel),
+ new_tuple = heap_modify_tuple(policy_tuple,
+ RelationGetDescr(pg_policy_rel),
values, isnull, replaces);
- simple_heap_update(pg_rowsecurity_rel, &new_tuple->t_self, new_tuple);
+ simple_heap_update(pg_policy_rel, &new_tuple->t_self, new_tuple);
/* Update Catalog Indexes */
- CatalogUpdateIndexes(pg_rowsecurity_rel, new_tuple);
+ CatalogUpdateIndexes(pg_policy_rel, new_tuple);
/* Update Dependencies. */
- deleteDependencyRecordsFor(RowSecurityRelationId, rowsec_id, false);
+ deleteDependencyRecordsFor(PolicyRelationId, policy_id, false);
/* Record Dependencies */
target.classId = RelationRelationId;
target.objectId = table_id;
target.objectSubId = 0;
- myself.classId = RowSecurityRelationId;
- myself.objectId = rowsec_id;
+ myself.classId = PolicyRelationId;
+ myself.objectId = policy_id;
myself.objectSubId = 0;
recordDependencyOn(&myself, &target, DEPENDENCY_AUTO);
@@ -820,9 +819,9 @@ AlterPolicy(AlterPolicyStmt *stmt)
/* Clean up. */
systable_endscan(sscan);
relation_close(target_table, NoLock);
- heap_close(pg_rowsecurity_rel, RowExclusiveLock);
+ heap_close(pg_policy_rel, RowExclusiveLock);
- return rowsec_id;
+ return policy_id;
}
/*
@@ -832,13 +831,13 @@ AlterPolicy(AlterPolicyStmt *stmt)
Oid
rename_policy(RenameStmt *stmt)
{
- Relation pg_rowsecurity_rel;
+ Relation pg_policy_rel;
Relation target_table;
Oid table_id;
Oid opoloid;
ScanKeyData skey[2];
SysScanDesc sscan;
- HeapTuple rsec_tuple;
+ HeapTuple policy_tuple;
/* Get id of table. Also handles permissions checks. */
table_id = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
@@ -848,74 +847,74 @@ rename_policy(RenameStmt *stmt)
target_table = relation_open(table_id, NoLock);
- pg_rowsecurity_rel = heap_open(RowSecurityRelationId, RowExclusiveLock);
+ pg_policy_rel = heap_open(PolicyRelationId, RowExclusiveLock);
/* First pass -- check for conflict */
- /* Add key - row security relation id. */
+ /* Add key - policy's relation id. */
ScanKeyInit(&skey[0],
- Anum_pg_rowsecurity_rsecrelid,
+ Anum_pg_policy_polrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(table_id));
- /* Add key - row security policy name. */
+ /* Add key - policy's name. */
ScanKeyInit(&skey[1],
- Anum_pg_rowsecurity_rsecpolname,
+ Anum_pg_policy_polname,
BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum(stmt->newname));
- sscan = systable_beginscan(pg_rowsecurity_rel,
- RowSecurityRelidPolnameIndexId, true, NULL, 2,
+ sscan = systable_beginscan(pg_policy_rel,
+ PolicyPolrelidPolnameIndexId, true, NULL, 2,
skey);
if (HeapTupleIsValid(systable_getnext(sscan)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("row-policy \"%s\" for table \"%s\" already exists",
+ errmsg("policy \"%s\" for table \"%s\" already exists",
stmt->newname, RelationGetRelationName(target_table))));
systable_endscan(sscan);
/* Second pass -- find existing policy and update */
- /* Add key - row security relation id. */
+ /* Add key - policy's relation id. */
ScanKeyInit(&skey[0],
- Anum_pg_rowsecurity_rsecrelid,
+ Anum_pg_policy_polrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(table_id));
- /* Add key - row security policy name. */
+ /* Add key - policy's name. */
ScanKeyInit(&skey[1],
- Anum_pg_rowsecurity_rsecpolname,
+ Anum_pg_policy_polname,
BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum(stmt->subname));
- sscan = systable_beginscan(pg_rowsecurity_rel,
- RowSecurityRelidPolnameIndexId, true, NULL, 2,
+ sscan = systable_beginscan(pg_policy_rel,
+ PolicyPolrelidPolnameIndexId, true, NULL, 2,
skey);
- rsec_tuple = systable_getnext(sscan);
+ policy_tuple = systable_getnext(sscan);
/* Complain if we did not find the policy */
- if (!HeapTupleIsValid(rsec_tuple))
+ if (!HeapTupleIsValid(policy_tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("row-policy \"%s\" for table \"%s\" does not exist",
+ errmsg("policy \"%s\" for table \"%s\" does not exist",
stmt->subname, RelationGetRelationName(target_table))));
- opoloid = HeapTupleGetOid(rsec_tuple);
+ opoloid = HeapTupleGetOid(policy_tuple);
- rsec_tuple = heap_copytuple(rsec_tuple);
+ policy_tuple = heap_copytuple(policy_tuple);
- namestrcpy(&((Form_pg_rowsecurity) GETSTRUCT(rsec_tuple))->rsecpolname,
+ namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname,
stmt->newname);
- simple_heap_update(pg_rowsecurity_rel, &rsec_tuple->t_self, rsec_tuple);
+ simple_heap_update(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
/* keep system catalog indexes current */
- CatalogUpdateIndexes(pg_rowsecurity_rel, rsec_tuple);
+ CatalogUpdateIndexes(pg_policy_rel, policy_tuple);
- InvokeObjectPostAlterHook(RowSecurityRelationId,
- HeapTupleGetOid(rsec_tuple), 0);
+ InvokeObjectPostAlterHook(PolicyRelationId,
+ HeapTupleGetOid(policy_tuple), 0);
/*
* Invalidate relation's relcache entry so that other backends (and
@@ -926,7 +925,7 @@ rename_policy(RenameStmt *stmt)
/* Clean up. */
systable_endscan(sscan);
- heap_close(pg_rowsecurity_rel, RowExclusiveLock);
+ heap_close(pg_policy_rel, RowExclusiveLock);
relation_close(target_table, NoLock);
return opoloid;
@@ -941,33 +940,33 @@ rename_policy(RenameStmt *stmt)
Oid
get_relation_policy_oid(Oid relid, const char *policy_name, bool missing_ok)
{
- Relation pg_rowsecurity_rel;
+ Relation pg_policy_rel;
ScanKeyData skey[2];
SysScanDesc sscan;
- HeapTuple rsec_tuple;
+ HeapTuple policy_tuple;
Oid policy_oid;
- pg_rowsecurity_rel = heap_open(RowSecurityRelationId, AccessShareLock);
+ pg_policy_rel = heap_open(PolicyRelationId, AccessShareLock);
- /* Add key - row security relation id. */
+ /* Add key - policy's relation id. */
ScanKeyInit(&skey[0],
- Anum_pg_rowsecurity_rsecrelid,
+ Anum_pg_policy_polrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
- /* Add key - row security policy name. */
+ /* Add key - policy's name. */
ScanKeyInit(&skey[1],
- Anum_pg_rowsecurity_rsecpolname,
+ Anum_pg_policy_polname,
BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum(policy_name));
- sscan = systable_beginscan(pg_rowsecurity_rel,
- RowSecurityRelidPolnameIndexId, true, NULL, 2,
+ sscan = systable_beginscan(pg_policy_rel,
+ PolicyPolrelidPolnameIndexId, true, NULL, 2,
skey);
- rsec_tuple = systable_getnext(sscan);
+ policy_tuple = systable_getnext(sscan);
- if (!HeapTupleIsValid(rsec_tuple))
+ if (!HeapTupleIsValid(policy_tuple))
{
if (!missing_ok)
ereport(ERROR,
@@ -978,11 +977,11 @@ get_relation_policy_oid(Oid relid, const char *policy_name, bool missing_ok)
policy_oid = InvalidOid;
}
else
- policy_oid = HeapTupleGetOid(rsec_tuple);
+ policy_oid = HeapTupleGetOid(policy_tuple);
/* Clean up. */
systable_endscan(sscan);
- heap_close(pg_rowsecurity_rel, AccessShareLock);
+ heap_close(pg_policy_rel, AccessShareLock);
return policy_oid;
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 56294552e71..2333e1bed92 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -37,7 +37,6 @@
#include "catalog/pg_inherits_fn.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
-#include "catalog/pg_rowsecurity.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
@@ -7986,6 +7985,24 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
colName)));
break;
+ case OCLASS_POLICY:
+
+ /*
+ * A policy can depend on a column because the column is
+ * specified in the policy's USING or WITH CHECK qual
+ * expressions. It might be possible to rewrite and recheck
+ * the policy expression, but punt for now. It's certainly
+ * easy enough to remove and recreate the policy; still,
+ * FIXME someday.
+ */
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot alter type of a column used in a policy definition"),
+ errdetail("%s depends on column \"%s\"",
+ getObjectDescription(&foundObject),
+ colName)));
+ break;
+
case OCLASS_DEFAULT:
/*
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index a753b207008..c499486f016 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -502,7 +502,7 @@ ExecutorRewind(QueryDesc *queryDesc)
* Returns true if permissions are adequate. Otherwise, throws an appropriate
* error if ereport_on_violation is true, or simply returns false otherwise.
*
- * Note that this does NOT address row-level security policies (aka: RLS). If
+ * Note that this does NOT address row level security policies (aka: RLS). If
* rows will be returned to the user as a result of this permission check
* passing, then RLS also needs to be consulted (and check_enable_rls()).
*
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index c97355e8fda..25f30676f02 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1171,7 +1171,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
/*
* If the subquery has the "security_barrier" flag, it means the subquery
- * originated from a view that must enforce row-level security. Then we
+ * originated from a view that must enforce row level security. Then we
* must not push down quals that contain leaky functions. (Ideally this
* would be checked inside subquery_is_pushdown_safe, but since we don't
* currently pass the RTE to that function, we must do it here.)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index fb74d6bf1f4..f752ecc16a5 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -177,7 +177,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
glob->lastPHId = 0;
glob->lastRowMarkId = 0;
glob->transientPlan = false;
- glob->has_rls = false;
+ glob->hasRowSecurity = false;
/* Determine what fraction of the plan is likely to be scanned */
if (cursorOptions & CURSOR_OPT_FAST_PLAN)
@@ -255,7 +255,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result->relationOids = glob->relationOids;
result->invalItems = glob->invalItems;
result->nParamExec = glob->nParamExec;
- result->has_rls = glob->has_rls;
+ result->hasRowSecurity = glob->hasRowSecurity;
return result;
}
@@ -1208,7 +1208,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
* This may add new security barrier subquery RTEs to the rangetable.
*/
expand_security_quals(root, tlist);
- root->glob->has_rls = parse->hasRowSecurity;
+ root->glob->hasRowSecurity = parse->hasRowSecurity;
/*
* Locate any window functions in the tlist. (We don't need to look
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index e630d0b6d81..4d3fbca5969 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2109,7 +2109,7 @@ extract_query_dependencies(Node *query,
glob.type = T_PlannerGlobal;
glob.relationOids = NIL;
glob.invalItems = NIL;
- glob.has_rls = false;
+ glob.hasRowSecurity = false;
MemSet(&root, 0, sizeof(root));
root.type = T_PlannerInfo;
@@ -2119,7 +2119,7 @@ extract_query_dependencies(Node *query,
*relationOids = glob.relationOids;
*invalItems = glob.invalItems;
- *hasRowSecurity = glob.has_rls;
+ *hasRowSecurity = glob.hasRowSecurity;
}
static bool
@@ -2135,8 +2135,8 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Query *query = (Query *) node;
ListCell *lc;
- /* Collect row-security information */
- context->glob->has_rls = query->hasRowSecurity;
+ /* Collect row security information */
+ context->glob->hasRowSecurity = query->hasRowSecurity;
if (query->commandType == CMD_UTILITY)
{
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index bd180e7e87b..7e48958ae85 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -5535,7 +5535,7 @@ opt_restart_seqs:
* COMMENT ON [ [ CONVERSION | COLLATION | DATABASE | DOMAIN |
* EXTENSION | EVENT TRIGGER | FOREIGN DATA WRAPPER |
* FOREIGN TABLE | INDEX | [PROCEDURAL] LANGUAGE |
- * MATERIALIZED VIEW | ROLE | SCHEMA | SEQUENCE |
+ * MATERIALIZED VIEW | POLICY | ROLE | SCHEMA | SEQUENCE |
* SERVER | TABLE | TABLESPACE |
* TEXT SEARCH CONFIGURATION | TEXT SEARCH DICTIONARY |
* TEXT SEARCH PARSER | TEXT SEARCH TEMPLATE | TYPE |
@@ -5601,6 +5601,15 @@ CommentStmt:
n->comment = $8;
$$ = (Node *) n;
}
+ | COMMENT ON POLICY name ON any_name IS comment_text
+ {
+ CommentStmt *n = makeNode(CommentStmt);
+ n->objtype = OBJECT_POLICY;
+ n->objname = lappend($6, makeString($4));
+ n->objargs = NIL;
+ n->comment = $8;
+ $$ = (Node *) n;
+ }
| COMMENT ON RULE name ON any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index e7021509017..ad983c7158b 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -1715,7 +1715,7 @@ fireRIRrules(Query *parsetree, List *activeRIRs, bool forUpdatePushedDown)
}
}
/*
- * If the RTE has row-security quals, apply them and recurse into the
+ * If the RTE has row security quals, apply them and recurse into the
* securityQuals.
*/
if (prepend_row_security_policies(parsetree, rte, rt_index))
@@ -1727,7 +1727,7 @@ fireRIRrules(Query *parsetree, List *activeRIRs, bool forUpdatePushedDown)
if (list_member_oid(activeRIRs, RelationGetRelid(rel)))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("infinite recursion detected in row-security policy for relation \"%s\"",
+ errmsg("infinite recursion detected in policy for relation \"%s\"",
RelationGetRelationName(rel))));
/*
diff --git a/src/backend/rewrite/rowsecurity.c b/src/backend/rewrite/rowsecurity.c
index 66c358cdec9..6c232dcf9ae 100644
--- a/src/backend/rewrite/rowsecurity.c
+++ b/src/backend/rewrite/rowsecurity.c
@@ -1,6 +1,6 @@
/*
* rewrite/rowsecurity.c
- * Routines to support policies for row-level security.
+ * Routines to support policies for row level security (aka RLS).
*
* Policies in PostgreSQL provide a mechanism to limit what records are
* returned to a user and what records a user is permitted to add to a table.
@@ -38,7 +38,7 @@
#include "access/sysattr.h"
#include "catalog/pg_class.h"
#include "catalog/pg_inherits_fn.h"
-#include "catalog/pg_rowsecurity.h"
+#include "catalog/pg_policy.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
@@ -72,8 +72,8 @@ static bool check_role_for_policy(ArrayType *policy_roles, Oid user_id);
row_security_policy_hook_type row_security_policy_hook = NULL;
/*
- * Check the given RTE to see whether it's already had row-security quals
- * expanded and, if not, prepend any row-security rules from built-in or
+ * Check the given RTE to see whether it's already had row security quals
+ * expanded and, if not, prepend any row security rules from built-in or
* plug-in sources to the securityQuals. The security quals are rewritten (for
* view expansion, etc) before being added to the RTE.
*
@@ -154,14 +154,14 @@ prepend_row_security_policies(Query* root, RangeTblEntry* rte, int rt_index)
/*
* Check if this is only the default-deny policy.
*
- * Normally, if the table has row-security enabled but there are
+ * Normally, if the table has row security enabled but there are
* no policies, we use a default-deny policy and not allow anything.
* However, when an extension uses the hook to add their own
* policies, we don't want to include the default deny policy or
* there won't be any way for a user to use an extension exclusively
* for the policies to be used.
*/
- if (((RowSecurityPolicy *) linitial(rowsec_policies))->rsecid
+ if (((RowSecurityPolicy *) linitial(rowsec_policies))->policy_id
== InvalidOid)
defaultDeny = true;
@@ -353,7 +353,7 @@ pull_row_security_policies(CmdType cmd, Relation relation, Oid user_id)
policy = palloc0(sizeof(RowSecurityPolicy));
policy->policy_name = pstrdup("default-deny policy");
- policy->rsecid = InvalidOid;
+ policy->policy_id = InvalidOid;
policy->cmd = '\0';
policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true,
'i');
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index d85ea1bbd3a..c537fe3236c 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -207,7 +207,7 @@ CreateCachedPlan(Node *raw_parse_tree,
plansource->generic_cost = -1;
plansource->total_custom_cost = 0;
plansource->num_custom_plans = 0;
- plansource->has_rls = false;
+ plansource->hasRowSecurity = false;
plansource->rowSecurityDisabled
= (security_context & SECURITY_ROW_LEVEL_DISABLED) != 0;
plansource->row_security_env = row_security;
@@ -383,7 +383,7 @@ CompleteCachedPlan(CachedPlanSource *plansource,
extract_query_dependencies((Node *) querytree_list,
&plansource->relationOids,
&plansource->invalItems,
- &plansource->has_rls);
+ &plansource->hasRowSecurity);
/*
* Also save the current search_path in the query_context. (This
@@ -617,7 +617,7 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
*/
if (plansource->is_valid
&& !plansource->rowSecurityDisabled
- && plansource->has_rls
+ && plansource->hasRowSecurity
&& (plansource->planUserId != GetUserId()
|| plansource->row_security_env != row_security))
plansource->is_valid = false;
@@ -766,7 +766,7 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
extract_query_dependencies((Node *) qlist,
&plansource->relationOids,
&plansource->invalItems,
- &plansource->has_rls);
+ &plansource->hasRowSecurity);
/*
* Also save the current search_path in the query_context. (This should
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index c80ef3c6f89..79244e56865 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -866,7 +866,7 @@ equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
if (policy2 == NULL)
return false;
- if (policy1->rsecid != policy2->rsecid)
+ if (policy1->policy_id != policy2->policy_id)
return false;
if (policy1->cmd != policy2->cmd)
return false;
@@ -3439,7 +3439,7 @@ RelationCacheInitializePhase3(void)
* they are not preserved in the cache. Note that we can never NOT
* have a policy while relrowsecurity is true,
* RelationBuildRowSecurity will create a single default-deny policy
- * if there is no policy defined in pg_rowsecurity.
+ * if there is no policy defined in pg_policy.
*/
if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
{
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 8bfc604eabb..1269ec3b28d 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -248,8 +248,8 @@ getSchemaData(Archive *fout, DumpOptions *dopt, int *numTablesPtr)
getRules(fout, &numRules);
if (g_verbose)
- write_msg(NULL, "reading row-security policies\n");
- getRowSecurity(fout, tblinfo, numTables);
+ write_msg(NULL, "reading policies\n");
+ getPolicies(fout, tblinfo, numTables);
*numTablesPtr = numTables;
return tblinfo;
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 1a2ebcb1f48..43065e84b2f 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -3328,6 +3328,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
strcmp(te->desc, "RULE") == 0 ||
strcmp(te->desc, "TRIGGER") == 0 ||
strcmp(te->desc, "ROW SECURITY") == 0 ||
+ strcmp(te->desc, "POLICY") == 0 ||
strcmp(te->desc, "USER MAPPING") == 0)
{
/* these object types don't have separate owners */
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 69d359458bc..4175ddc823e 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -233,7 +233,7 @@ static char *myFormatType(const char *typname, int32 typmod);
static void getBlobs(Archive *fout);
static void dumpBlob(Archive *fout, DumpOptions *dopt, BlobInfo *binfo);
static int dumpBlobs(Archive *fout, DumpOptions *dopt, void *arg);
-static void dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo);
+static void dumpPolicy(Archive *fout, DumpOptions *dopt, PolicyInfo *polinfo);
static void dumpDatabase(Archive *AH, DumpOptions *dopt);
static void dumpEncoding(Archive *AH);
static void dumpStdStrings(Archive *AH);
@@ -2765,22 +2765,22 @@ dumpBlobs(Archive *fout, DumpOptions *dopt, void *arg)
}
/*
- * getRowSecurity
- * get information about every row-security policy on a dumpable table.
+ * getPolicies
+ * get information about policies on a dumpable table.
*/
void
-getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
+getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
{
PQExpBuffer query;
PGresult *res;
- RowSecurityInfo *rsinfo;
+ PolicyInfo *polinfo;
int i_oid;
int i_tableoid;
- int i_rsecpolname;
- int i_rseccmd;
- int i_rsecroles;
- int i_rsecqual;
- int i_rsecwithcheck;
+ int i_polname;
+ int i_polcmd;
+ int i_polroles;
+ int i_polqual;
+ int i_polwithcheck;
int i,
j,
ntups;
@@ -2794,18 +2794,18 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
{
TableInfo *tbinfo = &tblinfo[i];
- /* Ignore row-security on tables not to be dumped */
+ /* Ignore row security on tables not to be dumped */
if (!tbinfo->dobj.dump)
continue;
if (g_verbose)
- write_msg(NULL, "reading row-security enabled for table \"%s\".\"%s\"\n",
+ write_msg(NULL, "reading row security enabled for table \"%s\".\"%s\"\n",
tbinfo->dobj.namespace->dobj.name,
tbinfo->dobj.name);
/*
- * Get row-security enabled information for the table. We represent
- * RLS enabled on a table by creating RowSecurityInfo object with an
+ * Get row security enabled information for the table. We represent
+ * RLS enabled on a table by creating PolicyInfo object with an
* empty policy.
*/
if (tbinfo->rowsec)
@@ -2814,23 +2814,23 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
* Note: use tableoid 0 so that this object won't be mistaken for
* something that pg_depend entries apply to.
*/
- rsinfo = pg_malloc(sizeof(RowSecurityInfo));
- rsinfo->dobj.objType = DO_ROW_SECURITY;
- rsinfo->dobj.catId.tableoid = 0;
- rsinfo->dobj.catId.oid = tbinfo->dobj.catId.oid;
- AssignDumpId(&rsinfo->dobj);
- rsinfo->dobj.namespace = tbinfo->dobj.namespace;
- rsinfo->dobj.name = pg_strdup(tbinfo->dobj.name);
- rsinfo->rstable = tbinfo;
- rsinfo->rsecpolname = NULL;
- rsinfo->rseccmd = NULL;
- rsinfo->rsecroles = NULL;
- rsinfo->rsecqual = NULL;
- rsinfo->rsecwithcheck = NULL;
+ polinfo = pg_malloc(sizeof(PolicyInfo));
+ polinfo->dobj.objType = DO_POLICY;
+ polinfo->dobj.catId.tableoid = 0;
+ polinfo->dobj.catId.oid = tbinfo->dobj.catId.oid;
+ AssignDumpId(&polinfo->dobj);
+ polinfo->dobj.namespace = tbinfo->dobj.namespace;
+ polinfo->dobj.name = pg_strdup(tbinfo->dobj.name);
+ polinfo->poltable = tbinfo;
+ polinfo->polname = NULL;
+ polinfo->polcmd = NULL;
+ polinfo->polroles = NULL;
+ polinfo->polqual = NULL;
+ polinfo->polwithcheck = NULL;
}
if (g_verbose)
- write_msg(NULL, "reading row-security policies for table \"%s\".\"%s\"\n",
+ write_msg(NULL, "reading policies for table \"%s\".\"%s\"\n",
tbinfo->dobj.namespace->dobj.name,
tbinfo->dobj.name);
@@ -2843,13 +2843,13 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
/* Get the policies for the table. */
appendPQExpBuffer(query,
- "SELECT oid, tableoid, s.rsecpolname, s.rseccmd, "
- "CASE WHEN s.rsecroles = '{0}' THEN 'PUBLIC' ELSE "
- " array_to_string(ARRAY(SELECT rolname from pg_roles WHERE oid = ANY(s.rsecroles)), ', ') END AS rsecroles, "
- "pg_get_expr(s.rsecqual, s.rsecrelid) AS rsecqual, "
- "pg_get_expr(s.rsecwithcheck, s.rsecrelid) AS rsecwithcheck "
- "FROM pg_catalog.pg_rowsecurity s "
- "WHERE rsecrelid = '%u'",
+ "SELECT oid, tableoid, pol.polname, pol.polcmd, "
+ "CASE WHEN pol.polroles = '{0}' THEN 'PUBLIC' ELSE "
+ " array_to_string(ARRAY(SELECT rolname from pg_roles WHERE oid = ANY(pol.polroles)), ', ') END AS polroles, "
+ "pg_get_expr(pol.polqual, pol.polrelid) AS polqual, "
+ "pg_get_expr(pol.polwithcheck, pol.polrelid) AS polwithcheck "
+ "FROM pg_catalog.pg_policy pol "
+ "WHERE polrelid = '%u'",
tbinfo->dobj.catId.oid);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -2868,45 +2868,44 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
i_oid = PQfnumber(res, "oid");
i_tableoid = PQfnumber(res, "tableoid");
- i_rsecpolname = PQfnumber(res, "rsecpolname");
- i_rseccmd = PQfnumber(res, "rseccmd");
- i_rsecroles = PQfnumber(res, "rsecroles");
- i_rsecqual = PQfnumber(res, "rsecqual");
- i_rsecwithcheck = PQfnumber(res, "rsecwithcheck");
+ i_polname = PQfnumber(res, "polname");
+ i_polcmd = PQfnumber(res, "polcmd");
+ i_polroles = PQfnumber(res, "polroles");
+ i_polqual = PQfnumber(res, "polqual");
+ i_polwithcheck = PQfnumber(res, "polwithcheck");
- rsinfo = pg_malloc(ntups * sizeof(RowSecurityInfo));
+ polinfo = pg_malloc(ntups * sizeof(PolicyInfo));
for (j = 0; j < ntups; j++)
{
- rsinfo[j].dobj.objType = DO_ROW_SECURITY;
- rsinfo[j].dobj.catId.tableoid =
+ polinfo[j].dobj.objType = DO_POLICY;
+ polinfo[j].dobj.catId.tableoid =
atooid(PQgetvalue(res, j, i_tableoid));
- rsinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
- AssignDumpId(&rsinfo[j].dobj);
- rsinfo[j].dobj.namespace = tbinfo->dobj.namespace;
- rsinfo[j].rstable = tbinfo;
- rsinfo[j].rsecpolname = pg_strdup(PQgetvalue(res, j,
- i_rsecpolname));
+ polinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
+ AssignDumpId(&polinfo[j].dobj);
+ polinfo[j].dobj.namespace = tbinfo->dobj.namespace;
+ polinfo[j].poltable = tbinfo;
+ polinfo[j].polname = pg_strdup(PQgetvalue(res, j, i_polname));
- rsinfo[j].dobj.name = pg_strdup(rsinfo[j].rsecpolname);
+ polinfo[j].dobj.name = pg_strdup(polinfo[j].polname);
- if (PQgetisnull(res, j, i_rseccmd))
- rsinfo[j].rseccmd = NULL;
+ if (PQgetisnull(res, j, i_polcmd))
+ polinfo[j].polcmd = NULL;
else
- rsinfo[j].rseccmd = pg_strdup(PQgetvalue(res, j, i_rseccmd));
+ polinfo[j].polcmd = pg_strdup(PQgetvalue(res, j, i_polcmd));
- rsinfo[j].rsecroles = pg_strdup(PQgetvalue(res, j, i_rsecroles));
+ polinfo[j].polroles = pg_strdup(PQgetvalue(res, j, i_polroles));
- if (PQgetisnull(res, j, i_rsecqual))
- rsinfo[j].rsecqual = NULL;
+ if (PQgetisnull(res, j, i_polqual))
+ polinfo[j].polqual = NULL;
else
- rsinfo[j].rsecqual = pg_strdup(PQgetvalue(res, j, i_rsecqual));
+ polinfo[j].polqual = pg_strdup(PQgetvalue(res, j, i_polqual));
- if (PQgetisnull(res, j, i_rsecwithcheck))
- rsinfo[j].rsecwithcheck = NULL;
+ if (PQgetisnull(res, j, i_polwithcheck))
+ polinfo[j].polwithcheck = NULL;
else
- rsinfo[j].rsecwithcheck
- = pg_strdup(PQgetvalue(res, j, i_rsecwithcheck));
+ polinfo[j].polwithcheck
+ = pg_strdup(PQgetvalue(res, j, i_polwithcheck));
}
PQclear(res);
}
@@ -2914,13 +2913,13 @@ getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables)
}
/*
- * dumpRowSecurity
- * dump the definition of the given row-security policy
+ * dumpPolicy
+ * dump the definition of the given policy
*/
static void
-dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo)
+dumpPolicy(Archive *fout, DumpOptions *dopt, PolicyInfo *polinfo)
{
- TableInfo *tbinfo = rsinfo->rstable;
+ TableInfo *tbinfo = polinfo->poltable;
PQExpBuffer query;
PQExpBuffer delqry;
const char *cmd;
@@ -2929,23 +2928,23 @@ dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo)
return;
/*
- * If rsecpolname is NULL, then this record is just indicating that ROW
+ * If polname is NULL, then this record is just indicating that ROW
* LEVEL SECURITY is enabled for the table. Dump as ALTER TABLE <table>
* ENABLE ROW LEVEL SECURITY.
*/
- if (rsinfo->rsecpolname == NULL)
+ if (polinfo->polname == NULL)
{
query = createPQExpBuffer();
appendPQExpBuffer(query, "ALTER TABLE %s ENABLE ROW LEVEL SECURITY;",
- fmtId(rsinfo->dobj.name));
+ fmtId(polinfo->dobj.name));
- ArchiveEntry(fout, rsinfo->dobj.catId, rsinfo->dobj.dumpId,
- rsinfo->dobj.name,
- rsinfo->dobj.namespace->dobj.name,
+ ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
+ polinfo->dobj.name,
+ polinfo->dobj.namespace->dobj.name,
NULL,
tbinfo->rolname, false,
- "ROW SECURITY", SECTION_NONE,
+ "ROW SECURITY", SECTION_POST_DATA,
query->data, "", NULL,
NULL, 0,
NULL, NULL);
@@ -2954,19 +2953,19 @@ dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo)
return;
}
- if (!rsinfo->rseccmd)
+ if (!polinfo->polcmd)
cmd = "ALL";
- else if (strcmp(rsinfo->rseccmd, "r") == 0)
+ else if (strcmp(polinfo->polcmd, "r") == 0)
cmd = "SELECT";
- else if (strcmp(rsinfo->rseccmd, "a") == 0)
+ else if (strcmp(polinfo->polcmd, "a") == 0)
cmd = "INSERT";
- else if (strcmp(rsinfo->rseccmd, "w") == 0)
+ else if (strcmp(polinfo->polcmd, "w") == 0)
cmd = "UPDATE";
- else if (strcmp(rsinfo->rseccmd, "d") == 0)
+ else if (strcmp(polinfo->polcmd, "d") == 0)
cmd = "DELETE";
else
{
- write_msg(NULL, "unexpected command type: '%s'\n", rsinfo->rseccmd);
+ write_msg(NULL, "unexpected command type: '%s'\n", polinfo->polcmd);
exit_nicely(1);
}
@@ -2974,28 +2973,28 @@ dumpRowSecurity(Archive *fout, DumpOptions *dopt, RowSecurityInfo *rsinfo)
delqry = createPQExpBuffer();
appendPQExpBuffer(query, "CREATE POLICY %s ON %s FOR %s",
- rsinfo->rsecpolname, fmtId(tbinfo->dobj.name), cmd);
+ polinfo->polname, fmtId(tbinfo->dobj.name), cmd);
- if (rsinfo->rsecroles != NULL)
- appendPQExpBuffer(query, " TO %s", rsinfo->rsecroles);
+ if (polinfo->polroles != NULL)
+ appendPQExpBuffer(query, " TO %s", polinfo->polroles);
- if (rsinfo->rsecqual != NULL)
- appendPQExpBuffer(query, " USING %s", rsinfo->rsecqual);
+ if (polinfo->polqual != NULL)
+ appendPQExpBuffer(query, " USING %s", polinfo->polqual);
- if (rsinfo->rsecwithcheck != NULL)
- appendPQExpBuffer(query, " WITH CHECK %s", rsinfo->rsecwithcheck);
+ if (polinfo->polwithcheck != NULL)
+ appendPQExpBuffer(query, " WITH CHECK %s", polinfo->polwithcheck);
appendPQExpBuffer(query, ";\n");
appendPQExpBuffer(delqry, "DROP POLICY %s ON %s;\n",
- rsinfo->rsecpolname, fmtId(tbinfo->dobj.name));
+ polinfo->polname, fmtId(tbinfo->dobj.name));
- ArchiveEntry(fout, rsinfo->dobj.catId, rsinfo->dobj.dumpId,
- rsinfo->dobj.name,
- rsinfo->dobj.namespace->dobj.name,
+ ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
+ polinfo->dobj.name,
+ polinfo->dobj.namespace->dobj.name,
NULL,
tbinfo->rolname, false,
- "ROW SECURITY", SECTION_POST_DATA,
+ "POLICY", SECTION_POST_DATA,
query->data, delqry->data, NULL,
NULL, 0,
NULL, NULL);
@@ -8232,8 +8231,8 @@ dumpDumpableObject(Archive *fout, DumpOptions *dopt, DumpableObject *dobj)
NULL, 0,
dumpBlobs, NULL);
break;
- case DO_ROW_SECURITY:
- dumpRowSecurity(fout, dopt, (RowSecurityInfo *) dobj);
+ case DO_POLICY:
+ dumpPolicy(fout, dopt, (PolicyInfo *) dobj);
break;
case DO_PRE_DATA_BOUNDARY:
case DO_POST_DATA_BOUNDARY:
@@ -15631,7 +15630,7 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
case DO_TRIGGER:
case DO_EVENT_TRIGGER:
case DO_DEFAULT_ACL:
- case DO_ROW_SECURITY:
+ case DO_POLICY:
/* Post-data objects: must come after the post-data boundary */
addObjectDependency(dobj, postDataBound->dumpId);
break;
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index a7eb2fd9364..d1d9ecbaa2d 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -76,7 +76,7 @@ typedef enum
DO_POST_DATA_BOUNDARY,
DO_EVENT_TRIGGER,
DO_REFRESH_MATVIEW,
- DO_ROW_SECURITY
+ DO_POLICY
} DumpableObjectType;
typedef struct _dumpableObject
@@ -210,7 +210,7 @@ typedef struct _tableInfo
bool hasindex; /* does it have any indexes? */
bool hasrules; /* does it have any rules? */
bool hastriggers; /* does it have any triggers? */
- bool rowsec; /* is row-security enabled? */
+ bool rowsec; /* is row security enabled? */
bool hasoids; /* does it have OIDs? */
uint32 frozenxid; /* for restore frozen xid */
uint32 minmxid; /* for restore min multi xid */
@@ -453,21 +453,21 @@ typedef struct _blobInfo
} BlobInfo;
/*
- * The RowSecurityInfo struct is used to represent row policies on a table and
+ * The PolicyInfo struct is used to represent policies on a table and
* to indicate if a table has RLS enabled (ENABLE ROW SECURITY). If
- * rsecpolname is NULL, then the record indicates ENABLE ROW SECURITY, while if
+ * polname is NULL, then the record indicates ENABLE ROW SECURITY, while if
* it's non-NULL then this is a regular policy definition.
*/
-typedef struct _rowSecurityInfo
+typedef struct _policyInfo
{
DumpableObject dobj;
- TableInfo *rstable;
- char *rsecpolname; /* null indicates RLS is enabled on rel */
- char *rseccmd;
- char *rsecroles;
- char *rsecqual;
- char *rsecwithcheck;
-} RowSecurityInfo;
+ TableInfo *poltable;
+ char *polname; /* null indicates RLS is enabled on rel */
+ char *polcmd;
+ char *polroles;
+ char *polqual;
+ char *polwithcheck;
+} PolicyInfo;
/* global decls */
extern bool force_quotes; /* double-quotes for identifiers flag */
@@ -549,6 +549,6 @@ extern DefaultACLInfo *getDefaultACLs(Archive *fout, DumpOptions *dopt, int *num
extern void getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[],
int numExtensions);
extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
-extern void getRowSecurity(Archive *fout, TableInfo tblinfo[], int numTables);
+extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
#endif /* PG_DUMP_H */
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 030bccc7e65..0e62af27765 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -28,8 +28,8 @@ static const char *modulename = gettext_noop("sorter");
* by OID. (This is a relatively crude hack to provide semi-reasonable
* behavior for old databases without full dependency info.) Note: collations,
* extensions, text search, foreign-data, materialized view, event trigger,
- * and default ACL objects can't really happen here, so the rather bogus
- * priorities for them don't matter.
+ * policies, and default ACL objects can't really happen here, so the rather
+ * bogus priorities for them don't matter.
*
* NOTE: object-type priorities must match the section assignments made in
* pg_dump.c; that is, PRE_DATA objects must sort before DO_PRE_DATA_BOUNDARY,
@@ -73,7 +73,7 @@ static const int oldObjectTypePriority[] =
13, /* DO_POST_DATA_BOUNDARY */
20, /* DO_EVENT_TRIGGER */
15, /* DO_REFRESH_MATVIEW */
- 21 /* DO_ROW_SECURITY */
+ 21 /* DO_POLICY */
};
/*
@@ -122,7 +122,7 @@ static const int newObjectTypePriority[] =
25, /* DO_POST_DATA_BOUNDARY */
32, /* DO_EVENT_TRIGGER */
33, /* DO_REFRESH_MATVIEW */
- 34 /* DO_ROW_SECURITY */
+ 34 /* DO_POLICY */
};
static DumpId preDataBoundId;
@@ -1438,9 +1438,9 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
"BLOB DATA (ID %d)",
obj->dumpId);
return;
- case DO_ROW_SECURITY:
+ case DO_POLICY:
snprintf(buf, bufsize,
- "ROW-SECURITY POLICY (ID %d OID %u)",
+ "POLICY (ID %d OID %u)",
obj->dumpId, obj->catId.oid);
return;
case DO_PRE_DATA_BOUNDARY:
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index a062fa871fa..5a9ceca0df5 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -783,31 +783,31 @@ permissionsList(const char *pattern)
if (pset.sversion >= 90500)
appendPQExpBuffer(&buf,
",\n pg_catalog.array_to_string(ARRAY(\n"
- " SELECT rsecpolname\n"
- " || CASE WHEN rseccmd IS NOT NULL THEN\n"
- " E' (' || rseccmd || E')'\n"
+ " SELECT polname\n"
+ " || CASE WHEN polcmd IS NOT NULL THEN\n"
+ " E' (' || polcmd || E')'\n"
" ELSE E':' \n"
" END\n"
- " || CASE WHEN rs.rsecqual IS NOT NULL THEN\n"
- " E'\\n (u): ' || pg_catalog.pg_get_expr(rsecqual, rsecrelid)\n"
+ " || CASE WHEN polqual IS NOT NULL THEN\n"
+ " E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n"
" ELSE E''\n"
" END\n"
- " || CASE WHEN rsecwithcheck IS NOT NULL THEN\n"
- " E'\\n (c): ' || pg_catalog.pg_get_expr(rsecwithcheck, rsecrelid)\n"
+ " || CASE WHEN polwithcheck IS NOT NULL THEN\n"
+ " E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n"
" ELSE E''\n"
" END"
- " || CASE WHEN rs.rsecroles <> '{0}' THEN\n"
+ " || CASE WHEN polroles <> '{0}' THEN\n"
" E'\\n to: ' || pg_catalog.array_to_string(\n"
" ARRAY(\n"
" SELECT rolname\n"
" FROM pg_catalog.pg_roles\n"
- " WHERE oid = ANY (rs.rsecroles)\n"
+ " WHERE oid = ANY (polroles)\n"
" ORDER BY 1\n"
" ), E', ')\n"
" ELSE E''\n"
" END\n"
- " FROM pg_catalog.pg_rowsecurity rs\n"
- " WHERE rsecrelid = c.oid), E'\\n')\n"
+ " FROM pg_catalog.pg_policy pol\n"
+ " WHERE polrelid = c.oid), E'\\n')\n"
" AS \"%s\"",
gettext_noop("Policies"));
@@ -2001,27 +2001,19 @@ describeOneTableDetails(const char *schemaname,
/* print any row-level policies */
if (pset.sversion >= 90500)
{
- appendPQExpBuffer(&buf,
- ",\n pg_catalog.pg_get_expr(rs.rsecqual, c.oid) as \"%s\"",
- gettext_noop("Row-security"));
-
- if (verbose)
- appendPQExpBuffer(&buf,
- "\n LEFT JOIN pg_rowsecurity rs ON rs.rsecrelid = c.oid");
-
printfPQExpBuffer(&buf,
- "SELECT rs.rsecpolname,\n"
- "CASE WHEN rs.rsecroles = '{0}' THEN NULL ELSE array_to_string(array(select rolname from pg_roles where oid = any (rs.rsecroles) order by 1),',') END,\n"
- "pg_catalog.pg_get_expr(rs.rsecqual, rs.rsecrelid),\n"
- "pg_catalog.pg_get_expr(rs.rsecwithcheck, rs.rsecrelid),\n"
- "CASE rs.rseccmd \n"
+ "SELECT pol.polname,\n"
+ "CASE WHEN pol.polroles = '{0}' THEN NULL ELSE array_to_string(array(select rolname from pg_roles where oid = any (pol.polroles) order by 1),',') END,\n"
+ "pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),\n"
+ "pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),\n"
+ "CASE pol.polcmd \n"
"WHEN 'r' THEN 'SELECT'\n"
"WHEN 'u' THEN 'UPDATE'\n"
"WHEN 'a' THEN 'INSERT'\n"
"WHEN 'd' THEN 'DELETE'\n"
"END AS cmd\n"
- "FROM pg_catalog.pg_rowsecurity rs\n"
- "WHERE rs.rsecrelid = '%s' ORDER BY 1;",
+ "FROM pg_catalog.pg_policy pol\n"
+ "WHERE pol.polrelid = '%s' ORDER BY 1;",
oid);
result = PSQLexec(buf.data);
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 278d3952d4d..1bb5a8373f3 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -2069,7 +2069,7 @@ psql_completion(const char *text, int start, int end)
static const char *const list_COMMENT[] =
{"CAST", "COLLATION", "CONVERSION", "DATABASE", "EVENT TRIGGER", "EXTENSION",
"FOREIGN DATA WRAPPER", "FOREIGN TABLE",
- "SERVER", "INDEX", "LANGUAGE", "RULE", "SCHEMA", "SEQUENCE",
+ "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
"TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
"OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
"TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index b670902b7d2..a9290886252 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201411251
+#define CATALOG_VERSION_NO 201411271
#endif
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 6a4913a66e5..87ac9240ae9 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -147,7 +147,7 @@ typedef enum ObjectClass
OCLASS_DEFACL, /* pg_default_acl */
OCLASS_EXTENSION, /* pg_extension */
OCLASS_EVENT_TRIGGER, /* pg_event_trigger */
- OCLASS_ROWSECURITY, /* pg_rowsecurity */
+ OCLASS_POLICY, /* pg_policy */
MAX_OCLASS /* MUST BE LAST */
} ObjectClass;
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 870692cf54f..bde1a848fee 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -299,11 +299,11 @@ DECLARE_UNIQUE_INDEX(pg_extension_name_index, 3081, on pg_extension using btree(
DECLARE_UNIQUE_INDEX(pg_range_rngtypid_index, 3542, on pg_range using btree(rngtypid oid_ops));
#define RangeTypidIndexId 3542
-DECLARE_UNIQUE_INDEX(pg_rowsecurity_oid_index, 3257, on pg_rowsecurity using btree(oid oid_ops));
-#define RowSecurityOidIndexId 3257
+DECLARE_UNIQUE_INDEX(pg_policy_oid_index, 3257, on pg_policy using btree(oid oid_ops));
+#define PolicyOidIndexId 3257
-DECLARE_UNIQUE_INDEX(pg_rowsecurity_polname_relid_index, 3258, on pg_rowsecurity using btree(rsecrelid oid_ops, rsecpolname name_ops));
-#define RowSecurityRelidPolnameIndexId 3258
+DECLARE_UNIQUE_INDEX(pg_policy_polrelid_polname_index, 3258, on pg_policy using btree(polrelid oid_ops, polname name_ops));
+#define PolicyPolrelidPolnameIndexId 3258
/* last step of initialization script: build the indexes declared above */
BUILD_INDICES
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 22c55a94903..1054cd0500b 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -65,7 +65,7 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO
bool relhasrules; /* has (or has had) any rules */
bool relhastriggers; /* has (or has had) any TRIGGERs */
bool relhassubclass; /* has (or has had) derived classes */
- bool relrowsecurity; /* row-security is enabled or not */
+ bool relrowsecurity; /* row security is enabled or not */
bool relispopulated; /* matview currently holds query results */
char relreplident; /* see REPLICA_IDENTITY_xxx constants */
TransactionId relfrozenxid; /* all Xids < this are frozen in this rel */
diff --git a/src/include/catalog/pg_policy.h b/src/include/catalog/pg_policy.h
new file mode 100644
index 00000000000..5d377a48389
--- /dev/null
+++ b/src/include/catalog/pg_policy.h
@@ -0,0 +1,53 @@
+/*
+ * pg_policy.h
+ * definition of the system "policy" relation (pg_policy)
+ *
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ */
+#ifndef PG_POLICY_H
+#define PG_POLICY_H
+
+#include "catalog/genbki.h"
+
+/* ----------------
+ * pg_policy definition. cpp turns this into
+ * typedef struct FormData_pg_policy
+ * ----------------
+ */
+#define PolicyRelationId 3256
+
+CATALOG(pg_policy,3256)
+{
+ NameData polname; /* Policy name. */
+ Oid polrelid; /* Oid of the relation with policy. */
+ char polcmd; /* One of ACL_*_CHR, or \0 for all */
+
+#ifdef CATALOG_VARLEN
+ Oid polroles[1] /* Roles associated with policy, not-NULL */
+ pg_node_tree polqual; /* Policy quals. */
+ pg_node_tree polwithcheck; /* WITH CHECK quals. */
+#endif
+} FormData_pg_policy;
+
+/* ----------------
+ * Form_pg_policy corresponds to a pointer to a row with
+ * the format of pg_policy relation.
+ * ----------------
+ */
+typedef FormData_pg_policy *Form_pg_policy;
+
+/* ----------------
+ * compiler constants for pg_policy
+ * ----------------
+ */
+#define Natts_pg_policy 6
+#define Anum_pg_policy_polname 1
+#define Anum_pg_policy_polrelid 2
+#define Anum_pg_policy_polcmd 3
+#define Anum_pg_policy_polroles 4
+#define Anum_pg_policy_polqual 5
+#define Anum_pg_policy_polwithcheck 6
+
+#endif /* PG_POLICY_H */
diff --git a/src/include/catalog/pg_rowsecurity.h b/src/include/catalog/pg_rowsecurity.h
deleted file mode 100644
index 2638d5e6848..00000000000
--- a/src/include/catalog/pg_rowsecurity.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * pg_rowsecurity.h
- * definition of the system catalog for row-security policy (pg_rowsecurity)
- *
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- */
-#ifndef PG_ROWSECURITY_H
-#define PG_ROWSECURITY_H
-
-#include "catalog/genbki.h"
-
-/* ----------------
- * pg_rowsecurity definition. cpp turns this into
- * typedef struct FormData_pg_rowsecurity
- * ----------------
- */
-#define RowSecurityRelationId 3256
-
-CATALOG(pg_rowsecurity,3256)
-{
- NameData rsecpolname; /* Policy name. */
- Oid rsecrelid; /* Oid of the relation with policy. */
- char rseccmd; /* One of ACL_*_CHR, or \0 for all */
-
-#ifdef CATALOG_VARLEN
- Oid rsecroles[1] /* Roles associated with policy, not-NULL */
- pg_node_tree rsecqual; /* Policy quals. */
- pg_node_tree rsecwithcheck; /* WITH CHECK quals. */
-#endif
-} FormData_pg_rowsecurity;
-
-/* ----------------
- * Form_pg_rowsecurity corresponds to a pointer to a row with
- * the format of pg_rowsecurity relation.
- * ----------------
- */
-typedef FormData_pg_rowsecurity *Form_pg_rowsecurity;
-
-/* ----------------
- * compiler constants for pg_rowsecurity
- * ----------------
- */
-#define Natts_pg_rowsecurity 6
-#define Anum_pg_rowsecurity_rsecpolname 1
-#define Anum_pg_rowsecurity_rsecrelid 2
-#define Anum_pg_rowsecurity_rseccmd 3
-#define Anum_pg_rowsecurity_rsecroles 4
-#define Anum_pg_rowsecurity_rsecqual 5
-#define Anum_pg_rowsecurity_rsecwithcheck 6
-
-#endif /* PG_ROWSECURITY_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 3e4f815852d..255415d93a3 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -121,7 +121,7 @@ typedef struct Query
bool hasRecursive; /* WITH RECURSIVE was specified */
bool hasModifyingCTE; /* has INSERT/UPDATE/DELETE in WITH */
bool hasForUpdate; /* FOR [KEY] UPDATE/SHARE was specified */
- bool hasRowSecurity; /* Row-security policy is applied */
+ bool hasRowSecurity; /* row security applied? */
List *cteList; /* WITH list (of CommonTableExpr's) */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 7f9eaf0df26..48203a0d21f 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -70,7 +70,7 @@ typedef struct PlannedStmt
int nParamExec; /* number of PARAM_EXEC Params used */
- bool has_rls; /* row-security applied? */
+ bool hasRowSecurity; /* row security applied? */
} PlannedStmt;
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 810b9c8893b..711649687ae 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -101,7 +101,7 @@ typedef struct PlannerGlobal
bool transientPlan; /* redo plan when TransactionXmin changes? */
- bool has_rls; /* row-security is applied? */
+ bool hasRowSecurity; /* row security applied? */
} PlannerGlobal;
diff --git a/src/include/rewrite/rowsecurity.h b/src/include/rewrite/rowsecurity.h
index 8b4d5c0918f..4144b25fec7 100644
--- a/src/include/rewrite/rowsecurity.h
+++ b/src/include/rewrite/rowsecurity.h
@@ -19,7 +19,7 @@
typedef struct RowSecurityPolicy
{
- Oid rsecid; /* OID of the policy */
+ Oid policy_id; /* OID of the policy */
char *policy_name; /* Name of the policy */
char cmd; /* Type of command policy is for */
ArrayType *roles; /* Array of roles policy is for */
@@ -30,8 +30,8 @@ typedef struct RowSecurityPolicy
typedef struct RowSecurityDesc
{
- MemoryContext rscxt; /* row-security memory context */
- List *policies; /* list of row-security policies */
+ MemoryContext rscxt; /* row security memory context */
+ List *policies; /* list of row security policies */
} RowSecurityDesc;
/* GUC variable */
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
index 2622ceb54bc..9e1c0000aab 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -109,9 +109,9 @@ typedef struct CachedPlanSource
double generic_cost; /* cost of generic plan, or -1 if not known */
double total_custom_cost; /* total cost of custom plans so far */
int num_custom_plans; /* number of plans included in total */
- bool has_rls; /* planned with row-security? */
+ bool hasRowSecurity; /* planned with row security? */
int row_security_env; /* row security setting when planned */
- bool rowSecurityDisabled; /* is row-security disabled? */
+ bool rowSecurityDisabled; /* is row security disabled? */
} CachedPlanSource;
/*
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 01a9ef32ebf..48ebf594943 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -106,7 +106,7 @@ typedef struct RelationData
MemoryContext rd_rulescxt; /* private memory cxt for rd_rules, if any */
TriggerDesc *trigdesc; /* Trigger info, or NULL if rel has none */
/* use "struct" here to avoid needing to include rowsecurity.h: */
- struct RowSecurityDesc *rd_rsdesc; /* Row-security policies, or NULL */
+ struct RowSecurityDesc *rd_rsdesc; /* row security policies, or NULL */
/* data managed by RelationGetIndexList: */
List *rd_indexlist; /* list of OIDs of indexes on relation */
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
index 376292ac2ef..5eb61c46aa2 100644
--- a/src/test/regress/expected/rowsecurity.out
+++ b/src/test/regress/expected/rowsecurity.out
@@ -173,7 +173,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dt
Index Cond: (pguser = "current_user"())
(11 rows)
--- only owner can change row-level security
+-- only owner can change policies
ALTER POLICY p1 ON document USING (true); --fail
ERROR: must be owner of relation document
DROP POLICY p1 ON document; --fail
@@ -724,7 +724,7 @@ CREATE TABLE dependent (x integer, y integer);
CREATE POLICY d1 ON dependent FOR ALL
TO PUBLIC
USING (x = (SELECT d.x FROM dependee d WHERE d.y = y));
-DROP TABLE dependee; -- Should fail without CASCADE due to dependency on row-security qual?
+DROP TABLE dependee; -- Should fail without CASCADE due to dependency on row security qual?
ERROR: cannot drop table dependee because other objects depend on it
DETAIL: policy d1 on table dependent depends on table dependee
HINT: Use DROP ... CASCADE to drop the dependent objects too.
@@ -746,7 +746,7 @@ CREATE POLICY r1 ON rec1 USING (x = (SELECT r.x FROM rec1 r WHERE y = r.y));
ALTER TABLE rec1 ENABLE ROW LEVEL SECURITY;
SET SESSION AUTHORIZATION rls_regress_user1;
SELECT * FROM rec1; -- fail, direct recursion
-ERROR: infinite recursion detected in row-security policy for relation "rec1"
+ERROR: infinite recursion detected in policy for relation "rec1"
--
-- Mutual recursion
--
@@ -757,7 +757,7 @@ CREATE POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1 WHERE y = b));
ALTER TABLE rec2 ENABLE ROW LEVEL SECURITY;
SET SESSION AUTHORIZATION rls_regress_user1;
SELECT * FROM rec1; -- fail, mutual recursion
-ERROR: infinite recursion detected in row-security policy for relation "rec1"
+ERROR: infinite recursion detected in policy for relation "rec1"
--
-- Mutual recursion via views
--
@@ -769,7 +769,7 @@ ALTER POLICY r1 ON rec1 USING (x = (SELECT a FROM rec2v WHERE b = y));
ALTER POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1v WHERE y = b));
SET SESSION AUTHORIZATION rls_regress_user1;
SELECT * FROM rec1; -- fail, mutual recursion via views
-ERROR: infinite recursion detected in row-security policy for relation "rec1"
+ERROR: infinite recursion detected in policy for relation "rec1"
--
-- Mutual recursion via .s.b views
--
@@ -785,7 +785,7 @@ CREATE POLICY r1 ON rec1 USING (x = (SELECT a FROM rec2v WHERE b = y));
CREATE POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1v WHERE y = b));
SET SESSION AUTHORIZATION rls_regress_user1;
SELECT * FROM rec1; -- fail, mutual recursion via s.b. views
-ERROR: infinite recursion detected in row-security policy for relation "rec1"
+ERROR: infinite recursion detected in policy for relation "rec1"
--
-- recursive RLS and VIEWs in policy
--
@@ -803,9 +803,9 @@ ALTER TABLE s2 ENABLE ROW LEVEL SECURITY;
SET SESSION AUTHORIZATION rls_regress_user1;
CREATE VIEW v2 AS SELECT * FROM s2 WHERE y like '%af%';
SELECT * FROM s1 WHERE f_leak(b); -- fail (infinite recursion)
-ERROR: infinite recursion detected in row-security policy for relation "s1"
+ERROR: infinite recursion detected in policy for relation "s1"
INSERT INTO s1 VALUES (1, 'foo'); -- fail (infinite recursion)
-ERROR: infinite recursion detected in row-security policy for relation "s1"
+ERROR: infinite recursion detected in policy for relation "s1"
SET SESSION AUTHORIZATION rls_regress_user0;
DROP POLICY p3 on s1;
ALTER POLICY p2 ON s2 USING (x % 2 = 0);
@@ -897,7 +897,7 @@ SET SESSION AUTHORIZATION rls_regress_user0;
ALTER POLICY p2 ON s2 USING (x in (select a from s1 where b like '%d2%'));
SET SESSION AUTHORIZATION rls_regress_user1;
SELECT * FROM s1 WHERE f_leak(b); -- fail (infinite recursion via view)
-ERROR: infinite recursion detected in row-security policy for relation "s1"
+ERROR: infinite recursion detected in policy for relation "s1"
-- prepared statement with rls_regress_user0 privilege
PREPARE p1(int) AS SELECT * FROM t1 WHERE a <= $1;
EXECUTE p1(2);
@@ -1714,24 +1714,24 @@ WITH cte1 AS (INSERT INTO t1 VALUES (20, 'Success') RETURNING *) SELECT * FROM c
--
RESET SESSION AUTHORIZATION;
ALTER POLICY p1 ON t1 RENAME TO p1; --fail
-ERROR: row-policy "p1" for table "t1" already exists
-SELECT rsecpolname, relname
- FROM pg_rowsecurity rs
- JOIN pg_class pc ON (pc.oid = rs.rsecrelid)
+ERROR: policy "p1" for table "t1" already exists
+SELECT polname, relname
+ FROM pg_policy pol
+ JOIN pg_class pc ON (pc.oid = pol.polrelid)
WHERE relname = 't1';
- rsecpolname | relname
--------------+---------
- p1 | t1
+ polname | relname
+---------+---------
+ p1 | t1
(1 row)
ALTER POLICY p1 ON t1 RENAME TO p2; --ok
-SELECT rsecpolname, relname
- FROM pg_rowsecurity rs
- JOIN pg_class pc ON (pc.oid = rs.rsecrelid)
+SELECT polname, relname
+ FROM pg_policy pol
+ JOIN pg_class pc ON (pc.oid = pol.polrelid)
WHERE relname = 't1';
- rsecpolname | relname
--------------+---------
- p2 | t1
+ polname | relname
+---------+---------
+ p2 | t1
(1 row)
--
@@ -2161,7 +2161,7 @@ SET row_security TO ON;
COPY copy_t FROM STDIN; --ok
SET row_security TO FORCE;
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR: COPY FROM not supported with row security.
+ERROR: COPY FROM not supported with row level security.
HINT: Use direct INSERT statements instead.
-- Check COPY FROM as user with permissions.
SET SESSION AUTHORIZATION rls_regress_user1;
@@ -2170,11 +2170,11 @@ COPY copy_t FROM STDIN; --fail - insufficient privilege to bypass rls.
ERROR: insufficient privilege to bypass row security.
SET row_security TO ON;
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR: COPY FROM not supported with row security.
+ERROR: COPY FROM not supported with row level security.
HINT: Use direct INSERT statements instead.
SET row_security TO FORCE;
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR: COPY FROM not supported with row security.
+ERROR: COPY FROM not supported with row level security.
HINT: Use direct INSERT statements instead.
-- Check COPY TO as user with permissions and BYPASSRLS
SET SESSION AUTHORIZATION rls_regress_exempt_user;
@@ -2182,11 +2182,11 @@ SET row_security TO OFF;
COPY copy_t FROM STDIN; --ok
SET row_security TO ON;
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR: COPY FROM not supported with row security.
+ERROR: COPY FROM not supported with row level security.
HINT: Use direct INSERT statements instead.
SET row_security TO FORCE;
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
-ERROR: COPY FROM not supported with row security.
+ERROR: COPY FROM not supported with row level security.
HINT: Use direct INSERT statements instead.
-- Check COPY FROM as user without permissions.
SET SESSION AUTHORIZATION rls_regress_user2;
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index c79b45c53a0..80c33512916 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1355,18 +1355,18 @@ pg_matviews| SELECT n.nspname AS schemaname,
WHERE (c.relkind = 'm'::"char");
pg_policies| SELECT n.nspname AS schemaname,
c.relname AS tablename,
- rs.rsecpolname AS policyname,
+ pol.polname AS policyname,
CASE
- WHEN (rs.rsecroles = '{0}'::oid[]) THEN (string_to_array('public'::text, ''::text))::name[]
+ WHEN (pol.polroles = '{0}'::oid[]) THEN (string_to_array('public'::text, ''::text))::name[]
ELSE ARRAY( SELECT pg_authid.rolname
FROM pg_authid
- WHERE (pg_authid.oid = ANY (rs.rsecroles))
+ WHERE (pg_authid.oid = ANY (pol.polroles))
ORDER BY pg_authid.rolname)
END AS roles,
CASE
- WHEN (rs.rseccmd IS NULL) THEN 'ALL'::text
+ WHEN (pol.polcmd IS NULL) THEN 'ALL'::text
ELSE
- CASE rs.rseccmd
+ CASE pol.polcmd
WHEN 'r'::"char" THEN 'SELECT'::text
WHEN 'a'::"char" THEN 'INSERT'::text
WHEN 'u'::"char" THEN 'UPDATE'::text
@@ -1374,10 +1374,10 @@ pg_policies| SELECT n.nspname AS schemaname,
ELSE NULL::text
END
END AS cmd,
- pg_get_expr(rs.rsecqual, rs.rsecrelid) AS qual,
- pg_get_expr(rs.rsecwithcheck, rs.rsecrelid) AS with_check
- FROM ((pg_rowsecurity rs
- JOIN pg_class c ON ((c.oid = rs.rsecrelid)))
+ pg_get_expr(pol.polqual, pol.polrelid) AS qual,
+ pg_get_expr(pol.polwithcheck, pol.polrelid) AS with_check
+ FROM ((pg_policy pol
+ JOIN pg_class c ON ((c.oid = pol.polrelid)))
LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)));
pg_prepared_statements| SELECT p.name,
p.statement,
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 2c8ec118a75..c7be273ae16 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -118,10 +118,10 @@ pg_opclass|t
pg_operator|t
pg_opfamily|t
pg_pltemplate|t
+pg_policy|t
pg_proc|t
pg_range|t
pg_rewrite|t
-pg_rowsecurity|t
pg_seclabel|t
pg_shdepend|t
pg_shdescription|t
diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql
index 2d5ddb4b832..181043f4164 100644
--- a/src/test/regress/sql/rowsecurity.sql
+++ b/src/test/regress/sql/rowsecurity.sql
@@ -102,7 +102,7 @@ SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle) ORDER BY did;
EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle);
EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle);
--- only owner can change row-level security
+-- only owner can change policies
ALTER POLICY p1 ON document USING (true); --fail
DROP POLICY p1 ON document; --fail
@@ -274,7 +274,7 @@ CREATE POLICY d1 ON dependent FOR ALL
TO PUBLIC
USING (x = (SELECT d.x FROM dependee d WHERE d.y = y));
-DROP TABLE dependee; -- Should fail without CASCADE due to dependency on row-security qual?
+DROP TABLE dependee; -- Should fail without CASCADE due to dependency on row security qual?
DROP TABLE dependee CASCADE;
@@ -659,16 +659,16 @@ WITH cte1 AS (INSERT INTO t1 VALUES (20, 'Success') RETURNING *) SELECT * FROM c
RESET SESSION AUTHORIZATION;
ALTER POLICY p1 ON t1 RENAME TO p1; --fail
-SELECT rsecpolname, relname
- FROM pg_rowsecurity rs
- JOIN pg_class pc ON (pc.oid = rs.rsecrelid)
+SELECT polname, relname
+ FROM pg_policy pol
+ JOIN pg_class pc ON (pc.oid = pol.polrelid)
WHERE relname = 't1';
ALTER POLICY p1 ON t1 RENAME TO p2; --ok
-SELECT rsecpolname, relname
- FROM pg_rowsecurity rs
- JOIN pg_class pc ON (pc.oid = rs.rsecrelid)
+SELECT polname, relname
+ FROM pg_policy pol
+ JOIN pg_class pc ON (pc.oid = pol.polrelid)
WHERE relname = 't1';
--