mirror of
https://github.com/SigNoz/signoz.git
synced 2026-11-13 20:01:05 +00:00
Compare commits
3 Commits
main
...
tvats-patt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d6dffa3a9 | ||
|
|
ed87ed1b24 | ||
|
|
47c273e428 |
@@ -38,6 +38,7 @@ primary
|
||||
| comparison
|
||||
| functionCall
|
||||
| searchCall
|
||||
| patternCall
|
||||
| fullText
|
||||
| key
|
||||
| value
|
||||
@@ -121,6 +122,16 @@ searchCall
|
||||
;
|
||||
|
||||
// Function parameters can be keys, single scalar values, or arrays
|
||||
/*
|
||||
* Log pattern filter: pattern('User <*> logged in from <IP>'[, '...']) keeps the
|
||||
* logs whose pattern is one of the given pattern texts. Handled in the visitor.
|
||||
* PATTERN carries its opening parenthesis, so a bare `pattern` stays a key
|
||||
* or a full-text word.
|
||||
*/
|
||||
patternCall
|
||||
: PATTERN valueList RPAREN
|
||||
;
|
||||
|
||||
functionParamList
|
||||
: functionParam ( COMMA functionParam )*
|
||||
;
|
||||
@@ -195,6 +206,7 @@ HAS : [Hh][Aa][Ss] ;
|
||||
HASANY : [Hh][Aa][Ss][Aa][Nn][Yy] ;
|
||||
HASALL : [Hh][Aa][Ss][Aa][Ll][Ll] ;
|
||||
SEARCH : [Ss][Ee][Aa][Rr][Cc][Hh] ;
|
||||
PATTERN : [Pp][Aa][Tt][Tt][Ee][Rr][Nn] [ \t\r\n]* '(' ;
|
||||
|
||||
// Potential boolean constants
|
||||
BOOL
|
||||
|
||||
@@ -176,6 +176,8 @@ func (r *WhereClauseRewriter) VisitPrimary(ctx *parser.PrimaryContext) any {
|
||||
ctx.FunctionCall().Accept(r)
|
||||
} else if ctx.SearchCall() != nil {
|
||||
ctx.SearchCall().Accept(r)
|
||||
} else if ctx.PatternCall() != nil {
|
||||
ctx.PatternCall().Accept(r)
|
||||
} else if ctx.FullText() != nil {
|
||||
ctx.FullText().Accept(r)
|
||||
} else if ctx.Key() != nil {
|
||||
@@ -374,6 +376,13 @@ func (r *WhereClauseRewriter) VisitSearchCall(ctx *parser.SearchCallContext) any
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitPatternCall visits pattern() calls. It has no keys to rewrite, so it
|
||||
// is preserved verbatim.
|
||||
func (r *WhereClauseRewriter) VisitPatternCall(ctx *parser.PatternCallContext) any {
|
||||
r.rewritten.WriteString(ctx.GetText())
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitFunctionCall visits function calls.
|
||||
func (r *WhereClauseRewriter) VisitFunctionCall(ctx *parser.FunctionCallContext) any {
|
||||
// Write function name
|
||||
|
||||
@@ -25,6 +25,16 @@ func TestPrepareFiltersV5(t *testing.T) {
|
||||
expected: "",
|
||||
description: "Should return empty string for empty inputs",
|
||||
},
|
||||
{
|
||||
name: "pattern_call_kept",
|
||||
labels: map[string]string{},
|
||||
whereClause: "service.name = 'serviceB' AND pattern('User <*> logged in')",
|
||||
groupByItems: []qbtypes.GroupByKey{
|
||||
{TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "service.name"}},
|
||||
},
|
||||
expected: "service.name='serviceB' AND pattern('User <*> logged in')",
|
||||
description: "pattern() has no key to rewrite, so it is kept",
|
||||
},
|
||||
{
|
||||
name: "no_label_replacement",
|
||||
labels: map[string]string{},
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -25,12 +25,13 @@ HAS=24
|
||||
HASANY=25
|
||||
HASALL=26
|
||||
SEARCH=27
|
||||
BOOL=28
|
||||
NUMBER=29
|
||||
QUOTED_TEXT=30
|
||||
KEY=31
|
||||
WS=32
|
||||
FREETEXT=33
|
||||
PATTERN=28
|
||||
BOOL=29
|
||||
NUMBER=30
|
||||
QUOTED_TEXT=31
|
||||
KEY=32
|
||||
WS=33
|
||||
FREETEXT=34
|
||||
'('=1
|
||||
')'=2
|
||||
'['=3
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -25,12 +25,13 @@ HAS=24
|
||||
HASANY=25
|
||||
HASALL=26
|
||||
SEARCH=27
|
||||
BOOL=28
|
||||
NUMBER=29
|
||||
QUOTED_TEXT=30
|
||||
KEY=31
|
||||
WS=32
|
||||
FREETEXT=33
|
||||
PATTERN=28
|
||||
BOOL=29
|
||||
NUMBER=30
|
||||
QUOTED_TEXT=31
|
||||
KEY=32
|
||||
WS=33
|
||||
FREETEXT=34
|
||||
'('=1
|
||||
')'=2
|
||||
'['=3
|
||||
|
||||
@@ -99,6 +99,12 @@ func (s *BaseFilterQueryListener) EnterSearchCall(ctx *SearchCallContext) {}
|
||||
// ExitSearchCall is called when production searchCall is exited.
|
||||
func (s *BaseFilterQueryListener) ExitSearchCall(ctx *SearchCallContext) {}
|
||||
|
||||
// EnterPatternCall is called when production patternCall is entered.
|
||||
func (s *BaseFilterQueryListener) EnterPatternCall(ctx *PatternCallContext) {}
|
||||
|
||||
// ExitPatternCall is called when production patternCall is exited.
|
||||
func (s *BaseFilterQueryListener) ExitPatternCall(ctx *PatternCallContext) {}
|
||||
|
||||
// EnterFunctionParamList is called when production functionParamList is entered.
|
||||
func (s *BaseFilterQueryListener) EnterFunctionParamList(ctx *FunctionParamListContext) {}
|
||||
|
||||
|
||||
@@ -60,6 +60,10 @@ func (v *BaseFilterQueryVisitor) VisitSearchCall(ctx *SearchCallContext) interfa
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseFilterQueryVisitor) VisitPatternCall(ctx *PatternCallContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseFilterQueryVisitor) VisitFunctionParamList(ctx *FunctionParamListContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
@@ -50,174 +50,184 @@ func filterquerylexerLexerInit() {
|
||||
"", "LPAREN", "RPAREN", "LBRACK", "RBRACK", "COMMA", "EQUALS", "NOT_EQUALS",
|
||||
"NEQ", "LT", "LE", "GT", "GE", "LIKE", "ILIKE", "BETWEEN", "EXISTS",
|
||||
"REGEXP", "CONTAINS", "IN", "NOT", "AND", "OR", "HASTOKEN", "HAS", "HASANY",
|
||||
"HASALL", "SEARCH", "BOOL", "NUMBER", "QUOTED_TEXT", "KEY", "WS", "FREETEXT",
|
||||
"HASALL", "SEARCH", "PATTERN", "BOOL", "NUMBER", "QUOTED_TEXT", "KEY",
|
||||
"WS", "FREETEXT",
|
||||
}
|
||||
staticData.RuleNames = []string{
|
||||
"LPAREN", "RPAREN", "LBRACK", "RBRACK", "COMMA", "EQUALS", "NOT_EQUALS",
|
||||
"NEQ", "LT", "LE", "GT", "GE", "LIKE", "ILIKE", "BETWEEN", "EXISTS",
|
||||
"REGEXP", "CONTAINS", "IN", "NOT", "AND", "OR", "HASTOKEN", "HAS", "HASANY",
|
||||
"HASALL", "SEARCH", "BOOL", "SIGN", "NUMBER", "QUOTED_TEXT", "SEGMENT",
|
||||
"EMPTY_BRACKS", "OLD_JSON_BRACKS", "KEY", "WS", "DIGIT", "FREETEXT",
|
||||
"HASALL", "SEARCH", "PATTERN", "BOOL", "SIGN", "NUMBER", "QUOTED_TEXT",
|
||||
"SEGMENT", "EMPTY_BRACKS", "OLD_JSON_BRACKS", "KEY", "WS", "DIGIT",
|
||||
"FREETEXT",
|
||||
}
|
||||
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
|
||||
staticData.serializedATN = []int32{
|
||||
4, 0, 33, 329, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2,
|
||||
4, 0, 34, 346, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2,
|
||||
4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2,
|
||||
10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15,
|
||||
7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7,
|
||||
20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25,
|
||||
2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2,
|
||||
31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36,
|
||||
7, 36, 2, 37, 7, 37, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1,
|
||||
4, 1, 4, 1, 5, 1, 5, 1, 5, 3, 5, 91, 8, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7,
|
||||
1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11,
|
||||
1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1,
|
||||
13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15,
|
||||
1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 134, 8, 15, 1, 16, 1, 16, 1, 16, 1,
|
||||
16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17,
|
||||
1, 17, 3, 17, 151, 8, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1,
|
||||
19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22,
|
||||
1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1,
|
||||
24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25,
|
||||
1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1,
|
||||
27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 3, 27, 210,
|
||||
8, 27, 1, 28, 1, 28, 1, 29, 3, 29, 215, 8, 29, 1, 29, 4, 29, 218, 8, 29,
|
||||
11, 29, 12, 29, 219, 1, 29, 1, 29, 5, 29, 224, 8, 29, 10, 29, 12, 29, 227,
|
||||
9, 29, 3, 29, 229, 8, 29, 1, 29, 1, 29, 3, 29, 233, 8, 29, 1, 29, 4, 29,
|
||||
236, 8, 29, 11, 29, 12, 29, 237, 3, 29, 240, 8, 29, 1, 29, 3, 29, 243,
|
||||
8, 29, 1, 29, 1, 29, 4, 29, 247, 8, 29, 11, 29, 12, 29, 248, 1, 29, 1,
|
||||
29, 3, 29, 253, 8, 29, 1, 29, 4, 29, 256, 8, 29, 11, 29, 12, 29, 257, 3,
|
||||
29, 260, 8, 29, 3, 29, 262, 8, 29, 1, 30, 1, 30, 1, 30, 1, 30, 5, 30, 268,
|
||||
8, 30, 10, 30, 12, 30, 271, 9, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 5,
|
||||
30, 278, 8, 30, 10, 30, 12, 30, 281, 9, 30, 1, 30, 3, 30, 284, 8, 30, 1,
|
||||
31, 1, 31, 5, 31, 288, 8, 31, 10, 31, 12, 31, 291, 9, 31, 1, 32, 1, 32,
|
||||
1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1,
|
||||
34, 1, 34, 4, 34, 307, 8, 34, 11, 34, 12, 34, 308, 5, 34, 311, 8, 34, 10,
|
||||
34, 12, 34, 314, 9, 34, 1, 35, 4, 35, 317, 8, 35, 11, 35, 12, 35, 318,
|
||||
1, 35, 1, 35, 1, 36, 1, 36, 1, 37, 4, 37, 326, 8, 37, 11, 37, 12, 37, 327,
|
||||
0, 0, 38, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19,
|
||||
10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37,
|
||||
19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55,
|
||||
28, 57, 0, 59, 29, 61, 30, 63, 0, 65, 0, 67, 0, 69, 31, 71, 32, 73, 0,
|
||||
75, 33, 1, 0, 29, 2, 0, 76, 76, 108, 108, 2, 0, 73, 73, 105, 105, 2, 0,
|
||||
75, 75, 107, 107, 2, 0, 69, 69, 101, 101, 2, 0, 66, 66, 98, 98, 2, 0, 84,
|
||||
84, 116, 116, 2, 0, 87, 87, 119, 119, 2, 0, 78, 78, 110, 110, 2, 0, 88,
|
||||
88, 120, 120, 2, 0, 83, 83, 115, 115, 2, 0, 82, 82, 114, 114, 2, 0, 71,
|
||||
71, 103, 103, 2, 0, 80, 80, 112, 112, 2, 0, 67, 67, 99, 99, 2, 0, 79, 79,
|
||||
111, 111, 2, 0, 65, 65, 97, 97, 2, 0, 68, 68, 100, 100, 2, 0, 72, 72, 104,
|
||||
104, 2, 0, 89, 89, 121, 121, 2, 0, 85, 85, 117, 117, 2, 0, 70, 70, 102,
|
||||
102, 2, 0, 43, 43, 45, 45, 2, 0, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92,
|
||||
4, 0, 35, 36, 64, 90, 95, 95, 97, 123, 7, 0, 35, 36, 45, 45, 47, 58, 64,
|
||||
90, 95, 95, 97, 123, 125, 125, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57,
|
||||
8, 0, 9, 10, 13, 13, 32, 34, 39, 41, 44, 44, 60, 62, 91, 91, 93, 93, 353,
|
||||
0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0,
|
||||
0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0,
|
||||
0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0,
|
||||
0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1,
|
||||
0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39,
|
||||
1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0,
|
||||
47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0,
|
||||
0, 55, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 69, 1, 0, 0,
|
||||
0, 0, 71, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 1, 77, 1, 0, 0, 0, 3, 79, 1, 0,
|
||||
0, 0, 5, 81, 1, 0, 0, 0, 7, 83, 1, 0, 0, 0, 9, 85, 1, 0, 0, 0, 11, 90,
|
||||
1, 0, 0, 0, 13, 92, 1, 0, 0, 0, 15, 95, 1, 0, 0, 0, 17, 98, 1, 0, 0, 0,
|
||||
19, 100, 1, 0, 0, 0, 21, 103, 1, 0, 0, 0, 23, 105, 1, 0, 0, 0, 25, 108,
|
||||
1, 0, 0, 0, 27, 113, 1, 0, 0, 0, 29, 119, 1, 0, 0, 0, 31, 127, 1, 0, 0,
|
||||
0, 33, 135, 1, 0, 0, 0, 35, 142, 1, 0, 0, 0, 37, 152, 1, 0, 0, 0, 39, 155,
|
||||
1, 0, 0, 0, 41, 159, 1, 0, 0, 0, 43, 163, 1, 0, 0, 0, 45, 166, 1, 0, 0,
|
||||
0, 47, 175, 1, 0, 0, 0, 49, 179, 1, 0, 0, 0, 51, 186, 1, 0, 0, 0, 53, 193,
|
||||
1, 0, 0, 0, 55, 209, 1, 0, 0, 0, 57, 211, 1, 0, 0, 0, 59, 261, 1, 0, 0,
|
||||
0, 61, 283, 1, 0, 0, 0, 63, 285, 1, 0, 0, 0, 65, 292, 1, 0, 0, 0, 67, 295,
|
||||
1, 0, 0, 0, 69, 299, 1, 0, 0, 0, 71, 316, 1, 0, 0, 0, 73, 322, 1, 0, 0,
|
||||
0, 75, 325, 1, 0, 0, 0, 77, 78, 5, 40, 0, 0, 78, 2, 1, 0, 0, 0, 79, 80,
|
||||
5, 41, 0, 0, 80, 4, 1, 0, 0, 0, 81, 82, 5, 91, 0, 0, 82, 6, 1, 0, 0, 0,
|
||||
83, 84, 5, 93, 0, 0, 84, 8, 1, 0, 0, 0, 85, 86, 5, 44, 0, 0, 86, 10, 1,
|
||||
0, 0, 0, 87, 91, 5, 61, 0, 0, 88, 89, 5, 61, 0, 0, 89, 91, 5, 61, 0, 0,
|
||||
90, 87, 1, 0, 0, 0, 90, 88, 1, 0, 0, 0, 91, 12, 1, 0, 0, 0, 92, 93, 5,
|
||||
33, 0, 0, 93, 94, 5, 61, 0, 0, 94, 14, 1, 0, 0, 0, 95, 96, 5, 60, 0, 0,
|
||||
96, 97, 5, 62, 0, 0, 97, 16, 1, 0, 0, 0, 98, 99, 5, 60, 0, 0, 99, 18, 1,
|
||||
0, 0, 0, 100, 101, 5, 60, 0, 0, 101, 102, 5, 61, 0, 0, 102, 20, 1, 0, 0,
|
||||
0, 103, 104, 5, 62, 0, 0, 104, 22, 1, 0, 0, 0, 105, 106, 5, 62, 0, 0, 106,
|
||||
107, 5, 61, 0, 0, 107, 24, 1, 0, 0, 0, 108, 109, 7, 0, 0, 0, 109, 110,
|
||||
7, 1, 0, 0, 110, 111, 7, 2, 0, 0, 111, 112, 7, 3, 0, 0, 112, 26, 1, 0,
|
||||
0, 0, 113, 114, 7, 1, 0, 0, 114, 115, 7, 0, 0, 0, 115, 116, 7, 1, 0, 0,
|
||||
116, 117, 7, 2, 0, 0, 117, 118, 7, 3, 0, 0, 118, 28, 1, 0, 0, 0, 119, 120,
|
||||
7, 4, 0, 0, 120, 121, 7, 3, 0, 0, 121, 122, 7, 5, 0, 0, 122, 123, 7, 6,
|
||||
0, 0, 123, 124, 7, 3, 0, 0, 124, 125, 7, 3, 0, 0, 125, 126, 7, 7, 0, 0,
|
||||
126, 30, 1, 0, 0, 0, 127, 128, 7, 3, 0, 0, 128, 129, 7, 8, 0, 0, 129, 130,
|
||||
7, 1, 0, 0, 130, 131, 7, 9, 0, 0, 131, 133, 7, 5, 0, 0, 132, 134, 7, 9,
|
||||
0, 0, 133, 132, 1, 0, 0, 0, 133, 134, 1, 0, 0, 0, 134, 32, 1, 0, 0, 0,
|
||||
135, 136, 7, 10, 0, 0, 136, 137, 7, 3, 0, 0, 137, 138, 7, 11, 0, 0, 138,
|
||||
139, 7, 3, 0, 0, 139, 140, 7, 8, 0, 0, 140, 141, 7, 12, 0, 0, 141, 34,
|
||||
1, 0, 0, 0, 142, 143, 7, 13, 0, 0, 143, 144, 7, 14, 0, 0, 144, 145, 7,
|
||||
7, 0, 0, 145, 146, 7, 5, 0, 0, 146, 147, 7, 15, 0, 0, 147, 148, 7, 1, 0,
|
||||
0, 148, 150, 7, 7, 0, 0, 149, 151, 7, 9, 0, 0, 150, 149, 1, 0, 0, 0, 150,
|
||||
151, 1, 0, 0, 0, 151, 36, 1, 0, 0, 0, 152, 153, 7, 1, 0, 0, 153, 154, 7,
|
||||
7, 0, 0, 154, 38, 1, 0, 0, 0, 155, 156, 7, 7, 0, 0, 156, 157, 7, 14, 0,
|
||||
0, 157, 158, 7, 5, 0, 0, 158, 40, 1, 0, 0, 0, 159, 160, 7, 15, 0, 0, 160,
|
||||
161, 7, 7, 0, 0, 161, 162, 7, 16, 0, 0, 162, 42, 1, 0, 0, 0, 163, 164,
|
||||
7, 14, 0, 0, 164, 165, 7, 10, 0, 0, 165, 44, 1, 0, 0, 0, 166, 167, 7, 17,
|
||||
0, 0, 167, 168, 7, 15, 0, 0, 168, 169, 7, 9, 0, 0, 169, 170, 7, 5, 0, 0,
|
||||
170, 171, 7, 14, 0, 0, 171, 172, 7, 2, 0, 0, 172, 173, 7, 3, 0, 0, 173,
|
||||
174, 7, 7, 0, 0, 174, 46, 1, 0, 0, 0, 175, 176, 7, 17, 0, 0, 176, 177,
|
||||
7, 15, 0, 0, 177, 178, 7, 9, 0, 0, 178, 48, 1, 0, 0, 0, 179, 180, 7, 17,
|
||||
0, 0, 180, 181, 7, 15, 0, 0, 181, 182, 7, 9, 0, 0, 182, 183, 7, 15, 0,
|
||||
0, 183, 184, 7, 7, 0, 0, 184, 185, 7, 18, 0, 0, 185, 50, 1, 0, 0, 0, 186,
|
||||
187, 7, 17, 0, 0, 187, 188, 7, 15, 0, 0, 188, 189, 7, 9, 0, 0, 189, 190,
|
||||
7, 15, 0, 0, 190, 191, 7, 0, 0, 0, 191, 192, 7, 0, 0, 0, 192, 52, 1, 0,
|
||||
0, 0, 193, 194, 7, 9, 0, 0, 194, 195, 7, 3, 0, 0, 195, 196, 7, 15, 0, 0,
|
||||
196, 197, 7, 10, 0, 0, 197, 198, 7, 13, 0, 0, 198, 199, 7, 17, 0, 0, 199,
|
||||
54, 1, 0, 0, 0, 200, 201, 7, 5, 0, 0, 201, 202, 7, 10, 0, 0, 202, 203,
|
||||
7, 19, 0, 0, 203, 210, 7, 3, 0, 0, 204, 205, 7, 20, 0, 0, 205, 206, 7,
|
||||
15, 0, 0, 206, 207, 7, 0, 0, 0, 207, 208, 7, 9, 0, 0, 208, 210, 7, 3, 0,
|
||||
0, 209, 200, 1, 0, 0, 0, 209, 204, 1, 0, 0, 0, 210, 56, 1, 0, 0, 0, 211,
|
||||
212, 7, 21, 0, 0, 212, 58, 1, 0, 0, 0, 213, 215, 3, 57, 28, 0, 214, 213,
|
||||
1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 217, 1, 0, 0, 0, 216, 218, 3, 73,
|
||||
36, 0, 217, 216, 1, 0, 0, 0, 218, 219, 1, 0, 0, 0, 219, 217, 1, 0, 0, 0,
|
||||
219, 220, 1, 0, 0, 0, 220, 228, 1, 0, 0, 0, 221, 225, 5, 46, 0, 0, 222,
|
||||
224, 3, 73, 36, 0, 223, 222, 1, 0, 0, 0, 224, 227, 1, 0, 0, 0, 225, 223,
|
||||
1, 0, 0, 0, 225, 226, 1, 0, 0, 0, 226, 229, 1, 0, 0, 0, 227, 225, 1, 0,
|
||||
0, 0, 228, 221, 1, 0, 0, 0, 228, 229, 1, 0, 0, 0, 229, 239, 1, 0, 0, 0,
|
||||
230, 232, 7, 3, 0, 0, 231, 233, 3, 57, 28, 0, 232, 231, 1, 0, 0, 0, 232,
|
||||
233, 1, 0, 0, 0, 233, 235, 1, 0, 0, 0, 234, 236, 3, 73, 36, 0, 235, 234,
|
||||
1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 238, 1, 0,
|
||||
0, 0, 238, 240, 1, 0, 0, 0, 239, 230, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0,
|
||||
240, 262, 1, 0, 0, 0, 241, 243, 3, 57, 28, 0, 242, 241, 1, 0, 0, 0, 242,
|
||||
243, 1, 0, 0, 0, 243, 244, 1, 0, 0, 0, 244, 246, 5, 46, 0, 0, 245, 247,
|
||||
3, 73, 36, 0, 246, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 246, 1,
|
||||
0, 0, 0, 248, 249, 1, 0, 0, 0, 249, 259, 1, 0, 0, 0, 250, 252, 7, 3, 0,
|
||||
0, 251, 253, 3, 57, 28, 0, 252, 251, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0,
|
||||
253, 255, 1, 0, 0, 0, 254, 256, 3, 73, 36, 0, 255, 254, 1, 0, 0, 0, 256,
|
||||
257, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 260,
|
||||
1, 0, 0, 0, 259, 250, 1, 0, 0, 0, 259, 260, 1, 0, 0, 0, 260, 262, 1, 0,
|
||||
0, 0, 261, 214, 1, 0, 0, 0, 261, 242, 1, 0, 0, 0, 262, 60, 1, 0, 0, 0,
|
||||
263, 269, 5, 34, 0, 0, 264, 268, 8, 22, 0, 0, 265, 266, 5, 92, 0, 0, 266,
|
||||
268, 9, 0, 0, 0, 267, 264, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 268, 271,
|
||||
1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 272, 1, 0,
|
||||
0, 0, 271, 269, 1, 0, 0, 0, 272, 284, 5, 34, 0, 0, 273, 279, 5, 39, 0,
|
||||
0, 274, 278, 8, 23, 0, 0, 275, 276, 5, 92, 0, 0, 276, 278, 9, 0, 0, 0,
|
||||
277, 274, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 278, 281, 1, 0, 0, 0, 279,
|
||||
277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 282, 1, 0, 0, 0, 281, 279,
|
||||
1, 0, 0, 0, 282, 284, 5, 39, 0, 0, 283, 263, 1, 0, 0, 0, 283, 273, 1, 0,
|
||||
0, 0, 284, 62, 1, 0, 0, 0, 285, 289, 7, 24, 0, 0, 286, 288, 7, 25, 0, 0,
|
||||
287, 286, 1, 0, 0, 0, 288, 291, 1, 0, 0, 0, 289, 287, 1, 0, 0, 0, 289,
|
||||
290, 1, 0, 0, 0, 290, 64, 1, 0, 0, 0, 291, 289, 1, 0, 0, 0, 292, 293, 5,
|
||||
91, 0, 0, 293, 294, 5, 93, 0, 0, 294, 66, 1, 0, 0, 0, 295, 296, 5, 91,
|
||||
0, 0, 296, 297, 5, 42, 0, 0, 297, 298, 5, 93, 0, 0, 298, 68, 1, 0, 0, 0,
|
||||
299, 312, 3, 63, 31, 0, 300, 301, 5, 46, 0, 0, 301, 311, 3, 63, 31, 0,
|
||||
302, 311, 3, 65, 32, 0, 303, 311, 3, 67, 33, 0, 304, 306, 5, 46, 0, 0,
|
||||
305, 307, 3, 73, 36, 0, 306, 305, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308,
|
||||
306, 1, 0, 0, 0, 308, 309, 1, 0, 0, 0, 309, 311, 1, 0, 0, 0, 310, 300,
|
||||
1, 0, 0, 0, 310, 302, 1, 0, 0, 0, 310, 303, 1, 0, 0, 0, 310, 304, 1, 0,
|
||||
0, 0, 311, 314, 1, 0, 0, 0, 312, 310, 1, 0, 0, 0, 312, 313, 1, 0, 0, 0,
|
||||
313, 70, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 315, 317, 7, 26, 0, 0, 316,
|
||||
315, 1, 0, 0, 0, 317, 318, 1, 0, 0, 0, 318, 316, 1, 0, 0, 0, 318, 319,
|
||||
1, 0, 0, 0, 319, 320, 1, 0, 0, 0, 320, 321, 6, 35, 0, 0, 321, 72, 1, 0,
|
||||
0, 0, 322, 323, 7, 27, 0, 0, 323, 74, 1, 0, 0, 0, 324, 326, 8, 28, 0, 0,
|
||||
325, 324, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 325, 1, 0, 0, 0, 327,
|
||||
328, 1, 0, 0, 0, 328, 76, 1, 0, 0, 0, 29, 0, 90, 133, 150, 209, 214, 219,
|
||||
225, 228, 232, 237, 239, 242, 248, 252, 257, 259, 261, 267, 269, 277, 279,
|
||||
283, 289, 308, 310, 312, 318, 327, 1, 6, 0, 0,
|
||||
7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2,
|
||||
1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 3, 5, 93, 8, 5, 1, 6, 1, 6, 1,
|
||||
6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11,
|
||||
1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1,
|
||||
13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14,
|
||||
1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 136, 8, 15, 1, 16, 1,
|
||||
16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17,
|
||||
1, 17, 1, 17, 1, 17, 3, 17, 153, 8, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1,
|
||||
19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 22,
|
||||
1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1,
|
||||
23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25,
|
||||
1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1,
|
||||
26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 5, 27,
|
||||
211, 8, 27, 10, 27, 12, 27, 214, 9, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1,
|
||||
28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 3, 28, 227, 8, 28, 1, 29,
|
||||
1, 29, 1, 30, 3, 30, 232, 8, 30, 1, 30, 4, 30, 235, 8, 30, 11, 30, 12,
|
||||
30, 236, 1, 30, 1, 30, 5, 30, 241, 8, 30, 10, 30, 12, 30, 244, 9, 30, 3,
|
||||
30, 246, 8, 30, 1, 30, 1, 30, 3, 30, 250, 8, 30, 1, 30, 4, 30, 253, 8,
|
||||
30, 11, 30, 12, 30, 254, 3, 30, 257, 8, 30, 1, 30, 3, 30, 260, 8, 30, 1,
|
||||
30, 1, 30, 4, 30, 264, 8, 30, 11, 30, 12, 30, 265, 1, 30, 1, 30, 3, 30,
|
||||
270, 8, 30, 1, 30, 4, 30, 273, 8, 30, 11, 30, 12, 30, 274, 3, 30, 277,
|
||||
8, 30, 3, 30, 279, 8, 30, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 285, 8, 31,
|
||||
10, 31, 12, 31, 288, 9, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 295,
|
||||
8, 31, 10, 31, 12, 31, 298, 9, 31, 1, 31, 3, 31, 301, 8, 31, 1, 32, 1,
|
||||
32, 5, 32, 305, 8, 32, 10, 32, 12, 32, 308, 9, 32, 1, 33, 1, 33, 1, 33,
|
||||
1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1,
|
||||
35, 4, 35, 324, 8, 35, 11, 35, 12, 35, 325, 5, 35, 328, 8, 35, 10, 35,
|
||||
12, 35, 331, 9, 35, 1, 36, 4, 36, 334, 8, 36, 11, 36, 12, 36, 335, 1, 36,
|
||||
1, 36, 1, 37, 1, 37, 1, 38, 4, 38, 343, 8, 38, 11, 38, 12, 38, 344, 0,
|
||||
0, 39, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10,
|
||||
21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19,
|
||||
39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28,
|
||||
57, 29, 59, 0, 61, 30, 63, 31, 65, 0, 67, 0, 69, 0, 71, 32, 73, 33, 75,
|
||||
0, 77, 34, 1, 0, 29, 2, 0, 76, 76, 108, 108, 2, 0, 73, 73, 105, 105, 2,
|
||||
0, 75, 75, 107, 107, 2, 0, 69, 69, 101, 101, 2, 0, 66, 66, 98, 98, 2, 0,
|
||||
84, 84, 116, 116, 2, 0, 87, 87, 119, 119, 2, 0, 78, 78, 110, 110, 2, 0,
|
||||
88, 88, 120, 120, 2, 0, 83, 83, 115, 115, 2, 0, 82, 82, 114, 114, 2, 0,
|
||||
71, 71, 103, 103, 2, 0, 80, 80, 112, 112, 2, 0, 67, 67, 99, 99, 2, 0, 79,
|
||||
79, 111, 111, 2, 0, 65, 65, 97, 97, 2, 0, 68, 68, 100, 100, 2, 0, 72, 72,
|
||||
104, 104, 2, 0, 89, 89, 121, 121, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 85,
|
||||
85, 117, 117, 2, 0, 70, 70, 102, 102, 2, 0, 43, 43, 45, 45, 2, 0, 34, 34,
|
||||
92, 92, 2, 0, 39, 39, 92, 92, 4, 0, 35, 36, 64, 90, 95, 95, 97, 123, 7,
|
||||
0, 35, 36, 45, 45, 47, 58, 64, 90, 95, 95, 97, 123, 125, 125, 1, 0, 48,
|
||||
57, 8, 0, 9, 10, 13, 13, 32, 34, 39, 41, 44, 44, 60, 62, 91, 91, 93, 93,
|
||||
371, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0,
|
||||
0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1,
|
||||
0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23,
|
||||
1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0,
|
||||
31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0,
|
||||
0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0,
|
||||
0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0,
|
||||
0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1,
|
||||
0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 1, 79,
|
||||
1, 0, 0, 0, 3, 81, 1, 0, 0, 0, 5, 83, 1, 0, 0, 0, 7, 85, 1, 0, 0, 0, 9,
|
||||
87, 1, 0, 0, 0, 11, 92, 1, 0, 0, 0, 13, 94, 1, 0, 0, 0, 15, 97, 1, 0, 0,
|
||||
0, 17, 100, 1, 0, 0, 0, 19, 102, 1, 0, 0, 0, 21, 105, 1, 0, 0, 0, 23, 107,
|
||||
1, 0, 0, 0, 25, 110, 1, 0, 0, 0, 27, 115, 1, 0, 0, 0, 29, 121, 1, 0, 0,
|
||||
0, 31, 129, 1, 0, 0, 0, 33, 137, 1, 0, 0, 0, 35, 144, 1, 0, 0, 0, 37, 154,
|
||||
1, 0, 0, 0, 39, 157, 1, 0, 0, 0, 41, 161, 1, 0, 0, 0, 43, 165, 1, 0, 0,
|
||||
0, 45, 168, 1, 0, 0, 0, 47, 177, 1, 0, 0, 0, 49, 181, 1, 0, 0, 0, 51, 188,
|
||||
1, 0, 0, 0, 53, 195, 1, 0, 0, 0, 55, 202, 1, 0, 0, 0, 57, 226, 1, 0, 0,
|
||||
0, 59, 228, 1, 0, 0, 0, 61, 278, 1, 0, 0, 0, 63, 300, 1, 0, 0, 0, 65, 302,
|
||||
1, 0, 0, 0, 67, 309, 1, 0, 0, 0, 69, 312, 1, 0, 0, 0, 71, 316, 1, 0, 0,
|
||||
0, 73, 333, 1, 0, 0, 0, 75, 339, 1, 0, 0, 0, 77, 342, 1, 0, 0, 0, 79, 80,
|
||||
5, 40, 0, 0, 80, 2, 1, 0, 0, 0, 81, 82, 5, 41, 0, 0, 82, 4, 1, 0, 0, 0,
|
||||
83, 84, 5, 91, 0, 0, 84, 6, 1, 0, 0, 0, 85, 86, 5, 93, 0, 0, 86, 8, 1,
|
||||
0, 0, 0, 87, 88, 5, 44, 0, 0, 88, 10, 1, 0, 0, 0, 89, 93, 5, 61, 0, 0,
|
||||
90, 91, 5, 61, 0, 0, 91, 93, 5, 61, 0, 0, 92, 89, 1, 0, 0, 0, 92, 90, 1,
|
||||
0, 0, 0, 93, 12, 1, 0, 0, 0, 94, 95, 5, 33, 0, 0, 95, 96, 5, 61, 0, 0,
|
||||
96, 14, 1, 0, 0, 0, 97, 98, 5, 60, 0, 0, 98, 99, 5, 62, 0, 0, 99, 16, 1,
|
||||
0, 0, 0, 100, 101, 5, 60, 0, 0, 101, 18, 1, 0, 0, 0, 102, 103, 5, 60, 0,
|
||||
0, 103, 104, 5, 61, 0, 0, 104, 20, 1, 0, 0, 0, 105, 106, 5, 62, 0, 0, 106,
|
||||
22, 1, 0, 0, 0, 107, 108, 5, 62, 0, 0, 108, 109, 5, 61, 0, 0, 109, 24,
|
||||
1, 0, 0, 0, 110, 111, 7, 0, 0, 0, 111, 112, 7, 1, 0, 0, 112, 113, 7, 2,
|
||||
0, 0, 113, 114, 7, 3, 0, 0, 114, 26, 1, 0, 0, 0, 115, 116, 7, 1, 0, 0,
|
||||
116, 117, 7, 0, 0, 0, 117, 118, 7, 1, 0, 0, 118, 119, 7, 2, 0, 0, 119,
|
||||
120, 7, 3, 0, 0, 120, 28, 1, 0, 0, 0, 121, 122, 7, 4, 0, 0, 122, 123, 7,
|
||||
3, 0, 0, 123, 124, 7, 5, 0, 0, 124, 125, 7, 6, 0, 0, 125, 126, 7, 3, 0,
|
||||
0, 126, 127, 7, 3, 0, 0, 127, 128, 7, 7, 0, 0, 128, 30, 1, 0, 0, 0, 129,
|
||||
130, 7, 3, 0, 0, 130, 131, 7, 8, 0, 0, 131, 132, 7, 1, 0, 0, 132, 133,
|
||||
7, 9, 0, 0, 133, 135, 7, 5, 0, 0, 134, 136, 7, 9, 0, 0, 135, 134, 1, 0,
|
||||
0, 0, 135, 136, 1, 0, 0, 0, 136, 32, 1, 0, 0, 0, 137, 138, 7, 10, 0, 0,
|
||||
138, 139, 7, 3, 0, 0, 139, 140, 7, 11, 0, 0, 140, 141, 7, 3, 0, 0, 141,
|
||||
142, 7, 8, 0, 0, 142, 143, 7, 12, 0, 0, 143, 34, 1, 0, 0, 0, 144, 145,
|
||||
7, 13, 0, 0, 145, 146, 7, 14, 0, 0, 146, 147, 7, 7, 0, 0, 147, 148, 7,
|
||||
5, 0, 0, 148, 149, 7, 15, 0, 0, 149, 150, 7, 1, 0, 0, 150, 152, 7, 7, 0,
|
||||
0, 151, 153, 7, 9, 0, 0, 152, 151, 1, 0, 0, 0, 152, 153, 1, 0, 0, 0, 153,
|
||||
36, 1, 0, 0, 0, 154, 155, 7, 1, 0, 0, 155, 156, 7, 7, 0, 0, 156, 38, 1,
|
||||
0, 0, 0, 157, 158, 7, 7, 0, 0, 158, 159, 7, 14, 0, 0, 159, 160, 7, 5, 0,
|
||||
0, 160, 40, 1, 0, 0, 0, 161, 162, 7, 15, 0, 0, 162, 163, 7, 7, 0, 0, 163,
|
||||
164, 7, 16, 0, 0, 164, 42, 1, 0, 0, 0, 165, 166, 7, 14, 0, 0, 166, 167,
|
||||
7, 10, 0, 0, 167, 44, 1, 0, 0, 0, 168, 169, 7, 17, 0, 0, 169, 170, 7, 15,
|
||||
0, 0, 170, 171, 7, 9, 0, 0, 171, 172, 7, 5, 0, 0, 172, 173, 7, 14, 0, 0,
|
||||
173, 174, 7, 2, 0, 0, 174, 175, 7, 3, 0, 0, 175, 176, 7, 7, 0, 0, 176,
|
||||
46, 1, 0, 0, 0, 177, 178, 7, 17, 0, 0, 178, 179, 7, 15, 0, 0, 179, 180,
|
||||
7, 9, 0, 0, 180, 48, 1, 0, 0, 0, 181, 182, 7, 17, 0, 0, 182, 183, 7, 15,
|
||||
0, 0, 183, 184, 7, 9, 0, 0, 184, 185, 7, 15, 0, 0, 185, 186, 7, 7, 0, 0,
|
||||
186, 187, 7, 18, 0, 0, 187, 50, 1, 0, 0, 0, 188, 189, 7, 17, 0, 0, 189,
|
||||
190, 7, 15, 0, 0, 190, 191, 7, 9, 0, 0, 191, 192, 7, 15, 0, 0, 192, 193,
|
||||
7, 0, 0, 0, 193, 194, 7, 0, 0, 0, 194, 52, 1, 0, 0, 0, 195, 196, 7, 9,
|
||||
0, 0, 196, 197, 7, 3, 0, 0, 197, 198, 7, 15, 0, 0, 198, 199, 7, 10, 0,
|
||||
0, 199, 200, 7, 13, 0, 0, 200, 201, 7, 17, 0, 0, 201, 54, 1, 0, 0, 0, 202,
|
||||
203, 7, 12, 0, 0, 203, 204, 7, 15, 0, 0, 204, 205, 7, 5, 0, 0, 205, 206,
|
||||
7, 5, 0, 0, 206, 207, 7, 3, 0, 0, 207, 208, 7, 10, 0, 0, 208, 212, 7, 7,
|
||||
0, 0, 209, 211, 7, 19, 0, 0, 210, 209, 1, 0, 0, 0, 211, 214, 1, 0, 0, 0,
|
||||
212, 210, 1, 0, 0, 0, 212, 213, 1, 0, 0, 0, 213, 215, 1, 0, 0, 0, 214,
|
||||
212, 1, 0, 0, 0, 215, 216, 5, 40, 0, 0, 216, 56, 1, 0, 0, 0, 217, 218,
|
||||
7, 5, 0, 0, 218, 219, 7, 10, 0, 0, 219, 220, 7, 20, 0, 0, 220, 227, 7,
|
||||
3, 0, 0, 221, 222, 7, 21, 0, 0, 222, 223, 7, 15, 0, 0, 223, 224, 7, 0,
|
||||
0, 0, 224, 225, 7, 9, 0, 0, 225, 227, 7, 3, 0, 0, 226, 217, 1, 0, 0, 0,
|
||||
226, 221, 1, 0, 0, 0, 227, 58, 1, 0, 0, 0, 228, 229, 7, 22, 0, 0, 229,
|
||||
60, 1, 0, 0, 0, 230, 232, 3, 59, 29, 0, 231, 230, 1, 0, 0, 0, 231, 232,
|
||||
1, 0, 0, 0, 232, 234, 1, 0, 0, 0, 233, 235, 3, 75, 37, 0, 234, 233, 1,
|
||||
0, 0, 0, 235, 236, 1, 0, 0, 0, 236, 234, 1, 0, 0, 0, 236, 237, 1, 0, 0,
|
||||
0, 237, 245, 1, 0, 0, 0, 238, 242, 5, 46, 0, 0, 239, 241, 3, 75, 37, 0,
|
||||
240, 239, 1, 0, 0, 0, 241, 244, 1, 0, 0, 0, 242, 240, 1, 0, 0, 0, 242,
|
||||
243, 1, 0, 0, 0, 243, 246, 1, 0, 0, 0, 244, 242, 1, 0, 0, 0, 245, 238,
|
||||
1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 246, 256, 1, 0, 0, 0, 247, 249, 7, 3,
|
||||
0, 0, 248, 250, 3, 59, 29, 0, 249, 248, 1, 0, 0, 0, 249, 250, 1, 0, 0,
|
||||
0, 250, 252, 1, 0, 0, 0, 251, 253, 3, 75, 37, 0, 252, 251, 1, 0, 0, 0,
|
||||
253, 254, 1, 0, 0, 0, 254, 252, 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255,
|
||||
257, 1, 0, 0, 0, 256, 247, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 279,
|
||||
1, 0, 0, 0, 258, 260, 3, 59, 29, 0, 259, 258, 1, 0, 0, 0, 259, 260, 1,
|
||||
0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 263, 5, 46, 0, 0, 262, 264, 3, 75,
|
||||
37, 0, 263, 262, 1, 0, 0, 0, 264, 265, 1, 0, 0, 0, 265, 263, 1, 0, 0, 0,
|
||||
265, 266, 1, 0, 0, 0, 266, 276, 1, 0, 0, 0, 267, 269, 7, 3, 0, 0, 268,
|
||||
270, 3, 59, 29, 0, 269, 268, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 272,
|
||||
1, 0, 0, 0, 271, 273, 3, 75, 37, 0, 272, 271, 1, 0, 0, 0, 273, 274, 1,
|
||||
0, 0, 0, 274, 272, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 277, 1, 0, 0,
|
||||
0, 276, 267, 1, 0, 0, 0, 276, 277, 1, 0, 0, 0, 277, 279, 1, 0, 0, 0, 278,
|
||||
231, 1, 0, 0, 0, 278, 259, 1, 0, 0, 0, 279, 62, 1, 0, 0, 0, 280, 286, 5,
|
||||
34, 0, 0, 281, 285, 8, 23, 0, 0, 282, 283, 5, 92, 0, 0, 283, 285, 9, 0,
|
||||
0, 0, 284, 281, 1, 0, 0, 0, 284, 282, 1, 0, 0, 0, 285, 288, 1, 0, 0, 0,
|
||||
286, 284, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 289, 1, 0, 0, 0, 288,
|
||||
286, 1, 0, 0, 0, 289, 301, 5, 34, 0, 0, 290, 296, 5, 39, 0, 0, 291, 295,
|
||||
8, 24, 0, 0, 292, 293, 5, 92, 0, 0, 293, 295, 9, 0, 0, 0, 294, 291, 1,
|
||||
0, 0, 0, 294, 292, 1, 0, 0, 0, 295, 298, 1, 0, 0, 0, 296, 294, 1, 0, 0,
|
||||
0, 296, 297, 1, 0, 0, 0, 297, 299, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 299,
|
||||
301, 5, 39, 0, 0, 300, 280, 1, 0, 0, 0, 300, 290, 1, 0, 0, 0, 301, 64,
|
||||
1, 0, 0, 0, 302, 306, 7, 25, 0, 0, 303, 305, 7, 26, 0, 0, 304, 303, 1,
|
||||
0, 0, 0, 305, 308, 1, 0, 0, 0, 306, 304, 1, 0, 0, 0, 306, 307, 1, 0, 0,
|
||||
0, 307, 66, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 309, 310, 5, 91, 0, 0, 310,
|
||||
311, 5, 93, 0, 0, 311, 68, 1, 0, 0, 0, 312, 313, 5, 91, 0, 0, 313, 314,
|
||||
5, 42, 0, 0, 314, 315, 5, 93, 0, 0, 315, 70, 1, 0, 0, 0, 316, 329, 3, 65,
|
||||
32, 0, 317, 318, 5, 46, 0, 0, 318, 328, 3, 65, 32, 0, 319, 328, 3, 67,
|
||||
33, 0, 320, 328, 3, 69, 34, 0, 321, 323, 5, 46, 0, 0, 322, 324, 3, 75,
|
||||
37, 0, 323, 322, 1, 0, 0, 0, 324, 325, 1, 0, 0, 0, 325, 323, 1, 0, 0, 0,
|
||||
325, 326, 1, 0, 0, 0, 326, 328, 1, 0, 0, 0, 327, 317, 1, 0, 0, 0, 327,
|
||||
319, 1, 0, 0, 0, 327, 320, 1, 0, 0, 0, 327, 321, 1, 0, 0, 0, 328, 331,
|
||||
1, 0, 0, 0, 329, 327, 1, 0, 0, 0, 329, 330, 1, 0, 0, 0, 330, 72, 1, 0,
|
||||
0, 0, 331, 329, 1, 0, 0, 0, 332, 334, 7, 19, 0, 0, 333, 332, 1, 0, 0, 0,
|
||||
334, 335, 1, 0, 0, 0, 335, 333, 1, 0, 0, 0, 335, 336, 1, 0, 0, 0, 336,
|
||||
337, 1, 0, 0, 0, 337, 338, 6, 36, 0, 0, 338, 74, 1, 0, 0, 0, 339, 340,
|
||||
7, 27, 0, 0, 340, 76, 1, 0, 0, 0, 341, 343, 8, 28, 0, 0, 342, 341, 1, 0,
|
||||
0, 0, 343, 344, 1, 0, 0, 0, 344, 342, 1, 0, 0, 0, 344, 345, 1, 0, 0, 0,
|
||||
345, 78, 1, 0, 0, 0, 30, 0, 92, 135, 152, 212, 226, 231, 236, 242, 245,
|
||||
249, 254, 256, 259, 265, 269, 274, 276, 278, 284, 286, 294, 296, 300, 306,
|
||||
325, 327, 329, 335, 344, 1, 6, 0, 0,
|
||||
}
|
||||
deserializer := antlr.NewATNDeserializer(nil)
|
||||
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
|
||||
@@ -285,10 +295,11 @@ const (
|
||||
FilterQueryLexerHASANY = 25
|
||||
FilterQueryLexerHASALL = 26
|
||||
FilterQueryLexerSEARCH = 27
|
||||
FilterQueryLexerBOOL = 28
|
||||
FilterQueryLexerNUMBER = 29
|
||||
FilterQueryLexerQUOTED_TEXT = 30
|
||||
FilterQueryLexerKEY = 31
|
||||
FilterQueryLexerWS = 32
|
||||
FilterQueryLexerFREETEXT = 33
|
||||
FilterQueryLexerPATTERN = 28
|
||||
FilterQueryLexerBOOL = 29
|
||||
FilterQueryLexerNUMBER = 30
|
||||
FilterQueryLexerQUOTED_TEXT = 31
|
||||
FilterQueryLexerKEY = 32
|
||||
FilterQueryLexerWS = 33
|
||||
FilterQueryLexerFREETEXT = 34
|
||||
)
|
||||
|
||||
@@ -47,6 +47,9 @@ type FilterQueryListener interface {
|
||||
// EnterSearchCall is called when entering the searchCall production.
|
||||
EnterSearchCall(c *SearchCallContext)
|
||||
|
||||
// EnterPatternCall is called when entering the patternCall production.
|
||||
EnterPatternCall(c *PatternCallContext)
|
||||
|
||||
// EnterFunctionParamList is called when entering the functionParamList production.
|
||||
EnterFunctionParamList(c *FunctionParamListContext)
|
||||
|
||||
@@ -101,6 +104,9 @@ type FilterQueryListener interface {
|
||||
// ExitSearchCall is called when exiting the searchCall production.
|
||||
ExitSearchCall(c *SearchCallContext)
|
||||
|
||||
// ExitPatternCall is called when exiting the patternCall production.
|
||||
ExitPatternCall(c *PatternCallContext)
|
||||
|
||||
// ExitFunctionParamList is called when exiting the functionParamList production.
|
||||
ExitFunctionParamList(c *FunctionParamListContext)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,9 @@ type FilterQueryVisitor interface {
|
||||
// Visit a parse tree produced by FilterQueryParser#searchCall.
|
||||
VisitSearchCall(ctx *SearchCallContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by FilterQueryParser#patternCall.
|
||||
VisitPatternCall(ctx *PatternCallContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by FilterQueryParser#functionParamList.
|
||||
VisitFunctionParamList(ctx *FunctionParamListContext) interface{}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ var friendly = map[string]string{
|
||||
"BETWEEN": "BETWEEN", "IN": "IN", "EXISTS": "EXISTS",
|
||||
"REGEXP": "REGEXP", "CONTAINS": "CONTAINS",
|
||||
"HAS": "has()", "HASANY": "hasAny()", "HASALL": "hasAll()",
|
||||
"HASTOKEN": "hasToken()", "SEARCH": "search()",
|
||||
"HASTOKEN": "hasToken()", "SEARCH": "search()", "PATTERN": "pattern()",
|
||||
|
||||
// literals / identifiers
|
||||
"NUMBER": "number",
|
||||
|
||||
@@ -194,6 +194,9 @@ func (d *LogicalContradictionDetector) VisitPrimary(ctx *grammar.PrimaryContext)
|
||||
} else if ctx.SearchCall() != nil {
|
||||
// search() spans all fields; it can never be a logical contradiction
|
||||
return nil
|
||||
} else if ctx.PatternCall() != nil {
|
||||
// pattern() reads no key, so it can't contradict a comparison
|
||||
return nil
|
||||
} else if ctx.FullText() != nil {
|
||||
// Handle full text search if needed
|
||||
return nil
|
||||
|
||||
@@ -204,6 +204,8 @@ func (v *filterExpressionVisitor) Visit(tree antlr.ParseTree) any {
|
||||
return v.VisitFullText(t)
|
||||
case *grammar.SearchCallContext:
|
||||
return v.VisitSearchCall(t)
|
||||
case *grammar.PatternCallContext:
|
||||
return v.VisitPatternCall(t)
|
||||
case *grammar.FunctionCallContext:
|
||||
return v.VisitFunctionCall(t)
|
||||
case *grammar.FunctionParamListContext:
|
||||
@@ -320,6 +322,8 @@ func (v *filterExpressionVisitor) VisitPrimary(ctx *grammar.PrimaryContext) any
|
||||
return v.Visit(ctx.FunctionCall())
|
||||
} else if ctx.SearchCall() != nil {
|
||||
return v.Visit(ctx.SearchCall())
|
||||
} else if ctx.PatternCall() != nil {
|
||||
return v.Visit(ctx.PatternCall())
|
||||
} else if ctx.FullText() != nil {
|
||||
return v.Visit(ctx.FullText())
|
||||
}
|
||||
@@ -841,6 +845,13 @@ func (v *filterExpressionVisitor) VisitSearchCall(ctx *grammar.SearchCallContext
|
||||
return v.builder.Or(conds...)
|
||||
}
|
||||
|
||||
// VisitPatternCall handles pattern('<pattern text>'[, ...]), the log pattern
|
||||
// filter. The grammar accepts it, but no storage evaluates it yet.
|
||||
func (v *filterExpressionVisitor) VisitPatternCall(_ *grammar.PatternCallContext) any {
|
||||
v.errors = append(v.errors, "function `pattern` is not supported yet")
|
||||
return ErrorConditionLiteral
|
||||
}
|
||||
|
||||
// searchParamText returns an argument's raw token text (quoted or bare) rather than its
|
||||
// visited value, so a bare word stays literal and search(1000000) isn't "1e+06".
|
||||
func searchParamText(val grammar.IValueContext) (string, bool) {
|
||||
|
||||
@@ -112,7 +112,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
category: "Single word",
|
||||
query: "<script>alert('xss')</script>",
|
||||
shouldPass: false,
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got '<'",
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got '<'",
|
||||
},
|
||||
|
||||
// Single word searches with spaces
|
||||
@@ -178,7 +178,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
category: "Special characters",
|
||||
query: "[tracing]",
|
||||
shouldPass: false,
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got '['",
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got '['",
|
||||
},
|
||||
{
|
||||
category: "Special characters",
|
||||
@@ -208,7 +208,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
category: "Special characters",
|
||||
query: "ERROR: cannot execute update() in a read-only context",
|
||||
shouldPass: false,
|
||||
expectedErrorContains: "expecting one of {(, AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got ')'",
|
||||
expectedErrorContains: "expecting one of {(, AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got ')'",
|
||||
},
|
||||
{
|
||||
category: "Special characters",
|
||||
@@ -630,7 +630,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "expecting one of {(, ), FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'and'",
|
||||
expectedErrorContains: "expecting one of {(, ), FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'and'",
|
||||
},
|
||||
{
|
||||
category: "Keyword conflict",
|
||||
@@ -638,7 +638,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'or'",
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'or'",
|
||||
},
|
||||
{
|
||||
category: "Keyword conflict",
|
||||
@@ -646,7 +646,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "expecting one of {(, ), FREETEXT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got EOF",
|
||||
expectedErrorContains: "expecting one of {(, ), FREETEXT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got EOF",
|
||||
},
|
||||
{
|
||||
category: "Keyword conflict",
|
||||
@@ -654,7 +654,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'like'",
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'like'",
|
||||
},
|
||||
{
|
||||
category: "Keyword conflict",
|
||||
@@ -662,7 +662,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'between'",
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'between'",
|
||||
},
|
||||
{
|
||||
category: "Keyword conflict",
|
||||
@@ -670,7 +670,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'in'",
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'in'",
|
||||
},
|
||||
{
|
||||
category: "Keyword conflict",
|
||||
@@ -678,7 +678,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'exists'",
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'exists'",
|
||||
},
|
||||
{
|
||||
category: "Keyword conflict",
|
||||
@@ -686,7 +686,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'regexp'",
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'regexp'",
|
||||
},
|
||||
{
|
||||
category: "Keyword conflict",
|
||||
@@ -694,7 +694,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'contains'",
|
||||
expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'contains'",
|
||||
},
|
||||
{
|
||||
category: "Keyword conflict",
|
||||
@@ -2062,9 +2062,9 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
expectedErrorContains: "",
|
||||
},
|
||||
|
||||
{category: "Only keywords", query: "AND", shouldPass: false, expectedErrorContains: "expecting one of {(, ), FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'AND'"},
|
||||
{category: "Only keywords", query: "OR", shouldPass: false, expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'OR'"},
|
||||
{category: "Only keywords", query: "NOT", shouldPass: false, expectedErrorContains: "expecting one of {(, ), FREETEXT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got EOF"},
|
||||
{category: "Only keywords", query: "AND", shouldPass: false, expectedErrorContains: "expecting one of {(, ), FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'AND'"},
|
||||
{category: "Only keywords", query: "OR", shouldPass: false, expectedErrorContains: "expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'OR'"},
|
||||
{category: "Only keywords", query: "NOT", shouldPass: false, expectedErrorContains: "expecting one of {(, ), FREETEXT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got EOF"},
|
||||
|
||||
{category: "Only functions", query: "has", shouldPass: false, expectedErrorContains: "expecting one of {(, )} but got EOF"},
|
||||
{category: "Only functions", query: "hasAny", shouldPass: false, expectedErrorContains: "expecting one of {(, )} but got EOF"},
|
||||
@@ -2206,7 +2206,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "line 1:0 expecting one of {(, ), FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'and'",
|
||||
expectedErrorContains: "line 1:0 expecting one of {(, ), FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'and'",
|
||||
},
|
||||
{
|
||||
category: "Operator keywords as keys",
|
||||
@@ -2214,7 +2214,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "line 1:0 expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'or'",
|
||||
expectedErrorContains: "line 1:0 expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'or'",
|
||||
},
|
||||
{
|
||||
category: "Operator keywords as keys",
|
||||
@@ -2222,7 +2222,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "line 1:3 expecting one of {(, ), FREETEXT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got '='",
|
||||
expectedErrorContains: "line 1:3 expecting one of {(, ), FREETEXT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got '='",
|
||||
},
|
||||
{
|
||||
category: "Operator keywords as keys",
|
||||
@@ -2230,7 +2230,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "line 1:0 expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'between'",
|
||||
expectedErrorContains: "line 1:0 expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'between'",
|
||||
},
|
||||
{
|
||||
category: "Operator keywords as keys",
|
||||
@@ -2238,7 +2238,7 @@ func TestFilterExprLogs(t *testing.T) {
|
||||
shouldPass: false,
|
||||
expectedQuery: "",
|
||||
expectedArgs: nil,
|
||||
expectedErrorContains: "line 1:0 expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, quoted text, search()} but got 'in'",
|
||||
expectedErrorContains: "line 1:0 expecting one of {(, ), AND, FREETEXT, NOT, boolean, has(), hasAll(), hasAny(), hasToken(), number, pattern(), quoted text, search()} but got 'in'",
|
||||
},
|
||||
|
||||
// Using function keywords as keys
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package logstelemetryschema
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/huandu/go-sqlbuilder"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/flagger/flaggertest"
|
||||
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
||||
"github.com/SigNoz/signoz/pkg/querybuilder"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
func TestFilterExprPattern(t *testing.T) {
|
||||
releaseTime := time.Date(2024, 1, 15, 10, 0, 0, 0, time.UTC)
|
||||
opts := querybuilder.FilterExprVisitorOpts{
|
||||
Context: context.Background(),
|
||||
Logger: instrumentationtest.New().Logger(),
|
||||
Storage: NewStorage(),
|
||||
Query: querybuilder.NewQueryInfo(context.Background(), valuer.UUID{}, flaggertest.New(t), telemetrytypes.SignalLogs, nil, uint64(releaseTime.Add(-5*time.Minute).UnixNano()), uint64(releaseTime.Add(5*time.Minute).UnixNano())),
|
||||
FieldKeys: BuildCompleteFieldKeyMap(releaseTime),
|
||||
FullTextColumn: DefaultFullTextColumn,
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
query string
|
||||
expectedQuery string
|
||||
expectedArgs []any
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "OnePattern_NotSupportedYet",
|
||||
query: "pattern('User <*> logged in from <IP>')",
|
||||
expectedError: "function `pattern` is not supported yet",
|
||||
},
|
||||
{
|
||||
name: "SeveralPatterns_NotSupportedYet",
|
||||
query: `pattern('<IP>', "can't connect to <IP>")`,
|
||||
expectedError: "function `pattern` is not supported yet",
|
||||
},
|
||||
{
|
||||
name: "Not_NotSupportedYet",
|
||||
query: "service.name = 'api' AND NOT pattern('<IP>')",
|
||||
expectedError: "function `pattern` is not supported yet",
|
||||
},
|
||||
{
|
||||
name: "SpaceBeforeParenthesis_NotSupportedYet",
|
||||
query: "PATTERN ('<IP>')",
|
||||
expectedError: "function `pattern` is not supported yet",
|
||||
},
|
||||
{
|
||||
name: "NewlineBeforeParenthesis_NotSupportedYet",
|
||||
query: "pattern\r\n('<IP>')",
|
||||
expectedError: "function `pattern` is not supported yet",
|
||||
},
|
||||
{
|
||||
name: "NoPattern_SyntaxError",
|
||||
query: "pattern()",
|
||||
expectedError: "syntax error",
|
||||
},
|
||||
{
|
||||
name: "PatternKey_StaysAKey",
|
||||
query: "pattern = 'x'",
|
||||
expectedQuery: "WHERE ((attributes_string['pattern'] = ? AND mapContains(attributes_string, 'pattern')) OR (JSON_VALUE(body, '$.\"pattern\"') = ? AND JSON_EXISTS(body, '$.\"pattern\"')))",
|
||||
expectedArgs: []any{"x", "x"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
clause, err := querybuilder.PrepareWhereClause(testCase.query, opts)
|
||||
if testCase.expectedError != "" {
|
||||
require.Error(t, err)
|
||||
assert.True(t, strings.Contains(err.Error(), testCase.expectedError) || detailContains(err, testCase.expectedError), err.Error())
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
sql, args := clause.WhereClause.BuildWithFlavor(sqlbuilder.ClickHouse)
|
||||
assert.Equal(t, testCase.expectedQuery, sql)
|
||||
assert.Equal(t, testCase.expectedArgs, args)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,8 @@ func (v *variableReplacementVisitor) Visit(tree antlr.ParseTree) any {
|
||||
return v.VisitFullText(t)
|
||||
case *grammar.SearchCallContext:
|
||||
return v.VisitSearchCall(t)
|
||||
case *grammar.PatternCallContext:
|
||||
return v.VisitPatternCall(t)
|
||||
case *grammar.FunctionCallContext:
|
||||
return v.VisitFunctionCall(t)
|
||||
case *grammar.FunctionParamListContext:
|
||||
@@ -207,6 +209,8 @@ func (v *variableReplacementVisitor) VisitPrimary(ctx *grammar.PrimaryContext) a
|
||||
return v.Visit(ctx.FunctionCall())
|
||||
} else if ctx.SearchCall() != nil {
|
||||
return v.Visit(ctx.SearchCall())
|
||||
} else if ctx.PatternCall() != nil {
|
||||
return v.Visit(ctx.PatternCall())
|
||||
} else if ctx.FullText() != nil {
|
||||
return v.Visit(ctx.FullText())
|
||||
}
|
||||
@@ -423,6 +427,18 @@ func (v *variableReplacementVisitor) VisitSearchCall(ctx *grammar.SearchCallCont
|
||||
return "search" + result
|
||||
}
|
||||
|
||||
func (v *variableReplacementVisitor) VisitPatternCall(ctx *grammar.PatternCallContext) any {
|
||||
if ctx.ValueList() == nil {
|
||||
return "pattern()"
|
||||
}
|
||||
// VisitValueList already parenthesizes the args and propagates the __all__ marker.
|
||||
result := v.Visit(ctx.ValueList()).(string)
|
||||
if result == specialSkipMarker {
|
||||
return specialSkipMarker
|
||||
}
|
||||
return "pattern" + result
|
||||
}
|
||||
|
||||
func (v *variableReplacementVisitor) VisitFunctionParamList(ctx *grammar.FunctionParamListContext) any {
|
||||
params := ctx.AllFunctionParam()
|
||||
parts := make([]string, 0, len(params))
|
||||
|
||||
@@ -279,6 +279,17 @@ func TestReplaceVariablesInExpression(t *testing.T) {
|
||||
},
|
||||
expected: "hasToken(tags, 'test')",
|
||||
},
|
||||
{
|
||||
name: "pattern function kept as is",
|
||||
expression: "service.name = $service AND pattern('User <*> logged in from <IP>', \"can't connect\")",
|
||||
variables: map[string]qbtypes.VariableItem{
|
||||
"service": {
|
||||
Type: qbtypes.DynamicVariableType,
|
||||
Value: "auth",
|
||||
},
|
||||
},
|
||||
expected: "service.name = 'auth' AND pattern('User <*> logged in from <IP>', \"can't connect\")",
|
||||
},
|
||||
{
|
||||
name: "empty array variable",
|
||||
expression: "service.name IN $services",
|
||||
|
||||
Reference in New Issue
Block a user