From 07835e14314d6541e0788b5afdac5272c9d65b61 Mon Sep 17 00:00:00 2001 From: Marcus Gartner Date: Thu, 1 Aug 2024 16:59:54 -0400 Subject: [PATCH] colexec: fix projections with constant NULL values This commit fixes a bug in the vectorized engine that caused incorrect results when projections operated on constant NULL values. The `proj_const_right_ops` operators do not correctly handle NULL inputs. So, we avoid these code paths when operator does not operate on NULL values and the RHS of an operator is NULL by simply projecting NULLs. Fixes #127814 Release note (bug fix): A bug has been fixed that could cause incorrect evaluation of scalar expressions involving `NULL` values in rare cases. --- pkg/sql/colexec/colbuilder/execplan.go | 8 +++++++- pkg/sql/logictest/testdata/logic_test/subquery | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/pkg/sql/colexec/colbuilder/execplan.go b/pkg/sql/colexec/colbuilder/execplan.go index 374c05bad0f0..7eaeef453108 100644 --- a/pkg/sql/colexec/colbuilder/execplan.go +++ b/pkg/sql/colexec/colbuilder/execplan.go @@ -2716,6 +2716,7 @@ func planProjectionExpr( resultIdx = len(typs) // The projection result will be outputted to a new column which is // appended to the input batch. + // TODO(#127814): We may need to handle the case when the left is DNull. op, err = colexecprojconst.GetProjectionLConstOperator( allocator, typs, left.ResolvedType(), outputType, projOp, input, rightIdx, lConstArg, resultIdx, evalCtx, binOp, cmpExpr, calledOnNullInput, @@ -2758,7 +2759,12 @@ func planProjectionExpr( // The projection result will be outputted to a new column which is // appended to the input batch. resultIdx = len(typs) - if isCmpProjOp { + if !calledOnNullInput && right == tree.DNull { + // If the right is NULL and the operator is not called on NULL, + // simply project NULL. + op = colexecbase.NewConstNullOp(allocator, input, resultIdx) + } else if isCmpProjOp { + // Use optimized operators for special cases. switch cmpProjOp.Symbol { case treecmp.Like, treecmp.NotLike, treecmp.ILike, treecmp.NotILike: negate, caseInsensitive := examineLikeOp(cmpProjOp) diff --git a/pkg/sql/logictest/testdata/logic_test/subquery b/pkg/sql/logictest/testdata/logic_test/subquery index a08d12fd75ad..460f426f1a2b 100644 --- a/pkg/sql/logictest/testdata/logic_test/subquery +++ b/pkg/sql/logictest/testdata/logic_test/subquery @@ -1039,4 +1039,18 @@ LEFT JOIN LATERAL ( row-1 row-1 {row-1} 1 row-2 row-2 {row-2} 1 -subtest end +# Regression test for #127814. The vectorized engine should correctly project +# expressions operating on NULL. +statement ok +CREATE TABLE t127814_empty (i INT) + +statement ok +CREATE TABLE t127814 (o OID) + +statement ok +INSERT INTO t127814 VALUES (0) + +query B +SELECT o NOT IN ((SELECT NULL FROM t127814_empty),) FROM t127814 +---- +NULL