2016-05-31 20:35:35 +00:00
|
|
|
// 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 (
|
|
|
|
"fmt"
|
|
|
|
"math/rand"
|
|
|
|
"reflect"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
//TODO agg bigint, bigrat, time, duration
|
|
|
|
|
|
|
|
var builtin = map[string]struct {
|
|
|
|
f func([]interface{}, map[interface{}]interface{}) (interface{}, error)
|
|
|
|
minArgs int
|
|
|
|
maxArgs int
|
|
|
|
isStatic bool
|
|
|
|
isAggregate bool
|
|
|
|
}{
|
|
|
|
"__testBlob": {builtinTestBlob, 1, 1, true, false},
|
|
|
|
"__testString": {builtinTestString, 1, 1, true, false},
|
|
|
|
"avg": {builtinAvg, 1, 1, false, true},
|
|
|
|
"complex": {builtinComplex, 2, 2, true, false},
|
|
|
|
"contains": {builtinContains, 2, 2, true, false},
|
|
|
|
"count": {builtinCount, 0, 1, false, true},
|
|
|
|
"date": {builtinDate, 8, 8, true, false},
|
|
|
|
"day": {builtinDay, 1, 1, true, false},
|
|
|
|
"formatTime": {builtinFormatTime, 2, 2, true, false},
|
|
|
|
"formatFloat": {builtinFormatFloat, 1, 4, true, false},
|
|
|
|
"formatInt": {builtinFormatInt, 1, 2, true, false},
|
|
|
|
"hasPrefix": {builtinHasPrefix, 2, 2, true, false},
|
|
|
|
"hasSuffix": {builtinHasSuffix, 2, 2, true, false},
|
|
|
|
"hour": {builtinHour, 1, 1, true, false},
|
|
|
|
"hours": {builtinHours, 1, 1, true, false},
|
|
|
|
"id": {builtinID, 0, 1, false, false},
|
|
|
|
"imag": {builtinImag, 1, 1, true, false},
|
|
|
|
"len": {builtinLen, 1, 1, true, false},
|
|
|
|
"max": {builtinMax, 1, 1, false, true},
|
|
|
|
"min": {builtinMin, 1, 1, false, true},
|
|
|
|
"minute": {builtinMinute, 1, 1, true, false},
|
|
|
|
"minutes": {builtinMinutes, 1, 1, true, false},
|
|
|
|
"month": {builtinMonth, 1, 1, true, false},
|
|
|
|
"nanosecond": {builtinNanosecond, 1, 1, true, false},
|
|
|
|
"nanoseconds": {builtinNanoseconds, 1, 1, true, false},
|
|
|
|
"now": {builtinNow, 0, 0, false, false},
|
|
|
|
"parseTime": {builtinParseTime, 2, 2, true, false},
|
|
|
|
"real": {builtinReal, 1, 1, true, false},
|
|
|
|
"second": {builtinSecond, 1, 1, true, false},
|
|
|
|
"seconds": {builtinSeconds, 1, 1, true, false},
|
|
|
|
"since": {builtinSince, 1, 1, false, false},
|
|
|
|
"sum": {builtinSum, 1, 1, false, true},
|
|
|
|
"timeIn": {builtinTimeIn, 2, 2, true, false},
|
|
|
|
"weekday": {builtinWeekday, 1, 1, true, false},
|
|
|
|
"year": {builtinYear, 1, 1, true, false},
|
|
|
|
"yearDay": {builtinYearday, 1, 1, true, false},
|
|
|
|
}
|
|
|
|
|
|
|
|
func badNArgs(min int, s string, arg []interface{}) error {
|
|
|
|
a := []string{}
|
|
|
|
for _, v := range arg {
|
|
|
|
a = append(a, fmt.Sprintf("%v", v))
|
|
|
|
}
|
|
|
|
switch len(arg) < min {
|
|
|
|
case true:
|
|
|
|
return fmt.Errorf("missing argument to %s(%s)", s, strings.Join(a, ", "))
|
|
|
|
default: //case false:
|
|
|
|
return fmt.Errorf("too many arguments to %s(%s)", s, strings.Join(a, ", "))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func invArg(arg interface{}, s string) error {
|
|
|
|
return fmt.Errorf("invalid argument %v (type %T) for %s", arg, arg, s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinTestBlob(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
n, err := intExpr(arg[0])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
rng := rand.New(rand.NewSource(n))
|
|
|
|
b := make([]byte, n)
|
|
|
|
for i := range b {
|
|
|
|
b[i] = byte(rng.Int())
|
|
|
|
}
|
|
|
|
return b, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinTestString(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
n, err := intExpr(arg[0])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
rng := rand.New(rand.NewSource(n))
|
|
|
|
b := make([]byte, n)
|
|
|
|
for i := range b {
|
|
|
|
b[i] = byte(rng.Int())
|
|
|
|
}
|
|
|
|
return string(b), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinAvg(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
type avg struct {
|
|
|
|
sum interface{}
|
|
|
|
n uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := ctx["$agg0"]; ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
fn := ctx["$fn"]
|
|
|
|
if _, ok := ctx["$agg"]; ok {
|
|
|
|
data, ok := ctx[fn].(avg)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
switch x := data.sum.(type) {
|
|
|
|
case complex64:
|
|
|
|
return complex64(complex128(x) / complex(float64(data.n), 0)), nil
|
|
|
|
case complex128:
|
2017-04-05 14:34:41 +00:00
|
|
|
return complex64(x / complex(float64(data.n), 0)), nil
|
2016-05-31 20:35:35 +00:00
|
|
|
case float32:
|
|
|
|
return float32(float64(x) / float64(data.n)), nil
|
|
|
|
case float64:
|
2017-04-05 14:34:41 +00:00
|
|
|
return x / float64(data.n), nil
|
2016-05-31 20:35:35 +00:00
|
|
|
case int8:
|
|
|
|
return int8(int64(x) / int64(data.n)), nil
|
|
|
|
case int16:
|
|
|
|
return int16(int64(x) / int64(data.n)), nil
|
|
|
|
case int32:
|
|
|
|
return int32(int64(x) / int64(data.n)), nil
|
|
|
|
case int64:
|
2017-04-05 14:34:41 +00:00
|
|
|
return x / int64(data.n), nil
|
2016-05-31 20:35:35 +00:00
|
|
|
case uint8:
|
|
|
|
return uint8(uint64(x) / data.n), nil
|
|
|
|
case uint16:
|
|
|
|
return uint16(uint64(x) / data.n), nil
|
|
|
|
case uint32:
|
|
|
|
return uint32(uint64(x) / data.n), nil
|
|
|
|
case uint64:
|
2017-04-05 14:34:41 +00:00
|
|
|
return x / data.n, nil
|
2016-05-31 20:35:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
data, _ := ctx[fn].(avg)
|
|
|
|
y := arg[0]
|
|
|
|
if y == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
switch x := data.sum.(type) {
|
|
|
|
case nil:
|
|
|
|
switch y := y.(type) {
|
|
|
|
case float32, float64, int8, int16, int32, int64, uint8, uint16, uint32, uint64:
|
|
|
|
data = avg{y, 0}
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("avg: cannot accept %v (value if type %T)", y, y)
|
|
|
|
}
|
|
|
|
case complex64:
|
|
|
|
data.sum = x + y.(complex64)
|
|
|
|
case complex128:
|
|
|
|
data.sum = x + y.(complex128)
|
|
|
|
case float32:
|
|
|
|
data.sum = x + y.(float32)
|
|
|
|
case float64:
|
|
|
|
data.sum = x + y.(float64)
|
|
|
|
case int8:
|
|
|
|
data.sum = x + y.(int8)
|
|
|
|
case int16:
|
|
|
|
data.sum = x + y.(int16)
|
|
|
|
case int32:
|
|
|
|
data.sum = x + y.(int32)
|
|
|
|
case int64:
|
|
|
|
data.sum = x + y.(int64)
|
|
|
|
case uint8:
|
|
|
|
data.sum = x + y.(uint8)
|
|
|
|
case uint16:
|
|
|
|
data.sum = x + y.(uint16)
|
|
|
|
case uint32:
|
|
|
|
data.sum = x + y.(uint32)
|
|
|
|
case uint64:
|
|
|
|
data.sum = x + y.(uint64)
|
|
|
|
}
|
|
|
|
data.n++
|
|
|
|
ctx[fn] = data
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinComplex(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
re, im := arg[0], arg[1]
|
|
|
|
if re == nil || im == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
re, im = coerce(re, im)
|
|
|
|
if reflect.TypeOf(re) != reflect.TypeOf(im) {
|
|
|
|
return nil, fmt.Errorf("complex(%T(%#v), %T(%#v)): invalid types", re, re, im, im)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch re := re.(type) {
|
|
|
|
case idealFloat:
|
|
|
|
return idealComplex(complex(float64(re), float64(im.(idealFloat)))), nil
|
|
|
|
case idealInt:
|
|
|
|
return idealComplex(complex(float64(re), float64(im.(idealInt)))), nil
|
|
|
|
case idealRune:
|
|
|
|
return idealComplex(complex(float64(re), float64(im.(idealRune)))), nil
|
|
|
|
case idealUint:
|
|
|
|
return idealComplex(complex(float64(re), float64(im.(idealUint)))), nil
|
|
|
|
case float32:
|
2017-04-05 14:34:41 +00:00
|
|
|
return complex(re, im.(float32)), nil
|
2016-05-31 20:35:35 +00:00
|
|
|
case float64:
|
2017-04-05 14:34:41 +00:00
|
|
|
return complex(re, im.(float64)), nil
|
2016-05-31 20:35:35 +00:00
|
|
|
case int8:
|
|
|
|
return complex(float64(re), float64(im.(int8))), nil
|
|
|
|
case int16:
|
|
|
|
return complex(float64(re), float64(im.(int16))), nil
|
|
|
|
case int32:
|
|
|
|
return complex(float64(re), float64(im.(int32))), nil
|
|
|
|
case int64:
|
|
|
|
return complex(float64(re), float64(im.(int64))), nil
|
|
|
|
case uint8:
|
|
|
|
return complex(float64(re), float64(im.(uint8))), nil
|
|
|
|
case uint16:
|
|
|
|
return complex(float64(re), float64(im.(uint16))), nil
|
|
|
|
case uint32:
|
|
|
|
return complex(float64(re), float64(im.(uint32))), nil
|
|
|
|
case uint64:
|
|
|
|
return complex(float64(re), float64(im.(uint64))), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(re, "complex")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinContains(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch s := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
switch chars := arg[1].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
return strings.Contains(s, chars), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(chars, "string")
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return nil, invArg(s, "string")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinCount(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
if _, ok := ctx["$agg0"]; ok {
|
|
|
|
return int64(0), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
fn := ctx["$fn"]
|
|
|
|
if _, ok := ctx["$agg"]; ok {
|
|
|
|
return ctx[fn].(int64), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
n, _ := ctx[fn].(int64)
|
|
|
|
switch len(arg) {
|
|
|
|
case 0:
|
|
|
|
n++
|
|
|
|
case 1:
|
|
|
|
if arg[0] != nil {
|
|
|
|
n++
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic("internal error 067")
|
|
|
|
}
|
|
|
|
ctx[fn] = n
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinDate(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
for i, v := range arg {
|
|
|
|
switch i {
|
|
|
|
case 7:
|
|
|
|
switch x := v.(type) {
|
|
|
|
case string:
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "date")
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
switch x := v.(type) {
|
|
|
|
case int64:
|
|
|
|
case idealInt:
|
|
|
|
arg[i] = int64(x)
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "date")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sloc := arg[7].(string)
|
|
|
|
loc := time.Local
|
|
|
|
switch sloc {
|
|
|
|
case "local":
|
|
|
|
default:
|
|
|
|
loc, err = time.LoadLocation(sloc)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return time.Date(
|
|
|
|
int(arg[0].(int64)),
|
|
|
|
time.Month(arg[1].(int64)),
|
|
|
|
int(arg[2].(int64)),
|
|
|
|
int(arg[3].(int64)),
|
|
|
|
int(arg[4].(int64)),
|
|
|
|
int(arg[5].(int64)),
|
|
|
|
int(arg[6].(int64)),
|
|
|
|
loc,
|
|
|
|
), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinLen(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
return int64(len(x)), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "len")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinDay(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return int64(x.Day()), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "day")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinFormatTime(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
switch y := arg[1].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
return x.Format(y), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(y, "formatTime")
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "formatTime")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinFormatFloat(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
var val float64
|
|
|
|
var fmt byte = 'g'
|
|
|
|
|
|
|
|
prec := -1
|
|
|
|
bitSize := 64
|
|
|
|
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case float32:
|
|
|
|
val = float64(x)
|
|
|
|
bitSize = 32
|
|
|
|
case float64:
|
|
|
|
val = x
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "formatFloat")
|
|
|
|
}
|
|
|
|
|
|
|
|
switch len(arg) {
|
|
|
|
case 4:
|
|
|
|
arg3 := coerce1(arg[3], int64(0))
|
|
|
|
switch y := arg3.(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case int64:
|
|
|
|
bitSize = int(y)
|
|
|
|
default:
|
|
|
|
return nil, invArg(y, "formatFloat")
|
|
|
|
}
|
|
|
|
fallthrough
|
|
|
|
case 3:
|
|
|
|
arg2 := coerce1(arg[2], int64(0))
|
|
|
|
switch y := arg2.(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case int64:
|
|
|
|
prec = int(y)
|
|
|
|
default:
|
|
|
|
return nil, invArg(y, "formatFloat")
|
|
|
|
}
|
|
|
|
fallthrough
|
|
|
|
case 2:
|
|
|
|
arg1 := coerce1(arg[1], byte(0))
|
|
|
|
switch y := arg1.(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case byte:
|
|
|
|
fmt = y
|
|
|
|
default:
|
|
|
|
return nil, invArg(y, "formatFloat")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return strconv.FormatFloat(val, fmt, prec, bitSize), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinFormatInt(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
var intVal int64
|
|
|
|
var uintVal uint64
|
|
|
|
|
|
|
|
uintType := false
|
|
|
|
base := 10
|
|
|
|
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case int8:
|
|
|
|
intVal = int64(x)
|
|
|
|
case int16:
|
|
|
|
intVal = int64(x)
|
|
|
|
case int32:
|
|
|
|
intVal = int64(x)
|
|
|
|
case int64:
|
|
|
|
intVal = x
|
|
|
|
case uint8:
|
|
|
|
uintType = true
|
|
|
|
uintVal = uint64(x)
|
|
|
|
case uint16:
|
|
|
|
uintType = true
|
|
|
|
uintVal = uint64(x)
|
|
|
|
case uint32:
|
|
|
|
uintType = true
|
|
|
|
uintVal = uint64(x)
|
|
|
|
case uint64:
|
|
|
|
uintType = true
|
|
|
|
uintVal = x
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "formatInt")
|
|
|
|
}
|
|
|
|
|
|
|
|
switch len(arg) {
|
|
|
|
case 2:
|
|
|
|
arg1 := coerce1(arg[1], int64(0))
|
|
|
|
switch y := arg1.(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case int64:
|
|
|
|
base = int(y)
|
|
|
|
default:
|
|
|
|
return nil, invArg(y, "formatInt")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if uintType {
|
|
|
|
return strconv.FormatUint(uintVal, base), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return strconv.FormatInt(intVal, base), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinHasPrefix(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch s := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
switch prefix := arg[1].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
return strings.HasPrefix(s, prefix), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(prefix, "string")
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return nil, invArg(s, "string")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinHasSuffix(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch s := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
switch suffix := arg[1].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
return strings.HasSuffix(s, suffix), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(suffix, "string")
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return nil, invArg(s, "string")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinHour(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return int64(x.Hour()), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "hour")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinHours(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Duration:
|
|
|
|
return x.Hours(), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "hours")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinID(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := ctx["$id"].(type) {
|
|
|
|
case map[string]interface{}:
|
|
|
|
if len(arg) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
tab := arg[0].(*ident)
|
|
|
|
id, ok := x[tab.s]
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("value not available: id(%s)", tab)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := id.(int64); ok {
|
|
|
|
return id, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("value not available: id(%s)", tab)
|
|
|
|
case int64:
|
|
|
|
return x, nil
|
|
|
|
default:
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinImag(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case idealComplex:
|
|
|
|
return imag(x), nil
|
|
|
|
case complex64:
|
|
|
|
return imag(x), nil
|
|
|
|
case complex128:
|
|
|
|
return imag(x), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "imag")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinMax(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
if _, ok := ctx["$agg0"]; ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
fn := ctx["$fn"]
|
|
|
|
if _, ok := ctx["$agg"]; ok {
|
|
|
|
if v, ok = ctx[fn]; ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
max := ctx[fn]
|
|
|
|
y := arg[0]
|
|
|
|
if y == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
switch x := max.(type) {
|
|
|
|
case nil:
|
|
|
|
switch y := y.(type) {
|
|
|
|
case float32, float64, string, int8, int16, int32, int64, uint8, uint16, uint32, uint64, time.Time:
|
|
|
|
max = y
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("max: cannot accept %v (value if type %T)", y, y)
|
|
|
|
}
|
|
|
|
case float32:
|
|
|
|
if y := y.(float32); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case float64:
|
|
|
|
if y := y.(float64); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case string:
|
|
|
|
if y := y.(string); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case int8:
|
|
|
|
if y := y.(int8); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case int16:
|
|
|
|
if y := y.(int16); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case int32:
|
|
|
|
if y := y.(int32); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case int64:
|
|
|
|
if y := y.(int64); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case uint8:
|
|
|
|
if y := y.(uint8); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case uint16:
|
|
|
|
if y := y.(uint16); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case uint32:
|
|
|
|
if y := y.(uint32); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case uint64:
|
|
|
|
if y := y.(uint64); y > x {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
case time.Time:
|
|
|
|
if y := y.(time.Time); y.After(x) {
|
|
|
|
max = y
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ctx[fn] = max
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinMin(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
if _, ok := ctx["$agg0"]; ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
fn := ctx["$fn"]
|
|
|
|
if _, ok := ctx["$agg"]; ok {
|
|
|
|
if v, ok = ctx[fn]; ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
min := ctx[fn]
|
|
|
|
y := arg[0]
|
|
|
|
if y == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
switch x := min.(type) {
|
|
|
|
case nil:
|
|
|
|
switch y := y.(type) {
|
|
|
|
case float32, float64, string, int8, int16, int32, int64, uint8, uint16, uint32, uint64, time.Time:
|
|
|
|
min = y
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("min: cannot accept %v (value if type %T)", y, y)
|
|
|
|
}
|
|
|
|
case float32:
|
|
|
|
if y := y.(float32); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case float64:
|
|
|
|
if y := y.(float64); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case string:
|
|
|
|
if y := y.(string); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case int8:
|
|
|
|
if y := y.(int8); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case int16:
|
|
|
|
if y := y.(int16); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case int32:
|
|
|
|
if y := y.(int32); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case int64:
|
|
|
|
if y := y.(int64); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case uint8:
|
|
|
|
if y := y.(uint8); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case uint16:
|
|
|
|
if y := y.(uint16); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case uint32:
|
|
|
|
if y := y.(uint32); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case uint64:
|
|
|
|
if y := y.(uint64); y < x {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
case time.Time:
|
|
|
|
if y := y.(time.Time); y.Before(x) {
|
|
|
|
min = y
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ctx[fn] = min
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinMinute(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return int64(x.Minute()), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "minute")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinMinutes(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Duration:
|
|
|
|
return x.Minutes(), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "minutes")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinMonth(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return int64(x.Month()), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "month")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinNanosecond(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return int64(x.Nanosecond()), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "nanosecond")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinNanoseconds(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Duration:
|
|
|
|
return x.Nanoseconds(), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "nanoseconds")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinNow(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
return time.Now(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinParseTime(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
var a [2]string
|
|
|
|
for i, v := range arg {
|
|
|
|
switch x := v.(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
a[i] = x
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "parseTime")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t, err := time.Parse(a[0], a[1])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
ls := t.Location().String()
|
|
|
|
if ls == "UTC" {
|
|
|
|
return t, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
l, err := time.LoadLocation(ls)
|
|
|
|
if err != nil {
|
|
|
|
return t, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return time.ParseInLocation(a[0], a[1], l)
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinReal(arg []interface{}, _ map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case idealComplex:
|
|
|
|
return real(x), nil
|
|
|
|
case complex64:
|
|
|
|
return real(x), nil
|
|
|
|
case complex128:
|
|
|
|
return real(x), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "real")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinSecond(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return int64(x.Second()), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "second")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinSeconds(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Duration:
|
|
|
|
return x.Seconds(), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "seconds")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinSince(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return time.Since(x), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "since")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinSum(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
if _, ok := ctx["$agg0"]; ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
fn := ctx["$fn"]
|
|
|
|
if _, ok := ctx["$agg"]; ok {
|
|
|
|
if v, ok = ctx[fn]; ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
sum := ctx[fn]
|
|
|
|
y := arg[0]
|
|
|
|
if y == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
switch x := sum.(type) {
|
|
|
|
case nil:
|
|
|
|
switch y := y.(type) {
|
|
|
|
case complex64, complex128, float32, float64, int8, int16, int32, int64, uint8, uint16, uint32, uint64:
|
|
|
|
sum = y
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("sum: cannot accept %v (value if type %T)", y, y)
|
|
|
|
}
|
|
|
|
case complex64:
|
|
|
|
sum = x + y.(complex64)
|
|
|
|
case complex128:
|
|
|
|
sum = x + y.(complex128)
|
|
|
|
case float32:
|
|
|
|
sum = x + y.(float32)
|
|
|
|
case float64:
|
|
|
|
sum = x + y.(float64)
|
|
|
|
case int8:
|
|
|
|
sum = x + y.(int8)
|
|
|
|
case int16:
|
|
|
|
sum = x + y.(int16)
|
|
|
|
case int32:
|
|
|
|
sum = x + y.(int32)
|
|
|
|
case int64:
|
|
|
|
sum = x + y.(int64)
|
|
|
|
case uint8:
|
|
|
|
sum = x + y.(uint8)
|
|
|
|
case uint16:
|
|
|
|
sum = x + y.(uint16)
|
|
|
|
case uint32:
|
|
|
|
sum = x + y.(uint32)
|
|
|
|
case uint64:
|
|
|
|
sum = x + y.(uint64)
|
|
|
|
}
|
|
|
|
ctx[fn] = sum
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinTimeIn(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
switch y := arg[1].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case string:
|
|
|
|
loc := time.Local
|
|
|
|
switch y {
|
|
|
|
case "local":
|
|
|
|
default:
|
|
|
|
loc, err = time.LoadLocation(y)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return x.In(loc), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "timeIn")
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "timeIn")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinWeekday(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return int64(x.Weekday()), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "weekday")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinYear(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return int64(x.Year()), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "year")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func builtinYearday(arg []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) {
|
|
|
|
switch x := arg[0].(type) {
|
|
|
|
case nil:
|
|
|
|
return nil, nil
|
|
|
|
case time.Time:
|
|
|
|
return int64(x.YearDay()), nil
|
|
|
|
default:
|
|
|
|
return nil, invArg(x, "yearDay")
|
|
|
|
}
|
|
|
|
}
|