github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/sqle/setalgebra/intersection_test.go (about) 1 // Copyright 2020 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package setalgebra 16 17 import ( 18 "testing" 19 20 "github.com/stretchr/testify/assert" 21 "github.com/stretchr/testify/require" 22 23 "github.com/dolthub/dolt/go/store/hash" 24 "github.com/dolthub/dolt/go/store/types" 25 ) 26 27 func TestFiniteSetIntersection(t *testing.T) { 28 tests := []struct { 29 name string 30 setVals1 []types.Value 31 setVals2 []types.Value 32 expected Set 33 expectErr bool 34 }{ 35 { 36 "empty finite set", 37 []types.Value{}, 38 []types.Value{}, 39 EmptySet{}, 40 false, 41 }, 42 { 43 "non overlapping", 44 []types.Value{types.Int(1), types.Int(2)}, 45 []types.Value{types.Int(3), types.Int(4)}, 46 EmptySet{}, 47 false, 48 }, 49 { 50 "some overlapping", 51 []types.Value{types.Int(1), types.Int(2)}, 52 []types.Value{types.Int(2), types.Int(3)}, 53 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(2))), 54 false, 55 }, 56 } 57 58 for _, test := range tests { 59 t.Run(test.name, func(t *testing.T) { 60 fs1, err := NewFiniteSet(types.Format_Default, test.setVals1...) 61 require.NoError(t, err) 62 63 fs2, err := NewFiniteSet(types.Format_Default, test.setVals2...) 64 require.NoError(t, err) 65 66 res, err := finiteSetIntersection(fs1, fs2) 67 assertErr(t, test.expectErr, err) 68 69 assert.Equal(t, test.expected, res) 70 }) 71 } 72 } 73 74 func TestFiniteSetIntervalIntersection(t *testing.T) { 75 tests := []struct { 76 name string 77 setVals []types.Value 78 in Interval 79 expected Set 80 expectErr bool 81 }{ 82 { 83 "interval contains set", 84 []types.Value{types.Int(0), types.Int(5), types.Int(10)}, 85 Interval{ 86 types.Format_Default, 87 &IntervalEndpoint{types.Int(0), true}, 88 &IntervalEndpoint{types.Int(10), true}, 89 }, 90 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(0), types.Int(5), types.Int(10))), 91 false, 92 }, 93 { 94 "some of set outside interval", 95 []types.Value{types.Int(-5), types.Int(0), types.Int(5), types.Int(20)}, 96 Interval{ 97 types.Format_Default, 98 &IntervalEndpoint{types.Int(0), true}, 99 &IntervalEndpoint{types.Int(10), true}, 100 }, 101 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(0), types.Int(5))), 102 false, 103 }, 104 { 105 "open intervals", 106 []types.Value{types.Int(0), types.Int(5), types.Int(10)}, 107 Interval{ 108 types.Format_Default, 109 &IntervalEndpoint{types.Int(0), false}, 110 &IntervalEndpoint{types.Int(10), false}, 111 }, 112 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(5))), 113 false, 114 }, 115 { 116 "negative infinity", 117 []types.Value{types.Int(0), types.Int(5), types.Int(10)}, 118 Interval{ 119 types.Format_Default, 120 nil, 121 &IntervalEndpoint{types.Int(10), true}, 122 }, 123 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(0), types.Int(5), types.Int(10))), 124 false, 125 }, 126 { 127 "positive infinity", 128 []types.Value{types.Int(0), types.Int(5), types.Int(10)}, 129 Interval{ 130 types.Format_Default, 131 &IntervalEndpoint{types.Int(0), false}, 132 nil, 133 }, 134 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(5), types.Int(10))), 135 false, 136 }, 137 { 138 "negative to positive infinity", 139 []types.Value{types.Int(0), types.Int(5), types.Int(10)}, 140 Interval{ 141 types.Format_Default, 142 nil, 143 nil, 144 }, 145 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(0), types.Int(5), types.Int(10))), 146 false, 147 }, 148 } 149 150 for _, test := range tests { 151 t.Run(test.name, func(t *testing.T) { 152 fs, err := NewFiniteSet(types.Format_Default, test.setVals...) 153 require.NoError(t, err) 154 155 res, err := finiteSetIntervalIntersection(fs, test.in) 156 assert.NoError(t, err) 157 158 assert.Equal(t, test.expected, res) 159 }) 160 } 161 } 162 163 func TestFiniteSetCompositeSetIntersection(t *testing.T) { 164 tests := []struct { 165 name string 166 setVals []types.Value 167 cs CompositeSet 168 expected Set 169 expectErr bool 170 }{ 171 /*{ 172 "empty set", 173 []types.Value{}, 174 CompositeSet{ 175 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(20))), 176 []Interval{ 177 { 178 types.Format_Default, 179 &IntervalEndpoint{types.Int(0), true}, 180 &IntervalEndpoint{types.Int(10), true}, 181 }, 182 }, 183 }, 184 EmptySet{}, 185 false, 186 }, 187 { 188 "set with contained and uncontained vals", 189 []types.Value{types.Int(-10), types.Int(0), types.Int(10), types.Int(20), types.Int(30)}, 190 CompositeSet{ 191 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(20))), 192 []Interval{ 193 { 194 types.Format_Default, 195 &IntervalEndpoint{types.Int(0), true}, 196 &IntervalEndpoint{types.Int(10), true}, 197 }, 198 }, 199 }, 200 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(0), types.Int(10), types.Int(20))), 201 false, 202 },*/ 203 { 204 "composite set with multiple intervals", 205 []types.Value{types.Int(-10), types.Int(0), types.Int(10), types.Int(20), types.Int(30), types.Int(99), types.Int(100), types.Int(0x7FFFFFFFFFFFFFFF)}, 206 CompositeSet{ 207 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(20))), 208 []Interval{ 209 { 210 types.Format_Default, 211 &IntervalEndpoint{types.Int(0), true}, 212 &IntervalEndpoint{types.Int(10), true}, 213 }, 214 { 215 types.Format_Default, 216 &IntervalEndpoint{types.Int(100), true}, 217 nil, 218 }, 219 }, 220 }, 221 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(0), types.Int(10), types.Int(20), types.Int(100), types.Int(0x7FFFFFFFFFFFFFFF))), 222 false, 223 }, 224 } 225 226 for _, test := range tests { 227 t.Run(test.name, func(t *testing.T) { 228 fs, err := NewFiniteSet(types.Format_Default, test.setVals...) 229 require.NoError(t, err) 230 231 res, err := finiteSetCompositeSetIntersection(fs, test.cs) 232 assert.NoError(t, err) 233 234 assert.Equal(t, test.expected, res) 235 }) 236 } 237 } 238 239 func TestIntersectIntervalWithStartPoints(t *testing.T) { 240 tests := []struct { 241 name string 242 in Interval 243 in2 Interval 244 expected Set 245 expectErr bool 246 }{ 247 { 248 "No overlap", 249 Interval{ 250 types.Format_Default, 251 &IntervalEndpoint{types.Int(0), true}, 252 &IntervalEndpoint{types.Int(10), false}, 253 }, 254 Interval{ 255 types.Format_Default, 256 &IntervalEndpoint{types.Int(10), false}, 257 &IntervalEndpoint{types.Int(20), true}, 258 }, 259 EmptySet{}, 260 false, 261 }, 262 { 263 "overlap at endpoints", 264 Interval{ 265 types.Format_Default, 266 &IntervalEndpoint{types.Int(0), true}, 267 &IntervalEndpoint{types.Int(10), true}, 268 }, 269 Interval{ 270 types.Format_Default, 271 &IntervalEndpoint{types.Int(10), true}, 272 &IntervalEndpoint{types.Int(20), true}, 273 }, 274 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10))), 275 false, 276 }, 277 { 278 "1 fully enclosed in 2", 279 Interval{ 280 types.Format_Default, 281 &IntervalEndpoint{types.Int(5), true}, 282 &IntervalEndpoint{types.Int(15), false}, 283 }, 284 Interval{ 285 types.Format_Default, 286 &IntervalEndpoint{types.Int(0), true}, 287 &IntervalEndpoint{types.Int(20), true}, 288 }, 289 Interval{ 290 types.Format_Default, 291 &IntervalEndpoint{types.Int(5), true}, 292 &IntervalEndpoint{types.Int(15), false}, 293 }, 294 false, 295 }, 296 { 297 "2 fully enclosed 1", 298 Interval{ 299 types.Format_Default, 300 &IntervalEndpoint{types.Int(0), true}, 301 &IntervalEndpoint{types.Int(20), true}, 302 }, 303 Interval{ 304 types.Format_Default, 305 &IntervalEndpoint{types.Int(5), true}, 306 &IntervalEndpoint{types.Int(15), false}, 307 }, 308 Interval{ 309 types.Format_Default, 310 &IntervalEndpoint{types.Int(5), true}, 311 &IntervalEndpoint{types.Int(15), false}, 312 }, 313 false, 314 }, 315 { 316 "intersect open and closed endpoints", 317 Interval{ 318 types.Format_Default, 319 &IntervalEndpoint{types.Int(0), true}, 320 &IntervalEndpoint{types.Int(20), true}, 321 }, 322 Interval{ 323 types.Format_Default, 324 &IntervalEndpoint{types.Int(0), false}, 325 &IntervalEndpoint{types.Int(20), false}, 326 }, 327 Interval{ 328 types.Format_Default, 329 &IntervalEndpoint{types.Int(0), false}, 330 &IntervalEndpoint{types.Int(20), false}, 331 }, 332 false, 333 }, 334 { 335 "overlap with infinite interval", 336 Interval{ 337 types.Format_Default, 338 &IntervalEndpoint{types.Int(10), true}, 339 nil, 340 }, 341 Interval{ 342 types.Format_Default, 343 &IntervalEndpoint{types.Int(0), true}, 344 &IntervalEndpoint{types.Int(20), true}, 345 }, 346 Interval{ 347 types.Format_Default, 348 &IntervalEndpoint{types.Int(10), true}, 349 &IntervalEndpoint{types.Int(20), true}, 350 }, 351 false, 352 }, 353 } 354 355 for _, test := range tests { 356 t.Run(test.name, func(t *testing.T) { 357 res, err := intervalIntersection(test.in, test.in2) 358 assert.NoError(t, err) 359 360 assert.Equal(t, test.expected, res) 361 }) 362 } 363 } 364 365 func TestIntervalCompositeSetIntersection(t *testing.T) { 366 tests := []struct { 367 name string 368 in Interval 369 cs CompositeSet 370 expected Set 371 expectErr bool 372 }{ 373 { 374 "make universal set", 375 testInterv(&IntervalEndpoint{types.Int(0), true}, nil), 376 CompositeSet{ 377 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(20))), 378 []Interval{ 379 testInterv(nil, &IntervalEndpoint{types.Int(0), true}), 380 }, 381 }, 382 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(0), types.Int(10), types.Int(20))), 383 false, 384 }, 385 { 386 "multiple intervals one overlapping", 387 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}), 388 CompositeSet{ 389 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(30))), 390 []Interval{ 391 testInterv(nil, &IntervalEndpoint{types.Int(0), true}), 392 testInterv(&IntervalEndpoint{types.Int(15), true}, &IntervalEndpoint{types.Int(25), true}), 393 testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}), 394 }, 395 }, 396 CompositeSet{ 397 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(30))), 398 []Interval{ 399 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(25), true}), 400 }, 401 }, 402 false, 403 }, 404 405 { 406 "open interval intersection", 407 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}), 408 CompositeSet{ 409 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(25))), 410 []Interval{ 411 testInterv(&IntervalEndpoint{types.Int(0), true}, &IntervalEndpoint{types.Int(20), false}), 412 testInterv(&IntervalEndpoint{types.Int(30), false}, &IntervalEndpoint{types.Int(100), true}), 413 }, 414 }, 415 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(25))), 416 false, 417 }, 418 419 { 420 "single interval intersection result", 421 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}), 422 CompositeSet{ 423 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(35))), 424 []Interval{ 425 testInterv(&IntervalEndpoint{types.Int(0), true}, &IntervalEndpoint{types.Int(25), false}), 426 testInterv(&IntervalEndpoint{types.Int(30), false}, &IntervalEndpoint{types.Int(100), true}), 427 }, 428 }, 429 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(25), false}), 430 false, 431 }, 432 433 { 434 "empty intersection result", 435 testInterv(&IntervalEndpoint{types.Int(26), true}, &IntervalEndpoint{types.Int(29), true}), 436 CompositeSet{ 437 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(35))), 438 []Interval{ 439 testInterv(&IntervalEndpoint{types.Int(0), true}, &IntervalEndpoint{types.Int(25), false}), 440 testInterv(&IntervalEndpoint{types.Int(30), false}, &IntervalEndpoint{types.Int(100), true}), 441 }, 442 }, 443 EmptySet{}, 444 false, 445 }, 446 } 447 448 for _, test := range tests { 449 t.Run(test.name, func(t *testing.T) { 450 res, err := intervalCompositeSetIntersection(test.in, test.cs) 451 assertErr(t, test.expectErr, err) 452 453 assert.Equal(t, test.expected, res) 454 }) 455 } 456 } 457 458 func TestCompositeSetIntersection(t *testing.T) { 459 tests := []struct { 460 name string 461 cs1 CompositeSet 462 cs2 CompositeSet 463 expected Set 464 expectErr bool 465 }{ 466 { 467 "single point overlap with interval and finiteSet overlap", 468 CompositeSet{ 469 FiniteSet{make(map[hash.Hash]types.Value)}, 470 []Interval{testInterv(&IntervalEndpoint{types.Int(0), true}, nil)}, 471 }, 472 CompositeSet{ 473 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(20))), 474 []Interval{ 475 testInterv(nil, &IntervalEndpoint{types.Int(0), true}), 476 }, 477 }, 478 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(0), types.Int(10), types.Int(20))), 479 false, 480 }, 481 { 482 "multiple intervals one overlapping", 483 CompositeSet{ 484 FiniteSet{make(map[hash.Hash]types.Value)}, 485 []Interval{ 486 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}), 487 }, 488 }, 489 CompositeSet{ 490 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(30))), 491 []Interval{ 492 testInterv(nil, &IntervalEndpoint{types.Int(0), true}), 493 testInterv(&IntervalEndpoint{types.Int(15), true}, &IntervalEndpoint{types.Int(25), true}), 494 testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}), 495 }, 496 }, 497 CompositeSet{ 498 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(30))), 499 []Interval{ 500 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(25), true}), 501 }, 502 }, 503 false, 504 }, 505 506 { 507 "multiple intervals in multiple composite sets", 508 CompositeSet{ 509 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(15), types.Int(400))), 510 []Interval{ 511 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}), 512 testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}), 513 testInterv(&IntervalEndpoint{types.Int(200), true}, &IntervalEndpoint{types.Int(300), true}), 514 }, 515 }, 516 CompositeSet{ 517 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(1), types.Int(10), types.Int(30))), 518 []Interval{ 519 testInterv(nil, &IntervalEndpoint{types.Int(0), true}), 520 testInterv(&IntervalEndpoint{types.Int(15), true}, &IntervalEndpoint{types.Int(25), true}), 521 testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}), 522 }, 523 }, 524 CompositeSet{ 525 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(10), types.Int(15), types.Int(30))), 526 []Interval{ 527 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(25), true}), 528 testInterv(&IntervalEndpoint{types.Int(50), true}, &IntervalEndpoint{types.Int(100), true}), 529 }, 530 }, 531 false, 532 }, 533 534 { 535 "No overlap", 536 CompositeSet{ 537 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(-10))), 538 []Interval{ 539 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}), 540 }, 541 }, 542 CompositeSet{ 543 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(50))), 544 []Interval{ 545 testInterv(&IntervalEndpoint{types.Int(0), true}, &IntervalEndpoint{types.Int(10), false}), 546 }, 547 }, 548 EmptySet{}, 549 false, 550 }, 551 552 { 553 "Single interval result", 554 CompositeSet{ 555 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(-10))), 556 []Interval{ 557 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(30), true}), 558 }, 559 }, 560 CompositeSet{ 561 mustFiniteSet(NewFiniteSet(types.Format_Default, types.Int(50))), 562 []Interval{ 563 testInterv(&IntervalEndpoint{types.Int(0), true}, &IntervalEndpoint{types.Int(25), false}), 564 }, 565 }, 566 testInterv(&IntervalEndpoint{types.Int(20), true}, &IntervalEndpoint{types.Int(25), false}), 567 false, 568 }, 569 } 570 571 for _, test := range tests { 572 t.Run(test.name, func(t *testing.T) { 573 res, err := compositeIntersection(test.cs1, test.cs2) 574 assertErr(t, test.expectErr, err) 575 576 assert.Equal(t, test.expected, res) 577 }) 578 } 579 580 }