github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sqlbase/keys.go (about) 1 // Copyright 2015 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 package sqlbase 12 13 import ( 14 "strings" 15 16 "github.com/cockroachdb/cockroach/pkg/keys" 17 "github.com/cockroachdb/cockroach/pkg/roachpb" 18 "github.com/cockroachdb/cockroach/pkg/util/encoding" 19 "github.com/cockroachdb/errors" 20 ) 21 22 const ( 23 // DefaultDatabaseName is the name ofthe default CockroachDB database used 24 // for connections without a current db set. 25 DefaultDatabaseName = "defaultdb" 26 27 // PgDatabaseName is the name of the default postgres system database. 28 PgDatabaseName = "postgres" 29 ) 30 31 // DefaultUserDBs is a set of the databases which are present in a new cluster. 32 var DefaultUserDBs = map[string]struct{}{ 33 DefaultDatabaseName: {}, 34 PgDatabaseName: {}, 35 } 36 37 // MaxDefaultDescriptorID is the maximum ID of a descriptor that exists in a 38 // new cluster. 39 var MaxDefaultDescriptorID = keys.MaxReservedDescID + ID(len(DefaultUserDBs)) 40 41 // IsDefaultCreatedDescriptor returns whether or not a given descriptor ID is 42 // present at the time of starting a cluster. 43 func IsDefaultCreatedDescriptor(descID ID) bool { 44 return descID <= MaxDefaultDescriptorID 45 } 46 47 // MakeNameMetadataKey returns the key for the name, as expected by 48 // versions >= 20.1. 49 // Pass name == "" in order to generate the prefix key to use to scan over all 50 // of the names for the specified parentID. 51 func MakeNameMetadataKey( 52 codec keys.SQLCodec, parentID ID, parentSchemaID ID, name string, 53 ) roachpb.Key { 54 k := codec.IndexPrefix(uint32(NamespaceTable.ID), uint32(NamespaceTable.PrimaryIndex.ID)) 55 k = encoding.EncodeUvarintAscending(k, uint64(parentID)) 56 k = encoding.EncodeUvarintAscending(k, uint64(parentSchemaID)) 57 if name != "" { 58 k = encoding.EncodeBytesAscending(k, []byte(name)) 59 k = keys.MakeFamilyKey(k, uint32(NamespaceTable.Columns[3].ID)) 60 } 61 return k 62 } 63 64 // DecodeNameMetadataKey returns the components that make up the 65 // NameMetadataKey for version >= 20.1. 66 func DecodeNameMetadataKey( 67 codec keys.SQLCodec, k roachpb.Key, 68 ) (parentID ID, parentSchemaID ID, name string, err error) { 69 k, _, err = codec.DecodeTablePrefix(k) 70 if err != nil { 71 return 0, 0, "", err 72 } 73 74 var buf uint64 75 k, buf, err = encoding.DecodeUvarintAscending(k) 76 if err != nil { 77 return 0, 0, "", err 78 } 79 if buf != uint64(NamespaceTable.PrimaryIndex.ID) { 80 return 0, 0, "", errors.Newf("tried get table %d, but got %d", NamespaceTable.PrimaryIndex.ID, buf) 81 } 82 83 k, buf, err = encoding.DecodeUvarintAscending(k) 84 if err != nil { 85 return 0, 0, "", err 86 } 87 parentID = ID(buf) 88 89 k, buf, err = encoding.DecodeUvarintAscending(k) 90 if err != nil { 91 return 0, 0, "", err 92 } 93 parentSchemaID = ID(buf) 94 95 var bytesBuf []byte 96 _, bytesBuf, err = encoding.DecodeBytesAscending(k, nil) 97 if err != nil { 98 return 0, 0, "", err 99 } 100 name = string(bytesBuf) 101 102 return parentID, parentSchemaID, name, nil 103 } 104 105 // MakeDeprecatedNameMetadataKey returns the key for a name, as expected by 106 // versions < 20.1. Pass name == "" in order to generate the prefix key to use 107 // to scan over all of the names for the specified parentID. 108 func MakeDeprecatedNameMetadataKey(codec keys.SQLCodec, parentID ID, name string) roachpb.Key { 109 k := codec.IndexPrefix( 110 uint32(DeprecatedNamespaceTable.ID), uint32(DeprecatedNamespaceTable.PrimaryIndex.ID)) 111 k = encoding.EncodeUvarintAscending(k, uint64(parentID)) 112 if name != "" { 113 k = encoding.EncodeBytesAscending(k, []byte(name)) 114 k = keys.MakeFamilyKey(k, uint32(DeprecatedNamespaceTable.Columns[2].ID)) 115 } 116 return k 117 } 118 119 // MakeAllDescsMetadataKey returns the key for all descriptors. 120 func MakeAllDescsMetadataKey(codec keys.SQLCodec) roachpb.Key { 121 return codec.DescMetadataPrefix() 122 } 123 124 // MakeDescMetadataKey returns the key for the descriptor. 125 func MakeDescMetadataKey(codec keys.SQLCodec, descID ID) roachpb.Key { 126 return codec.DescMetadataKey(uint32(descID)) 127 } 128 129 // IndexKeyValDirs returns the corresponding encoding.Directions for all the 130 // encoded values in index's "fullest" possible index key, including directions 131 // for table/index IDs, the interleaved sentinel and the index column values. 132 // For example, given 133 // CREATE INDEX foo ON bar (a, b DESC) INTERLEAVED IN PARENT bar (a) 134 // a typical index key with all values specified could be 135 // /51/1/42/#/51/2/1337 136 // which would return the slice 137 // {ASC, ASC, ASC, 0, ASC, ASC, DESC} 138 func IndexKeyValDirs(index *IndexDescriptor) []encoding.Direction { 139 if index == nil { 140 return nil 141 } 142 143 dirs := make([]encoding.Direction, 0, (len(index.Interleave.Ancestors)+1)*2+len(index.ColumnDirections)) 144 145 colIdx := 0 146 for _, ancs := range index.Interleave.Ancestors { 147 // Table/Index IDs are always encoded ascending. 148 dirs = append(dirs, encoding.Ascending, encoding.Ascending) 149 for i := 0; i < int(ancs.SharedPrefixLen); i++ { 150 d, err := index.ColumnDirections[colIdx].ToEncodingDirection() 151 if err != nil { 152 panic(err) 153 } 154 dirs = append(dirs, d) 155 colIdx++ 156 } 157 158 // The interleaved sentinel uses the 0 value for 159 // encoding.Direction when pretty-printing (see 160 // encoding.go:prettyPrintFirstValue). 161 dirs = append(dirs, 0) 162 } 163 164 // The index's table/index ID. 165 dirs = append(dirs, encoding.Ascending, encoding.Ascending) 166 167 for colIdx < len(index.ColumnDirections) { 168 d, err := index.ColumnDirections[colIdx].ToEncodingDirection() 169 if err != nil { 170 panic(err) 171 } 172 dirs = append(dirs, d) 173 colIdx++ 174 } 175 176 return dirs 177 } 178 179 // PrettyKey pretty-prints the specified key, skipping over the first `skip` 180 // fields. The pretty printed key looks like: 181 // 182 // /Table/<tableID>/<indexID>/... 183 // 184 // We always strip off the /Table prefix and then `skip` more fields. Note that 185 // this assumes that the fields themselves do not contain '/', but that is 186 // currently true for the fields we care about stripping (the table and index 187 // ID). 188 func PrettyKey(valDirs []encoding.Direction, key roachpb.Key, skip int) string { 189 p := key.StringWithDirs(valDirs, 0 /* maxLen */) 190 for i := 0; i <= skip; i++ { 191 n := strings.IndexByte(p[1:], '/') 192 if n == -1 { 193 return "" 194 } 195 p = p[n+1:] 196 } 197 return p 198 } 199 200 // PrettySpan returns a human-readable representation of a span. 201 func PrettySpan(valDirs []encoding.Direction, span roachpb.Span, skip int) string { 202 var b strings.Builder 203 b.WriteString(PrettyKey(valDirs, span.Key, skip)) 204 b.WriteByte('-') 205 b.WriteString(PrettyKey(valDirs, span.EndKey, skip)) 206 return b.String() 207 } 208 209 // PrettySpans returns a human-readable description of the spans. 210 // If index is nil, then pretty print subroutines will use their default 211 // settings. 212 func PrettySpans(index *IndexDescriptor, spans []roachpb.Span, skip int) string { 213 if len(spans) == 0 { 214 return "" 215 } 216 217 valDirs := IndexKeyValDirs(index) 218 219 var b strings.Builder 220 for i, span := range spans { 221 if i > 0 { 222 b.WriteString(" ") 223 } 224 b.WriteString(PrettySpan(valDirs, span, skip)) 225 } 226 return b.String() 227 }