github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/selection_ops_test.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package colexec
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"math/rand"
    17  	"reflect"
    18  	"testing"
    19  
    20  	"github.com/cockroachdb/cockroach/pkg/col/coldata"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/colexecbase"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    24  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    25  	"github.com/cockroachdb/cockroach/pkg/util/timeutil/pgdate"
    26  )
    27  
    28  const (
    29  	selectivity     = .5
    30  	nullProbability = .1
    31  )
    32  
    33  func TestSelLTInt64Int64ConstOp(t *testing.T) {
    34  	defer leaktest.AfterTest(t)()
    35  	tups := tuples{{0}, {1}, {2}, {nil}}
    36  	runTests(t, []tuples{tups}, tuples{{0}, {1}}, orderedVerifier, func(input []colexecbase.Operator) (colexecbase.Operator, error) {
    37  		return &selLTInt64Int64ConstOp{
    38  			selConstOpBase: selConstOpBase{
    39  				OneInputNode: NewOneInputNode(input[0]),
    40  				colIdx:       0,
    41  			},
    42  			constArg: 2,
    43  		}, nil
    44  	})
    45  }
    46  
    47  func TestSelLTInt64Int64(t *testing.T) {
    48  	defer leaktest.AfterTest(t)()
    49  	tups := tuples{
    50  		{0, 0},
    51  		{0, 1},
    52  		{1, 0},
    53  		{1, 1},
    54  		{nil, 1},
    55  		{-1, nil},
    56  		{nil, nil},
    57  	}
    58  	runTests(t, []tuples{tups}, tuples{{0, 1}}, orderedVerifier, func(input []colexecbase.Operator) (colexecbase.Operator, error) {
    59  		return &selLTInt64Int64Op{
    60  			selOpBase: selOpBase{
    61  				OneInputNode: NewOneInputNode(input[0]),
    62  				col1Idx:      0,
    63  				col2Idx:      1,
    64  			},
    65  		}, nil
    66  	})
    67  }
    68  
    69  func TestGetSelectionConstOperator(t *testing.T) {
    70  	defer leaktest.AfterTest(t)()
    71  	cmpOp := tree.LT
    72  	var input colexecbase.Operator
    73  	colIdx := 3
    74  	constVal := int64(31)
    75  	constArg := tree.NewDDate(pgdate.MakeCompatibleDateFromDisk(constVal))
    76  	op, err := GetSelectionConstOperator(types.Date, types.Date, cmpOp, input, colIdx, constArg, overloadHelper{})
    77  	if err != nil {
    78  		t.Error(err)
    79  	}
    80  	expected := &selLTInt64Int64ConstOp{
    81  		selConstOpBase: selConstOpBase{
    82  			OneInputNode: NewOneInputNode(input),
    83  			colIdx:       colIdx,
    84  		},
    85  		constArg: constVal,
    86  	}
    87  	if !reflect.DeepEqual(op, expected) {
    88  		t.Errorf("got %+v, expected %+v", op, expected)
    89  	}
    90  }
    91  
    92  func TestGetSelectionConstMixedTypeOperator(t *testing.T) {
    93  	defer leaktest.AfterTest(t)()
    94  	cmpOp := tree.LT
    95  	var input colexecbase.Operator
    96  	colIdx := 3
    97  	constVal := int16(31)
    98  	constArg := tree.NewDInt(tree.DInt(constVal))
    99  	op, err := GetSelectionConstOperator(types.Int, types.Int2, cmpOp, input, colIdx, constArg, overloadHelper{})
   100  	if err != nil {
   101  		t.Error(err)
   102  	}
   103  	expected := &selLTInt64Int16ConstOp{
   104  		selConstOpBase: selConstOpBase{
   105  			OneInputNode: NewOneInputNode(input),
   106  			colIdx:       colIdx,
   107  		},
   108  		constArg: constVal,
   109  	}
   110  	if !reflect.DeepEqual(op, expected) {
   111  		t.Errorf("got %+v, expected %+v", op, expected)
   112  	}
   113  }
   114  
   115  func TestGetSelectionOperator(t *testing.T) {
   116  	defer leaktest.AfterTest(t)()
   117  	ct := types.Int2
   118  	cmpOp := tree.GE
   119  	var input colexecbase.Operator
   120  	col1Idx := 5
   121  	col2Idx := 7
   122  	op, err := GetSelectionOperator(ct, ct, cmpOp, input, col1Idx, col2Idx, overloadHelper{})
   123  	if err != nil {
   124  		t.Error(err)
   125  	}
   126  	expected := &selGEInt16Int16Op{
   127  		selOpBase: selOpBase{
   128  			OneInputNode: NewOneInputNode(input),
   129  			col1Idx:      col1Idx,
   130  			col2Idx:      col2Idx,
   131  		},
   132  	}
   133  	if !reflect.DeepEqual(op, expected) {
   134  		t.Errorf("got %+v, expected %+v", op, expected)
   135  	}
   136  }
   137  
   138  func benchmarkSelLTInt64Int64ConstOp(b *testing.B, useSelectionVector bool, hasNulls bool) {
   139  	ctx := context.Background()
   140  
   141  	typs := []*types.T{types.Int}
   142  	batch := testAllocator.NewMemBatch(typs)
   143  	col := batch.ColVec(0).Int64()
   144  	for i := 0; i < coldata.BatchSize(); i++ {
   145  		if float64(i) < float64(coldata.BatchSize())*selectivity {
   146  			col[i] = -1
   147  		} else {
   148  			col[i] = 1
   149  		}
   150  	}
   151  	if hasNulls {
   152  		for i := 0; i < coldata.BatchSize(); i++ {
   153  			if rand.Float64() < nullProbability {
   154  				batch.ColVec(0).Nulls().SetNull(i)
   155  			}
   156  		}
   157  	}
   158  	batch.SetLength(coldata.BatchSize())
   159  	if useSelectionVector {
   160  		batch.SetSelection(true)
   161  		sel := batch.Selection()
   162  		for i := 0; i < coldata.BatchSize(); i++ {
   163  			sel[i] = i
   164  		}
   165  	}
   166  	source := colexecbase.NewRepeatableBatchSource(testAllocator, batch, typs)
   167  	source.Init()
   168  
   169  	plusOp := &selLTInt64Int64ConstOp{
   170  		selConstOpBase: selConstOpBase{
   171  			OneInputNode: NewOneInputNode(source),
   172  			colIdx:       0,
   173  		},
   174  		constArg: 0,
   175  	}
   176  	plusOp.Init()
   177  
   178  	b.SetBytes(int64(8 * coldata.BatchSize()))
   179  	b.ResetTimer()
   180  	for i := 0; i < b.N; i++ {
   181  		plusOp.Next(ctx)
   182  	}
   183  }
   184  
   185  func BenchmarkSelLTInt64Int64ConstOp(b *testing.B) {
   186  	for _, useSel := range []bool{true, false} {
   187  		for _, hasNulls := range []bool{true, false} {
   188  			b.Run(fmt.Sprintf("useSel=%t,hasNulls=%t", useSel, hasNulls), func(b *testing.B) {
   189  				benchmarkSelLTInt64Int64ConstOp(b, useSel, hasNulls)
   190  			})
   191  		}
   192  	}
   193  }
   194  
   195  func benchmarkSelLTInt64Int64Op(b *testing.B, useSelectionVector bool, hasNulls bool) {
   196  	ctx := context.Background()
   197  
   198  	typs := []*types.T{types.Int, types.Int}
   199  	batch := testAllocator.NewMemBatch(typs)
   200  	col1 := batch.ColVec(0).Int64()
   201  	col2 := batch.ColVec(1).Int64()
   202  	for i := 0; i < coldata.BatchSize(); i++ {
   203  		if float64(i) < float64(coldata.BatchSize())*selectivity {
   204  			col1[i], col2[i] = -1, 1
   205  		} else {
   206  			col1[i], col2[i] = 1, -1
   207  		}
   208  	}
   209  	if hasNulls {
   210  		for i := 0; i < coldata.BatchSize(); i++ {
   211  			if rand.Float64() < nullProbability {
   212  				batch.ColVec(0).Nulls().SetNull(i)
   213  			}
   214  			if rand.Float64() < nullProbability {
   215  				batch.ColVec(1).Nulls().SetNull(i)
   216  			}
   217  		}
   218  	}
   219  	batch.SetLength(coldata.BatchSize())
   220  	if useSelectionVector {
   221  		batch.SetSelection(true)
   222  		sel := batch.Selection()
   223  		for i := 0; i < coldata.BatchSize(); i++ {
   224  			sel[i] = i
   225  		}
   226  	}
   227  	source := colexecbase.NewRepeatableBatchSource(testAllocator, batch, typs)
   228  	source.Init()
   229  
   230  	plusOp := &selLTInt64Int64Op{
   231  		selOpBase: selOpBase{
   232  			OneInputNode: NewOneInputNode(source),
   233  			col1Idx:      0,
   234  			col2Idx:      1,
   235  		},
   236  	}
   237  	plusOp.Init()
   238  
   239  	b.SetBytes(int64(8 * coldata.BatchSize() * 2))
   240  	b.ResetTimer()
   241  	for i := 0; i < b.N; i++ {
   242  		plusOp.Next(ctx)
   243  	}
   244  }
   245  
   246  func BenchmarkSelLTInt64Int64Op(b *testing.B) {
   247  	for _, useSel := range []bool{true, false} {
   248  		for _, hasNulls := range []bool{true, false} {
   249  			b.Run(fmt.Sprintf("useSel=%t,hasNulls=%t", useSel, hasNulls), func(b *testing.B) {
   250  				benchmarkSelLTInt64Int64Op(b, useSel, hasNulls)
   251  			})
   252  		}
   253  	}
   254  }