Skip to content

Commit

Permalink
opt: replace "udf" with "routine" in the metadata
Browse files Browse the repository at this point in the history
This commit changes the naming of some methods and data structures used
in query plan metadata to refer to "routines" instead of "udfs". This
clarifies that stored procedures are also valid targets for metadata
tracking.

Epic: None

Release note: None
  • Loading branch information
DrewKimball committed Nov 25, 2024
1 parent 8969b00 commit 4dc62d0
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 37 deletions.
4 changes: 2 additions & 2 deletions pkg/sql/explain_bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,8 +623,8 @@ func (b *stmtBundleBuilder) addEnv(ctx context.Context) {
if err := c.PrintCreateEnum(&buf, b.flags.RedactValues); err != nil {
b.printError(fmt.Sprintf("-- error getting schema for enums: %v", err), &buf)
}
if mem.Metadata().HasUserDefinedFunctions() {
// Get all relevant user-defined functions.
if mem.Metadata().HasUserDefinedRoutines() {
// Get all relevant user-defined routines.
blankLine()
err = c.PrintRelevantCreateRoutine(
&buf, strings.ToLower(b.stmt), b.flags.RedactValues, &b.errorStrings, false, /* procedure */
Expand Down
65 changes: 34 additions & 31 deletions pkg/sql/opt/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type SchemaID int32
// 1 << privilege.Kind, so that multiple privileges can be stored.
type privilegeBitmap uint64

type udfDep struct {
type routineDep struct {
overload *tree.Overload
invocationTypes []*types.T
}
Expand Down Expand Up @@ -122,9 +122,9 @@ type Metadata struct {
// dataSourceDeps stores each data source object that the query depends on.
dataSourceDeps map[cat.StableID]cat.DataSource

// udfDeps stores each user-defined function overload (as well as the
// invocation signature) that the query depends on.
udfDeps map[cat.StableID]udfDep
// routineDeps stores each user-defined function and stored procedure overload
// (as well as the invocation signature) that the query depends on.
routineDeps map[cat.StableID]routineDep

// objectRefsByName stores each unique name that the query uses to reference
// each object. It is needed because changes to the search path may change
Expand Down Expand Up @@ -182,12 +182,12 @@ func (md *Metadata) Init() {
delete(md.dataSourceDeps, id)
}

udfDeps := md.udfDeps
if udfDeps == nil {
udfDeps = make(map[cat.StableID]udfDep)
routineDeps := md.routineDeps
if routineDeps == nil {
routineDeps = make(map[cat.StableID]routineDep)
}
for id := range md.udfDeps {
delete(md.udfDeps, id)
for id := range md.routineDeps {
delete(md.routineDeps, id)
}

objectRefsByName := md.objectRefsByName
Expand Down Expand Up @@ -223,7 +223,7 @@ func (md *Metadata) Init() {
md.sequences = sequences[:0]
md.views = views[:0]
md.dataSourceDeps = dataSourceDeps
md.udfDeps = udfDeps
md.routineDeps = routineDeps
md.objectRefsByName = objectRefsByName
md.privileges = privileges
md.builtinRefsByName = builtinRefsByName
Expand All @@ -241,7 +241,7 @@ func (md *Metadata) CopyFrom(from *Metadata, copyScalarFn func(Expr) Expr) {
if len(md.schemas) != 0 || len(md.cols) != 0 || len(md.tables) != 0 ||
len(md.sequences) != 0 || len(md.views) != 0 || len(md.userDefinedTypes) != 0 ||
len(md.userDefinedTypesSlice) != 0 || len(md.dataSourceDeps) != 0 ||
len(md.udfDeps) != 0 || len(md.objectRefsByName) != 0 || len(md.privileges) != 0 ||
len(md.routineDeps) != 0 || len(md.objectRefsByName) != 0 || len(md.privileges) != 0 ||
len(md.builtinRefsByName) != 0 {
panic(errors.AssertionFailedf("CopyFrom requires empty destination"))
}
Expand Down Expand Up @@ -285,11 +285,11 @@ func (md *Metadata) CopyFrom(from *Metadata, copyScalarFn func(Expr) Expr) {
md.dataSourceDeps[id] = dataSource
}

for id, overload := range from.udfDeps {
if md.udfDeps == nil {
md.udfDeps = make(map[cat.StableID]udfDep)
for id, overload := range from.routineDeps {
if md.routineDeps == nil {
md.routineDeps = make(map[cat.StableID]routineDep)
}
md.udfDeps[id] = overload
md.routineDeps[id] = overload
}

for id, names := range from.objectRefsByName {
Expand Down Expand Up @@ -418,8 +418,9 @@ func (md *Metadata) CheckDependencies(
}
}

// Check that no referenced user defined functions have changed.
for id, dep := range md.udfDeps {
// Check that no referenced user defined functions or stored procedures have
// changed.
for id, dep := range md.routineDeps {
overload := dep.overload
if names, ok := md.objectRefsByName[id]; ok {
for _, name := range names {
Expand Down Expand Up @@ -503,7 +504,7 @@ func (md *Metadata) CheckDependencies(
if err := md.checkDataSourcePrivileges(ctx, optCatalog); err != nil {
return false, err
}
for _, dep := range md.udfDeps {
for _, dep := range md.routineDeps {
if err := optCatalog.CheckExecutionPrivilege(ctx, dep.overload.Oid, optCatalog.GetCurrentUser()); err != nil {
return false, err
}
Expand Down Expand Up @@ -591,21 +592,23 @@ func (md *Metadata) AllUserDefinedTypes() []*types.T {
return md.userDefinedTypesSlice
}

// HasUserDefinedFunctions returns true if the query references a UDF.
func (md *Metadata) HasUserDefinedFunctions() bool {
return len(md.udfDeps) > 0
// HasUserDefinedRoutines returns true if the query references a UDF or stored
// procedure.
func (md *Metadata) HasUserDefinedRoutines() bool {
return len(md.routineDeps) > 0
}

// AddUserDefinedFunction adds a user-defined function to the metadata for this
// query. If the function was resolved by name, the name will also be tracked.
func (md *Metadata) AddUserDefinedFunction(
// AddUserDefinedRoutine adds a user-defined function or stored procedure to the
// metadata for this query. If the routine was resolved by name, the name will
// also be tracked.
func (md *Metadata) AddUserDefinedRoutine(
overload *tree.Overload, invocationTypes []*types.T, name *tree.UnresolvedObjectName,
) {
if overload.Type != tree.UDFRoutine {
return
}
id := cat.StableID(catid.UserDefinedOIDToID(overload.Oid))
md.udfDeps[id] = udfDep{
md.routineDeps[id] = routineDep{
overload: overload,
invocationTypes: invocationTypes,
}
Expand Down Expand Up @@ -1174,14 +1177,14 @@ func (md *Metadata) TestingDataSourceDeps() map[cat.StableID]cat.DataSource {
return md.dataSourceDeps
}

// TestingUDFDepsEqual returns whether the UDF deps of the other Metadata are
// equal to the UDF deps of this Metadata.
func (md *Metadata) TestingUDFDepsEqual(other *Metadata) bool {
if len(md.udfDeps) != len(other.udfDeps) {
// TestingRoutineDepsEqual returns whether the routine deps of the other
// Metadata are equal to the routine deps of this Metadata.
func (md *Metadata) TestingRoutineDepsEqual(other *Metadata) bool {
if len(md.routineDeps) != len(other.routineDeps) {
return false
}
for id, otherDep := range other.udfDeps {
dep, ok := md.udfDeps[id]
for id, otherDep := range other.routineDeps {
dep, ok := md.routineDeps[id]
if !ok {
return false
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/sql/opt/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func TestMetadata(t *testing.T) {
}

udfName := tree.MakeQualifiedRoutineName("t", "public", "udf")
md.AddUserDefinedFunction(
md.AddUserDefinedRoutine(
&tree.Overload{Oid: catid.FuncIDToOID(1111)},
types.OneIntCol,
udfName.ToUnresolvedObjectName(),
Expand Down Expand Up @@ -175,8 +175,8 @@ func TestMetadata(t *testing.T) {
}
}

if !mdNew.TestingUDFDepsEqual(md) {
t.Fatalf("expected UDF dependency to be copied")
if !mdNew.TestingRoutineDepsEqual(md) {
t.Fatalf("expected user-defined routine dependency to be copied")
}

newNamesByID, oldNamesByID := mdNew.TestingObjectRefsByName(), md.TestingObjectRefsByName()
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/opt/optbuilder/routine.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func (b *Builder) buildRoutine(
}
invocationTypes[i] = texpr.ResolvedType()
}
b.factory.Metadata().AddUserDefinedFunction(o, invocationTypes, f.Func.ReferenceByName)
b.factory.Metadata().AddUserDefinedRoutine(o, invocationTypes, f.Func.ReferenceByName)

// Validate that the return types match the original return types defined in
// the function. Return types like user defined return types may change
Expand Down

0 comments on commit 4dc62d0

Please sign in to comment.