Skip to content

Commit 941632b

Browse files
craig[bot]spilchen
andcommitted
Merge #147696
147696: sql/rls: retain function backrefs when updating policy dependencies r=spilchen a=spilchen When a row-level security (RLS) policy references a user-defined function, we correctly establish both forward and backward references during creation. However, if a dependency of that function changes (e.g., a column used in the function's default expression is dropped), the schema changer updates the function’s dependencies but inadvertently drops the backreference to the RLS policy. This leads to a missing backref, causing the schema changes to fail due. This change ensures the policy backref is preserved. Fixes #147471 Release note (bug fix): Fixed a bug where functions lost their RLS policy backreferences, leading to schema change failures. Co-authored-by: Matt Spilchen <[email protected]>
2 parents 3afeb1b + 0fabf98 commit 941632b

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

pkg/sql/catalog/funcdesc/func_desc.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,9 @@ func (desc *immutable) validateInboundFunctionRef(
328328
}
329329
// Validate all other references are unset.
330330
if ref.ColumnIDs != nil || ref.IndexIDs != nil ||
331-
ref.ConstraintIDs != nil || ref.TriggerIDs != nil {
332-
return errors.AssertionFailedf("function reference has invalid references (%v, %v %v, %v)",
333-
ref.ColumnIDs, ref.IndexIDs, ref.ConstraintIDs, ref.TriggerIDs)
331+
ref.ConstraintIDs != nil || ref.TriggerIDs != nil || ref.PolicyIDs != nil {
332+
return errors.AssertionFailedf("function reference has invalid references (%v, %v %v, %v, %v)",
333+
ref.ColumnIDs, ref.IndexIDs, ref.ConstraintIDs, ref.TriggerIDs, ref.PolicyIDs)
334334
}
335335
// Validate a reference exists to this function.
336336
for _, refID := range backrefFunctionDesc.GetDependsOnFunctions() {
@@ -860,7 +860,7 @@ func (desc *Mutable) maybeRemoveTableReference(id descpb.ID) {
860860
var ret []descpb.FunctionDescriptor_Reference
861861
for _, ref := range desc.DependedOnBy {
862862
if ref.ID == id && len(ref.ColumnIDs) == 0 && len(ref.IndexIDs) == 0 &&
863-
len(ref.ConstraintIDs) == 0 && len(ref.TriggerIDs) == 0 {
863+
len(ref.ConstraintIDs) == 0 && len(ref.TriggerIDs) == 0 && len(ref.PolicyIDs) == 0 {
864864
continue
865865
}
866866
ret = append(ret, ref)

pkg/sql/logictest/testdata/logic_test/row_level_security

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,64 @@ ALTER TABLE colref DROP COLUMN c2;
705705
statement ok
706706
DROP TABLE colref;
707707

708+
# Added for bug found in issue #147471
709+
subtest func_ref
710+
711+
statement ok
712+
CREATE FUNCTION f() RETURNS BOOL LANGUAGE SQL AS $$ SELECT true; $$;
713+
714+
statement ok
715+
CREATE TABLE t (x INT, y INT, b BOOL DEFAULT f());
716+
717+
statement ok
718+
CREATE POLICY p ON t USING (f());
719+
720+
query T
721+
SELECT jsonb_pretty(crdb_internal.pb_to_json('descriptor', descriptor)->'function'->'dependedOnBy') as dependedOnBy
722+
FROM system.descriptor
723+
WHERE id = (select 'f'::REGPROC::INT - 100000);
724+
----
725+
[
726+
{
727+
"columnIds": [
728+
3
729+
],
730+
"id": 127,
731+
"policyIds": [
732+
1
733+
]
734+
}
735+
]
736+
737+
# Function reference should be updated but still include dependency on policy.
738+
statement ok
739+
ALTER TABLE t DROP COLUMN b;
740+
741+
query T
742+
SELECT jsonb_pretty(crdb_internal.pb_to_json('descriptor', descriptor)->'function'->'dependedOnBy') as dependedOnBy
743+
FROM system.descriptor
744+
WHERE id = (select 'f'::REGPROC::INT - 100000);
745+
----
746+
[
747+
{
748+
"id": 127,
749+
"policyIds": [
750+
1
751+
]
752+
}
753+
]
754+
755+
query B
756+
SELECT f();
757+
----
758+
true
759+
760+
statement ok
761+
DROP TABLE t;
762+
763+
statement ok
764+
DROP FUNCTION f;
765+
708766
subtest no_subvar_expr
709767

710768
statement ok

0 commit comments

Comments
 (0)