作者:kyled
项目:qlbridg
// Convert to Integer: Best attempt at converting to integer
//
// toint("5") => 5
// toint("5.75") => 5
// toint("5,555") => 5555
// toint("$5") => 5
// toint("5,555.00") => 5555
//
func ToInt(ctx expr.EvalContext, item value.Value) (value.IntValue, bool) {
iv, ok := value.ToInt64(reflect.ValueOf(item.Value()))
if !ok {
return value.NewIntValue(0), false
}
return value.NewIntValue(iv), true
}
作者:kyled
项目:qlbridg
// Not: urnary negation function
//
// eq(item,5)
func NotFunc(ctx expr.EvalContext, item value.Value) (value.BoolValue, bool) {
boolVal, ok := value.ToBool(item.Rv())
if ok {
return value.NewBoolValue(!boolVal), true
}
return value.BoolValueFalse, false
}
作者:kyled
项目:qlbridg
// Convert to Number: Best attempt at converting to integer
//
// tonumber("5") => 5.0
// tonumber("5.75") => 5.75
// tonumber("5,555") => 5555
// tonumber("$5") => 5.00
// tonumber("5,555.00") => 5555
//
func ToNumber(ctx expr.EvalContext, item value.Value) (value.NumberValue, bool) {
fv, ok := value.ToFloat64(reflect.ValueOf(item.Value()))
if !ok {
return value.NewNumberValue(0), false
}
return value.NewNumberValue(fv), true
}
作者:jmptrade
项目:qlbridg
// Extract host from a String (must be urlish), doesn't do much/any validation
func Qs(ctx expr.EvalContext, urlItem, keyItem value.Value) (value.StringValue, bool) {
val, ok := value.ToString(urlItem.Rv())
if !ok {
return value.EmptyStringValue, false
}
if val == "" {
return value.EmptyStringValue, false
}
urlstr := strings.ToLower(val)
if len(urlstr) < 8 {
return value.EmptyStringValue, false
}
keyVal, ok := value.ToString(keyItem.Rv())
if !ok {
return value.EmptyStringValue, false
}
if keyVal == "" {
return value.EmptyStringValue, false
}
if !strings.HasPrefix(urlstr, "http") {
urlstr = "http://" + urlstr
}
if urlParsed, err := url.Parse(urlstr); err == nil {
//u.Infof("url.parse: %#v", urlParsed)
qsval, ok := urlParsed.Query()[keyVal]
if !ok {
return value.EmptyStringValue, false
}
if len(qsval) > 0 {
return value.NewStringValue(qsval[0]), true
}
}
return value.EmptyStringValue, false
}
作者:kyled
项目:qlbridg
// Count
func CountFunc(ctx EvalContext, val value.Value) (value.IntValue, bool) {
if val.Err() || val.Nil() {
return value.NewIntValue(0), false
}
//u.Infof("??? vals=[%v]", val.Value())
return value.NewIntValue(1), true
}
作者:schmichae
项目:qlbridg
// Equal function? returns true if items are equal
//
// eq(item,5)
func Eq(ctx expr.EvalContext, itemA, itemB value.Value) (value.BoolValue, bool) {
//return BoolValue(itemA == itemB)
//rvb := value.CoerceTo(itemA.Rv(), itemB.Rv())
//u.Infof("Eq(): a:%T b:%T %v=%v?", itemA, itemB, itemA.Value(), rvb)
//u.Infof("Eq()2: %T %T", itemA.Rv(), rvb)
return value.NewBoolValue(reflect.DeepEqual(itemA.Value(), itemB.Value())), true
}
作者:kyled
项目:qlbridg
// String lower function
// must be able to convert to string
//
func Lower(ctx expr.EvalContext, item value.Value) (value.StringValue, bool) {
val, ok := value.ToString(item.Rv())
if !ok {
return value.EmptyStringValue, false
}
return value.NewStringValue(strings.ToLower(val)), true
}
作者:kyled
项目:qlbridg
// <= Less Than or Equal
// Must be able to convert items to Floats or else not ok
//
func LeFunc(ctx expr.EvalContext, lv, rv value.Value) (value.BoolValue, bool) {
left, _ := value.ToFloat64(lv.Rv())
right, _ := value.ToFloat64(rv.Rv())
if math.IsNaN(left) || math.IsNaN(right) {
return value.BoolValueFalse, false
}
return value.NewBoolValue(left <= right), true
}
作者:jmptrade
项目:qlbridg
// < Less Than
// Must be able to convert items to Floats or else not ok
//
func LtFunc(ctx expr.EvalContext, lv, rv value.Value) (value.BoolValue, bool) {
left := value.ToFloat64(lv.Rv())
right := value.ToFloat64(rv.Rv())
if left == math.NaN() || right == math.NaN() {
return value.BoolValueFalse, false
}
return value.NewBoolValue(left < right), true
}
作者:kyled
项目:qlbridg
// Example of a custom Function, that we are adding into the Expression VM
//
// select
// user_id AS theuserid, email, item_count * 2, reg_date
// FROM stdio
// WHERE email_is_valid(email)
func EmailIsValid(ctx expr.EvalContext, email value.Value) (value.BoolValue, bool) {
emailstr, ok := value.ToString(email.Rv())
if !ok || emailstr == "" {
return value.BoolValueFalse, true
}
if _, err := mail.ParseAddress(emailstr); err == nil {
return value.BoolValueTrue, true
}
return value.BoolValueFalse, true
}
作者:jmptrade
项目:qlbridg
// todate
func ToDate(ctx expr.EvalContext, item value.Value) (value.TimeValue, bool) {
dateStr, ok := value.ToString(item.Rv())
if !ok {
return value.TimeZeroValue, false
}
//u.Infof("v=%v %v ", v, item.Rv())
if t, err := dateparse.ParseAny(dateStr); err == nil {
return value.NewTimeValue(t), true
}
return value.TimeZeroValue, false
}
作者:kyled
项目:qlbridg
// Sqrt
//
// sqrt(4) => 2, true
// sqrt(9) => 3, true
// sqrt(not_number) => 0, false
//
func SqrtFunc(ctx expr.EvalContext, val value.Value) (value.NumberValue, bool) {
nv, ok := val.(value.NumericValue)
if !ok {
return value.NewNumberValue(math.NaN()), false
}
if val.Err() || val.Nil() {
return value.NewNumberValue(0), false
}
fv := nv.Float()
fv = math.Sqrt(fv)
//u.Infof("??? vals=[%v]", val.Value())
return value.NewNumberValue(fv), true
}
作者:allisonmorga
项目:qlbridg
// Convert to Integer: Best attempt at converting to integer
//
// toint("5") => 5, true
// toint("5.75") => 5, true
// toint("5,555") => 5555, true
// toint("$5") => 5, true
// toint("5,555.00") => 5555, true
//
func ToInt(ctx expr.EvalContext, item value.Value) (value.IntValue, bool) {
switch itemT := item.(type) {
case value.TimeValue:
iv := itemT.Val().UnixNano() / 1e6 // Milliseconds
return value.NewIntValue(iv), true
}
iv, ok := value.ToInt64(reflect.ValueOf(item.Value()))
if !ok {
return value.NewIntValue(0), false
}
return value.NewIntValue(iv), true
}
作者:allisonmorga
项目:qlbridg
// totimestamp: convert to date, then to unix Seconds
//
func ToTimestamp(ctx expr.EvalContext, item value.Value) (value.IntValue, bool) {
dateStr, ok := value.ToString(item.Rv())
if !ok {
return value.NewIntValue(0), false
}
if t, err := dateparse.ParseAny(dateStr); err == nil {
//u.Infof("v=%v %v unix=%v", item, item.Rv(), t.Unix())
return value.NewIntValue(int64(t.Unix())), true
}
return value.NewIntValue(0), false
}
作者:kyled
项目:qlbridg
// String contains
// Will first convert to string, so may get unexpected results
//
func ContainsFunc(ctx expr.EvalContext, lv, rv value.Value) (value.BoolValue, bool) {
left, leftOk := value.ToString(lv.Rv())
right, rightOk := value.ToString(rv.Rv())
if !leftOk || !rightOk {
return value.BoolValueFalse, false
}
//u.Infof("Contains(%v, %v)", left, right)
if left == "" || right == "" {
return value.BoolValueFalse, false
}
if strings.Contains(left, right) {
return value.BoolValueTrue, true
}
return value.BoolValueFalse, true
}
作者:kyled
项目:qlbridg
// Split a string, accepts an optional with parameter
//
// split(item, ",")
//
func SplitFunc(ctx expr.EvalContext, input value.Value, splitByV value.StringValue) (value.StringsValue, bool) {
sv, ok := value.ToString(input.Rv())
splitBy, splitByOk := value.ToString(splitByV.Rv())
if !ok || !splitByOk {
return value.NewStringsValue(make([]string, 0)), false
}
if sv == "" {
return value.NewStringsValue(make([]string, 0)), false
}
if splitBy == "" {
return value.NewStringsValue(make([]string, 0)), false
}
vals := strings.Split(sv, splitBy)
return value.NewStringsValue(vals), true
}
作者:kyled
项目:qlbridg
// emailname a string, parses email
//
// emailname("Bob <[email protected]>") => Bob
//
func EmailNameFunc(ctx expr.EvalContext, item value.Value) (value.StringValue, bool) {
val, ok := value.ToString(item.Rv())
if !ok {
return value.EmptyStringValue, false
}
if val == "" {
return value.EmptyStringValue, false
}
if len(val) < 6 {
return value.EmptyStringValue, false
}
if em, err := mail.ParseAddress(val); err == nil {
return value.NewStringValue(em.Name), true
}
return value.EmptyStringValue, false
}
作者:schmichae
项目:qlbridg
func Yy(ctx expr.EvalContext, item value.Value) (value.IntValue, bool) {
//u.Info("yy: %T", item)
val, ok := value.ToString(item.Rv())
if !ok || val == "" {
return value.NewIntValue(0), false
}
//u.Infof("v=%v %v ", val, item.Rv())
if t, err := dateparse.ParseAny(val); err == nil {
yy := t.Year()
if yy >= 2000 {
yy = yy - 2000
} else if yy >= 1900 {
yy = yy - 1900
}
//u.Infof("Yy = %v yy = %v", item, yy)
return value.NewIntValue(int64(yy)), true
}
return value.NewIntValue(0), false
}
作者:kyled
项目:qlbridg
// email a string, parses email
//
// email("Bob <[email protected]>") => [email protected]
//
func EmailDomainFunc(ctx expr.EvalContext, item value.Value) (value.StringValue, bool) {
val, ok := value.ToString(item.Rv())
if !ok {
return value.EmptyStringValue, false
}
if val == "" {
return value.EmptyStringValue, false
}
if len(val) < 6 {
return value.EmptyStringValue, false
}
if em, err := mail.ParseAddress(strings.ToLower(val)); err == nil {
parts := strings.SplitN(strings.ToLower(em.Address), "@", 2)
if len(parts) == 2 {
return value.NewStringValue(parts[1]), true
}
}
return value.EmptyStringValue, false
}
作者:kyled
项目:qlbridg
// urlminusqs removes a specific query parameter and its value from a url
//
// urlminusqs("http://www.lytics.io/?q1=google&q2=123", "q1") => "http://www.lytics.io/?q2=123", true
//
func UrlMinusQs(ctx expr.EvalContext, urlItem, keyItem value.Value) (value.StringValue, bool) {
val := ""
switch itemT := urlItem.(type) {
case value.StringValue:
val = itemT.Val()
case value.StringsValue:
if len(itemT.Val()) == 0 {
return value.EmptyStringValue, false
}
val = itemT.Val()[0]
}
if val == "" {
return value.EmptyStringValue, false
}
if !strings.HasPrefix(val, "http") {
val = "http://" + val
}
keyVal, ok := value.ToString(keyItem.Rv())
if !ok {
return value.EmptyStringValue, false
}
if keyVal == "" {
return value.EmptyStringValue, false
}
if up, err := url.Parse(val); err == nil {
qsval := up.Query()
_, ok := qsval[keyVal]
if !ok {
return value.NewStringValue(fmt.Sprintf("%s://%s%s?%s", up.Scheme, up.Host, up.Path, up.RawQuery)), true
}
qsval.Del(keyVal)
up.RawQuery = qsval.Encode()
if up.RawQuery == "" {
return value.NewStringValue(fmt.Sprintf("%s://%s%s", up.Scheme, up.Host, up.Path)), true
}
return value.NewStringValue(fmt.Sprintf("%s://%s%s?%s", up.Scheme, up.Host, up.Path, up.RawQuery)), true
}
return value.EmptyStringValue, false
}