@@ -28,11 +28,28 @@ func (b *Builder) addRowLevelSecurityFilter(
28
28
if b .isExemptFromRLSPolicies (tabMeta , cmdScope ) {
29
29
return
30
30
}
31
- scalar := b .buildRowLevelSecurityUsingExpression (tabMeta , tableScope , cmdScope )
32
- if scalar != nil {
33
- tableScope .expr = b .factory .ConstructSelect (tableScope .expr ,
34
- memo.FiltersExpr {b .factory .ConstructFiltersItem (scalar )})
31
+
32
+ var scalar opt.ScalarExpr
33
+ switch cmdScope {
34
+ case cat .PolicyScopeSelect :
35
+ scalar = b .genPolicyUsingExpr (tabMeta , tableScope , cat .PolicyScopeSelect )
36
+ case cat .PolicyScopeUpdate :
37
+ scalar = b .factory .ConstructAnd (
38
+ b .genPolicyUsingExpr (tabMeta , tableScope , cat .PolicyScopeSelect ),
39
+ b .genPolicyUsingExpr (tabMeta , tableScope , cat .PolicyScopeUpdate ),
40
+ )
41
+ case cat .PolicyScopeDelete :
42
+ scalar = b .factory .ConstructAnd (
43
+ b .genPolicyUsingExpr (tabMeta , tableScope , cat .PolicyScopeSelect ),
44
+ b .genPolicyUsingExpr (tabMeta , tableScope , cat .PolicyScopeDelete ),
45
+ )
46
+ default :
47
+ panic (errors .AssertionFailedf ("unsupported policy command scope for filter: %v" , cmdScope ))
35
48
}
49
+
50
+ tableScope .expr = b .factory .ConstructSelect (tableScope .expr ,
51
+ memo.FiltersExpr {b .factory .ConstructFiltersItem (scalar )})
52
+ b .factory .Metadata ().GetRLSMeta ().RefreshNoPoliciesAppliedForTable (tabMeta .MetaID )
36
53
}
37
54
38
55
// isExemptFromRLSPolicies will check if the given user is exempt from RLS policies.
@@ -65,52 +82,11 @@ func (b *Builder) isExemptFromRLSPolicies(
65
82
return false
66
83
}
67
84
68
- // buildRowLevelSecurityUsingExpression generates a scalar expression for read
69
- // operations by combining all applicable RLS policies. An expression is always
70
- // returned; if no policies apply, a 'false' expression is returned.
71
- func (b * Builder ) buildRowLevelSecurityUsingExpression (
72
- tabMeta * opt.TableMeta , tableScope * scope , cmdScope cat.PolicyCommandScope ,
73
- ) opt.ScalarExpr {
74
- combinedExpr := b .combinePolicyUsingExpressionForCommand (tabMeta , tableScope , cmdScope )
75
- if combinedExpr == nil {
76
- // No policies, filter out all rows by adding a "false" expression.
77
- b .factory .Metadata ().GetRLSMeta ().NoPoliciesApplied = true
78
- return memo .FalseSingleton
79
- }
80
- return b .buildScalar (combinedExpr , tableScope , nil , nil , nil )
81
- }
82
-
83
- // combinePolicyUsingExpressionForCommand generates a `tree.TypedExpr` command
84
- // for use in the scan. Depending on the policy command scope, it may simply
85
- // pass through to `buildRowLevelSecurityUsingExpressionForCommand`.
86
- // For other commands, the process is more complex and may involve multiple
87
- // calls to that function to generate the expression.
88
- func (b * Builder ) combinePolicyUsingExpressionForCommand (
89
- tabMeta * opt.TableMeta , tableScope * scope , cmdScope cat.PolicyCommandScope ,
90
- ) tree.TypedExpr {
91
- // For DELETE and UPDATE, we always apply SELECT/ALL policies because
92
- // reading the existing row is necessary before performing the write.
93
- switch cmdScope {
94
- case cat .PolicyScopeUpdate , cat .PolicyScopeDelete :
95
- selectExpr := b .buildRowLevelSecurityUsingExpressionForCommand (tabMeta , tableScope , cat .PolicyScopeSelect )
96
- if selectExpr == nil {
97
- return selectExpr
98
- }
99
- updateExpr := b .buildRowLevelSecurityUsingExpressionForCommand (tabMeta , tableScope , cmdScope )
100
- if updateExpr == nil {
101
- return nil
102
- }
103
- return tree .NewTypedAndExpr (selectExpr , updateExpr )
104
- default :
105
- return b .buildRowLevelSecurityUsingExpressionForCommand (tabMeta , tableScope , cmdScope )
106
- }
107
- }
108
-
109
- // buildRowLevelSecurityUsingExpressionForCommand will generate a tree.TypedExpr
85
+ // genPolicyUsingExpr will generate a opt.ScalarExpr
110
86
// for all policies that apply to the given policy command scope.
111
- func (b * Builder ) buildRowLevelSecurityUsingExpressionForCommand (
87
+ func (b * Builder ) genPolicyUsingExpr (
112
88
tabMeta * opt.TableMeta , tableScope * scope , cmdScope cat.PolicyCommandScope ,
113
- ) tree. TypedExpr {
89
+ ) opt. ScalarExpr {
114
90
var policiesUsed opt.PolicyIDSet
115
91
var combinedExpr tree.TypedExpr
116
92
policies := tabMeta .Table .Policies ()
@@ -147,8 +123,8 @@ func (b *Builder) buildRowLevelSecurityUsingExpressionForCommand(
147
123
buildForPolicy (policy , false /* restrictive */ )
148
124
}
149
125
if combinedExpr == nil {
150
- // No permissive policies. Return an empty expr to force the caller to generate a deny-all expression.
151
- return nil
126
+ // No permissive policies. Return the false expr as a deny-all expression.
127
+ return memo . FalseSingleton
152
128
}
153
129
for _ , policy := range policies .Restrictive {
154
130
buildForPolicy (policy , true /* restrictive */ )
@@ -159,7 +135,7 @@ func (b *Builder) buildRowLevelSecurityUsingExpressionForCommand(
159
135
panic (errors .AssertionFailedf ("at least one applicable policy should have been found" ))
160
136
}
161
137
b .factory .Metadata ().GetRLSMeta ().AddPoliciesUsed (tabMeta .MetaID , policiesUsed , true /* applyFilterExpr */ )
162
- return combinedExpr
138
+ return b . buildScalar ( combinedExpr , tableScope , nil , nil , nil )
163
139
}
164
140
165
141
// policyAppliesToCommandScope checks whether a given PolicyCommandScope applies
0 commit comments