func (a *varianceAggregate) add(datum parser.Datum) error { if datum == parser.DNull { return nil } var d parser.DFloat switch t := datum.(type) { case parser.DInt: d = parser.DFloat(t) case parser.DFloat: d = t // case parser.DDecimal: // TODO(nvanbenschoten) add support for decimal variance and stddev // aggregation functions. Will require adding decimal.Sqrt() to library. default: return util.Errorf("unexpected VARIANCE argument type: %s", datum.Type()) } // Uses the Knuth/Welford method for accurately computing variance online in a // single pass. See http://www.johndcook.com/blog/standard_deviation/ and // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm. a.count++ delta := d - a.mean a.mean += delta / parser.DFloat(a.count) a.sqrDiff += delta * (d - a.mean) return nil }
func decodeTableKey(valType parser.Datum, key []byte) (parser.Datum, []byte, error) { var isNull bool if key, isNull = encoding.DecodeIfNull(key); isNull { return parser.DNull, key, nil } switch valType.(type) { case parser.DBool: rkey, i, err := encoding.DecodeVarint(key) return parser.DBool(i != 0), rkey, err case parser.DInt: rkey, i, err := encoding.DecodeVarint(key) return parser.DInt(i), rkey, err case parser.DFloat: rkey, f, err := encoding.DecodeFloat(key, nil) return parser.DFloat(f), rkey, err case parser.DString: rkey, r, err := encoding.DecodeString(key, nil) return parser.DString(r), rkey, err case parser.DBytes: rkey, r, err := encoding.DecodeString(key, nil) return parser.DBytes(r), rkey, err case parser.DDate: rkey, t, err := encoding.DecodeTime(key) return parser.DDate{Time: t}, rkey, err case parser.DTimestamp: rkey, t, err := encoding.DecodeTime(key) return parser.DTimestamp{Time: t}, rkey, err case parser.DInterval: rkey, d, err := encoding.DecodeVarint(key) return parser.DInterval{Duration: time.Duration(d)}, rkey, err default: return nil, nil, util.Errorf("TODO(pmattis): decoded index key: %s", valType.Type()) } }
func datumFromProto(d driver.Datum) parser.Datum { arg := d.Payload if arg == nil { return parser.DNull } switch t := arg.(type) { case *driver.Datum_BoolVal: return parser.DBool(t.BoolVal) case *driver.Datum_IntVal: return parser.DInt(t.IntVal) case *driver.Datum_FloatVal: return parser.DFloat(t.FloatVal) case *driver.Datum_DecimalVal: dd := &parser.DDecimal{} if _, ok := dd.SetString(t.DecimalVal); !ok { panic(fmt.Sprintf("could not parse string %q as decimal", t.DecimalVal)) } return dd case *driver.Datum_BytesVal: return parser.DBytes(t.BytesVal) case *driver.Datum_StringVal: return parser.DString(t.StringVal) case *driver.Datum_DateVal: return parser.DDate(t.DateVal) case *driver.Datum_TimeVal: return parser.DTimestamp{Time: t.TimeVal.GoTime()} case *driver.Datum_IntervalVal: return parser.DInterval{Duration: time.Duration(t.IntervalVal)} default: panic(fmt.Sprintf("unexpected type %T", t)) } }
// decodeKeyVals decodes the values that are part of the key. ValTypes is a // slice returned from makeKeyVals. The decoded values are stored in the vals // parameter while the valTypes parameter is unmodified. Note that len(vals) >= // len(valTypes). The types of the decoded values will match the corresponding // entry in the valTypes parameter with the exception that a value might also // be parser.DNull. The remaining bytes in the key after decoding the values // are returned. func decodeKeyVals(valTypes, vals []parser.Datum, key []byte) ([]byte, error) { for j := range valTypes { var isNull bool if key, isNull = encoding.DecodeIfNull(key); isNull { vals[j] = parser.DNull continue } switch valTypes[j].(type) { case parser.DInt: var i int64 key, i = encoding.DecodeVarint(key) vals[j] = parser.DInt(i) case parser.DFloat: var f float64 key, f = encoding.DecodeFloat(key, nil) vals[j] = parser.DFloat(f) case parser.DString: var r string key, r = encoding.DecodeString(key, nil) vals[j] = parser.DString(r) default: return nil, util.Errorf("TODO(pmattis): decoded index key: %s", valTypes[j].Type()) } } return key, nil }
// Arg implements the parser.Args interface. func (p parameters) Arg(name string) (parser.Datum, bool) { i, err := processPositionalArgument(name) if err != nil { return nil, false } if i < 1 || int(i) > len(p) { return nil, false } arg := p[i-1].Payload if arg == nil { return parser.DNull, true } switch t := arg.(type) { case *driver.Datum_BoolVal: return parser.DBool(t.BoolVal), true case *driver.Datum_IntVal: return parser.DInt(t.IntVal), true case *driver.Datum_FloatVal: return parser.DFloat(t.FloatVal), true case *driver.Datum_BytesVal: return parser.DBytes(t.BytesVal), true case *driver.Datum_StringVal: return parser.DString(t.StringVal), true case *driver.Datum_DateVal: return parser.DDate(t.DateVal), true case *driver.Datum_TimeVal: return parser.DTimestamp{Time: t.TimeVal.GoTime()}, true case *driver.Datum_IntervalVal: return parser.DInterval{Duration: time.Duration(t.IntervalVal)}, true default: panic(fmt.Sprintf("unexpected type %T", t)) } }
func decodeTableKey(valType parser.Datum, key []byte) (parser.Datum, []byte, error) { var isNull bool if key, isNull = encoding.DecodeIfNull(key); isNull { return parser.DNull, key, nil } switch valType.(type) { case parser.DBool: var i int64 key, i = encoding.DecodeVarint(key) return parser.DBool(i != 0), key, nil case parser.DInt: var i int64 key, i = encoding.DecodeVarint(key) return parser.DInt(i), key, nil case parser.DFloat: var f float64 key, f = encoding.DecodeFloat(key, nil) return parser.DFloat(f), key, nil case parser.DString: var r string key, r = encoding.DecodeString(key, nil) return parser.DString(r), key, nil default: return nil, nil, util.Errorf("TODO(pmattis): decoded index key: %s", valType.Type()) } }
func datumFromProto(d driver.Datum) parser.Datum { arg := d.Payload if arg == nil { return parser.DNull } switch t := arg.(type) { case *driver.Datum_BoolVal: return parser.DBool(t.BoolVal) case *driver.Datum_IntVal: return parser.DInt(t.IntVal) case *driver.Datum_FloatVal: return parser.DFloat(t.FloatVal) case *driver.Datum_DecimalVal: dec, err := decimal.NewFromString(t.DecimalVal) if err != nil { panic(fmt.Sprintf("could not parse decimal: %v", err)) } return parser.DDecimal{Decimal: dec} case *driver.Datum_BytesVal: return parser.DBytes(t.BytesVal) case *driver.Datum_StringVal: return parser.DString(t.StringVal) case *driver.Datum_DateVal: return parser.DDate(t.DateVal) case *driver.Datum_TimeVal: return parser.DTimestamp{Time: t.TimeVal.GoTime()} case *driver.Datum_IntervalVal: return parser.DInterval{Duration: time.Duration(t.IntervalVal)} default: panic(fmt.Sprintf("unexpected type %T", t)) } }
// Arg implements the Args interface func (p parameters) Arg(name string) (parser.Datum, bool) { if !unicode.IsDigit(rune(name[0])) { // TODO(pmattis): Add support for named parameters (vs the numbered // parameter support below). return nil, false } i, err := strconv.ParseInt(name, 10, 0) if err != nil { return nil, false } if i < 1 || int(i) > len(p) { return nil, false } arg := p[i-1].GetValue() if arg == nil { return parser.DNull, true } switch t := arg.(type) { case *bool: return parser.DBool(*t), true case *int64: return parser.DInt(*t), true case *float64: return parser.DFloat(*t), true case []byte: return parser.DString(t), true case *string: return parser.DString(*t), true default: panic(fmt.Sprintf("unexpected type %T", t)) } }
func (n *scanNode) unmarshalValue(kv client.KeyValue) (parser.Datum, bool) { kind, ok := n.colKind[n.colID] if !ok { n.err = fmt.Errorf("column-id \"%d\" does not exist", n.colID) return nil, false } if kv.Exists() { switch kind { case ColumnType_INT: return parser.DInt(kv.ValueInt()), true case ColumnType_BOOL: return parser.DBool(kv.ValueInt() != 0), true case ColumnType_FLOAT: return parser.DFloat(math.Float64frombits(uint64(kv.ValueInt()))), true case ColumnType_STRING, ColumnType_BYTES: return parser.DString(kv.ValueBytes()), true case ColumnType_DATE: var t time.Time if err := t.UnmarshalBinary(kv.ValueBytes()); err != nil { return nil, false } return parser.DDate{Time: t}, true case ColumnType_TIMESTAMP: var t time.Time if err := t.UnmarshalBinary(kv.ValueBytes()); err != nil { return nil, false } return parser.DTimestamp{Time: t}, true case ColumnType_INTERVAL: return parser.DInterval{Duration: time.Duration(kv.ValueInt())}, true } } return parser.DNull, true }
func makeIndexKeyVals(desc *structured.TableDescriptor, index structured.IndexDescriptor) ([]parser.Datum, error) { vals := make([]parser.Datum, len(index.ColumnIDs)) for i, id := range index.ColumnIDs { col, err := desc.FindColumnByID(id) if err != nil { return nil, err } switch col.Type.Kind { case structured.ColumnType_BIT, structured.ColumnType_INT: vals[i] = parser.DInt(0) case structured.ColumnType_FLOAT: vals[i] = parser.DFloat(0) case structured.ColumnType_CHAR, structured.ColumnType_TEXT, structured.ColumnType_BLOB: vals[i] = parser.DString("") default: return nil, util.Errorf("TODO(pmattis): decoded index key: %s", col.Type.Kind) } } if !index.Unique { // Non-unique columns are suffixed by the primary index key. pkVals, err := makeIndexKeyVals(desc, desc.PrimaryIndex) if err != nil { return nil, err } vals = append(vals, pkVals...) } return vals, nil }
func (n *scanNode) getQVal(col ColumnDescriptor) parser.Expr { if n.qvals == nil { n.qvals = make(qvalMap) } qval := n.qvals[col.ID] if qval == nil { qval = &qvalue{col: col} // We initialize the qvalue expression to a datum of the type matching the // column. This allows type analysis to be performed on the expression // before we start retrieving rows. // // TODO(pmattis): Nullable columns can have NULL values. The type analysis // needs to take that into consideration, but how to surface that info? switch col.Type.Kind { case ColumnType_BIT, ColumnType_INT: qval.datum = parser.DInt(0) case ColumnType_BOOL: qval.datum = parser.DBool(true) case ColumnType_FLOAT: qval.datum = parser.DFloat(0) case ColumnType_CHAR, ColumnType_TEXT, ColumnType_BLOB: qval.datum = parser.DString("") default: panic(fmt.Sprintf("unsupported column type: %s", col.Type.Kind)) } n.qvals[col.ID] = qval } return qval }
func (a *avgAggregate) Result() (parser.Datum, error) { sum, err := a.sumAggregate.Result() if err != nil { return parser.DNull, err } if sum == parser.DNull { return sum, nil } switch t := sum.(type) { case parser.DInt: return parser.DFloat(t) / parser.DFloat(a.count), nil case parser.DFloat: return t / parser.DFloat(a.count), nil default: return parser.DNull, fmt.Errorf("unexpected SUM result type: %s", t.Type()) } }
// DecodeTableValue decodes a value encoded by EncodeTableValue. func DecodeTableValue(a *DatumAlloc, valType parser.Datum, b []byte) (parser.Datum, []byte, error) { // TODO(dan): Merge this and DecodeTableKey. if len(b) == 0 { return nil, nil, util.Errorf("empty slice") } if roachpb.ValueType(b[0]) == roachpb.ValueType_NULL { return parser.DNull, b[1:], nil } var err error switch valType.(type) { case *parser.DBool: var i int64 b, i, err = roachpb.DecodeIntValue(b) // No need to chunk allocate DBool as MakeDBool returns either // parser.DBoolTrue or parser.DBoolFalse. return parser.MakeDBool(parser.DBool(i != 0)), b, err case *parser.DInt: var i int64 b, i, err = roachpb.DecodeIntValue(b) return a.NewDInt(parser.DInt(i)), b, err case *parser.DFloat: var f float64 b, f, err = roachpb.DecodeFloatValue(b) return a.NewDFloat(parser.DFloat(f)), b, err case *parser.DDecimal: var d *inf.Dec b, d, err = roachpb.DecodeDecimalValue(b) dd := a.NewDDecimal(parser.DDecimal{}) dd.Set(d) return dd, b, err case *parser.DString: var data []byte b, data, err = roachpb.DecodeBytesValue(b) return a.NewDString(parser.DString(data)), b, err case *parser.DBytes: var data []byte b, data, err = roachpb.DecodeBytesValue(b) return a.NewDBytes(parser.DBytes(data)), b, err case *parser.DDate: var i int64 b, i, err = roachpb.DecodeIntValue(b) return a.NewDDate(parser.DDate(i)), b, err case *parser.DTimestamp: var t time.Time b, t, err = roachpb.DecodeTimeValue(b) return a.NewDTimestamp(parser.DTimestamp{Time: t}), b, err case *parser.DTimestampTZ: var t time.Time b, t, err = roachpb.DecodeTimeValue(b) return a.NewDTimestampTZ(parser.DTimestampTZ{Time: t}), b, err case *parser.DInterval: var d duration.Duration b, d, err = roachpb.DecodeDurationValue(b) return a.NewDInterval(parser.DInterval{Duration: d}), b, err default: return nil, nil, util.Errorf("TODO(pmattis): decoded index value: %s", valType.Type()) } }
// unmarshalColumnValue decodes the value from a key-value pair using the type // expected by the column. An error is returned if the value's type does not // match the column's type. func unmarshalColumnValue(kind ColumnType_Kind, value *proto.Value) (parser.Datum, error) { if value == nil { return parser.DNull, nil } switch kind { case ColumnType_BOOL: v, err := value.GetInt() if err != nil { return nil, err } return parser.DBool(v != 0), nil case ColumnType_INT: v, err := value.GetInt() if err != nil { return nil, err } return parser.DInt(v), nil case ColumnType_FLOAT: v, err := value.GetFloat() if err != nil { return nil, err } return parser.DFloat(v), nil case ColumnType_STRING: v, err := value.GetBytesChecked() if err != nil { return nil, err } return parser.DString(v), nil case ColumnType_BYTES: v, err := value.GetBytesChecked() if err != nil { return nil, err } return parser.DBytes(v), nil case ColumnType_DATE: v, err := value.GetTime() if err != nil { return nil, err } return parser.DDate{Time: v}, nil case ColumnType_TIMESTAMP: v, err := value.GetTime() if err != nil { return nil, err } return parser.DTimestamp{Time: v}, nil case ColumnType_INTERVAL: v, err := value.GetInt() if err != nil { return nil, err } return parser.DInterval{Duration: time.Duration(v)}, nil default: return nil, util.Errorf("unsupported column type: %s", kind) } }
// DecodeTableValue decodes a value encoded by EncodeTableValue. func DecodeTableValue(a *DatumAlloc, valType parser.Datum, b []byte) (parser.Datum, []byte, error) { _, dataOffset, _, typ, err := encoding.DecodeValueTag(b) if err != nil { return nil, b, err } if typ == encoding.Null { return parser.DNull, b[dataOffset:], nil } switch valType.(type) { case *parser.DBool: var x bool b, x, err = encoding.DecodeBoolValue(b) // No need to chunk allocate DBool as MakeDBool returns either // parser.DBoolTrue or parser.DBoolFalse. return parser.MakeDBool(parser.DBool(x)), b, err case *parser.DInt: var i int64 b, i, err = encoding.DecodeIntValue(b) return a.NewDInt(parser.DInt(i)), b, err case *parser.DFloat: var f float64 b, f, err = encoding.DecodeFloatValue(b) return a.NewDFloat(parser.DFloat(f)), b, err case *parser.DDecimal: var d *inf.Dec b, d, err = encoding.DecodeDecimalValue(b) dd := a.NewDDecimal(parser.DDecimal{}) dd.Set(d) return dd, b, err case *parser.DString: var data []byte b, data, err = encoding.DecodeBytesValue(b) return a.NewDString(parser.DString(data)), b, err case *parser.DBytes: var data []byte b, data, err = encoding.DecodeBytesValue(b) return a.NewDBytes(parser.DBytes(data)), b, err case *parser.DDate: var i int64 b, i, err = encoding.DecodeIntValue(b) return a.NewDDate(parser.DDate(i)), b, err case *parser.DTimestamp: var t time.Time b, t, err = encoding.DecodeTimeValue(b) return a.NewDTimestamp(parser.DTimestamp{Time: t}), b, err case *parser.DTimestampTZ: var t time.Time b, t, err = encoding.DecodeTimeValue(b) return a.NewDTimestampTZ(parser.DTimestampTZ{Time: t}), b, err case *parser.DInterval: var d duration.Duration b, d, err = encoding.DecodeDurationValue(b) return a.NewDInterval(parser.DInterval{Duration: d}), b, err default: return nil, nil, errors.Errorf("TODO(pmattis): decoded index value: %s", valType.Type()) } }
// golangFillQueryArguments populates the placeholder map with // types and values from an array of Go values. // TODO: This does not support arguments of the SQL 'Date' type, as there is not // an equivalent type in Go's standard library. It's not currently needed by any // of our internal tables. func golangFillQueryArguments(pinfo *parser.PlaceholderInfo, args []interface{}) { pinfo.Clear() for i, arg := range args { k := fmt.Sprint(i + 1) if arg == nil { pinfo.SetValue(k, parser.DNull) continue } // A type switch to handle a few explicit types with special semantics: // - Datums are passed along as is. // - Time datatypes get special representation in the database. var d parser.Datum switch t := arg.(type) { case parser.Datum: d = t case time.Time: d = parser.MakeDTimestamp(t, time.Microsecond) case time.Duration: d = &parser.DInterval{Duration: duration.Duration{Nanos: t.Nanoseconds()}} case *inf.Dec: dd := &parser.DDecimal{} dd.Set(t) d = dd } if d == nil { // Handle all types which have an underlying type that can be stored in the // database. // Note: if this reflection becomes a performance concern in the future, // commonly used types could be added explicitly into the type switch above // for a performance gain. val := reflect.ValueOf(arg) switch val.Kind() { case reflect.Bool: d = parser.MakeDBool(parser.DBool(val.Bool())) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: d = parser.NewDInt(parser.DInt(val.Int())) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: d = parser.NewDInt(parser.DInt(val.Uint())) case reflect.Float32, reflect.Float64: d = parser.NewDFloat(parser.DFloat(val.Float())) case reflect.String: d = parser.NewDString(val.String()) case reflect.Slice: // Handle byte slices. if val.Type().Elem().Kind() == reflect.Uint8 { d = parser.NewDBytes(parser.DBytes(val.Bytes())) } } if d == nil { panic(fmt.Sprintf("unexpected type %T", arg)) } } pinfo.SetValue(k, d) } }
func makeFloatTestDatum(count int) []parser.Datum { rng, _ := randutil.NewPseudoRand() vals := make([]parser.Datum, count) for i := range vals { vals[i] = parser.DFloat(rng.Float64()) } return vals }
// Arg implements the parser.Args interface. // TODO: This does not support arguments of the SQL 'Date' type, as there is not // an equivalent type in Go's standard library. It's not currently needed by any // of our internal tables. func (gp golangParameters) Arg(name string) (parser.Datum, bool) { i, err := processPositionalArgument(name) if err != nil { return nil, false } if i < 1 || int(i) > len(gp) { return nil, false } arg := gp[i-1] if arg == nil { return parser.DNull, true } // A type switch to handle a few explicit types with special semantics. switch t := arg.(type) { // Datums are passed along as is. case parser.Datum: return t, true // Time datatypes get special representation in the database. case time.Time: return parser.DTimestamp{Time: t}, true case time.Duration: return parser.DInterval{Duration: t}, true case *inf.Dec: dd := &parser.DDecimal{} dd.Set(t) return dd, true } // Handle all types which have an underlying type that can be stored in the // database. // Note: if this reflection becomes a performance concern in the future, // commonly used types could be added explicitly into the type switch above // for a performance gain. val := reflect.ValueOf(arg) switch val.Kind() { case reflect.Bool: return parser.DBool(val.Bool()), true case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return parser.DInt(val.Int()), true case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return parser.DInt(val.Uint()), true case reflect.Float32, reflect.Float64: return parser.DFloat(val.Float()), true case reflect.String: return parser.DString(val.String()), true case reflect.Slice: // Handle byte slices. if val.Type().Elem().Kind() == reflect.Uint8 { return parser.DBytes(val.Bytes()), true } } panic(fmt.Sprintf("unexpected type %T", arg)) }
func (a *stddevAggregate) result() (parser.Datum, error) { variance, err := a.varianceAggregate.result() if err != nil || variance == parser.DNull { return variance, err } switch t := variance.(type) { case parser.DFloat: return parser.DFloat(math.Sqrt(float64(t))), nil } return nil, util.Errorf("unexpected variance result type: %s", variance.Type()) }
func (a *avgAggregate) result() (parser.Datum, error) { sum, err := a.sumAggregate.result() if err != nil { return parser.DNull, err } if sum == parser.DNull { return sum, nil } switch t := sum.(type) { case parser.DInt: // TODO(nvanbenschoten) decimal: this should be a numeric, once // better type coercion semantics are defined. return parser.DFloat(t) / parser.DFloat(a.count), nil case parser.DFloat: return t / parser.DFloat(a.count), nil case parser.DDecimal: return parser.DDecimal{Decimal: t.Div(decimal.New(int64(a.count), 0))}, nil default: return parser.DNull, util.Errorf("unexpected SUM result type: %s", t.Type()) } }
// prettyKey pretty-prints the specified key, skipping over the first skip // fields. func prettyKey(key roachpb.Key, skip int) string { if !bytes.HasPrefix(key, keys.TableDataPrefix) { return fmt.Sprintf("index key missing table data prefix: %q vs %q", key, keys.TableDataPrefix) } key = key[len(keys.TableDataPrefix):] var buf bytes.Buffer for k := 0; len(key) > 0; k++ { var d interface{} var err error switch encoding.PeekType(key) { case encoding.Null: key, _ = encoding.DecodeIfNull(key) d = parser.DNull case encoding.NotNull: key, _ = encoding.DecodeIfNotNull(key) d = "#" case encoding.Int: var i int64 key, i, err = encoding.DecodeVarint(key) d = parser.DInt(i) case encoding.Float: var f float64 key, f, err = encoding.DecodeFloat(key, nil) d = parser.DFloat(f) case encoding.Bytes: var s string key, s, err = encoding.DecodeString(key, nil) d = parser.DString(s) case encoding.Time: var t time.Time key, t, err = encoding.DecodeTime(key) d = parser.DTimestamp{Time: t} default: // This shouldn't ever happen, but if it does let the loop exit. key = nil d = "unknown" } if skip > 0 { skip-- continue } if err != nil { fmt.Fprintf(&buf, "/<%v>", err) continue } fmt.Fprintf(&buf, "/%s", d) } return buf.String() }
func unmarshalValue(col structured.ColumnDescriptor, kv client.KeyValue) parser.Datum { if kv.Exists() { switch col.Type.Kind { case structured.ColumnType_BIT, structured.ColumnType_INT: return parser.DInt(kv.ValueInt()) case structured.ColumnType_FLOAT: return parser.DFloat(math.Float64frombits(uint64(kv.ValueInt()))) case structured.ColumnType_CHAR, structured.ColumnType_TEXT, structured.ColumnType_BLOB: return parser.DString(kv.ValueBytes()) } } return parser.DNull }
func decodeIndexKey(desc *structured.TableDescriptor, index structured.IndexDescriptor, vals map[string]parser.Datum, key []byte) ([]byte, error) { if !bytes.HasPrefix(key, keys.TableDataPrefix) { return nil, fmt.Errorf("%s: invalid key prefix: %q", desc.Name, key) } key = bytes.TrimPrefix(key, keys.TableDataPrefix) var tableID uint64 key, tableID = encoding.DecodeUvarint(key) if uint32(tableID) != desc.ID { return nil, fmt.Errorf("%s: unexpected table ID: %d != %d", desc.Name, desc.ID, tableID) } var indexID uint64 key, indexID = encoding.DecodeUvarint(key) if uint32(indexID) != index.ID { return nil, fmt.Errorf("%s: unexpected index ID: %d != %d", desc.Name, index.ID, indexID) } for _, id := range index.ColumnIDs { col, err := desc.FindColumnByID(id) if err != nil { return nil, err } switch col.Type.Kind { case structured.ColumnType_BIT, structured.ColumnType_INT: var i int64 key, i = encoding.DecodeVarint(key) vals[col.Name] = parser.DInt(i) case structured.ColumnType_FLOAT: var f float64 key, f = encoding.DecodeNumericFloat(key) vals[col.Name] = parser.DFloat(f) case structured.ColumnType_CHAR, structured.ColumnType_TEXT, structured.ColumnType_BLOB: var r []byte key, r = encoding.DecodeBytes(key, nil) vals[col.Name] = parser.DString(r) default: return nil, util.Errorf("TODO(pmattis): decoded index key: %s", col.Type.Kind) } } return key, nil }
// Arg implements the Args interface func (p parameters) Arg(i int) (parser.Datum, bool) { if i < 1 || i > len(p) { return nil, false } switch t := p[i-1].GetValue().(type) { case *bool: return parser.DBool(*t), true case *int: return parser.DInt(*t), true case *float64: return parser.DFloat(*t), true case []byte: return parser.DString(t), true case *string: return parser.DString(*t), true } return parser.DNull{}, true }
// Arg implements the parser.Args interface. func (p parameters) Arg(name string) (parser.Datum, bool) { if len(name) == 0 { // This shouldn't happen unless the parser let through an invalid parameter // specification. panic(fmt.Sprintf("invalid empty parameter name")) } if ch := name[0]; ch < '0' || ch > '9' { // TODO(pmattis): Add support for named parameters (vs the numbered // parameter support below). return nil, false } i, err := strconv.ParseInt(name, 10, 0) if err != nil { return nil, false } if i < 1 || int(i) > len(p) { return nil, false } arg := p[i-1].Payload if arg == nil { return parser.DNull, true } switch t := arg.(type) { case *driver.Datum_BoolVal: return parser.DBool(t.BoolVal), true case *driver.Datum_IntVal: return parser.DInt(t.IntVal), true case *driver.Datum_FloatVal: return parser.DFloat(t.FloatVal), true case *driver.Datum_BytesVal: return parser.DBytes(t.BytesVal), true case *driver.Datum_StringVal: return parser.DString(t.StringVal), true case *driver.Datum_DateVal: return parser.DDate(t.DateVal), true case *driver.Datum_TimeVal: return parser.DTimestamp{Time: t.TimeVal.GoTime()}, true case *driver.Datum_IntervalVal: return parser.DInterval{Duration: time.Duration(t.IntervalVal)}, true default: panic(fmt.Sprintf("unexpected type %T", t)) } }
// Arg implements the Args interface func (p parameters) Arg(i int) (parser.Datum, bool) { if i < 1 || i > len(p) { return parser.DNull{}, false } d := p[i-1] if d.BoolVal != nil { return parser.DBool(*d.BoolVal), true } else if d.IntVal != nil { return parser.DInt(*d.IntVal), true } else if d.FloatVal != nil { return parser.DFloat(*d.FloatVal), true } else if d.BytesVal != nil { // TODO(vivek): Add DBytes return parser.DString(d.BytesVal), true } else if d.StringVal != nil { return parser.DString(*d.StringVal), true } return parser.DNull{}, false }
// RandDatum generates a random Datum of the given type. // If null is true, the datum can be DNull. func RandDatum(rng *rand.Rand, typ ColumnType_Kind, null bool) parser.Datum { if null && rng.Intn(10) == 0 { return parser.DNull } switch typ { case ColumnType_BOOL: return parser.MakeDBool(rng.Intn(2) == 1) case ColumnType_INT: return parser.NewDInt(parser.DInt(rng.Int63())) case ColumnType_FLOAT: return parser.NewDFloat(parser.DFloat(rng.NormFloat64())) case ColumnType_DECIMAL: d := &parser.DDecimal{} d.Dec.SetScale(inf.Scale(rng.Intn(40) - 20)) d.Dec.SetUnscaled(rng.Int63()) return d case ColumnType_DATE: return parser.NewDDate(parser.DDate(rng.Intn(10000))) case ColumnType_TIMESTAMP: return &parser.DTimestamp{Time: time.Unix(rng.Int63n(1000000), rng.Int63n(1000000))} case ColumnType_INTERVAL: return &parser.DInterval{Duration: duration.Duration{Months: rng.Int63n(1000), Days: rng.Int63n(1000), Nanos: rng.Int63n(1000000), }} case ColumnType_STRING: // Generate a random ASCII string. p := make([]byte, rng.Intn(10)) for i := range p { p[i] = byte(1 + rng.Intn(127)) } return parser.NewDString(string(p)) case ColumnType_BYTES: p := make([]byte, rng.Intn(10)) _, _ = rng.Read(p) return parser.NewDBytes(parser.DBytes(p)) case ColumnType_TIMESTAMPTZ: return &parser.DTimestampTZ{Time: time.Unix(rng.Int63n(1000000), rng.Int63n(1000000))} default: panic(fmt.Sprintf("invalid type %s", typ)) } }
func (n *scanNode) unmarshalValue(kv client.KeyValue) (parser.Datum, bool) { kind, ok := n.colKind[n.colID] if !ok { n.err = fmt.Errorf("column-id \"%d\" does not exist", n.colID) return nil, false } if kv.Exists() { switch kind { case ColumnType_INT: return parser.DInt(kv.ValueInt()), true case ColumnType_BOOL: return parser.DBool(kv.ValueInt() != 0), true case ColumnType_FLOAT: return parser.DFloat(math.Float64frombits(uint64(kv.ValueInt()))), true case ColumnType_STRING, ColumnType_BYTES: return parser.DString(kv.ValueBytes()), true } } return parser.DNull, true }
func makeKeyVals(desc *TableDescriptor, columnIDs []ColumnID) ([]parser.Datum, error) { vals := make([]parser.Datum, len(columnIDs)) for i, id := range columnIDs { col, err := desc.FindColumnByID(id) if err != nil { return nil, err } switch col.Type.Kind { // TODO(pmattis): ColumnType_BOOL. case ColumnType_INT: vals[i] = parser.DInt(0) case ColumnType_FLOAT: vals[i] = parser.DFloat(0) case ColumnType_STRING, ColumnType_BYTES: vals[i] = parser.DString("") default: return nil, util.Errorf("TODO(pmattis): decoded index key: %s", col.Type.Kind) } } return vals, nil }
// decodeIndexKey decodes the values that are a part of the specified index // key. Vals is a slice returned from makeIndexKeyVals. The remaining bytes in // the index key are returned which will either be an encoded column ID for the // primary key index, the primary key suffix for non-unique secondary indexes // or unique secondary indexes containing NULL or empty. func decodeIndexKey(desc *structured.TableDescriptor, index structured.IndexDescriptor, vals []parser.Datum, key []byte) ([]byte, error) { if !bytes.HasPrefix(key, keys.TableDataPrefix) { return nil, fmt.Errorf("%s: invalid key prefix: %q", desc.Name, key) } key = bytes.TrimPrefix(key, keys.TableDataPrefix) var tableID uint64 key, tableID = encoding.DecodeUvarint(key) if structured.ID(tableID) != desc.ID { return nil, fmt.Errorf("%s: unexpected table ID: %d != %d", desc.Name, desc.ID, tableID) } var indexID uint64 key, indexID = encoding.DecodeUvarint(key) if structured.IndexID(indexID) != index.ID { return nil, fmt.Errorf("%s: unexpected index ID: %d != %d", desc.Name, index.ID, indexID) } for j := range vals { switch vals[j].(type) { case parser.DInt: var i int64 key, i = encoding.DecodeVarint(key) vals[j] = parser.DInt(i) case parser.DFloat: var f float64 key, f = encoding.DecodeNumericFloat(key) vals[j] = parser.DFloat(f) case parser.DString: var r []byte key, r = encoding.DecodeBytes(key, nil) vals[j] = parser.DString(r) default: return nil, util.Errorf("TODO(pmattis): decoded index key: %s", vals[j].Type()) } } return key, nil }