github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/constraint/spans_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  // This file implements data structures used by index constraints generation.
    12  
    13  package constraint
    14  
    15  import (
    16  	"testing"
    17  
    18  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    19  	"github.com/cockroachdb/cockroach/pkg/util/randutil"
    20  )
    21  
    22  func TestSpans(t *testing.T) {
    23  	var s Spans
    24  	check := func(exp string) {
    25  		if actual := s.String(); actual != exp {
    26  			t.Errorf("expected %s, got %s", exp, actual)
    27  		}
    28  	}
    29  	add := func(x int) {
    30  		k := MakeKey(tree.NewDInt(tree.DInt(x)))
    31  		var span Span
    32  		span.Init(k, IncludeBoundary, k, IncludeBoundary)
    33  		s.Append(&span)
    34  	}
    35  	check("")
    36  	add(1)
    37  	check("[/1 - /1]")
    38  	add(2)
    39  	check("[/1 - /1] [/2 - /2]")
    40  	add(3)
    41  	check("[/1 - /1] [/2 - /2] [/3 - /3]")
    42  
    43  	// Verify that Alloc doesn't lose spans.
    44  	s.Alloc(10)
    45  	check("[/1 - /1] [/2 - /2] [/3 - /3]")
    46  
    47  	s.Truncate(2)
    48  	check("[/1 - /1] [/2 - /2]")
    49  	s.Truncate(1)
    50  	check("[/1 - /1]")
    51  	s.Truncate(0)
    52  	check("")
    53  }
    54  
    55  func TestSpansSortAndMerge(t *testing.T) {
    56  	keyCtx := testKeyContext(1)
    57  	evalCtx := keyCtx.EvalCtx
    58  
    59  	// To test SortAndMerge, we note that the result can also be obtained by
    60  	// creating a constraint per span and calculating the union. We generate
    61  	// random cases and cross-check.
    62  	for testIdx := 0; testIdx < 100; testIdx++ {
    63  		rng, _ := randutil.NewPseudoRand()
    64  		n := 1 + rng.Intn(10)
    65  		var spans Spans
    66  		for i := 0; i < n; i++ {
    67  			x, y := rng.Intn(20), rng.Intn(20)
    68  			if x > y {
    69  				x, y = y, x
    70  			}
    71  			xk, yk := EmptyKey, EmptyKey
    72  			if x > 0 {
    73  				xk = MakeKey(tree.NewDInt(tree.DInt(x)))
    74  			}
    75  			if y > 0 {
    76  				yk = MakeKey(tree.NewDInt(tree.DInt(y)))
    77  			}
    78  
    79  			xb, yb := IncludeBoundary, IncludeBoundary
    80  			if x != 0 && x != y && rng.Intn(2) == 0 {
    81  				xb = ExcludeBoundary
    82  			}
    83  			if y != 0 && x != y && rng.Intn(2) == 0 {
    84  				yb = ExcludeBoundary
    85  			}
    86  			var sp Span
    87  			if x != 0 || y != 0 {
    88  				sp.Init(xk, xb, yk, yb)
    89  			}
    90  			spans.Append(&sp)
    91  		}
    92  		origStr := spans.String()
    93  
    94  		// Calculate via constraints.
    95  		var c Constraint
    96  		c.InitSingleSpan(keyCtx, spans.Get(0))
    97  		for i := 1; i < spans.Count(); i++ {
    98  			var d Constraint
    99  			d.InitSingleSpan(keyCtx, spans.Get(i))
   100  			c.UnionWith(evalCtx, &d)
   101  		}
   102  		expected := c.Spans.String()
   103  
   104  		spans.SortAndMerge(keyCtx)
   105  		if actual := spans.String(); actual != expected {
   106  			t.Fatalf("%s : expected  %s  got  %s", origStr, expected, actual)
   107  		}
   108  	}
   109  }