github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/constraint/key_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  	"fmt"
    17  	"math"
    18  	"testing"
    19  
    20  	"github.com/cockroachdb/cockroach/pkg/settings/cluster"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    23  )
    24  
    25  func TestKey(t *testing.T) {
    26  	testKey(t, EmptyKey, "")
    27  
    28  	k := MakeKey(tree.NewDInt(1))
    29  	testKey(t, k, "/1")
    30  
    31  	k = MakeCompositeKey(tree.NewDInt(2))
    32  	testKey(t, k, "/2")
    33  
    34  	k = MakeCompositeKey(tree.NewDString("foo"), tree.NewDInt(3))
    35  	testKey(t, k, "/'foo'/3")
    36  }
    37  
    38  func TestKeyCompare(t *testing.T) {
    39  	keyCtx := testKeyContext(1, 2)
    40  
    41  	test := func(k, l Key, kExt, lExt KeyExtension, expected int) {
    42  		t.Helper()
    43  		if actual := k.Compare(keyCtx, l, kExt, lExt); actual != expected {
    44  			t.Errorf("k: %s, l %s, expected: %d, actual: %d", k, l, expected, actual)
    45  		} else if actual := l.Compare(keyCtx, k, lExt, kExt); actual != -expected {
    46  			t.Errorf("l: %s, k %s, expected: %d, actual: %d", l, k, -expected, actual)
    47  		}
    48  	}
    49  
    50  	key0 := MakeKey(tree.NewDInt(0))
    51  	key1 := MakeKey(tree.NewDInt(1))
    52  	key01 := MakeCompositeKey(tree.NewDInt(0), tree.NewDInt(1))
    53  	keyNull := MakeKey(tree.DNull)
    54  
    55  	test(EmptyKey, keyNull, ExtendLow, ExtendLow, -1)
    56  	test(EmptyKey, keyNull, ExtendLow, ExtendHigh, -1)
    57  	test(EmptyKey, keyNull, ExtendHigh, ExtendLow, 1)
    58  	test(EmptyKey, keyNull, ExtendHigh, ExtendHigh, 1)
    59  
    60  	test(key0, key0, ExtendLow, ExtendLow, 0)
    61  	test(key0, key0, ExtendLow, ExtendHigh, -1)
    62  	test(key0, key0, ExtendHigh, ExtendLow, 1)
    63  	test(key0, key0, ExtendHigh, ExtendHigh, 0)
    64  
    65  	test(key0, key1, ExtendLow, ExtendLow, -1)
    66  	test(key0, key1, ExtendLow, ExtendHigh, -1)
    67  	test(key0, key1, ExtendHigh, ExtendLow, -1)
    68  	test(key0, key1, ExtendHigh, ExtendHigh, -1)
    69  
    70  	test(key01, key0, ExtendLow, ExtendLow, 1)
    71  	test(key01, key0, ExtendLow, ExtendHigh, -1)
    72  	test(key01, key0, ExtendHigh, ExtendLow, 1)
    73  	test(key01, key0, ExtendHigh, ExtendHigh, -1)
    74  
    75  	test(keyNull, key0, ExtendHigh, ExtendLow, -1)
    76  
    77  	// Invert the direction of the first column.
    78  	keyCtx = testKeyContext(-1, 2)
    79  
    80  	test(EmptyKey, keyNull, ExtendLow, ExtendLow, -1)
    81  	test(EmptyKey, keyNull, ExtendLow, ExtendHigh, -1)
    82  	test(EmptyKey, keyNull, ExtendHigh, ExtendLow, 1)
    83  	test(EmptyKey, keyNull, ExtendHigh, ExtendHigh, 1)
    84  
    85  	test(key0, key0, ExtendLow, ExtendLow, 0)
    86  	test(key0, key0, ExtendLow, ExtendHigh, -1)
    87  	test(key0, key0, ExtendHigh, ExtendLow, 1)
    88  	test(key0, key0, ExtendHigh, ExtendHigh, 0)
    89  
    90  	test(key0, key1, ExtendLow, ExtendLow, 1)
    91  	test(key0, key1, ExtendLow, ExtendHigh, 1)
    92  	test(key0, key1, ExtendHigh, ExtendLow, 1)
    93  	test(key0, key1, ExtendHigh, ExtendHigh, 1)
    94  
    95  	test(key01, key0, ExtendLow, ExtendLow, 1)
    96  	test(key01, key0, ExtendLow, ExtendHigh, -1)
    97  	test(key01, key0, ExtendHigh, ExtendLow, 1)
    98  	test(key01, key0, ExtendHigh, ExtendHigh, -1)
    99  
   100  	test(keyNull, key0, ExtendHigh, ExtendLow, 1)
   101  }
   102  
   103  func TestKeyConcat(t *testing.T) {
   104  	k := EmptyKey
   105  
   106  	// Empty + empty.
   107  	k = k.Concat(EmptyKey)
   108  	testKey(t, k, "")
   109  
   110  	// Empty + single value.
   111  	k = k.Concat(MakeKey(tree.NewDInt(1)))
   112  	testKey(t, k, "/1")
   113  
   114  	// Single value + empty.
   115  	k = k.Concat(EmptyKey)
   116  	testKey(t, k, "/1")
   117  
   118  	// Single value + single value.
   119  	k = k.Concat(MakeKey(tree.NewDInt(2)))
   120  	testKey(t, k, "/1/2")
   121  
   122  	// Multiple values + empty.
   123  	k = k.Concat(EmptyKey)
   124  	testKey(t, k, "/1/2")
   125  
   126  	// Multiple values + single value.
   127  	k = k.Concat(MakeKey(tree.NewDInt(3)))
   128  	testKey(t, k, "/1/2/3")
   129  
   130  	// Multiple values + multiple values.
   131  	k = k.Concat(MakeCompositeKey(tree.NewDString("bar"), tree.DBoolTrue))
   132  	testKey(t, k, "/1/2/3/'bar'/true")
   133  }
   134  
   135  func TestKeyNextPrev(t *testing.T) {
   136  	kcAscAsc := testKeyContext(1, 2)
   137  	kcDesc := testKeyContext(-1)
   138  	kcAscDesc := testKeyContext(1, -2)
   139  
   140  	testCases := []struct {
   141  		key     Key
   142  		keyCtx  *KeyContext
   143  		expNext string
   144  		expPrev string
   145  	}{
   146  		{ // 0
   147  			key:     MakeKey(tree.NewDInt(1)),
   148  			keyCtx:  kcAscAsc,
   149  			expNext: "/2",
   150  			expPrev: "/0",
   151  		},
   152  		{ // 1
   153  			key:     MakeKey(tree.NewDInt(math.MaxInt64)),
   154  			keyCtx:  kcAscAsc,
   155  			expNext: "FAIL",
   156  			expPrev: "/9223372036854775806",
   157  		},
   158  		{ // 2
   159  			key:     MakeKey(tree.NewDInt(math.MinInt64)),
   160  			keyCtx:  kcAscAsc,
   161  			expNext: "/-9223372036854775807",
   162  			expPrev: "FAIL",
   163  		},
   164  		{ // 3
   165  			key:     MakeCompositeKey(tree.NewDInt(1), tree.NewDInt(2)),
   166  			keyCtx:  kcAscAsc,
   167  			expNext: "/1/3",
   168  			expPrev: "/1/1",
   169  		},
   170  		{ // 4
   171  			key:     MakeCompositeKey(tree.NewDInt(1), tree.DBoolFalse),
   172  			keyCtx:  kcAscAsc,
   173  			expNext: "/1/true",
   174  			expPrev: "FAIL",
   175  		},
   176  		{ // 5
   177  			key:     MakeCompositeKey(tree.NewDInt(1), tree.DBoolTrue),
   178  			keyCtx:  kcAscAsc,
   179  			expNext: "FAIL",
   180  			expPrev: "/1/false",
   181  		},
   182  		{ // 6
   183  			key:     MakeCompositeKey(tree.NewDInt(1), tree.NewDString("foo")),
   184  			keyCtx:  kcAscAsc,
   185  			expNext: "/1/e'foo\\x00'",
   186  			expPrev: "FAIL",
   187  		},
   188  		{ // 7
   189  			key:     MakeCompositeKey(tree.NewDInt(1)),
   190  			keyCtx:  kcDesc,
   191  			expNext: "/0",
   192  			expPrev: "/2",
   193  		},
   194  		{ // 8
   195  			key:     MakeCompositeKey(tree.NewDInt(1), tree.NewDInt(2)),
   196  			keyCtx:  kcAscDesc,
   197  			expNext: "/1/1",
   198  			expPrev: "/1/3",
   199  		},
   200  	}
   201  
   202  	for i, tc := range testCases {
   203  		t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
   204  			toStr := func(k Key, ok bool) string {
   205  				if !ok {
   206  					return "FAIL"
   207  				}
   208  				return k.String()
   209  			}
   210  
   211  			key, ok := tc.key.Next(tc.keyCtx)
   212  			if res := toStr(key, ok); res != tc.expNext {
   213  				t.Errorf("Next(%s) = %s, expected %s", tc.key, res, tc.expNext)
   214  			}
   215  			key, ok = tc.key.Prev(tc.keyCtx)
   216  			if res := toStr(key, ok); res != tc.expPrev {
   217  				t.Errorf("Prev(%s) = %s, expected %s", tc.key, res, tc.expPrev)
   218  			}
   219  		})
   220  	}
   221  
   222  }
   223  
   224  func testKey(t *testing.T, k Key, expected string) {
   225  	t.Helper()
   226  	if k.String() != expected {
   227  		t.Errorf("expected: %s, actual: %s", expected, k.String())
   228  	}
   229  }
   230  
   231  func testKeyContext(cols ...opt.OrderingColumn) *KeyContext {
   232  	st := cluster.MakeTestingClusterSettings()
   233  	evalCtx := tree.MakeTestingEvalContext(st)
   234  
   235  	var columns Columns
   236  	columns.Init(cols)
   237  
   238  	keyCtx := MakeKeyContext(&columns, &evalCtx)
   239  	return &keyCtx
   240  }