// PeekValueLength returns the length of the encoded value at the start of b. // Note: If this function succeeds, it's not a guarantee that decoding the value // will succeed. func PeekValueLength(b []byte) (int, error) { if len(b) == 0 { return 0, util.Errorf("empty slice") } tag := ValueType(b[0]) switch tag { case ValueType_NULL: return 1, nil case ValueType_INT: _, n, _, err := encoding.DecodeNonsortingVarint(b[1:]) return 1 + n, err case ValueType_FLOAT: return 9, nil case ValueType_DELIMITED_BYTES, ValueType_DELIMITED_DECIMAL: _, n, i, err := encoding.DecodeNonsortingVarint(b[1:]) return 1 + n + int(i), err case ValueType_TIME: n, err := encoding.GetMultiVarintLen(b[1:], 2) return 1 + n, err case ValueType_DURATION: n, err := encoding.GetMultiVarintLen(b[1:], 3) return 1 + n, err case ValueType_BYTES, ValueType_DECIMAL: return 0, util.Errorf("not a self-delimiting tag: %q", tag) } return 0, util.Errorf("unknown tag %q", tag) }
// DecodeIntValue decodes a value encoded by EncodeIntValue. func DecodeIntValue(b []byte) ([]byte, int64, error) { if len(b) == 0 { return nil, 0, fmt.Errorf("array is empty") } if tag := ValueType(b[0]); tag != ValueType_INT { return nil, 0, fmt.Errorf("value type is not %s: %s", ValueType_INT, tag) } var i int64 var err error b, _, i, err = encoding.DecodeNonsortingVarint(b[1:]) return b, i, err }
// DecodeBytesValue decodes a value encoded by EncodeBytesValue. func DecodeBytesValue(b []byte) ([]byte, []byte, error) { if len(b) == 0 { return nil, nil, fmt.Errorf("array is empty") } tag := ValueType(b[0]) b = b[1:] switch tag { case ValueType_BYTES: return nil, b, nil case ValueType_DELIMITED_BYTES: var i int64 var err error b, _, i, err = encoding.DecodeNonsortingVarint(b) if err != nil { return nil, nil, err } return b[int(i):], b[:int(i)], nil } return nil, nil, fmt.Errorf( "value type is not %s or %s: %s", ValueType_BYTES, ValueType_DELIMITED_BYTES, tag) }
// DecodeDecimalValue decodes a value encoded by EncodeDecimalValue. func DecodeDecimalValue(b []byte) ([]byte, *inf.Dec, error) { if len(b) == 0 { return nil, nil, fmt.Errorf("array is empty") } tag := ValueType(b[0]) b = b[1:] switch tag { case ValueType_DECIMAL: d, err := encoding.DecodeNonsortingDecimal(b, nil) return nil, d, err case ValueType_DELIMITED_DECIMAL: var i int64 var err error b, _, i, err = encoding.DecodeNonsortingVarint(b) if err != nil { return nil, nil, err } d, err := encoding.DecodeNonsortingDecimal(b[:int(i)], nil) return b[int(i):], d, err } return nil, nil, fmt.Errorf("value type is not %s or %s: %s", ValueType_DECIMAL, ValueType_DELIMITED_DECIMAL, tag) }
// processValueTuple processes the given values (of columns family.ColumnIDs), // setting values in the rf.row accordingly. The key is only used for logging. func (rf *RowFetcher) processValueTuple( family *ColumnFamilyDescriptor, kv client.KeyValue, debugStrings bool, prettyKeyPrefix string, ) (prettyKey string, prettyValue string, err error) { prettyKey = prettyKeyPrefix if debugStrings { rf.prettyValueBuf.Reset() } tupleBytes, err := kv.Value.GetTuple() if err != nil { return "", "", err } var colIDRaw int64 var value parser.Datum for len(tupleBytes) > 0 { tupleBytes, _, colIDRaw, err = encoding.DecodeNonsortingVarint(tupleBytes) if err != nil { return "", "", err } if colIDRaw < 0 || colIDRaw > math.MaxUint32 { return "", "", util.Errorf("invalid column-id: %d", colIDRaw) } idx, ok := rf.colIdxMap[ColumnID(colIDRaw)] // TODO(dan): Ideally rowFetcher would generate EncDatums instead of Datums // and that would make the logic simpler. We won't need valNeededForCol at // all, it would be up to the user of the class to decide if they want to // decode them or not. if !ok || !rf.valNeededForCol[idx] { // This column wasn't requested, so read its length and skip it. i, err := roachpb.PeekValueLength(tupleBytes) if err != nil { return "", "", err } tupleBytes = tupleBytes[i:] if log.V(3) { log.Infof("Scan %s -> [%d] (skipped)", kv.Key, colIDRaw) } continue } if debugStrings { prettyKey = fmt.Sprintf("%s/%s", prettyKey, rf.desc.Columns[idx].Name) } kind := rf.cols[idx].Type.Kind.ToDatumType() value, tupleBytes, err = DecodeTableValue(&rf.alloc, kind, tupleBytes) if err != nil { return "", "", err } if debugStrings { fmt.Fprintf(&rf.prettyValueBuf, "/%v", value) } if rf.row[idx] != nil { panic(fmt.Sprintf("duplicate value for column %d", idx)) } rf.row[idx] = value if log.V(3) { log.Infof("Scan %d -> %v", idx, value) } } if debugStrings { prettyValue = rf.prettyValueBuf.String() } return prettyKey, prettyValue, nil }