Skip to content

Commit

Permalink
builtins: implement pg_*_is_visible as UDF
Browse files Browse the repository at this point in the history
Now that we support UDFs, we can implement builtin functions as "virtual
UDFs", that are defined in the builtins map.

The builtin appears to be about twice as fast with this method, which is
nice because it gets used a lot in ORM introspection queries.

Epic: None

Release note (performance improvement): improve the performance of
pg_{function,table,type}_is_visible

Co-authored-by: rafiss <[email protected]>
  • Loading branch information
jordanlewis and rafiss committed Jan 5, 2023
1 parent f4e3749 commit acf5006
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 55 deletions.
3 changes: 2 additions & 1 deletion pkg/sql/pg_catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/catalog/catprivilege"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descs"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/funcdesc"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/schemadesc"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/schemaexpr"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc"
Expand Down Expand Up @@ -2601,7 +2602,7 @@ https://www.postgresql.org/docs/9.5/catalog-pg-proc.html`,
return false, err
}

if overload.IsUDF {
if funcdesc.IsOIDUserDefinedFunc(ooid) {
fnDesc, err := p.Descriptors().GetImmutableFunctionByID(
ctx, p.Txn(), descpb.ID(overload.Oid),
tree.ObjectLookupFlags{
Expand Down
72 changes: 18 additions & 54 deletions pkg/sql/sem/builtins/pg_builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -1226,26 +1226,14 @@ SELECT description
// https://www.postgresql.org/docs/9.6/static/functions-info.html
"pg_function_is_visible": makeBuiltin(defProps(),
tree.Overload{
IsUDF: true,
Types: tree.ParamTypes{{Name: "oid", Typ: types.Oid}},
ReturnType: tree.FixedReturnType(types.Bool),
Fn: func(ctx context.Context, evalCtx *eval.Context, args tree.Datums) (tree.Datum, error) {
oidArg := tree.MustBeDOid(args[0])
row, err := evalCtx.Planner.QueryRowEx(
ctx, "pg_function_is_visible",
sessiondata.NoSessionDataOverride,
"SELECT n.nspname from pg_proc p JOIN pg_namespace n ON p.pronamespace = n.oid WHERE p.oid=$1 LIMIT 1",
oidArg,
)
if err != nil {
return nil, err
}
if row == nil {
return tree.DNull, nil
}
foundSchemaName := string(tree.MustBeDString(row[0]))
isVisible := evalCtx.SessionData().SearchPath.Contains(foundSchemaName, true /* includeImplicit */)
return tree.MakeDBool(tree.DBool(isVisible)), nil
},
Body: `SELECT n.nspname = any current_schemas(true)
FROM pg_proc p
INNER LOOKUP JOIN pg_namespace n
ON p.pronamespace = n.oid
WHERE p.oid=$1 LIMIT 1`,
Info: "Returns whether the function with the given OID belongs to one of the schemas on the search path.",
Volatility: volatility.Stable,
},
Expand All @@ -1255,26 +1243,14 @@ SELECT description
// https://www.postgresql.org/docs/9.6/static/functions-info.html
"pg_table_is_visible": makeBuiltin(defProps(),
tree.Overload{
IsUDF: true,
Types: tree.ParamTypes{{Name: "oid", Typ: types.Oid}},
ReturnType: tree.FixedReturnType(types.Bool),
Fn: func(ctx context.Context, evalCtx *eval.Context, args tree.Datums) (tree.Datum, error) {
oidArg := tree.MustBeDOid(args[0])
row, err := evalCtx.Planner.QueryRowEx(
ctx, "pg_table_is_visible",
sessiondata.NoSessionDataOverride,
"SELECT n.nspname from pg_class c INNER LOOKUP JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.oid=$1 LIMIT 1",
oidArg,
)
if err != nil {
return nil, err
}
if row == nil {
return tree.DNull, nil
}
foundSchemaName := string(tree.MustBeDString(row[0]))
isVisible := evalCtx.SessionData().SearchPath.Contains(foundSchemaName, true /* includeImplicit */)
return tree.MakeDBool(tree.DBool(isVisible)), nil
},
Body: `SELECT n.nspname = any current_schemas(true)
FROM pg_class c
INNER LOOKUP JOIN pg_namespace n
ON c.relnamespace = n.oid
WHERE c.oid=$1 LIMIT 1`,
Info: "Returns whether the table with the given OID belongs to one of the schemas on the search path.",
Volatility: volatility.Stable,
},
Expand All @@ -1288,26 +1264,14 @@ SELECT description
// https://www.postgresql.org/docs/9.6/static/functions-info.html
"pg_type_is_visible": makeBuiltin(defProps(),
tree.Overload{
IsUDF: true,
Types: tree.ParamTypes{{Name: "oid", Typ: types.Oid}},
ReturnType: tree.FixedReturnType(types.Bool),
Fn: func(ctx context.Context, evalCtx *eval.Context, args tree.Datums) (tree.Datum, error) {
oidArg := tree.MustBeDOid(args[0])
row, err := evalCtx.Planner.QueryRowEx(
ctx, "pg_type_is_visible",
sessiondata.NoSessionDataOverride,
"SELECT n.nspname from pg_type t JOIN pg_namespace n ON t.typnamespace = n.oid WHERE t.oid=$1 LIMIT 1",
oidArg,
)
if err != nil {
return nil, err
}
if row == nil {
return tree.DNull, nil
}
foundSchemaName := string(tree.MustBeDString(row[0]))
isVisible := evalCtx.SessionData().SearchPath.Contains(foundSchemaName, true /* includeImplicit */)
return tree.MakeDBool(tree.DBool(isVisible)), nil
},
Body: `SELECT n.nspname = any current_schemas(true)
FROM pg_type t
INNER LOOKUP JOIN pg_namespace n
ON t.typnamespace = n.oid
WHERE t.oid=$1 LIMIT 1`,
Info: "Returns whether the type with the given OID belongs to one of the schemas on the search path.",
Volatility: volatility.Stable,
},
Expand Down

0 comments on commit acf5006

Please sign in to comment.