Skip to content

Commit 6c2bef5

Browse files
committed
schemachanger: track partial index dependencies on functions
This commit adds the plumbing necessary to find referenced UDF IDs in a partial index predicate, and updates the declarative schema changer to add back-references. Release note (sql change): Partial indexes can now reference user-defined function.
1 parent f383bc5 commit 6c2bef5

File tree

46 files changed

+1524
-1037
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1524
-1037
lines changed

pkg/sql/catalog/descriptor.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,12 @@ type TableDescriptor interface {
680680
colID descpb.ColumnID,
681681
) (DescriptorIDSet, error)
682682

683+
// GetAllReferencedFunctionIDsInIndex returns descriptor IDs of all user
684+
// defined functions referenced in expressions used by this index.
685+
GetAllReferencedFunctionIDsInIndex(
686+
indexID descpb.IndexID,
687+
) (DescriptorIDSet, error)
688+
683689
// ForeachDependedOnBy runs a function on all indexes, including those being
684690
// added in the mutations.
685691
ForeachDependedOnBy(f func(dep *descpb.TableDescriptor_Reference) error) error

pkg/sql/catalog/funcdesc/func_desc.go

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,18 @@ func (desc *immutable) validateInboundTableRef(
385385
return errors.AssertionFailedf("depended-on-by relation %q (%d) does not have an index with ID %d",
386386
backRefTbl.GetName(), by.ID, idxID)
387387
}
388-
// TODO(chengxiong): add logic to validate reference in index expressions
389-
// when UDF usage is allowed in indexes.
388+
fnIDs, err := backRefTbl.GetAllReferencedFunctionIDsInIndex(idxID)
389+
if err != nil {
390+
return err
391+
}
392+
if fnIDs.Contains(desc.GetID()) {
393+
foundInTable = true
394+
continue
395+
}
396+
return errors.AssertionFailedf(
397+
"index %d in depended-on-by relation %q (%d) does not have reference to function %q (%d)",
398+
idxID, backRefTbl.GetName(), backRefTbl.GetID(), desc.GetName(), desc.GetID(),
399+
)
390400
}
391401

392402
for _, cstID := range by.ConstraintIDs {
@@ -852,6 +862,55 @@ func (desc *Mutable) RemovePolicyReference(id descpb.ID, policyID descpb.PolicyI
852862
}
853863
}
854864

865+
// AddIndexReference adds back reference to an index to the function.
866+
func (desc *Mutable) AddIndexReference(id descpb.ID, indexID descpb.IndexID) error {
867+
for _, dep := range desc.DependsOn {
868+
if dep == id {
869+
return pgerror.Newf(pgcode.InvalidFunctionDefinition,
870+
"cannot add dependency from descriptor %d to function %s (%d) because there will be a dependency cycle", id, desc.GetName(), desc.GetID(),
871+
)
872+
}
873+
}
874+
for i := range desc.DependedOnBy {
875+
if desc.DependedOnBy[i].ID == id {
876+
for _, prevID := range desc.DependedOnBy[i].IndexIDs {
877+
if prevID == indexID {
878+
return nil
879+
}
880+
}
881+
desc.DependedOnBy[i].IndexIDs = append(desc.DependedOnBy[i].IndexIDs, indexID)
882+
return nil
883+
}
884+
}
885+
desc.DependedOnBy = append(
886+
desc.DependedOnBy,
887+
descpb.FunctionDescriptor_Reference{
888+
ID: id,
889+
IndexIDs: []descpb.IndexID{indexID},
890+
},
891+
)
892+
sort.Slice(desc.DependedOnBy, func(i, j int) bool {
893+
return desc.DependedOnBy[i].ID < desc.DependedOnBy[j].ID
894+
})
895+
return nil
896+
}
897+
898+
// RemoveIndexReference removes back reference to an index from the function.
899+
func (desc *Mutable) RemoveIndexReference(id descpb.ID, indexID descpb.IndexID) {
900+
for i := range desc.DependedOnBy {
901+
if desc.DependedOnBy[i].ID == id {
902+
dep := &desc.DependedOnBy[i]
903+
for j := range dep.IndexIDs {
904+
if dep.IndexIDs[j] == indexID {
905+
dep.IndexIDs = append(dep.IndexIDs[:j], dep.IndexIDs[j+1:]...)
906+
desc.maybeRemoveTableReference(id)
907+
return
908+
}
909+
}
910+
}
911+
}
912+
}
913+
855914
// maybeRemoveTableReference removes a table's references from the function if
856915
// the column, index and constraint references are all empty. This function is
857916
// only used internally when removing an individual column, index or constraint

pkg/sql/catalog/tabledesc/structured.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,12 +458,20 @@ func (desc *wrapper) GetAllReferencedFunctionIDs() (catalog.DescriptorIDSet, err
458458
for i := range desc.Triggers {
459459
ret = ret.Union(catalog.MakeDescriptorIDSet(desc.Triggers[i].DependsOnRoutines...))
460460
}
461-
// Add deps from policies
461+
// Add deps from policies.
462462
for i := range desc.Policies {
463463
ret = ret.Union(catalog.MakeDescriptorIDSet(desc.Policies[i].DependsOnFunctions...))
464464
}
465-
// TODO(chengxiong): add logic to extract references from indexes when UDFs
466-
// are allowed in them.
465+
// Add deps from partial indexes.
466+
for _, idx := range desc.AllIndexes() {
467+
if idx.IsPartial() {
468+
ids, err := schemaexpr.GetUDFIDsFromExprStr(idx.GetPredicate())
469+
if err != nil {
470+
return catalog.DescriptorIDSet{}, err
471+
}
472+
ret = ret.Union(ids)
473+
}
474+
}
467475
return ret.Union(catalog.MakeDescriptorIDSet(desc.DependsOnFunctions...)), nil
468476
}
469477

@@ -496,6 +504,26 @@ func (desc *wrapper) GetAllReferencedFunctionIDsInTrigger(
496504
return fnIDs
497505
}
498506

507+
// GetAllReferencedFunctionIDsInIndex implements the TableDescriptor interface.
508+
func (desc *wrapper) GetAllReferencedFunctionIDsInIndex(
509+
indexID descpb.IndexID,
510+
) (fnIDs catalog.DescriptorIDSet, err error) {
511+
idx := catalog.FindIndexByID(desc, indexID)
512+
if idx == nil {
513+
return catalog.DescriptorIDSet{}, nil
514+
}
515+
516+
var ret catalog.DescriptorIDSet
517+
if idx.IsPartial() {
518+
ids, err := schemaexpr.GetUDFIDsFromExprStr(idx.GetPredicate())
519+
if err != nil {
520+
return catalog.DescriptorIDSet{}, err
521+
}
522+
ret = ret.Union(ids)
523+
}
524+
return ret, nil
525+
}
526+
499527
// GetAllReferencedFunctionIDsInPolicy implements the TableDescriptor interface.
500528
func (desc *wrapper) GetAllReferencedFunctionIDsInPolicy(
501529
policyID descpb.PolicyID,

0 commit comments

Comments
 (0)