Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: handle implicit record return types better #96696

Merged
merged 1 commit into from Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 47 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/udf
Expand Up @@ -3044,3 +3044,50 @@ query I
SELECT count(descriptor) FROM system.descriptor WHERE id = $dropped_fn_id;
----
0

subtest udt_alter

statement ok
CREATE TABLE t_alter (
a INT PRIMARY KEY,
b INT
)

statement ok
CREATE FUNCTION f_rtbl() RETURNS t_alter LANGUAGE SQL AS 'SELECT 1, 2;'

query T
SELECT f_rtbl();
----
(1,2)

statement ok
ALTER TABLE t_alter DROP COLUMN b;

statement error pq: return type mismatch in function declared to return t_alter
SELECT f_rtbl();

statement ok
ALTER TABLE t_alter ADD COLUMN b INT;

query T
SELECT f_rtbl();
----
(1,2)

statement ok
SET enable_experimental_alter_column_type_general=true

statement ok
ALTER TABLE t_alter ALTER b TYPE FLOAT;

statement error pq: return type mismatch in function declared to return t_alter
SELECT f_rtbl();

statement ok
ALTER TABLE t_alter ALTER b TYPE INT;

query T
SELECT f_rtbl();
----
(1,2)
16 changes: 10 additions & 6 deletions pkg/sql/logictest/testdata/logic_test/udf_star
Expand Up @@ -173,16 +173,20 @@ SELECT f_allcolsel_alias()
----
(1,2)

# Return an error after adding a column when the table is used as the return
# type. Note that this behavior is ok for late binding.
statement ok
ALTER TABLE t_twocol ADD COLUMN c INT DEFAULT 5;

# TODO(#95558): With early binding, postgres returns an error after adding a
# column when the table is used as the return type. Note that this behavior is
# ok for late binding.
query T
statement error pq: return type mismatch in function declared to return t_twocol
SELECT f_unqualified_twocol()

# Dropping the new column renders the function usable again.
statement ok
ALTER TABLE t_twocol DROP COLUMN c;

statement ok
SELECT f_unqualified_twocol()
----
(1,2)

# Altering a column type is not allowed in postgres or CRDB.
statement error pq: cannot alter type of column "b" because function "f_unqualified_twocol" depends on it
Expand Down
17 changes: 17 additions & 0 deletions pkg/sql/opt/optbuilder/scalar.go
Expand Up @@ -620,6 +620,23 @@ func (b *Builder) buildUDF(
) (out opt.ScalarExpr) {
o := f.ResolvedOverload()

// Validate that the return types match the original return types defined in
// the function. Return types like user defined return types may change since
// the function was first created.
rtyp := f.ResolvedType()
if rtyp.UserDefined() {
funcReturnType, err := tree.ResolveType(b.ctx,
&tree.OIDTypeReference{OID: rtyp.Oid()}, b.semaCtx.TypeResolver)
if err != nil {
panic(err)
}
if !funcReturnType.Equivalent(rtyp) {
panic(pgerror.Newf(
pgcode.InvalidFunctionDefinition,
"return type mismatch in function declared to return %s", rtyp.Name()))
}
}

// Build the argument expressions.
var args memo.ScalarListExpr
if len(f.Exprs) > 0 {
Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/schema_resolver.go
Expand Up @@ -320,6 +320,8 @@ func (sr *schemaResolver) ResolveType(
}

// ResolveTypeByOID implements the tree.TypeReferenceResolver interface.
// Note: Type resolution only works for OIDs of user-defined types. Builtin
// types do not need to be hydrated.
func (sr *schemaResolver) ResolveTypeByOID(ctx context.Context, oid oid.Oid) (*types.T, error) {
return typedesc.ResolveHydratedTByOID(ctx, oid, sr)
}
Expand Down