// 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 *sumAggregate) result() (parser.Datum, error) { if a.sum == nil { return parser.DNull, nil } switch t := a.sum.(type) { case parser.DDecimal: dd := parser.DDecimal{} dd.Set(&t.Dec) return dd, nil default: return a.sum, nil } }
func (a *sumAggregate) add(datum parser.Datum) error { if datum == parser.DNull { return nil } if a.sum == nil { switch t := datum.(type) { case parser.DDecimal: // Make copy of decimal to allow for modification later. dd := parser.DDecimal{} dd.Set(&t.Dec) datum = dd } a.sum = datum return nil } switch t := datum.(type) { case parser.DInt: if v, ok := a.sum.(parser.DInt); ok { a.sum = v + t return nil } case parser.DFloat: if v, ok := a.sum.(parser.DFloat); ok { a.sum = v + t return nil } case parser.DDecimal: if v, ok := a.sum.(parser.DDecimal); ok { v.Add(&v.Dec, &t.Dec) a.sum = v return nil } } return util.Errorf("unexpected SUM argument type: %s", datum.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 *roachpb.Value) (parser.Datum, *roachpb.Error) { if value == nil { return parser.DNull, nil } switch kind { case ColumnType_BOOL: v, err := value.GetInt() if err != nil { return nil, roachpb.NewError(err) } return parser.DBool(v != 0), nil case ColumnType_INT: v, err := value.GetInt() if err != nil { return nil, roachpb.NewError(err) } return parser.DInt(v), nil case ColumnType_FLOAT: v, err := value.GetFloat() if err != nil { return nil, roachpb.NewError(err) } return parser.DFloat(v), nil case ColumnType_DECIMAL: v, err := value.GetDecimal() if err != nil { return nil, roachpb.NewError(err) } dd := parser.DDecimal{} dd.Set(v) return dd, nil case ColumnType_STRING: v, err := value.GetBytes() if err != nil { return nil, roachpb.NewError(err) } return parser.DString(v), nil case ColumnType_BYTES: v, err := value.GetBytes() if err != nil { return nil, roachpb.NewError(err) } return parser.DBytes(v), nil case ColumnType_DATE: v, err := value.GetInt() if err != nil { return nil, roachpb.NewError(err) } return parser.DDate(v), nil case ColumnType_TIMESTAMP: v, err := value.GetTime() if err != nil { return nil, roachpb.NewError(err) } return parser.DTimestamp{Time: v}, nil case ColumnType_INTERVAL: v, err := value.GetInt() if err != nil { return nil, roachpb.NewError(err) } return parser.DInterval{Duration: time.Duration(v)}, nil default: return nil, roachpb.NewErrorf("unsupported column type: %s", kind) } }
func decodeTableKey(valType parser.Datum, key []byte, dir encoding.Direction) ( parser.Datum, []byte, error) { if (dir != encoding.Ascending) && (dir != encoding.Descending) { return nil, nil, util.Errorf("invalid direction: %d", dir) } var isNull bool if key, isNull = encoding.DecodeIfNull(key); isNull { return parser.DNull, key, nil } var rkey []byte var err error switch valType.(type) { case parser.DBool: var i int64 if dir == encoding.Ascending { rkey, i, err = encoding.DecodeVarintAscending(key) } else { rkey, i, err = encoding.DecodeVarintDescending(key) } return parser.DBool(i != 0), rkey, err case parser.DInt: var i int64 if dir == encoding.Ascending { rkey, i, err = encoding.DecodeVarintAscending(key) } else { rkey, i, err = encoding.DecodeVarintDescending(key) } return parser.DInt(i), rkey, err case parser.DFloat: var f float64 if dir == encoding.Ascending { rkey, f, err = encoding.DecodeFloatAscending(key, nil) } else { rkey, f, err = encoding.DecodeFloatDescending(key, nil) } return parser.DFloat(f), rkey, err case parser.DDecimal: var d *inf.Dec if dir == encoding.Ascending { rkey, d, err = encoding.DecodeDecimalAscending(key, nil) } else { rkey, d, err = encoding.DecodeDecimalDescending(key, nil) } dd := parser.DDecimal{} dd.Set(d) return dd, rkey, err case parser.DString: var r string if dir == encoding.Ascending { rkey, r, err = encoding.DecodeStringAscending(key, nil) } else { rkey, r, err = encoding.DecodeStringDescending(key, nil) } return parser.DString(r), rkey, err case parser.DBytes: var r []byte if dir == encoding.Ascending { rkey, r, err = encoding.DecodeBytesAscending(key, nil) } else { rkey, r, err = encoding.DecodeBytesDescending(key, nil) } return parser.DBytes(r), rkey, err case parser.DDate: var t int64 if dir == encoding.Ascending { rkey, t, err = encoding.DecodeVarintAscending(key) } else { rkey, t, err = encoding.DecodeVarintDescending(key) } return parser.DDate(t), rkey, err case parser.DTimestamp: var t time.Time if dir == encoding.Ascending { rkey, t, err = encoding.DecodeTimeAscending(key) } else { rkey, t, err = encoding.DecodeTimeDescending(key) } return parser.DTimestamp{Time: t}, rkey, err case parser.DInterval: var d int64 if dir == encoding.Ascending { rkey, d, err = encoding.DecodeVarintAscending(key) } else { rkey, d, err = encoding.DecodeVarintDescending(key) } return parser.DInterval{Duration: time.Duration(d)}, rkey, err default: return nil, nil, util.Errorf("TODO(pmattis): decoded index key: %s", valType.Type()) } }