24
24
#include "catalog/namespace.h"
25
25
#include "catalog/objectaccess.h"
26
26
#include "catalog/pg_authid.h"
27
+ #include "catalog/pg_depend.h"
27
28
#include "catalog/pg_policy.h"
28
29
#include "catalog/pg_type.h"
30
+ #include "commands/comment.h"
29
31
#include "commands/policy.h"
30
32
#include "miscadmin.h"
31
33
#include "nodes/pg_list.h"
32
34
#include "parser/parse_clause.h"
33
35
#include "parser/parse_collate.h"
34
36
#include "parser/parse_node.h"
35
37
#include "parser/parse_relation.h"
38
+ #include "parser/parse_utilcmd.h"
36
39
#include "rewrite/rewriteManip.h"
37
40
#include "rewrite/rowsecurity.h"
38
41
#include "utils/acl.h"
@@ -566,7 +569,7 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
566
569
* stmt - the CreatePolicyStmt that describes the policy to create.
567
570
*/
568
571
ObjectAddress
569
- CreatePolicy (CreatePolicyStmt * stmt )
572
+ CreatePolicy (CreatePolicyStmt * stmt , const char * queryString )
570
573
{
571
574
Relation pg_policy_rel ;
572
575
Oid policy_id ;
@@ -576,8 +579,7 @@ CreatePolicy(CreatePolicyStmt *stmt)
576
579
Datum * role_oids ;
577
580
int nitems = 0 ;
578
581
ArrayType * role_ids ;
579
- ParseState * qual_pstate ;
580
- ParseState * with_check_pstate ;
582
+ ParseState * pstate ;
581
583
ParseNamespaceItem * nsitem ;
582
584
Node * qual ;
583
585
Node * with_check_qual ;
@@ -615,10 +617,6 @@ CreatePolicy(CreatePolicyStmt *stmt)
615
617
role_oids = policy_role_list_to_array (stmt -> roles , & nitems );
616
618
role_ids = construct_array_builtin (role_oids , nitems , OIDOID );
617
619
618
- /* Parse the supplied clause */
619
- qual_pstate = make_parsestate (NULL );
620
- with_check_pstate = make_parsestate (NULL );
621
-
622
620
/* zero-clear */
623
621
memset (values , 0 , sizeof (values ));
624
622
memset (isnull , 0 , sizeof (isnull ));
@@ -628,35 +626,23 @@ CreatePolicy(CreatePolicyStmt *stmt)
628
626
0 ,
629
627
RangeVarCallbackForPolicy ,
630
628
stmt );
629
+ if (!stmt -> transformed )
630
+ stmt = transformPolicyStmt (table_id , stmt , queryString );
631
631
632
- /* Open target_table to build quals. No additional lock is necessary. */
633
- target_table = relation_open ( table_id , NoLock ) ;
632
+ qual = stmt -> qual ;
633
+ with_check_qual = stmt -> with_check ;
634
634
635
- /* Add for the regular security quals */
636
- nsitem = addRangeTableEntryForRelation (qual_pstate , target_table ,
637
- AccessShareLock ,
638
- NULL , false, false);
639
- addNSItemToQuery (qual_pstate , nsitem , false, true, true);
635
+ /* we'll need the pstate->rtable for recordDependencyOnExpr */
636
+ pstate = make_parsestate (NULL );
637
+ pstate -> p_sourcetext = queryString ;
640
638
641
- /* Add for the with-check quals */
642
- nsitem = addRangeTableEntryForRelation (with_check_pstate , target_table ,
639
+ /* No additional lock is necessary. */
640
+ target_table = relation_open (table_id , NoLock );
641
+
642
+ nsitem = addRangeTableEntryForRelation (pstate , target_table ,
643
643
AccessShareLock ,
644
644
NULL , false, false);
645
- addNSItemToQuery (with_check_pstate , nsitem , false, true, true);
646
-
647
- qual = transformWhereClause (qual_pstate ,
648
- stmt -> qual ,
649
- EXPR_KIND_POLICY ,
650
- "POLICY" );
651
-
652
- with_check_qual = transformWhereClause (with_check_pstate ,
653
- stmt -> with_check ,
654
- EXPR_KIND_POLICY ,
655
- "POLICY" );
656
-
657
- /* Fix up collation information */
658
- assign_expr_collations (qual_pstate , qual );
659
- assign_expr_collations (with_check_pstate , with_check_qual );
645
+ addNSItemToQuery (pstate , nsitem , false, true, true);
660
646
661
647
/* Open pg_policy catalog */
662
648
pg_policy_rel = table_open (PolicyRelationId , RowExclusiveLock );
@@ -724,11 +710,11 @@ CreatePolicy(CreatePolicyStmt *stmt)
724
710
725
711
recordDependencyOn (& myself , & target , DEPENDENCY_AUTO );
726
712
727
- recordDependencyOnExpr (& myself , qual , qual_pstate -> p_rtable ,
713
+ recordDependencyOnExpr (& myself , qual , pstate -> p_rtable ,
728
714
DEPENDENCY_NORMAL );
729
715
730
716
recordDependencyOnExpr (& myself , with_check_qual ,
731
- with_check_pstate -> p_rtable , DEPENDENCY_NORMAL );
717
+ pstate -> p_rtable , DEPENDENCY_NORMAL );
732
718
733
719
/* Register role dependencies */
734
720
target .classId = AuthIdRelationId ;
@@ -749,12 +735,16 @@ CreatePolicy(CreatePolicyStmt *stmt)
749
735
750
736
/* Clean up. */
751
737
heap_freetuple (policy_tuple );
752
- free_parsestate (qual_pstate );
753
- free_parsestate (with_check_pstate );
738
+ free_parsestate (pstate );
754
739
systable_endscan (sscan );
755
740
relation_close (target_table , NoLock );
756
741
table_close (pg_policy_rel , RowExclusiveLock );
757
742
743
+ /* Add any requested comment */
744
+ if (stmt -> polcomment != NULL )
745
+ CreateComments (policy_id , PolicyRelationId , 0 ,
746
+ stmt -> polcomment );
747
+
758
748
return myself ;
759
749
}
760
750
@@ -1277,3 +1267,55 @@ relation_has_policies(Relation rel)
1277
1267
1278
1268
return ret ;
1279
1269
}
1270
+
1271
+ /*
1272
+ * PoliciesGetRelations -
1273
+ * Collect all relations this policy depends on.
1274
+ * The policy's check qual or qual may reference other relations, we include
1275
+ * those as well.
1276
+ */
1277
+ List *
1278
+ PoliciesGetRelations (Oid policyId )
1279
+ {
1280
+ List * result = NIL ;
1281
+ Relation depRel ;
1282
+ ScanKeyData key [2 ];
1283
+ SysScanDesc depScan ;
1284
+ HeapTuple depTup ;
1285
+
1286
+ /*
1287
+ * We scan pg_depend to find those things that policy being depended on.
1288
+ */
1289
+ depRel = table_open (DependRelationId , AccessShareLock );
1290
+
1291
+ ScanKeyInit (& key [0 ],
1292
+ Anum_pg_depend_classid ,
1293
+ BTEqualStrategyNumber , F_OIDEQ ,
1294
+ ObjectIdGetDatum (PolicyRelationId ));
1295
+ ScanKeyInit (& key [1 ],
1296
+ Anum_pg_depend_objid ,
1297
+ BTEqualStrategyNumber , F_OIDEQ ,
1298
+ ObjectIdGetDatum (policyId ));
1299
+
1300
+ depScan = systable_beginscan (depRel , DependDependerIndexId , true,
1301
+ NULL , 2 , key );
1302
+ while (HeapTupleIsValid (depTup = systable_getnext (depScan )))
1303
+ {
1304
+ Form_pg_depend pg_depend = (Form_pg_depend ) GETSTRUCT (depTup );
1305
+
1306
+ /* Prepend oid of the relation with this policy. */
1307
+ if (pg_depend -> refclassid == RelationRelationId )
1308
+ {
1309
+ if (pg_depend -> deptype == DEPENDENCY_AUTO )
1310
+ result = lcons_oid (pg_depend -> refobjid , result );
1311
+ else
1312
+ result = lappend_oid (result , pg_depend -> refobjid );
1313
+ }
1314
+ }
1315
+ systable_endscan (depScan );
1316
+
1317
+ relation_close (depRel , AccessShareLock );
1318
+
1319
+ Assert (result != NIL );
1320
+ return result ;
1321
+ }
0 commit comments