// ObjectIDForKey returns the object ID (table or database) for 'key', // or (_, false) if not within the structured key space. func ObjectIDForKey(key roachpb.RKey) (uint32, bool) { if key.Equal(roachpb.RKeyMax) { return 0, false } if encoding.PeekType(key) != encoding.Int { // TODO(marc): this should eventually return SystemDatabaseID. return 0, false } // Consume first encoded int. _, id64, err := encoding.DecodeUvarintAscending(key) return uint32(id64), err == nil }
// EnsureSafeSplitKey transforms an SQL table key such that it is a valid split key // (i.e. does not occur in the middle of a row). func EnsureSafeSplitKey(key roachpb.Key) (roachpb.Key, error) { if encoding.PeekType(key) != encoding.Int { // Not a table key, so already a split key. return key, nil } n := len(key) // The column ID length is encoded as a varint and we take advantage of the // fact that the column ID itself will be encoded in 0-9 bytes and thus the // length of the column ID data will fit in a single byte. buf := key[n-1:] if encoding.PeekType(buf) != encoding.Int { // The last byte is not a valid column ID suffix. return nil, errors.Errorf("%s: not a valid table key", key) } // Strip off the family ID / column ID suffix from the buf. The last byte of the buf // contains the length of the column ID suffix (which might be 0 if the buf // does not contain a column ID suffix). _, colIDLen, err := encoding.DecodeUvarintAscending(buf) if err != nil { return nil, err } if int(colIDLen)+1 > n { // The column ID length was impossible. colIDLen is the length of // the encoded column ID suffix. We add 1 to account for the byte // holding the length of the encoded column ID and if that total // (colIDLen+1) is greater than the key suffix (n == len(buf)) // then we bail. Note that we don't consider this an error because // EnsureSafeSplitKey can be called on keys that look like table // keys but which do not have a column ID length suffix (e.g // SystemConfig.ComputeSplitKeys). return nil, errors.Errorf("%s: malformed table key", key) } return key[:len(key)-int(colIDLen)-1], nil }
func localRangeIDKeyPrint(key roachpb.Key) string { var buf bytes.Buffer if encoding.PeekType(key) != encoding.Int { return fmt.Sprintf("/err<%q>", []byte(key)) } // Get the rangeID. key, i, err := encoding.DecodeVarintAscending(key) if err != nil { return fmt.Sprintf("/err<%v:%q>", err, []byte(key)) } fmt.Fprintf(&buf, "/%d", i) // Print and remove the rangeID infix specifier. if len(key) != 0 { fmt.Fprintf(&buf, "/%s", string(key[0])) key = key[1:] } // Get the suffix. hasSuffix := false for _, s := range rangeIDSuffixDict { if bytes.HasPrefix(key, s.suffix) { fmt.Fprintf(&buf, "/%s", s.name) key = key[len(s.suffix):] if s.ppFunc != nil && len(key) != 0 { fmt.Fprintf(&buf, "%s", s.ppFunc(key)) return buf.String() } hasSuffix = true break } } // Get the encode values. if hasSuffix { fmt.Fprintf(&buf, "%s", decodeKeyPrint(key)) } else { fmt.Fprintf(&buf, "%q", []byte(key)) } return buf.String() }
// MakeRekeyMVCCKeyValFunc takes an iterator function for MVCCKeyValues and // returns a new iterator function where the keys are rewritten inline to the // have the given table ID. func MakeRekeyMVCCKeyValFunc( newTableID sqlbase.ID, f func(kv engine.MVCCKeyValue) (bool, error), ) func(engine.MVCCKeyValue) (bool, error) { encodedNewTableID := encoding.EncodeUvarintAscending(nil, uint64(newTableID)) return func(kv engine.MVCCKeyValue) (bool, error) { if encoding.PeekType(kv.Key.Key) != encoding.Int { return false, errors.Errorf("unable to decode table key: %s", kv.Key.Key) } existingTableIDLen, err := encoding.PeekLength(kv.Key.Key) if err != nil { return false, err } if existingTableIDLen == len(encodedNewTableID) { copy(kv.Key.Key, encodedNewTableID) } else { kv.Key.Key = append(encodedNewTableID, kv.Key.Key[existingTableIDLen:]...) } return f(kv) } }
// DecodeTablePrefix validates that the given key has a table prefix, returning // the remainder of the key (with the prefix removed) and the decoded descriptor // ID of the table. func DecodeTablePrefix(key roachpb.Key) ([]byte, uint64, error) { if encoding.PeekType(key) != encoding.Int { return key, 0, errors.Errorf("invalid key prefix: %q", key) } return encoding.DecodeUvarintAscending(key) }