From d0a5b853a31d4739a62c09f059577185a618ead4 Mon Sep 17 00:00:00 2001 From: Marcus Gartner Date: Mon, 17 Oct 2022 15:48:39 -0400 Subject: [PATCH] sql: disallow star expressions in UDF bodies This commit disallows star expressions in UDF bodies (see the release note below). It also fixes an error message returned when trying to create a view that references non-existent columns that incorrectly mentioned star expressions. Fixes #86070 Release note (sql change): Star expressions, e.g., `SELECT * FROM ...` are no longer allowed in statements in user-defined functions. They were allowed in early betas of v22.2 from v22.2.0-beta.1 to v22.2.0-beta.4, but have been disallowed because they do not behave correctly. Issue #90080 tracks re-enabling star expressions in UDFs. --- pkg/sql/logictest/testdata/logic_test/udf | 41 ++++++++++++++----- pkg/sql/logictest/testdata/logic_test/views | 7 +++- pkg/sql/opt/optbuilder/project.go | 7 ++-- pkg/sql/opt/optbuilder/scope.go | 7 +++- .../opt/optbuilder/testdata/create_function | 2 +- pkg/sql/opt/optbuilder/util.go | 3 ++ 6 files changed, 50 insertions(+), 17 deletions(-) diff --git a/pkg/sql/logictest/testdata/logic_test/udf b/pkg/sql/logictest/testdata/logic_test/udf index 06537bc24c08..44d35443fb77 100644 --- a/pkg/sql/logictest/testdata/logic_test/udf +++ b/pkg/sql/logictest/testdata/logic_test/udf @@ -49,8 +49,26 @@ CREATE FUNCTION c(i INT, j INT) RETURNS INT LANGUAGE SQL AS 'SELECT i - j' statement error column \"j\" does not exist CREATE FUNCTION err(i INT) RETURNS INT LANGUAGE SQL AS 'SELECT j' -statement error column \"j\" does not exist -CREATE FUNCTION err(i INT) RETURNS INT LANGUAGE SQL AS 'SELECT * FROM ab WHERE a = j' +statement error pgcode 42703 column \"j\" does not exist +CREATE FUNCTION err(i INT) RETURNS INT LANGUAGE SQL AS 'SELECT a FROM ab WHERE a = j' + +statement error pgcode 0A000 functions do not currently support \* expressions +CREATE FUNCTION err(i INT) RETURNS ab LANGUAGE SQL AS 'SELECT * FROM ab' + +statement error pgcode 0A000 functions do not currently support \* expressions +CREATE FUNCTION err(i INT) RETURNS ab LANGUAGE SQL AS 'SELECT ab.* FROM ab' + +statement error pgcode 0A000 functions do not currently support \* expressions +CREATE FUNCTION err(i INT) RETURNS ab LANGUAGE SQL AS $$ + SELECT 1; + SELECT * FROM ab; +$$ + +statement error pgcode 0A000 functions do not currently support \* expressions +CREATE FUNCTION err(i INT) RETURNS INT LANGUAGE SQL AS $$ + SELECT * FROM ab; + SELECT 1; +$$ statement ok CREATE FUNCTION d(i INT2) RETURNS INT4 LANGUAGE SQL AS 'SELECT i' @@ -2403,15 +2421,16 @@ SELECT imp(), (1,2,'a')::imp = imp(), pg_typeof(imp()) ---- (1,2,a) true imp -statement ok -CREATE FUNCTION imp_star() RETURNS imp LANGUAGE SQL AS $$ - SELECT * FROM imp -$$ - -query TBT -SELECT imp_star(), (1,2,'a')::imp = imp_star(), pg_typeof(imp_star()) ----- -(1,2,a) true imp +# TODO(#90080): Allow star expressions in UDFs. +# statement ok +# CREATE FUNCTION imp_star() RETURNS imp LANGUAGE SQL AS $$ +# SELECT * FROM imp +# $$ +# +# query TBT +# SELECT imp_star(), (1,2,'a')::imp = imp_star(), pg_typeof(imp_star()) +# ---- +# (1,2,a) true imp statement ok INSERT INTO imp VALUES (100, 200, 'z') diff --git a/pkg/sql/logictest/testdata/logic_test/views b/pkg/sql/logictest/testdata/logic_test/views index 61796b891858..36f31f5bbfe8 100644 --- a/pkg/sql/logictest/testdata/logic_test/views +++ b/pkg/sql/logictest/testdata/logic_test/views @@ -43,6 +43,12 @@ CREATE VIEW v6 (x, y) AS SELECT a, b FROM v1 statement ok CREATE VIEW v7 (x, y) AS SELECT a, b FROM v1 ORDER BY a DESC LIMIT 2 +statement error pgcode 42703 column \"j\" does not exist +CREATE VIEW err AS SELECT j FROM t + +statement error pgcode 42703 column \"j\" does not exist +CREATE VIEW err AS SELECT a FROM t WHERE a = j + query II colnames,rowsort SELECT * FROM v1 ---- @@ -1492,4 +1498,3 @@ SELECT * FROM v; statement ok SET DATABASE = test; - diff --git a/pkg/sql/opt/optbuilder/project.go b/pkg/sql/opt/optbuilder/project.go index fa2b4944e749..a9c9e7622a9c 100644 --- a/pkg/sql/opt/optbuilder/project.go +++ b/pkg/sql/opt/optbuilder/project.go @@ -196,9 +196,10 @@ func (b *Builder) resolveColRef(e tree.Expr, inScope *scope) tree.TypedExpr { if resolveErr != nil { // It may be a reference to a table, e.g. SELECT tbl FROM tbl. // Attempt to resolve as a TupleStar. We do not attempt to resolve - // as a TupleStar if we are inside a view definition because views - // do not support * expressions. - if !b.insideViewDef && sqlerrors.IsUndefinedColumnError(resolveErr) { + // as a TupleStar if we are inside a view or function definition + // because views and functions do not support * expressions. + if !b.insideViewDef && !b.insideFuncDef && + sqlerrors.IsUndefinedColumnError(resolveErr) { return func() tree.TypedExpr { defer wrapColTupleStarPanic(resolveErr) return inScope.resolveType(columnNameAsTupleStar(colName), types.Any) diff --git a/pkg/sql/opt/optbuilder/scope.go b/pkg/sql/opt/optbuilder/scope.go index 61291f907411..af83dc178a28 100644 --- a/pkg/sql/opt/optbuilder/scope.go +++ b/pkg/sql/opt/optbuilder/scope.go @@ -1025,7 +1025,12 @@ func (s *scope) VisitPre(expr tree.Expr) (recurse bool, newExpr tree.Expr) { case *tree.ColumnItem: colI, resolveErr := colinfo.ResolveColumnItem(s.builder.ctx, s, t) if resolveErr != nil { - if sqlerrors.IsUndefinedColumnError(resolveErr) { + // It may be a reference to a table, e.g. SELECT tbl FROM tbl. + // Attempt to resolve as a TupleStar. We do not attempt to resolve + // as a TupleStar if we are inside a view or function definition + // because views and functions do not support * expressions. + if !s.builder.insideViewDef && !s.builder.insideFuncDef && + sqlerrors.IsUndefinedColumnError(resolveErr) { // Attempt to resolve as columnname.*, which allows items // such as SELECT row_to_json(tbl_name) FROM tbl_name to work. return func() (bool, tree.Expr) { diff --git a/pkg/sql/opt/optbuilder/testdata/create_function b/pkg/sql/opt/optbuilder/testdata/create_function index 370ea14ad61f..5ee1e03191e2 100644 --- a/pkg/sql/opt/optbuilder/testdata/create_function +++ b/pkg/sql/opt/optbuilder/testdata/create_function @@ -110,7 +110,7 @@ create-function build CREATE FUNCTION f() RETURNS INT LANGUAGE SQL AS $$ SELECT * FROM ab $$ ---- -error (42P13): return type mismatch in function declared to return int +error (0A000): unimplemented: functions do not currently support * expressions build CREATE FUNCTION f() RETURNS INT LANGUAGE SQL BEGIN ATOMIC SELECT 1; END; diff --git a/pkg/sql/opt/optbuilder/util.go b/pkg/sql/opt/optbuilder/util.go index c210674d376c..c3f7f68781a0 100644 --- a/pkg/sql/opt/optbuilder/util.go +++ b/pkg/sql/opt/optbuilder/util.go @@ -64,6 +64,9 @@ func (b *Builder) expandStar( if b.insideViewDef { panic(unimplemented.NewWithIssue(10028, "views do not currently support * expressions")) } + if b.insideFuncDef { + panic(unimplemented.NewWithIssue(90080, "functions do not currently support * expressions")) + } switch t := expr.(type) { case *tree.TupleStar: texpr := inScope.resolveType(t.Expr, types.Any)