Skip to content

Commit

Permalink
sql: implement function OID reference
Browse files Browse the repository at this point in the history
This commit implements `[FUNCTION xxxx]` OID references syntax
of functions. With this change, functions can be called with
the new OID numerical representation. For example
`SELECT [FUNCTION 123]('helloworld')`. The intention of this
syntax is only for internal serialization of references to UDFs.
But it's general enough for builtin functions as well.

A new implementation of the `ResolvableFunctionReference`
interface, `OIDFunctionReference` is introduced for function
resolution purpose for the new syntax.

The `ResolveFunctionByOID` method is also refactored to return
a qualified name.

Fixes: cockroachdb#83231

Release note: None
  • Loading branch information
chengxiong-ruan committed Feb 6, 2023
1 parent 4ab6b68 commit 6c9468e
Show file tree
Hide file tree
Showing 27 changed files with 397 additions and 90 deletions.
30 changes: 17 additions & 13 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -3491,11 +3491,11 @@ opt_interval_qualifier ::=
|

func_application ::=
func_name '(' ')'
| func_name '(' expr_list opt_sort_clause ')'
| func_name '(' 'ALL' expr_list opt_sort_clause ')'
| func_name '(' 'DISTINCT' expr_list ')'
| func_name '(' '*' ')'
func_application_name '(' ')'
| func_application_name '(' expr_list opt_sort_clause ')'
| func_application_name '(' 'ALL' expr_list opt_sort_clause ')'
| func_application_name '(' 'DISTINCT' expr_list ')'
| func_application_name '(' '*' ')'

within_group_clause ::=
'WITHIN' 'GROUP' '(' single_sort_clause ')'
Expand Down Expand Up @@ -3747,10 +3747,9 @@ rowsfrom_item ::=
opt_col_def_list ::=
'(' col_def_list ')'

func_name ::=
type_function_name
| prefixed_column_path
| 'INDEX'
func_application_name ::=
func_name
| '[' 'FUNCTION' iconst32 ']'

single_sort_clause ::=
'ORDER' 'BY' sortby
Expand Down Expand Up @@ -3898,10 +3897,10 @@ create_as_params ::=
col_def_list ::=
( col_def ) ( ( ',' col_def ) )*

type_function_name ::=
'identifier'
| unreserved_keyword
| type_func_name_keyword
func_name ::=
type_function_name
| prefixed_column_path
| 'INDEX'

opt_existing_window_name ::=
name
Expand Down Expand Up @@ -3942,6 +3941,11 @@ trim_list ::=
| 'FROM' expr_list
| expr_list

type_function_name ::=
'identifier'
| unreserved_keyword
| type_func_name_keyword

