diff --git a/pkg/sql/colexec/execgen/cmd/execgen/select_in_gen.go b/pkg/sql/colexec/execgen/cmd/execgen/select_in_gen.go index d62bfe94bee9..772b6278f514 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/select_in_gen.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/select_in_gen.go @@ -25,6 +25,7 @@ func genSelectIn(inputFileContents string, wr io.Writer) error { "_CANONICAL_TYPE_FAMILY", "{{.CanonicalTypeFamilyStr}}", "_TYPE_WIDTH", typeWidthReplacement, "_GOTYPESLICE", "{{.GoTypeSliceName}}", + "_GOTYPE_UPCAST_INT", `{{if or (eq .VecMethod "Int16") (eq .VecMethod "Int32")}}int64{{else}}{{.GoType}}{{end}}`, "_GOTYPE", "{{.GoType}}", "_TYPE", "{{.VecMethod}}", "TemplateType", "{{.VecMethod}}", diff --git a/pkg/sql/colexec/select_in.eg.go b/pkg/sql/colexec/select_in.eg.go index 820174e75bbd..0890c24ec39f 100644 --- a/pkg/sql/colexec/select_in.eg.go +++ b/pkg/sql/colexec/select_in.eg.go @@ -1039,7 +1039,7 @@ func (pi *projectInOpDecimal) Next() coldata.Batch { type selectInOpInt16 struct { colexecop.OneInputHelper - filterRow []int16 + filterRow []int64 colIdx int hasNulls bool negate bool @@ -1050,7 +1050,7 @@ var _ colexecop.Operator = &selectInOpInt16{} type projectInOpInt16 struct { colexecop.OneInputHelper allocator *colmem.Allocator - filterRow []int16 + filterRow []int64 colIdx int outputIdx int hasNulls bool @@ -1061,19 +1061,20 @@ var _ colexecop.Operator = &projectInOpInt16{} func fillDatumRowInt16( evalCtx *eval.Context, t *types.T, datumTuple *tree.DTuple, -) ([]int16, bool) { +) ([]int64, bool) { // Sort the contents of the tuple, if they are not already sorted. datumTuple.Normalize(evalCtx) - conv := colconv.GetDatumToPhysicalFn(t) - var result []int16 + // Ensure that we always upcast all integer types. + conv := colconv.GetDatumToPhysicalFn(types.Int) + var result []int64 hasNulls := false for _, d := range datumTuple.D { if d == tree.DNull { hasNulls = true } else { convRaw := conv(d) - converted := convRaw.(int16) + converted := convRaw.(int64) result = append(result, converted) } } @@ -1081,7 +1082,7 @@ func fillDatumRowInt16( } func cmpInInt16( - targetElem int16, targetCol coldata.Int16s, filterRow []int16, hasNulls bool, + targetElem int16, targetCol coldata.Int16s, filterRow []int64, hasNulls bool, ) comparisonResult { // Filter row input was already sorted in fillDatumRowInt16, so we can // perform a binary search. @@ -1276,7 +1277,7 @@ func (pi *projectInOpInt16) Next() coldata.Batch { type selectInOpInt32 struct { colexecop.OneInputHelper - filterRow []int32 + filterRow []int64 colIdx int hasNulls bool negate bool @@ -1287,7 +1288,7 @@ var _ colexecop.Operator = &selectInOpInt32{} type projectInOpInt32 struct { colexecop.OneInputHelper allocator *colmem.Allocator - filterRow []int32 + filterRow []int64 colIdx int outputIdx int hasNulls bool @@ -1298,19 +1299,20 @@ var _ colexecop.Operator = &projectInOpInt32{} func fillDatumRowInt32( evalCtx *eval.Context, t *types.T, datumTuple *tree.DTuple, -) ([]int32, bool) { +) ([]int64, bool) { // Sort the contents of the tuple, if they are not already sorted. datumTuple.Normalize(evalCtx) - conv := colconv.GetDatumToPhysicalFn(t) - var result []int32 + // Ensure that we always upcast all integer types. + conv := colconv.GetDatumToPhysicalFn(types.Int) + var result []int64 hasNulls := false for _, d := range datumTuple.D { if d == tree.DNull { hasNulls = true } else { convRaw := conv(d) - converted := convRaw.(int32) + converted := convRaw.(int64) result = append(result, converted) } } @@ -1318,7 +1320,7 @@ func fillDatumRowInt32( } func cmpInInt32( - targetElem int32, targetCol coldata.Int32s, filterRow []int32, hasNulls bool, + targetElem int32, targetCol coldata.Int32s, filterRow []int64, hasNulls bool, ) comparisonResult { // Filter row input was already sorted in fillDatumRowInt32, so we can // perform a binary search. diff --git a/pkg/sql/colexec/select_in_tmpl.go b/pkg/sql/colexec/select_in_tmpl.go index a4de8383b601..10d564fa4ae4 100644 --- a/pkg/sql/colexec/select_in_tmpl.go +++ b/pkg/sql/colexec/select_in_tmpl.go @@ -56,6 +56,7 @@ var ( // {{/* type _GOTYPESLICE interface{} +type _GOTYPE_UPCAST_INT interface{} type _GOTYPE interface{} type _TYPE interface{} @@ -146,7 +147,7 @@ func GetInOperator( type selectInOp_TYPE struct { colexecop.OneInputHelper - filterRow []_GOTYPE + filterRow []_GOTYPE_UPCAST_INT colIdx int hasNulls bool negate bool @@ -157,7 +158,7 @@ var _ colexecop.Operator = &selectInOp_TYPE{} type projectInOp_TYPE struct { colexecop.OneInputHelper allocator *colmem.Allocator - filterRow []_GOTYPE + filterRow []_GOTYPE_UPCAST_INT colIdx int outputIdx int hasNulls bool @@ -168,19 +169,24 @@ var _ colexecop.Operator = &projectInOp_TYPE{} func fillDatumRow_TYPE( evalCtx *eval.Context, t *types.T, datumTuple *tree.DTuple, -) ([]_GOTYPE, bool) { +) ([]_GOTYPE_UPCAST_INT, bool) { // Sort the contents of the tuple, if they are not already sorted. datumTuple.Normalize(evalCtx) + // {{if or (eq .VecMethod "Int16") (eq .VecMethod "Int32")}} + // Ensure that we always upcast all integer types. + conv := colconv.GetDatumToPhysicalFn(types.Int) + //{{else}} conv := colconv.GetDatumToPhysicalFn(t) - var result []_GOTYPE + // {{end}} + var result []_GOTYPE_UPCAST_INT hasNulls := false for _, d := range datumTuple.D { if d == tree.DNull { hasNulls = true } else { convRaw := conv(d) - converted := convRaw.(_GOTYPE) + converted := convRaw.(_GOTYPE_UPCAST_INT) result = append(result, converted) } } @@ -188,7 +194,7 @@ func fillDatumRow_TYPE( } func cmpIn_TYPE( - targetElem _GOTYPE, targetCol _GOTYPESLICE, filterRow []_GOTYPE, hasNulls bool, + targetElem _GOTYPE, targetCol _GOTYPESLICE, filterRow []_GOTYPE_UPCAST_INT, hasNulls bool, ) comparisonResult { // Filter row input was already sorted in fillDatumRow_TYPE, so we can // perform a binary search. diff --git a/pkg/sql/logictest/testdata/logic_test/select b/pkg/sql/logictest/testdata/logic_test/select index 0af830569895..6599db308afb 100644 --- a/pkg/sql/logictest/testdata/logic_test/select +++ b/pkg/sql/logictest/testdata/logic_test/select @@ -938,3 +938,14 @@ ORDER BY 1 DESC ---- 5ebfedee-0dcf-41e6-a315-5fa0b51b9883 2 1999-11-30 23:59:58 +0000 +0000 5ebfedee-0dcf-41e6-a315-5fa0b51b9882 1 1999-11-30 23:59:59 +0000 +0000 + +# Regression test for incorrect evaluation of the IN filter due to integer +# overflow when working with INT4 type (#102864). +statement ok +CREATE TABLE t102864 (c INT4); +INSERT INTO t102864 (c) VALUES (0); + +query I +SELECT c FROM t102864 WHERE c IN (0, 862827606027206657::INT8); +---- +0