// DecodeIndexKeyPrefix decodes the prefix of an index key and returns the // index id and a slice for the rest of the key. // // Don't use this function in the scan "hot path". func DecodeIndexKeyPrefix( a *DatumAlloc, desc *TableDescriptor, key []byte, ) (indexID IndexID, remaining []byte, err error) { // TODO(dan): This whole operation is n^2 because of the interleaves // bookkeeping. We could improve it to n with a prefix tree of components. interleaves := append([]IndexDescriptor{desc.PrimaryIndex}, desc.Indexes...) for component := 0; ; component++ { var tableID ID key, tableID, indexID, err = DecodeTableIDIndexID(key) if err != nil { return 0, nil, err } if tableID == desc.ID { // Once desc's table id has been decoded, there can be no more // interleaves. break } for i := len(interleaves) - 1; i >= 0; i-- { if len(interleaves[i].Interleave.Ancestors) <= component || interleaves[i].Interleave.Ancestors[component].TableID != tableID || interleaves[i].Interleave.Ancestors[component].IndexID != indexID { // This component, and thus this interleave, doesn't match what was // decoded, remove it. copy(interleaves[i:], interleaves[i+1:]) interleaves = interleaves[:len(interleaves)-1] } } // The decoded key doesn't many any known interleaves if len(interleaves) == 0 { return 0, nil, errors.Errorf("no known interleaves for key") } // Anything left has the same SharedPrefixLen at index `component`, so just // use the first one. for i := uint32(0); i < interleaves[0].Interleave.Ancestors[component].SharedPrefixLen; i++ { l, err := encoding.PeekLength(key) if err != nil { return 0, nil, err } key = key[l:] } // We reuse NotNullDescending as the interleave sentinel, consume it. var ok bool key, ok = encoding.DecodeIfNotNull(key) if !ok { return 0, nil, errors.Errorf("invalid interleave key") } } return indexID, key, err }
// 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) } }
// EncDatumFromBuffer initializes an EncDatum with an encoding that is // possibly followed by other data. Similar to EncDatumFromEncoded, // except that this function figures out where the encoding stops and returns a // slice for the rest of the buffer. func EncDatumFromBuffer(typ ColumnType, enc DatumEncoding, buf []byte) (EncDatum, []byte, error) { switch enc { case DatumEncoding_ASCENDING_KEY, DatumEncoding_DESCENDING_KEY: encLen, err := encoding.PeekLength(buf) if err != nil { return EncDatum{}, nil, err } ed := EncDatumFromEncoded(typ, enc, buf[:encLen]) return ed, buf[encLen:], nil case DatumEncoding_VALUE: typeOffset, encLen, err := encoding.PeekValueLength(buf) if err != nil { return EncDatum{}, nil, err } ed := EncDatumFromEncoded(typ, enc, buf[typeOffset:encLen]) return ed, buf[encLen:], nil default: panic(fmt.Sprintf("unknown encoding %s", enc)) } }
// SetFromBuffer initializes the EncDatum with an encoding that is possibly // followed by other data. Similar to SetEncoded, except that this function // figures out where the encoding stops and returns a slice for the rest of the // buffer. func (ed *EncDatum) SetFromBuffer( typ ColumnType_Kind, enc DatumEncoding, buf []byte, ) (remaining []byte, err error) { switch enc { case DatumEncoding_ASCENDING_KEY, DatumEncoding_DESCENDING_KEY: encLen, err := encoding.PeekLength(buf) if err != nil { return nil, err } ed.SetEncoded(typ, enc, buf[:encLen]) return buf[encLen:], nil case DatumEncoding_VALUE: typeOffset, encLen, err := encoding.PeekValueLength(buf) if err != nil { return nil, err } ed.SetEncoded(typ, enc, buf[typeOffset:encLen]) return buf[encLen:], nil default: panic(fmt.Sprintf("unknown encoding %s", ed.encoding)) } }