示例#1
0
func TimeExtractFunc(ctx expr.EvalContext, items ...value.Value) (value.StringValue, bool) {
	switch len(items) {
	case 0:
		// if we have no "items", return time associated with ctx
		// This is an alias of now()
		t := ctx.Ts()
		if !t.IsZero() {
			return value.NewStringValue(t.String()), true
		}
		return value.EmptyStringValue, false

	case 1:
		// if only 1 item, convert item to time
		dateStr, ok := value.ToString(items[0].Rv())
		if !ok {
			return value.EmptyStringValue, false
		}
		t, err := dateparse.ParseAny(dateStr)
		if err != nil {
			return value.EmptyStringValue, false
		}
		return value.NewStringValue(t.String()), true

	case 2:
		// if we have 2 items, the first is the time string
		// and the second is the format string.
		// Use leekchan/timeutil package
		dateStr, ok := value.ToString(items[0].Rv())
		if !ok {
			return value.EmptyStringValue, false
		}

		formatStr, ok := value.ToString(items[1].Rv())
		if !ok {
			return value.EmptyStringValue, false
		}

		t, err := dateparse.ParseAny(dateStr)
		if err != nil {
			return value.EmptyStringValue, false
		}

		formatted := timeutil.Strftime(&t, formatStr)
		return value.NewStringValue(formatted), true

	default:
		return value.EmptyStringValue, false
	}
}
示例#2
0
// Extract Domain from a Value, or Values (must be urlish), doesn't do much/any validation
//
//     domain("http://www.lytics.io/index.html") =>  "lytics.io"
//
//  if input is a list of strings, only first is evaluated, for plural see domains()
//
func DomainFunc(ctx expr.EvalContext, item value.Value) (value.StringValue, bool) {

	urlstr := ""
	switch itemT := item.(type) {
	case value.StringValue:
		urlstr = itemT.Val()
	case value.StringsValue:
		for _, sv := range itemT.Val() {
			urlstr = sv
			break
		}
	}

	urlstr = strings.ToLower(urlstr)
	if !strings.HasPrefix(urlstr, "http") {
		urlstr = "http://" + urlstr
	}
	if urlParsed, err := url.Parse(urlstr); err == nil {
		parts := strings.Split(urlParsed.Host, ".")
		if len(parts) > 2 {
			parts = parts[len(parts)-2:]
		}
		if len(parts) > 0 {
			return value.NewStringValue(strings.Join(parts, ".")), true
		}

	}
	return value.EmptyStringValue, false
}
示例#3
0
// 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
}
示例#4
0
// 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
}
示例#5
0
// Extract url path from a String (must be urlish), doesn't do much/any validation
//
//     path("http://www.lytics.io/blog/index.html") =>  blog/index.html
//
// In the event the value contains more than one input url, will ONLY evaluate first
//
func UrlPath(ctx expr.EvalContext, item value.Value) (value.StringValue, bool) {
	val := ""
	switch itemT := item.(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
	}
	urlstr := strings.ToLower(val)
	if len(urlstr) < 8 {
		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)
		return value.NewStringValue(urlParsed.Path), true
	}

	return value.EmptyStringValue, false
}
示例#6
0
// defaultTypeWriter Convert a qlbridge value type to qlbridge value type
//
func defaultTypeWriter(ctx expr.EvalContext, val value.Value) (value.StringValue, bool) {
	switch sv := val.(type) {
	case value.StringValue:
		return sv, true
	}
	return value.NewStringValue(""), false
}
示例#7
0
// Join items together (string concatenation)
//
//   join("apples","oranges",",")   => "apples,oranges"
//   join(["apples","oranges"],",") => "apples,oranges"
//   join("apples","oranges","")    => "applesoranges"
//
func JoinFunc(ctx expr.EvalContext, items ...value.Value) (value.StringValue, bool) {
	if len(items) <= 1 {
		return value.EmptyStringValue, false
	}
	sep, ok := value.ToString(items[len(items)-1].Rv())
	if !ok {
		return value.EmptyStringValue, false
	}
	args := make([]string, 0)
	for i := 0; i < len(items)-1; i++ {
		switch valTyped := items[i].(type) {
		case value.SliceValue:
			vals := make([]string, len(valTyped.Val()))
			for i, sv := range valTyped.Val() {
				vals[i] = sv.ToString()
			}
			args = append(args, vals...)
		case value.StringsValue:
			vals := make([]string, len(valTyped.Val()))
			for i, sv := range valTyped.Val() {
				vals[i] = sv
			}
			args = append(args, vals...)
		case value.StringValue, value.NumberValue, value.IntValue:
			val := valTyped.ToString()
			if val == "" {
				return value.EmptyStringValue, false
			}
			args = append(args, val)
		}

	}
	return value.NewStringValue(strings.Join(args, sep)), true
}
示例#8
0
func (m *Sqlbridge) parseUpdateList() (map[string]*ValueColumn, error) {

	cols := make(map[string]*ValueColumn)
	lastColName := ""
	for {

		//u.Debug(m.Cur().String())
		switch m.Cur().T {
		case lex.TokenWhere, lex.TokenLimit, lex.TokenEOS, lex.TokenEOF:
			return cols, nil
		case lex.TokenValue:
			cols[lastColName] = &ValueColumn{Value: value.NewStringValue(m.Cur().V)}
		case lex.TokenInteger:
			iv, _ := strconv.ParseInt(m.Cur().V, 10, 64)
			cols[lastColName] = &ValueColumn{Value: value.NewIntValue(iv)}
		case lex.TokenComma, lex.TokenEqual:
			// don't need to do anything
		case lex.TokenIdentity:
			lastColName = m.Cur().V
		case lex.TokenUdfExpr:
			tree := NewTree(m.SqlTokenPager)
			if err := m.parseNode(tree); err != nil {
				u.Errorf("could not parse: %v", err)
				return nil, err
			}
			cols[lastColName] = &ValueColumn{Expr: tree.Root}
		default:
			u.Warnf("don't know how to handle ?  %v", m.Cur())
			return nil, fmt.Errorf("expected column but got: %v", m.Cur().String())
		}
		m.Next()
	}
	panic("unreachable")
}
示例#9
0
func BenchmarkVmExecute(b *testing.B) {
	msg := datasource.NewContextSimpleData(
		map[string]value.Value{
			"int5":       value.NewIntValue(5),
			"item_count": value.NewStringValue("5"),
			"reg_date":   value.NewStringValue("2014/11/01"),
			"user_id":    value.NewStringValue("abc")},
	)
	b.ReportAllocs()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		for _, sqlText := range bmSql {
			verifyBenchmarkSql(b, sqlText, msg)
		}
	}
}
示例#10
0
文件: vm.go 项目: kyledj/qlbridge
func Eval(ctx expr.EvalContext, arg expr.Node) (value.Value, bool) {
	//u.Debugf("Eval() node=%T  %v", arg, arg)
	// can we switch to arg.Type()
	switch argVal := arg.(type) {
	case *expr.NumberNode:
		return numberNodeToValue(argVal)
	case *expr.BinaryNode:
		return walkBinary(ctx, argVal)
	case *expr.UnaryNode:
		return walkUnary(ctx, argVal)
	case *expr.TriNode:
		return walkTri(ctx, argVal)
	case *expr.MultiArgNode:
		return walkMulti(ctx, argVal)
	case *expr.FuncNode:
		return walkFunc(ctx, argVal)
	case *expr.IdentityNode:
		return walkIdentity(ctx, argVal)
	case *expr.StringNode:
		return value.NewStringValue(argVal.Text), true
	case nil:
		return nil, true
	default:
		u.Errorf("Unknonwn node type:  %T", argVal)
		panic(ErrUnknownNodeType)
	}
}
示例#11
0
// HashSha512Func Hash a value to SHA512 string
//
//     hash.sha512("/blog/index.html")  =>  abc345xyz
//
func HashSha512Func(ctx expr.EvalContext, arg value.Value) (value.StringValue, bool) {
	if arg.Err() || arg.Nil() {
		return value.EmptyStringValue, true
	}
	hasher := sha512.New()
	hasher.Write([]byte(arg.ToString()))
	return value.NewStringValue(hex.EncodeToString(hasher.Sum(nil))), true
}
示例#12
0
func TestNamespaces(t *testing.T) {

	a1 := value.NewStringValue("a1")
	b1 := value.NewStringValue("b1")
	b2 := value.NewStringValue("b2")
	c1 := value.NewStringValue("c1")
	d1 := value.NewStringValue("d1")
	readers := []expr.ContextReader{
		datasource.NewNamespacedContextReader(datasource.NewContextSimpleData(map[string]value.Value{
			"a": a1,
			"b": b1,
			"d": d1,
		}), "foo"),
		datasource.NewNamespacedContextReader(datasource.NewContextSimpleData(map[string]value.Value{
			"b": b2,
			"c": c1,
		}), "BAR"),
		datasource.NewContextSimpleData(map[string]value.Value{
			"a": a1,
		}),
	}

	nc := datasource.NewNestedContextReader(readers, time.Now())
	expected := map[string]value.Value{
		"foo.a": a1,
		"foo.b": b1,
		"foo.d": d1,
		"bar.b": b2,
		"bar.c": c1,
		"a":     a1,
	}

	for k, v := range expected {
		checkval(t, nc, k, v)
	}
	r := nc.Row()
	assert.Equal(t, len(expected), len(r))
	for k, v := range expected {
		assert.Equal(t, v, r[k])
	}

	// _, ok := nc.Get("no")
	// assert.Equal(t, false, ok)
}
示例#13
0
func walkIdentity(ctx expr.EvalContext, node *expr.IdentityNode) (value.Value, bool) {

	if node.IsBooleanIdentity() {
		//u.Debugf("walkIdentity() boolean: node=%T  %v Bool:%v", node, node, node.Bool())
		return value.NewBoolValue(node.Bool()), true
	}
	if ctx == nil {
		return value.NewStringValue(node.Text), true
	}
	return ctx.Get(node.Text)
}
示例#14
0
// Get yymm in 4 digits from argument if supplied, else uses message context ts
//
func YyMm(ctx expr.EvalContext, items ...value.Value) (value.StringValue, bool) {

	if len(items) == 0 {
		if !ctx.Ts().IsZero() {
			t := ctx.Ts()
			return value.NewStringValue(t.Format(yymmTimeLayout)), true
		}
	} else if len(items) == 1 {
		dateStr, ok := value.ToString(items[0].Rv())
		if !ok {
			return value.EmptyStringValue, false
		}
		//u.Infof("v=%v   %v  ", v, items[0].Rv())
		if t, err := dateparse.ParseAny(dateStr); err == nil {
			return value.NewStringValue(t.Format(yymmTimeLayout)), true
		}
	}

	return value.EmptyStringValue, false
}
示例#15
0
func TestSqlDelete(t *testing.T) {

	db := datasource.NewContextSimple()
	user1 := map[string]value.Value{
		"user_id":    value.NewIntValue(5),
		"item_count": value.NewStringValue("5"),
		"bval":       value.NewBoolValue(true),
		"bvalf":      value.NewBoolValue(false),
		"reg_date":   value.NewStringValue("2014/11/01"),
		"name":       value.NewStringValue("bob")}
	db.Insert(user1)
	user2 := map[string]value.Value{
		"user_id":    value.NewIntValue(6),
		"item_count": value.NewStringValue("5"),
		"reg_date":   value.NewStringValue("2012/11/01"),
		"name":       value.NewStringValue("allison")}
	db.Insert(user2)
	assert.Tf(t, len(db.Rows) == 2, "has 2 users")
	verifySqlDelete(t, `
		DELETE FROM mytable
		WHERE yy(reg_date) == 14
		`, db)

	assert.Tf(t, len(db.Rows) == 1, "must have 1 rows: %v  %v", len(db.Rows), db.Rows)
	assert.Tf(t, db.Rows[0]["name"].ToString() == "allison", "%v", db.Rows)
}
示例#16
0
// 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
}
示例#17
0
// ValueArray
//     IN ("a","b","c")
//     ["a","b","c"]
func ValueArray(pg TokenPager) (value.Value, error) {

	//u.Debugf("valueArray cur:%v peek:%v", pg.Cur().V, pg.Peek().V)
	vals := make([]value.Value, 0)
arrayLoop:
	for {
		tok := pg.Next() // consume token
		//u.Infof("valueArray() consumed token?: %v", tok)
		switch tok.T {
		case lex.TokenComma:
			// continue
		case lex.TokenRightParenthesis:
			//u.Warnf("found right paren  %v cur: %v", tok, pg.Cur())
			break arrayLoop
		case lex.TokenEOF, lex.TokenEOS, lex.TokenFrom, lex.TokenAs:
			//u.Debugf("return: %v", tok)
			break arrayLoop
		case lex.TokenValue:
			vals = append(vals, value.NewStringValue(tok.V))
		case lex.TokenInteger:
			fv, err := strconv.ParseFloat(tok.V, 64)
			if err == nil {
				vals = append(vals, value.NewNumberValue(fv))
			} else {
				return value.NilValueVal, err
			}
		case lex.TokenFloat:
			fv, err := strconv.ParseFloat(tok.V, 64)
			if err == nil {
				vals = append(vals, value.NewNumberValue(fv))
			} else {
				return value.NilValueVal, err
			}
		default:
			return value.NilValueVal, fmt.Errorf("Could not recognize token: %v", tok)
		}

		tok = pg.Next()
		switch tok.T {
		case lex.TokenComma:
			// fine, consume the comma
		case lex.TokenRightBracket:
			//u.Warnf("right bracket: %v", tok)
			break arrayLoop
		default:
			u.Warnf("unrecognized token: %v", tok)
			return value.NilValueVal, fmt.Errorf("unrecognized token %v", tok)
		}
	}
	//u.Debugf("returning array: %v", vals)
	return value.NewSliceValues(vals), nil
}
示例#18
0
func BenchmarkVmExecuteNoParse(b *testing.B) {
	readContext := datasource.NewContextSimpleData(
		map[string]value.Value{
			"int5":       value.NewIntValue(5),
			"item_count": value.NewStringValue("5"),
			"reg_date":   value.NewStringValue("2014/11/01"),
			"user_id":    value.NewStringValue("abc")},
	)
	sqlVm, err := NewSqlVm(bmSql[0])
	if err != nil {
		b.Fail()
	}
	writeContext := datasource.NewContextSimple()
	b.ReportAllocs()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		err = sqlVm.Execute(writeContext, readContext)
		if err != nil {
			b.Fail()
		}
	}
}
示例#19
0
// Replace a string(s), accepts any number of parameters to replace
//    replaces with ""
//
//     replace("/blog/index.html", "/blog","")  =>  /index.html
//     replace("/blog/index.html", "/blog")  =>  /index.html
//     replace("/blog/index.html", "/blog/archive/","/blog")  =>  /blog/index.html
//     replace(item, "M")
//
func Replace(ctx expr.EvalContext, vals ...value.Value) (value.StringValue, bool) {
	if len(vals) < 2 {
		return value.EmptyStringValue, false
	}
	val1 := vals[0].ToString()
	arg := vals[1]
	replaceWith := ""
	if len(vals) == 3 {
		replaceWith = vals[2].ToString()
	}
	if arg.Err() {
		return value.EmptyStringValue, false
	}
	val1 = strings.Replace(val1, arg.ToString(), replaceWith, -1)
	return value.NewStringValue(val1), true
}
示例#20
0
// emailname a string, parses email
//
//     emailname("Bob <*****@*****.**>") =>  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
}
示例#21
0
// Replace a string(s), accepts any number of parameters to replace
//    replaces with ""
//
//     replace("/blog/index.html", "/blog","M2")  =>  /index.html
//     replace(item, "M")
//
func Replace(ctx expr.EvalContext, vals ...value.Value) (value.StringValue, bool) {
	if len(vals) < 2 {
		return value.EmptyStringValue, false
	}
	val1 := vals[0].ToString()
	for _, v := range vals[1:] {
		if v.Err() || v.Nil() {
			return value.EmptyStringValue, false
		} else if value.IsNilIsh(v.Rv()) {
			return value.EmptyStringValue, false
		}
		v2 := v.ToString()
		if len(v2) > 0 {
			val1 = strings.Replace(val1, v2, "", -1)
		}
	}
	return value.NewStringValue(val1), true
}
示例#22
0
func Eval(ctx expr.EvalContext, arg expr.Node) (value.Value, bool) {
	//u.Debugf("Eval() node=%T  %v", arg, arg)
	// can we switch to arg.Type()
	switch argVal := arg.(type) {
	case *expr.NumberNode:
		return numberNodeToValue(argVal)
	case *expr.BinaryNode:
		return walkBinary(ctx, argVal)
	case *expr.UnaryNode:
		return walkUnary(ctx, argVal)
	case *expr.TriNode:
		return walkTri(ctx, argVal)
	case *expr.ArrayNode:
		return walkArray(ctx, argVal)
	case *expr.FuncNode:
		return walkFunc(ctx, argVal)
	case *expr.IdentityNode:
		return walkIdentity(ctx, argVal)
	case *expr.StringNode:
		return value.NewStringValue(argVal.Text), true
	case nil:
		return nil, false
	case *expr.NullNode:
		// WHERE (`users.user_id` != NULL)
		return value.NewNilValue(), true
	case *expr.ValueNode:
		if argVal.Value == nil {
			return nil, false
		}
		switch val := argVal.Value.(type) {
		case *value.NilValue, value.NilValue:
			return nil, false
		case value.SliceValue:
			//u.Warnf("got slice? %#v", argVal)
			return val, true
		}
		u.Errorf("Unknonwn node type:  %#v", argVal.Value)
		panic(ErrUnknownNodeType)
	default:
		u.Errorf("Unknonwn node type:  %#v", arg)
		panic(ErrUnknownNodeType)
	}
}
示例#23
0
// urlmain remove the querystring and scheme from url
//
//     urlmain("http://www.lytics.io/?utm_source=google")  => "www.lytics.io/", true
//
func UrlMain(ctx expr.EvalContext, urlItem 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 up, err := url.Parse(val); err == nil {
		return value.NewStringValue(fmt.Sprintf("%s%s", up.Host, up.Path)), true
	}

	return value.EmptyStringValue, false
}
示例#24
0
// Join items
//
//   join("applies","oranges",",") => "apples,oranges"
//
func JoinFunc(ctx expr.EvalContext, items ...value.Value) (value.StringValue, bool) {
	if len(items) <= 1 {
		return value.EmptyStringValue, false
	}
	sep, ok := value.ToString(items[len(items)-1].Rv())
	if !ok {
		return value.EmptyStringValue, false
	}
	args := make([]string, 0)
	for i := 0; i < len(items)-1; i++ {
		val, ok := value.ToString(items[i].Rv())
		if !ok {
			return value.EmptyStringValue, false
		}
		if val == "" {
			return value.EmptyStringValue, false
		}
		args = append(args, val)
	}
	return value.NewStringValue(strings.Join(args, sep)), true
}
示例#25
0
// email a string, parses email
//
//     email("Bob <*****@*****.**>") =>  [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
}
示例#26
0
// Extract url path from a String (must be urlish), doesn't do much/any validation
func UrlPath(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
	}
	urlstr := strings.ToLower(val)
	if len(urlstr) < 8 {
		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)
		return value.NewStringValue(urlParsed.Path), true
	}

	return value.EmptyStringValue, false
}
示例#27
0
func (m *Sqlbridge) parseValueList(stmt *SqlInsert) error {

	if m.Cur().T != lex.TokenLeftParenthesis {
		return fmt.Errorf("Expecting opening paren ( but got %v", m.Cur())
	}
	//m.Next()
	stmt.Rows = make([][]value.Value, 0)
	var row []value.Value
	for {

		//u.Debug(m.Cur().String())
		switch m.Cur().T {
		case lex.TokenLeftParenthesis:
			// start of row
			row = make([]value.Value, 0)
		case lex.TokenRightParenthesis:
			stmt.Rows = append(stmt.Rows, row)
		case lex.TokenFrom, lex.TokenInto, lex.TokenLimit, lex.TokenEOS, lex.TokenEOF:
			// This indicates we have come to the End of the values
			//u.Debugf("Ending %v ", m.Cur())
			return nil
		case lex.TokenValue:
			row = append(row, value.NewStringValue(m.Cur().V))
		case lex.TokenInteger:
			iv, _ := strconv.ParseInt(m.Cur().V, 10, 64)
			row = append(row, value.NewIntValue(iv))
		case lex.TokenComma:
			//row = append(row, col)
			//u.Debugf("comma, added cols:  %v", len(stmt.Columns))
		default:
			u.Warnf("don't know how to handle ?  %v", m.Cur())
			return fmt.Errorf("expected column but got: %v", m.Cur().String())
		}
		m.Next()
	}
	//u.Debugf("cols: %d", len(stmt.Columns))
	return nil
}
示例#28
0
// url decode a string
//
//     urldecode("http://www.lytics.io/index.html") =>  http://www.lytics.io
//
// In the event the value contains more than one input url, will ONLY evaluate first
//
func UrlDecode(ctx expr.EvalContext, item value.Value) (value.StringValue, bool) {

	val := ""
	switch itemT := item.(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
	}
	val, err := url.QueryUnescape(val)
	if err != nil {
		return value.EmptyStringValue, false
	}

	return value.NewStringValue(val), true
}
示例#29
0
func Evaluator(arg expr.Node) EvaluatorFunc {
	//u.Debugf("Evaluator() node=%T  %v", arg, arg)
	switch argVal := arg.(type) {
	case *expr.NumberNode:
		return func(ctx expr.EvalContext) (value.Value, bool) { return numberNodeToValue(argVal) }
	case *expr.BinaryNode:
		return func(ctx expr.EvalContext) (value.Value, bool) { return walkBinary(ctx, argVal) }
	case *expr.UnaryNode:
		return func(ctx expr.EvalContext) (value.Value, bool) { return walkUnary(ctx, argVal) }
	case *expr.FuncNode:
		return func(ctx expr.EvalContext) (value.Value, bool) { return walkFunc(ctx, argVal) }
	case *expr.IdentityNode:
		return func(ctx expr.EvalContext) (value.Value, bool) { return walkIdentity(ctx, argVal) }
	case *expr.StringNode:
		return func(ctx expr.EvalContext) (value.Value, bool) { return value.NewStringValue(argVal.Text), true }
	case *expr.TriNode:
		return func(ctx expr.EvalContext) (value.Value, bool) { return walkTri(ctx, argVal) }
	case *expr.ArrayNode:
		return func(ctx expr.EvalContext) (value.Value, bool) { return walkArray(ctx, argVal) }
	default:
		u.Errorf("Unknonwn node type:  %T", argVal)
		panic(ErrUnknownNodeType)
	}
}
示例#30
0
func (m *Sqlbridge) parseValueList() ([][]*ValueColumn, error) {

	if m.Cur().T != lex.TokenLeftParenthesis {
		return nil, fmt.Errorf("Expecting opening paren ( but got %v", m.Cur())
	}

	var row []*ValueColumn
	values := make([][]*ValueColumn, 0)

	for {

		//u.Debug(m.Cur().String())
		switch m.Cur().T {
		case lex.TokenLeftParenthesis:
			// start of row
			if len(row) > 0 {
				values = append(values, row)
			}
			row = make([]*ValueColumn, 0)
		case lex.TokenRightParenthesis:
			values = append(values, row)
		case lex.TokenFrom, lex.TokenInto, lex.TokenLimit, lex.TokenEOS, lex.TokenEOF:
			if len(row) > 0 {
				values = append(values, row)
			}
			return values, nil
		case lex.TokenValue:
			row = append(row, &ValueColumn{Value: value.NewStringValue(m.Cur().V)})
		case lex.TokenInteger:
			iv, err := strconv.ParseInt(m.Cur().V, 10, 64)
			if err != nil {
				return nil, err
			}
			row = append(row, &ValueColumn{Value: value.NewIntValue(iv)})
		case lex.TokenFloat:
			fv, err := strconv.ParseFloat(m.Cur().V, 64)
			if err != nil {
				return nil, err
			}
			row = append(row, &ValueColumn{Value: value.NewNumberValue(fv)})
		case lex.TokenBool:
			bv, err := strconv.ParseBool(m.Cur().V)
			if err != nil {
				return nil, err
			}
			row = append(row, &ValueColumn{Value: value.NewBoolValue(bv)})
		case lex.TokenIdentity:
			// TODO:  this is a bug in lexer
			lv := m.Cur().V
			if bv, err := strconv.ParseBool(lv); err == nil {
				row = append(row, &ValueColumn{Value: value.NewBoolValue(bv)})
			} else {
				// error?
				u.Warnf("Could not figure out how to use: %v", m.Cur())
			}
		case lex.TokenLeftBracket:
			// an array of values?
			m.Next() // Consume the [
			arrayVal, err := expr.ValueArray(m.SqlTokenPager)
			if err != nil {
				return nil, err
			}
			//n := NewValueNode(arrayVal)
			row = append(row, &ValueColumn{Value: arrayVal})
			u.Infof("what is token?  %v peek:%v", m.Cur(), m.Peek())
			//t.Next()
		case lex.TokenComma:
			// don't need to do anything
		case lex.TokenUdfExpr:
			tree := expr.NewTreeFuncs(m.SqlTokenPager, m.funcs)
			if err := m.parseNode(tree); err != nil {
				u.Errorf("could not parse: %v", err)
				return nil, err
			}
			//col.Expr = tree.Root
			row = append(row, &ValueColumn{Expr: tree.Root})
		default:
			u.Warnf("don't know how to handle ?  %v", m.Cur())
			return nil, fmt.Errorf("expected column but got: %v", m.Cur().String())
		}
		m.Next()
	}
	panic("unreachable")
}