Skip to content

Commit 6ba3e71

Browse files
craig[bot]DrewKimball
andcommitted
Merge #143170
143170: sql: only re-use resolved routine type when flag is set r=mgartner a=DrewKimball This commit adds a `RoutineUseResolvedType` flag to the `SemaContext` properties to indicate that type-checking for a routine that has already been resolved to a concrete type should short-circuit. This is used to determine the column type for a `Values` operator which depends on a RECORD-returning routine, which only determines its type after the body is built. This will prevent regressions in other code paths that do not desire this short-circuiting behavior. Fixes #142615 Release note (bug fix): Fixed a bug in `v24.1.14`, `v24.3.7`, `v24.3.8`, and `v25.1` which could cause a nil-pointer error when a column's default expression contained a volatile expression (like `nextval`) as a UDF argument. Co-authored-by: Drew Kimball <[email protected]>
2 parents fc31030 + d4a233f commit 6ba3e71

File tree

3 files changed

+50
-11
lines changed

3 files changed

+50
-11
lines changed

pkg/sql/logictest/testdata/logic_test/udf

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,8 @@ LIMIT
981981
subtest end
982982

983983
# Regression test for #104009.
984+
subtest regression_104009
985+
984986
statement ok
985987
CREATE TABLE ab104009(a INT PRIMARY KEY, b INT)
986988

@@ -1005,6 +1007,10 @@ PREPARE p AS SELECT f($1::REGCLASS::INT)
10051007
statement ok
10061008
EXECUTE p(10)
10071009

1010+
subtest end
1011+
1012+
subtest regression_142886
1013+
10081014
# Regression test for #142886 - we should not be able to create an overload that
10091015
# differs only in the type width of the input type.
10101016
statement ok
@@ -1015,3 +1021,28 @@ CREATE FUNCTION f142886(p VARCHAR(100)) RETURNS INT LANGUAGE SQL AS $$ SELECT 0;
10151021

10161022
statement ok
10171023
DROP FUNCTION f142886;
1024+
1025+
subtest end
1026+
1027+
# Regression test for #142615.
1028+
subtest regression_142615
1029+
1030+
statement ok
1031+
create function app_to_db_id(app_id INT8) RETURNS INT8 LANGUAGE plpgsql AS $$ BEGIN RETURN app_id * 2; END; $$;
1032+
1033+
statement ok
1034+
create sequence seq1;
1035+
1036+
statement ok
1037+
create table test (id int8 not null default app_to_db_id(nextval('seq1'::REGCLASS)));
1038+
1039+
query TTITT rowsort
1040+
select * from pg_catalog.pg_attrdef;
1041+
----
1042+
1508958170 132 2 unique_rowid() unique_rowid()
1043+
1202826234 151 1 gen_random_uuid() gen_random_uuid()
1044+
1202826232 151 3 now() now()
1045+
3466299042 175 1 public.app_to_db_id(nextval('public.seq1'::REGCLASS)) public.app_to_db_id(nextval('public.seq1'::REGCLASS))
1046+
3466299041 175 2 unique_rowid() unique_rowid()
1047+
1048+
subtest end

pkg/sql/opt/optbuilder/values.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,15 @@ func (b *Builder) buildValuesClause(
7777
elemPos += numCols
7878
if texpr.ResolvedType().IsWildcardType() {
7979
// Type-check the expression once again in order to update expressions
80-
// that wrap a routine to reflect the modified type. Make sure to use
81-
// the previously resolved type as the desired type, since the AST may
82-
// have been modified to remove type annotations. This can happen when
83-
// the routine's return type is unknown until its body is built.
84-
texpr, err = tree.TypeCheck(b.ctx, texpr, b.semaCtx, texpr.ResolvedType())
85-
if err != nil {
86-
panic(err)
87-
}
80+
// that wrap a routine to reflect the modified type.
81+
func() {
82+
defer b.semaCtx.Properties.Restore(b.semaCtx.Properties)
83+
b.semaCtx.Properties.RoutineUseResolvedType = true
84+
texpr, err = tree.TypeCheck(b.ctx, texpr, b.semaCtx, desired)
85+
if err != nil {
86+
panic(err)
87+
}
88+
}()
8889
}
8990
if typ := texpr.ResolvedType(); typ.Family() != types.UnknownFamily {
9091
if colTypes[colIdx].Family() == types.UnknownFamily {

pkg/sql/sem/tree/type_check.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ type SemaProperties struct {
9696
// IgnoreUnpreferredOverloads is set to true when "unpreferred" overloads
9797
// should not be used during type-checking and overload resolution.
9898
IgnoreUnpreferredOverloads bool
99+
100+
// RoutineUseResolvedType is set to true when type-checking for a routine
101+
// should reuse the already resolved type, if any. This is used to handle
102+
// "re-type-checking" that occurs for a RECORD-returning routine, for which
103+
// the return type is not known until the routine body is built.
104+
RoutineUseResolvedType bool
99105
}
100106

101107
type semaRequirements struct {
@@ -1179,9 +1185,10 @@ func (expr *FuncExpr) typeCheckWithFuncAncestor(semaCtx *SemaContext, fn func()
11791185
func (expr *FuncExpr) TypeCheck(
11801186
ctx context.Context, semaCtx *SemaContext, desired *types.T,
11811187
) (TypedExpr, error) {
1182-
if expr.fn != nil && expr.fn.Type != BuiltinRoutine && expr.typ != nil {
1183-
// Don't overwrite the resolved properties for a user-defined routine if the
1184-
// routine has already been resolved.
1188+
if semaCtx != nil && semaCtx.Properties.RoutineUseResolvedType &&
1189+
expr.typ != nil && !expr.typ.IsWildcardType() {
1190+
// Don't overwrite the resolved properties for a routine if the routine has
1191+
// already been resolved (and we are in a context that needs this behavior).
11851192
return expr, nil
11861193
}
11871194

0 commit comments

Comments
 (0)