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 }