char_aliases ::=
'CHAR'
| 'CHARACTER'
Expand Down
8 changes: 4 additions & 4 deletions pkg/ccl/changefeedccl/cdceval/func_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ func (rs *cdcFunctionResolver) ResolveFunction(
// ResolveFunctionByOID implements FunctionReferenceResolver interface.
func (rs *cdcFunctionResolver) ResolveFunctionByOID(
ctx context.Context, oid oid.Oid,
) (string, *tree.Overload, error) {
) (*tree.FunctionName, *tree.Overload, error) {
fnName, overload, err := rs.wrapped.ResolveFunctionByOID(ctx, oid)
if err != nil {
return "", nil, err
return nil, nil, err
}
if err := checkOverloadSupported(fnName, overload); err != nil {
return "", nil, err
if err := checkOverloadSupported(fnName.Object(), overload); err != nil {
return nil, nil, err
}
return fnName, overload, err
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/ccl/logictestccl/tests/3node-tenant/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/sql/faketreeeval/evalctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,8 +446,8 @@ func (ep *DummyEvalPlanner) ResolveFunction(
// ResolveFunctionByOID implements FunctionReferenceResolver interface.
func (ep *DummyEvalPlanner) ResolveFunctionByOID(
ctx context.Context, oid oid.Oid,
) (string, *tree.Overload, error) {
return "", nil, errors.AssertionFailedf("ResolveFunctionByOID unimplemented")
) (*tree.FunctionName, *tree.Overload, error) {
return nil, nil, errors.AssertionFailedf("ResolveFunctionByOID unimplemented")
}

// GetMultiregionConfig is part of the eval.Planner interface.
Expand Down
4 changes: 2 additions & 2 deletions pkg/sql/importer/import_table_creation.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,6 @@ func (r fkResolver) ResolveFunction(
// ResolveFunctionByOID implements the resolver.SchemaResolver interface.
func (r fkResolver) ResolveFunctionByOID(
ctx context.Context, oid oid.Oid,
) (string, *tree.Overload, error) {
return "", nil, errSchemaResolver
) (*tree.FunctionName, *tree.Overload, error) {
return nil, nil, errSchemaResolver
}
101 changes: 101 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/udf_oid_ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
query T
SELECT [FUNCTION 1074]('hello,world', ',')
----
{hello,world}

statement ok
CREATE TABLE t1(a INT PRIMARY KEY, b STRING DEFAULT ([FUNCTION 1074]('hello,world', ',')))

statement ok
INSERT INTO t1(a) VALUES (1)

query IT
SELECT * FROM t1
----
1 {hello,world}

statement ok
INSERT INTO t1 VALUES (2, 'hello,new,world')

statement ok
CREATE INDEX idx ON t1([FUNCTION 1074](b,','))

query IT
SELECT * FROM t1@idx WHERE [FUNCTION 1074](b, ',') = ARRAY['hello','new','world']
----
2 hello,new,world

statement ok
ALTER TABLE t1 ADD CONSTRAINT c_len CHECK ([FUNCTION 814](b) > 2)

statement error pq: failed to satisfy CHECK constraint \(length\(b\) > 2:::INT8\)
INSERT INTO t1 VALUES (3, 'a')

statement ok
CREATE FUNCTION f1() RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$

let $fn_oid
SELECT oid FROM pg_catalog.pg_proc WHERE proname = 'f1'

query I
SELECT [FUNCTION $fn_oid]()
----
1

statement ok
CREATE FUNCTION f2(a STRING) RETURNS STRING LANGUAGE SQL AS $$ SELECT a $$

let $fn_oid
SELECT oid FROM pg_catalog.pg_proc WHERE proname = 'f2'

query T
SELECT [FUNCTION $fn_oid]('hello world')
----
hello world

# Make sure that renaming does not break the reference.
statement ok
ALTER FUNCTION f2(STRING) RENAME TO f2_new;

query T
SELECT [FUNCTION $fn_oid]('hello world')
----
hello world

statement ok
CREATE SCHEMA sc1;

statement ok
ALTER FUNCTION f2_new(STRING) SET SCHEMA sc1;

query T
SELECT [FUNCTION $fn_oid]('hello world')
----
hello world

# Make sure that function dropped cannot be resolved.
statement ok
DROP FUNCTION sc1.f2_new(STRING);

statement error function undefined
SELECT [FUNCTION $fn_oid]('maybe')

subtest cross_db_reference_should_fail

statement ok
CREATE DATABASE db1;

statement ok
USE db1;

statement ok
CREATE FUNCTION f_db1(a STRING) RETURNS STRING LANGUAGE SQL AS $$ SELECT a $$

let $fn_oid
SELECT oid FROM pg_catalog.pg_proc WHERE proname = 'f_db1'

statement ok
USE test;

statement error pq: cross database function references are not supported
SELECT [FUNCTION $fn_oid]('hello world')
7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/fakedist-disk/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/fakedist-vec-off/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/fakedist/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/local-vec-off/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions pkg/sql/logictest/tests/local/generated_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/sql/opt/cat/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ type Catalog interface {
) (*tree.ResolvedFunctionDefinition, error)

// ResolveFunctionByOID resolves a function overload by OID.
ResolveFunctionByOID(ctx context.Context, oid oid.Oid) (string, *tree.Overload, error)
ResolveFunctionByOID(ctx context.Context, oid oid.Oid) (*tree.FunctionName, *tree.Overload, error)

// CheckPrivilege verifies that the current user has the given privilege on
// the given catalog object. If not, then CheckPrivilege returns an error.
Expand Down
4 changes: 2 additions & 2 deletions pkg/sql/opt/testutils/testcat/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ func (tc *Catalog) ResolveFunction(
// ResolveFunctionByOID part of the tree.FunctionReferenceResolver interface.
func (tc *Catalog) ResolveFunctionByOID(
ctx context.Context, oid oid.Oid,
) (string, *tree.Overload, error) {
return "", nil, errors.AssertionFailedf("ResolveFunctionByOID not supported in test catalog")
) (*tree.FunctionName, *tree.Overload, error) {
return nil, nil, errors.AssertionFailedf("ResolveFunctionByOID not supported in test catalog")
}

// CreateFunction handles the CREATE FUNCTION statement.
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/opt_catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ func (oc *optCatalog) ResolveFunction(

func (oc *optCatalog) ResolveFunctionByOID(
ctx context.Context, oid oid.Oid,
) (string, *tree.Overload, error) {
) (*tree.FunctionName, *tree.Overload, error) {
return oc.planner.ResolveFunctionByOID(ctx, oid)
}

Expand Down
Loading

0 comments on commit 6c9468e

Please sign in to comment.