123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package interpreter
- import (
- "fmt"
- "regexp"
- "strconv"
- "strings"
- "devt.de/krotik/eliasdb/eql/parser"
- "devt.de/krotik/eliasdb/graph/data"
- )
- /*
- CondRuntime is a component of a condition which can be evaluated
- with a node and an edge.
- */
- type CondRuntime interface {
- /*
- CondEval evaluates this condition runtime element.
- */
- CondEval(node data.Node, edge data.Edge) (interface{}, error)
- }
- /*
- Abstract runtime for condition components
- */
- type whereItemRuntime struct {
- rtp *eqlRuntimeProvider
- astNode *parser.ASTNode
- }
- /*
- Validate this node and all its child nodes.
- */
- func (rt *whereItemRuntime) Validate() error {
- return rt.rtp.newRuntimeError(ErrInvalidConstruct, rt.astNode.Name, rt.astNode)
- }
- /*
- Eval evaluate this condition component.
- */
- func (rt *whereItemRuntime) Eval() (interface{}, error) {
- return nil, rt.rtp.newRuntimeError(ErrInvalidConstruct, rt.astNode.Name, rt.astNode)
- }
- /*
- valOp executes an operation on two abstract values.
- */
- func (rt *whereItemRuntime) valOp(node data.Node, edge data.Edge, op func(interface{}, interface{}) interface{}) (interface{}, error) {
- res1, err := rt.astNode.Children[0].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- res2, err := rt.astNode.Children[1].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- return op(res1, res2), nil
- }
- /*
- stringOp executes an operation on two strings.
- */
- func (rt *whereItemRuntime) stringOp(node data.Node, edge data.Edge, op func(string, string) interface{}) (interface{}, error) {
- res1, err := rt.astNode.Children[0].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- res2, err := rt.astNode.Children[1].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- return op(fmt.Sprint(res1), fmt.Sprint(res2)), nil
- }
- /*
- regexOp executes an operation on a string and a regex.
- */
- func (rt *whereItemRuntime) regexOp(node data.Node, edge data.Edge, op func(string, *regexp.Regexp) interface{}) (interface{}, error) {
- res1, err := rt.astNode.Children[0].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- res2, err := rt.astNode.Children[1].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- // Try to compile the regex
- res2String := fmt.Sprint(res2)
- regexp, err := regexp.Compile(res2String)
- if err != nil {
- return nil, rt.rtp.newRuntimeError(ErrNotARegex,
- fmt.Sprintf("%#v - %s", res2String, err.Error()), rt.astNode.Children[1])
- }
- return op(fmt.Sprint(res1), regexp), nil
- }
- /*
- numOp executes an operation on two number values.
- */
- func (rt *whereItemRuntime) numOp(node data.Node, edge data.Edge, op func(float64, float64) interface{}) (interface{}, error) {
- res1, err := rt.astNode.Children[0].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- res2, err := rt.astNode.Children[1].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- errDetail := func(tokenVal string, opVal string) string {
- if tokenVal == opVal {
- return opVal
- }
- return tokenVal + "=" + opVal
- }
- // Parse the values to numbers
- res1Str := fmt.Sprint(res1)
- res1Num, err := strconv.ParseFloat(res1Str, 64)
- if err != nil {
- return nil, rt.rtp.newRuntimeError(ErrNotANumber, errDetail(rt.astNode.Children[0].Token.Val, res1Str), rt.astNode.Children[0])
- }
- res2Str := fmt.Sprint(res2)
- res2Num, err := strconv.ParseFloat(res2Str, 64)
- if err != nil {
- return nil, rt.rtp.newRuntimeError(ErrNotANumber, errDetail(rt.astNode.Children[1].Token.Val, res2Str), rt.astNode.Children[1])
- }
- return op(res1Num, res2Num), nil
- }
- /*
- listOp executes a list operation on a single value and a list.
- */
- func (rt *whereItemRuntime) listOp(node data.Node, edge data.Edge, op func(interface{}, []interface{}) interface{}) (interface{}, error) {
- res1, err := rt.astNode.Children[0].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- res2, err := rt.astNode.Children[1].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- errDetail := func(tokenVal string, opVal string) string {
- if tokenVal == opVal {
- return opVal
- }
- return tokenVal + "=" + opVal
- }
- // Parse right value to a list
- res2List, ok := res2.([]interface{})
- if !ok {
- return nil, rt.rtp.newRuntimeError(ErrNotAList, errDetail(rt.astNode.Children[1].Token.Val, fmt.Sprint(res2)), rt.astNode.Children[1])
- }
- return op(res1, res2List), nil
- }
- /*
- boolOp executes an operation on two boolean values. Can optionally try a
- short circuit operation.
- */
- func (rt *whereItemRuntime) boolOp(node data.Node, edge data.Edge, op func(bool, bool) interface{},
- scop func(bool) interface{}) (interface{}, error) {
- res1, err := rt.astNode.Children[0].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- if len(rt.astNode.Children) == 1 {
- // Special case for "not" operation
- return op(toBool(res1), false), nil
- }
- // Try short circuit
- res1bool := toBool(res1)
- if scop != nil {
- if ret := scop(res1bool); ret != nil {
- return ret, nil
- }
- }
- res2, err := rt.astNode.Children[1].Runtime.(CondRuntime).CondEval(node, edge)
- if err != nil {
- return nil, err
- }
- return op(res1bool, toBool(res2)), nil
- }
- /*
- toBool is a helper function to turn any value into a boolean.
- */
- func toBool(res interface{}) bool {
- switch res := res.(type) {
- default:
- return res != nil
- case bool:
- return res
- case float64:
- return res > 0
- case string:
- // Try to convert the string into a number
- num, err := strconv.ParseFloat(res, 64)
- if err == nil {
- return num > 0
- }
- return res != ""
- }
- }
- func equals(res1 interface{}, res2 interface{}) bool {
- // Try to convert the string into a number
- num1, err := strconv.ParseFloat(fmt.Sprint(res1), 64)
- if err == nil {
- num2, err := strconv.ParseFloat(fmt.Sprint(res2), 64)
- if err == nil {
- return num1 == num2
- }
- }
- return fmt.Sprintf("%v", res1) == fmt.Sprintf("%v", res2)
- }
- // Where runtime
- // =============
- /*
- Runtime for where
- */
- type whereRuntime struct {
- rtp *eqlRuntimeProvider
- astNode *parser.ASTNode
- specIndex int // Index of this traversal in the traversals array
- }
- /*
- whereRuntimeInst returns a new runtime component instance.
- */
- func whereRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &whereRuntime{rtp, node, 0}
- }
- /*
- Validate this node and all its child nodes.
- */
- func (rt *whereRuntime) Validate() error {
- var visitChildren func(astNode *parser.ASTNode) error
- visitChildren = func(astNode *parser.ASTNode) error {
- // Determine which values should be interpreted as node attributes
- if astNode.Name == parser.NodeVALUE {
- val := astNode.Token.Val
- lcval := strings.ToLower(val)
- valRuntime, ok := astNode.Runtime.(*valueRuntime)
- if !ok {
- return astNode.Runtime.Validate()
- }
- if strings.HasPrefix(lcval, "eattr:") {
- valRuntime.condVal = val[6:]
- valRuntime.isNodeAttrValue = false
- valRuntime.isEdgeAttrValue = true
- } else if strings.HasPrefix(lcval, "attr:") {
- valRuntime.condVal = val[5:]
- valRuntime.isNodeAttrValue = true
- valRuntime.isEdgeAttrValue = false
- } else if strings.HasPrefix(lcval, "val:") {
- valRuntime.condVal = val[4:]
- valRuntime.isNodeAttrValue = false
- valRuntime.isEdgeAttrValue = false
- } else {
- valRuntime.condVal = val
- valRuntime.isNodeAttrValue = rt.rtp.ni.IsValidAttr(val)
- valRuntime.isEdgeAttrValue = false
- // Check if we have a nested value
- if strings.Contains(val, ".") {
- nestedValuePath := strings.Split(val, ".")
- if rt.rtp.ni.IsValidAttr(nestedValuePath[0]) {
- valRuntime.condVal = nestedValuePath[0]
- valRuntime.nestedValuePath = nestedValuePath
- valRuntime.isNodeAttrValue = true
- }
- }
- }
- // Make sure attributes are queried
- if valRuntime.isNodeAttrValue {
- rt.rtp.attrsNodes[rt.specIndex][valRuntime.condVal] = ""
- } else if valRuntime.isEdgeAttrValue {
- rt.rtp.attrsEdges[rt.specIndex][valRuntime.condVal] = ""
- }
- }
- for _, child := range astNode.Children {
- if err := visitChildren(child); err != nil {
- return err
- }
- }
- return nil
- }
- return visitChildren(rt.astNode)
- }
- /*
- Eval evaluates the where clause a
- */
- func (rt *whereRuntime) Eval() (interface{}, error) {
- return nil, rt.rtp.newRuntimeError(ErrInvalidConstruct, rt.astNode.Name, rt.astNode)
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *whereRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- res, err := rt.astNode.Children[0].Runtime.(CondRuntime).CondEval(node, edge)
- return toBool(res), err
- }
- // Where related runtimes
- // ======================
- /*
- Equal runtime
- */
- type equalRuntime struct {
- *whereItemRuntime
- }
- /*
- equalRuntimeInst returns a new runtime component instance.
- */
- func equalRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &equalRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- Evaluate this condition runtime element.
- */
- func (rt *equalRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.valOp(node, edge, func(res1 interface{}, res2 interface{}) interface{} { return equals(res1, res2) })
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- type notEqualRuntime struct {
- *whereItemRuntime
- }
- /*
- notEqualRuntimeInst returns a new runtime component instance.
- */
- func notEqualRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return ¬EqualRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *notEqualRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.valOp(node, edge, func(res1 interface{}, res2 interface{}) interface{} { return !equals(res1, res2) })
- }
- /*
- Less than runtime
- */
- type lessThanRuntime struct {
- *whereItemRuntime
- }
- /*
- lessThanRuntimeInst returns a new runtime component instance.
- */
- func lessThanRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &lessThanRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *lessThanRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- ret, err := rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return res1 < res2 })
- if err != nil {
- // Do a simple string ordering
- ret, err = rt.valOp(node, edge, func(res1 interface{}, res2 interface{}) interface{} { return fmt.Sprint(res1) < fmt.Sprint(res2) })
- }
- return ret, err
- }
- /*
- Less than equals runtime
- */
- type lessThanEqualsRuntime struct {
- *whereItemRuntime
- }
- /*
- lessThanEqualsRuntimeInst returns a new runtime component instance.
- */
- func lessThanEqualsRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &lessThanEqualsRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *lessThanEqualsRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- ret, err := rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return res1 <= res2 })
- if err != nil {
- // Do a simple string ordering
- ret, err = rt.valOp(node, edge, func(res1 interface{}, res2 interface{}) interface{} { return fmt.Sprint(res1) <= fmt.Sprint(res2) })
- }
- return ret, err
- }
- /*
- Greater than runtime
- */
- type greaterThanRuntime struct {
- *whereItemRuntime
- }
- /*
- greaterThanRuntimeInst returns a new runtime component instance.
- */
- func greaterThanRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &greaterThanRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *greaterThanRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- ret, err := rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return res1 > res2 })
- if err != nil {
- // Do a simple string ordering
- ret, err = rt.valOp(node, edge, func(res1 interface{}, res2 interface{}) interface{} { return fmt.Sprint(res1) > fmt.Sprint(res2) })
- }
- return ret, err
- }
- /*
- Greater than equals runtime
- */
- type greaterThanEqualsRuntime struct {
- *whereItemRuntime
- }
- /*
- greaterThanEqualsRuntimeInst returns a new runtime component instance.
- */
- func greaterThanEqualsRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &greaterThanEqualsRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *greaterThanEqualsRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- ret, err := rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return res1 >= res2 })
- if err != nil {
- // Do a simple string ordering
- ret, err = rt.valOp(node, edge, func(res1 interface{}, res2 interface{}) interface{} { return fmt.Sprint(res1) >= fmt.Sprint(res2) })
- }
- return ret, err
- }
- /*
- And runtime
- */
- type andRuntime struct {
- *whereItemRuntime
- }
- /*
- andRuntimeInst returns a new runtime component instance.
- */
- func andRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &andRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *andRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.boolOp(node, edge, func(res1 bool, res2 bool) interface{} { return res1 && res2 },
- func(res1 bool) interface{} {
- if !res1 {
- return false
- }
- return nil
- })
- }
- /*
- Or runtime
- */
- type orRuntime struct {
- *whereItemRuntime
- }
- /*
- orRuntimeInst returns a new runtime component instance.
- */
- func orRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &orRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *orRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.boolOp(node, edge, func(res1 bool, res2 bool) interface{} { return res1 || res2 },
- func(res1 bool) interface{} {
- if res1 {
- return true
- }
- return nil
- })
- }
- /*
- Not runtime
- */
- type notRuntime struct {
- *whereItemRuntime
- }
- /*
- notRuntimeInst returns a new runtime component instance.
- */
- func notRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return ¬Runtime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *notRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.boolOp(node, edge, func(res1 bool, res2 bool) interface{} { return !res1 }, nil)
- }
- /*
- Plus runtime
- */
- type plusRuntime struct {
- *whereItemRuntime
- }
- /*
- plusRuntimeInst returns a new runtime component instance.
- */
- func plusRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &plusRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *plusRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return res1 + res2 })
- }
- /*
- Minus runtime
- */
- type minusRuntime struct {
- *whereItemRuntime
- }
- /*
- minusRuntimeInst returns a new runtime component instance.
- */
- func minusRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &minusRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *minusRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return res1 - res2 })
- }
- /*
- Times runtime
- */
- type timesRuntime struct {
- *whereItemRuntime
- }
- /*
- timesRuntimeInst returns a new runtime component instance.
- */
- func timesRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return ×Runtime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *timesRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return res1 * res2 })
- }
- /*
- Div runtime
- */
- type divRuntime struct {
- *whereItemRuntime
- }
- /*
- divRuntimeInst returns a new runtime component instance.
- */
- func divRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &divRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *divRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return res1 / res2 })
- }
- /*
- ModInt runtime
- */
- type modIntRuntime struct {
- *whereItemRuntime
- }
- /*
- modIntRuntimeInst returns a new runtime component instance.
- */
- func modIntRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &modIntRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *modIntRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return int(int(res1) % int(res2)) })
- }
- /*
- DivInt runtime
- */
- type divIntRuntime struct {
- *whereItemRuntime
- }
- /*
- divIntRuntimeInst returns a new runtime component instance.
- */
- func divIntRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &divIntRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *divIntRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.numOp(node, edge, func(res1 float64, res2 float64) interface{} { return int(int(res1) / int(res2)) })
- }
- /*
- In runtime
- */
- type inRuntime struct {
- *whereItemRuntime
- }
- /*
- inRuntimeInst returns a new runtime component instance.
- */
- func inRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &inRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *inRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.listOp(node, edge, func(res1 interface{}, res2 []interface{}) interface{} {
- for _, item := range res2 {
- if equals(res1, item) {
- return true
- }
- }
- return false
- })
- }
- /*
- Not in runtime
- */
- type notInRuntime struct {
- *whereItemRuntime
- }
- /*
- notInRuntimeInst returns a new runtime component instance.
- */
- func notInRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return ¬InRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *notInRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.listOp(node, edge, func(res1 interface{}, res2 []interface{}) interface{} {
- for _, item := range res2 {
- if equals(res1, item) {
- return false
- }
- }
- return true
- })
- }
- /*
- Like runtime
- */
- type likeRuntime struct {
- compiledRegex *regexp.Regexp // Quick lookup of the compiled regex if it is a constant
- *whereItemRuntime
- }
- /*
- likeRuntimeInst returns a new runtime component instance.
- */
- func likeRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &likeRuntime{nil, &whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *likeRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- // Check for constant regexp
- if valRT, ok := rt.astNode.Children[1].Runtime.(*valueRuntime); ok {
- if !valRT.isNodeAttrValue && !valRT.isEdgeAttrValue {
- // Given regex is a constant and only needs to be compiled once
- val, _ := valRT.CondEval(node, edge)
- valStr := fmt.Sprint(val)
- regexp, err := regexp.Compile(valStr)
- if err != nil {
- return nil, rt.rtp.newRuntimeError(ErrNotARegex,
- fmt.Sprintf("%#v - %s", valStr, err.Error()), rt.astNode.Children[1])
- }
- rt.compiledRegex = regexp
- }
- }
- if rt.compiledRegex == nil {
- return rt.regexOp(node, edge, func(res1 string, res2 *regexp.Regexp) interface{} { return res2.MatchString(res1) })
- }
- return rt.stringOp(node, edge, func(res1 string, res2 string) interface{} { return rt.compiledRegex.MatchString(res1) })
- }
- /*
- Contains runtime
- */
- type containsRuntime struct {
- *whereItemRuntime
- }
- /*
- containsRuntimeInst returns a new runtime component instance.
- */
- func containsRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &containsRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *containsRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.stringOp(node, edge, func(res1 string, res2 string) interface{} { return strings.Contains(res1, res2) })
- }
- /*
- Contains not runtime
- */
- type containsNotRuntime struct {
- *whereItemRuntime
- }
- /*
- containsNotRuntimeInst returns a new runtime component instance.
- */
- func containsNotRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &containsNotRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *containsNotRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.stringOp(node, edge, func(res1 string, res2 string) interface{} { return !strings.Contains(res1, res2) })
- }
- /*
- Begins with runtime
- */
- type beginsWithRuntime struct {
- *whereItemRuntime
- }
- /*
- beginsWithRuntimeInst returns a new runtime component instance.
- */
- func beginsWithRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &beginsWithRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *beginsWithRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.stringOp(node, edge, func(res1 string, res2 string) interface{} { return strings.HasPrefix(res1, res2) })
- }
- /*
- Ends with runtime
- */
- type endsWithRuntime struct {
- *whereItemRuntime
- }
- /*
- endsWithRuntimeInst returns a new runtime component instance.
- */
- func endsWithRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &endsWithRuntime{&whereItemRuntime{rtp, node}}
- }
- /*
- CondEval evaluates this condition runtime element.
- */
- func (rt *endsWithRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {
- return rt.stringOp(node, edge, func(res1 string, res2 string) interface{} { return strings.HasSuffix(res1, res2) })
- }
|