From 3989b363ceb19ba0258e48c9012d1acd1dc06acb Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Tue, 1 Feb 2022 08:30:48 -0700 Subject: [PATCH 01/14] Add variable support to PQL --- pql/ast.go | 55 + pql/pql.peg | 3 + pql/pql.peg.go | 2690 +++++++++++++++++++++++--------------------- pql/pqlpeg_test.go | 9 + 4 files changed, 1462 insertions(+), 1295 deletions(-) diff --git a/pql/ast.go b/pql/ast.go index 538810c2c..a4d14b7b9 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -19,6 +19,22 @@ type Query struct { conditional []string } +// ExpandVars recursively replaces variables in the query with their values. +func (q *Query) ExpandVars(vars map[string]interface{}) (*Query, error) { + other := *q + other.Calls = make([]*Call, 0, len(q.Calls)) + + for _, c := range q.Calls { + newCalls, err := c.ExpandVars(vars) + if err != nil { + return err + } + other.Calls = append(other.Calls, newCalls...) + } + + return q, nil +} + func (q *Query) startCall(name string) { // Coerce every name into a canonical form if we know of one. if canon, ok := canonicalCaps[strings.ToLower(name)]; ok { @@ -896,6 +912,28 @@ func (c *Call) ArgString(key string) string { return s } +// ExpandVars recursively replaces variables in the call with their values. +func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { + other := *c + other.Args = CopyArgs(c.Args) + other.Children = make([]*Call, 0, len(c.Children)) + + // TODO: Replace field variables. + + // Recursively expand variables in children. + for _, child := range c.Children { + newChildren, err := child.ExpandVars(vars) + if err != nil { + return nil, err + } + other.Children = append(other.Children, newChildren...) + } + + // TODO: Return multiple calls for list. + + return []*Call{&other}, nil +} + // Condition represents an operation & value. // When used in an argument map it represents a binary expression. type Condition struct { @@ -1034,6 +1072,21 @@ func (cond *Condition) StringSliceValue() ([]string, bool) { return nil, false } +// Variable represents a placeholder variable in a query. +type Variable struct { + Name string +} + +// NewVariable returns a new instance of Variable. +func NewVariable(name string) *Variable { + return &Variable{Name: name} +} + +// String returns the string representation of v. +func (v *Variable) String() string { + return "$" + v.Name +} + func formatValue(v interface{}) string { switch v := v.(type) { case nil: @@ -1048,6 +1101,8 @@ func formatValue(v interface{}) string { return fmt.Sprintf("\"%s\"", v.Format(time.RFC3339Nano)) case *Condition: return v.String() + case *Variable: + return v.String() default: return fmt.Sprintf("%v", v) } diff --git a/pql/pql.peg b/pql/pql.peg index a5590132d..42b119512 100644 --- a/pql/pql.peg +++ b/pql/pql.peg @@ -43,6 +43,7 @@ items <- item (comma items)? item <- 'null' &(comma / close) { p.addVal(nil) } / 'true' &(comma / close) { p.addVal(true) } / 'false' &(comma / close) { p.addVal(false) } + / '$' < variable > { p.addVal(NewVariable(text)) } / timefmt { p.addVal(text) } / timestampfmt { p.addTimestampVal(text) } / < decimal > { p.addNumVal(text) } @@ -54,6 +55,8 @@ item <- 'null' &(comma / close) { p.addVal(nil) } doublequotedstring <- ( '\\"' / '\\\\' / '\\n' / '\\t' / [^"\\] )* singlequotedstring <- ( '\\\'' / '\\\\' / '\\n' / '\\t' / [^'\\] )* +variable <- ( [[A-Z]] / '_' ) ( [[A-Z]] / [0-9] / '_' / '-' )* + fieldExpr <- ( [[A-Z]] / '_' ) ( [[A-Z]] / [0-9] / '_' / '-' )* field <- { p.addField(text) } reserved <- '_row' / '_col' / '_start' / '_end' / '_timestamp' / '_field' diff --git a/pql/pql.peg.go b/pql/pql.peg.go index bbc48da7f..694d07b35 100644 --- a/pql/pql.peg.go +++ b/pql/pql.peg.go @@ -8,6 +8,7 @@ import ( "os" "sort" "strconv" + "strings" ) const endSymbol rune = 1114112 @@ -32,6 +33,7 @@ const ( ruleitem ruledoublequotedstring rulesinglequotedstring + rulevariable rulefieldExpr rulefield rulereserved @@ -118,6 +120,7 @@ const ( ruleAction58 ruleAction59 ruleAction60 + ruleAction61 ) var rul3s = [...]string{ @@ -137,6 +140,7 @@ var rul3s = [...]string{ "item", "doublequotedstring", "singlequotedstring", + "variable", "fieldExpr", "field", "reserved", @@ -223,6 +227,7 @@ var rul3s = [...]string{ "Action58", "Action59", "Action60", + "Action61", } type token32 struct { @@ -251,7 +256,7 @@ func (node *node32) print(w io.Writer, pretty bool, buffer string) { if !pretty { fmt.Fprintf(w, "%v %v\n", rule, quote) } else { - fmt.Fprintf(w, "\x1B[34m%v\x1B[m %v\n", rule, quote) + fmt.Fprintf(w, "\x1B[36m%v\x1B[m %v\n", rule, quote) } if node.up != nil { print(node.up, depth+1) @@ -339,7 +344,7 @@ type PQL struct { Buffer string buffer []rune - rules [102]func() bool + rules [104]func() bool parse func(rule ...int) error reset func() Pretty bool @@ -426,6 +431,12 @@ func (p *PQL) WriteSyntaxTree(w io.Writer) { p.tokens32.WriteSyntaxTree(w, p.Buffer) } +func (p *PQL) SprintSyntaxTree() string { + var bldr strings.Builder + p.WriteSyntaxTree(&bldr) + return bldr.String() +} + func (p *PQL) Execute() { buffer, _buffer, text, begin, end := p.Buffer, p.buffer, "", 0, 0 for _, token := range p.Tokens() { @@ -530,32 +541,34 @@ func (p *PQL) Execute() { case ruleAction46: p.addVal(false) case ruleAction47: - p.addVal(text) + p.addVal(NewVariable(text)) case ruleAction48: - p.addTimestampVal(text) - case ruleAction49: - p.addNumVal(text) - case ruleAction50: - p.startCall(text) - case ruleAction51: - p.addVal(p.endCall()) - case ruleAction52: p.addVal(text) + case ruleAction49: + p.addTimestampVal(text) + case ruleAction50: + p.addNumVal(text) + case ruleAction51: + p.startCall(text) + case ruleAction52: + p.addVal(p.endCall()) case ruleAction53: p.addVal(text) case ruleAction54: p.addVal(text) case ruleAction55: - p.addField(text) + p.addVal(text) case ruleAction56: - p.addPosStr("_field", text) + p.addField(text) case ruleAction57: - p.addPosNum("_col", text) + p.addPosStr("_field", text) case ruleAction58: - p.addPosStr("_col", text) + p.addPosNum("_col", text) case ruleAction59: p.addPosStr("_col", text) case ruleAction60: + p.addPosStr("_col", text) + case ruleAction61: p.addPosStr("_timestamp", text) } @@ -769,7 +782,7 @@ func (p *PQL) Init(options ...func(*PQL) error) error { add(rulePegText, position19) } { - add(ruleAction60, position) + add(ruleAction61, position) } add(ruletime, position18) } @@ -2439,7 +2452,7 @@ func (p *PQL) Init(options ...func(*PQL) error) error { position, tokenIndex = position250, tokenIndex250 return false }, - /* 12 item <- <(('n' 'u' 'l' 'l' &(comma / close) Action44) / ('t' 'r' 'u' 'e' &(comma / close) Action45) / ('f' 'a' 'l' 's' 'e' &(comma / close) Action46) / (timefmt Action47) / (timestampfmt Action48) / ( Action49) / ( Action50 open allargs comma? close Action51) / (<([a-z] / [A-Z] / [0-9] / '-' / '_' / ':')+> Action52) / (<('"' doublequotedstring '"')> Action53) / (<('\'' singlequotedstring '\'')> Action54))> */ + /* 12 item <- <(('n' 'u' 'l' 'l' &(comma / close) Action44) / ('t' 'r' 'u' 'e' &(comma / close) Action45) / ('f' 'a' 'l' 's' 'e' &(comma / close) Action46) / ('$' Action47) / (timefmt Action48) / (timestampfmt Action49) / ( Action50) / ( Action51 open allargs comma? close Action52) / (<([a-z] / [A-Z] / [0-9] / '-' / '_' / ':')+> Action53) / (<('"' doublequotedstring '"')> Action54) / (<('\'' singlequotedstring '\'')> Action55))> */ func() bool { position254, tokenIndex254 := position, tokenIndex { @@ -2567,246 +2580,329 @@ func (p *PQL) Init(options ...func(*PQL) error) error { goto l256 l267: position, tokenIndex = position256, tokenIndex256 - if !_rules[ruletimefmt]() { + if buffer[position] != rune('$') { goto l272 } + position++ + { + position273 := position + { + position274 := position + { + position275, tokenIndex275 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l276 + } + position++ + goto l275 + l276: + position, tokenIndex = position275, tokenIndex275 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l277 + } + position++ + goto l275 + l277: + position, tokenIndex = position275, tokenIndex275 + if buffer[position] != rune('_') { + goto l272 + } + position++ + } + l275: + l278: + { + position279, tokenIndex279 := position, tokenIndex + { + position280, tokenIndex280 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l281 + } + position++ + goto l280 + l281: + position, tokenIndex = position280, tokenIndex280 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l282 + } + position++ + goto l280 + l282: + position, tokenIndex = position280, tokenIndex280 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l283 + } + position++ + goto l280 + l283: + position, tokenIndex = position280, tokenIndex280 + if buffer[position] != rune('_') { + goto l284 + } + position++ + goto l280 + l284: + position, tokenIndex = position280, tokenIndex280 + if buffer[position] != rune('-') { + goto l279 + } + position++ + } + l280: + goto l278 + l279: + position, tokenIndex = position279, tokenIndex279 + } + add(rulevariable, position274) + } + add(rulePegText, position273) + } { add(ruleAction47, position) } goto l256 l272: position, tokenIndex = position256, tokenIndex256 - { - position275 := position - { - position276, tokenIndex276 := position, tokenIndex - if buffer[position] != rune('"') { - goto l277 - } - position++ - { - position278 := position - if !_rules[ruletimestampbasicfmt]() { - goto l277 - } - add(rulePegText, position278) - } - if buffer[position] != rune('"') { - goto l277 - } - position++ - goto l276 - l277: - position, tokenIndex = position276, tokenIndex276 - if buffer[position] != rune('\'') { - goto l279 - } - position++ - { - position280 := position - if !_rules[ruletimestampbasicfmt]() { - goto l279 - } - add(rulePegText, position280) - } - if buffer[position] != rune('\'') { - goto l279 - } - position++ - goto l276 - l279: - position, tokenIndex = position276, tokenIndex276 - { - position281 := position - if !_rules[ruletimestampbasicfmt]() { - goto l274 - } - add(rulePegText, position281) - } - } - l276: - add(ruletimestampfmt, position275) + if !_rules[ruletimefmt]() { + goto l286 } { add(ruleAction48, position) } goto l256 - l274: + l286: position, tokenIndex = position256, tokenIndex256 { - position284 := position - if !_rules[ruledecimal]() { - goto l283 + position289 := position + { + position290, tokenIndex290 := position, tokenIndex + if buffer[position] != rune('"') { + goto l291 + } + position++ + { + position292 := position + if !_rules[ruletimestampbasicfmt]() { + goto l291 + } + add(rulePegText, position292) + } + if buffer[position] != rune('"') { + goto l291 + } + position++ + goto l290 + l291: + position, tokenIndex = position290, tokenIndex290 + if buffer[position] != rune('\'') { + goto l293 + } + position++ + { + position294 := position + if !_rules[ruletimestampbasicfmt]() { + goto l293 + } + add(rulePegText, position294) + } + if buffer[position] != rune('\'') { + goto l293 + } + position++ + goto l290 + l293: + position, tokenIndex = position290, tokenIndex290 + { + position295 := position + if !_rules[ruletimestampbasicfmt]() { + goto l288 + } + add(rulePegText, position295) + } } - add(rulePegText, position284) + l290: + add(ruletimestampfmt, position289) } { add(ruleAction49, position) } goto l256 - l283: + l288: position, tokenIndex = position256, tokenIndex256 { - position287 := position - if !_rules[ruleIDENT]() { - goto l286 + position298 := position + if !_rules[ruledecimal]() { + goto l297 } - add(rulePegText, position287) + add(rulePegText, position298) } { add(ruleAction50, position) } - if !_rules[ruleopen]() { - goto l286 - } - if !_rules[ruleallargs]() { - goto l286 - } + goto l256 + l297: + position, tokenIndex = position256, tokenIndex256 { - position289, tokenIndex289 := position, tokenIndex - if !_rules[rulecomma]() { - goto l289 + position301 := position + if !_rules[ruleIDENT]() { + goto l300 } - goto l290 - l289: - position, tokenIndex = position289, tokenIndex289 - } - l290: - if !_rules[ruleclose]() { - goto l286 + add(rulePegText, position301) } { add(ruleAction51, position) } - goto l256 - l286: - position, tokenIndex = position256, tokenIndex256 + if !_rules[ruleopen]() { + goto l300 + } + if !_rules[ruleallargs]() { + goto l300 + } { - position293 := position - { - position296, tokenIndex296 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l297 - } - position++ - goto l296 - l297: - position, tokenIndex = position296, tokenIndex296 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l298 - } - position++ - goto l296 - l298: - position, tokenIndex = position296, tokenIndex296 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l299 - } - position++ - goto l296 - l299: - position, tokenIndex = position296, tokenIndex296 - if buffer[position] != rune('-') { - goto l300 - } - position++ - goto l296 - l300: - position, tokenIndex = position296, tokenIndex296 - if buffer[position] != rune('_') { - goto l301 - } - position++ - goto l296 - l301: - position, tokenIndex = position296, tokenIndex296 - if buffer[position] != rune(':') { - goto l292 - } - position++ + position303, tokenIndex303 := position, tokenIndex + if !_rules[rulecomma]() { + goto l303 } - l296: - l294: - { - position295, tokenIndex295 := position, tokenIndex - { - position302, tokenIndex302 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l303 - } - position++ - goto l302 - l303: - position, tokenIndex = position302, tokenIndex302 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l304 - } - position++ - goto l302 - l304: - position, tokenIndex = position302, tokenIndex302 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l305 - } - position++ - goto l302 - l305: - position, tokenIndex = position302, tokenIndex302 - if buffer[position] != rune('-') { - goto l306 - } - position++ - goto l302 - l306: - position, tokenIndex = position302, tokenIndex302 - if buffer[position] != rune('_') { - goto l307 - } - position++ - goto l302 - l307: - position, tokenIndex = position302, tokenIndex302 - if buffer[position] != rune(':') { - goto l295 - } - position++ - } - l302: - goto l294 - l295: - position, tokenIndex = position295, tokenIndex295 - } - add(rulePegText, position293) + goto l304 + l303: + position, tokenIndex = position303, tokenIndex303 + } + l304: + if !_rules[ruleclose]() { + goto l300 } { add(ruleAction52, position) } goto l256 - l292: + l300: position, tokenIndex = position256, tokenIndex256 { - position310 := position - if buffer[position] != rune('"') { - goto l309 + position307 := position + { + position310, tokenIndex310 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l311 + } + position++ + goto l310 + l311: + position, tokenIndex = position310, tokenIndex310 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l312 + } + position++ + goto l310 + l312: + position, tokenIndex = position310, tokenIndex310 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l313 + } + position++ + goto l310 + l313: + position, tokenIndex = position310, tokenIndex310 + if buffer[position] != rune('-') { + goto l314 + } + position++ + goto l310 + l314: + position, tokenIndex = position310, tokenIndex310 + if buffer[position] != rune('_') { + goto l315 + } + position++ + goto l310 + l315: + position, tokenIndex = position310, tokenIndex310 + if buffer[position] != rune(':') { + goto l306 + } + position++ } - position++ - if !_rules[ruledoublequotedstring]() { - goto l309 + l310: + l308: + { + position309, tokenIndex309 := position, tokenIndex + { + position316, tokenIndex316 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l317 + } + position++ + goto l316 + l317: + position, tokenIndex = position316, tokenIndex316 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l318 + } + position++ + goto l316 + l318: + position, tokenIndex = position316, tokenIndex316 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l319 + } + position++ + goto l316 + l319: + position, tokenIndex = position316, tokenIndex316 + if buffer[position] != rune('-') { + goto l320 + } + position++ + goto l316 + l320: + position, tokenIndex = position316, tokenIndex316 + if buffer[position] != rune('_') { + goto l321 + } + position++ + goto l316 + l321: + position, tokenIndex = position316, tokenIndex316 + if buffer[position] != rune(':') { + goto l309 + } + position++ + } + l316: + goto l308 + l309: + position, tokenIndex = position309, tokenIndex309 } - if buffer[position] != rune('"') { - goto l309 - } - position++ - add(rulePegText, position310) + add(rulePegText, position307) } { add(ruleAction53, position) } goto l256 - l309: + l306: position, tokenIndex = position256, tokenIndex256 { - position312 := position + position324 := position + if buffer[position] != rune('"') { + goto l323 + } + position++ + if !_rules[ruledoublequotedstring]() { + goto l323 + } + if buffer[position] != rune('"') { + goto l323 + } + position++ + add(rulePegText, position324) + } + { + add(ruleAction54, position) + } + goto l256 + l323: + position, tokenIndex = position256, tokenIndex256 + { + position326 := position if buffer[position] != rune('\'') { goto l254 } @@ -2818,10 +2914,10 @@ func (p *PQL) Init(options ...func(*PQL) error) error { goto l254 } position++ - add(rulePegText, position312) + add(rulePegText, position326) } { - add(ruleAction54, position) + add(ruleAction55, position) } } l256: @@ -2835,731 +2931,632 @@ func (p *PQL) Init(options ...func(*PQL) error) error { /* 13 doublequotedstring <- <(('\\' '"') / ('\\' '\\') / ('\\' 'n') / ('\\' 't') / (!('"' / '\\') .))*> */ func() bool { { - position315 := position - l316: + position329 := position + l330: { - position317, tokenIndex317 := position, tokenIndex + position331, tokenIndex331 := position, tokenIndex { - position318, tokenIndex318 := position, tokenIndex + position332, tokenIndex332 := position, tokenIndex if buffer[position] != rune('\\') { - goto l319 + goto l333 } position++ if buffer[position] != rune('"') { - goto l319 + goto l333 } position++ - goto l318 - l319: - position, tokenIndex = position318, tokenIndex318 + goto l332 + l333: + position, tokenIndex = position332, tokenIndex332 if buffer[position] != rune('\\') { - goto l320 + goto l334 } position++ if buffer[position] != rune('\\') { - goto l320 + goto l334 } position++ - goto l318 - l320: - position, tokenIndex = position318, tokenIndex318 + goto l332 + l334: + position, tokenIndex = position332, tokenIndex332 if buffer[position] != rune('\\') { - goto l321 + goto l335 } position++ if buffer[position] != rune('n') { - goto l321 + goto l335 } position++ - goto l318 - l321: - position, tokenIndex = position318, tokenIndex318 + goto l332 + l335: + position, tokenIndex = position332, tokenIndex332 if buffer[position] != rune('\\') { - goto l322 + goto l336 } position++ if buffer[position] != rune('t') { - goto l322 + goto l336 } position++ - goto l318 - l322: - position, tokenIndex = position318, tokenIndex318 + goto l332 + l336: + position, tokenIndex = position332, tokenIndex332 { - position323, tokenIndex323 := position, tokenIndex + position337, tokenIndex337 := position, tokenIndex { - position324, tokenIndex324 := position, tokenIndex + position338, tokenIndex338 := position, tokenIndex if buffer[position] != rune('"') { - goto l325 + goto l339 } position++ - goto l324 - l325: - position, tokenIndex = position324, tokenIndex324 + goto l338 + l339: + position, tokenIndex = position338, tokenIndex338 if buffer[position] != rune('\\') { - goto l323 + goto l337 } position++ } - l324: - goto l317 - l323: - position, tokenIndex = position323, tokenIndex323 + l338: + goto l331 + l337: + position, tokenIndex = position337, tokenIndex337 } if !matchDot() { - goto l317 + goto l331 } } - l318: - goto l316 - l317: - position, tokenIndex = position317, tokenIndex317 + l332: + goto l330 + l331: + position, tokenIndex = position331, tokenIndex331 } - add(ruledoublequotedstring, position315) + add(ruledoublequotedstring, position329) } return true }, /* 14 singlequotedstring <- <(('\\' '\'') / ('\\' '\\') / ('\\' 'n') / ('\\' 't') / (!('\'' / '\\') .))*> */ func() bool { { - position327 := position - l328: + position341 := position + l342: { - position329, tokenIndex329 := position, tokenIndex + position343, tokenIndex343 := position, tokenIndex { - position330, tokenIndex330 := position, tokenIndex + position344, tokenIndex344 := position, tokenIndex if buffer[position] != rune('\\') { - goto l331 + goto l345 } position++ if buffer[position] != rune('\'') { - goto l331 + goto l345 } position++ - goto l330 - l331: - position, tokenIndex = position330, tokenIndex330 + goto l344 + l345: + position, tokenIndex = position344, tokenIndex344 if buffer[position] != rune('\\') { - goto l332 - } - position++ - if buffer[position] != rune('\\') { - goto l332 - } - position++ - goto l330 - l332: - position, tokenIndex = position330, tokenIndex330 - if buffer[position] != rune('\\') { - goto l333 - } - position++ - if buffer[position] != rune('n') { - goto l333 - } - position++ - goto l330 - l333: - position, tokenIndex = position330, tokenIndex330 - if buffer[position] != rune('\\') { - goto l334 - } - position++ - if buffer[position] != rune('t') { - goto l334 - } - position++ - goto l330 - l334: - position, tokenIndex = position330, tokenIndex330 - { - position335, tokenIndex335 := position, tokenIndex - { - position336, tokenIndex336 := position, tokenIndex - if buffer[position] != rune('\'') { - goto l337 - } - position++ - goto l336 - l337: - position, tokenIndex = position336, tokenIndex336 - if buffer[position] != rune('\\') { - goto l335 - } - position++ - } - l336: - goto l329 - l335: - position, tokenIndex = position335, tokenIndex335 - } - if !matchDot() { - goto l329 - } - } - l330: - goto l328 - l329: - position, tokenIndex = position329, tokenIndex329 - } - add(rulesinglequotedstring, position327) - } - return true - }, - /* 15 fieldExpr <- <(([a-z] / [A-Z] / '_') ([a-z] / [A-Z] / [0-9] / '_' / '-')*)> */ - func() bool { - position338, tokenIndex338 := position, tokenIndex - { - position339 := position - { - position340, tokenIndex340 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l341 - } - position++ - goto l340 - l341: - position, tokenIndex = position340, tokenIndex340 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l342 - } - position++ - goto l340 - l342: - position, tokenIndex = position340, tokenIndex340 - if buffer[position] != rune('_') { - goto l338 - } - position++ - } - l340: - l343: - { - position344, tokenIndex344 := position, tokenIndex - { - position345, tokenIndex345 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { goto l346 } position++ - goto l345 + if buffer[position] != rune('\\') { + goto l346 + } + position++ + goto l344 l346: - position, tokenIndex = position345, tokenIndex345 - if c := buffer[position]; c < rune('A') || c > rune('Z') { + position, tokenIndex = position344, tokenIndex344 + if buffer[position] != rune('\\') { goto l347 } position++ - goto l345 + if buffer[position] != rune('n') { + goto l347 + } + position++ + goto l344 l347: - position, tokenIndex = position345, tokenIndex345 - if c := buffer[position]; c < rune('0') || c > rune('9') { + position, tokenIndex = position344, tokenIndex344 + if buffer[position] != rune('\\') { goto l348 } position++ - goto l345 + if buffer[position] != rune('t') { + goto l348 + } + position++ + goto l344 l348: - position, tokenIndex = position345, tokenIndex345 - if buffer[position] != rune('_') { - goto l349 - } - position++ - goto l345 - l349: - position, tokenIndex = position345, tokenIndex345 - if buffer[position] != rune('-') { - goto l344 - } - position++ - } - l345: - goto l343 - l344: - position, tokenIndex = position344, tokenIndex344 - } - add(rulefieldExpr, position339) - } - return true - l338: - position, tokenIndex = position338, tokenIndex338 - return false - }, - /* 16 field <- <(<(fieldExpr / reserved)> Action55)> */ - func() bool { - position350, tokenIndex350 := position, tokenIndex - { - position351 := position - { - position352 := position - { - position353, tokenIndex353 := position, tokenIndex - if !_rules[rulefieldExpr]() { - goto l354 - } - goto l353 - l354: - position, tokenIndex = position353, tokenIndex353 + position, tokenIndex = position344, tokenIndex344 { - position355 := position + position349, tokenIndex349 := position, tokenIndex { - position356, tokenIndex356 := position, tokenIndex - if buffer[position] != rune('_') { - goto l357 + position350, tokenIndex350 := position, tokenIndex + if buffer[position] != rune('\'') { + goto l351 } position++ - if buffer[position] != rune('r') { - goto l357 - } - position++ - if buffer[position] != rune('o') { - goto l357 - } - position++ - if buffer[position] != rune('w') { - goto l357 - } - position++ - goto l356 - l357: - position, tokenIndex = position356, tokenIndex356 - if buffer[position] != rune('_') { - goto l358 - } - position++ - if buffer[position] != rune('c') { - goto l358 - } - position++ - if buffer[position] != rune('o') { - goto l358 - } - position++ - if buffer[position] != rune('l') { - goto l358 - } - position++ - goto l356 - l358: - position, tokenIndex = position356, tokenIndex356 - if buffer[position] != rune('_') { - goto l359 - } - position++ - if buffer[position] != rune('s') { - goto l359 - } - position++ - if buffer[position] != rune('t') { - goto l359 - } - position++ - if buffer[position] != rune('a') { - goto l359 - } - position++ - if buffer[position] != rune('r') { - goto l359 - } - position++ - if buffer[position] != rune('t') { - goto l359 - } - position++ - goto l356 - l359: - position, tokenIndex = position356, tokenIndex356 - if buffer[position] != rune('_') { - goto l360 - } - position++ - if buffer[position] != rune('e') { - goto l360 - } - position++ - if buffer[position] != rune('n') { - goto l360 - } - position++ - if buffer[position] != rune('d') { - goto l360 - } - position++ - goto l356 - l360: - position, tokenIndex = position356, tokenIndex356 - if buffer[position] != rune('_') { - goto l361 - } - position++ - if buffer[position] != rune('t') { - goto l361 - } - position++ - if buffer[position] != rune('i') { - goto l361 - } - position++ - if buffer[position] != rune('m') { - goto l361 - } - position++ - if buffer[position] != rune('e') { - goto l361 - } - position++ - if buffer[position] != rune('s') { - goto l361 - } - position++ - if buffer[position] != rune('t') { - goto l361 - } - position++ - if buffer[position] != rune('a') { - goto l361 - } - position++ - if buffer[position] != rune('m') { - goto l361 - } - position++ - if buffer[position] != rune('p') { - goto l361 - } - position++ - goto l356 - l361: - position, tokenIndex = position356, tokenIndex356 - if buffer[position] != rune('_') { - goto l350 - } - position++ - if buffer[position] != rune('f') { - goto l350 - } - position++ - if buffer[position] != rune('i') { - goto l350 - } - position++ - if buffer[position] != rune('e') { - goto l350 - } - position++ - if buffer[position] != rune('l') { - goto l350 - } - position++ - if buffer[position] != rune('d') { - goto l350 + goto l350 + l351: + position, tokenIndex = position350, tokenIndex350 + if buffer[position] != rune('\\') { + goto l349 } position++ } - l356: - add(rulereserved, position355) + l350: + goto l343 + l349: + position, tokenIndex = position349, tokenIndex349 + } + if !matchDot() { + goto l343 } } - l353: - add(rulePegText, position352) + l344: + goto l342 + l343: + position, tokenIndex = position343, tokenIndex343 } - { - add(ruleAction55, position) - } - add(rulefield, position351) + add(rulesinglequotedstring, position341) } return true - l350: - position, tokenIndex = position350, tokenIndex350 + }, + /* 15 variable <- <(([a-z] / [A-Z] / '_') ([a-z] / [A-Z] / [0-9] / '_' / '-')*)> */ + nil, + /* 16 fieldExpr <- <(([a-z] / [A-Z] / '_') ([a-z] / [A-Z] / [0-9] / '_' / '-')*)> */ + func() bool { + position353, tokenIndex353 := position, tokenIndex + { + position354 := position + { + position355, tokenIndex355 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l356 + } + position++ + goto l355 + l356: + position, tokenIndex = position355, tokenIndex355 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l357 + } + position++ + goto l355 + l357: + position, tokenIndex = position355, tokenIndex355 + if buffer[position] != rune('_') { + goto l353 + } + position++ + } + l355: + l358: + { + position359, tokenIndex359 := position, tokenIndex + { + position360, tokenIndex360 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l361 + } + position++ + goto l360 + l361: + position, tokenIndex = position360, tokenIndex360 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l362 + } + position++ + goto l360 + l362: + position, tokenIndex = position360, tokenIndex360 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l363 + } + position++ + goto l360 + l363: + position, tokenIndex = position360, tokenIndex360 + if buffer[position] != rune('_') { + goto l364 + } + position++ + goto l360 + l364: + position, tokenIndex = position360, tokenIndex360 + if buffer[position] != rune('-') { + goto l359 + } + position++ + } + l360: + goto l358 + l359: + position, tokenIndex = position359, tokenIndex359 + } + add(rulefieldExpr, position354) + } + return true + l353: + position, tokenIndex = position353, tokenIndex353 return false }, - /* 17 reserved <- <(('_' 'r' 'o' 'w') / ('_' 'c' 'o' 'l') / ('_' 's' 't' 'a' 'r' 't') / ('_' 'e' 'n' 'd') / ('_' 't' 'i' 'm' 'e' 's' 't' 'a' 'm' 'p') / ('_' 'f' 'i' 'e' 'l' 'd'))> */ - nil, - /* 18 posfield <- <(('f' 'i' 'e' 'l' 'd' '=')? Action56)> */ + /* 17 field <- <(<(fieldExpr / reserved)> Action56)> */ func() bool { - position364, tokenIndex364 := position, tokenIndex + position365, tokenIndex365 := position, tokenIndex { - position365 := position + position366 := position { - position366, tokenIndex366 := position, tokenIndex - if buffer[position] != rune('f') { - goto l366 + position367 := position + { + position368, tokenIndex368 := position, tokenIndex + if !_rules[rulefieldExpr]() { + goto l369 + } + goto l368 + l369: + position, tokenIndex = position368, tokenIndex368 + { + position370 := position + { + position371, tokenIndex371 := position, tokenIndex + if buffer[position] != rune('_') { + goto l372 + } + position++ + if buffer[position] != rune('r') { + goto l372 + } + position++ + if buffer[position] != rune('o') { + goto l372 + } + position++ + if buffer[position] != rune('w') { + goto l372 + } + position++ + goto l371 + l372: + position, tokenIndex = position371, tokenIndex371 + if buffer[position] != rune('_') { + goto l373 + } + position++ + if buffer[position] != rune('c') { + goto l373 + } + position++ + if buffer[position] != rune('o') { + goto l373 + } + position++ + if buffer[position] != rune('l') { + goto l373 + } + position++ + goto l371 + l373: + position, tokenIndex = position371, tokenIndex371 + if buffer[position] != rune('_') { + goto l374 + } + position++ + if buffer[position] != rune('s') { + goto l374 + } + position++ + if buffer[position] != rune('t') { + goto l374 + } + position++ + if buffer[position] != rune('a') { + goto l374 + } + position++ + if buffer[position] != rune('r') { + goto l374 + } + position++ + if buffer[position] != rune('t') { + goto l374 + } + position++ + goto l371 + l374: + position, tokenIndex = position371, tokenIndex371 + if buffer[position] != rune('_') { + goto l375 + } + position++ + if buffer[position] != rune('e') { + goto l375 + } + position++ + if buffer[position] != rune('n') { + goto l375 + } + position++ + if buffer[position] != rune('d') { + goto l375 + } + position++ + goto l371 + l375: + position, tokenIndex = position371, tokenIndex371 + if buffer[position] != rune('_') { + goto l376 + } + position++ + if buffer[position] != rune('t') { + goto l376 + } + position++ + if buffer[position] != rune('i') { + goto l376 + } + position++ + if buffer[position] != rune('m') { + goto l376 + } + position++ + if buffer[position] != rune('e') { + goto l376 + } + position++ + if buffer[position] != rune('s') { + goto l376 + } + position++ + if buffer[position] != rune('t') { + goto l376 + } + position++ + if buffer[position] != rune('a') { + goto l376 + } + position++ + if buffer[position] != rune('m') { + goto l376 + } + position++ + if buffer[position] != rune('p') { + goto l376 + } + position++ + goto l371 + l376: + position, tokenIndex = position371, tokenIndex371 + if buffer[position] != rune('_') { + goto l365 + } + position++ + if buffer[position] != rune('f') { + goto l365 + } + position++ + if buffer[position] != rune('i') { + goto l365 + } + position++ + if buffer[position] != rune('e') { + goto l365 + } + position++ + if buffer[position] != rune('l') { + goto l365 + } + position++ + if buffer[position] != rune('d') { + goto l365 + } + position++ + } + l371: + add(rulereserved, position370) + } } - position++ - if buffer[position] != rune('i') { - goto l366 - } - position++ - if buffer[position] != rune('e') { - goto l366 - } - position++ - if buffer[position] != rune('l') { - goto l366 - } - position++ - if buffer[position] != rune('d') { - goto l366 - } - position++ - if buffer[position] != rune('=') { - goto l366 - } - position++ - goto l367 - l366: - position, tokenIndex = position366, tokenIndex366 - } - l367: - { - position368 := position - if !_rules[rulefieldExpr]() { - goto l364 - } - add(rulePegText, position368) + l368: + add(rulePegText, position367) } { add(ruleAction56, position) } - add(ruleposfield, position365) + add(rulefield, position366) } return true - l364: - position, tokenIndex = position364, tokenIndex364 + l365: + position, tokenIndex = position365, tokenIndex365 return false }, - /* 19 col <- <(( Action57) / (<('\'' singlequotedstring '\'')> Action58) / (<('"' doublequotedstring '"')> Action59))> */ + /* 18 reserved <- <(('_' 'r' 'o' 'w') / ('_' 'c' 'o' 'l') / ('_' 's' 't' 'a' 'r' 't') / ('_' 'e' 'n' 'd') / ('_' 't' 'i' 'm' 'e' 's' 't' 'a' 'm' 'p') / ('_' 'f' 'i' 'e' 'l' 'd'))> */ + nil, + /* 19 posfield <- <(('f' 'i' 'e' 'l' 'd' '=')? Action57)> */ func() bool { - position370, tokenIndex370 := position, tokenIndex + position379, tokenIndex379 := position, tokenIndex { - position371 := position + position380 := position { - position372, tokenIndex372 := position, tokenIndex + position381, tokenIndex381 := position, tokenIndex + if buffer[position] != rune('f') { + goto l381 + } + position++ + if buffer[position] != rune('i') { + goto l381 + } + position++ + if buffer[position] != rune('e') { + goto l381 + } + position++ + if buffer[position] != rune('l') { + goto l381 + } + position++ + if buffer[position] != rune('d') { + goto l381 + } + position++ + if buffer[position] != rune('=') { + goto l381 + } + position++ + goto l382 + l381: + position, tokenIndex = position381, tokenIndex381 + } + l382: + { + position383 := position + if !_rules[rulefieldExpr]() { + goto l379 + } + add(rulePegText, position383) + } + { + add(ruleAction57, position) + } + add(ruleposfield, position380) + } + return true + l379: + position, tokenIndex = position379, tokenIndex379 + return false + }, + /* 20 col <- <(( Action58) / (<('\'' singlequotedstring '\'')> Action59) / (<('"' doublequotedstring '"')> Action60))> */ + func() bool { + position385, tokenIndex385 := position, tokenIndex + { + position386 := position + { + position387, tokenIndex387 := position, tokenIndex { - position374 := position + position389 := position if !_rules[ruledigits]() { - goto l373 + goto l388 } - add(rulePegText, position374) - } - { - add(ruleAction57, position) - } - goto l372 - l373: - position, tokenIndex = position372, tokenIndex372 - { - position377 := position - if buffer[position] != rune('\'') { - goto l376 - } - position++ - if !_rules[rulesinglequotedstring]() { - goto l376 - } - if buffer[position] != rune('\'') { - goto l376 - } - position++ - add(rulePegText, position377) + add(rulePegText, position389) } { add(ruleAction58, position) } - goto l372 - l376: - position, tokenIndex = position372, tokenIndex372 + goto l387 + l388: + position, tokenIndex = position387, tokenIndex387 { - position379 := position - if buffer[position] != rune('"') { - goto l370 + position392 := position + if buffer[position] != rune('\'') { + goto l391 } position++ - if !_rules[ruledoublequotedstring]() { - goto l370 + if !_rules[rulesinglequotedstring]() { + goto l391 } - if buffer[position] != rune('"') { - goto l370 + if buffer[position] != rune('\'') { + goto l391 } position++ - add(rulePegText, position379) + add(rulePegText, position392) } { add(ruleAction59, position) } - } - l372: - add(rulecol, position371) - } - return true - l370: - position, tokenIndex = position370, tokenIndex370 - return false - }, - /* 20 open <- <('(' sp)> */ - func() bool { - position381, tokenIndex381 := position, tokenIndex - { - position382 := position - if buffer[position] != rune('(') { - goto l381 - } - position++ - if !_rules[rulesp]() { - goto l381 - } - add(ruleopen, position382) - } - return true - l381: - position, tokenIndex = position381, tokenIndex381 - return false - }, - /* 21 close <- <(sp ')' sp)> */ - func() bool { - position383, tokenIndex383 := position, tokenIndex - { - position384 := position - if !_rules[rulesp]() { - goto l383 - } - if buffer[position] != rune(')') { - goto l383 - } - position++ - if !_rules[rulesp]() { - goto l383 - } - add(ruleclose, position384) - } - return true - l383: - position, tokenIndex = position383, tokenIndex383 - return false - }, - /* 22 sp <- <(' ' / '\t' / '\n')*> */ - func() bool { - { - position386 := position - l387: - { - position388, tokenIndex388 := position, tokenIndex - { - position389, tokenIndex389 := position, tokenIndex - if buffer[position] != rune(' ') { - goto l390 - } - position++ - goto l389 - l390: - position, tokenIndex = position389, tokenIndex389 - if buffer[position] != rune('\t') { - goto l391 - } - position++ - goto l389 - l391: - position, tokenIndex = position389, tokenIndex389 - if buffer[position] != rune('\n') { - goto l388 - } - position++ - } - l389: goto l387 - l388: - position, tokenIndex = position388, tokenIndex388 + l391: + position, tokenIndex = position387, tokenIndex387 + { + position394 := position + if buffer[position] != rune('"') { + goto l385 + } + position++ + if !_rules[ruledoublequotedstring]() { + goto l385 + } + if buffer[position] != rune('"') { + goto l385 + } + position++ + add(rulePegText, position394) + } + { + add(ruleAction60, position) + } } - add(rulesp, position386) + l387: + add(rulecol, position386) } return true + l385: + position, tokenIndex = position385, tokenIndex385 + return false }, - /* 23 eq <- <(sp '=' sp)> */ + /* 21 open <- <('(' sp)> */ func() bool { - position392, tokenIndex392 := position, tokenIndex + position396, tokenIndex396 := position, tokenIndex { - position393 := position - if !_rules[rulesp]() { - goto l392 - } - if buffer[position] != rune('=') { - goto l392 + position397 := position + if buffer[position] != rune('(') { + goto l396 } position++ if !_rules[rulesp]() { - goto l392 + goto l396 } - add(ruleeq, position393) + add(ruleopen, position397) } return true - l392: - position, tokenIndex = position392, tokenIndex392 + l396: + position, tokenIndex = position396, tokenIndex396 return false }, - /* 24 comma <- <(sp ',' sp)> */ - func() bool { - position394, tokenIndex394 := position, tokenIndex - { - position395 := position - if !_rules[rulesp]() { - goto l394 - } - if buffer[position] != rune(',') { - goto l394 - } - position++ - if !_rules[rulesp]() { - goto l394 - } - add(rulecomma, position395) - } - return true - l394: - position, tokenIndex = position394, tokenIndex394 - return false - }, - /* 25 lbrack <- <('[' sp)> */ - nil, - /* 26 rbrack <- <(sp ']' sp)> */ - nil, - /* 27 IDENT <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / [0-9])*)> */ + /* 22 close <- <(sp ')' sp)> */ func() bool { position398, tokenIndex398 := position, tokenIndex { position399 := position - { - position400, tokenIndex400 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l401 - } - position++ - goto l400 - l401: - position, tokenIndex = position400, tokenIndex400 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l398 - } - position++ + if !_rules[rulesp]() { + goto l398 } - l400: + if buffer[position] != rune(')') { + goto l398 + } + position++ + if !_rules[rulesp]() { + goto l398 + } + add(ruleclose, position399) + } + return true + l398: + position, tokenIndex = position398, tokenIndex398 + return false + }, + /* 23 sp <- <(' ' / '\t' / '\n')*> */ + func() bool { + { + position401 := position l402: { position403, tokenIndex403 := position, tokenIndex { position404, tokenIndex404 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { + if buffer[position] != rune(' ') { goto l405 } position++ goto l404 l405: position, tokenIndex = position404, tokenIndex404 - if c := buffer[position]; c < rune('A') || c > rune('Z') { + if buffer[position] != rune('\t') { goto l406 } position++ goto l404 l406: position, tokenIndex = position404, tokenIndex404 - if c := buffer[position]; c < rune('0') || c > rune('9') { + if buffer[position] != rune('\n') { goto l403 } position++ @@ -3569,702 +3566,805 @@ func (p *PQL) Init(options ...func(*PQL) error) error { l403: position, tokenIndex = position403, tokenIndex403 } - add(ruleIDENT, position399) + add(rulesp, position401) } return true - l398: - position, tokenIndex = position398, tokenIndex398 - return false }, - /* 28 digits <- <[0-9]+> */ + /* 24 eq <- <(sp '=' sp)> */ func() bool { position407, tokenIndex407 := position, tokenIndex { position408 := position - if c := buffer[position]; c < rune('0') || c > rune('9') { + if !_rules[rulesp]() { + goto l407 + } + if buffer[position] != rune('=') { goto l407 } position++ - l409: - { - position410, tokenIndex410 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l410 - } - position++ - goto l409 - l410: - position, tokenIndex = position410, tokenIndex410 + if !_rules[rulesp]() { + goto l407 } - add(ruledigits, position408) + add(ruleeq, position408) } return true l407: position, tokenIndex = position407, tokenIndex407 return false }, - /* 29 signedDigits <- <('-'? digits)> */ - nil, - /* 30 decimal <- <((signedDigits ('.' digits?)?) / ('-'? '.' digits))> */ + /* 25 comma <- <(sp ',' sp)> */ func() bool { - position412, tokenIndex412 := position, tokenIndex + position409, tokenIndex409 := position, tokenIndex { - position413 := position + position410 := position + if !_rules[rulesp]() { + goto l409 + } + if buffer[position] != rune(',') { + goto l409 + } + position++ + if !_rules[rulesp]() { + goto l409 + } + add(rulecomma, position410) + } + return true + l409: + position, tokenIndex = position409, tokenIndex409 + return false + }, + /* 26 lbrack <- <('[' sp)> */ + nil, + /* 27 rbrack <- <(sp ']' sp)> */ + nil, + /* 28 IDENT <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / [0-9])*)> */ + func() bool { + position413, tokenIndex413 := position, tokenIndex + { + position414 := position { - position414, tokenIndex414 := position, tokenIndex - { - position416 := position - { - position417, tokenIndex417 := position, tokenIndex - if buffer[position] != rune('-') { - goto l417 - } - position++ - goto l418 - l417: - position, tokenIndex = position417, tokenIndex417 - } - l418: - if !_rules[ruledigits]() { - goto l415 - } - add(rulesignedDigits, position416) + position415, tokenIndex415 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l416 } + position++ + goto l415 + l416: + position, tokenIndex = position415, tokenIndex415 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l413 + } + position++ + } + l415: + l417: + { + position418, tokenIndex418 := position, tokenIndex { position419, tokenIndex419 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l420 + } + position++ + goto l419 + l420: + position, tokenIndex = position419, tokenIndex419 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l421 + } + position++ + goto l419 + l421: + position, tokenIndex = position419, tokenIndex419 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l418 + } + position++ + } + l419: + goto l417 + l418: + position, tokenIndex = position418, tokenIndex418 + } + add(ruleIDENT, position414) + } + return true + l413: + position, tokenIndex = position413, tokenIndex413 + return false + }, + /* 29 digits <- <[0-9]+> */ + func() bool { + position422, tokenIndex422 := position, tokenIndex + { + position423 := position + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l422 + } + position++ + l424: + { + position425, tokenIndex425 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l425 + } + position++ + goto l424 + l425: + position, tokenIndex = position425, tokenIndex425 + } + add(ruledigits, position423) + } + return true + l422: + position, tokenIndex = position422, tokenIndex422 + return false + }, + /* 30 signedDigits <- <('-'? digits)> */ + nil, + /* 31 decimal <- <((signedDigits ('.' digits?)?) / ('-'? '.' digits))> */ + func() bool { + position427, tokenIndex427 := position, tokenIndex + { + position428 := position + { + position429, tokenIndex429 := position, tokenIndex + { + position431 := position + { + position432, tokenIndex432 := position, tokenIndex + if buffer[position] != rune('-') { + goto l432 + } + position++ + goto l433 + l432: + position, tokenIndex = position432, tokenIndex432 + } + l433: + if !_rules[ruledigits]() { + goto l430 + } + add(rulesignedDigits, position431) + } + { + position434, tokenIndex434 := position, tokenIndex if buffer[position] != rune('.') { - goto l419 + goto l434 } position++ { - position421, tokenIndex421 := position, tokenIndex + position436, tokenIndex436 := position, tokenIndex if !_rules[ruledigits]() { - goto l421 + goto l436 } - goto l422 - l421: - position, tokenIndex = position421, tokenIndex421 + goto l437 + l436: + position, tokenIndex = position436, tokenIndex436 } - l422: - goto l420 - l419: - position, tokenIndex = position419, tokenIndex419 + l437: + goto l435 + l434: + position, tokenIndex = position434, tokenIndex434 } - l420: - goto l414 - l415: - position, tokenIndex = position414, tokenIndex414 + l435: + goto l429 + l430: + position, tokenIndex = position429, tokenIndex429 { - position423, tokenIndex423 := position, tokenIndex + position438, tokenIndex438 := position, tokenIndex if buffer[position] != rune('-') { - goto l423 + goto l438 } position++ - goto l424 - l423: - position, tokenIndex = position423, tokenIndex423 + goto l439 + l438: + position, tokenIndex = position438, tokenIndex438 } - l424: + l439: if buffer[position] != rune('.') { - goto l412 + goto l427 } position++ if !_rules[ruledigits]() { - goto l412 + goto l427 } } - l414: - add(ruledecimal, position413) + l429: + add(ruledecimal, position428) } return true - l412: - position, tokenIndex = position412, tokenIndex412 + l427: + position, tokenIndex = position427, tokenIndex427 return false }, - /* 31 tz <- <('Z' / ('-' [0-9] [0-9] ':' [0-9] [0-9]) / ('+' [0-9] [0-9] ':' [0-9] [0-9]))> */ + /* 32 tz <- <('Z' / ('-' [0-9] [0-9] ':' [0-9] [0-9]) / ('+' [0-9] [0-9] ':' [0-9] [0-9]))> */ func() bool { - position425, tokenIndex425 := position, tokenIndex + position440, tokenIndex440 := position, tokenIndex { - position426 := position + position441 := position { - position427, tokenIndex427 := position, tokenIndex + position442, tokenIndex442 := position, tokenIndex if buffer[position] != rune('Z') { - goto l428 + goto l443 } position++ - goto l427 - l428: - position, tokenIndex = position427, tokenIndex427 + goto l442 + l443: + position, tokenIndex = position442, tokenIndex442 if buffer[position] != rune('-') { - goto l429 + goto l444 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l429 + goto l444 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l429 + goto l444 } position++ if buffer[position] != rune(':') { - goto l429 + goto l444 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l429 + goto l444 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l429 + goto l444 } position++ - goto l427 - l429: - position, tokenIndex = position427, tokenIndex427 + goto l442 + l444: + position, tokenIndex = position442, tokenIndex442 if buffer[position] != rune('+') { - goto l425 + goto l440 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l425 + goto l440 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l425 + goto l440 } position++ if buffer[position] != rune(':') { - goto l425 + goto l440 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l425 + goto l440 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l425 + goto l440 } position++ } - l427: - add(ruletz, position426) + l442: + add(ruletz, position441) } return true - l425: - position, tokenIndex = position425, tokenIndex425 + l440: + position, tokenIndex = position440, tokenIndex440 return false }, - /* 32 iso8601 <- <([0-9] [0-9] [0-9] [0-9] '-' ('0' / '1') [0-9] '-' [0-3] [0-9] 'T' [0-9] [0-9] ':' [0-9] [0-9] ':' [0-9] [0-9] )> */ + /* 33 iso8601 <- <([0-9] [0-9] [0-9] [0-9] '-' ('0' / '1') [0-9] '-' [0-3] [0-9] 'T' [0-9] [0-9] ':' [0-9] [0-9] ':' [0-9] [0-9] )> */ nil, - /* 33 iso8601nano <- <([0-9] [0-9] [0-9] [0-9] '-' ('0' / '1') [0-9] '-' [0-3] [0-9] 'T' [0-9] [0-9] ':' [0-9] [0-9] ':' [0-9] [0-9] '.' [0-9]+ )> */ + /* 34 iso8601nano <- <([0-9] [0-9] [0-9] [0-9] '-' ('0' / '1') [0-9] '-' [0-3] [0-9] 'T' [0-9] [0-9] ':' [0-9] [0-9] ':' [0-9] [0-9] '.' [0-9]+ )> */ nil, - /* 34 timestampbasicfmt <- <(iso8601nano / iso8601)> */ - func() bool { - position432, tokenIndex432 := position, tokenIndex - { - position433 := position - { - position434, tokenIndex434 := position, tokenIndex - { - position436 := position - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if buffer[position] != rune('-') { - goto l435 - } - position++ - { - position437, tokenIndex437 := position, tokenIndex - if buffer[position] != rune('0') { - goto l438 - } - position++ - goto l437 - l438: - position, tokenIndex = position437, tokenIndex437 - if buffer[position] != rune('1') { - goto l435 - } - position++ - } - l437: - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if buffer[position] != rune('-') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('3') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if buffer[position] != rune('T') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if buffer[position] != rune(':') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if buffer[position] != rune(':') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - if buffer[position] != rune('.') { - goto l435 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l435 - } - position++ - l439: - { - position440, tokenIndex440 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l440 - } - position++ - goto l439 - l440: - position, tokenIndex = position440, tokenIndex440 - } - { - position441 := position - if !_rules[ruletz]() { - goto l435 - } - add(rulePegText, position441) - } - add(ruleiso8601nano, position436) - } - goto l434 - l435: - position, tokenIndex = position434, tokenIndex434 - { - position442 := position - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if buffer[position] != rune('-') { - goto l432 - } - position++ - { - position443, tokenIndex443 := position, tokenIndex - if buffer[position] != rune('0') { - goto l444 - } - position++ - goto l443 - l444: - position, tokenIndex = position443, tokenIndex443 - if buffer[position] != rune('1') { - goto l432 - } - position++ - } - l443: - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if buffer[position] != rune('-') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('3') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if buffer[position] != rune('T') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if buffer[position] != rune(':') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if buffer[position] != rune(':') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l432 - } - position++ - { - position445 := position - if !_rules[ruletz]() { - goto l432 - } - add(rulePegText, position445) - } - add(ruleiso8601, position442) - } - } - l434: - add(ruletimestampbasicfmt, position433) - } - return true - l432: - position, tokenIndex = position432, tokenIndex432 - return false - }, - /* 35 timestampfmt <- <(('"' '"') / ('\'' '\'') / )> */ - nil, - /* 36 timebasicfmt <- <([0-9] [0-9] [0-9] [0-9] '-' ('0' / '1') [0-9] '-' [0-3] [0-9] 'T' [0-9] [0-9] ':' [0-9] [0-9])> */ + /* 35 timestampbasicfmt <- <(iso8601nano / iso8601)> */ func() bool { position447, tokenIndex447 := position, tokenIndex { position448 := position - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - if buffer[position] != rune('-') { - goto l447 - } - position++ { position449, tokenIndex449 := position, tokenIndex - if buffer[position] != rune('0') { - goto l450 + { + position451 := position + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if buffer[position] != rune('-') { + goto l450 + } + position++ + { + position452, tokenIndex452 := position, tokenIndex + if buffer[position] != rune('0') { + goto l453 + } + position++ + goto l452 + l453: + position, tokenIndex = position452, tokenIndex452 + if buffer[position] != rune('1') { + goto l450 + } + position++ + } + l452: + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if buffer[position] != rune('-') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('3') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if buffer[position] != rune('T') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if buffer[position] != rune(':') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if buffer[position] != rune(':') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + if buffer[position] != rune('.') { + goto l450 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l450 + } + position++ + l454: + { + position455, tokenIndex455 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l455 + } + position++ + goto l454 + l455: + position, tokenIndex = position455, tokenIndex455 + } + { + position456 := position + if !_rules[ruletz]() { + goto l450 + } + add(rulePegText, position456) + } + add(ruleiso8601nano, position451) } - position++ goto l449 l450: position, tokenIndex = position449, tokenIndex449 - if buffer[position] != rune('1') { - goto l447 + { + position457 := position + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if buffer[position] != rune('-') { + goto l447 + } + position++ + { + position458, tokenIndex458 := position, tokenIndex + if buffer[position] != rune('0') { + goto l459 + } + position++ + goto l458 + l459: + position, tokenIndex = position458, tokenIndex458 + if buffer[position] != rune('1') { + goto l447 + } + position++ + } + l458: + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if buffer[position] != rune('-') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('3') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if buffer[position] != rune('T') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if buffer[position] != rune(':') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if buffer[position] != rune(':') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l447 + } + position++ + { + position460 := position + if !_rules[ruletz]() { + goto l447 + } + add(rulePegText, position460) + } + add(ruleiso8601, position457) } - position++ } l449: - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - if buffer[position] != rune('-') { - goto l447 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('3') { - goto l447 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - if buffer[position] != rune('T') { - goto l447 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - if buffer[position] != rune(':') { - goto l447 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 - } - position++ - add(ruletimebasicfmt, position448) + add(ruletimestampbasicfmt, position448) } return true l447: position, tokenIndex = position447, tokenIndex447 return false }, - /* 37 timefmt <- <(('"' '"') / ('\'' '\'') / )> */ + /* 36 timestampfmt <- <(('"' '"') / ('\'' '\'') / )> */ + nil, + /* 37 timebasicfmt <- <([0-9] [0-9] [0-9] [0-9] '-' ('0' / '1') [0-9] '-' [0-3] [0-9] 'T' [0-9] [0-9] ':' [0-9] [0-9])> */ func() bool { - position451, tokenIndex451 := position, tokenIndex + position462, tokenIndex462 := position, tokenIndex { - position452 := position - { - position453, tokenIndex453 := position, tokenIndex - if buffer[position] != rune('"') { - goto l454 - } - position++ - { - position455 := position - if !_rules[ruletimebasicfmt]() { - goto l454 - } - add(rulePegText, position455) - } - if buffer[position] != rune('"') { - goto l454 - } - position++ - goto l453 - l454: - position, tokenIndex = position453, tokenIndex453 - if buffer[position] != rune('\'') { - goto l456 - } - position++ - { - position457 := position - if !_rules[ruletimebasicfmt]() { - goto l456 - } - add(rulePegText, position457) - } - if buffer[position] != rune('\'') { - goto l456 - } - position++ - goto l453 - l456: - position, tokenIndex = position453, tokenIndex453 - { - position458 := position - if !_rules[ruletimebasicfmt]() { - goto l451 - } - add(rulePegText, position458) - } + position463 := position + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 } - l453: - add(ruletimefmt, position452) + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + if buffer[position] != rune('-') { + goto l462 + } + position++ + { + position464, tokenIndex464 := position, tokenIndex + if buffer[position] != rune('0') { + goto l465 + } + position++ + goto l464 + l465: + position, tokenIndex = position464, tokenIndex464 + if buffer[position] != rune('1') { + goto l462 + } + position++ + } + l464: + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + if buffer[position] != rune('-') { + goto l462 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('3') { + goto l462 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + if buffer[position] != rune('T') { + goto l462 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + if buffer[position] != rune(':') { + goto l462 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + add(ruletimebasicfmt, position463) } return true - l451: - position, tokenIndex = position451, tokenIndex451 + l462: + position, tokenIndex = position462, tokenIndex462 return false }, - /* 38 time <- <( Action60)> */ + /* 38 timefmt <- <(('"' '"') / ('\'' '\'') / )> */ + func() bool { + position466, tokenIndex466 := position, tokenIndex + { + position467 := position + { + position468, tokenIndex468 := position, tokenIndex + if buffer[position] != rune('"') { + goto l469 + } + position++ + { + position470 := position + if !_rules[ruletimebasicfmt]() { + goto l469 + } + add(rulePegText, position470) + } + if buffer[position] != rune('"') { + goto l469 + } + position++ + goto l468 + l469: + position, tokenIndex = position468, tokenIndex468 + if buffer[position] != rune('\'') { + goto l471 + } + position++ + { + position472 := position + if !_rules[ruletimebasicfmt]() { + goto l471 + } + add(rulePegText, position472) + } + if buffer[position] != rune('\'') { + goto l471 + } + position++ + goto l468 + l471: + position, tokenIndex = position468, tokenIndex468 + { + position473 := position + if !_rules[ruletimebasicfmt]() { + goto l466 + } + add(rulePegText, position473) + } + } + l468: + add(ruletimefmt, position467) + } + return true + l466: + position, tokenIndex = position466, tokenIndex466 + return false + }, + /* 39 time <- <( Action61)> */ nil, - /* 40 Action0 <- <{p.startCall("Set")}> */ + /* 41 Action0 <- <{p.startCall("Set")}> */ nil, - /* 41 Action1 <- <{p.endCall()}> */ + /* 42 Action1 <- <{p.endCall()}> */ nil, - /* 42 Action2 <- <{p.startCall("Clear")}> */ + /* 43 Action2 <- <{p.startCall("Clear")}> */ nil, - /* 43 Action3 <- <{p.endCall()}> */ + /* 44 Action3 <- <{p.endCall()}> */ nil, - /* 44 Action4 <- <{p.startCall("ClearRow")}> */ + /* 45 Action4 <- <{p.startCall("ClearRow")}> */ nil, - /* 45 Action5 <- <{p.endCall()}> */ + /* 46 Action5 <- <{p.endCall()}> */ nil, - /* 46 Action6 <- <{p.startCall("Store")}> */ + /* 47 Action6 <- <{p.startCall("Store")}> */ nil, - /* 47 Action7 <- <{p.endCall()}> */ + /* 48 Action7 <- <{p.endCall()}> */ nil, - /* 48 Action8 <- <{p.startCall("TopN")}> */ + /* 49 Action8 <- <{p.startCall("TopN")}> */ nil, - /* 49 Action9 <- <{p.endCall()}> */ + /* 50 Action9 <- <{p.endCall()}> */ nil, - /* 50 Action10 <- <{p.startCall("TopK")}> */ + /* 51 Action10 <- <{p.startCall("TopK")}> */ nil, - /* 51 Action11 <- <{p.endCall()}> */ + /* 52 Action11 <- <{p.endCall()}> */ nil, - /* 52 Action12 <- <{p.startCall("Percentile")}> */ + /* 53 Action12 <- <{p.startCall("Percentile")}> */ nil, - /* 53 Action13 <- <{p.endCall()}> */ + /* 54 Action13 <- <{p.endCall()}> */ nil, - /* 54 Action14 <- <{p.startCall("Rows")}> */ + /* 55 Action14 <- <{p.startCall("Rows")}> */ nil, - /* 55 Action15 <- <{p.endCall()}> */ + /* 56 Action15 <- <{p.endCall()}> */ nil, - /* 56 Action16 <- <{p.startCall("Min")}> */ + /* 57 Action16 <- <{p.startCall("Min")}> */ nil, - /* 57 Action17 <- <{p.endCall()}> */ + /* 58 Action17 <- <{p.endCall()}> */ nil, - /* 58 Action18 <- <{p.startCall("Max")}> */ + /* 59 Action18 <- <{p.startCall("Max")}> */ nil, - /* 59 Action19 <- <{p.endCall()}> */ + /* 60 Action19 <- <{p.endCall()}> */ nil, - /* 60 Action20 <- <{p.startCall("Sum")}> */ + /* 61 Action20 <- <{p.startCall("Sum")}> */ nil, - /* 61 Action21 <- <{p.endCall()}> */ + /* 62 Action21 <- <{p.endCall()}> */ nil, - /* 62 Action22 <- <{p.startCall("Range")}> */ + /* 63 Action22 <- <{p.startCall("Range")}> */ nil, - /* 63 Action23 <- <{p.addField("from")}> */ + /* 64 Action23 <- <{p.addField("from")}> */ nil, - /* 64 Action24 <- <{p.addVal(text)}> */ + /* 65 Action24 <- <{p.addVal(text)}> */ nil, - /* 65 Action25 <- <{p.addField("to")}> */ + /* 66 Action25 <- <{p.addField("to")}> */ nil, - /* 66 Action26 <- <{p.addVal(text)}> */ + /* 67 Action26 <- <{p.addVal(text)}> */ nil, - /* 67 Action27 <- <{p.endCall()}> */ + /* 68 Action27 <- <{p.endCall()}> */ nil, nil, - /* 69 Action28 <- <{ p.startCall(text) }> */ + /* 70 Action28 <- <{ p.startCall(text) }> */ nil, - /* 70 Action29 <- <{ p.endCall() }> */ + /* 71 Action29 <- <{ p.endCall() }> */ nil, - /* 71 Action30 <- <{ p.addBTWN() }> */ + /* 72 Action30 <- <{ p.addBTWN() }> */ nil, - /* 72 Action31 <- <{ p.addLTE() }> */ + /* 73 Action31 <- <{ p.addLTE() }> */ nil, - /* 73 Action32 <- <{ p.addGTE() }> */ + /* 74 Action32 <- <{ p.addGTE() }> */ nil, - /* 74 Action33 <- <{ p.addEQ() }> */ + /* 75 Action33 <- <{ p.addEQ() }> */ nil, - /* 75 Action34 <- <{ p.addNEQ() }> */ + /* 76 Action34 <- <{ p.addNEQ() }> */ nil, - /* 76 Action35 <- <{ p.addLT() }> */ + /* 77 Action35 <- <{ p.addLT() }> */ nil, - /* 77 Action36 <- <{ p.addGT() }> */ + /* 78 Action36 <- <{ p.addGT() }> */ nil, - /* 78 Action37 <- <{p.startConditional()}> */ + /* 79 Action37 <- <{p.startConditional()}> */ nil, - /* 79 Action38 <- <{p.endConditional()}> */ + /* 80 Action38 <- <{p.endConditional()}> */ nil, - /* 80 Action39 <- <{p.condAdd(text)}> */ + /* 81 Action39 <- <{p.condAdd(text)}> */ nil, - /* 81 Action40 <- <{p.condAdd(text)}> */ + /* 82 Action40 <- <{p.condAdd(text)}> */ nil, - /* 82 Action41 <- <{p.condAdd(text)}> */ + /* 83 Action41 <- <{p.condAdd(text)}> */ nil, - /* 83 Action42 <- <{ p.startList() }> */ + /* 84 Action42 <- <{ p.startList() }> */ nil, - /* 84 Action43 <- <{ p.endList() }> */ + /* 85 Action43 <- <{ p.endList() }> */ nil, - /* 85 Action44 <- <{ p.addVal(nil) }> */ + /* 86 Action44 <- <{ p.addVal(nil) }> */ nil, - /* 86 Action45 <- <{ p.addVal(true) }> */ + /* 87 Action45 <- <{ p.addVal(true) }> */ nil, - /* 87 Action46 <- <{ p.addVal(false) }> */ + /* 88 Action46 <- <{ p.addVal(false) }> */ nil, - /* 88 Action47 <- <{ p.addVal(text) }> */ + /* 89 Action47 <- <{ p.addVal(NewVariable(text)) }> */ nil, - /* 89 Action48 <- <{ p.addTimestampVal(text) }> */ + /* 90 Action48 <- <{ p.addVal(text) }> */ nil, - /* 90 Action49 <- <{ p.addNumVal(text) }> */ + /* 91 Action49 <- <{ p.addTimestampVal(text) }> */ nil, - /* 91 Action50 <- <{ p.startCall(text) }> */ + /* 92 Action50 <- <{ p.addNumVal(text) }> */ nil, - /* 92 Action51 <- <{ p.addVal(p.endCall()) }> */ + /* 93 Action51 <- <{ p.startCall(text) }> */ nil, - /* 93 Action52 <- <{ p.addVal(text) }> */ + /* 94 Action52 <- <{ p.addVal(p.endCall()) }> */ nil, - /* 94 Action53 <- <{ p.addVal(text) }> */ + /* 95 Action53 <- <{ p.addVal(text) }> */ nil, - /* 95 Action54 <- <{ p.addVal(text) }> */ + /* 96 Action54 <- <{ p.addVal(text) }> */ nil, - /* 96 Action55 <- <{ p.addField(text) }> */ + /* 97 Action55 <- <{ p.addVal(text) }> */ nil, - /* 97 Action56 <- <{ p.addPosStr("_field", text) }> */ + /* 98 Action56 <- <{ p.addField(text) }> */ nil, - /* 98 Action57 <- <{p.addPosNum("_col", text)}> */ + /* 99 Action57 <- <{ p.addPosStr("_field", text) }> */ nil, - /* 99 Action58 <- <{p.addPosStr("_col", text)}> */ + /* 100 Action58 <- <{p.addPosNum("_col", text)}> */ nil, - /* 100 Action59 <- <{p.addPosStr("_col", text)}> */ + /* 101 Action59 <- <{p.addPosStr("_col", text)}> */ nil, - /* 101 Action60 <- <{p.addPosStr("_timestamp", text)}> */ + /* 102 Action60 <- <{p.addPosStr("_col", text)}> */ + nil, + /* 103 Action61 <- <{p.addPosStr("_timestamp", text)}> */ nil, } p.rules = _rules diff --git a/pql/pqlpeg_test.go b/pql/pqlpeg_test.go index 41d053633..b11f0392c 100644 --- a/pql/pqlpeg_test.go +++ b/pql/pqlpeg_test.go @@ -752,6 +752,15 @@ func TestPQLDeepEquality(t *testing.T) { {Name: "Rows"}, }, }}, + { + name: "Variable", + call: "Row(f=$my_VAR123)", + exp: &Call{ + Name: "Row", + Args: map[string]interface{}{ + "f": &Variable{Name: "my_VAR123"}, + }, + }}, } for i, test := range tests { From b3faaa9dc061048c60553a123ca7dc48db7201ab Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Mon, 7 Feb 2022 12:55:10 -0600 Subject: [PATCH 02/14] handle expanding of Row call working for equality, but not for inequalityh ATM --- pql/ast.go | 115 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 17 deletions(-) diff --git a/pql/ast.go b/pql/ast.go index a4d14b7b9..f7458281e 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -9,6 +9,8 @@ import ( "strconv" "strings" "time" + + "github.com/jinzhu/copier" ) // Query represents a PQL query. @@ -27,12 +29,12 @@ func (q *Query) ExpandVars(vars map[string]interface{}) (*Query, error) { for _, c := range q.Calls { newCalls, err := c.ExpandVars(vars) if err != nil { - return err + return nil, err } other.Calls = append(other.Calls, newCalls...) } - return q, nil + return &other, nil } func (q *Query) startCall(name string) { @@ -912,28 +914,107 @@ func (c *Call) ArgString(key string) string { return s } -// ExpandVars recursively replaces variables in the call with their values. func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { - other := *c - other.Args = CopyArgs(c.Args) - other.Children = make([]*Call, 0, len(c.Children)) + switch c.Name { + case "Row": - // TODO: Replace field variables. + for k, v := range vars { + if _, ok := c.Args[k]; ok { + union := &Call{Name: "Union"} + switch tv := v.(type) { + case []interface{}: + for i := range tv { + r := Call{Name: "Row"} + r.Args = CopyArgs(c.Args) + switch cond := r.Args[k].(type) { + case *Condition: + cond.Value = tv[i] + r.Args[k] = cond + default: + cond = tv[i] + r.Args[k] = cond + } + union.Children = append(union.Children, &r) + } + } - // Recursively expand variables in children. - for _, child := range c.Children { - newChildren, err := child.ExpandVars(vars) - if err != nil { - return nil, err + return []*Call{union}, nil + } } - other.Children = append(other.Children, newChildren...) + return []*Call{c}, nil + case "Rows": + row1 := &Call{Name: "Rows"} + row2 := &Call{Name: "Rows"} + return []*Call{row1, row2}, nil + default: + other := &Call{} + copier.Copy(other, c) + other.Children = make([]*Call, 0, len(c.Children)) + for _, child := range c.Children { + newChildren, err := child.ExpandVars(vars) + if err != nil { + return nil, err + } + other.Children = append(other.Children, newChildren...) + } + return []*Call{other}, nil + //Expand then return Union to caller } - - // TODO: Return multiple calls for list. - - return []*Call{&other}, nil } +// ExpandVars recursively replaces variables in the call with their values. +// func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { +// other := *c +// other.Args = CopyArgs(c.Args) +// other.Children = make([]*Call, 0, len(c.Children)) + +// for _, child := range c.Children { +// switch child.Name { +// case "Row": +// for key, val := range vars { +// if _, ok := child.Args[key]; ok { +// // Make Union Cal +// union := &Call{Name: "Union"} +// // data type for val? +// vi := reflect.ValueOf(val) +// switch vi.Kind() { +// case reflect.Slice: +// for i := 0; i < vi.Len(); i++ { +// cpy := &Call{} +// copier.Copy(cpy, child) +// cpy.Args[key] = vi.Index(i) +// union.Children = append(union.Children, cpy) +// } +// // case []uint, []uint16, []uint32, []uint64: +// // case []float32, []float64: +// } +// // Loop thru val + +// // Make copy of Child replacing its val for val + +// other.Children = append(other.Children, union) +// break +// } +// } +// } +// } + +// // TODO: Replace field variables. + +// // Recursively expand variables in children. +// for _, child := range c.Children { +// newChildren, err := child.ExpandVars(vars) +// if err != nil { +// return nil, err +// } +// other.Children = append(other.Children, newChildren...) +// } + +// // TODO: Return multiple calls for list. + +// return []*Call{&other}, nil +// } + // Condition represents an operation & value. // When used in an argument map it represents a binary expression. type Condition struct { From a755006d959251aa3c74de57301113b538b675f4 Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Mon, 7 Feb 2022 15:43:32 -0600 Subject: [PATCH 03/14] match on variable name, not field name --- pql/ast.go | 83 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/pql/ast.go b/pql/ast.go index f7458281e..02ce5618d 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -917,35 +917,74 @@ func (c *Call) ArgString(key string) string { func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { switch c.Name { case "Row": - - for k, v := range vars { - if _, ok := c.Args[k]; ok { - union := &Call{Name: "Union"} - switch tv := v.(type) { - case []interface{}: - for i := range tv { - r := Call{Name: "Row"} - r.Args = CopyArgs(c.Args) - switch cond := r.Args[k].(type) { - case *Condition: - cond.Value = tv[i] - r.Args[k] = cond - default: - cond = tv[i] - r.Args[k] = cond + for argK, argV := range c.Args { // animal: interface{} + switch variable := argV.(type) { + case *Variable: // if interface{} is of type Variable + for varK, varV := range vars { // go through all the vars. "var1": ["cat", "dog"] + if variable.Name == varK { + switch values := varV.(type) { + case []interface{}: + union := &Call{Name: "Union"} + for i := range values { + r := Call{Name: "Row"} + r.Args = CopyArgs(c.Args) + switch cond := r.Args[argK].(type) { + case *Condition: + r.Args[argK] = &Condition{Op: cond.Op, Value: values[i]} + default: + r.Args[argK] = values[i] + } + union.Children = append(union.Children, &r) + } + return []*Call{union}, nil } - union.Children = append(union.Children, &r) } } - return []*Call{union}, nil + } + } + + // for k, v := range vars { + // if _, ok := c.Args[k]; ok { + // union := &Call{Name: "Union"} + // switch tv := v.(type) { + // case []interface{}: + // for i := range tv { + // r := Call{Name: "Row"} + // r.Args = CopyArgs(c.Args) + // switch cond := r.Args[k].(type) { + // case *Condition: + // r.Args[k] = &Condition{Op: cond.Op, Value: tv[i]} + // default: + // r.Args[k] = tv[i] + // } + // union.Children = append(union.Children, &r) + // } + // } + // return []*Call{union}, nil + // } + // } + return []*Call{c}, nil + case "Rows": + for k, v := range vars { + if _, ok := c.Args[k]; ok { + rows := make([]*Call, len(vars)) + switch tv := v.(type) { + case []interface{}: + for i := range tv { + r := Call{Name: "Rows"} + r.Args = CopyArgs(c.Args) + r.Args[k] = tv[i] + rows = append(rows, &r) + } + } + return rows, nil } } return []*Call{c}, nil - case "Rows": - row1 := &Call{Name: "Rows"} - row2 := &Call{Name: "Rows"} - return []*Call{row1, row2}, nil + // row1 := &Call{Name: "Rows"} + // row2 := &Call{Name: "Rows"} + // return []*Call{row1, row2}, nil default: other := &Call{} copier.Copy(other, c) From f5d0b227fae89bc843afaab9b092958519d779f0 Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Mon, 7 Feb 2022 16:21:35 -0600 Subject: [PATCH 04/14] messing with parser, Rows call messing around trying to get Rows call to recognize $ syntax. got Rows to not barf, but it is interpreting $ syntax as string values for the _field parameter as opposed to a Variable --- pql/pql.peg | 2 +- pql/pql.peg.go | 895 +++++++++++++++++++++++++------------------------ 2 files changed, 452 insertions(+), 445 deletions(-) diff --git a/pql/pql.peg b/pql/pql.peg index 42b119512..c67c06abb 100644 --- a/pql/pql.peg +++ b/pql/pql.peg @@ -57,7 +57,7 @@ singlequotedstring <- ( '\\\'' / '\\\\' / '\\n' / '\\t' / [^'\\] )* variable <- ( [[A-Z]] / '_' ) ( [[A-Z]] / [0-9] / '_' / '-' )* -fieldExpr <- ( [[A-Z]] / '_' ) ( [[A-Z]] / [0-9] / '_' / '-' )* +fieldExpr <- ( [[A-Z]] / '_' / '$' ) ( [[A-Z]] / [0-9] / '_' / '-' )* field <- { p.addField(text) } reserved <- '_row' / '_col' / '_start' / '_end' / '_timestamp' / '_field' posfield <- 'field='? { p.addPosStr("_field", text) } diff --git a/pql/pql.peg.go b/pql/pql.peg.go index 694d07b35..7a2286fe5 100644 --- a/pql/pql.peg.go +++ b/pql/pql.peg.go @@ -3104,7 +3104,7 @@ func (p *PQL) Init(options ...func(*PQL) error) error { }, /* 15 variable <- <(([a-z] / [A-Z] / '_') ([a-z] / [A-Z] / [0-9] / '_' / '-')*)> */ nil, - /* 16 fieldExpr <- <(([a-z] / [A-Z] / '_') ([a-z] / [A-Z] / [0-9] / '_' / '-')*)> */ + /* 16 fieldExpr <- <(([a-z] / [A-Z] / '_' / '$') ([a-z] / [A-Z] / [0-9] / '_' / '-')*)> */ func() bool { position353, tokenIndex353 := position, tokenIndex { @@ -3126,53 +3126,60 @@ func (p *PQL) Init(options ...func(*PQL) error) error { l357: position, tokenIndex = position355, tokenIndex355 if buffer[position] != rune('_') { + goto l358 + } + position++ + goto l355 + l358: + position, tokenIndex = position355, tokenIndex355 + if buffer[position] != rune('$') { goto l353 } position++ } l355: - l358: + l359: { - position359, tokenIndex359 := position, tokenIndex + position360, tokenIndex360 := position, tokenIndex { - position360, tokenIndex360 := position, tokenIndex + position361, tokenIndex361 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l361 - } - position++ - goto l360 - l361: - position, tokenIndex = position360, tokenIndex360 - if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l362 } position++ - goto l360 + goto l361 l362: - position, tokenIndex = position360, tokenIndex360 - if c := buffer[position]; c < rune('0') || c > rune('9') { + position, tokenIndex = position361, tokenIndex361 + if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l363 } position++ - goto l360 + goto l361 l363: - position, tokenIndex = position360, tokenIndex360 - if buffer[position] != rune('_') { + position, tokenIndex = position361, tokenIndex361 + if c := buffer[position]; c < rune('0') || c > rune('9') { goto l364 } position++ - goto l360 + goto l361 l364: - position, tokenIndex = position360, tokenIndex360 + position, tokenIndex = position361, tokenIndex361 + if buffer[position] != rune('_') { + goto l365 + } + position++ + goto l361 + l365: + position, tokenIndex = position361, tokenIndex361 if buffer[position] != rune('-') { - goto l359 + goto l360 } position++ } + l361: + goto l359 l360: - goto l358 - l359: - position, tokenIndex = position359, tokenIndex359 + position, tokenIndex = position360, tokenIndex360 } add(rulefieldExpr, position354) } @@ -3183,435 +3190,435 @@ func (p *PQL) Init(options ...func(*PQL) error) error { }, /* 17 field <- <(<(fieldExpr / reserved)> Action56)> */ func() bool { - position365, tokenIndex365 := position, tokenIndex + position366, tokenIndex366 := position, tokenIndex { - position366 := position + position367 := position { - position367 := position + position368 := position { - position368, tokenIndex368 := position, tokenIndex + position369, tokenIndex369 := position, tokenIndex if !_rules[rulefieldExpr]() { - goto l369 + goto l370 } - goto l368 - l369: - position, tokenIndex = position368, tokenIndex368 + goto l369 + l370: + position, tokenIndex = position369, tokenIndex369 { - position370 := position + position371 := position { - position371, tokenIndex371 := position, tokenIndex + position372, tokenIndex372 := position, tokenIndex if buffer[position] != rune('_') { - goto l372 + goto l373 } position++ if buffer[position] != rune('r') { - goto l372 + goto l373 } position++ if buffer[position] != rune('o') { - goto l372 + goto l373 } position++ if buffer[position] != rune('w') { - goto l372 + goto l373 } position++ - goto l371 - l372: - position, tokenIndex = position371, tokenIndex371 + goto l372 + l373: + position, tokenIndex = position372, tokenIndex372 if buffer[position] != rune('_') { - goto l373 + goto l374 } position++ if buffer[position] != rune('c') { - goto l373 + goto l374 } position++ if buffer[position] != rune('o') { - goto l373 + goto l374 } position++ if buffer[position] != rune('l') { - goto l373 + goto l374 } position++ - goto l371 - l373: - position, tokenIndex = position371, tokenIndex371 + goto l372 + l374: + position, tokenIndex = position372, tokenIndex372 if buffer[position] != rune('_') { - goto l374 + goto l375 } position++ if buffer[position] != rune('s') { - goto l374 + goto l375 } position++ if buffer[position] != rune('t') { - goto l374 + goto l375 } position++ if buffer[position] != rune('a') { - goto l374 + goto l375 } position++ if buffer[position] != rune('r') { - goto l374 + goto l375 } position++ if buffer[position] != rune('t') { - goto l374 + goto l375 } position++ - goto l371 - l374: - position, tokenIndex = position371, tokenIndex371 + goto l372 + l375: + position, tokenIndex = position372, tokenIndex372 if buffer[position] != rune('_') { - goto l375 + goto l376 } position++ if buffer[position] != rune('e') { - goto l375 + goto l376 } position++ if buffer[position] != rune('n') { - goto l375 + goto l376 } position++ if buffer[position] != rune('d') { - goto l375 + goto l376 } position++ - goto l371 - l375: - position, tokenIndex = position371, tokenIndex371 + goto l372 + l376: + position, tokenIndex = position372, tokenIndex372 if buffer[position] != rune('_') { - goto l376 + goto l377 } position++ if buffer[position] != rune('t') { - goto l376 + goto l377 } position++ if buffer[position] != rune('i') { - goto l376 + goto l377 } position++ if buffer[position] != rune('m') { - goto l376 + goto l377 } position++ if buffer[position] != rune('e') { - goto l376 + goto l377 } position++ if buffer[position] != rune('s') { - goto l376 + goto l377 } position++ if buffer[position] != rune('t') { - goto l376 + goto l377 } position++ if buffer[position] != rune('a') { - goto l376 + goto l377 } position++ if buffer[position] != rune('m') { - goto l376 + goto l377 } position++ if buffer[position] != rune('p') { - goto l376 + goto l377 } position++ - goto l371 - l376: - position, tokenIndex = position371, tokenIndex371 + goto l372 + l377: + position, tokenIndex = position372, tokenIndex372 if buffer[position] != rune('_') { - goto l365 + goto l366 } position++ if buffer[position] != rune('f') { - goto l365 + goto l366 } position++ if buffer[position] != rune('i') { - goto l365 + goto l366 } position++ if buffer[position] != rune('e') { - goto l365 + goto l366 } position++ if buffer[position] != rune('l') { - goto l365 + goto l366 } position++ if buffer[position] != rune('d') { - goto l365 + goto l366 } position++ } - l371: - add(rulereserved, position370) + l372: + add(rulereserved, position371) } } - l368: - add(rulePegText, position367) + l369: + add(rulePegText, position368) } { add(ruleAction56, position) } - add(rulefield, position366) + add(rulefield, position367) } return true - l365: - position, tokenIndex = position365, tokenIndex365 + l366: + position, tokenIndex = position366, tokenIndex366 return false }, /* 18 reserved <- <(('_' 'r' 'o' 'w') / ('_' 'c' 'o' 'l') / ('_' 's' 't' 'a' 'r' 't') / ('_' 'e' 'n' 'd') / ('_' 't' 'i' 'm' 'e' 's' 't' 'a' 'm' 'p') / ('_' 'f' 'i' 'e' 'l' 'd'))> */ nil, /* 19 posfield <- <(('f' 'i' 'e' 'l' 'd' '=')? Action57)> */ func() bool { - position379, tokenIndex379 := position, tokenIndex + position380, tokenIndex380 := position, tokenIndex { - position380 := position + position381 := position { - position381, tokenIndex381 := position, tokenIndex + position382, tokenIndex382 := position, tokenIndex if buffer[position] != rune('f') { - goto l381 + goto l382 } position++ if buffer[position] != rune('i') { - goto l381 + goto l382 } position++ if buffer[position] != rune('e') { - goto l381 + goto l382 } position++ if buffer[position] != rune('l') { - goto l381 + goto l382 } position++ if buffer[position] != rune('d') { - goto l381 + goto l382 } position++ if buffer[position] != rune('=') { - goto l381 + goto l382 } position++ - goto l382 - l381: - position, tokenIndex = position381, tokenIndex381 + goto l383 + l382: + position, tokenIndex = position382, tokenIndex382 } - l382: + l383: { - position383 := position + position384 := position if !_rules[rulefieldExpr]() { - goto l379 + goto l380 } - add(rulePegText, position383) + add(rulePegText, position384) } { add(ruleAction57, position) } - add(ruleposfield, position380) + add(ruleposfield, position381) } return true - l379: - position, tokenIndex = position379, tokenIndex379 + l380: + position, tokenIndex = position380, tokenIndex380 return false }, /* 20 col <- <(( Action58) / (<('\'' singlequotedstring '\'')> Action59) / (<('"' doublequotedstring '"')> Action60))> */ func() bool { - position385, tokenIndex385 := position, tokenIndex + position386, tokenIndex386 := position, tokenIndex { - position386 := position + position387 := position { - position387, tokenIndex387 := position, tokenIndex + position388, tokenIndex388 := position, tokenIndex { - position389 := position + position390 := position if !_rules[ruledigits]() { - goto l388 + goto l389 } - add(rulePegText, position389) + add(rulePegText, position390) } { add(ruleAction58, position) } - goto l387 - l388: - position, tokenIndex = position387, tokenIndex387 + goto l388 + l389: + position, tokenIndex = position388, tokenIndex388 { - position392 := position + position393 := position if buffer[position] != rune('\'') { - goto l391 + goto l392 } position++ if !_rules[rulesinglequotedstring]() { - goto l391 + goto l392 } if buffer[position] != rune('\'') { - goto l391 + goto l392 } position++ - add(rulePegText, position392) + add(rulePegText, position393) } { add(ruleAction59, position) } - goto l387 - l391: - position, tokenIndex = position387, tokenIndex387 + goto l388 + l392: + position, tokenIndex = position388, tokenIndex388 { - position394 := position + position395 := position if buffer[position] != rune('"') { - goto l385 + goto l386 } position++ if !_rules[ruledoublequotedstring]() { - goto l385 + goto l386 } if buffer[position] != rune('"') { - goto l385 + goto l386 } position++ - add(rulePegText, position394) + add(rulePegText, position395) } { add(ruleAction60, position) } } - l387: - add(rulecol, position386) + l388: + add(rulecol, position387) } return true - l385: - position, tokenIndex = position385, tokenIndex385 + l386: + position, tokenIndex = position386, tokenIndex386 return false }, /* 21 open <- <('(' sp)> */ func() bool { - position396, tokenIndex396 := position, tokenIndex + position397, tokenIndex397 := position, tokenIndex { - position397 := position + position398 := position if buffer[position] != rune('(') { - goto l396 + goto l397 } position++ if !_rules[rulesp]() { - goto l396 + goto l397 } - add(ruleopen, position397) + add(ruleopen, position398) } return true - l396: - position, tokenIndex = position396, tokenIndex396 + l397: + position, tokenIndex = position397, tokenIndex397 return false }, /* 22 close <- <(sp ')' sp)> */ func() bool { - position398, tokenIndex398 := position, tokenIndex + position399, tokenIndex399 := position, tokenIndex { - position399 := position + position400 := position if !_rules[rulesp]() { - goto l398 + goto l399 } if buffer[position] != rune(')') { - goto l398 + goto l399 } position++ if !_rules[rulesp]() { - goto l398 + goto l399 } - add(ruleclose, position399) + add(ruleclose, position400) } return true - l398: - position, tokenIndex = position398, tokenIndex398 + l399: + position, tokenIndex = position399, tokenIndex399 return false }, /* 23 sp <- <(' ' / '\t' / '\n')*> */ func() bool { { - position401 := position - l402: + position402 := position + l403: { - position403, tokenIndex403 := position, tokenIndex + position404, tokenIndex404 := position, tokenIndex { - position404, tokenIndex404 := position, tokenIndex + position405, tokenIndex405 := position, tokenIndex if buffer[position] != rune(' ') { - goto l405 - } - position++ - goto l404 - l405: - position, tokenIndex = position404, tokenIndex404 - if buffer[position] != rune('\t') { goto l406 } position++ - goto l404 + goto l405 l406: - position, tokenIndex = position404, tokenIndex404 + position, tokenIndex = position405, tokenIndex405 + if buffer[position] != rune('\t') { + goto l407 + } + position++ + goto l405 + l407: + position, tokenIndex = position405, tokenIndex405 if buffer[position] != rune('\n') { - goto l403 + goto l404 } position++ } + l405: + goto l403 l404: - goto l402 - l403: - position, tokenIndex = position403, tokenIndex403 + position, tokenIndex = position404, tokenIndex404 } - add(rulesp, position401) + add(rulesp, position402) } return true }, /* 24 eq <- <(sp '=' sp)> */ func() bool { - position407, tokenIndex407 := position, tokenIndex + position408, tokenIndex408 := position, tokenIndex { - position408 := position + position409 := position if !_rules[rulesp]() { - goto l407 + goto l408 } if buffer[position] != rune('=') { - goto l407 + goto l408 } position++ if !_rules[rulesp]() { - goto l407 + goto l408 } - add(ruleeq, position408) + add(ruleeq, position409) } return true - l407: - position, tokenIndex = position407, tokenIndex407 + l408: + position, tokenIndex = position408, tokenIndex408 return false }, /* 25 comma <- <(sp ',' sp)> */ func() bool { - position409, tokenIndex409 := position, tokenIndex + position410, tokenIndex410 := position, tokenIndex { - position410 := position + position411 := position if !_rules[rulesp]() { - goto l409 + goto l410 } if buffer[position] != rune(',') { - goto l409 + goto l410 } position++ if !_rules[rulesp]() { - goto l409 + goto l410 } - add(rulecomma, position410) + add(rulecomma, position411) } return true - l409: - position, tokenIndex = position409, tokenIndex409 + l410: + position, tokenIndex = position410, tokenIndex410 return false }, /* 26 lbrack <- <('[' sp)> */ @@ -3620,237 +3627,237 @@ func (p *PQL) Init(options ...func(*PQL) error) error { nil, /* 28 IDENT <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / [0-9])*)> */ func() bool { - position413, tokenIndex413 := position, tokenIndex + position414, tokenIndex414 := position, tokenIndex { - position414 := position + position415 := position { - position415, tokenIndex415 := position, tokenIndex + position416, tokenIndex416 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l416 + goto l417 } position++ - goto l415 - l416: - position, tokenIndex = position415, tokenIndex415 + goto l416 + l417: + position, tokenIndex = position416, tokenIndex416 if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l413 + goto l414 } position++ } - l415: - l417: + l416: + l418: { - position418, tokenIndex418 := position, tokenIndex + position419, tokenIndex419 := position, tokenIndex { - position419, tokenIndex419 := position, tokenIndex + position420, tokenIndex420 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l420 - } - position++ - goto l419 - l420: - position, tokenIndex = position419, tokenIndex419 - if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l421 } position++ - goto l419 + goto l420 l421: - position, tokenIndex = position419, tokenIndex419 + position, tokenIndex = position420, tokenIndex420 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l422 + } + position++ + goto l420 + l422: + position, tokenIndex = position420, tokenIndex420 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l418 + goto l419 } position++ } + l420: + goto l418 l419: - goto l417 - l418: - position, tokenIndex = position418, tokenIndex418 + position, tokenIndex = position419, tokenIndex419 } - add(ruleIDENT, position414) + add(ruleIDENT, position415) } return true - l413: - position, tokenIndex = position413, tokenIndex413 + l414: + position, tokenIndex = position414, tokenIndex414 return false }, /* 29 digits <- <[0-9]+> */ func() bool { - position422, tokenIndex422 := position, tokenIndex + position423, tokenIndex423 := position, tokenIndex { - position423 := position + position424 := position if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l422 + goto l423 } position++ - l424: + l425: { - position425, tokenIndex425 := position, tokenIndex + position426, tokenIndex426 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l425 + goto l426 } position++ - goto l424 - l425: - position, tokenIndex = position425, tokenIndex425 + goto l425 + l426: + position, tokenIndex = position426, tokenIndex426 } - add(ruledigits, position423) + add(ruledigits, position424) } return true - l422: - position, tokenIndex = position422, tokenIndex422 + l423: + position, tokenIndex = position423, tokenIndex423 return false }, /* 30 signedDigits <- <('-'? digits)> */ nil, /* 31 decimal <- <((signedDigits ('.' digits?)?) / ('-'? '.' digits))> */ func() bool { - position427, tokenIndex427 := position, tokenIndex + position428, tokenIndex428 := position, tokenIndex { - position428 := position + position429 := position { - position429, tokenIndex429 := position, tokenIndex + position430, tokenIndex430 := position, tokenIndex { - position431 := position + position432 := position { - position432, tokenIndex432 := position, tokenIndex + position433, tokenIndex433 := position, tokenIndex if buffer[position] != rune('-') { - goto l432 + goto l433 } position++ - goto l433 - l432: - position, tokenIndex = position432, tokenIndex432 + goto l434 + l433: + position, tokenIndex = position433, tokenIndex433 } - l433: + l434: if !_rules[ruledigits]() { - goto l430 + goto l431 } - add(rulesignedDigits, position431) + add(rulesignedDigits, position432) } { - position434, tokenIndex434 := position, tokenIndex + position435, tokenIndex435 := position, tokenIndex if buffer[position] != rune('.') { - goto l434 + goto l435 } position++ { - position436, tokenIndex436 := position, tokenIndex + position437, tokenIndex437 := position, tokenIndex if !_rules[ruledigits]() { - goto l436 + goto l437 } - goto l437 - l436: - position, tokenIndex = position436, tokenIndex436 - } - l437: - goto l435 - l434: - position, tokenIndex = position434, tokenIndex434 - } - l435: - goto l429 - l430: - position, tokenIndex = position429, tokenIndex429 - { - position438, tokenIndex438 := position, tokenIndex - if buffer[position] != rune('-') { goto l438 + l437: + position, tokenIndex = position437, tokenIndex437 + } + l438: + goto l436 + l435: + position, tokenIndex = position435, tokenIndex435 + } + l436: + goto l430 + l431: + position, tokenIndex = position430, tokenIndex430 + { + position439, tokenIndex439 := position, tokenIndex + if buffer[position] != rune('-') { + goto l439 } position++ - goto l439 - l438: - position, tokenIndex = position438, tokenIndex438 + goto l440 + l439: + position, tokenIndex = position439, tokenIndex439 } - l439: + l440: if buffer[position] != rune('.') { - goto l427 + goto l428 } position++ if !_rules[ruledigits]() { - goto l427 + goto l428 } } - l429: - add(ruledecimal, position428) + l430: + add(ruledecimal, position429) } return true - l427: - position, tokenIndex = position427, tokenIndex427 + l428: + position, tokenIndex = position428, tokenIndex428 return false }, /* 32 tz <- <('Z' / ('-' [0-9] [0-9] ':' [0-9] [0-9]) / ('+' [0-9] [0-9] ':' [0-9] [0-9]))> */ func() bool { - position440, tokenIndex440 := position, tokenIndex + position441, tokenIndex441 := position, tokenIndex { - position441 := position + position442 := position { - position442, tokenIndex442 := position, tokenIndex + position443, tokenIndex443 := position, tokenIndex if buffer[position] != rune('Z') { - goto l443 - } - position++ - goto l442 - l443: - position, tokenIndex = position442, tokenIndex442 - if buffer[position] != rune('-') { goto l444 } position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l444 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l444 - } - position++ - if buffer[position] != rune(':') { - goto l444 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l444 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l444 - } - position++ - goto l442 + goto l443 l444: - position, tokenIndex = position442, tokenIndex442 - if buffer[position] != rune('+') { - goto l440 + position, tokenIndex = position443, tokenIndex443 + if buffer[position] != rune('-') { + goto l445 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l440 + goto l445 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l440 + goto l445 } position++ if buffer[position] != rune(':') { - goto l440 + goto l445 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l440 + goto l445 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l440 + goto l445 + } + position++ + goto l443 + l445: + position, tokenIndex = position443, tokenIndex443 + if buffer[position] != rune('+') { + goto l441 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l441 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l441 + } + position++ + if buffer[position] != rune(':') { + goto l441 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l441 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l441 } position++ } - l442: - add(ruletz, position441) + l443: + add(ruletz, position442) } return true - l440: - position, tokenIndex = position440, tokenIndex440 + l441: + position, tokenIndex = position441, tokenIndex441 return false }, /* 33 iso8601 <- <([0-9] [0-9] [0-9] [0-9] '-' ('0' / '1') [0-9] '-' [0-3] [0-9] 'T' [0-9] [0-9] ':' [0-9] [0-9] ':' [0-9] [0-9] )> */ @@ -3859,384 +3866,384 @@ func (p *PQL) Init(options ...func(*PQL) error) error { nil, /* 35 timestampbasicfmt <- <(iso8601nano / iso8601)> */ func() bool { - position447, tokenIndex447 := position, tokenIndex + position448, tokenIndex448 := position, tokenIndex { - position448 := position + position449 := position { - position449, tokenIndex449 := position, tokenIndex + position450, tokenIndex450 := position, tokenIndex { - position451 := position + position452 := position if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if buffer[position] != rune('-') { - goto l450 + goto l451 } position++ { - position452, tokenIndex452 := position, tokenIndex + position453, tokenIndex453 := position, tokenIndex if buffer[position] != rune('0') { - goto l453 + goto l454 } position++ - goto l452 - l453: - position, tokenIndex = position452, tokenIndex452 + goto l453 + l454: + position, tokenIndex = position453, tokenIndex453 if buffer[position] != rune('1') { - goto l450 + goto l451 } position++ } - l452: + l453: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if buffer[position] != rune('-') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('3') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if buffer[position] != rune('T') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if buffer[position] != rune(':') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if buffer[position] != rune(':') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ if buffer[position] != rune('.') { - goto l450 + goto l451 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l450 + goto l451 } position++ - l454: + l455: { - position455, tokenIndex455 := position, tokenIndex + position456, tokenIndex456 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l455 + goto l456 } position++ - goto l454 - l455: - position, tokenIndex = position455, tokenIndex455 + goto l455 + l456: + position, tokenIndex = position456, tokenIndex456 } { - position456 := position + position457 := position if !_rules[ruletz]() { - goto l450 + goto l451 } - add(rulePegText, position456) + add(rulePegText, position457) } - add(ruleiso8601nano, position451) + add(ruleiso8601nano, position452) } - goto l449 - l450: - position, tokenIndex = position449, tokenIndex449 + goto l450 + l451: + position, tokenIndex = position450, tokenIndex450 { - position457 := position + position458 := position if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if buffer[position] != rune('-') { - goto l447 + goto l448 } position++ { - position458, tokenIndex458 := position, tokenIndex + position459, tokenIndex459 := position, tokenIndex if buffer[position] != rune('0') { - goto l459 + goto l460 } position++ - goto l458 - l459: - position, tokenIndex = position458, tokenIndex458 + goto l459 + l460: + position, tokenIndex = position459, tokenIndex459 if buffer[position] != rune('1') { - goto l447 + goto l448 } position++ } - l458: + l459: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if buffer[position] != rune('-') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('3') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if buffer[position] != rune('T') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if buffer[position] != rune(':') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if buffer[position] != rune(':') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l447 + goto l448 } position++ { - position460 := position + position461 := position if !_rules[ruletz]() { - goto l447 + goto l448 } - add(rulePegText, position460) + add(rulePegText, position461) } - add(ruleiso8601, position457) + add(ruleiso8601, position458) } } - l449: - add(ruletimestampbasicfmt, position448) + l450: + add(ruletimestampbasicfmt, position449) } return true - l447: - position, tokenIndex = position447, tokenIndex447 + l448: + position, tokenIndex = position448, tokenIndex448 return false }, /* 36 timestampfmt <- <(('"' '"') / ('\'' '\'') / )> */ nil, /* 37 timebasicfmt <- <([0-9] [0-9] [0-9] [0-9] '-' ('0' / '1') [0-9] '-' [0-3] [0-9] 'T' [0-9] [0-9] ':' [0-9] [0-9])> */ func() bool { - position462, tokenIndex462 := position, tokenIndex + position463, tokenIndex463 := position, tokenIndex { - position463 := position + position464 := position if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ if buffer[position] != rune('-') { - goto l462 + goto l463 } position++ { - position464, tokenIndex464 := position, tokenIndex + position465, tokenIndex465 := position, tokenIndex if buffer[position] != rune('0') { - goto l465 + goto l466 } position++ - goto l464 - l465: - position, tokenIndex = position464, tokenIndex464 + goto l465 + l466: + position, tokenIndex = position465, tokenIndex465 if buffer[position] != rune('1') { - goto l462 + goto l463 } position++ } - l464: + l465: if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ if buffer[position] != rune('-') { - goto l462 + goto l463 } position++ if c := buffer[position]; c < rune('0') || c > rune('3') { - goto l462 + goto l463 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ if buffer[position] != rune('T') { - goto l462 + goto l463 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ if buffer[position] != rune(':') { - goto l462 + goto l463 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l462 + goto l463 } position++ - add(ruletimebasicfmt, position463) + add(ruletimebasicfmt, position464) } return true - l462: - position, tokenIndex = position462, tokenIndex462 + l463: + position, tokenIndex = position463, tokenIndex463 return false }, /* 38 timefmt <- <(('"' '"') / ('\'' '\'') / )> */ func() bool { - position466, tokenIndex466 := position, tokenIndex + position467, tokenIndex467 := position, tokenIndex { - position467 := position + position468 := position { - position468, tokenIndex468 := position, tokenIndex + position469, tokenIndex469 := position, tokenIndex if buffer[position] != rune('"') { - goto l469 + goto l470 } position++ { - position470 := position + position471 := position if !_rules[ruletimebasicfmt]() { - goto l469 + goto l470 } - add(rulePegText, position470) + add(rulePegText, position471) } if buffer[position] != rune('"') { - goto l469 + goto l470 } position++ - goto l468 - l469: - position, tokenIndex = position468, tokenIndex468 + goto l469 + l470: + position, tokenIndex = position469, tokenIndex469 if buffer[position] != rune('\'') { - goto l471 + goto l472 } position++ - { - position472 := position - if !_rules[ruletimebasicfmt]() { - goto l471 - } - add(rulePegText, position472) - } - if buffer[position] != rune('\'') { - goto l471 - } - position++ - goto l468 - l471: - position, tokenIndex = position468, tokenIndex468 { position473 := position if !_rules[ruletimebasicfmt]() { - goto l466 + goto l472 } add(rulePegText, position473) } + if buffer[position] != rune('\'') { + goto l472 + } + position++ + goto l469 + l472: + position, tokenIndex = position469, tokenIndex469 + { + position474 := position + if !_rules[ruletimebasicfmt]() { + goto l467 + } + add(rulePegText, position474) + } } - l468: - add(ruletimefmt, position467) + l469: + add(ruletimefmt, position468) } return true - l466: - position, tokenIndex = position466, tokenIndex466 + l467: + position, tokenIndex = position467, tokenIndex467 return false }, /* 39 time <- <( Action61)> */ From 4fb795d6cb1f6605463603373bed9891cb83372a Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Mon, 7 Feb 2022 15:40:24 -0700 Subject: [PATCH 05/14] Parse variables for _field --- pql/ast.go | 41 ++++++++++++++++++++++++++++++----------- pql/pqlpeg_test.go | 9 +++++++++ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/pql/ast.go b/pql/ast.go index 02ce5618d..be4c2fb1d 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -78,7 +78,11 @@ func (q *Query) addPosNum(key, value string) { func (q *Query) addPosStr(key, value string) { q.addField(key) - q.addVal(value) + if strings.HasPrefix(value, "$") { + q.addVal(NewVariable(strings.TrimPrefix(value, "$"))) + } else { + q.addVal(value) + } } func (q *Query) startConditional() { @@ -369,11 +373,17 @@ type stringOrInt64Type struct{} var stringOrInt64 stringOrInt64Type +// We want to be able to accept either a string or variable for +// _field args. Special-case type: +type stringOrVariableType struct{} + +var stringOrVariable stringOrVariableType + var allowField = callInfo{ allowUnknown: false, prototypes: map[string]interface{}{ - "_field": "", - "field": "", + "_field": stringOrVariable, + "field": stringOrVariable, }, } @@ -419,8 +429,8 @@ var callInfoByFunc = map[string]callInfo{ "Rows": { allowUnknown: false, prototypes: map[string]interface{}{ - "_field": "", - "field": "", + "_field": stringOrVariable, + "field": stringOrVariable, "limit": int64(0), "column": nil, "previous": nil, @@ -466,8 +476,8 @@ var callInfoByFunc = map[string]callInfo{ "TopK": { allowUnknown: false, prototypes: map[string]interface{}{ - "_field": "", - "field": "", + "_field": stringOrVariable, + "field": stringOrVariable, "k": int64(0), "filter": nil, "from": nil, @@ -478,15 +488,15 @@ var callInfoByFunc = map[string]callInfo{ "TopN": { allowUnknown: true, prototypes: map[string]interface{}{ - "_field": "", - "field": "", + "_field": stringOrVariable, + "field": stringOrVariable, }, }, "Percentile": { allowUnknown: false, prototypes: map[string]interface{}{ - "field": "", - "_field": "", + "field": stringOrVariable, + "_field": stringOrVariable, "filter": nil, "nth": nil, }, @@ -595,6 +605,15 @@ func (c *Call) CheckCallInfo() error { c.String(), k, v) } } + if reflect.TypeOf(acceptable) == reflect.TypeOf(stringOrVariable) { + switch v.(type) { + case string, *Variable: + continue + default: + return fmt.Errorf("'%s': arg '%s' needed a string or variable value, got %T", + c.String(), k, v) + } + } return fmt.Errorf("'%s': arg '%s' wrong type (got %T, expected %T)", c.String(), k, v, acceptable) } diff --git a/pql/pqlpeg_test.go b/pql/pqlpeg_test.go index b11f0392c..d4a799e6e 100644 --- a/pql/pqlpeg_test.go +++ b/pql/pqlpeg_test.go @@ -761,6 +761,15 @@ func TestPQLDeepEquality(t *testing.T) { "f": &Variable{Name: "my_VAR123"}, }, }}, + { + name: "RowsWithVariable", + call: `Rows($var)`, + exp: &Call{ + Name: "Rows", + Args: map[string]interface{}{ + "_field": &Variable{Name: "var"}, + }, + }}, } for i, test := range tests { From 9a52dd1a2cbc5d82537ee3b174d32c1586729cb7 Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Mon, 7 Feb 2022 20:00:05 -0600 Subject: [PATCH 06/14] handle rows for the most part --- pql/ast.go | 82 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/pql/ast.go b/pql/ast.go index be4c2fb1d..f6165bfe4 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -937,29 +937,34 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { switch c.Name { case "Row": for argK, argV := range c.Args { // animal: interface{} - switch variable := argV.(type) { + var variable *Variable + switch vari := argV.(type) { + case *Condition: + variable = vari.Value.(*Variable) case *Variable: // if interface{} is of type Variable - for varK, varV := range vars { // go through all the vars. "var1": ["cat", "dog"] - if variable.Name == varK { - switch values := varV.(type) { - case []interface{}: - union := &Call{Name: "Union"} - for i := range values { - r := Call{Name: "Row"} - r.Args = CopyArgs(c.Args) - switch cond := r.Args[argK].(type) { - case *Condition: - r.Args[argK] = &Condition{Op: cond.Op, Value: values[i]} - default: - r.Args[argK] = values[i] - } - union.Children = append(union.Children, &r) + variable = vari + default: + return []*Call{c}, nil + } + for varK, varV := range vars { // go through all the vars. "var1": ["cat", "dog"] + if variable.Name == varK { + switch values := varV.(type) { + case []interface{}: + union := &Call{Name: "Union"} + for i := range values { + r := Call{Name: "Row"} + r.Args = CopyArgs(c.Args) + switch cond := r.Args[argK].(type) { + case *Condition: + r.Args[argK] = &Condition{Op: cond.Op, Value: values[i]} + default: + r.Args[argK] = values[i] } - return []*Call{union}, nil + union.Children = append(union.Children, &r) } + return []*Call{union}, nil } } - } } @@ -985,21 +990,29 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { // } return []*Call{c}, nil case "Rows": - for k, v := range vars { - if _, ok := c.Args[k]; ok { - rows := make([]*Call, len(vars)) - switch tv := v.(type) { - case []interface{}: - for i := range tv { - r := Call{Name: "Rows"} - r.Args = CopyArgs(c.Args) - r.Args[k] = tv[i] - rows = append(rows, &r) + + for argK, argV := range c.Args { // animal: interface{} + switch variable := argV.(type) { + case *Variable: // if interface{} is of type Variable + for varK, varV := range vars { // go through all the vars. "var1": ["cat", "dog"] + if variable.Name == varK { + switch values := varV.(type) { + case []interface{}: + rows := make([]*Call, 0, len(values)) + for i := range values { + r := Call{Name: "Rows"} + r.Args = CopyArgs(c.Args) + r.Args[argK] = values[i] + rows = append(rows, &r) + } + return rows, nil + } } } - return rows, nil + } } + return []*Call{c}, nil // row1 := &Call{Name: "Rows"} // row2 := &Call{Name: "Rows"} @@ -1015,6 +1028,17 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { } other.Children = append(other.Children, newChildren...) } + for key, val := range other.Args { + switch call := val.(type) { + case *Call: + newChildren, err := call.ExpandVars(vars) + if err != nil { + return nil, err + } + other.Args[key] = newChildren[0] + + } + } return []*Call{other}, nil //Expand then return Union to caller } From fbe23915cf2f6bb3af7018e294b8134d070781b7 Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Tue, 8 Feb 2022 13:39:22 -0600 Subject: [PATCH 07/14] support ConstRow expansion and cleanup --- pql/ast.go | 104 ++++++++++++++++++++++++----------------------------- 1 file changed, 47 insertions(+), 57 deletions(-) diff --git a/pql/ast.go b/pql/ast.go index f6165bfe4..29e9eccc7 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -379,6 +379,12 @@ type stringOrVariableType struct{} var stringOrVariable stringOrVariableType +// We want to be able to accept either a interface or variable for +// column args. Special-case type: +type interfaceOrVariableType struct{} + +var interfaceOrVariable stringOrVariableType + var allowField = callInfo{ allowUnknown: false, prototypes: map[string]interface{}{ @@ -468,7 +474,8 @@ var callInfoByFunc = map[string]callInfo{ "ConstRow": { allowUnknown: false, prototypes: map[string]interface{}{ - "columns": []interface{}{}, + "columns": interfaceOrVariable, + // "columns": []interface{}{}, }, callType: PrecallGlobal, }, @@ -614,6 +621,15 @@ func (c *Call) CheckCallInfo() error { c.String(), k, v) } } + if reflect.TypeOf(acceptable) == reflect.TypeOf(interfaceOrVariable) { + switch v.(type) { + case []interface{}, *Variable: + continue + default: + return fmt.Errorf("'%s': arg '%s' needed a []interfacer{} or variable value, got %T", + c.String(), k, v) + } + } return fmt.Errorf("'%s': arg '%s' wrong type (got %T, expected %T)", c.String(), k, v, acceptable) } @@ -935,14 +951,14 @@ func (c *Call) ArgString(key string) string { func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { switch c.Name { - case "Row": + case "Row", "ConstRow", "Rows": for argK, argV := range c.Args { // animal: interface{} var variable *Variable - switch vari := argV.(type) { + switch _var := argV.(type) { case *Condition: - variable = vari.Value.(*Variable) + variable = _var.Value.(*Variable) case *Variable: // if interface{} is of type Variable - variable = vari + variable = _var default: return []*Call{c}, nil } @@ -950,54 +966,22 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { if variable.Name == varK { switch values := varV.(type) { case []interface{}: - union := &Call{Name: "Union"} - for i := range values { - r := Call{Name: "Row"} - r.Args = CopyArgs(c.Args) - switch cond := r.Args[argK].(type) { - case *Condition: - r.Args[argK] = &Condition{Op: cond.Op, Value: values[i]} - default: - r.Args[argK] = values[i] + switch c.Name { + case "Row": + union := &Call{Name: "Union"} + for i := range values { + r := Call{Name: "Row"} + r.Args = CopyArgs(c.Args) + switch cond := r.Args[argK].(type) { + case *Condition: + r.Args[argK] = &Condition{Op: cond.Op, Value: values[i]} + default: + r.Args[argK] = values[i] + } + union.Children = append(union.Children, &r) } - union.Children = append(union.Children, &r) - } - return []*Call{union}, nil - } - } - } - } - - // for k, v := range vars { - // if _, ok := c.Args[k]; ok { - // union := &Call{Name: "Union"} - // switch tv := v.(type) { - // case []interface{}: - // for i := range tv { - // r := Call{Name: "Row"} - // r.Args = CopyArgs(c.Args) - // switch cond := r.Args[k].(type) { - // case *Condition: - // r.Args[k] = &Condition{Op: cond.Op, Value: tv[i]} - // default: - // r.Args[k] = tv[i] - // } - // union.Children = append(union.Children, &r) - // } - // } - // return []*Call{union}, nil - // } - // } - return []*Call{c}, nil - case "Rows": - - for argK, argV := range c.Args { // animal: interface{} - switch variable := argV.(type) { - case *Variable: // if interface{} is of type Variable - for varK, varV := range vars { // go through all the vars. "var1": ["cat", "dog"] - if variable.Name == varK { - switch values := varV.(type) { - case []interface{}: + return []*Call{union}, nil + case "Rows": rows := make([]*Call, 0, len(values)) for i := range values { r := Call{Name: "Rows"} @@ -1006,17 +990,21 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { rows = append(rows, &r) } return rows, nil + case "ConstRow": + r := Call{Name: "ConstRow"} + r.Args = CopyArgs(c.Args) + r.Args[argK] = values + return []*Call{&r}, nil + default: + // TODO: } + default: + // TODO: } } - } } - return []*Call{c}, nil - // row1 := &Call{Name: "Rows"} - // row2 := &Call{Name: "Rows"} - // return []*Call{row1, row2}, nil default: other := &Call{} copier.Copy(other, c) @@ -1036,6 +1024,8 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { return nil, err } other.Args[key] = newChildren[0] + default: + //TODO } } From cd0bdd4c30d05a1e2e7111c7511f56f33f7f92f6 Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Tue, 8 Feb 2022 15:43:14 -0600 Subject: [PATCH 08/14] refactor --- pql/ast.go | 151 +++++++++++++++++++---------------------------------- 1 file changed, 55 insertions(+), 96 deletions(-) diff --git a/pql/ast.go b/pql/ast.go index 29e9eccc7..ac3fef673 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -949,57 +949,22 @@ func (c *Call) ArgString(key string) string { return s } +// ExpandVars recursively replaces variables in the call with their values. func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { switch c.Name { case "Row", "ConstRow", "Rows": for argK, argV := range c.Args { // animal: interface{} - var variable *Variable - switch _var := argV.(type) { - case *Condition: - variable = _var.Value.(*Variable) - case *Variable: // if interface{} is of type Variable - variable = _var - default: + variable := getVariable(argV) + if variable == nil { return []*Call{c}, nil } for varK, varV := range vars { // go through all the vars. "var1": ["cat", "dog"] if variable.Name == varK { switch values := varV.(type) { case []interface{}: - switch c.Name { - case "Row": - union := &Call{Name: "Union"} - for i := range values { - r := Call{Name: "Row"} - r.Args = CopyArgs(c.Args) - switch cond := r.Args[argK].(type) { - case *Condition: - r.Args[argK] = &Condition{Op: cond.Op, Value: values[i]} - default: - r.Args[argK] = values[i] - } - union.Children = append(union.Children, &r) - } - return []*Call{union}, nil - case "Rows": - rows := make([]*Call, 0, len(values)) - for i := range values { - r := Call{Name: "Rows"} - r.Args = CopyArgs(c.Args) - r.Args[argK] = values[i] - rows = append(rows, &r) - } - return rows, nil - case "ConstRow": - r := Call{Name: "ConstRow"} - r.Args = CopyArgs(c.Args) - r.Args[argK] = values - return []*Call{&r}, nil - default: - // TODO: - } + return c.expandVars(argK, values), nil default: - // TODO: + return nil, fmt.Errorf("expected variable value of type []interface{}, got: %T", values) } } } @@ -1019,14 +984,14 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { for key, val := range other.Args { switch call := val.(type) { case *Call: - newChildren, err := call.ExpandVars(vars) + newArg, err := call.ExpandVars(vars) if err != nil { return nil, err } - other.Args[key] = newChildren[0] - default: - //TODO - + if len(newArg) != 1 { + return nil, fmt.Errorf("variable: requires single value for argument") + } + other.Args[key] = newArg[0] } } return []*Call{other}, nil @@ -1034,58 +999,52 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { } } -// ExpandVars recursively replaces variables in the call with their values. -// func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { -// other := *c -// other.Args = CopyArgs(c.Args) -// other.Children = make([]*Call, 0, len(c.Children)) +// expandVars specifies the implementation for variable expansion for various Call types +func (c *Call) expandVars(name string, values []interface{}) []*Call { + switch c.Name { + case "Row": + union := &Call{Name: "Union"} + for i := range values { + r := Call{Name: "Row"} + r.Args = CopyArgs(c.Args) + switch cond := r.Args[name].(type) { + case *Condition: + r.Args[name] = &Condition{Op: cond.Op, Value: values[i]} + default: + r.Args[name] = values[i] + } + union.Children = append(union.Children, &r) + } + return []*Call{union} + case "Rows": + rows := make([]*Call, 0, len(values)) + for i := range values { + r := Call{Name: "Rows"} + r.Args = CopyArgs(c.Args) + r.Args[name] = values[i] + rows = append(rows, &r) + } + return rows + case "ConstRow": + r := Call{Name: "ConstRow"} + r.Args = CopyArgs(c.Args) + r.Args[name] = values + return []*Call{&r} + } + return []*Call{c} +} -// for _, child := range c.Children { -// switch child.Name { -// case "Row": -// for key, val := range vars { -// if _, ok := child.Args[key]; ok { -// // Make Union Cal -// union := &Call{Name: "Union"} -// // data type for val? -// vi := reflect.ValueOf(val) -// switch vi.Kind() { -// case reflect.Slice: -// for i := 0; i < vi.Len(); i++ { -// cpy := &Call{} -// copier.Copy(cpy, child) -// cpy.Args[key] = vi.Index(i) -// union.Children = append(union.Children, cpy) -// } -// // case []uint, []uint16, []uint32, []uint64: -// // case []float32, []float64: -// } -// // Loop thru val - -// // Make copy of Child replacing its val for val - -// other.Children = append(other.Children, union) -// break -// } -// } -// } -// } - -// // TODO: Replace field variables. - -// // Recursively expand variables in children. -// for _, child := range c.Children { -// newChildren, err := child.ExpandVars(vars) -// if err != nil { -// return nil, err -// } -// other.Children = append(other.Children, newChildren...) -// } - -// // TODO: Return multiple calls for list. - -// return []*Call{&other}, nil -// } +// getVariable returns *Variable given a Call argument if present +func getVariable(i interface{}) *Variable { + switch _var := i.(type) { + case *Condition: + return _var.Value.(*Variable) + case *Variable: // if interface{} is of type Variable + return _var + default: + return nil + } +} // Condition represents an operation & value. // When used in an argument map it represents a binary expression. From 9e8b968c19f099899a917d254255c5a1ddc73d9a Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Tue, 8 Feb 2022 15:43:14 -0600 Subject: [PATCH 09/14] Refactor ExpandVars to reduce complexity --- go.mod | 1 + go.sum | 2 + pql/ast.go | 156 ++++++++++++++++++++--------------------------------- 3 files changed, 60 insertions(+), 99 deletions(-) diff --git a/go.mod b/go.mod index f1d6d285b..6e0a32512 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/gorilla/securecookie v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.0 github.com/improbable-eng/grpc-web v0.13.0 + github.com/jinzhu/copier v0.3.5 github.com/lib/pq v1.8.0 github.com/molecula/apophenia v0.0.0-20190827192002-68b7a14a478b github.com/opentracing/opentracing-go v1.1.0 diff --git a/go.sum b/go.sum index 2778ff697..fdbdb8c1c 100644 --- a/go.sum +++ b/go.sum @@ -220,6 +220,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a h1:vMqgISSVkIqWxCIZs8m1L4096temR7IbYyNdMiBxSPA= github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o= +github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= +github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= diff --git a/pql/ast.go b/pql/ast.go index 29e9eccc7..65a74908f 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -949,57 +949,22 @@ func (c *Call) ArgString(key string) string { return s } +// ExpandVars recursively replaces variables in the call with their values. func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { switch c.Name { case "Row", "ConstRow", "Rows": - for argK, argV := range c.Args { // animal: interface{} - var variable *Variable - switch _var := argV.(type) { - case *Condition: - variable = _var.Value.(*Variable) - case *Variable: // if interface{} is of type Variable - variable = _var - default: + for argK, argV := range c.Args { + variable := getVariable(argV) + if variable == nil { return []*Call{c}, nil } - for varK, varV := range vars { // go through all the vars. "var1": ["cat", "dog"] + for varK, varV := range vars { if variable.Name == varK { switch values := varV.(type) { case []interface{}: - switch c.Name { - case "Row": - union := &Call{Name: "Union"} - for i := range values { - r := Call{Name: "Row"} - r.Args = CopyArgs(c.Args) - switch cond := r.Args[argK].(type) { - case *Condition: - r.Args[argK] = &Condition{Op: cond.Op, Value: values[i]} - default: - r.Args[argK] = values[i] - } - union.Children = append(union.Children, &r) - } - return []*Call{union}, nil - case "Rows": - rows := make([]*Call, 0, len(values)) - for i := range values { - r := Call{Name: "Rows"} - r.Args = CopyArgs(c.Args) - r.Args[argK] = values[i] - rows = append(rows, &r) - } - return rows, nil - case "ConstRow": - r := Call{Name: "ConstRow"} - r.Args = CopyArgs(c.Args) - r.Args[argK] = values - return []*Call{&r}, nil - default: - // TODO: - } + return c.expandVars(argK, values), nil default: - // TODO: + return nil, fmt.Errorf("expected variable value of type []interface{}, got: %T", values) } } } @@ -1019,73 +984,66 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { for key, val := range other.Args { switch call := val.(type) { case *Call: - newChildren, err := call.ExpandVars(vars) + newArg, err := call.ExpandVars(vars) if err != nil { return nil, err } - other.Args[key] = newChildren[0] - default: - //TODO - + if len(newArg) != 1 { + return nil, fmt.Errorf("variable: requires single value for argument, got: %+v", newArg) + } + other.Args[key] = newArg[0] } } return []*Call{other}, nil - //Expand then return Union to caller } } -// ExpandVars recursively replaces variables in the call with their values. -// func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { -// other := *c -// other.Args = CopyArgs(c.Args) -// other.Children = make([]*Call, 0, len(c.Children)) +// expandVars specifies the implementation for variable expansion for various Call types +func (c *Call) expandVars(name string, values []interface{}) []*Call { + switch c.Name { + case "Row": + union := &Call{Name: "Union"} + for i := range values { + r := Call{Name: "Row"} + r.Args = CopyArgs(c.Args) + switch cond := r.Args[name].(type) { + case *Condition: + r.Args[name] = &Condition{Op: cond.Op, Value: values[i]} + default: + r.Args[name] = values[i] + } + union.Children = append(union.Children, &r) + } + return []*Call{union} + case "Rows": + rows := make([]*Call, 0, len(values)) + for i := range values { + r := Call{Name: "Rows"} + r.Args = CopyArgs(c.Args) + r.Args[name] = values[i] + rows = append(rows, &r) + } + return rows + case "ConstRow": + r := Call{Name: "ConstRow"} + r.Args = CopyArgs(c.Args) + r.Args[name] = values + return []*Call{&r} + } + return []*Call{c} +} -// for _, child := range c.Children { -// switch child.Name { -// case "Row": -// for key, val := range vars { -// if _, ok := child.Args[key]; ok { -// // Make Union Cal -// union := &Call{Name: "Union"} -// // data type for val? -// vi := reflect.ValueOf(val) -// switch vi.Kind() { -// case reflect.Slice: -// for i := 0; i < vi.Len(); i++ { -// cpy := &Call{} -// copier.Copy(cpy, child) -// cpy.Args[key] = vi.Index(i) -// union.Children = append(union.Children, cpy) -// } -// // case []uint, []uint16, []uint32, []uint64: -// // case []float32, []float64: -// } -// // Loop thru val - -// // Make copy of Child replacing its val for val - -// other.Children = append(other.Children, union) -// break -// } -// } -// } -// } - -// // TODO: Replace field variables. - -// // Recursively expand variables in children. -// for _, child := range c.Children { -// newChildren, err := child.ExpandVars(vars) -// if err != nil { -// return nil, err -// } -// other.Children = append(other.Children, newChildren...) -// } - -// // TODO: Return multiple calls for list. - -// return []*Call{&other}, nil -// } +// getVariable returns *Variable given a Call argument if present +func getVariable(i interface{}) *Variable { + switch _var := i.(type) { + case *Condition: + return _var.Value.(*Variable) + case *Variable: // if interface{} is of type Variable + return _var + default: + return nil + } +} // Condition represents an operation & value. // When used in an argument map it represents a binary expression. From edc16a61ea0fba939b67d30e06eecfa1deb8f875 Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Tue, 8 Feb 2022 16:08:04 -0600 Subject: [PATCH 10/14] remove comment --- pql/ast.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pql/ast.go b/pql/ast.go index 65a74908f..383e37e15 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -475,7 +475,6 @@ var callInfoByFunc = map[string]callInfo{ allowUnknown: false, prototypes: map[string]interface{}{ "columns": interfaceOrVariable, - // "columns": []interface{}{}, }, callType: PrecallGlobal, }, From bfcbf9d784f33bc7085dc9245fcedeeb48edf927 Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Wed, 9 Feb 2022 11:29:11 -0600 Subject: [PATCH 11/14] change interfaceOrVariable type --- pql/ast.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pql/ast.go b/pql/ast.go index 383e37e15..3aa6a29db 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -383,7 +383,7 @@ var stringOrVariable stringOrVariableType // column args. Special-case type: type interfaceOrVariableType struct{} -var interfaceOrVariable stringOrVariableType +var interfaceOrVariable interfaceOrVariableType var allowField = callInfo{ allowUnknown: false, From be68241d8e1a9a5be73f1cd072f753701e13cab9 Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Wed, 9 Feb 2022 12:33:12 -0600 Subject: [PATCH 12/14] add test --- pql/ast_test.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/pql/ast_test.go b/pql/ast_test.go index b095fe878..d77fe623b 100644 --- a/pql/ast_test.go +++ b/pql/ast_test.go @@ -2,6 +2,7 @@ package pql_test import ( + "strings" "testing" "github.com/molecula/featurebase/v3/pql" @@ -52,3 +53,106 @@ func TestCondition_StringWithSubj(t *testing.T) { } } } + +func TestQuery_ExpandVars(t *testing.T) { + tests := []struct { + name string + input string + output string + vars map[string]interface{} + wantErr bool + }{ + { + name: "ExpandRowEQInterior", + input: `count(row(animal=$var1))`, + output: `Count(Union(Row(animal="cat"), Row(animal="dog"), Row(animal="pig")))`, + vars: map[string]interface{}{"var1": []interface{}{"cat", "dog", "pig"}}, + }, + { + name: "ExpandRowEQExterior", + input: `row(animal=$var1)`, + output: `Union(Row(animal="cat"))`, + vars: map[string]interface{}{"var1": []interface{}{"cat"}}, + }, + { + name: "ExpandRowGT", + input: `count(row(num>$var1))`, + output: `Count(Union(Row(num>5), Row(num>10)))`, + vars: map[string]interface{}{"var1": []interface{}{5, 10}}, + }, + { + name: "ExpandRowNOT", + input: `count(row(num!=$var1))`, + output: `Count(Union(Row(num!=5), Row(num!=10)))`, + vars: map[string]interface{}{"var1": []interface{}{5, 10}}, + }, + { + name: "ExpandRowLTString", + input: `count(row(num<$var1))`, + output: `Count(Union(Row(num<"cat"), Row(num<"dog")))`, + vars: map[string]interface{}{"var1": []interface{}{"cat", "dog"}}, + }, + { + name: "ExpandRowsInterior", + input: `GroupBy(rows($var1), limit=5)`, + output: `GroupBy(Rows(_field="cat"), Rows(_field="dog"), limit=5)`, + vars: map[string]interface{}{"var1": []interface{}{"cat", "dog"}}, + }, + { + name: "ExpandRowsExterior", + input: `rows($var1)`, + output: `Rows(_field="cat")` + "\n" + `Rows(_field="dog")`, + vars: map[string]interface{}{"var1": []interface{}{"cat", "dog"}}, + }, + { + name: "ExpandRowAndRows", + input: `GroupBy(Rows($animal), limit=7, filter=Row(size=$size))`, + output: `GroupBy(Rows(_field="cat"), Rows(_field="dog"), filter=Union(Row(size="lg"), Row(size="md")), limit=7)`, + vars: map[string]interface{}{"animal": []interface{}{"cat", "dog"}, "size": []interface{}{"lg", "md"}}, + }, + { + name: "ExpandBad", + input: `$animal`, + vars: map[string]interface{}{"animal": []interface{}{"cat", "dog"}, "columns": []interface{}{5, 10}}, + wantErr: true, + }, + { + name: "ExpandBad2", + input: `GroupBy($animal)`, + output: `Intersect(ConstRow(columns=[5, 10]), Union(Row(animal="cat"), Row(animal="dog")))`, + wantErr: true, + }, + { + name: "ExpandAsCSV", + input: `Intersect(ConstRow(columns=$var2), Row(animal=$var1))`, + output: `Intersect(ConstRow(columns=[5,10]), Union(Row(animal="cat"), Row(animal="dog")))`, + vars: map[string]interface{}{"var1": []interface{}{"cat", "dog"}, "var2": []interface{}{5, 10}}, + }, + { + name: "ExpandPercentile", + input: `Percentile(field="bytes", nth=99.0, filter=Row(level=$animal))`, + output: `Percentile(field="bytes", filter=Union(Row(level="cat"), Row(level="dog")), nth=99)`, + vars: map[string]interface{}{"animal": []interface{}{"cat", "dog"}, "columns": []interface{}{5, 10}}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + q, err := pql.NewParser(strings.NewReader(tt.input)).Parse() + if err != nil { + if !tt.wantErr { + t.Errorf("Parse error = %v, wantErr %v", err, tt.wantErr) + } + return + } + + got, err := q.ExpandVars(tt.vars) + if err != nil { + t.Errorf("Query.ExpandVars() error = %v", err) + return + } + if tt.output != got.String() { + t.Errorf("got %v, want %v", got, tt.output) + } + }) + } +} From 39c9a062aaae8c76563d6da9f89b4811edadde39 Mon Sep 17 00:00:00 2001 From: Samir Patel <48686912+54mir@users.noreply.github.com> Date: Wed, 9 Feb 2022 13:16:19 -0600 Subject: [PATCH 13/14] address feedback --- go.mod | 1 - go.sum | 2 -- pql/ast.go | 36 +++++++++++++++++++----------------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 6e0a32512..f1d6d285b 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,6 @@ require ( github.com/gorilla/securecookie v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.0 github.com/improbable-eng/grpc-web v0.13.0 - github.com/jinzhu/copier v0.3.5 github.com/lib/pq v1.8.0 github.com/molecula/apophenia v0.0.0-20190827192002-68b7a14a478b github.com/opentracing/opentracing-go v1.1.0 diff --git a/go.sum b/go.sum index fdbdb8c1c..2778ff697 100644 --- a/go.sum +++ b/go.sum @@ -220,8 +220,6 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a h1:vMqgISSVkIqWxCIZs8m1L4096temR7IbYyNdMiBxSPA= github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o= -github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= -github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= diff --git a/pql/ast.go b/pql/ast.go index 3aa6a29db..2f9ec02e8 100644 --- a/pql/ast.go +++ b/pql/ast.go @@ -9,8 +9,6 @@ import ( "strconv" "strings" "time" - - "github.com/jinzhu/copier" ) // Query represents a PQL query. @@ -625,7 +623,7 @@ func (c *Call) CheckCallInfo() error { case []interface{}, *Variable: continue default: - return fmt.Errorf("'%s': arg '%s' needed a []interfacer{} or variable value, got %T", + return fmt.Errorf("'%s': arg '%s' needed a []interface{} or variable value, got %T", c.String(), k, v) } } @@ -955,23 +953,25 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { for argK, argV := range c.Args { variable := getVariable(argV) if variable == nil { - return []*Call{c}, nil + continue } for varK, varV := range vars { - if variable.Name == varK { - switch values := varV.(type) { - case []interface{}: - return c.expandVars(argK, values), nil - default: - return nil, fmt.Errorf("expected variable value of type []interface{}, got: %T", values) - } + if variable.Name != varK { + continue } + switch values := varV.(type) { + case []interface{}: + return c.expandVars(argK, values), nil + default: + return nil, fmt.Errorf("expected variable value of type []interface{}, got: %T", values) + } + } } return []*Call{c}, nil default: - other := &Call{} - copier.Copy(other, c) + other := *c + other.Args = CopyArgs(c.Args) other.Children = make([]*Call, 0, len(c.Children)) for _, child := range c.Children { newChildren, err := child.ExpandVars(vars) @@ -993,7 +993,7 @@ func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) { other.Args[key] = newArg[0] } } - return []*Call{other}, nil + return []*Call{&other}, nil } } @@ -1003,8 +1003,7 @@ func (c *Call) expandVars(name string, values []interface{}) []*Call { case "Row": union := &Call{Name: "Union"} for i := range values { - r := Call{Name: "Row"} - r.Args = CopyArgs(c.Args) + r := Call{Name: "Row", Args: CopyArgs(c.Args)} switch cond := r.Args[name].(type) { case *Condition: r.Args[name] = &Condition{Op: cond.Op, Value: values[i]} @@ -1036,7 +1035,10 @@ func (c *Call) expandVars(name string, values []interface{}) []*Call { func getVariable(i interface{}) *Variable { switch _var := i.(type) { case *Condition: - return _var.Value.(*Variable) + if v, ok := _var.Value.(*Variable); ok { + return v + } + return nil case *Variable: // if interface{} is of type Variable return _var default: From 62e6544089fceb9eb10f07927e1794623a1e3aed Mon Sep 17 00:00:00 2001 From: "garrison.davis@molecula.com" Date: Wed, 9 Feb 2022 13:19:36 -0700 Subject: [PATCH 14/14] Stop termination in the gauntlet stage We have pipelines that get to the gauntlet stage then get failed because the ASG scales-in before the gauntlet stage finishes. (4/6 of the last gauntlet failures were from this failure.) There are a few ways to fix this, but my proposal is to turn on scale-in protection to stop scaling in the instance running the gauntlet job (scale in other instances instead), then turn off the scale-in protection after the gauntlet test is run. --- .gitlab/.gitlab-ci.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.gitlab/.gitlab-ci.yml b/.gitlab/.gitlab-ci.yml index 4c0cb0c3b..6039b4844 100644 --- a/.gitlab/.gitlab-ci.yml +++ b/.gitlab/.gitlab-ci.yml @@ -382,10 +382,12 @@ gauntlet: timeout: 4h image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest variables: - PROFILE: "service-terraform" + FBCI_PROFILE: "service-terraform" + INFRA_PROFILE: "service-gitlab" AWS_SSH_PRIVATE_KEY: $AWS_FBCI_SSH_KEY AWS_ACCESS_KEY_ID: $AWS_FBCI_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY: $AWS_FBCI_SECRET_ACCESS_KEY + ASG_NAME: "gitlab-runners" TF_VAR_cluster_prefix: "" TF_VAR_branch: "" tags: @@ -402,7 +404,9 @@ gauntlet: - aws configure set aws_access_key_id $AWS_FBCI_ACCESS_KEY_ID - aws configure set aws_secret_access_key $AWS_FBCI_SECRET_ACCESS_KEY - aws configure set region "us-east-2" - - aws configure set aws_profile $PROFILE + - aws configure set aws_profile $FBCI_PROFILE + - aws configure set aws_access_key_id $AWS_INFRA_ACCESS_KEY_ID --profile $INFRA_PROFILE + - aws configure set aws_secret_access_key $AWS_INFRA_SECRET_ACCESS_KEY --profile $INFRA_PROFILE - echo $AWS_FBCI_SSH_KEY > gitlab-featurebase-ci.pem - chmod 400 gitlab-featurebase-ci.pem - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' @@ -421,11 +425,15 @@ gauntlet: - echo "Cluster Prefix --> $TF_VAR_cluster_prefix" - TF_VAR_branch=$CI_COMMIT_BRANCH - echo "Branch --> $TF_VAR_branch" + - export INSTANCE_ID=$(curl --silent --fail "http://169.254.169.254/latest/meta-data/instance-id" | tee instance_id) + - aws autoscaling set-instance-protection --instance-ids "$INSTANCE_ID" --auto-scaling-group-name $ASG_NAME --protected-from-scale-in --profile $INFRA_PROFILE script: - ./qa/scripts/setupSamsungGauntlet.sh - ./qa/scripts/testSamsungGauntlet.sh after_script: - - ./qa/scripts/teardownSamsungGauntlet.sh + - ./qa/scripts/teardownSamsungGauntlet.sh || true # leaving dangling resources is better than dangling ASG instances that can't be terminated + - export INSTANCE_ID=$(cat instance_id) + - aws autoscaling set-instance-protection --instance-ids "$INSTANCE_ID" --auto-scaling-group-name $ASG_NAME --no-protected-from-scale-in --profile $INFRA_PROFILE s3 dump: stage: post build