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 }