diff --git a/pkg/sql/opt/norm/inline_funcs.go b/pkg/sql/opt/norm/inline_funcs.go index c60a69da3e5a..b1b1a697c689 100644 --- a/pkg/sql/opt/norm/inline_funcs.go +++ b/pkg/sql/opt/norm/inline_funcs.go @@ -388,6 +388,16 @@ func (c *CustomFuncs) InlineConstVar(f memo.FiltersExpr) memo.FiltersExpr { replace = func(nd opt.Expr) opt.Expr { if t, ok := nd.(*memo.VariableExpr); ok { if e, ok := vals[t.Col]; ok { + // The constant was matched against the variable using Equivalent + // (not Identical) above, so its type may differ from the + // variable's (e.g. a STRING constant for a NAME column). + // Substituting the constant directly would change the result of + // type-sensitive expressions such as pg_typeof, so cast the + // constant to the variable's type when the two are not identical. + colType := c.mem.Metadata().ColumnMeta(t.Col).Type + if !e.DataType().Identical(colType) { + return c.f.ConstructCast(e, colType) + } return e } } diff --git a/pkg/sql/opt/norm/testdata/rules/inline b/pkg/sql/opt/norm/testdata/rules/inline index be0f9a2f920c..d7f33da60e36 100644 --- a/pkg/sql/opt/norm/testdata/rules/inline +++ b/pkg/sql/opt/norm/testdata/rules/inline @@ -226,6 +226,27 @@ project │ └── true [as=column14:14] └── false +# Regression test for #170544. InlineConstVar must not replace a variable with a +# constant whose type is equivalent but not identical to the variable's type +# without a cast, since that changes the result of type-sensitive expressions +# such as pg_typeof. Here n is NAME and the constant 'hello' is STRING; the +# inlined constant is cast back to NAME so pg_typeof(n) still reports 'name' and +# the row is not incorrectly filtered out. +exec-ddl +CREATE TABLE t_name (n NAME) +---- + +norm expect=InlineConstVar +SELECT * FROM t_name WHERE n = 'hello' AND pg_typeof(n)::TEXT = 'name' +---- +select + ├── columns: n:1!null + ├── fd: ()-->(1) + ├── scan t_name + │ └── columns: n:1 + └── filters + └── n:1 = 'hello' [outer=(1), constraints=(/1: [/'hello' - /'hello']; tight), fd=()-->(1)] + # -------------------------------------------------- # InlineProjectConstants # --------------------------------------------------