-
Notifications
You must be signed in to change notification settings - Fork 3.8k
/
keys.go
168 lines (149 loc) · 5.59 KB
/
keys.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Copyright 2015 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
package sqlbase
import (
"strings"
"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/roachpb"
"github.com/cockroachdb/cockroach/pkg/settings/cluster"
"github.com/cockroachdb/cockroach/pkg/util/encoding"
)
// MakeNameMetadataKey returns the key for the name.
// Pass name == "" in order to generate the prefix key to use to scan over all
// of the names for the specified parentID.
// Pass settings == nil to construct the key for cluster versions >= 20.1 .
func MakeNameMetadataKey(
parentID ID, parentSchemaID ID, name string, settings *cluster.Settings,
) roachpb.Key {
if settings != nil && !settings.Version.IsActive(cluster.VersionNamespaceTableUngossip) {
return MakeDeprecatedNameMetadataKey(parentID, name)
}
k := keys.MakeTablePrefix(uint32(NamespaceTable.ID))
k = encoding.EncodeUvarintAscending(k, uint64(NamespaceTable.PrimaryIndex.ID))
k = encoding.EncodeUvarintAscending(k, uint64(parentID))
k = encoding.EncodeUvarintAscending(k, uint64(parentSchemaID))
if name != "" {
k = encoding.EncodeBytesAscending(k, []byte(name))
k = keys.MakeFamilyKey(k, uint32(NamespaceTable.Columns[3].ID))
}
return k
}
// MakeDeprecatedNameMetadataKey returns the key for a name, as expected by
// versions < 20.1 . Pass name == "" in order to generate the prefix key to use
// to scan over all of the names for the specified parentID.
func MakeDeprecatedNameMetadataKey(parentID ID, name string) roachpb.Key {
k := keys.MakeTablePrefix(uint32(DeprecatedNamespaceTable.ID))
k = encoding.EncodeUvarintAscending(k, uint64(DeprecatedNamespaceTable.PrimaryIndex.ID))
k = encoding.EncodeUvarintAscending(k, uint64(parentID))
if name != "" {
k = encoding.EncodeBytesAscending(k, []byte(name))
k = keys.MakeFamilyKey(k, uint32(DeprecatedNamespaceTable.Columns[2].ID))
}
return k
}
// MakeAllDescsMetadataKey returns the key for all descriptors.
func MakeAllDescsMetadataKey() roachpb.Key {
k := keys.MakeTablePrefix(uint32(DescriptorTable.ID))
return encoding.EncodeUvarintAscending(k, uint64(DescriptorTable.PrimaryIndex.ID))
}
// MakeDescMetadataKey returns the key for the descriptor.
func MakeDescMetadataKey(descID ID) roachpb.Key {
k := MakeAllDescsMetadataKey()
k = encoding.EncodeUvarintAscending(k, uint64(descID))
return keys.MakeFamilyKey(k, uint32(DescriptorTable.Columns[1].ID))
}
// IndexKeyValDirs returns the corresponding encoding.Directions for all the
// encoded values in index's "fullest" possible index key, including directions
// for table/index IDs, the interleaved sentinel and the index column values.
// For example, given
// CREATE INDEX foo ON bar (a, b DESC) INTERLEAVED IN PARENT bar (a)
// a typical index key with all values specified could be
// /51/1/42/#/51/2/1337
// which would return the slice
// {ASC, ASC, ASC, 0, ASC, ASC, DESC}
func IndexKeyValDirs(index *IndexDescriptor) []encoding.Direction {
if index == nil {
return nil
}
dirs := make([]encoding.Direction, 0, (len(index.Interleave.Ancestors)+1)*2+len(index.ColumnDirections))
colIdx := 0
for _, ancs := range index.Interleave.Ancestors {
// Table/Index IDs are always encoded ascending.
dirs = append(dirs, encoding.Ascending, encoding.Ascending)
for i := 0; i < int(ancs.SharedPrefixLen); i++ {
d, err := index.ColumnDirections[colIdx].ToEncodingDirection()
if err != nil {
panic(err)
}
dirs = append(dirs, d)
colIdx++
}
// The interleaved sentinel uses the 0 value for
// encoding.Direction when pretty-printing (see
// encoding.go:prettyPrintFirstValue).
dirs = append(dirs, 0)
}
// The index's table/index ID.
dirs = append(dirs, encoding.Ascending, encoding.Ascending)
for colIdx < len(index.ColumnDirections) {
d, err := index.ColumnDirections[colIdx].ToEncodingDirection()
if err != nil {
panic(err)
}
dirs = append(dirs, d)
colIdx++
}
return dirs
}
// PrettyKey pretty-prints the specified key, skipping over the first `skip`
// fields. The pretty printed key looks like:
//
// /Table/<tableID>/<indexID>/...
//
// We always strip off the /Table prefix and then `skip` more fields. Note that
// this assumes that the fields themselves do not contain '/', but that is
// currently true for the fields we care about stripping (the table and index
// ID).
func PrettyKey(valDirs []encoding.Direction, key roachpb.Key, skip int) string {
p := key.StringWithDirs(valDirs, 0 /* maxLen */)
for i := 0; i <= skip; i++ {
n := strings.IndexByte(p[1:], '/')
if n == -1 {
return ""
}
p = p[n+1:]
}
return p
}
// PrettySpan returns a human-readable representation of a span.
func PrettySpan(valDirs []encoding.Direction, span roachpb.Span, skip int) string {
var b strings.Builder
b.WriteString(PrettyKey(valDirs, span.Key, skip))
b.WriteByte('-')
b.WriteString(PrettyKey(valDirs, span.EndKey, skip))
return b.String()
}
// PrettySpans returns a human-readable description of the spans.
// If index is nil, then pretty print subroutines will use their default
// settings.
func PrettySpans(index *IndexDescriptor, spans []roachpb.Span, skip int) string {
if len(spans) == 0 {
return ""
}
valDirs := IndexKeyValDirs(index)
var b strings.Builder
for i, span := range spans {
if i > 0 {
b.WriteString(" ")
}
b.WriteString(PrettySpan(valDirs, span, skip))
}
return b.String()
}