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 }
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 }
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 }
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 }
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 }
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} }
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 }
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 }
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 }
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 }
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 }
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()) } } }
// 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 } } }
// 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 } } }