diff --git a/pkg/sql/colexec/bool_vec_to_sel.go b/pkg/sql/colexec/bool_vec_to_sel.go index 040a3ddc125b..50cfc1513ee4 100644 --- a/pkg/sql/colexec/bool_vec_to_sel.go +++ b/pkg/sql/colexec/bool_vec_to_sel.go @@ -31,7 +31,7 @@ func boolOrUnknownToSelOp( // If the column is of an Unknown type, then all values in that column // must be NULLs, so the selection vector will always be empty, and we // can simply plan a zero operator. - return NewZeroOp(input), nil + return newZeroOp(input), nil default: return nil, errors.Errorf("unexpectedly %s is neither bool nor unknown", typs[vecIdx]) } diff --git a/pkg/sql/colexec/execplan.go b/pkg/sql/colexec/execplan.go index 7eb704b7a657..a88c4fb2f38d 100644 --- a/pkg/sql/colexec/execplan.go +++ b/pkg/sql/colexec/execplan.go @@ -195,6 +195,12 @@ func isSupported( case core.Noop != nil: return true, nil + case core.Values != nil: + if core.Values.NumRows != 0 { + return false, errors.Newf("values core only with zero rows supported") + } + return true, nil + case core.TableReader != nil: if core.TableReader.IsCheck { return false, errors.Newf("scrub table reader is unsupported in vectorized") @@ -628,6 +634,20 @@ func NewColOperator( result.Op, result.IsStreaming = NewNoop(inputs[0]), true result.ColumnTypes = make([]*types.T, len(spec.Input[0].ColumnTypes)) copy(result.ColumnTypes, spec.Input[0].ColumnTypes) + + case core.Values != nil: + if err := checkNumIn(inputs, 0); err != nil { + return result, err + } + if core.Values.NumRows != 0 { + return result, errors.AssertionFailedf("values core only with zero rows supported, %d given", core.Values.NumRows) + } + result.Op, result.IsStreaming = NewZeroOpNoInput(), true + result.ColumnTypes = make([]*types.T, len(core.Values.Columns)) + for i, col := range core.Values.Columns { + result.ColumnTypes[i] = col.Type + } + case core.TableReader != nil: if err := checkNumIn(inputs, 0); err != nil { return result, err @@ -1376,7 +1396,7 @@ func (r *postProcessResult) planFilterExpr( if helper.Expr == tree.DNull { // The filter expression is tree.DNull meaning that it is always false, so // we put a zero operator. - r.Op = NewZeroOp(r.Op) + r.Op = newZeroOp(r.Op) return nil } var filterColumnTypes []*types.T diff --git a/pkg/sql/colexec/operator.go b/pkg/sql/colexec/operator.go index c94ad8712e3f..e3781acc9df0 100644 --- a/pkg/sql/colexec/operator.go +++ b/pkg/sql/colexec/operator.go @@ -185,8 +185,8 @@ type zeroOperator struct { var _ colexecbase.Operator = &zeroOperator{} -// NewZeroOp creates a new operator which just returns an empty batch. -func NewZeroOp(input colexecbase.Operator) colexecbase.Operator { +// newZeroOp creates a new operator which just returns an empty batch. +func newZeroOp(input colexecbase.Operator) colexecbase.Operator { return &zeroOperator{OneInputNode: NewOneInputNode(input)} } @@ -198,6 +198,25 @@ func (s *zeroOperator) Next(ctx context.Context) coldata.Batch { return coldata.ZeroBatch } +type zeroOperatorNoInput struct { + colexecbase.ZeroInputNode + NonExplainable +} + +var _ colexecbase.Operator = &zeroOperatorNoInput{} + +// NewZeroOpNoInput creates a new operator which just returns an empty batch +// and doesn't an input. +func NewZeroOpNoInput() colexecbase.Operator { + return &zeroOperatorNoInput{} +} + +func (s *zeroOperatorNoInput) Init() {} + +func (s *zeroOperatorNoInput) Next(ctx context.Context) coldata.Batch { + return coldata.ZeroBatch +} + type singleTupleNoInputOperator struct { colexecbase.ZeroInputNode NonExplainable diff --git a/pkg/sql/colflow/vectorized_flow_space_test.go b/pkg/sql/colflow/vectorized_flow_space_test.go index 409d9c44b6cf..d759296ab62c 100644 --- a/pkg/sql/colflow/vectorized_flow_space_test.go +++ b/pkg/sql/colflow/vectorized_flow_space_test.go @@ -82,9 +82,9 @@ func TestVectorizeInternalMemorySpaceError(t *testing.T) { for _, tc := range testCases { for _, success := range []bool{true, false} { t.Run(fmt.Sprintf("%s-success-expected-%t", tc.desc, success), func(t *testing.T) { - inputs := []colexecbase.Operator{colexec.NewZeroOp(nil)} + inputs := []colexecbase.Operator{colexec.NewZeroOpNoInput()} if len(tc.spec.Input) > 1 { - inputs = append(inputs, colexec.NewZeroOp(nil)) + inputs = append(inputs, colexec.NewZeroOpNoInput()) } memMon := mon.MakeMonitor("MemoryMonitor", mon.MemoryResource, nil, nil, 0, math.MaxInt64, st) if success {