// 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. remaining = key 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 }
// 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) { var encLen int switch enc { case DatumEncoding_ASCENDING_KEY, DatumEncoding_DESCENDING_KEY: encLen, err = encoding.PeekLength(buf) case DatumEncoding_VALUE: encLen, err = roachpb.PeekValueLength(buf) default: panic(fmt.Sprintf("unknown encoding %s", ed.encoding)) } if err != nil { return nil, err } ed.SetEncoded(typ, enc, buf[:encLen]) return buf[encLen:], nil }