github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/keys/sql.go (about) 1 // Copyright 2020 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 keys 12 13 import ( 14 "bytes" 15 16 "github.com/cockroachdb/cockroach/pkg/roachpb" 17 "github.com/cockroachdb/cockroach/pkg/util/encoding" 18 "github.com/cockroachdb/errors" 19 ) 20 21 // MakeTenantPrefix creates the key prefix associated with the specified tenant. 22 func MakeTenantPrefix(tenID roachpb.TenantID) roachpb.Key { 23 if tenID == roachpb.SystemTenantID { 24 return nil 25 } 26 return encoding.EncodeUvarintAscending(TenantPrefix, tenID.ToUint64()) 27 } 28 29 // DecodeTenantPrefix determines the tenant ID from the key prefix, returning 30 // the remainder of the key (with the prefix removed) and the decoded tenant ID. 31 func DecodeTenantPrefix(key roachpb.Key) ([]byte, roachpb.TenantID, error) { 32 if len(key) == 0 { // key.Equal(roachpb.RKeyMin) 33 return nil, roachpb.SystemTenantID, nil 34 } 35 if key[0] != tenantPrefixByte { 36 return key, roachpb.SystemTenantID, nil 37 } 38 rem, tenID, err := encoding.DecodeUvarintAscending(key[1:]) 39 if err != nil { 40 return nil, roachpb.TenantID{}, err 41 } 42 return rem, roachpb.MakeTenantID(tenID), nil 43 } 44 45 // SQLCodec provides methods for encoding SQL table keys bound to a given 46 // tenant. The generator also provides methods for efficiently decoding keys 47 // previously generated by it. The generated keys are safe to use indefinitely 48 // and the generator is safe to use concurrently. 49 type SQLCodec struct { 50 sqlEncoder 51 sqlDecoder 52 _ func() // incomparable 53 } 54 55 // sqlEncoder implements the encoding logic for SQL keys. 56 // 57 // The type is expressed as a pointer to a slice instead of a slice directly so 58 // that its zero value is not usable. Any attempt to use the methods on the zero 59 // value of a sqlEncoder will panic. 60 type sqlEncoder struct { 61 buf *roachpb.Key 62 } 63 64 // sqlEncoder implements the decoding logic for SQL keys. 65 // 66 // The type is expressed as a pointer to a slice instead of a slice directly so 67 // that its zero value is not usable. Any attempt to use the methods on the zero 68 // value of a sqlDecoder will panic. 69 type sqlDecoder struct { 70 buf *roachpb.Key 71 } 72 73 // MakeSQLCodec creates a new SQLCodec suitable for manipulating SQL keys. 74 func MakeSQLCodec(tenID roachpb.TenantID) SQLCodec { 75 k := MakeTenantPrefix(tenID) 76 k = k[:len(k):len(k)] // bound capacity, avoid aliasing 77 return SQLCodec{ 78 sqlEncoder: sqlEncoder{&k}, 79 sqlDecoder: sqlDecoder{&k}, 80 } 81 } 82 83 // SystemSQLCodec is a SQL key codec for the system tenant. 84 var SystemSQLCodec = MakeSQLCodec(roachpb.SystemTenantID) 85 86 // TODOSQLCodec is a SQL key codec. It is equivalent to SystemSQLCodec, but 87 // should be used when it is unclear which tenant should be referenced by the 88 // surrounding context. 89 var TODOSQLCodec = MakeSQLCodec(roachpb.SystemTenantID) 90 91 // ForSystemTenant returns whether the encoder is bound to the system tenant. 92 func (e sqlEncoder) ForSystemTenant() bool { 93 return len(e.TenantPrefix()) == 0 94 } 95 96 // TenantPrefix returns the key prefix used for the tenants's data. 97 func (e sqlEncoder) TenantPrefix() roachpb.Key { 98 return *e.buf 99 } 100 101 // TablePrefix returns the key prefix used for the table's data. 102 func (e sqlEncoder) TablePrefix(tableID uint32) roachpb.Key { 103 k := e.TenantPrefix() 104 return encoding.EncodeUvarintAscending(k, uint64(tableID)) 105 } 106 107 // IndexPrefix returns the key prefix used for the index's data. 108 func (e sqlEncoder) IndexPrefix(tableID, indexID uint32) roachpb.Key { 109 k := e.TablePrefix(tableID) 110 return encoding.EncodeUvarintAscending(k, uint64(indexID)) 111 } 112 113 // DescMetadataPrefix returns the key prefix for all descriptors. 114 func (e sqlEncoder) DescMetadataPrefix() roachpb.Key { 115 return e.IndexPrefix(DescriptorTableID, DescriptorTablePrimaryKeyIndexID) 116 } 117 118 // DescMetadataKey returns the key for the descriptor. 119 func (e sqlEncoder) DescMetadataKey(descID uint32) roachpb.Key { 120 k := e.DescMetadataPrefix() 121 k = encoding.EncodeUvarintAscending(k, uint64(descID)) 122 return MakeFamilyKey(k, DescriptorTableDescriptorColFamID) 123 } 124 125 // SequenceKey returns the key used to store the value of a sequence. 126 func (e sqlEncoder) SequenceKey(tableID uint32) roachpb.Key { 127 k := e.IndexPrefix(tableID, SequenceIndexID) 128 k = encoding.EncodeUvarintAscending(k, 0) // Primary key value 129 k = MakeFamilyKey(k, SequenceColumnFamilyID) // Column family 130 return k 131 } 132 133 // DescIDSequenceKey returns the key used for the descriptor ID sequence. 134 func (e sqlEncoder) DescIDSequenceKey() roachpb.Key { 135 if e.ForSystemTenant() { 136 // To maintain backwards compatibility, the system tenant uses a 137 // separate, non-SQL, key to store its descriptor ID sequence. 138 return descIDGenerator 139 } 140 return e.SequenceKey(DescIDSequenceID) 141 } 142 143 // ZoneKeyPrefix returns the key prefix for id's row in the system.zones table. 144 func (e sqlEncoder) ZoneKeyPrefix(id uint32) roachpb.Key { 145 if !e.ForSystemTenant() { 146 panic("zone keys only exist in the system tenant's keyspace") 147 } 148 k := e.IndexPrefix(ZonesTableID, ZonesTablePrimaryIndexID) 149 return encoding.EncodeUvarintAscending(k, uint64(id)) 150 } 151 152 // ZoneKey returns the key for id's entry in the system.zones table. 153 func (e sqlEncoder) ZoneKey(id uint32) roachpb.Key { 154 if !e.ForSystemTenant() { 155 panic("zone keys only exist in the system tenant's keyspace") 156 } 157 k := e.ZoneKeyPrefix(id) 158 return MakeFamilyKey(k, uint32(ZonesTableConfigColumnID)) 159 } 160 161 // MigrationKeyPrefix returns the key prefix to store all migration details. 162 func (e sqlEncoder) MigrationKeyPrefix() roachpb.Key { 163 return append(e.TenantPrefix(), MigrationPrefix...) 164 } 165 166 // MigrationLeaseKey returns the key that nodes must take a lease on in order to 167 // run system migrations on the cluster. 168 func (e sqlEncoder) MigrationLeaseKey() roachpb.Key { 169 return append(e.TenantPrefix(), MigrationLease...) 170 } 171 172 // unexpected to avoid colliding with sqlEncoder.tenantPrefix. 173 func (d sqlDecoder) tenantPrefix() roachpb.Key { 174 return *d.buf 175 } 176 177 // StripTenantPrefix validates that the given key has the proper tenant ID 178 // prefix, returning the remainder of the key with the prefix removed. The 179 // method returns an error if the key has a different tenant ID prefix than 180 // would be generated by the generator. 181 func (d sqlDecoder) StripTenantPrefix(key roachpb.Key) ([]byte, error) { 182 tenPrefix := d.tenantPrefix() 183 if !bytes.HasPrefix(key, tenPrefix) { 184 return nil, errors.Errorf("invalid tenant id prefix: %q", key) 185 } 186 return key[len(tenPrefix):], nil 187 } 188 189 // DecodeTablePrefix validates that the given key has a table prefix, returning 190 // the remainder of the key (with the prefix removed) and the decoded descriptor 191 // ID of the table. 192 func (d sqlDecoder) DecodeTablePrefix(key roachpb.Key) ([]byte, uint32, error) { 193 key, err := d.StripTenantPrefix(key) 194 if err != nil { 195 return nil, 0, err 196 } 197 if encoding.PeekType(key) != encoding.Int { 198 return nil, 0, errors.Errorf("invalid key prefix: %q", key) 199 } 200 key, tableID, err := encoding.DecodeUvarintAscending(key) 201 return key, uint32(tableID), err 202 } 203 204 // DecodeIndexPrefix validates that the given key has a table ID followed by an 205 // index ID, returning the remainder of the key (with the table and index prefix 206 // removed) and the decoded IDs of the table and index, respectively. 207 func (d sqlDecoder) DecodeIndexPrefix(key roachpb.Key) ([]byte, uint32, uint32, error) { 208 key, tableID, err := d.DecodeTablePrefix(key) 209 if err != nil { 210 return nil, 0, 0, err 211 } 212 if encoding.PeekType(key) != encoding.Int { 213 return nil, 0, 0, errors.Errorf("invalid key prefix: %q", key) 214 } 215 key, indexID, err := encoding.DecodeUvarintAscending(key) 216 return key, tableID, uint32(indexID), err 217 } 218 219 // DecodeDescMetadataID decodes a descriptor ID from a descriptor metadata key. 220 func (d sqlDecoder) DecodeDescMetadataID(key roachpb.Key) (uint64, error) { 221 // Extract table and index ID from key. 222 remaining, tableID, _, err := d.DecodeIndexPrefix(key) 223 if err != nil { 224 return 0, err 225 } 226 if tableID != DescriptorTableID { 227 return 0, errors.Errorf("key is not a descriptor table entry: %v", key) 228 } 229 // Extract the descriptor ID. 230 _, id, err := encoding.DecodeUvarintAscending(remaining) 231 if err != nil { 232 return 0, err 233 } 234 return id, nil 235 }