github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/rowexec/set_op_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 rowexec
    12  
    13  import (
    14  	"github.com/cockroachdb/cockroach/pkg/sql/execinfrapb"
    15  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    16  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    18  	"github.com/cockroachdb/cockroach/pkg/util/encoding"
    19  )
    20  
    21  type setOpTestCase struct {
    22  	setOpType   sqlbase.JoinType
    23  	columnTypes []*types.T
    24  	ordering    sqlbase.ColumnOrdering
    25  	leftInput   sqlbase.EncDatumRows
    26  	rightInput  sqlbase.EncDatumRows
    27  	expected    sqlbase.EncDatumRows
    28  }
    29  
    30  func setOpTestCaseToMergeJoinerTestCase(tc setOpTestCase) mergeJoinerTestCase {
    31  	spec := execinfrapb.MergeJoinerSpec{Type: tc.setOpType, NullEquality: true}
    32  	var ordering sqlbase.ColumnOrdering
    33  	if tc.ordering != nil {
    34  		ordering = tc.ordering
    35  	} else {
    36  		ordering = make(sqlbase.ColumnOrdering, 0, len(tc.columnTypes))
    37  		for i := range tc.columnTypes {
    38  			ordering = append(ordering, sqlbase.ColumnOrderInfo{ColIdx: i, Direction: encoding.Ascending})
    39  		}
    40  	}
    41  	outCols := make([]uint32, 0, len(tc.columnTypes))
    42  	for i := range tc.columnTypes {
    43  		outCols = append(outCols, uint32(i))
    44  	}
    45  	spec.LeftOrdering = execinfrapb.ConvertToSpecOrdering(ordering)
    46  	spec.RightOrdering = execinfrapb.ConvertToSpecOrdering(ordering)
    47  
    48  	return mergeJoinerTestCase{
    49  		spec:          spec,
    50  		outCols:       outCols,
    51  		leftTypes:     tc.columnTypes,
    52  		leftInput:     tc.leftInput,
    53  		rightTypes:    tc.columnTypes,
    54  		rightInput:    tc.rightInput,
    55  		expectedTypes: tc.columnTypes,
    56  		expected:      tc.expected,
    57  	}
    58  }
    59  
    60  func setOpTestCaseToJoinerTestCase(tc setOpTestCase) joinerTestCase {
    61  	outCols := make([]uint32, 0, len(tc.columnTypes))
    62  	for i := range tc.columnTypes {
    63  		outCols = append(outCols, uint32(i))
    64  	}
    65  
    66  	return joinerTestCase{
    67  		leftEqCols:  outCols,
    68  		rightEqCols: outCols,
    69  		joinType:    tc.setOpType,
    70  		outCols:     outCols,
    71  		leftTypes:   tc.columnTypes,
    72  		leftInput:   tc.leftInput,
    73  		rightTypes:  tc.columnTypes,
    74  		rightInput:  tc.rightInput,
    75  		expected:    tc.expected,
    76  	}
    77  }
    78  
    79  func intersectAllTestCases() []setOpTestCase {
    80  	null := sqlbase.EncDatum{Datum: tree.DNull}
    81  	var v = [10]sqlbase.EncDatum{}
    82  	for i := range v {
    83  		v[i] = sqlbase.DatumToEncDatum(types.Int, tree.NewDInt(tree.DInt(i)))
    84  	}
    85  
    86  	return []setOpTestCase{
    87  		{
    88  			// Check that INTERSECT ALL only returns rows that are in both the left
    89  			// and right side.
    90  			setOpType:   sqlbase.IntersectAllJoin,
    91  			columnTypes: sqlbase.TwoIntCols,
    92  			leftInput: sqlbase.EncDatumRows{
    93  				{null, null},
    94  				{null, null},
    95  				{null, v[0]},
    96  				{null, v[1]},
    97  				{null, v[1]},
    98  				{v[0], v[0]},
    99  				{v[0], v[0]},
   100  				{v[0], v[1]},
   101  				{v[0], v[3]},
   102  				{v[1], null},
   103  				{v[1], null},
   104  				{v[5], v[0]},
   105  				{v[5], v[1]},
   106  			},
   107  			rightInput: sqlbase.EncDatumRows{
   108  				{null, null},
   109  				{null, v[1]},
   110  				{null, v[1]},
   111  				{null, v[1]},
   112  				{null, v[2]},
   113  				{v[0], v[0]},
   114  				{v[0], v[0]},
   115  				{v[0], v[1]},
   116  				{v[1], null},
   117  				{v[5], v[0]},
   118  				{v[5], v[1]},
   119  			},
   120  			expected: sqlbase.EncDatumRows{
   121  				{null, null},
   122  				{null, v[1]},
   123  				{null, v[1]},
   124  				{v[0], v[0]},
   125  				{v[0], v[0]},
   126  				{v[0], v[1]},
   127  				{v[1], null},
   128  				{v[5], v[0]},
   129  				{v[5], v[1]},
   130  			},
   131  		},
   132  		{
   133  			// Check that INTERSECT ALL returns the correct number of duplicates when
   134  			// the left side contains more duplicates of a row than the right side.
   135  			setOpType:   sqlbase.IntersectAllJoin,
   136  			columnTypes: sqlbase.TwoIntCols,
   137  			leftInput: sqlbase.EncDatumRows{
   138  				{null, null},
   139  				{null, null},
   140  				{null, v[0]},
   141  				{null, v[0]},
   142  				{null, v[0]},
   143  				{v[0], v[0]},
   144  				{v[0], v[0]},
   145  				{v[0], v[0]},
   146  				{v[0], v[1]},
   147  				{v[0], v[3]},
   148  				{v[5], v[0]},
   149  				{v[5], v[1]},
   150  			},
   151  			rightInput: sqlbase.EncDatumRows{
   152  				{null, null},
   153  				{null, v[0]},
   154  				{v[0], v[0]},
   155  				{v[0], v[0]},
   156  				{v[0], v[1]},
   157  				{v[5], v[0]},
   158  				{v[5], v[1]},
   159  			},
   160  			expected: sqlbase.EncDatumRows{
   161  				{null, null},
   162  				{null, v[0]},
   163  				{v[0], v[0]},
   164  				{v[0], v[0]},
   165  				{v[0], v[1]},
   166  				{v[5], v[0]},
   167  				{v[5], v[1]},
   168  			},
   169  		},
   170  		{
   171  			// Check that INTERSECT ALL returns the correct number of duplicates when
   172  			// the right side contains more duplicates of a row than the left side.
   173  			setOpType:   sqlbase.IntersectAllJoin,
   174  			columnTypes: sqlbase.TwoIntCols,
   175  			leftInput: sqlbase.EncDatumRows{
   176  				{null, null},
   177  				{null, v[0]},
   178  				{v[0], v[0]},
   179  				{v[0], v[0]},
   180  				{v[0], v[1]},
   181  				{v[0], v[3]},
   182  				{v[5], v[0]},
   183  				{v[5], v[1]},
   184  			},
   185  			rightInput: sqlbase.EncDatumRows{
   186  				{null, null},
   187  				{null, null},
   188  				{null, v[0]},
   189  				{null, v[0]},
   190  				{null, v[0]},
   191  				{v[0], v[0]},
   192  				{v[0], v[0]},
   193  				{v[0], v[0]},
   194  				{v[0], v[1]},
   195  				{v[0], v[1]},
   196  				{v[5], v[0]},
   197  				{v[5], v[1]},
   198  			},
   199  			expected: sqlbase.EncDatumRows{
   200  				{null, null},
   201  				{null, v[0]},
   202  				{v[0], v[0]},
   203  				{v[0], v[0]},
   204  				{v[0], v[1]},
   205  				{v[5], v[0]},
   206  				{v[5], v[1]},
   207  			},
   208  		},
   209  	}
   210  }
   211  
   212  func exceptAllTestCases() []setOpTestCase {
   213  	null := sqlbase.EncDatum{Datum: tree.DNull}
   214  	var v = [10]sqlbase.EncDatum{}
   215  	for i := range v {
   216  		v[i] = sqlbase.DatumToEncDatum(types.Int, tree.NewDInt(tree.DInt(i)))
   217  	}
   218  
   219  	return []setOpTestCase{
   220  		{
   221  			// Check that EXCEPT ALL only returns rows that are on the left side
   222  			// but not the right side.
   223  			setOpType:   sqlbase.ExceptAllJoin,
   224  			columnTypes: sqlbase.TwoIntCols,
   225  			leftInput: sqlbase.EncDatumRows{
   226  				{null, null},
   227  				{null, null},
   228  				{null, v[0]},
   229  				{null, v[1]},
   230  				{null, v[1]},
   231  				{v[0], v[0]},
   232  				{v[0], v[0]},
   233  				{v[0], v[1]},
   234  				{v[0], v[3]},
   235  				{v[1], null},
   236  				{v[1], null},
   237  				{v[5], v[0]},
   238  				{v[5], v[1]},
   239  			},
   240  			rightInput: sqlbase.EncDatumRows{
   241  				{null, null},
   242  				{null, v[1]},
   243  				{null, v[1]},
   244  				{null, v[1]},
   245  				{null, v[2]},
   246  				{v[0], v[0]},
   247  				{v[0], v[0]},
   248  				{v[0], v[1]},
   249  				{v[1], null},
   250  				{v[5], v[0]},
   251  				{v[5], v[1]},
   252  			},
   253  			expected: sqlbase.EncDatumRows{
   254  				{null, null},
   255  				{null, v[0]},
   256  				{v[0], v[3]},
   257  				{v[1], null},
   258  			},
   259  		},
   260  		{
   261  			// Check that EXCEPT ALL returns the correct number of duplicates when
   262  			// the left side contains more duplicates of a row than the right side.
   263  			setOpType:   sqlbase.ExceptAllJoin,
   264  			columnTypes: sqlbase.TwoIntCols,
   265  			leftInput: sqlbase.EncDatumRows{
   266  				{null, null},
   267  				{null, null},
   268  				{null, v[0]},
   269  				{null, v[0]},
   270  				{null, v[0]},
   271  				{v[0], v[0]},
   272  				{v[0], v[0]},
   273  				{v[0], v[0]},
   274  				{v[0], v[1]},
   275  				{v[0], v[3]},
   276  				{v[5], v[0]},
   277  				{v[5], v[1]},
   278  			},
   279  			rightInput: sqlbase.EncDatumRows{
   280  				{null, null},
   281  				{null, v[0]},
   282  				{v[0], v[0]},
   283  				{v[0], v[0]},
   284  				{v[0], v[1]},
   285  				{v[5], v[0]},
   286  				{v[5], v[1]},
   287  			},
   288  			expected: sqlbase.EncDatumRows{
   289  				{null, null},
   290  				{null, v[0]},
   291  				{null, v[0]},
   292  				{v[0], v[0]},
   293  				{v[0], v[3]},
   294  			},
   295  		},
   296  		{
   297  			// Check that EXCEPT ALL returns the correct number of duplicates when
   298  			// the right side contains more duplicates of a row than the left side.
   299  			setOpType:   sqlbase.ExceptAllJoin,
   300  			columnTypes: sqlbase.TwoIntCols,
   301  			leftInput: sqlbase.EncDatumRows{
   302  				{null, null},
   303  				{null, v[0]},
   304  				{v[0], v[0]},
   305  				{v[0], v[0]},
   306  				{v[0], v[1]},
   307  				{v[0], v[3]},
   308  				{v[5], v[0]},
   309  				{v[5], v[1]},
   310  			},
   311  			rightInput: sqlbase.EncDatumRows{
   312  				{null, null},
   313  				{null, null},
   314  				{null, v[0]},
   315  				{null, v[0]},
   316  				{null, v[0]},
   317  				{v[0], v[0]},
   318  				{v[0], v[0]},
   319  				{v[0], v[0]},
   320  				{v[0], v[1]},
   321  				{v[0], v[1]},
   322  				{v[5], v[0]},
   323  				{v[5], v[1]},
   324  			},
   325  			expected: sqlbase.EncDatumRows{
   326  				{v[0], v[3]},
   327  			},
   328  		},
   329  		{
   330  			// Check that EXCEPT ALL handles mixed ordering correctly.
   331  			setOpType:   sqlbase.ExceptAllJoin,
   332  			columnTypes: sqlbase.TwoIntCols,
   333  			ordering: sqlbase.ColumnOrdering{
   334  				{ColIdx: 0, Direction: encoding.Descending},
   335  				{ColIdx: 1, Direction: encoding.Ascending},
   336  			},
   337  			leftInput: sqlbase.EncDatumRows{
   338  				{v[4], null},
   339  				{v[4], v[1]},
   340  				{v[1], null},
   341  				{v[1], v[2]},
   342  				{v[0], v[2]},
   343  				{v[0], v[3]},
   344  				{null, v[1]},
   345  				{null, v[2]},
   346  				{null, v[2]},
   347  				{null, v[3]},
   348  			},
   349  			rightInput: sqlbase.EncDatumRows{
   350  				{v[3], v[2]},
   351  				{v[2], v[1]},
   352  				{v[2], v[2]},
   353  				{v[2], v[3]},
   354  				{v[1], null},
   355  				{v[1], v[1]},
   356  				{v[1], v[1]},
   357  				{v[0], v[1]},
   358  				{v[0], v[2]},
   359  				{null, v[2]},
   360  			},
   361  			expected: sqlbase.EncDatumRows{
   362  				{v[4], null},
   363  				{v[4], v[1]},
   364  				{v[1], v[2]},
   365  				{v[0], v[3]},
   366  				{null, v[1]},
   367  				{null, v[2]},
   368  				{null, v[3]},
   369  			},
   370  		},
   371  	}
   372  }