Skip to content

Commit

Permalink
sql: do not type-check subqueries in views outside of optbuilder
Browse files Browse the repository at this point in the history
This commit fixes a bug that was caused when attempting to re-type-check
a view's query that contains a subquery. This type-checking occurred
outside of optbuilder. However, the logic for type-checking subqueries
is only implemented within optbuilder, so it failed.

Fixes #105259

Release note (bug fix): A bug has been fixed that caused internal errors
when using user-defined types in views and user-defined functions that
have subqueries. This bug was present when using views since version
v21.2. It was present when using user-defined functions since v23.1.
  • Loading branch information
mgartner committed Jul 17, 2023
1 parent 26456a8 commit bd38886
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 0 deletions.
14 changes: 14 additions & 0 deletions pkg/sql/create_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,20 @@ func serializeUserDefinedTypes(
default:
return true, expr, nil
}
// We cannot type-check subqueries without using optbuilder, and there
// is no need to because we only need to rewrite string values that are
// directly cast to enums. For example, we must rewrite the 'foo' in:
//
// SELECT 'foo'::myenum
//
// We don't need to rewrite the 'foo' in the query below, which can be
// corrupted by renaming the 'foo' value in the myenum type.
//
// SELECT (SELECT 'foo')::myenum
//
if _, ok := innerExpr.(*tree.Subquery); ok {
return true, expr, nil
}
// semaCtx may be nil if this is a virtual view being created at
// init time.
var typeResolver tree.TypeReferenceResolver
Expand Down
27 changes: 27 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/udf
Original file line number Diff line number Diff line change
Expand Up @@ -3619,3 +3619,30 @@ CREATE FUNCTION public.func104242_not_null()
$$

subtest end

# Regression test for #105259. Do not type-check subqueries in UDFs outside
# optbuilder. Doing so can cause internal errors.
subtest regression_105259

statement ok
CREATE TYPE e105259 AS ENUM ('foo');

statement ok
CREATE FUNCTION f() RETURNS VOID LANGUAGE SQL AS $$
SELECT (SELECT 'foo')::e105259;
SELECT NULL;
$$

query T
SELECT f()
----
NULL

statement ok
ALTER TYPE e105259 RENAME VALUE 'foo' TO 'bar'

# Renaming the enum value corrupts the UDF. This is expected behavior.
statement error pgcode 22P02 invalid input value for enum e105259: "foo"
SELECT f()

subtest end
31 changes: 31 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/views
Original file line number Diff line number Diff line change
Expand Up @@ -1829,6 +1829,8 @@ CREATE VIEW pg_comedies AS
statement error pq: cannot drop columns from view
CREATE OR REPLACE VIEW comedies AS SELECT ARRAY[films.*]::string FROM films;

subtest end

subtest circular_dependency

statement ok
Expand Down Expand Up @@ -1863,6 +1865,8 @@ DROP VIEW cd_v1;
statement ok
DROP VIEW cd_v1 CASCADE;

subtest end

# Regression test for #104927. Correctly resolve table references in views as
# TupleStars.
subtest regression_104927
Expand Down Expand Up @@ -1893,3 +1897,30 @@ query T
SELECT * FROM v104927
----
[{"i": 1, "s": "foo"}]

subtest end

# Regression test for #105259. Do not type-check subqueries in views outside
# optbuilder. Doing so can cause internal errors.
subtest regression_105259

statement ok
CREATE TYPE e105259 AS ENUM ('foo');

statement ok
CREATE VIEW v105259 AS
SELECT (SELECT 'foo')::e105259

query T
SELECT * FROM v105259
----
foo

statement ok
ALTER TYPE e105259 RENAME VALUE 'foo' TO 'bar'

# Renaming the enum value corrupts the view. This is expected behavior.
statement error pgcode 22P02 invalid input value for enum e105259: "foo"
SELECT * FROM v105259

subtest end
14 changes: 14 additions & 0 deletions pkg/sql/schemachanger/scbuild/builder_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,20 @@ func (b *builderState) serializeUserDefinedTypes(queryStr string) string {
default:
return true, expr, nil
}
// We cannot type-check subqueries without using optbuilder, and there
// is no need to because we only need to rewrite string values that are
// directly cast to enums. For example, we must rewrite the 'foo' in:
//
// SELECT 'foo'::myenum
//
// We don't need to rewrite the 'foo' in the query below, which can be
// corrupted by renaming the 'foo' value in the myenum type.
//
// SELECT (SELECT 'foo')::myenum
//
if _, ok := innerExpr.(*tree.Subquery); ok {
return true, expr, nil
}
var typ *types.T
typ, err = tree.ResolveType(b.ctx, typRef, b.semaCtx.TypeResolver)
if err != nil {
Expand Down

0 comments on commit bd38886

Please sign in to comment.