// Copyright 2014 The ql Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ql import ( "bytes" "fmt" "io" "math" "math/big" "time" ) // QL types. const ( qBool = 0x62 // 'b' qComplex64 = 0x63 // 'c' qComplex128 = 0x64 // 'd' qFloat32 = 0x66 // 'f' qFloat64 = 0x67 // 'g', alias float qInt8 = 0x69 // 'i' qInt16 = 0x6a // 'j' qInt32 = 0x6b // 'k' qInt64 = 0x6c // 'l', alias int qString = 0x73 // 's' qUint8 = 0x75 // 'u', alias byte qUint16 = 0x76 // 'v' qUint32 = 0x77 // 'w' qUint64 = 0x78 // 'x', alias uint qBigInt = 0x49 // 'I' qBigRat = 0x52 // 'R' qBlob = 0x42 // 'B' qDuration = 0x44 // 'D' qTime = 0x54 // 'T' ) var ( type2Str = map[int]string{ qBigInt: "bigint", qBigRat: "bigrat", qBlob: "blob", qBool: "bool", qComplex128: "complex128", qComplex64: "complex64", qDuration: "duration", qFloat32: "float32", qFloat64: "float64", qInt16: "int16", qInt32: "int32", qInt64: "int64", qInt8: "int8", qString: "string", qTime: "time", qUint16: "uint16", qUint32: "uint32", qUint64: "uint64", qUint8: "uint8", } ) func typeStr(typ int) (r string) { return type2Str[typ] } func noEOF(err error) error { if err == io.EOF { err = nil } return err } func runErr(err error) error { return fmt.Errorf("run time error: %s", err) } func invXOp(s, x interface{}) error { return fmt.Errorf("invalid operation: %v[%v] (index of type %T)", s, x, x) } func invSOp(s interface{}) error { return fmt.Errorf("cannot slice %s (type %T)", s, s) } func invNegX(x interface{}) error { return fmt.Errorf("invalid string index %v (index must be non-negative)", x) } func invNegLO(x interface{}) error { return fmt.Errorf("invalid LIMIT or OFFSET value %v (must be non-negative)", x) } func invSliceNegX(x interface{}) error { return fmt.Errorf("invalid slice index %v (index must be non-negative)", x) } func invBoundX(s string, x uint64) error { return fmt.Errorf("invalid string index %d (out of bounds for %d-byte string)", x, len(s)) } func invSliceBoundX(s string, x uint64) error { return fmt.Errorf("invalid slice index %d (out of bounds for %d-byte string)", x, len(s)) } func intExpr(x interface{}) (i int64, err error) { switch x := x.(type) { case idealInt: if x < 0 { return 0, invNegLO(x) } return int64(x), nil case idealRune: if x < 0 { return 0, invNegLO(x) } return int64(x), nil case idealUint: if x < 0 { return 0, invNegLO(x) } return int64(x), nil case int8: if x < 0 { return 0, invNegLO(x) } return int64(x), nil case int16: if x < 0 { return 0, invNegLO(x) } return int64(x), nil case int32: if x < 0 { return 0, invNegLO(x) } return int64(x), nil case int64: if x < 0 { return 0, invNegLO(x) } return int64(x), nil case uint8: return int64(x), nil case uint16: return int64(x), nil case uint32: return int64(x), nil case uint64: return int64(x), nil default: return 0, fmt.Errorf("non-integer expression: %v (value of type %T)", x, x) } } func limOffExpr(x interface{}) (i uint64, err error) { switch x := x.(type) { case idealInt: if x < 0 { return 0, invNegLO(x) } return uint64(x), nil case idealRune: if x < 0 { return 0, invNegLO(x) } return uint64(x), nil case idealUint: if x < 0 { return 0, invNegLO(x) } return uint64(x), nil case int8: if x < 0 { return 0, invNegLO(x) } return uint64(x), nil case int16: if x < 0 { return 0, invNegLO(x) } return uint64(x), nil case int32: if x < 0 { return 0, invNegLO(x) } return uint64(x), nil case int64: if x < 0 { return 0, invNegLO(x) } return uint64(x), nil case uint8: return uint64(x), nil case uint16: return uint64(x), nil case uint32: return uint64(x), nil case uint64: return uint64(x), nil default: return 0, fmt.Errorf("non-integer used in LIMIT or OFFSET: %v (value of type %T)", x, x) } } func indexExpr(s *string, x interface{}) (i uint64, err error) { switch x := x.(type) { case idealFloat: if x < 0 { return 0, invNegX(x) } if s != nil && int(x) >= len(*s) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case idealInt: if x < 0 { return 0, invNegX(x) } if s != nil && int64(x) >= int64(len(*s)) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case idealRune: if x < 0 { return 0, invNegX(x) } if s != nil && int32(x) >= int32(len(*s)) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case idealUint: if x < 0 { return 0, invNegX(x) } if s != nil && uint64(x) >= uint64(len(*s)) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case int8: if x < 0 { return 0, invNegX(x) } if s != nil && int(x) >= len(*s) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case int16: if x < 0 { return 0, invNegX(x) } if s != nil && int(x) >= len(*s) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case int32: if x < 0 { return 0, invNegX(x) } if s != nil && int(x) >= len(*s) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case int64: if x < 0 { return 0, invNegX(x) } if s != nil && x >= int64(len(*s)) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case uint8: if s != nil && int(x) >= len(*s) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case uint16: if s != nil && int(x) >= len(*s) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case uint32: if s != nil && x >= uint32(len(*s)) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil case uint64: if s != nil && x >= uint64(len(*s)) { return 0, invBoundX(*s, uint64(x)) } return uint64(x), nil default: return 0, fmt.Errorf("non-integer string index %v (value of type %T)", x, x) } } func sliceExpr(s *string, x interface{}, mod int) (i uint64, err error) { switch x := x.(type) { case idealFloat: if x < 0 { return 0, invSliceNegX(x) } if s != nil && int(x) >= len(*s)+mod { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case idealInt: if x < 0 { return 0, invSliceNegX(x) } if s != nil && int64(x) >= int64(len(*s)+mod) { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case idealRune: if x < 0 { return 0, invSliceNegX(x) } if s != nil && int32(x) >= int32(len(*s)+mod) { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case idealUint: if x < 0 { return 0, invSliceNegX(x) } if s != nil && uint64(x) >= uint64(len(*s)+mod) { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case int8: if x < 0 { return 0, invSliceNegX(x) } if s != nil && int(x) >= len(*s)+mod { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case int16: if x < 0 { return 0, invSliceNegX(x) } if s != nil && int(x) >= len(*s)+mod { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case int32: if x < 0 { return 0, invSliceNegX(x) } if s != nil && int(x) >= len(*s)+mod { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case int64: if x < 0 { return 0, invSliceNegX(x) } if s != nil && x >= int64(len(*s)+mod) { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case uint8: if s != nil && int(x) >= len(*s)+mod { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case uint16: if s != nil && int(x) >= len(*s)+mod { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case uint32: if s != nil && x >= uint32(len(*s)+mod) { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil case uint64: if s != nil && x >= uint64(len(*s)+mod) { return 0, invSliceBoundX(*s, uint64(x)) } return uint64(x), nil default: return 0, fmt.Errorf("invalid slice index %s (type %T)", x, x) } } type iop int func (o iop) String() string { switch i := int(o); i { case andand: return "&&" case andnot: return "&^" case lsh: return "<<" case le: return "<=" case eq: return "==" case ge: return ">=" case neq: return "!=" case oror: return "||" case rsh: return ">>" default: return string(i) } } func ideal(v interface{}) interface{} { switch x := v.(type) { case idealComplex: return complex128(x) case idealFloat: return float64(x) case idealInt: return int64(x) case idealRune: return int64(x) case idealUint: return uint64(x) default: return v } } func eval(v expression, execCtx *execCtx, ctx map[interface{}]interface{}) (y interface{}) { y, err := expand1(v.eval(execCtx, ctx)) if err != nil { panic(err) // panic ok here } return } func eval2(a, b expression, execCtx *execCtx, ctx map[interface{}]interface{}) (x, y interface{}) { return eval(a, execCtx, ctx), eval(b, execCtx, ctx) } func invOp2(x, y interface{}, o int) (interface{}, error) { return nil, fmt.Errorf("invalid operation: %v %v %v (mismatched types %T and %T)", x, iop(o), y, ideal(x), ideal(y)) } func undOp(x interface{}, o int) (interface{}, error) { return nil, fmt.Errorf("invalid operation: %v%v (operator %v not defined on %T)", iop(o), x, iop(o), x) } func undOp2(x, y interface{}, o int) (interface{}, error) { return nil, fmt.Errorf("invalid operation: %v %v %v (operator %v not defined on %T)", x, iop(o), y, iop(o), x) } func invConv(val interface{}, typ int) (interface{}, error) { return nil, fmt.Errorf("cannot convert %v (type %T) to type %s", val, val, typeStr(typ)) } func truncConv(val interface{}) (interface{}, error) { return nil, fmt.Errorf("constant %v truncated to integer", val) } func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE if val == nil { return nil, nil } switch typ { case qBool: switch x := val.(type) { //case nil: //case idealComplex: //case idealFloat: //case idealInt: //case idealRune: //case idealUint: case bool: return bool(x), nil //case complex64: //case complex128: //case float32: //case float64: //case int8: //case int16: //case int32: //case int64: //case string: //case uint8: //case uint16: //case uint32: //case uint64: default: return invConv(val, typ) } case qComplex64: switch x := val.(type) { //case nil: case idealComplex: return complex64(x), nil case idealFloat: return complex(float32(x), 0), nil case idealInt: return complex(float32(x), 0), nil case idealRune: return complex(float32(x), 0), nil case idealUint: return complex(float32(x), 0), nil //case bool: case complex64: return complex64(x), nil case complex128: return complex64(x), nil //case float32: //case float64: //case int8: //case int16: //case int32: //case int64: //case string: //case uint8: //case uint16: //case uint32: //case uint64: default: return invConv(val, typ) } case qComplex128: switch x := val.(type) { //case nil: case idealComplex: return complex128(x), nil case idealFloat: return complex(float64(x), 0), nil case idealInt: return complex(float64(x), 0), nil case idealRune: return complex(float64(x), 0), nil case idealUint: return complex(float64(x), 0), nil //case bool: case complex64: return complex128(x), nil case complex128: return complex128(x), nil //case float32: //case float64: //case int8: //case int16: //case int32: //case int64: //case string: //case uint8: //case uint16: //case uint32: //case uint64: default: return invConv(val, typ) } case qFloat32: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: return float32(x), nil case idealInt: return float32(x), nil case idealRune: return float32(x), nil case idealUint: return float32(x), nil //case bool: //case complex64: //case complex128: case float32: return float32(x), nil case float64: return float32(x), nil case int8: return float32(x), nil case int16: return float32(x), nil case int32: return float32(x), nil case int64: return float32(x), nil //case string: case uint8: return float32(x), nil case uint16: return float32(x), nil case uint32: return float32(x), nil case uint64: return float32(x), nil case *big.Int: v, _ := big.NewRat(1, 1).SetInt(x).Float64() return float32(v), nil case *big.Rat: v, _ := x.Float64() return float32(v), nil case time.Duration: return float32(x), nil default: return invConv(val, typ) } case qFloat64: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: return float64(x), nil case idealInt: return float64(x), nil case idealRune: return float64(x), nil case idealUint: return float64(x), nil //case bool: //case complex64: //case complex128: case float32: return float64(x), nil case float64: return float64(x), nil case int8: return float64(x), nil case int16: return float64(x), nil case int32: return float64(x), nil case int64: return float64(x), nil //case string: case uint8: return float64(x), nil case uint16: return float64(x), nil case uint32: return float64(x), nil case uint64: return float64(x), nil case *big.Int: v, _ := big.NewRat(1, 1).SetInt(x).Float64() return v, nil case *big.Rat: v, _ := x.Float64() return v, nil case time.Duration: return float64(x), nil default: return invConv(val, typ) } case qInt8: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: if _, frac := math.Modf(float64(x)); frac != 0 { return truncConv(x) } return int8(x), nil case idealInt: return int8(x), nil case idealRune: return int8(x), nil case idealUint: return int8(x), nil //case bool: //case complex64: //case complex128: case float32: return int8(x), nil case float64: return int8(x), nil case int8: return int8(x), nil case int16: return int8(x), nil case int32: return int8(x), nil case int64: return int8(x), nil //case string: case uint8: return int8(x), nil case uint16: return int8(x), nil case uint32: return int8(x), nil case uint64: return int8(x), nil case *big.Int: return int8(x.Int64()), nil case time.Duration: return int8(x), nil default: return invConv(val, typ) } case qInt16: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: if _, frac := math.Modf(float64(x)); frac != 0 { return truncConv(x) } return int16(x), nil case idealInt: return int16(x), nil case idealRune: return int16(x), nil case idealUint: return int16(x), nil //case bool: //case complex64: //case complex128: case float32: return int16(x), nil case float64: return int16(x), nil case int8: return int16(x), nil case int16: return int16(x), nil case int32: return int16(x), nil case int64: return int16(x), nil //case string: case uint8: return int16(x), nil case uint16: return int16(x), nil case uint32: return int16(x), nil case uint64: return int16(x), nil case *big.Int: return int16(x.Int64()), nil case time.Duration: return int16(x), nil default: return invConv(val, typ) } case qInt32: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: if _, frac := math.Modf(float64(x)); frac != 0 { return truncConv(x) } return int32(x), nil case idealInt: return int32(x), nil case idealRune: return int32(x), nil case idealUint: return int32(x), nil //case bool: //case complex64: //case complex128: case float32: return int32(x), nil case float64: return int32(x), nil case int8: return int32(x), nil case int16: return int32(x), nil case int32: return int32(x), nil case int64: return int32(x), nil //case string: case uint8: return int32(x), nil case uint16: return int32(x), nil case uint32: return int32(x), nil case uint64: return int32(x), nil case *big.Int: return int32(x.Int64()), nil case time.Duration: return int32(x), nil default: return invConv(val, typ) } case qInt64: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: if _, frac := math.Modf(float64(x)); frac != 0 { return truncConv(x) } return int64(x), nil case idealInt: return int64(x), nil case idealRune: return int64(x), nil case idealUint: return int64(x), nil //case bool: //case complex64: //case complex128: case float32: return int64(x), nil case float64: return int64(x), nil case int8: return int64(x), nil case int16: return int64(x), nil case int32: return int64(x), nil case int64: return int64(x), nil //case string: case uint8: return int64(x), nil case uint16: return int64(x), nil case uint32: return int64(x), nil case uint64: return int64(x), nil case *big.Int: return x.Int64(), nil case time.Duration: return int64(x), nil default: return invConv(val, typ) } case qString: switch x := val.(type) { //case nil: //case idealComplex: //case idealFloat: case idealInt: return string(x), nil case idealRune: return string(x), nil case idealUint: return string(x), nil //case bool: //case complex64: //case complex128: //case float32: //case float64: case int8: return string(x), nil case int16: return string(x), nil case int32: return string(x), nil case int64: return string(x), nil case string: return string(x), nil case uint8: return string(x), nil case uint16: return string(x), nil case uint32: return string(x), nil case uint64: return string(x), nil case []byte: return string(x), nil case *big.Int: return x.String(), nil case time.Time: return x.String(), nil case time.Duration: return x.String(), nil default: return invConv(val, typ) } case qUint8: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: if _, frac := math.Modf(float64(x)); frac != 0 { return truncConv(x) } return uint8(x), nil case idealInt: return uint8(x), nil case idealRune: return uint8(x), nil case idealUint: return uint8(x), nil //case bool: //case complex64: //case complex128: case float32: return uint8(x), nil case float64: return uint8(x), nil case int8: return uint8(x), nil case int16: return uint8(x), nil case int32: return uint8(x), nil case int64: return uint8(x), nil //case string: case uint8: return uint8(x), nil case uint16: return uint8(x), nil case uint32: return uint8(x), nil case uint64: return uint8(x), nil case *big.Int: return uint8(x.Int64()), nil case time.Duration: return uint8(x), nil default: return invConv(val, typ) } case qUint16: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: if _, frac := math.Modf(float64(x)); frac != 0 { return truncConv(x) } return uint16(x), nil case idealInt: return uint16(x), nil case idealRune: return uint16(x), nil case idealUint: return uint16(x), nil //case bool: //case complex64: //case complex128: case float32: return uint16(x), nil case float64: return uint16(x), nil case int8: return uint16(x), nil case int16: return uint16(x), nil case int32: return uint16(x), nil case int64: return uint16(x), nil //case string: case uint8: return uint16(x), nil case uint16: return uint16(x), nil case uint32: return uint16(x), nil case uint64: return uint16(x), nil case *big.Int: return uint16(x.Int64()), nil case time.Duration: return uint16(x), nil default: return invConv(val, typ) } case qUint32: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: if _, frac := math.Modf(float64(x)); frac != 0 { return truncConv(x) } return uint32(x), nil case idealInt: return uint32(x), nil case idealRune: return uint32(x), nil case idealUint: return uint32(x), nil //case bool: //case complex64: //case complex128: case float32: return uint32(x), nil case float64: return uint32(x), nil case int8: return uint32(x), nil case int16: return uint32(x), nil case int32: return uint32(x), nil case int64: return uint32(x), nil //case string: case uint8: return uint32(x), nil case uint16: return uint32(x), nil case uint32: return uint32(x), nil case uint64: return uint32(x), nil case *big.Int: return uint32(x.Int64()), nil case time.Duration: return uint32(x), nil default: return invConv(val, typ) } case qUint64: switch x := val.(type) { //case nil: //case idealComplex: case idealFloat: if _, frac := math.Modf(float64(x)); frac != 0 { return truncConv(x) } return uint64(x), nil case idealInt: return uint64(x), nil case idealRune: return uint64(x), nil case idealUint: return uint64(x), nil //case bool: //case complex64: //case complex128: case float32: return uint64(x), nil case float64: return uint64(x), nil case int8: return uint64(x), nil case int16: return uint64(x), nil case int32: return uint64(x), nil case int64: return uint64(x), nil //case string: case uint8: return uint64(x), nil case uint16: return uint64(x), nil case uint32: return uint64(x), nil case uint64: return uint64(x), nil case *big.Int: return x.Uint64(), nil case time.Duration: return uint64(x), nil default: return invConv(val, typ) } case qBlob: switch x := val.(type) { case string: return []byte(x), nil case []byte: return x, nil default: return invConv(val, typ) } case qBigInt: switch x := val.(type) { // case blob // case bool //case idealComplex: case idealFloat: if _, frac := math.Modf(float64(x)); frac != 0 { return truncConv(x) } rr := big.NewRat(1, 1).SetFloat64(float64(x)) ii := big.NewInt(0).Set(rr.Num()) ii.Quo(ii, rr.Denom()) return ii, nil case idealInt: return big.NewInt(0).SetInt64(int64(x)), nil case idealRune: return big.NewInt(0).SetInt64(int64(x)), nil case idealUint: return big.NewInt(0).SetUint64(uint64(x)), nil //case complex64 //case complex128 case float32: rr := big.NewRat(1, 1).SetFloat64(float64(x)) ii := big.NewInt(0).Set(rr.Num()) ii.Quo(ii, rr.Denom()) return ii, nil case float64: rr := big.NewRat(1, 1).SetFloat64(float64(x)) ii := big.NewInt(0).Set(rr.Num()) ii.Quo(ii, rr.Denom()) return ii, nil case int8: return big.NewInt(0).SetInt64(int64(x)), nil case int16: return big.NewInt(0).SetInt64(int64(x)), nil case int32: return big.NewInt(0).SetInt64(int64(x)), nil case int64: return big.NewInt(0).SetInt64(x), nil case string: y := big.NewInt(0) if _, ok := y.SetString(x, 0); !ok { return invConv(val, typ) } return y, nil case uint8: return big.NewInt(0).SetUint64(uint64(x)), nil case uint16: return big.NewInt(0).SetUint64(uint64(x)), nil case uint32: return big.NewInt(0).SetUint64(uint64(x)), nil case uint64: return big.NewInt(0).SetUint64(x), nil case *big.Int: return x, nil case *big.Rat: ii := big.NewInt(0).Set(x.Num()) ii.Div(ii, x.Denom()) return ii, nil default: return invConv(val, typ) } case qBigRat: switch x := val.(type) { // case blob // case bool //case idealComplex: case idealFloat: return big.NewRat(1, 1).SetFloat64(float64(x)), nil case idealInt: return big.NewRat(1, 1).SetInt64(int64(x)), nil case idealRune: return big.NewRat(1, 1).SetInt64(int64(x)), nil case idealUint: return big.NewRat(1, 1).SetInt(big.NewInt(0).SetUint64(uint64(x))), nil //case complex64 //case complex128 case float32: return big.NewRat(1, 1).SetFloat64(float64(x)), nil case float64: return big.NewRat(1, 1).SetFloat64(x), nil case int8: return big.NewRat(1, 1).SetInt64(int64(x)), nil case int16: return big.NewRat(1, 1).SetInt64(int64(x)), nil case int32: return big.NewRat(1, 1).SetInt64(int64(x)), nil case int64: return big.NewRat(1, 1).SetInt64(x), nil case string: y := big.NewRat(1, 1) if _, ok := y.SetString(x); !ok { return invConv(val, typ) } return y, nil case uint8: return big.NewRat(1, 1).SetInt64(int64(x)), nil case uint16: return big.NewRat(1, 1).SetInt64(int64(x)), nil case uint32: return big.NewRat(1, 1).SetInt64(int64(x)), nil case uint64: return big.NewRat(1, 1).SetInt(big.NewInt(0).SetUint64(x)), nil case *big.Int: return big.NewRat(1, 1).SetInt(x), nil case *big.Rat: return x, nil default: return invConv(val, typ) } case qDuration: switch x := val.(type) { // case blob // case bool //case idealComplex: case idealFloat: return time.Duration(x), nil case idealInt: return time.Duration(x), nil case idealRune: return time.Duration(x), nil case idealUint: return time.Duration(x), nil //case complex64 //case complex128 case float32: return time.Duration(x), nil case float64: return time.Duration(x), nil case int8: return time.Duration(x), nil case int16: return time.Duration(x), nil case int32: return time.Duration(x), nil case int64: return time.Duration(x), nil case string: return time.ParseDuration(x) case uint8: return time.Duration(x), nil case uint16: return time.Duration(x), nil case uint32: return time.Duration(x), nil case uint64: return time.Duration(x), nil case *big.Int: return time.Duration(x.Int64()), nil case *big.Rat: f, _ := x.Float64() return time.Duration(f), nil case time.Duration: return x, nil default: return invConv(val, typ) } case qTime: switch x := val.(type) { // case blob // case bool //case idealComplex: //case idealFloat: //case idealInt: //case idealRune: //case idealUint: //case complex64 //case complex128 //case float32: //case float64: //case int8: //case int16: //case int32: //case int64: //case string: //case uint8: //case uint16: //case uint32: //case uint64: //case *big.Int: //case *big.Rat: //case time.Duration: case time.Time: return x, nil default: return invConv(val, typ) } default: panic("internal error 006") } } func invShiftRHS(lhs, rhs interface{}) (interface{}, error) { return nil, fmt.Errorf("invalid operation: %v << %v (shift count type %T, must be unsigned integer)", lhs, rhs, rhs) } func invTruncInt(v interface{}) error { return fmt.Errorf("constant %v truncated to integer", v) } func overflow(v interface{}, typ int) error { return fmt.Errorf("constant %v overflows %s", v, typeStr(typ)) } func typeCheck1(val interface{}, c *col) (interface{}, error) { rec := []interface{}{val} c = c.clone() c.index = 0 if err := typeCheck(rec, []*col{c}); err != nil { return nil, err } return rec[0], nil } func typeCheck(rec []interface{}, cols []*col) (err error) { for _, c := range cols { i := c.index if v := rec[i]; !c.typeCheck(v) { switch v.(type) { case idealComplex: y := complex128(v.(idealComplex)) switch c.typ { case qBool: case qComplex64: rec[i] = complex64(y) continue case qComplex128: rec[i] = complex128(y) continue case qFloat32, qFloat64, qInt8, qInt16, qInt32, qInt64, qUint8, qUint16, qUint32, qUint64: return fmt.Errorf("constant %v truncated to real", y) } case idealFloat: y := float64(v.(idealFloat)) switch c.typ { case qBool: case qComplex64: rec[i] = complex(float32(y), 0) continue case qComplex128: rec[i] = complex(float64(y), 0) continue case qFloat32: rec[i] = float32(y) continue case qFloat64: rec[i] = float64(y) continue case qInt8: if math.Floor(y) != y { return invTruncInt(y) } if y < math.MinInt8 || y > math.MaxInt8 { return overflow(y, c.typ) } rec[i] = int8(y) continue case qInt16: if math.Floor(y) != y { return invTruncInt(y) } if y < math.MinInt16 || y > math.MaxInt16 { return overflow(y, c.typ) } rec[i] = int16(y) continue case qInt32: if math.Floor(y) != y { return invTruncInt(y) } if y < math.MinInt32 || y > math.MaxInt32 { return overflow(y, c.typ) } rec[i] = int32(y) continue case qInt64: if math.Floor(y) != y { return invTruncInt(y) } if y < math.MinInt64 || y > math.MaxInt64 { return overflow(y, c.typ) } rec[i] = int64(y) continue case qString: case qUint8: if math.Floor(y) != y { return invTruncInt(y) } if y < 0 || y > math.MaxUint8 { return overflow(y, c.typ) } rec[i] = uint8(y) continue case qUint16: if math.Floor(y) != y { return invTruncInt(y) } if y < 0 || y > math.MaxUint16 { return overflow(y, c.typ) } rec[i] = uint16(y) continue case qUint32: if math.Floor(y) != y { return invTruncInt(y) } if y < 0 || y > math.MaxUint32 { return overflow(y, c.typ) } rec[i] = uint32(y) continue case qUint64: if math.Floor(y) != y { return invTruncInt(y) } if y < 0 || y > math.MaxUint64 { return overflow(y, c.typ) } rec[i] = uint64(y) continue case qBigInt: if math.Floor(y) != y { return invTruncInt(y) } rr := big.NewRat(1, 1).SetFloat64(y) ii := big.NewInt(0) ii.Set(rr.Num()) ii.Quo(ii, rr.Denom()) rec[i] = ii continue case qBigRat: rec[i] = big.NewRat(1, 1).SetFloat64(y) continue } case idealInt: y := int64(v.(idealInt)) switch c.typ { case qBool: case qComplex64: rec[i] = complex(float32(y), 0) continue case qComplex128: rec[i] = complex(float64(y), 0) continue case qFloat32: rec[i] = float32(y) continue case qFloat64: rec[i] = float64(y) continue case qInt8: if y < math.MinInt8 || y > math.MaxInt8 { return overflow(y, c.typ) } rec[i] = int8(y) continue case qInt16: if y < math.MinInt16 || y > math.MaxInt16 { return overflow(y, c.typ) } rec[i] = int16(y) continue case qInt32: if y < math.MinInt32 || y > math.MaxInt32 { return overflow(y, c.typ) } rec[i] = int32(y) continue case qInt64: if y < math.MinInt64 || y > math.MaxInt64 { return overflow(y, c.typ) } rec[i] = int64(y) continue case qString: case qUint8: if y < 0 || y > math.MaxUint8 { return overflow(y, c.typ) } rec[i] = uint8(y) continue case qUint16: if y < 0 || y > math.MaxUint16 { return overflow(y, c.typ) } rec[i] = uint16(y) continue case qUint32: if y < 0 || y > math.MaxUint32 { return overflow(y, c.typ) } rec[i] = uint32(y) continue case qUint64: if y < 0 { return overflow(y, c.typ) } rec[i] = uint64(y) continue case qBigInt: rec[i] = big.NewInt(y) continue case qBigRat: rec[i] = big.NewRat(1, 1).SetInt64(y) continue } case idealRune: y := int64(v.(idealRune)) switch c.typ { case qBool: case qComplex64: rec[i] = complex(float32(y), 0) continue case qComplex128: rec[i] = complex(float64(y), 0) continue case qFloat32: rec[i] = float32(y) continue case qFloat64: rec[i] = float64(y) continue case qInt8: if y < math.MinInt8 || y > math.MaxInt8 { return overflow(y, c.typ) } rec[i] = int8(y) continue case qInt16: if y < math.MinInt16 || y > math.MaxInt16 { return overflow(y, c.typ) } rec[i] = int16(y) continue case qInt32: if y < math.MinInt32 || y > math.MaxInt32 { return overflow(y, c.typ) } rec[i] = int32(y) continue case qInt64: if y < math.MinInt64 || y > math.MaxInt64 { return overflow(y, c.typ) } rec[i] = int64(y) continue case qString: case qUint8: if y < 0 || y > math.MaxUint8 { return overflow(y, c.typ) } rec[i] = uint8(y) continue case qUint16: if y < 0 || y > math.MaxUint16 { return overflow(y, c.typ) } rec[i] = uint16(y) continue case qUint32: if y < 0 { return overflow(y, c.typ) } rec[i] = uint32(y) continue case qUint64: if y < 0 { return overflow(y, c.typ) } rec[i] = uint64(y) continue case qBigInt: rec[i] = big.NewInt(y) continue case qBigRat: rec[i] = big.NewRat(1, 1).SetInt64(y) continue } case idealUint: y := uint64(v.(idealUint)) switch c.typ { case qBool: case qComplex64: rec[i] = complex(float32(y), 0) continue case qComplex128: rec[i] = complex(float64(y), 0) continue case qFloat32: rec[i] = float32(y) continue case qFloat64: rec[i] = float64(y) continue case qInt8: if y > math.MaxInt8 { return overflow(y, c.typ) } rec[i] = int8(y) continue case qInt16: if y > math.MaxInt16 { return overflow(y, c.typ) } rec[i] = int16(y) continue case qInt32: if y > math.MaxInt32 { return overflow(y, c.typ) } rec[i] = int32(y) continue case qInt64: if y > math.MaxInt64 { return overflow(y, c.typ) } rec[i] = int64(y) continue case qString: rec[i] = string(y) continue case qUint8: if y > math.MaxUint8 { return overflow(y, c.typ) } rec[i] = uint8(y) continue case qUint16: if y > math.MaxUint16 { return overflow(y, c.typ) } rec[i] = uint16(y) continue case qUint32: if y > math.MaxUint32 { return overflow(y, c.typ) } rec[i] = uint32(y) continue case qUint64: rec[i] = uint64(y) continue case qBigInt: rec[i] = big.NewInt(0).SetUint64(y) continue case qBigRat: ii := big.NewInt(0).SetUint64(y) rec[i] = big.NewRat(1, 1).SetInt(ii) continue } } return fmt.Errorf("cannot use %v (type %T) in assignment to, or comparison with, column %s (type %s)", v, ideal(v), c.name, typeStr(c.typ)) } } return } //TODO collate1 should return errors instead of panicing func collate1(a, b interface{}) int { switch x := a.(type) { case nil: if b != nil { return -1 } return 0 case bool: switch y := b.(type) { case nil: return 1 case bool: if !x && y { return -1 } if x == y { return 0 } return 1 default: // Make bool collate before anything except nil and // other bool for index seeking first non NULL value. return -1 } case idealComplex: switch y := b.(type) { case nil: return 1 case idealComplex: if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 case complex64: { x, y := complex64(x), complex64(y) if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 } case complex128: { x := complex128(x) if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 } default: panic("internal error 012") } case idealUint: switch y := b.(type) { case nil: return 1 case idealUint: if x < y { return -1 } if x == y { return 0 } return 1 case uint8: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case uint16: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case uint32: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case uint64: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case uint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 013") } case idealRune: switch y := b.(type) { case nil: return 1 case idealRune: if x < y { return -1 } if x == y { return 0 } return 1 case int8: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int16: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int32: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int64: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 014") } case idealInt: switch y := b.(type) { case nil: return 1 case idealInt: if x < y { return -1 } if x == y { return 0 } return 1 case int8: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int16: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int32: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int64: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 015") } case idealFloat: switch y := b.(type) { case nil: return 1 case idealFloat: if x < y { return -1 } if x == y { return 0 } return 1 case float32: { x, y := float64(x), float64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case float64: { x, y := float64(x), float64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 016") } case complex64: switch y := b.(type) { case nil: return 1 case complex64: if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 case idealComplex: { x, y := complex64(x), complex64(y) if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 } default: panic("internal error 017") } case complex128: switch y := b.(type) { case nil: return 1 case complex128: if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 case idealComplex: { x, y := complex128(x), complex128(y) if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 } default: panic("internal error 018") } case float32: switch y := b.(type) { case nil: return 1 case float32: if x < y { return -1 } if x == y { return 0 } return 1 case idealFloat: { x, y := float32(x), float32(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 019") } case float64: switch y := b.(type) { case nil: return 1 case float64: if x < y { return -1 } if x == y { return 0 } return 1 case idealFloat: { x, y := float64(x), float64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 020") } case int8: switch y := b.(type) { case nil: return 1 case int8: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 021") } case int16: switch y := b.(type) { case nil: return 1 case int16: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 022") } case int32: switch y := b.(type) { case nil: return 1 case int32: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 023") } case int64: switch y := b.(type) { case nil: return 1 case int64: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 024") } case uint8: switch y := b.(type) { case nil: return 1 case uint8: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case idealUint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 025") } case uint16: switch y := b.(type) { case nil: return 1 case uint16: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case idealUint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 026") } case uint32: switch y := b.(type) { case nil: return 1 case uint32: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case idealUint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 027") } case uint64: switch y := b.(type) { case nil: return 1 case uint64: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case idealUint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 028") } case string: switch y := b.(type) { case nil: return 1 case string: if x < y { return -1 } if x == y { return 0 } return 1 default: panic("internal error 029") } case []byte: switch y := b.(type) { case nil: return 1 case []byte: return bytes.Compare(x, y) default: panic("internal error 030") } case *big.Int: switch y := b.(type) { case nil: return 1 case *big.Int: return x.Cmp(y) case idealInt: { y := big.NewInt(int64(y)) return x.Cmp(y) } case idealUint: { u := big.NewInt(0) u.SetUint64(uint64(y)) return x.Cmp(u) } default: panic("internal error 031") } case *big.Rat: switch y := b.(type) { case nil: return 1 case *big.Rat: return x.Cmp(y) case idealInt: { y := big.NewRat(int64(y), 1) return x.Cmp(y) } case idealUint: { u := big.NewInt(0) u.SetUint64(uint64(y)) var y big.Rat y.SetInt(u) return x.Cmp(&y) } default: panic("internal error 032") } case time.Time: switch y := b.(type) { case nil: return 1 case time.Time: if x.Before(y) { return -1 } if x.Equal(y) { return 0 } return 1 default: panic("internal error 033") } case time.Duration: switch y := b.(type) { case nil: return 1 case time.Duration: if x < y { return -1 } if x == y { return 0 } return 1 default: panic("internal error 034") } case chunk: switch y := b.(type) { case nil: return 1 case chunk: a, err := x.expand() if err != nil { panic(err) } b, err := y.expand() if err != nil { panic(err) } return collate1(a, b) default: panic("internal error 035") } default: //dbg("%T(%v) %T(%v)", a, a, b, b) panic("internal error 036") } } //TODO collate should return errors from collate1 func collate(x, y []interface{}) (r int) { //defer func() { dbg("%v %v -> %v", x, y, r) }() nx, ny := len(x), len(y) switch { case nx == 0 && ny != 0: return -1 case nx == 0 && ny == 0: return 0 case nx != 0 && ny == 0: return 1 } r = 1 if nx > ny { x, y, r = y, x, -r } for i, xi := range x { if c := collate1(xi, y[i]); c != 0 { return c * r } } if nx == ny { return 0 } return -r } var collators = map[bool]func(a, b []interface{}) int{false: collateDesc, true: collate} func collateDesc(a, b []interface{}) int { return -collate(a, b) } func isOrderedType(v interface{}) (y interface{}, r bool, err error) { //dbg("====") //dbg("%T(%v)", v, v) //defer func() { dbg("%T(%v)", y, y) }() switch x := v.(type) { case idealFloat, idealInt, idealRune, idealUint, float32, float64, int8, int16, int32, int64, uint8, uint16, uint32, uint64, string: return v, true, nil case *big.Int, *big.Rat, time.Time, time.Duration: return x, true, nil case chunk: if y, err = x.expand(); err != nil { return } return isOrderedType(y) } return v, false, nil } var isSystemName = map[string]bool{ "__Column": true, "__Column2": true, "__Index": true, "__Index2": true, "__Index2_Column": true, "__Index2_Expr": true, "__Table": true, } func qnames(l []string) []string { r := make([]string, len(l)) for i, v := range l { r[i] = fmt.Sprintf("%q", v) } return r }