summaryrefslogtreecommitdiffstats
path: root/src/test/modules/test_rls_hooks
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/modules/test_rls_hooks')
-rw-r--r--src/test/modules/test_rls_hooks/.gitignore4
-rw-r--r--src/test/modules/test_rls_hooks/Makefile27
-rw-r--r--src/test/modules/test_rls_hooks/README16
-rw-r--r--src/test/modules/test_rls_hooks/expected/test_rls_hooks.out201
-rw-r--r--src/test/modules/test_rls_hooks/rls_hooks.conf1
-rw-r--r--src/test/modules/test_rls_hooks/sql/test_rls_hooks.sql176
-rw-r--r--src/test/modules/test_rls_hooks/test_rls_hooks.c178
-rw-r--r--src/test/modules/test_rls_hooks/test_rls_hooks.control4
-rw-r--r--src/test/modules/test_rls_hooks/test_rls_hooks.h25
9 files changed, 632 insertions, 0 deletions
diff --git a/src/test/modules/test_rls_hooks/.gitignore b/src/test/modules/test_rls_hooks/.gitignore
new file mode 100644
index 0000000..5dcb3ff
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/test_rls_hooks/Makefile b/src/test/modules/test_rls_hooks/Makefile
new file mode 100644
index 0000000..a4f7d85
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/Makefile
@@ -0,0 +1,27 @@
+# src/test/modules/test_rls_hooks/Makefile
+
+MODULE_big = test_rls_hooks
+OBJS = \
+ $(WIN32RES) \
+ test_rls_hooks.o
+PGFILEDESC = "test_rls_hooks - example use of RLS hooks"
+
+EXTENSION = test_rls_hooks
+# DATA = test_rls_hooks--1.0.sql
+
+REGRESS = test_rls_hooks
+REGRESS_OPTS = --temp-config=$(top_srcdir)/src/test/modules/test_rls_hooks/rls_hooks.conf
+# Disabled because these tests require "shared_preload_libraries=test_rls_hooks",
+# which typical installcheck users do not have (e.g. buildfarm clients).
+NO_INSTALLCHECK = 1
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_rls_hooks
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_rls_hooks/README b/src/test/modules/test_rls_hooks/README
new file mode 100644
index 0000000..c22e0d3
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/README
@@ -0,0 +1,16 @@
+test_rls_hooks is an example of how to use the hooks provided for RLS to
+define additional policies to be used.
+
+Functions
+=========
+test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
+ RETURNS List*
+
+Returns a list of policies which should be added to any existing
+policies on the relation, combined with OR.
+
+test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
+ RETURNS List*
+
+Returns a list of policies which should be added to any existing
+policies on the relation, combined with AND.
diff --git a/src/test/modules/test_rls_hooks/expected/test_rls_hooks.out b/src/test/modules/test_rls_hooks/expected/test_rls_hooks.out
new file mode 100644
index 0000000..b8c6d38
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/expected/test_rls_hooks.out
@@ -0,0 +1,201 @@
+LOAD 'test_rls_hooks';
+CREATE TABLE rls_test_permissive (
+ username name,
+ supervisor name,
+ data integer
+);
+-- initial test data
+INSERT INTO rls_test_permissive VALUES ('regress_r1','regress_s1',4);
+INSERT INTO rls_test_permissive VALUES ('regress_r2','regress_s2',5);
+INSERT INTO rls_test_permissive VALUES ('regress_r3','regress_s3',6);
+CREATE TABLE rls_test_restrictive (
+ username name,
+ supervisor name,
+ data integer
+);
+-- At least one permissive policy must exist, otherwise
+-- the default deny policy will be applied. For
+-- testing the only-restrictive-policies from the hook,
+-- create a simple 'allow all' policy.
+CREATE POLICY p1 ON rls_test_restrictive USING (true);
+-- initial test data
+INSERT INTO rls_test_restrictive VALUES ('regress_r1','regress_s1',1);
+INSERT INTO rls_test_restrictive VALUES ('regress_r2','regress_s2',2);
+INSERT INTO rls_test_restrictive VALUES ('regress_r3','regress_s3',3);
+CREATE TABLE rls_test_both (
+ username name,
+ supervisor name,
+ data integer
+);
+-- initial test data
+INSERT INTO rls_test_both VALUES ('regress_r1','regress_s1',7);
+INSERT INTO rls_test_both VALUES ('regress_r2','regress_s2',8);
+INSERT INTO rls_test_both VALUES ('regress_r3','regress_s3',9);
+ALTER TABLE rls_test_permissive ENABLE ROW LEVEL SECURITY;
+ALTER TABLE rls_test_restrictive ENABLE ROW LEVEL SECURITY;
+ALTER TABLE rls_test_both ENABLE ROW LEVEL SECURITY;
+CREATE ROLE regress_r1;
+CREATE ROLE regress_s1;
+GRANT SELECT,INSERT ON rls_test_permissive TO regress_r1;
+GRANT SELECT,INSERT ON rls_test_restrictive TO regress_r1;
+GRANT SELECT,INSERT ON rls_test_both TO regress_r1;
+GRANT SELECT,INSERT ON rls_test_permissive TO regress_s1;
+GRANT SELECT,INSERT ON rls_test_restrictive TO regress_s1;
+GRANT SELECT,INSERT ON rls_test_both TO regress_s1;
+SET ROLE regress_r1;
+-- With only the hook's policies, permissive
+-- hook's policy is current_user = username
+EXPLAIN (costs off) SELECT * FROM rls_test_permissive;
+ QUERY PLAN
+-----------------------------------------
+ Seq Scan on rls_test_permissive
+ Filter: ("current_user"() = username)
+(2 rows)
+
+SELECT * FROM rls_test_permissive;
+ username | supervisor | data
+------------+------------+------
+ regress_r1 | regress_s1 | 4
+(1 row)
+
+-- success
+INSERT INTO rls_test_permissive VALUES ('regress_r1','regress_s1',10);
+-- failure
+INSERT INTO rls_test_permissive VALUES ('regress_r4','regress_s4',10);
+ERROR: new row violates row-level security policy for table "rls_test_permissive"
+SET ROLE regress_s1;
+-- With only the hook's policies, restrictive
+-- hook's policy is current_user = supervisor
+EXPLAIN (costs off) SELECT * FROM rls_test_restrictive;
+ QUERY PLAN
+-------------------------------------------
+ Seq Scan on rls_test_restrictive
+ Filter: ("current_user"() = supervisor)
+(2 rows)
+
+SELECT * FROM rls_test_restrictive;
+ username | supervisor | data
+------------+------------+------
+ regress_r1 | regress_s1 | 1
+(1 row)
+
+-- success
+INSERT INTO rls_test_restrictive VALUES ('regress_r1','regress_s1',10);
+-- failure
+INSERT INTO rls_test_restrictive VALUES ('regress_r4','regress_s4',10);
+ERROR: new row violates row-level security policy "extension policy" for table "rls_test_restrictive"
+SET ROLE regress_s1;
+-- With only the hook's policies, both
+-- permissive hook's policy is current_user = username
+-- restrictive hook's policy is current_user = superuser
+-- combined with AND, results in nothing being allowed
+EXPLAIN (costs off) SELECT * FROM rls_test_both;
+ QUERY PLAN
+-------------------------------------------------------------------------------
+ Seq Scan on rls_test_both
+ Filter: ((supervisor = "current_user"()) AND (username = "current_user"()))
+(2 rows)
+
+SELECT * FROM rls_test_both;
+ username | supervisor | data
+----------+------------+------
+(0 rows)
+
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r1','regress_s1',10);
+ERROR: new row violates row-level security policy for table "rls_test_both"
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r4','regress_s1',10);
+ERROR: new row violates row-level security policy for table "rls_test_both"
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r4','regress_s4',10);
+ERROR: new row violates row-level security policy for table "rls_test_both"
+RESET ROLE;
+-- Create "internal" policies, to check that the policies from
+-- the hooks are combined correctly.
+CREATE POLICY p1 ON rls_test_permissive USING (data % 2 = 0);
+-- Remove the original allow-all policy
+DROP POLICY p1 ON rls_test_restrictive;
+CREATE POLICY p1 ON rls_test_restrictive USING (data % 2 = 0);
+CREATE POLICY p1 ON rls_test_both USING (data % 2 = 0);
+SET ROLE regress_r1;
+-- With both internal and hook policies, permissive
+EXPLAIN (costs off) SELECT * FROM rls_test_permissive;
+ QUERY PLAN
+---------------------------------------------------------------
+ Seq Scan on rls_test_permissive
+ Filter: (((data % 2) = 0) OR ("current_user"() = username))
+(2 rows)
+
+SELECT * FROM rls_test_permissive;
+ username | supervisor | data
+------------+------------+------
+ regress_r1 | regress_s1 | 4
+ regress_r3 | regress_s3 | 6
+ regress_r1 | regress_s1 | 10
+(3 rows)
+
+-- success
+INSERT INTO rls_test_permissive VALUES ('regress_r1','regress_s1',7);
+-- success
+INSERT INTO rls_test_permissive VALUES ('regress_r3','regress_s3',10);
+-- failure
+INSERT INTO rls_test_permissive VALUES ('regress_r4','regress_s4',7);
+ERROR: new row violates row-level security policy for table "rls_test_permissive"
+SET ROLE regress_s1;
+-- With both internal and hook policies, restrictive
+EXPLAIN (costs off) SELECT * FROM rls_test_restrictive;
+ QUERY PLAN
+------------------------------------------------------------------
+ Seq Scan on rls_test_restrictive
+ Filter: (("current_user"() = supervisor) AND ((data % 2) = 0))
+(2 rows)
+
+SELECT * FROM rls_test_restrictive;
+ username | supervisor | data
+------------+------------+------
+ regress_r1 | regress_s1 | 10
+(1 row)
+
+-- success
+INSERT INTO rls_test_restrictive VALUES ('regress_r1','regress_s1',8);
+-- failure
+INSERT INTO rls_test_restrictive VALUES ('regress_r3','regress_s3',10);
+ERROR: new row violates row-level security policy "extension policy" for table "rls_test_restrictive"
+-- failure
+INSERT INTO rls_test_restrictive VALUES ('regress_r1','regress_s1',7);
+ERROR: new row violates row-level security policy for table "rls_test_restrictive"
+-- failure
+INSERT INTO rls_test_restrictive VALUES ('regress_r4','regress_s4',7);
+ERROR: new row violates row-level security policy for table "rls_test_restrictive"
+-- With both internal and hook policies, both permissive
+-- and restrictive hook policies
+EXPLAIN (costs off) SELECT * FROM rls_test_both;
+ QUERY PLAN
+-----------------------------------------------------------------------------------------------------
+ Seq Scan on rls_test_both
+ Filter: (("current_user"() = supervisor) AND (((data % 2) = 0) OR ("current_user"() = username)))
+(2 rows)
+
+SELECT * FROM rls_test_both;
+ username | supervisor | data
+----------+------------+------
+(0 rows)
+
+-- success
+INSERT INTO rls_test_both VALUES ('regress_r1','regress_s1',8);
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r3','regress_s3',10);
+ERROR: new row violates row-level security policy "extension policy" for table "rls_test_both"
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r1','regress_s1',7);
+ERROR: new row violates row-level security policy for table "rls_test_both"
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r4','regress_s4',7);
+ERROR: new row violates row-level security policy for table "rls_test_both"
+RESET ROLE;
+DROP TABLE rls_test_restrictive;
+DROP TABLE rls_test_permissive;
+DROP TABLE rls_test_both;
+DROP ROLE regress_r1;
+DROP ROLE regress_s1;
diff --git a/src/test/modules/test_rls_hooks/rls_hooks.conf b/src/test/modules/test_rls_hooks/rls_hooks.conf
new file mode 100644
index 0000000..a522c0e
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/rls_hooks.conf
@@ -0,0 +1 @@
+shared_preload_libraries = test_rls_hooks
diff --git a/src/test/modules/test_rls_hooks/sql/test_rls_hooks.sql b/src/test/modules/test_rls_hooks/sql/test_rls_hooks.sql
new file mode 100644
index 0000000..746f6dd
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/sql/test_rls_hooks.sql
@@ -0,0 +1,176 @@
+LOAD 'test_rls_hooks';
+
+CREATE TABLE rls_test_permissive (
+ username name,
+ supervisor name,
+ data integer
+);
+
+-- initial test data
+INSERT INTO rls_test_permissive VALUES ('regress_r1','regress_s1',4);
+INSERT INTO rls_test_permissive VALUES ('regress_r2','regress_s2',5);
+INSERT INTO rls_test_permissive VALUES ('regress_r3','regress_s3',6);
+
+CREATE TABLE rls_test_restrictive (
+ username name,
+ supervisor name,
+ data integer
+);
+
+-- At least one permissive policy must exist, otherwise
+-- the default deny policy will be applied. For
+-- testing the only-restrictive-policies from the hook,
+-- create a simple 'allow all' policy.
+CREATE POLICY p1 ON rls_test_restrictive USING (true);
+
+-- initial test data
+INSERT INTO rls_test_restrictive VALUES ('regress_r1','regress_s1',1);
+INSERT INTO rls_test_restrictive VALUES ('regress_r2','regress_s2',2);
+INSERT INTO rls_test_restrictive VALUES ('regress_r3','regress_s3',3);
+
+CREATE TABLE rls_test_both (
+ username name,
+ supervisor name,
+ data integer
+);
+
+-- initial test data
+INSERT INTO rls_test_both VALUES ('regress_r1','regress_s1',7);
+INSERT INTO rls_test_both VALUES ('regress_r2','regress_s2',8);
+INSERT INTO rls_test_both VALUES ('regress_r3','regress_s3',9);
+
+ALTER TABLE rls_test_permissive ENABLE ROW LEVEL SECURITY;
+ALTER TABLE rls_test_restrictive ENABLE ROW LEVEL SECURITY;
+ALTER TABLE rls_test_both ENABLE ROW LEVEL SECURITY;
+
+CREATE ROLE regress_r1;
+CREATE ROLE regress_s1;
+
+GRANT SELECT,INSERT ON rls_test_permissive TO regress_r1;
+GRANT SELECT,INSERT ON rls_test_restrictive TO regress_r1;
+GRANT SELECT,INSERT ON rls_test_both TO regress_r1;
+
+GRANT SELECT,INSERT ON rls_test_permissive TO regress_s1;
+GRANT SELECT,INSERT ON rls_test_restrictive TO regress_s1;
+GRANT SELECT,INSERT ON rls_test_both TO regress_s1;
+
+SET ROLE regress_r1;
+
+-- With only the hook's policies, permissive
+-- hook's policy is current_user = username
+EXPLAIN (costs off) SELECT * FROM rls_test_permissive;
+
+SELECT * FROM rls_test_permissive;
+
+-- success
+INSERT INTO rls_test_permissive VALUES ('regress_r1','regress_s1',10);
+
+-- failure
+INSERT INTO rls_test_permissive VALUES ('regress_r4','regress_s4',10);
+
+SET ROLE regress_s1;
+
+-- With only the hook's policies, restrictive
+-- hook's policy is current_user = supervisor
+EXPLAIN (costs off) SELECT * FROM rls_test_restrictive;
+
+SELECT * FROM rls_test_restrictive;
+
+-- success
+INSERT INTO rls_test_restrictive VALUES ('regress_r1','regress_s1',10);
+
+-- failure
+INSERT INTO rls_test_restrictive VALUES ('regress_r4','regress_s4',10);
+
+SET ROLE regress_s1;
+
+-- With only the hook's policies, both
+-- permissive hook's policy is current_user = username
+-- restrictive hook's policy is current_user = superuser
+-- combined with AND, results in nothing being allowed
+EXPLAIN (costs off) SELECT * FROM rls_test_both;
+
+SELECT * FROM rls_test_both;
+
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r1','regress_s1',10);
+
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r4','regress_s1',10);
+
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r4','regress_s4',10);
+
+RESET ROLE;
+
+-- Create "internal" policies, to check that the policies from
+-- the hooks are combined correctly.
+CREATE POLICY p1 ON rls_test_permissive USING (data % 2 = 0);
+
+-- Remove the original allow-all policy
+DROP POLICY p1 ON rls_test_restrictive;
+CREATE POLICY p1 ON rls_test_restrictive USING (data % 2 = 0);
+
+CREATE POLICY p1 ON rls_test_both USING (data % 2 = 0);
+
+SET ROLE regress_r1;
+
+-- With both internal and hook policies, permissive
+EXPLAIN (costs off) SELECT * FROM rls_test_permissive;
+
+SELECT * FROM rls_test_permissive;
+
+-- success
+INSERT INTO rls_test_permissive VALUES ('regress_r1','regress_s1',7);
+
+-- success
+INSERT INTO rls_test_permissive VALUES ('regress_r3','regress_s3',10);
+
+-- failure
+INSERT INTO rls_test_permissive VALUES ('regress_r4','regress_s4',7);
+
+SET ROLE regress_s1;
+
+-- With both internal and hook policies, restrictive
+EXPLAIN (costs off) SELECT * FROM rls_test_restrictive;
+
+SELECT * FROM rls_test_restrictive;
+
+-- success
+INSERT INTO rls_test_restrictive VALUES ('regress_r1','regress_s1',8);
+
+-- failure
+INSERT INTO rls_test_restrictive VALUES ('regress_r3','regress_s3',10);
+
+-- failure
+INSERT INTO rls_test_restrictive VALUES ('regress_r1','regress_s1',7);
+
+-- failure
+INSERT INTO rls_test_restrictive VALUES ('regress_r4','regress_s4',7);
+
+-- With both internal and hook policies, both permissive
+-- and restrictive hook policies
+EXPLAIN (costs off) SELECT * FROM rls_test_both;
+
+SELECT * FROM rls_test_both;
+
+-- success
+INSERT INTO rls_test_both VALUES ('regress_r1','regress_s1',8);
+
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r3','regress_s3',10);
+
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r1','regress_s1',7);
+
+-- failure
+INSERT INTO rls_test_both VALUES ('regress_r4','regress_s4',7);
+
+RESET ROLE;
+
+DROP TABLE rls_test_restrictive;
+DROP TABLE rls_test_permissive;
+DROP TABLE rls_test_both;
+
+DROP ROLE regress_r1;
+DROP ROLE regress_s1;
diff --git a/src/test/modules/test_rls_hooks/test_rls_hooks.c b/src/test/modules/test_rls_hooks/test_rls_hooks.c
new file mode 100644
index 0000000..0bfa878
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/test_rls_hooks.c
@@ -0,0 +1,178 @@
+/*--------------------------------------------------------------------------
+ *
+ * test_rls_hooks.c
+ * Code for testing RLS hooks.
+ *
+ * Copyright (c) 2015-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/test/modules/test_rls_hooks/test_rls_hooks.c
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "catalog/pg_type.h"
+#include "fmgr.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "parser/parse_clause.h"
+#include "parser/parse_collate.h"
+#include "parser/parse_node.h"
+#include "parser/parse_relation.h"
+#include "rewrite/rowsecurity.h"
+#include "test_rls_hooks.h"
+#include "utils/acl.h"
+#include "utils/rel.h"
+#include "utils/relcache.h"
+
+PG_MODULE_MAGIC;
+
+/* Saved hook values in case of unload */
+static row_security_policy_hook_type prev_row_security_policy_hook_permissive = NULL;
+static row_security_policy_hook_type prev_row_security_policy_hook_restrictive = NULL;
+
+void _PG_init(void);
+void _PG_fini(void);
+
+/* Install hooks */
+void
+_PG_init(void)
+{
+ /* Save values for unload */
+ prev_row_security_policy_hook_permissive = row_security_policy_hook_permissive;
+ prev_row_security_policy_hook_restrictive = row_security_policy_hook_restrictive;
+
+ /* Set our hooks */
+ row_security_policy_hook_permissive = test_rls_hooks_permissive;
+ row_security_policy_hook_restrictive = test_rls_hooks_restrictive;
+}
+
+/* Uninstall hooks */
+void
+_PG_fini(void)
+{
+ row_security_policy_hook_permissive = prev_row_security_policy_hook_permissive;
+ row_security_policy_hook_restrictive = prev_row_security_policy_hook_restrictive;
+}
+
+/*
+ * Return permissive policies to be added
+ */
+List *
+test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
+{
+ List *policies = NIL;
+ RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
+ Datum role;
+ FuncCall *n;
+ Node *e;
+ ColumnRef *c;
+ ParseState *qual_pstate;
+ ParseNamespaceItem *nsitem;
+
+ if (strcmp(RelationGetRelationName(relation), "rls_test_permissive") != 0 &&
+ strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
+ return NIL;
+
+ qual_pstate = make_parsestate(NULL);
+
+ nsitem = addRangeTableEntryForRelation(qual_pstate,
+ relation, AccessShareLock,
+ NULL, false, false);
+ addNSItemToQuery(qual_pstate, nsitem, false, true, true);
+
+ role = ObjectIdGetDatum(ACL_ID_PUBLIC);
+
+ policy->policy_name = pstrdup("extension policy");
+ policy->polcmd = '*';
+ policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, TYPALIGN_INT);
+
+ /*
+ * policy->qual = (Expr *) makeConst(BOOLOID, -1, InvalidOid,
+ * sizeof(bool), BoolGetDatum(true), false, true);
+ */
+
+ n = makeFuncCall(list_make2(makeString("pg_catalog"),
+ makeString("current_user")), NIL, 0);
+
+ c = makeNode(ColumnRef);
+ c->fields = list_make1(makeString("username"));
+ c->location = 0;
+
+ e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
+
+ policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
+ EXPR_KIND_POLICY,
+ "POLICY");
+ /* Fix up collation information */
+ assign_expr_collations(qual_pstate, (Node *) policy->qual);
+
+ policy->with_check_qual = copyObject(policy->qual);
+ policy->hassublinks = false;
+
+ policies = list_make1(policy);
+
+ return policies;
+}
+
+/*
+ * Return restrictive policies to be added
+ *
+ * Note that a permissive policy must exist or the default-deny policy
+ * will be included and nothing will be visible. If no filtering should
+ * be done except for the restrictive policy, then a single "USING (true)"
+ * permissive policy can be used; see the regression tests.
+ */
+List *
+test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
+{
+ List *policies = NIL;
+ RowSecurityPolicy *policy = palloc0(sizeof(RowSecurityPolicy));
+ Datum role;
+ FuncCall *n;
+ Node *e;
+ ColumnRef *c;
+ ParseState *qual_pstate;
+ ParseNamespaceItem *nsitem;
+
+ if (strcmp(RelationGetRelationName(relation), "rls_test_restrictive") != 0 &&
+ strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
+ return NIL;
+
+ qual_pstate = make_parsestate(NULL);
+
+ nsitem = addRangeTableEntryForRelation(qual_pstate,
+ relation, AccessShareLock,
+ NULL, false, false);
+ addNSItemToQuery(qual_pstate, nsitem, false, true, true);
+
+ role = ObjectIdGetDatum(ACL_ID_PUBLIC);
+
+ policy->policy_name = pstrdup("extension policy");
+ policy->polcmd = '*';
+ policy->roles = construct_array(&role, 1, OIDOID, sizeof(Oid), true, TYPALIGN_INT);
+
+ n = makeFuncCall(list_make2(makeString("pg_catalog"),
+ makeString("current_user")), NIL, 0);
+
+ c = makeNode(ColumnRef);
+ c->fields = list_make1(makeString("supervisor"));
+ c->location = 0;
+
+ e = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", (Node *) n, (Node *) c, 0);
+
+ policy->qual = (Expr *) transformWhereClause(qual_pstate, copyObject(e),
+ EXPR_KIND_POLICY,
+ "POLICY");
+ /* Fix up collation information */
+ assign_expr_collations(qual_pstate, (Node *) policy->qual);
+
+ policy->with_check_qual = copyObject(policy->qual);
+ policy->hassublinks = false;
+
+ policies = list_make1(policy);
+
+ return policies;
+}
diff --git a/src/test/modules/test_rls_hooks/test_rls_hooks.control b/src/test/modules/test_rls_hooks/test_rls_hooks.control
new file mode 100644
index 0000000..9f9f13f
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/test_rls_hooks.control
@@ -0,0 +1,4 @@
+comment = 'Test code for RLS hooks'
+default_version = '1.0'
+module_pathname = '$libdir/test_rls_hooks'
+relocatable = true
diff --git a/src/test/modules/test_rls_hooks/test_rls_hooks.h b/src/test/modules/test_rls_hooks/test_rls_hooks.h
new file mode 100644
index 0000000..f4c94bc
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/test_rls_hooks.h
@@ -0,0 +1,25 @@
+/*--------------------------------------------------------------------------
+ *
+ * test_rls_hooks.h
+ * Definitions for RLS hooks
+ *
+ * Copyright (c) 2015-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/test/modules/test_rls_hooks/test_rls_hooks.h
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef TEST_RLS_HOOKS_H
+#define TEST_RLS_HOOKS_H
+
+#include <rewrite/rowsecurity.h>
+
+/* Return set of permissive hooks based on CmdType and Relation */
+extern List *test_rls_hooks_permissive(CmdType cmdtype, Relation relation);
+
+/* Return set of restrictive hooks based on CmdType and Relation */
+extern List *test_rls_hooks_restrictive(CmdType cmdtype, Relation relation);
+
+#endif