예제 #1
0
func (m ContextUrlValues) Get(key string) (value.Value, bool) {
	vals, ok := m.Data[key]
	if ok {
		if len(vals) == 1 {
			return value.NewValue(vals[0]), true
		}
		return value.NewValue(vals), true
	}
	return value.EmptyStringValue, false
}
예제 #2
0
func (m *SqlDriverMessageMap) Get(key string) (value.Value, bool) {
	if idx, ok := m.ColIndex[key]; ok {
		return value.NewValue(m.Vals[idx]), true
	}
	//u.Debugf("could not find: %v in %#v", key, m.ColIndex)
	_, right, hasLeft := expr.LeftRight(key)
	if hasLeft {
		if idx, ok := m.ColIndex[right]; ok {
			return value.NewValue(m.Vals[idx]), true
		}
	}
	return nil, false
}
예제 #3
0
func (m *SqlDriverMessageMap) Row() map[string]value.Value {
	row := make(map[string]value.Value)
	for k, val := range m.Vals {
		row[k] = value.NewValue(val)
	}
	return row
}
예제 #4
0
파일: context.go 프로젝트: kyledj/qlbridge
func (m *SqlDriverMessageMap) Get(key string) (value.Value, bool) {
	if idx, ok := m.colindex[key]; ok {
		return value.NewValue(m.row[idx]), true
	}
	//u.Debugf("could not find: %v in %#v", key, m.colindex)
	return nil, true
}
예제 #5
0
파일: context.go 프로젝트: kyledj/qlbridge
func (m *SqlDriverMessageMap) Row() map[string]value.Value {
	row := make(map[string]value.Value)
	for k, idx := range m.colindex {
		row[k] = value.NewValue(m.row[idx])
	}
	return row
}
예제 #6
0
func NewContextSimpleNative(data map[string]interface{}) *ContextSimple {
	vals := make(map[string]value.Value)
	for k, v := range data {
		vals[k] = value.NewValue(v)
	}
	return &ContextSimple{Data: vals, ts: time.Now(), cursor: 0}
}
예제 #7
0
func (m *SqlDriverMessageMap) Get(key string) (value.Value, bool) {
	if val, ok := m.Vals[key]; ok {
		return value.NewValue(val), true
	} else {
		u.Warnf("could not find key: %v", key)
	}
	return value.ErrValue, false
}
예제 #8
0
func (m *ValueContextWrapper) Get(key string) (value.Value, bool) {
	if col, ok := m.cols[key]; ok {
		if col.Index < len(m.Vals) {
			return value.NewValue(m.Vals[col.Index]), true
		}
	}
	return nil, false
}
예제 #9
0
func (m *ValueContextWrapper) Row() map[string]value.Value {
	row := make(map[string]value.Value)
	for _, col := range m.cols {
		if col.Index <= len(m.Vals) {
			row[col.Key()] = value.NewValue(m.Vals[col.Index])
		}
	}
	return row
}
예제 #10
0
func (m *ValueContextWrapper) Get(key string) (value.Value, bool) {
	if col, ok := m.cols[key]; ok {
		if col.Index < len(m.Vals) {
			return value.NewValue(m.Vals[col.Index]), true
		}
		u.Warnf("could not find index?: %v col.idx:%v   len(vals)=%v", key, col.Index, len(m.Vals))
	} else {
		u.Warnf("could not find key: %v", key)
	}
	return value.ErrValue, false
}
예제 #11
0
func (m ContextUrlValues) Row() map[string]value.Value {
	mi := make(map[string]value.Value)
	for k, v := range m.Data {
		if len(v) == 1 {
			mi[k] = value.NewValue(v[0])
		} else if len(v) > 1 {
			mi[k] = value.NewStringsValue(v)
		}
	}
	return mi
}
예제 #12
0
func TestFilterQlVm(t *testing.T) {
	t.Parallel()

	t1, _ := dateparse.ParseAny("12/18/2015")
	//u.Infof("t1 %v", t1)
	nminus1 := time.Now().Add(time.Hour * -1)
	tr := true
	user := &User{
		Name:          "Yoda",
		Created:       t1,
		Updated:       &nminus1,
		Authenticated: true,
		HasSession:    &tr,
		Address:       Address{"Detroit", 55},
		Roles:         []string{"admin", "api"},
		BankAmount:    55.5,
	}

	readers := []expr.ContextReader{
		datasource.NewContextWrapper(user),
		datasource.NewContextSimpleNative(map[string]interface{}{
			"city": "Peoria, IL",
			"zip":  5,
		}),
	}

	nc := datasource.NewNestedContextReader(readers, time.Now())

	hits := []string{
		`FILTER name == "Yoda"`,                         // upper case sensitive name
		`FILTER name != "yoda"`,                         // we should be case-sensitive by default
		`FILTER name = "Yoda"`,                          // is equivalent to ==
		`FILTER "Yoda" == name`,                         // reverse order of identity/value
		`FILTER name != "Anakin"`,                       // negation on missing fields == true
		`FILTER first_name != "Anakin"`,                 // key doesn't exist
		`FILTER tolower(name) == "yoda"`,                // use functions in evaluation
		`FILTER FullName == "Yoda, Jedi"`,               // use functions on structs in evaluation
		`FILTER Address.City == "Detroit"`,              // traverse struct with path.field
		`FILTER name LIKE "*da"`,                        // LIKE
		`FILTER name NOT LIKE "*kin"`,                   // LIKE Negation
		`FILTER name CONTAINS "od"`,                     // Contains
		`FILTER name NOT CONTAINS "kin"`,                // Contains
		`FILTER roles INTERSECTS ("user", "api")`,       // Intersects
		`FILTER roles NOT INTERSECTS ("user", "guest")`, // Intersects
		`FILTER Created < "now-1d"`,                     // Date Math
		`FILTER Updated > "now-2h"`,                     // Date Math
		`FILTER *`,                                      // match all
		`FILTER OR (
			EXISTS name,       -- inline comments
			EXISTS not_a_key,  -- more inline comments
		)`,
		// show that line-breaks serve as expression separators
		`FILTER OR (
			EXISTS name
			EXISTS not_a_key   -- even if they have inline comments
		)`,
		//`FILTER a == "Yoda" AND b == "Peoria, IL" AND c == 5`,
		`FILTER AND (name == "Yoda", city == "Peoria, IL", zip == 5, BankAmount > 50)`,
		`FILTER AND (zip == 5, "Yoda" == name, OR ( city IN ( "Portland, OR", "New York, NY", "Peoria, IL" ) ) )`,
		`FILTER OR (
			EXISTS q, 
			AND ( 
				zip > 0, 
				OR ( zip > 10000, zip < 100 ) 
			), 
			NOT ( name == "Yoda" ) )`,
	}

	for _, q := range hits {
		fs, err := rel.ParseFilterQL(q)
		assert.Equal(t, nil, err)
		match, err := NewFilterVm(nil).Matches(nc, fs)
		assert.Equalf(t, nil, err, "error matching on query %q: %v", q, err)
		assert.T(t, match, q)
	}

	misses := []string{
		`FILTER name == "yoda"`, // casing
		"FILTER OR (false, false, AND (true, false))",
		`FILTER AND (name == "Yoda", city == "xxx", zip == 5)`,
	}

	for _, q := range misses {
		fs, err := rel.ParseFilterQL(q)
		assert.Equal(t, nil, err)
		match, err := NewFilterVm(nil).Matches(nc, fs)
		assert.Equal(t, nil, err)
		assert.T(t, !match)
	}

	// Filter Select Statements
	filterSelects := []fsel{
		fsel{`select name, zip FROM mycontext FILTER name == "Yoda"`, map[string]interface{}{"name": "Yoda", "zip": 5}},
	}
	for _, test := range filterSelects {

		//u.Debugf("about to parse: %v", test.qlText)
		sel, err := rel.ParseFilterSelect(test.query)
		assert.T(t, err == nil, "expected no error but got ", err, " for ", test.query)

		writeContext := datasource.NewContextSimple()
		_, err = EvalFilerSelect(sel, nil, writeContext, nc)
		assert.T(t, err == nil, "expected no error but got ", err, " for ", test.query)

		for key, val := range test.expect {
			v := value.NewValue(val)
			v2, ok := writeContext.Get(key)
			assert.Tf(t, ok, "Get(%q)=%v but got: %#v", key, val, writeContext.Row())
			assert.Equalf(t, v2.Value(), v.Value(), "?? %s  %v!=%v %T %T", key, v.Value(), v2.Value(), v.Value(), v2.Value())
		}
	}
}
예제 #13
0
// Create handler function for evaluation (ie, field selection from tuples)
func (m *Projection) projectionEvaluator() MessageHandler {
	out := m.MessageOut()
	columns := m.sql.Columns
	// if len(m.sql.From) > 1 && m.sql.From[0].Source != nil && len(m.sql.From[0].Source.Columns) > 0 {
	// 	// we have re-written this query, lets build new list of columns
	// 	columns = make(expr.Columns, 0)
	// 	for _, from := range m.sql.From {
	// 		for _, col := range from.Source.Columns {
	// 			columns = append(columns, col)
	// 		}
	// 	}
	// }
	return func(ctx *expr.Context, msg datasource.Message) bool {
		// defer func() {
		// 	if r := recover(); r != nil {
		// 		u.Errorf("crap, %v", r)
		// 	}
		// }()

		//u.Infof("got projection message: %T %#v", msg, msg.Body())
		var outMsg datasource.Message
		switch mt := msg.(type) {
		case *datasource.SqlDriverMessageMap:
			// readContext := datasource.NewContextUrlValues(uv)
			// use our custom write context for example purposes
			writeContext := datasource.NewContextSimple()
			outMsg = writeContext
			//u.Debugf("about to project: %#v", mt)
			for _, col := range columns {
				if col.ParentIndex < 0 {
					continue
				}
				//u.Debugf("col: idx:%v pidx:%v key:%v   %s", col.Index, col.ParentIndex, col.Key(), col.Expr)
				if col.Guard != nil {
					ifColValue, ok := vm.Eval(mt, col.Guard)
					if !ok {
						u.Errorf("Could not evaluate if:   %v", col.Guard.String())
						//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
					}
					//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
					switch ifColVal := ifColValue.(type) {
					case value.BoolValue:
						if ifColVal.Val() == false {
							//u.Debugf("Filtering out col")
							continue
						}
					}
				}
				if col.Star {
					for k, v := range mt.Row() {
						writeContext.Put(&expr.Column{As: k}, nil, value.NewValue(v))
					}
				} else {
					v, ok := vm.Eval(mt, col.Expr)
					if !ok {
						u.Warnf("failed eval key=%v  val=%#v expr:%s   mt:%#v", col.Key(), v, col.Expr, mt)
					} else if v == nil {
						u.Debugf("evaled: key=%v  val=%v", col.Key(), v)
						writeContext.Put(col, mt, v)
					} else {
						//u.Debugf("evaled: key=%v  val=%v", col.Key(), v.Value())
						writeContext.Put(col, mt, v)
					}
				}
			}

		case *datasource.ContextUrlValues:
			// readContext := datasource.NewContextUrlValues(uv)
			// use our custom write context for example purposes
			writeContext := datasource.NewContextSimple()
			outMsg = writeContext
			//u.Infof("about to project: colsct%v %#v", len(sql.Columns), outMsg)
			for _, col := range columns {
				//u.Debugf("col:   %#v", col)
				if col.Guard != nil {
					ifColValue, ok := vm.Eval(mt, col.Guard)
					if !ok {
						u.Errorf("Could not evaluate if:   %v", col.Guard.String())
						//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
					}
					//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
					switch ifColVal := ifColValue.(type) {
					case value.BoolValue:
						if ifColVal.Val() == false {
							//u.Debugf("Filtering out col")
							continue
						}
					}
				}
				if col.Star {
					for k, v := range mt.Row() {
						writeContext.Put(&expr.Column{As: k}, nil, v)
					}
				} else {
					//u.Debugf("tree.Root: as?%v %#v", col.As, col.Expr)
					v, ok := vm.Eval(mt, col.Expr)
					//u.Debugf("evaled: ok?%v key=%v  val=%v", ok, col.Key(), v)
					if ok {
						writeContext.Put(col, mt, v)
					}
				}

			}
		default:
			u.Errorf("could not project msg:  %T", msg)
		}

		//u.Debugf("completed projection for: %p %#v", out, outMsg)
		select {
		case out <- outMsg:
			return true
		case <-m.SigChan():
			return false
		}
	}
}
예제 #14
0
// Create handler function for evaluation (ie, field selection from tuples)
func projectionEvaluator(sql *expr.SqlSelect, task TaskRunner) MessageHandler {
	out := task.MessageOut()
	//evaluator := vm.Evaluator(where)
	return func(ctx *Context, msg datasource.Message) bool {
		defer func() {
			if r := recover(); r != nil {
				u.Errorf("crap, %v", r)
			}
		}()

		//u.Infof("got projection message: %#v", msg.Body())
		var outMsg datasource.Message
		switch mt := msg.(type) {
		case *datasource.SqlDriverMessageMap:
			// readContext := datasource.NewContextUrlValues(uv)
			// use our custom write context for example purposes
			writeContext := datasource.NewContextSimple()
			outMsg = writeContext
			//u.Infof("about to project: colsct%v %#v", len(sql.Columns), outMsg)
			for _, from := range sql.From {
				for _, col := range from.Columns {
					//u.Debugf("col:   %#v", col)
					if col.Guard != nil {
						ifColValue, ok := vm.Eval(mt, col.Guard)
						if !ok {
							u.Errorf("Could not evaluate if:   %v", col.Guard.StringAST())
							//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
						}
						//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
						switch ifColVal := ifColValue.(type) {
						case value.BoolValue:
							if ifColVal.Val() == false {
								//u.Debugf("Filtering out col")
								continue
							}
						}
					}
					if col.Star {
						for k, v := range mt.Vals {
							writeContext.Put(&expr.Column{As: k}, nil, value.NewValue(v))
						}
					} else {
						//u.Debugf("tree.Root: as?%v %v", col.As, col.Expr.String())
						v, ok := vm.Eval(mt, col.Expr)
						//u.Debugf("evaled: ok?%v key=%v  val=%v", ok, col.Key(), v)
						if ok {
							writeContext.Put(col, mt, v)
						}
					}
				}
			}

		case *datasource.ContextUrlValues:
			// readContext := datasource.NewContextUrlValues(uv)
			// use our custom write context for example purposes
			writeContext := datasource.NewContextSimple()
			outMsg = writeContext
			//u.Infof("about to project: colsct%v %#v", len(sql.Columns), outMsg)
			for _, col := range sql.Columns {
				//u.Debugf("col:   %#v", col)
				if col.Guard != nil {
					ifColValue, ok := vm.Eval(mt, col.Guard)
					if !ok {
						u.Errorf("Could not evaluate if:   %v", col.Guard.StringAST())
						//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
					}
					//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
					switch ifColVal := ifColValue.(type) {
					case value.BoolValue:
						if ifColVal.Val() == false {
							//u.Debugf("Filtering out col")
							continue
						}
					}
				}
				if col.Star {
					for k, v := range mt.Row() {
						writeContext.Put(&expr.Column{As: k}, nil, v)
					}
				} else {
					//u.Debugf("tree.Root: as?%v %#v", col.As, col.Expr)
					v, ok := vm.Eval(mt, col.Expr)
					//u.Debugf("evaled: ok?%v key=%v  val=%v", ok, col.Key(), v)
					if ok {
						writeContext.Put(col, mt, v)
					}
				}

			}
		default:
			u.Errorf("could not project msg:  %T", msg)
		}

		//u.Debugf("completed projection for: %p %#v", out, outMsg)
		select {
		case out <- outMsg:
			return true
		case <-task.SigChan():
			return false
		}
	}
}