diff --git a/x-pack/plugin/eql/qa/common/src/main/resources/data/extra.data b/x-pack/plugin/eql/qa/common/src/main/resources/data/extra.data index d1c1783530096..ed7a269453918 100644 --- a/x-pack/plugin/eql/qa/common/src/main/resources/data/extra.data +++ b/x-pack/plugin/eql/qa/common/src/main/resources/data/extra.data @@ -34,5 +34,22 @@ "event_type": "STAT", "transID": 1235, "sequence": 3 + }, + { + "@timestamp": "100", + "event_type": "OPTIONAL", + "default_null_value_field": null, + "sequence": 4 + }, + { + "@timestamp": "101", + "event_type": "OPTIONAL", + "sequence": 5 + }, + { + "@timestamp": "102", + "event_type": "OPTIONAL", + "default_null_value_field": null, + "sequence": 6 } ] diff --git a/x-pack/plugin/eql/qa/common/src/main/resources/data/extra.mapping b/x-pack/plugin/eql/qa/common/src/main/resources/data/extra.mapping index e58b98cf33118..f2cd59ea6ca9c 100644 --- a/x-pack/plugin/eql/qa/common/src/main/resources/data/extra.mapping +++ b/x-pack/plugin/eql/qa/common/src/main/resources/data/extra.mapping @@ -20,6 +20,13 @@ "path": "sequence" } } + }, + "no_docs_field": { + "type": "keyword" + }, + "default_null_value_field": { + "type": "keyword", + "null_value": "NULL" } } } diff --git a/x-pack/plugin/eql/qa/common/src/main/resources/test_extra.toml b/x-pack/plugin/eql/qa/common/src/main/resources/test_extra.toml index 66de63b4a2b95..9b9e805723c9c 100644 --- a/x-pack/plugin/eql/qa/common/src/main/resources/test_extra.toml +++ b/x-pack/plugin/eql/qa/common/src/main/resources/test_extra.toml @@ -27,3 +27,45 @@ query = ''' [ STAT where transID == 1234 ] ''' expected_event_ids = [1,2,3] + +[[queries]] +name = "optionalNoDocsFieldNullEquality" +query = ''' + OPTIONAL where ?no_docs_field == null +''' +expected_event_ids = [4,5,6] + +[[queries]] +name = "optionalNoDocsFieldNumericEquality" +query = ''' + OPTIONAL where ?no_docs_field == 123 +''' +expected_event_ids = [] + +[[queries]] +name = "optionalDefaultNullValueFieldEqualNull" +query = ''' + OPTIONAL where ?default_null_value_field == null +''' +expected_event_ids = [5] + +[[queries]] +name = "optionalDefaultNullValueFieldEqualDefaultValue" +query = ''' + OPTIONAL where ?default_null_value_field == "NULL" +''' +expected_event_ids = [4,6] + +[[queries]] +name = "optionalMissingFieldNullEquality" +query = ''' + OPTIONAL where ?inexistent_field == null +''' +expected_event_ids = [4,5,6] + +[[queries]] +name = "optionalMissingFieldImplicitBooleanEquality" +query = ''' + OPTIONAL where ?inexistent_field +''' +expected_event_ids = [] diff --git a/x-pack/plugin/eql/src/main/antlr/EqlBase.g4 b/x-pack/plugin/eql/src/main/antlr/EqlBase.g4 index dfffb4aa06368..3b7e7ee3ad4b0 100644 --- a/x-pack/plugin/eql/src/main/antlr/EqlBase.g4 +++ b/x-pack/plugin/eql/src/main/antlr/EqlBase.g4 @@ -137,7 +137,7 @@ booleanValue ; qualifiedName - : identifier (DOT identifier | LB INTEGER_VALUE+ RB)* + : OPTIONAL? identifier (DOT identifier | LB INTEGER_VALUE+ RB)* ; identifier @@ -204,6 +204,7 @@ RB: ']'; LP: '('; RP: ')'; PIPE: '|'; +OPTIONAL: '?'; fragment STRING_ESCAPE : '\\' [btnfr"'\\] diff --git a/x-pack/plugin/eql/src/main/antlr/EqlBase.tokens b/x-pack/plugin/eql/src/main/antlr/EqlBase.tokens index 295f164b3e888..59d10b853e31a 100644 --- a/x-pack/plugin/eql/src/main/antlr/EqlBase.tokens +++ b/x-pack/plugin/eql/src/main/antlr/EqlBase.tokens @@ -39,15 +39,16 @@ RB=38 LP=39 RP=40 PIPE=41 -STRING=42 -INTEGER_VALUE=43 -DECIMAL_VALUE=44 -IDENTIFIER=45 -QUOTED_IDENTIFIER=46 -TILDE_IDENTIFIER=47 -LINE_COMMENT=48 -BRACKETED_COMMENT=49 -WS=50 +OPTIONAL=42 +STRING=43 +INTEGER_VALUE=44 +DECIMAL_VALUE=45 +IDENTIFIER=46 +QUOTED_IDENTIFIER=47 +TILDE_IDENTIFIER=48 +LINE_COMMENT=49 +BRACKETED_COMMENT=50 +WS=51 'and'=1 'any'=2 'by'=3 @@ -89,3 +90,4 @@ WS=50 '('=39 ')'=40 '|'=41 +'?'=42 diff --git a/x-pack/plugin/eql/src/main/antlr/EqlBaseLexer.tokens b/x-pack/plugin/eql/src/main/antlr/EqlBaseLexer.tokens index 295f164b3e888..59d10b853e31a 100644 --- a/x-pack/plugin/eql/src/main/antlr/EqlBaseLexer.tokens +++ b/x-pack/plugin/eql/src/main/antlr/EqlBaseLexer.tokens @@ -39,15 +39,16 @@ RB=38 LP=39 RP=40 PIPE=41 -STRING=42 -INTEGER_VALUE=43 -DECIMAL_VALUE=44 -IDENTIFIER=45 -QUOTED_IDENTIFIER=46 -TILDE_IDENTIFIER=47 -LINE_COMMENT=48 -BRACKETED_COMMENT=49 -WS=50 +OPTIONAL=42 +STRING=43 +INTEGER_VALUE=44 +DECIMAL_VALUE=45 +IDENTIFIER=46 +QUOTED_IDENTIFIER=47 +TILDE_IDENTIFIER=48 +LINE_COMMENT=49 +BRACKETED_COMMENT=50 +WS=51 'and'=1 'any'=2 'by'=3 @@ -89,3 +90,4 @@ WS=50 '('=39 ')'=40 '|'=41 +'?'=42 diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/analysis/Analyzer.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/analysis/Analyzer.java index d9c38ec5e096b..7c1467017b614 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/analysis/Analyzer.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/analysis/Analyzer.java @@ -9,7 +9,8 @@ import org.elasticsearch.xpack.ql.common.Failure; import org.elasticsearch.xpack.ql.expression.Attribute; -import org.elasticsearch.xpack.ql.expression.NamedExpression; +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.UnresolvedAttribute; import org.elasticsearch.xpack.ql.expression.function.Function; import org.elasticsearch.xpack.ql.expression.function.FunctionDefinition; @@ -21,21 +22,24 @@ import java.util.Collection; import java.util.LinkedHashSet; +import java.util.Set; import static java.util.Arrays.asList; import static org.elasticsearch.xpack.eql.analysis.AnalysisUtils.resolveAgainstList; -import static org.elasticsearch.xpack.ql.analyzer.AnalyzerRules.AddMissingEqualsToBoolField; +import org.elasticsearch.xpack.ql.analyzer.AnalyzerRules.AddMissingEqualsToBoolField; public class Analyzer extends RuleExecutor { private final Configuration configuration; private final FunctionRegistry functionRegistry; private final Verifier verifier; + private final Set optionals; - public Analyzer(Configuration configuration, FunctionRegistry functionRegistry, Verifier verifier) { + public Analyzer(Configuration configuration, FunctionRegistry functionRegistry, Verifier verifier, Set optionals) { this.configuration = configuration; this.functionRegistry = functionRegistry; this.verifier = verifier; + this.optionals = optionals; } @Override @@ -62,7 +66,7 @@ private LogicalPlan verify(LogicalPlan plan) { return plan; } - private static class ResolveRefs extends AnalyzerRule { + private class ResolveRefs extends AnalyzerRule { @Override protected LogicalPlan rule(LogicalPlan plan) { @@ -81,7 +85,11 @@ protected LogicalPlan rule(LogicalPlan plan) { for (LogicalPlan child : plan.children()) { childrenOutput.addAll(child.output()); } - NamedExpression named = resolveAgainstList(u, childrenOutput); + Expression named = resolveAgainstList(u, childrenOutput); + // if it's not resolved (it doesn't exist in mappings) and it's an optional field, replace it with "null" + if (named == null && optionals.contains(u)) { + named = Literal.NULL; + } // if resolved, return it; otherwise keep it in place to be resolved later if (named != null) { if (log.isTraceEnabled()) { diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/AstBuilder.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/AstBuilder.java index 9697421efb237..6fbe4e3747ecf 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/AstBuilder.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/AstBuilder.java @@ -8,12 +8,15 @@ package org.elasticsearch.xpack.eql.parser; import org.elasticsearch.xpack.eql.parser.EqlBaseParser.SingleStatementContext; +import org.elasticsearch.xpack.ql.expression.UnresolvedAttribute; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; +import java.util.Set; + public class AstBuilder extends LogicalPlanBuilder { - AstBuilder(ParserParams params) { - super(params); + AstBuilder(ParserParams params, Set optionals) { + super(params, optionals); } @Override diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseLexer.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseLexer.java index 0a822b9b8f486..5d23efd4c5bf8 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseLexer.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseLexer.java @@ -22,8 +22,9 @@ class EqlBaseLexer extends Lexer { SEQUENCE=17, TRUE=18, UNTIL=19, WHERE=20, WITH=21, SEQ=22, ASGN=23, EQ=24, NEQ=25, LT=26, LTE=27, GT=28, GTE=29, PLUS=30, MINUS=31, ASTERISK=32, SLASH=33, PERCENT=34, DOT=35, COMMA=36, LB=37, RB=38, LP=39, RP=40, PIPE=41, - STRING=42, INTEGER_VALUE=43, DECIMAL_VALUE=44, IDENTIFIER=45, QUOTED_IDENTIFIER=46, - TILDE_IDENTIFIER=47, LINE_COMMENT=48, BRACKETED_COMMENT=49, WS=50; + OPTIONAL=42, STRING=43, INTEGER_VALUE=44, DECIMAL_VALUE=45, IDENTIFIER=46, + QUOTED_IDENTIFIER=47, TILDE_IDENTIFIER=48, LINE_COMMENT=49, BRACKETED_COMMENT=50, + WS=51; public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -38,10 +39,10 @@ private static String[] makeRuleNames() { "LIKE_INSENSITIVE", "MAXSPAN", "NOT", "NULL", "OF", "OR", "REGEX", "REGEX_INSENSITIVE", "SEQUENCE", "TRUE", "UNTIL", "WHERE", "WITH", "SEQ", "ASGN", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", - "DOT", "COMMA", "LB", "RB", "LP", "RP", "PIPE", "STRING_ESCAPE", "HEX_DIGIT", - "UNICODE_ESCAPE", "UNESCAPED_CHARS", "STRING", "INTEGER_VALUE", "DECIMAL_VALUE", - "IDENTIFIER", "QUOTED_IDENTIFIER", "TILDE_IDENTIFIER", "EXPONENT", "DIGIT", - "LETTER", "LINE_COMMENT", "BRACKETED_COMMENT", "WS" + "DOT", "COMMA", "LB", "RB", "LP", "RP", "PIPE", "OPTIONAL", "STRING_ESCAPE", + "HEX_DIGIT", "UNICODE_ESCAPE", "UNESCAPED_CHARS", "STRING", "INTEGER_VALUE", + "DECIMAL_VALUE", "IDENTIFIER", "QUOTED_IDENTIFIER", "TILDE_IDENTIFIER", + "EXPONENT", "DIGIT", "LETTER", "LINE_COMMENT", "BRACKETED_COMMENT", "WS" }; } public static final String[] ruleNames = makeRuleNames(); @@ -53,7 +54,7 @@ private static String[] makeLiteralNames() { "'regex'", "'regex~'", "'sequence'", "'true'", "'until'", "'where'", "'with'", "':'", "'='", "'=='", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", "'.'", "','", "'['", "']'", "'('", - "')'", "'|'" + "')'", "'|'", "'?'" }; } private static final String[] _LITERAL_NAMES = makeLiteralNames(); @@ -63,9 +64,9 @@ private static String[] makeSymbolicNames() { "LIKE_INSENSITIVE", "MAXSPAN", "NOT", "NULL", "OF", "OR", "REGEX", "REGEX_INSENSITIVE", "SEQUENCE", "TRUE", "UNTIL", "WHERE", "WITH", "SEQ", "ASGN", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", - "DOT", "COMMA", "LB", "RB", "LP", "RP", "PIPE", "STRING", "INTEGER_VALUE", - "DECIMAL_VALUE", "IDENTIFIER", "QUOTED_IDENTIFIER", "TILDE_IDENTIFIER", - "LINE_COMMENT", "BRACKETED_COMMENT", "WS" + "DOT", "COMMA", "LB", "RB", "LP", "RP", "PIPE", "OPTIONAL", "STRING", + "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "QUOTED_IDENTIFIER", + "TILDE_IDENTIFIER", "LINE_COMMENT", "BRACKETED_COMMENT", "WS" }; } private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); @@ -127,181 +128,184 @@ public EqlBaseLexer(CharStream input) { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\64\u01e7\b\1\4\2"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\65\u01eb\b\1\4\2"+ "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+ "\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+ "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+ "\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t"+ " \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t"+ "+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64"+ - "\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\3\2\3\2\3\2\3\2"+ - "\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\7\3"+ - "\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n"+ - "\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\r\3\r\3"+ - "\r\3\r\3\r\3\16\3\16\3\16\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20"+ - "\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22"+ - "\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\25"+ - "\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\30\3\30"+ - "\3\31\3\31\3\31\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\36"+ - "\3\36\3\36\3\37\3\37\3 \3 \3!\3!\3\"\3\"\3#\3#\3$\3$\3%\3%\3&\3&\3\'\3"+ - "\'\3(\3(\3)\3)\3*\3*\3+\3+\3+\3,\3,\3-\3-\3-\3-\3-\6-\u0117\n-\r-\16-"+ - "\u0118\3-\3-\3.\3.\3/\3/\3/\3/\7/\u0123\n/\f/\16/\u0126\13/\3/\3/\3/\3"+ - "/\3/\3/\7/\u012e\n/\f/\16/\u0131\13/\3/\3/\3/\3/\3/\5/\u0138\n/\3/\5/"+ - "\u013b\n/\3/\3/\3/\3/\7/\u0141\n/\f/\16/\u0144\13/\3/\3/\3/\3/\3/\3/\3"+ - "/\7/\u014d\n/\f/\16/\u0150\13/\3/\3/\3/\3/\3/\3/\3/\7/\u0159\n/\f/\16"+ - "/\u015c\13/\3/\5/\u015f\n/\3\60\6\60\u0162\n\60\r\60\16\60\u0163\3\61"+ - "\6\61\u0167\n\61\r\61\16\61\u0168\3\61\3\61\7\61\u016d\n\61\f\61\16\61"+ - "\u0170\13\61\3\61\3\61\6\61\u0174\n\61\r\61\16\61\u0175\3\61\6\61\u0179"+ - "\n\61\r\61\16\61\u017a\3\61\3\61\7\61\u017f\n\61\f\61\16\61\u0182\13\61"+ - "\5\61\u0184\n\61\3\61\3\61\3\61\3\61\6\61\u018a\n\61\r\61\16\61\u018b"+ - "\3\61\3\61\5\61\u0190\n\61\3\62\3\62\5\62\u0194\n\62\3\62\3\62\3\62\7"+ - "\62\u0199\n\62\f\62\16\62\u019c\13\62\3\63\3\63\3\63\3\63\7\63\u01a2\n"+ - "\63\f\63\16\63\u01a5\13\63\3\63\3\63\3\64\3\64\3\64\3\64\7\64\u01ad\n"+ - "\64\f\64\16\64\u01b0\13\64\3\64\3\64\3\65\3\65\5\65\u01b6\n\65\3\65\6"+ - "\65\u01b9\n\65\r\65\16\65\u01ba\3\66\3\66\3\67\3\67\38\38\38\38\78\u01c5"+ - "\n8\f8\168\u01c8\138\38\58\u01cb\n8\38\58\u01ce\n8\38\38\39\39\39\39\3"+ - "9\79\u01d7\n9\f9\169\u01da\139\39\39\39\39\39\3:\6:\u01e2\n:\r:\16:\u01e3"+ - "\3:\3:\4\u012f\u01d8\2;\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f"+ + "\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\3\2\3\2\3"+ + "\2\3\2\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6"+ + "\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3"+ + "\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\r"+ + "\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20"+ + "\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22"+ + "\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24"+ + "\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\30"+ + "\3\30\3\31\3\31\3\31\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35"+ + "\3\36\3\36\3\36\3\37\3\37\3 \3 \3!\3!\3\"\3\"\3#\3#\3$\3$\3%\3%\3&\3&"+ + "\3\'\3\'\3(\3(\3)\3)\3*\3*\3+\3+\3,\3,\3,\3-\3-\3.\3.\3.\3.\3.\6.\u011b"+ + "\n.\r.\16.\u011c\3.\3.\3/\3/\3\60\3\60\3\60\3\60\7\60\u0127\n\60\f\60"+ + "\16\60\u012a\13\60\3\60\3\60\3\60\3\60\3\60\3\60\7\60\u0132\n\60\f\60"+ + "\16\60\u0135\13\60\3\60\3\60\3\60\3\60\3\60\5\60\u013c\n\60\3\60\5\60"+ + "\u013f\n\60\3\60\3\60\3\60\3\60\7\60\u0145\n\60\f\60\16\60\u0148\13\60"+ + "\3\60\3\60\3\60\3\60\3\60\3\60\3\60\7\60\u0151\n\60\f\60\16\60\u0154\13"+ + "\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\7\60\u015d\n\60\f\60\16\60\u0160"+ + "\13\60\3\60\5\60\u0163\n\60\3\61\6\61\u0166\n\61\r\61\16\61\u0167\3\62"+ + "\6\62\u016b\n\62\r\62\16\62\u016c\3\62\3\62\7\62\u0171\n\62\f\62\16\62"+ + "\u0174\13\62\3\62\3\62\6\62\u0178\n\62\r\62\16\62\u0179\3\62\6\62\u017d"+ + "\n\62\r\62\16\62\u017e\3\62\3\62\7\62\u0183\n\62\f\62\16\62\u0186\13\62"+ + "\5\62\u0188\n\62\3\62\3\62\3\62\3\62\6\62\u018e\n\62\r\62\16\62\u018f"+ + "\3\62\3\62\5\62\u0194\n\62\3\63\3\63\5\63\u0198\n\63\3\63\3\63\3\63\7"+ + "\63\u019d\n\63\f\63\16\63\u01a0\13\63\3\64\3\64\3\64\3\64\7\64\u01a6\n"+ + "\64\f\64\16\64\u01a9\13\64\3\64\3\64\3\65\3\65\3\65\3\65\7\65\u01b1\n"+ + "\65\f\65\16\65\u01b4\13\65\3\65\3\65\3\66\3\66\5\66\u01ba\n\66\3\66\6"+ + "\66\u01bd\n\66\r\66\16\66\u01be\3\67\3\67\38\38\39\39\39\39\79\u01c9\n"+ + "9\f9\169\u01cc\139\39\59\u01cf\n9\39\59\u01d2\n9\39\39\3:\3:\3:\3:\3:"+ + "\7:\u01db\n:\f:\16:\u01de\13:\3:\3:\3:\3:\3:\3;\6;\u01e6\n;\r;\16;\u01e7"+ + "\3;\3;\4\u0133\u01dc\2<\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f"+ "\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63"+ - "\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U\2W\2Y\2[\2],_-a.c/"+ - "e\60g\61i\2k\2m\2o\62q\63s\64\3\2\20\n\2$$))^^ddhhppttvv\5\2\62;CHch\6"+ - "\2\f\f\17\17$$^^\4\2\f\f\17\17\6\2\f\f\17\17))^^\5\2\f\f\17\17$$\5\2\f"+ - "\f\17\17))\4\2BBaa\3\2bb\4\2GGgg\4\2--//\3\2\62;\4\2C\\c|\5\2\13\f\17"+ - "\17\"\"\2\u020c\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3"+ - "\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2"+ - "\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3"+ - "\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2"+ - "\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\2"+ - "9\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3"+ - "\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2"+ - "\2\2S\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2"+ - "g\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\3u\3\2\2\2\5y\3\2\2\2\7}\3"+ - "\2\2\2\t\u0080\3\2\2\2\13\u0086\3\2\2\2\r\u0089\3\2\2\2\17\u008d\3\2\2"+ - "\2\21\u0092\3\2\2\2\23\u0097\3\2\2\2\25\u009d\3\2\2\2\27\u00a5\3\2\2\2"+ - "\31\u00a9\3\2\2\2\33\u00ae\3\2\2\2\35\u00b1\3\2\2\2\37\u00b4\3\2\2\2!"+ - "\u00ba\3\2\2\2#\u00c1\3\2\2\2%\u00ca\3\2\2\2\'\u00cf\3\2\2\2)\u00d5\3"+ - "\2\2\2+\u00db\3\2\2\2-\u00e0\3\2\2\2/\u00e2\3\2\2\2\61\u00e4\3\2\2\2\63"+ - "\u00e7\3\2\2\2\65\u00ea\3\2\2\2\67\u00ec\3\2\2\29\u00ef\3\2\2\2;\u00f1"+ - "\3\2\2\2=\u00f4\3\2\2\2?\u00f6\3\2\2\2A\u00f8\3\2\2\2C\u00fa\3\2\2\2E"+ - "\u00fc\3\2\2\2G\u00fe\3\2\2\2I\u0100\3\2\2\2K\u0102\3\2\2\2M\u0104\3\2"+ - "\2\2O\u0106\3\2\2\2Q\u0108\3\2\2\2S\u010a\3\2\2\2U\u010c\3\2\2\2W\u010f"+ - "\3\2\2\2Y\u0111\3\2\2\2[\u011c\3\2\2\2]\u015e\3\2\2\2_\u0161\3\2\2\2a"+ - "\u018f\3\2\2\2c\u0193\3\2\2\2e\u019d\3\2\2\2g\u01a8\3\2\2\2i\u01b3\3\2"+ - "\2\2k\u01bc\3\2\2\2m\u01be\3\2\2\2o\u01c0\3\2\2\2q\u01d1\3\2\2\2s\u01e1"+ - "\3\2\2\2uv\7c\2\2vw\7p\2\2wx\7f\2\2x\4\3\2\2\2yz\7c\2\2z{\7p\2\2{|\7{"+ - "\2\2|\6\3\2\2\2}~\7d\2\2~\177\7{\2\2\177\b\3\2\2\2\u0080\u0081\7h\2\2"+ - "\u0081\u0082\7c\2\2\u0082\u0083\7n\2\2\u0083\u0084\7u\2\2\u0084\u0085"+ - "\7g\2\2\u0085\n\3\2\2\2\u0086\u0087\7k\2\2\u0087\u0088\7p\2\2\u0088\f"+ - "\3\2\2\2\u0089\u008a\7k\2\2\u008a\u008b\7p\2\2\u008b\u008c\7\u0080\2\2"+ - "\u008c\16\3\2\2\2\u008d\u008e\7l\2\2\u008e\u008f\7q\2\2\u008f\u0090\7"+ - "k\2\2\u0090\u0091\7p\2\2\u0091\20\3\2\2\2\u0092\u0093\7n\2\2\u0093\u0094"+ - "\7k\2\2\u0094\u0095\7m\2\2\u0095\u0096\7g\2\2\u0096\22\3\2\2\2\u0097\u0098"+ - "\7n\2\2\u0098\u0099\7k\2\2\u0099\u009a\7m\2\2\u009a\u009b\7g\2\2\u009b"+ - "\u009c\7\u0080\2\2\u009c\24\3\2\2\2\u009d\u009e\7o\2\2\u009e\u009f\7c"+ - "\2\2\u009f\u00a0\7z\2\2\u00a0\u00a1\7u\2\2\u00a1\u00a2\7r\2\2\u00a2\u00a3"+ - "\7c\2\2\u00a3\u00a4\7p\2\2\u00a4\26\3\2\2\2\u00a5\u00a6\7p\2\2\u00a6\u00a7"+ - "\7q\2\2\u00a7\u00a8\7v\2\2\u00a8\30\3\2\2\2\u00a9\u00aa\7p\2\2\u00aa\u00ab"+ - "\7w\2\2\u00ab\u00ac\7n\2\2\u00ac\u00ad\7n\2\2\u00ad\32\3\2\2\2\u00ae\u00af"+ - "\7q\2\2\u00af\u00b0\7h\2\2\u00b0\34\3\2\2\2\u00b1\u00b2\7q\2\2\u00b2\u00b3"+ - "\7t\2\2\u00b3\36\3\2\2\2\u00b4\u00b5\7t\2\2\u00b5\u00b6\7g\2\2\u00b6\u00b7"+ - "\7i\2\2\u00b7\u00b8\7g\2\2\u00b8\u00b9\7z\2\2\u00b9 \3\2\2\2\u00ba\u00bb"+ - "\7t\2\2\u00bb\u00bc\7g\2\2\u00bc\u00bd\7i\2\2\u00bd\u00be\7g\2\2\u00be"+ - "\u00bf\7z\2\2\u00bf\u00c0\7\u0080\2\2\u00c0\"\3\2\2\2\u00c1\u00c2\7u\2"+ - "\2\u00c2\u00c3\7g\2\2\u00c3\u00c4\7s\2\2\u00c4\u00c5\7w\2\2\u00c5\u00c6"+ - "\7g\2\2\u00c6\u00c7\7p\2\2\u00c7\u00c8\7e\2\2\u00c8\u00c9\7g\2\2\u00c9"+ - "$\3\2\2\2\u00ca\u00cb\7v\2\2\u00cb\u00cc\7t\2\2\u00cc\u00cd\7w\2\2\u00cd"+ - "\u00ce\7g\2\2\u00ce&\3\2\2\2\u00cf\u00d0\7w\2\2\u00d0\u00d1\7p\2\2\u00d1"+ - "\u00d2\7v\2\2\u00d2\u00d3\7k\2\2\u00d3\u00d4\7n\2\2\u00d4(\3\2\2\2\u00d5"+ - "\u00d6\7y\2\2\u00d6\u00d7\7j\2\2\u00d7\u00d8\7g\2\2\u00d8\u00d9\7t\2\2"+ - "\u00d9\u00da\7g\2\2\u00da*\3\2\2\2\u00db\u00dc\7y\2\2\u00dc\u00dd\7k\2"+ - "\2\u00dd\u00de\7v\2\2\u00de\u00df\7j\2\2\u00df,\3\2\2\2\u00e0\u00e1\7"+ - "<\2\2\u00e1.\3\2\2\2\u00e2\u00e3\7?\2\2\u00e3\60\3\2\2\2\u00e4\u00e5\7"+ - "?\2\2\u00e5\u00e6\7?\2\2\u00e6\62\3\2\2\2\u00e7\u00e8\7#\2\2\u00e8\u00e9"+ - "\7?\2\2\u00e9\64\3\2\2\2\u00ea\u00eb\7>\2\2\u00eb\66\3\2\2\2\u00ec\u00ed"+ - "\7>\2\2\u00ed\u00ee\7?\2\2\u00ee8\3\2\2\2\u00ef\u00f0\7@\2\2\u00f0:\3"+ - "\2\2\2\u00f1\u00f2\7@\2\2\u00f2\u00f3\7?\2\2\u00f3<\3\2\2\2\u00f4\u00f5"+ - "\7-\2\2\u00f5>\3\2\2\2\u00f6\u00f7\7/\2\2\u00f7@\3\2\2\2\u00f8\u00f9\7"+ - ",\2\2\u00f9B\3\2\2\2\u00fa\u00fb\7\61\2\2\u00fbD\3\2\2\2\u00fc\u00fd\7"+ - "\'\2\2\u00fdF\3\2\2\2\u00fe\u00ff\7\60\2\2\u00ffH\3\2\2\2\u0100\u0101"+ - "\7.\2\2\u0101J\3\2\2\2\u0102\u0103\7]\2\2\u0103L\3\2\2\2\u0104\u0105\7"+ - "_\2\2\u0105N\3\2\2\2\u0106\u0107\7*\2\2\u0107P\3\2\2\2\u0108\u0109\7+"+ - "\2\2\u0109R\3\2\2\2\u010a\u010b\7~\2\2\u010bT\3\2\2\2\u010c\u010d\7^\2"+ - "\2\u010d\u010e\t\2\2\2\u010eV\3\2\2\2\u010f\u0110\t\3\2\2\u0110X\3\2\2"+ - "\2\u0111\u0112\7^\2\2\u0112\u0113\7w\2\2\u0113\u0114\3\2\2\2\u0114\u0116"+ - "\7}\2\2\u0115\u0117\5W,\2\u0116\u0115\3\2\2\2\u0117\u0118\3\2\2\2\u0118"+ - "\u0116\3\2\2\2\u0118\u0119\3\2\2\2\u0119\u011a\3\2\2\2\u011a\u011b\7\177"+ - "\2\2\u011bZ\3\2\2\2\u011c\u011d\n\4\2\2\u011d\\\3\2\2\2\u011e\u0124\7"+ - "$\2\2\u011f\u0123\5U+\2\u0120\u0123\5Y-\2\u0121\u0123\5[.\2\u0122\u011f"+ - "\3\2\2\2\u0122\u0120\3\2\2\2\u0122\u0121\3\2\2\2\u0123\u0126\3\2\2\2\u0124"+ - "\u0122\3\2\2\2\u0124\u0125\3\2\2\2\u0125\u0127\3\2\2\2\u0126\u0124\3\2"+ - "\2\2\u0127\u015f\7$\2\2\u0128\u0129\7$\2\2\u0129\u012a\7$\2\2\u012a\u012b"+ - "\7$\2\2\u012b\u012f\3\2\2\2\u012c\u012e\n\5\2\2\u012d\u012c\3\2\2\2\u012e"+ - "\u0131\3\2\2\2\u012f\u0130\3\2\2\2\u012f\u012d\3\2\2\2\u0130\u0132\3\2"+ - "\2\2\u0131\u012f\3\2\2\2\u0132\u0133\7$\2\2\u0133\u0134\7$\2\2\u0134\u0135"+ - "\7$\2\2\u0135\u0137\3\2\2\2\u0136\u0138\7$\2\2\u0137\u0136\3\2\2\2\u0137"+ - "\u0138\3\2\2\2\u0138\u013a\3\2\2\2\u0139\u013b\7$\2\2\u013a\u0139\3\2"+ - "\2\2\u013a\u013b\3\2\2\2\u013b\u015f\3\2\2\2\u013c\u0142\7)\2\2\u013d"+ - "\u013e\7^\2\2\u013e\u0141\t\2\2\2\u013f\u0141\n\6\2\2\u0140\u013d\3\2"+ - "\2\2\u0140\u013f\3\2\2\2\u0141\u0144\3\2\2\2\u0142\u0140\3\2\2\2\u0142"+ - "\u0143\3\2\2\2\u0143\u0145\3\2\2\2\u0144\u0142\3\2\2\2\u0145\u015f\7)"+ - "\2\2\u0146\u0147\7A\2\2\u0147\u0148\7$\2\2\u0148\u014e\3\2\2\2\u0149\u014a"+ - "\7^\2\2\u014a\u014d\7$\2\2\u014b\u014d\n\7\2\2\u014c\u0149\3\2\2\2\u014c"+ - "\u014b\3\2\2\2\u014d\u0150\3\2\2\2\u014e\u014c\3\2\2\2\u014e\u014f\3\2"+ - "\2\2\u014f\u0151\3\2\2\2\u0150\u014e\3\2\2\2\u0151\u015f\7$\2\2\u0152"+ - "\u0153\7A\2\2\u0153\u0154\7)\2\2\u0154\u015a\3\2\2\2\u0155\u0156\7^\2"+ - "\2\u0156\u0159\7)\2\2\u0157\u0159\n\b\2\2\u0158\u0155\3\2\2\2\u0158\u0157"+ - "\3\2\2\2\u0159\u015c\3\2\2\2\u015a\u0158\3\2\2\2\u015a\u015b\3\2\2\2\u015b"+ - "\u015d\3\2\2\2\u015c\u015a\3\2\2\2\u015d\u015f\7)\2\2\u015e\u011e\3\2"+ - "\2\2\u015e\u0128\3\2\2\2\u015e\u013c\3\2\2\2\u015e\u0146\3\2\2\2\u015e"+ - "\u0152\3\2\2\2\u015f^\3\2\2\2\u0160\u0162\5k\66\2\u0161\u0160\3\2\2\2"+ - "\u0162\u0163\3\2\2\2\u0163\u0161\3\2\2\2\u0163\u0164\3\2\2\2\u0164`\3"+ - "\2\2\2\u0165\u0167\5k\66\2\u0166\u0165\3\2\2\2\u0167\u0168\3\2\2\2\u0168"+ - "\u0166\3\2\2\2\u0168\u0169\3\2\2\2\u0169\u016a\3\2\2\2\u016a\u016e\5G"+ - "$\2\u016b\u016d\5k\66\2\u016c\u016b\3\2\2\2\u016d\u0170\3\2\2\2\u016e"+ - "\u016c\3\2\2\2\u016e\u016f\3\2\2\2\u016f\u0190\3\2\2\2\u0170\u016e\3\2"+ - "\2\2\u0171\u0173\5G$\2\u0172\u0174\5k\66\2\u0173\u0172\3\2\2\2\u0174\u0175"+ - "\3\2\2\2\u0175\u0173\3\2\2\2\u0175\u0176\3\2\2\2\u0176\u0190\3\2\2\2\u0177"+ - "\u0179\5k\66\2\u0178\u0177\3\2\2\2\u0179\u017a\3\2\2\2\u017a\u0178\3\2"+ - "\2\2\u017a\u017b\3\2\2\2\u017b\u0183\3\2\2\2\u017c\u0180\5G$\2\u017d\u017f"+ - "\5k\66\2\u017e\u017d\3\2\2\2\u017f\u0182\3\2\2\2\u0180\u017e\3\2\2\2\u0180"+ - "\u0181\3\2\2\2\u0181\u0184\3\2\2\2\u0182\u0180\3\2\2\2\u0183\u017c\3\2"+ - "\2\2\u0183\u0184\3\2\2\2\u0184\u0185\3\2\2\2\u0185\u0186\5i\65\2\u0186"+ - "\u0190\3\2\2\2\u0187\u0189\5G$\2\u0188\u018a\5k\66\2\u0189\u0188\3\2\2"+ - "\2\u018a\u018b\3\2\2\2\u018b\u0189\3\2\2\2\u018b\u018c\3\2\2\2\u018c\u018d"+ - "\3\2\2\2\u018d\u018e\5i\65\2\u018e\u0190\3\2\2\2\u018f\u0166\3\2\2\2\u018f"+ - "\u0171\3\2\2\2\u018f\u0178\3\2\2\2\u018f\u0187\3\2\2\2\u0190b\3\2\2\2"+ - "\u0191\u0194\5m\67\2\u0192\u0194\t\t\2\2\u0193\u0191\3\2\2\2\u0193\u0192"+ - "\3\2\2\2\u0194\u019a\3\2\2\2\u0195\u0199\5m\67\2\u0196\u0199\5k\66\2\u0197"+ - "\u0199\7a\2\2\u0198\u0195\3\2\2\2\u0198\u0196\3\2\2\2\u0198\u0197\3\2"+ - "\2\2\u0199\u019c\3\2\2\2\u019a\u0198\3\2\2\2\u019a\u019b\3\2\2\2\u019b"+ - "d\3\2\2\2\u019c\u019a\3\2\2\2\u019d\u01a3\7b\2\2\u019e\u01a2\n\n\2\2\u019f"+ - "\u01a0\7b\2\2\u01a0\u01a2\7b\2\2\u01a1\u019e\3\2\2\2\u01a1\u019f\3\2\2"+ - "\2\u01a2\u01a5\3\2\2\2\u01a3\u01a1\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4\u01a6"+ - "\3\2\2\2\u01a5\u01a3\3\2\2\2\u01a6\u01a7\7b\2\2\u01a7f\3\2\2\2\u01a8\u01ae"+ - "\5m\67\2\u01a9\u01ad\5m\67\2\u01aa\u01ad\5k\66\2\u01ab\u01ad\7a\2\2\u01ac"+ - "\u01a9\3\2\2\2\u01ac\u01aa\3\2\2\2\u01ac\u01ab\3\2\2\2\u01ad\u01b0\3\2"+ - "\2\2\u01ae\u01ac\3\2\2\2\u01ae\u01af\3\2\2\2\u01af\u01b1\3\2\2\2\u01b0"+ - "\u01ae\3\2\2\2\u01b1\u01b2\7\u0080\2\2\u01b2h\3\2\2\2\u01b3\u01b5\t\13"+ - "\2\2\u01b4\u01b6\t\f\2\2\u01b5\u01b4\3\2\2\2\u01b5\u01b6\3\2\2\2\u01b6"+ - "\u01b8\3\2\2\2\u01b7\u01b9\5k\66\2\u01b8\u01b7\3\2\2\2\u01b9\u01ba\3\2"+ - "\2\2\u01ba\u01b8\3\2\2\2\u01ba\u01bb\3\2\2\2\u01bbj\3\2\2\2\u01bc\u01bd"+ - "\t\r\2\2\u01bdl\3\2\2\2\u01be\u01bf\t\16\2\2\u01bfn\3\2\2\2\u01c0\u01c1"+ - "\7\61\2\2\u01c1\u01c2\7\61\2\2\u01c2\u01c6\3\2\2\2\u01c3\u01c5\n\5\2\2"+ - "\u01c4\u01c3\3\2\2\2\u01c5\u01c8\3\2\2\2\u01c6\u01c4\3\2\2\2\u01c6\u01c7"+ - "\3\2\2\2\u01c7\u01ca\3\2\2\2\u01c8\u01c6\3\2\2\2\u01c9\u01cb\7\17\2\2"+ - "\u01ca\u01c9\3\2\2\2\u01ca\u01cb\3\2\2\2\u01cb\u01cd\3\2\2\2\u01cc\u01ce"+ - "\7\f\2\2\u01cd\u01cc\3\2\2\2\u01cd\u01ce\3\2\2\2\u01ce\u01cf\3\2\2\2\u01cf"+ - "\u01d0\b8\2\2\u01d0p\3\2\2\2\u01d1\u01d2\7\61\2\2\u01d2\u01d3\7,\2\2\u01d3"+ - "\u01d8\3\2\2\2\u01d4\u01d7\5q9\2\u01d5\u01d7\13\2\2\2\u01d6\u01d4\3\2"+ - "\2\2\u01d6\u01d5\3\2\2\2\u01d7\u01da\3\2\2\2\u01d8\u01d9\3\2\2\2\u01d8"+ - "\u01d6\3\2\2\2\u01d9\u01db\3\2\2\2\u01da\u01d8\3\2\2\2\u01db\u01dc\7,"+ - "\2\2\u01dc\u01dd\7\61\2\2\u01dd\u01de\3\2\2\2\u01de\u01df\b9\2\2\u01df"+ - "r\3\2\2\2\u01e0\u01e2\t\17\2\2\u01e1\u01e0\3\2\2\2\u01e2\u01e3\3\2\2\2"+ - "\u01e3\u01e1\3\2\2\2\u01e3\u01e4\3\2\2\2\u01e4\u01e5\3\2\2\2\u01e5\u01e6"+ - "\b:\2\2\u01e6t\3\2\2\2(\2\u0118\u0122\u0124\u012f\u0137\u013a\u0140\u0142"+ - "\u014c\u014e\u0158\u015a\u015e\u0163\u0168\u016e\u0175\u017a\u0180\u0183"+ - "\u018b\u018f\u0193\u0198\u019a\u01a1\u01a3\u01ac\u01ae\u01b5\u01ba\u01c6"+ - "\u01ca\u01cd\u01d6\u01d8\u01e3\3\2\3\2"; + "\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W\2Y\2[\2]\2_-a.c/"+ + "e\60g\61i\62k\2m\2o\2q\63s\64u\65\3\2\20\n\2$$))^^ddhhppttvv\5\2\62;C"+ + "Hch\6\2\f\f\17\17$$^^\4\2\f\f\17\17\6\2\f\f\17\17))^^\5\2\f\f\17\17$$"+ + "\5\2\f\f\17\17))\4\2BBaa\3\2bb\4\2GGgg\4\2--//\3\2\62;\4\2C\\c|\5\2\13"+ + "\f\17\17\"\"\2\u0210\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2"+ + "\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3"+ + "\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2"+ + "\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2"+ + "\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2"+ + "\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2"+ + "\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q"+ + "\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2"+ + "\2\2\2g\3\2\2\2\2i\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\3w\3\2\2\2"+ + "\5{\3\2\2\2\7\177\3\2\2\2\t\u0082\3\2\2\2\13\u0088\3\2\2\2\r\u008b\3\2"+ + "\2\2\17\u008f\3\2\2\2\21\u0094\3\2\2\2\23\u0099\3\2\2\2\25\u009f\3\2\2"+ + "\2\27\u00a7\3\2\2\2\31\u00ab\3\2\2\2\33\u00b0\3\2\2\2\35\u00b3\3\2\2\2"+ + "\37\u00b6\3\2\2\2!\u00bc\3\2\2\2#\u00c3\3\2\2\2%\u00cc\3\2\2\2\'\u00d1"+ + "\3\2\2\2)\u00d7\3\2\2\2+\u00dd\3\2\2\2-\u00e2\3\2\2\2/\u00e4\3\2\2\2\61"+ + "\u00e6\3\2\2\2\63\u00e9\3\2\2\2\65\u00ec\3\2\2\2\67\u00ee\3\2\2\29\u00f1"+ + "\3\2\2\2;\u00f3\3\2\2\2=\u00f6\3\2\2\2?\u00f8\3\2\2\2A\u00fa\3\2\2\2C"+ + "\u00fc\3\2\2\2E\u00fe\3\2\2\2G\u0100\3\2\2\2I\u0102\3\2\2\2K\u0104\3\2"+ + "\2\2M\u0106\3\2\2\2O\u0108\3\2\2\2Q\u010a\3\2\2\2S\u010c\3\2\2\2U\u010e"+ + "\3\2\2\2W\u0110\3\2\2\2Y\u0113\3\2\2\2[\u0115\3\2\2\2]\u0120\3\2\2\2_"+ + "\u0162\3\2\2\2a\u0165\3\2\2\2c\u0193\3\2\2\2e\u0197\3\2\2\2g\u01a1\3\2"+ + "\2\2i\u01ac\3\2\2\2k\u01b7\3\2\2\2m\u01c0\3\2\2\2o\u01c2\3\2\2\2q\u01c4"+ + "\3\2\2\2s\u01d5\3\2\2\2u\u01e5\3\2\2\2wx\7c\2\2xy\7p\2\2yz\7f\2\2z\4\3"+ + "\2\2\2{|\7c\2\2|}\7p\2\2}~\7{\2\2~\6\3\2\2\2\177\u0080\7d\2\2\u0080\u0081"+ + "\7{\2\2\u0081\b\3\2\2\2\u0082\u0083\7h\2\2\u0083\u0084\7c\2\2\u0084\u0085"+ + "\7n\2\2\u0085\u0086\7u\2\2\u0086\u0087\7g\2\2\u0087\n\3\2\2\2\u0088\u0089"+ + "\7k\2\2\u0089\u008a\7p\2\2\u008a\f\3\2\2\2\u008b\u008c\7k\2\2\u008c\u008d"+ + "\7p\2\2\u008d\u008e\7\u0080\2\2\u008e\16\3\2\2\2\u008f\u0090\7l\2\2\u0090"+ + "\u0091\7q\2\2\u0091\u0092\7k\2\2\u0092\u0093\7p\2\2\u0093\20\3\2\2\2\u0094"+ + "\u0095\7n\2\2\u0095\u0096\7k\2\2\u0096\u0097\7m\2\2\u0097\u0098\7g\2\2"+ + "\u0098\22\3\2\2\2\u0099\u009a\7n\2\2\u009a\u009b\7k\2\2\u009b\u009c\7"+ + "m\2\2\u009c\u009d\7g\2\2\u009d\u009e\7\u0080\2\2\u009e\24\3\2\2\2\u009f"+ + "\u00a0\7o\2\2\u00a0\u00a1\7c\2\2\u00a1\u00a2\7z\2\2\u00a2\u00a3\7u\2\2"+ + "\u00a3\u00a4\7r\2\2\u00a4\u00a5\7c\2\2\u00a5\u00a6\7p\2\2\u00a6\26\3\2"+ + "\2\2\u00a7\u00a8\7p\2\2\u00a8\u00a9\7q\2\2\u00a9\u00aa\7v\2\2\u00aa\30"+ + "\3\2\2\2\u00ab\u00ac\7p\2\2\u00ac\u00ad\7w\2\2\u00ad\u00ae\7n\2\2\u00ae"+ + "\u00af\7n\2\2\u00af\32\3\2\2\2\u00b0\u00b1\7q\2\2\u00b1\u00b2\7h\2\2\u00b2"+ + "\34\3\2\2\2\u00b3\u00b4\7q\2\2\u00b4\u00b5\7t\2\2\u00b5\36\3\2\2\2\u00b6"+ + "\u00b7\7t\2\2\u00b7\u00b8\7g\2\2\u00b8\u00b9\7i\2\2\u00b9\u00ba\7g\2\2"+ + "\u00ba\u00bb\7z\2\2\u00bb \3\2\2\2\u00bc\u00bd\7t\2\2\u00bd\u00be\7g\2"+ + "\2\u00be\u00bf\7i\2\2\u00bf\u00c0\7g\2\2\u00c0\u00c1\7z\2\2\u00c1\u00c2"+ + "\7\u0080\2\2\u00c2\"\3\2\2\2\u00c3\u00c4\7u\2\2\u00c4\u00c5\7g\2\2\u00c5"+ + "\u00c6\7s\2\2\u00c6\u00c7\7w\2\2\u00c7\u00c8\7g\2\2\u00c8\u00c9\7p\2\2"+ + "\u00c9\u00ca\7e\2\2\u00ca\u00cb\7g\2\2\u00cb$\3\2\2\2\u00cc\u00cd\7v\2"+ + "\2\u00cd\u00ce\7t\2\2\u00ce\u00cf\7w\2\2\u00cf\u00d0\7g\2\2\u00d0&\3\2"+ + "\2\2\u00d1\u00d2\7w\2\2\u00d2\u00d3\7p\2\2\u00d3\u00d4\7v\2\2\u00d4\u00d5"+ + "\7k\2\2\u00d5\u00d6\7n\2\2\u00d6(\3\2\2\2\u00d7\u00d8\7y\2\2\u00d8\u00d9"+ + "\7j\2\2\u00d9\u00da\7g\2\2\u00da\u00db\7t\2\2\u00db\u00dc\7g\2\2\u00dc"+ + "*\3\2\2\2\u00dd\u00de\7y\2\2\u00de\u00df\7k\2\2\u00df\u00e0\7v\2\2\u00e0"+ + "\u00e1\7j\2\2\u00e1,\3\2\2\2\u00e2\u00e3\7<\2\2\u00e3.\3\2\2\2\u00e4\u00e5"+ + "\7?\2\2\u00e5\60\3\2\2\2\u00e6\u00e7\7?\2\2\u00e7\u00e8\7?\2\2\u00e8\62"+ + "\3\2\2\2\u00e9\u00ea\7#\2\2\u00ea\u00eb\7?\2\2\u00eb\64\3\2\2\2\u00ec"+ + "\u00ed\7>\2\2\u00ed\66\3\2\2\2\u00ee\u00ef\7>\2\2\u00ef\u00f0\7?\2\2\u00f0"+ + "8\3\2\2\2\u00f1\u00f2\7@\2\2\u00f2:\3\2\2\2\u00f3\u00f4\7@\2\2\u00f4\u00f5"+ + "\7?\2\2\u00f5<\3\2\2\2\u00f6\u00f7\7-\2\2\u00f7>\3\2\2\2\u00f8\u00f9\7"+ + "/\2\2\u00f9@\3\2\2\2\u00fa\u00fb\7,\2\2\u00fbB\3\2\2\2\u00fc\u00fd\7\61"+ + "\2\2\u00fdD\3\2\2\2\u00fe\u00ff\7\'\2\2\u00ffF\3\2\2\2\u0100\u0101\7\60"+ + "\2\2\u0101H\3\2\2\2\u0102\u0103\7.\2\2\u0103J\3\2\2\2\u0104\u0105\7]\2"+ + "\2\u0105L\3\2\2\2\u0106\u0107\7_\2\2\u0107N\3\2\2\2\u0108\u0109\7*\2\2"+ + "\u0109P\3\2\2\2\u010a\u010b\7+\2\2\u010bR\3\2\2\2\u010c\u010d\7~\2\2\u010d"+ + "T\3\2\2\2\u010e\u010f\7A\2\2\u010fV\3\2\2\2\u0110\u0111\7^\2\2\u0111\u0112"+ + "\t\2\2\2\u0112X\3\2\2\2\u0113\u0114\t\3\2\2\u0114Z\3\2\2\2\u0115\u0116"+ + "\7^\2\2\u0116\u0117\7w\2\2\u0117\u0118\3\2\2\2\u0118\u011a\7}\2\2\u0119"+ + "\u011b\5Y-\2\u011a\u0119\3\2\2\2\u011b\u011c\3\2\2\2\u011c\u011a\3\2\2"+ + "\2\u011c\u011d\3\2\2\2\u011d\u011e\3\2\2\2\u011e\u011f\7\177\2\2\u011f"+ + "\\\3\2\2\2\u0120\u0121\n\4\2\2\u0121^\3\2\2\2\u0122\u0128\7$\2\2\u0123"+ + "\u0127\5W,\2\u0124\u0127\5[.\2\u0125\u0127\5]/\2\u0126\u0123\3\2\2\2\u0126"+ + "\u0124\3\2\2\2\u0126\u0125\3\2\2\2\u0127\u012a\3\2\2\2\u0128\u0126\3\2"+ + "\2\2\u0128\u0129\3\2\2\2\u0129\u012b\3\2\2\2\u012a\u0128\3\2\2\2\u012b"+ + "\u0163\7$\2\2\u012c\u012d\7$\2\2\u012d\u012e\7$\2\2\u012e\u012f\7$\2\2"+ + "\u012f\u0133\3\2\2\2\u0130\u0132\n\5\2\2\u0131\u0130\3\2\2\2\u0132\u0135"+ + "\3\2\2\2\u0133\u0134\3\2\2\2\u0133\u0131\3\2\2\2\u0134\u0136\3\2\2\2\u0135"+ + "\u0133\3\2\2\2\u0136\u0137\7$\2\2\u0137\u0138\7$\2\2\u0138\u0139\7$\2"+ + "\2\u0139\u013b\3\2\2\2\u013a\u013c\7$\2\2\u013b\u013a\3\2\2\2\u013b\u013c"+ + "\3\2\2\2\u013c\u013e\3\2\2\2\u013d\u013f\7$\2\2\u013e\u013d\3\2\2\2\u013e"+ + "\u013f\3\2\2\2\u013f\u0163\3\2\2\2\u0140\u0146\7)\2\2\u0141\u0142\7^\2"+ + "\2\u0142\u0145\t\2\2\2\u0143\u0145\n\6\2\2\u0144\u0141\3\2\2\2\u0144\u0143"+ + "\3\2\2\2\u0145\u0148\3\2\2\2\u0146\u0144\3\2\2\2\u0146\u0147\3\2\2\2\u0147"+ + "\u0149\3\2\2\2\u0148\u0146\3\2\2\2\u0149\u0163\7)\2\2\u014a\u014b\7A\2"+ + "\2\u014b\u014c\7$\2\2\u014c\u0152\3\2\2\2\u014d\u014e\7^\2\2\u014e\u0151"+ + "\7$\2\2\u014f\u0151\n\7\2\2\u0150\u014d\3\2\2\2\u0150\u014f\3\2\2\2\u0151"+ + "\u0154\3\2\2\2\u0152\u0150\3\2\2\2\u0152\u0153\3\2\2\2\u0153\u0155\3\2"+ + "\2\2\u0154\u0152\3\2\2\2\u0155\u0163\7$\2\2\u0156\u0157\7A\2\2\u0157\u0158"+ + "\7)\2\2\u0158\u015e\3\2\2\2\u0159\u015a\7^\2\2\u015a\u015d\7)\2\2\u015b"+ + "\u015d\n\b\2\2\u015c\u0159\3\2\2\2\u015c\u015b\3\2\2\2\u015d\u0160\3\2"+ + "\2\2\u015e\u015c\3\2\2\2\u015e\u015f\3\2\2\2\u015f\u0161\3\2\2\2\u0160"+ + "\u015e\3\2\2\2\u0161\u0163\7)\2\2\u0162\u0122\3\2\2\2\u0162\u012c\3\2"+ + "\2\2\u0162\u0140\3\2\2\2\u0162\u014a\3\2\2\2\u0162\u0156\3\2\2\2\u0163"+ + "`\3\2\2\2\u0164\u0166\5m\67\2\u0165\u0164\3\2\2\2\u0166\u0167\3\2\2\2"+ + "\u0167\u0165\3\2\2\2\u0167\u0168\3\2\2\2\u0168b\3\2\2\2\u0169\u016b\5"+ + "m\67\2\u016a\u0169\3\2\2\2\u016b\u016c\3\2\2\2\u016c\u016a\3\2\2\2\u016c"+ + "\u016d\3\2\2\2\u016d\u016e\3\2\2\2\u016e\u0172\5G$\2\u016f\u0171\5m\67"+ + "\2\u0170\u016f\3\2\2\2\u0171\u0174\3\2\2\2\u0172\u0170\3\2\2\2\u0172\u0173"+ + "\3\2\2\2\u0173\u0194\3\2\2\2\u0174\u0172\3\2\2\2\u0175\u0177\5G$\2\u0176"+ + "\u0178\5m\67\2\u0177\u0176\3\2\2\2\u0178\u0179\3\2\2\2\u0179\u0177\3\2"+ + "\2\2\u0179\u017a\3\2\2\2\u017a\u0194\3\2\2\2\u017b\u017d\5m\67\2\u017c"+ + "\u017b\3\2\2\2\u017d\u017e\3\2\2\2\u017e\u017c\3\2\2\2\u017e\u017f\3\2"+ + "\2\2\u017f\u0187\3\2\2\2\u0180\u0184\5G$\2\u0181\u0183\5m\67\2\u0182\u0181"+ + "\3\2\2\2\u0183\u0186\3\2\2\2\u0184\u0182\3\2\2\2\u0184\u0185\3\2\2\2\u0185"+ + "\u0188\3\2\2\2\u0186\u0184\3\2\2\2\u0187\u0180\3\2\2\2\u0187\u0188\3\2"+ + "\2\2\u0188\u0189\3\2\2\2\u0189\u018a\5k\66\2\u018a\u0194\3\2\2\2\u018b"+ + "\u018d\5G$\2\u018c\u018e\5m\67\2\u018d\u018c\3\2\2\2\u018e\u018f\3\2\2"+ + "\2\u018f\u018d\3\2\2\2\u018f\u0190\3\2\2\2\u0190\u0191\3\2\2\2\u0191\u0192"+ + "\5k\66\2\u0192\u0194\3\2\2\2\u0193\u016a\3\2\2\2\u0193\u0175\3\2\2\2\u0193"+ + "\u017c\3\2\2\2\u0193\u018b\3\2\2\2\u0194d\3\2\2\2\u0195\u0198\5o8\2\u0196"+ + "\u0198\t\t\2\2\u0197\u0195\3\2\2\2\u0197\u0196\3\2\2\2\u0198\u019e\3\2"+ + "\2\2\u0199\u019d\5o8\2\u019a\u019d\5m\67\2\u019b\u019d\7a\2\2\u019c\u0199"+ + "\3\2\2\2\u019c\u019a\3\2\2\2\u019c\u019b\3\2\2\2\u019d\u01a0\3\2\2\2\u019e"+ + "\u019c\3\2\2\2\u019e\u019f\3\2\2\2\u019ff\3\2\2\2\u01a0\u019e\3\2\2\2"+ + "\u01a1\u01a7\7b\2\2\u01a2\u01a6\n\n\2\2\u01a3\u01a4\7b\2\2\u01a4\u01a6"+ + "\7b\2\2\u01a5\u01a2\3\2\2\2\u01a5\u01a3\3\2\2\2\u01a6\u01a9\3\2\2\2\u01a7"+ + "\u01a5\3\2\2\2\u01a7\u01a8\3\2\2\2\u01a8\u01aa\3\2\2\2\u01a9\u01a7\3\2"+ + "\2\2\u01aa\u01ab\7b\2\2\u01abh\3\2\2\2\u01ac\u01b2\5o8\2\u01ad\u01b1\5"+ + "o8\2\u01ae\u01b1\5m\67\2\u01af\u01b1\7a\2\2\u01b0\u01ad\3\2\2\2\u01b0"+ + "\u01ae\3\2\2\2\u01b0\u01af\3\2\2\2\u01b1\u01b4\3\2\2\2\u01b2\u01b0\3\2"+ + "\2\2\u01b2\u01b3\3\2\2\2\u01b3\u01b5\3\2\2\2\u01b4\u01b2\3\2\2\2\u01b5"+ + "\u01b6\7\u0080\2\2\u01b6j\3\2\2\2\u01b7\u01b9\t\13\2\2\u01b8\u01ba\t\f"+ + "\2\2\u01b9\u01b8\3\2\2\2\u01b9\u01ba\3\2\2\2\u01ba\u01bc\3\2\2\2\u01bb"+ + "\u01bd\5m\67\2\u01bc\u01bb\3\2\2\2\u01bd\u01be\3\2\2\2\u01be\u01bc\3\2"+ + "\2\2\u01be\u01bf\3\2\2\2\u01bfl\3\2\2\2\u01c0\u01c1\t\r\2\2\u01c1n\3\2"+ + "\2\2\u01c2\u01c3\t\16\2\2\u01c3p\3\2\2\2\u01c4\u01c5\7\61\2\2\u01c5\u01c6"+ + "\7\61\2\2\u01c6\u01ca\3\2\2\2\u01c7\u01c9\n\5\2\2\u01c8\u01c7\3\2\2\2"+ + "\u01c9\u01cc\3\2\2\2\u01ca\u01c8\3\2\2\2\u01ca\u01cb\3\2\2\2\u01cb\u01ce"+ + "\3\2\2\2\u01cc\u01ca\3\2\2\2\u01cd\u01cf\7\17\2\2\u01ce\u01cd\3\2\2\2"+ + "\u01ce\u01cf\3\2\2\2\u01cf\u01d1\3\2\2\2\u01d0\u01d2\7\f\2\2\u01d1\u01d0"+ + "\3\2\2\2\u01d1\u01d2\3\2\2\2\u01d2\u01d3\3\2\2\2\u01d3\u01d4\b9\2\2\u01d4"+ + "r\3\2\2\2\u01d5\u01d6\7\61\2\2\u01d6\u01d7\7,\2\2\u01d7\u01dc\3\2\2\2"+ + "\u01d8\u01db\5s:\2\u01d9\u01db\13\2\2\2\u01da\u01d8\3\2\2\2\u01da\u01d9"+ + "\3\2\2\2\u01db\u01de\3\2\2\2\u01dc\u01dd\3\2\2\2\u01dc\u01da\3\2\2\2\u01dd"+ + "\u01df\3\2\2\2\u01de\u01dc\3\2\2\2\u01df\u01e0\7,\2\2\u01e0\u01e1\7\61"+ + "\2\2\u01e1\u01e2\3\2\2\2\u01e2\u01e3\b:\2\2\u01e3t\3\2\2\2\u01e4\u01e6"+ + "\t\17\2\2\u01e5\u01e4\3\2\2\2\u01e6\u01e7\3\2\2\2\u01e7\u01e5\3\2\2\2"+ + "\u01e7\u01e8\3\2\2\2\u01e8\u01e9\3\2\2\2\u01e9\u01ea\b;\2\2\u01eav\3\2"+ + "\2\2(\2\u011c\u0126\u0128\u0133\u013b\u013e\u0144\u0146\u0150\u0152\u015c"+ + "\u015e\u0162\u0167\u016c\u0172\u0179\u017e\u0184\u0187\u018f\u0193\u0197"+ + "\u019c\u019e\u01a5\u01a7\u01b0\u01b2\u01b9\u01be\u01ca\u01ce\u01d1\u01da"+ + "\u01dc\u01e7\3\2\3\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseParser.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseParser.java index 0043df2122746..bc560aaa5a95b 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseParser.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlBaseParser.java @@ -22,8 +22,9 @@ class EqlBaseParser extends Parser { SEQUENCE=17, TRUE=18, UNTIL=19, WHERE=20, WITH=21, SEQ=22, ASGN=23, EQ=24, NEQ=25, LT=26, LTE=27, GT=28, GTE=29, PLUS=30, MINUS=31, ASTERISK=32, SLASH=33, PERCENT=34, DOT=35, COMMA=36, LB=37, RB=38, LP=39, RP=40, PIPE=41, - STRING=42, INTEGER_VALUE=43, DECIMAL_VALUE=44, IDENTIFIER=45, QUOTED_IDENTIFIER=46, - TILDE_IDENTIFIER=47, LINE_COMMENT=48, BRACKETED_COMMENT=49, WS=50; + OPTIONAL=42, STRING=43, INTEGER_VALUE=44, DECIMAL_VALUE=45, IDENTIFIER=46, + QUOTED_IDENTIFIER=47, TILDE_IDENTIFIER=48, LINE_COMMENT=49, BRACKETED_COMMENT=50, + WS=51; public static final int RULE_singleStatement = 0, RULE_singleExpression = 1, RULE_statement = 2, RULE_query = 3, RULE_sequenceParams = 4, RULE_sequence = 5, RULE_join = 6, @@ -53,7 +54,7 @@ private static String[] makeLiteralNames() { "'regex'", "'regex~'", "'sequence'", "'true'", "'until'", "'where'", "'with'", "':'", "'='", "'=='", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", "'.'", "','", "'['", "']'", "'('", - "')'", "'|'" + "')'", "'|'", "'?'" }; } private static final String[] _LITERAL_NAMES = makeLiteralNames(); @@ -63,9 +64,9 @@ private static String[] makeSymbolicNames() { "LIKE_INSENSITIVE", "MAXSPAN", "NOT", "NULL", "OF", "OR", "REGEX", "REGEX_INSENSITIVE", "SEQUENCE", "TRUE", "UNTIL", "WHERE", "WITH", "SEQ", "ASGN", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", - "DOT", "COMMA", "LB", "RB", "LP", "RP", "PIPE", "STRING", "INTEGER_VALUE", - "DECIMAL_VALUE", "IDENTIFIER", "QUOTED_IDENTIFIER", "TILDE_IDENTIFIER", - "LINE_COMMENT", "BRACKETED_COMMENT", "WS" + "DOT", "COMMA", "LB", "RB", "LP", "RP", "PIPE", "OPTIONAL", "STRING", + "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "QUOTED_IDENTIFIER", + "TILDE_IDENTIFIER", "LINE_COMMENT", "BRACKETED_COMMENT", "WS" }; } private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); @@ -672,7 +673,7 @@ public final PipeContext pipe() throws RecognitionException { setState(129); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FALSE) | (1L << NOT) | (1L << NULL) | (1L << TRUE) | (1L << PLUS) | (1L << MINUS) | (1L << LP) | (1L << STRING) | (1L << INTEGER_VALUE) | (1L << DECIMAL_VALUE) | (1L << IDENTIFIER) | (1L << QUOTED_IDENTIFIER) | (1L << TILDE_IDENTIFIER))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FALSE) | (1L << NOT) | (1L << NULL) | (1L << TRUE) | (1L << PLUS) | (1L << MINUS) | (1L << LP) | (1L << OPTIONAL) | (1L << STRING) | (1L << INTEGER_VALUE) | (1L << DECIMAL_VALUE) | (1L << IDENTIFIER) | (1L << QUOTED_IDENTIFIER) | (1L << TILDE_IDENTIFIER))) != 0)) { { setState(121); booleanExpression(0); @@ -1551,6 +1552,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE case NULL: case TRUE: case LP: + case OPTIONAL: case STRING: case INTEGER_VALUE: case DECIMAL_VALUE: @@ -2044,7 +2046,7 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx setState(268); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FALSE) | (1L << NOT) | (1L << NULL) | (1L << TRUE) | (1L << PLUS) | (1L << MINUS) | (1L << LP) | (1L << STRING) | (1L << INTEGER_VALUE) | (1L << DECIMAL_VALUE) | (1L << IDENTIFIER) | (1L << QUOTED_IDENTIFIER) | (1L << TILDE_IDENTIFIER))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FALSE) | (1L << NOT) | (1L << NULL) | (1L << TRUE) | (1L << PLUS) | (1L << MINUS) | (1L << LP) | (1L << OPTIONAL) | (1L << STRING) | (1L << INTEGER_VALUE) | (1L << DECIMAL_VALUE) | (1L << IDENTIFIER) | (1L << QUOTED_IDENTIFIER) | (1L << TILDE_IDENTIFIER))) != 0)) { { setState(260); expression(); @@ -2391,6 +2393,7 @@ public List identifier() { public IdentifierContext identifier(int i) { return getRuleContext(IdentifierContext.class,i); } + public TerminalNode OPTIONAL() { return getToken(EqlBaseParser.OPTIONAL, 0); } public List DOT() { return getTokens(EqlBaseParser.DOT); } public TerminalNode DOT(int i) { return getToken(EqlBaseParser.DOT, i); @@ -2434,44 +2437,54 @@ public final QualifiedNameContext qualifiedName() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(284); + setState(285); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==OPTIONAL) { + { + setState(284); + match(OPTIONAL); + } + } + + setState(287); identifier(); - setState(296); + setState(299); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,35,_ctx); + _alt = getInterpreter().adaptivePredict(_input,36,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { - setState(294); + setState(297); _errHandler.sync(this); switch (_input.LA(1)) { case DOT: { - setState(285); + setState(288); match(DOT); - setState(286); + setState(289); identifier(); } break; case LB: { - setState(287); + setState(290); match(LB); - setState(289); + setState(292); _errHandler.sync(this); _la = _input.LA(1); do { { { - setState(288); + setState(291); match(INTEGER_VALUE); } } - setState(291); + setState(294); _errHandler.sync(this); _la = _input.LA(1); } while ( _la==INTEGER_VALUE ); - setState(293); + setState(296); match(RB); } break; @@ -2480,9 +2493,9 @@ public final QualifiedNameContext qualifiedName() throws RecognitionException { } } } - setState(298); + setState(301); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,35,_ctx); + _alt = getInterpreter().adaptivePredict(_input,36,_ctx); } } } @@ -2526,7 +2539,7 @@ public final IdentifierContext identifier() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(299); + setState(302); _la = _input.LA(1); if ( !(_la==IDENTIFIER || _la==QUOTED_IDENTIFIER) ) { _errHandler.recoverInline(this); @@ -2581,14 +2594,14 @@ public final TimeUnitContext timeUnit() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(301); + setState(304); number(); - setState(303); + setState(306); _errHandler.sync(this); _la = _input.LA(1); if (_la==IDENTIFIER) { { - setState(302); + setState(305); ((TimeUnitContext)_localctx).unit = match(IDENTIFIER); } } @@ -2656,14 +2669,14 @@ public final NumberContext number() throws RecognitionException { NumberContext _localctx = new NumberContext(_ctx, getState()); enterRule(_localctx, 56, RULE_number); try { - setState(307); + setState(310); _errHandler.sync(this); switch (_input.LA(1)) { case DECIMAL_VALUE: _localctx = new DecimalLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(305); + setState(308); match(DECIMAL_VALUE); } break; @@ -2671,7 +2684,7 @@ public final NumberContext number() throws RecognitionException { _localctx = new IntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(306); + setState(309); match(INTEGER_VALUE); } break; @@ -2717,7 +2730,7 @@ public final StringContext string() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(309); + setState(312); match(STRING); } } @@ -2761,7 +2774,7 @@ public final EventValueContext eventValue() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(311); + setState(314); _la = _input.LA(1); if ( !(_la==STRING || _la==IDENTIFIER) ) { _errHandler.recoverInline(this); @@ -2813,7 +2826,7 @@ private boolean operatorExpression_sempred(OperatorExpressionContext _localctx, } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\64\u013c\4\2\t\2"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\65\u013f\4\2\t\2"+ "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -2835,94 +2848,96 @@ private boolean operatorExpression_sempred(OperatorExpressionContext _localctx, "\24\3\24\3\24\5\24\u00fa\n\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\5\25"+ "\u0103\n\25\3\26\3\26\3\26\3\26\3\26\7\26\u010a\n\26\f\26\16\26\u010d"+ "\13\26\5\26\u010f\n\26\3\26\3\26\3\27\3\27\3\30\3\30\3\30\3\30\5\30\u0119"+ - "\n\30\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\33\3\33\6\33\u0124\n\33\r\33"+ - "\16\33\u0125\3\33\7\33\u0129\n\33\f\33\16\33\u012c\13\33\3\34\3\34\3\35"+ - "\3\35\5\35\u0132\n\35\3\36\3\36\5\36\u0136\n\36\3\37\3\37\3 \3 \3 \2\4"+ - " $!\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>\2"+ - "\13\3\2 !\3\2\"$\3\2\7\b\5\2\n\13\21\22\30\30\4\2//\61\61\3\2\32\37\4"+ - "\2\6\6\24\24\3\2/\60\4\2,,//\2\u014a\2@\3\2\2\2\4C\3\2\2\2\6F\3\2\2\2"+ - "\bP\3\2\2\2\nR\3\2\2\2\fW\3\2\2\2\16k\3\2\2\2\20y\3\2\2\2\22\u0085\3\2"+ - "\2\2\24\u008e\3\2\2\2\26\u0092\3\2\2\2\30\u009e\3\2\2\2\32\u00a2\3\2\2"+ - "\2\34\u00a6\3\2\2\2\36\u00ab\3\2\2\2 \u00b4\3\2\2\2\"\u00c6\3\2\2\2$\u00cf"+ - "\3\2\2\2&\u00f9\3\2\2\2(\u0102\3\2\2\2*\u0104\3\2\2\2,\u0112\3\2\2\2."+ - "\u0118\3\2\2\2\60\u011a\3\2\2\2\62\u011c\3\2\2\2\64\u011e\3\2\2\2\66\u012d"+ - "\3\2\2\28\u012f\3\2\2\2:\u0135\3\2\2\2<\u0137\3\2\2\2>\u0139\3\2\2\2@"+ - "A\5\6\4\2AB\7\2\2\3B\3\3\2\2\2CD\5\36\20\2DE\7\2\2\3E\5\3\2\2\2FJ\5\b"+ - "\5\2GI\5\20\t\2HG\3\2\2\2IL\3\2\2\2JH\3\2\2\2JK\3\2\2\2K\7\3\2\2\2LJ\3"+ - "\2\2\2MQ\5\f\7\2NQ\5\16\b\2OQ\5\32\16\2PM\3\2\2\2PN\3\2\2\2PO\3\2\2\2"+ - "Q\t\3\2\2\2RS\7\27\2\2ST\7\f\2\2TU\7\31\2\2UV\58\35\2V\13\3\2\2\2W`\7"+ - "\23\2\2XZ\5\22\n\2Y[\5\n\6\2ZY\3\2\2\2Z[\3\2\2\2[a\3\2\2\2\\^\5\n\6\2"+ - "]_\5\22\n\2^]\3\2\2\2^_\3\2\2\2_a\3\2\2\2`X\3\2\2\2`\\\3\2\2\2`a\3\2\2"+ - "\2ac\3\2\2\2bd\5\26\f\2cb\3\2\2\2de\3\2\2\2ec\3\2\2\2ef\3\2\2\2fi\3\2"+ - "\2\2gh\7\25\2\2hj\5\26\f\2ig\3\2\2\2ij\3\2\2\2j\r\3\2\2\2km\7\t\2\2ln"+ - "\5\22\n\2ml\3\2\2\2mn\3\2\2\2no\3\2\2\2oq\5\24\13\2pr\5\24\13\2qp\3\2"+ - "\2\2rs\3\2\2\2sq\3\2\2\2st\3\2\2\2tw\3\2\2\2uv\7\25\2\2vx\5\24\13\2wu"+ - "\3\2\2\2wx\3\2\2\2x\17\3\2\2\2yz\7+\2\2z\u0083\7/\2\2{\u0080\5 \21\2|"+ - "}\7&\2\2}\177\5 \21\2~|\3\2\2\2\177\u0082\3\2\2\2\u0080~\3\2\2\2\u0080"+ - "\u0081\3\2\2\2\u0081\u0084\3\2\2\2\u0082\u0080\3\2\2\2\u0083{\3\2\2\2"+ - "\u0083\u0084\3\2\2\2\u0084\21\3\2\2\2\u0085\u0086\7\5\2\2\u0086\u008b"+ - "\5\36\20\2\u0087\u0088\7&\2\2\u0088\u008a\5\36\20\2\u0089\u0087\3\2\2"+ - "\2\u008a\u008d\3\2\2\2\u008b\u0089\3\2\2\2\u008b\u008c\3\2\2\2\u008c\23"+ - "\3\2\2\2\u008d\u008b\3\2\2\2\u008e\u0090\5\30\r\2\u008f\u0091\5\22\n\2"+ - "\u0090\u008f\3\2\2\2\u0090\u0091\3\2\2\2\u0091\25\3\2\2\2\u0092\u0094"+ - "\5\30\r\2\u0093\u0095\5\22\n\2\u0094\u0093\3\2\2\2\u0094\u0095\3\2\2\2"+ - "\u0095\u009c\3\2\2\2\u0096\u0097\7\'\2\2\u0097\u0098\7/\2\2\u0098\u0099"+ - "\7\31\2\2\u0099\u009a\5:\36\2\u009a\u009b\7(\2\2\u009b\u009d\3\2\2\2\u009c"+ - "\u0096\3\2\2\2\u009c\u009d\3\2\2\2\u009d\27\3\2\2\2\u009e\u009f\7\'\2"+ - "\2\u009f\u00a0\5\34\17\2\u00a0\u00a1\7(\2\2\u00a1\31\3\2\2\2\u00a2\u00a3"+ - "\5\34\17\2\u00a3\33\3\2\2\2\u00a4\u00a7\7\4\2\2\u00a5\u00a7\5> \2\u00a6"+ - "\u00a4\3\2\2\2\u00a6\u00a5\3\2\2\2\u00a7\u00a8\3\2\2\2\u00a8\u00a9\7\26"+ - "\2\2\u00a9\u00aa\5\36\20\2\u00aa\35\3\2\2\2\u00ab\u00ac\5 \21\2\u00ac"+ - "\37\3\2\2\2\u00ad\u00ae\b\21\1\2\u00ae\u00af\7\r\2\2\u00af\u00b5\5 \21"+ - "\7\u00b0\u00b1\7/\2\2\u00b1\u00b2\7\17\2\2\u00b2\u00b5\5\30\r\2\u00b3"+ - "\u00b5\5\"\22\2\u00b4\u00ad\3\2\2\2\u00b4\u00b0\3\2\2\2\u00b4\u00b3\3"+ - "\2\2\2\u00b5\u00be\3\2\2\2\u00b6\u00b7\f\4\2\2\u00b7\u00b8\7\3\2\2\u00b8"+ - "\u00bd\5 \21\5\u00b9\u00ba\f\3\2\2\u00ba\u00bb\7\20\2\2\u00bb\u00bd\5"+ - " \21\4\u00bc\u00b6\3\2\2\2\u00bc\u00b9\3\2\2\2\u00bd\u00c0\3\2\2\2\u00be"+ - "\u00bc\3\2\2\2\u00be\u00bf\3\2\2\2\u00bf!\3\2\2\2\u00c0\u00be\3\2\2\2"+ - "\u00c1\u00c7\5$\23\2\u00c2\u00c3\5$\23\2\u00c3\u00c4\5\60\31\2\u00c4\u00c5"+ - "\5$\23\2\u00c5\u00c7\3\2\2\2\u00c6\u00c1\3\2\2\2\u00c6\u00c2\3\2\2\2\u00c7"+ - "#\3\2\2\2\u00c8\u00c9\b\23\1\2\u00c9\u00cb\5(\25\2\u00ca\u00cc\5&\24\2"+ - "\u00cb\u00ca\3\2\2\2\u00cb\u00cc\3\2\2\2\u00cc\u00d0\3\2\2\2\u00cd\u00ce"+ - "\t\2\2\2\u00ce\u00d0\5$\23\5\u00cf\u00c8\3\2\2\2\u00cf\u00cd\3\2\2\2\u00d0"+ - "\u00d9\3\2\2\2\u00d1\u00d2\f\4\2\2\u00d2\u00d3\t\3\2\2\u00d3\u00d8\5$"+ - "\23\5\u00d4\u00d5\f\3\2\2\u00d5\u00d6\t\2\2\2\u00d6\u00d8\5$\23\4\u00d7"+ - "\u00d1\3\2\2\2\u00d7\u00d4\3\2\2\2\u00d8\u00db\3\2\2\2\u00d9\u00d7\3\2"+ - "\2\2\u00d9\u00da\3\2\2\2\u00da%\3\2\2\2\u00db\u00d9\3\2\2\2\u00dc\u00de"+ - "\7\r\2\2\u00dd\u00dc\3\2\2\2\u00dd\u00de\3\2\2\2\u00de\u00df\3\2\2\2\u00df"+ - "\u00e0\t\4\2\2\u00e0\u00e1\7)\2\2\u00e1\u00e6\5\36\20\2\u00e2\u00e3\7"+ - "&\2\2\u00e3\u00e5\5\36\20\2\u00e4\u00e2\3\2\2\2\u00e5\u00e8\3\2\2\2\u00e6"+ - "\u00e4\3\2\2\2\u00e6\u00e7\3\2\2\2\u00e7\u00e9\3\2\2\2\u00e8\u00e6\3\2"+ - "\2\2\u00e9\u00ea\7*\2\2\u00ea\u00fa\3\2\2\2\u00eb\u00ec\t\5\2\2\u00ec"+ - "\u00fa\5.\30\2\u00ed\u00ee\t\5\2\2\u00ee\u00ef\7)\2\2\u00ef\u00f4\5.\30"+ - "\2\u00f0\u00f1\7&\2\2\u00f1\u00f3\5.\30\2\u00f2\u00f0\3\2\2\2\u00f3\u00f6"+ - "\3\2\2\2\u00f4\u00f2\3\2\2\2\u00f4\u00f5\3\2\2\2\u00f5\u00f7\3\2\2\2\u00f6"+ - "\u00f4\3\2\2\2\u00f7\u00f8\7*\2\2\u00f8\u00fa\3\2\2\2\u00f9\u00dd\3\2"+ - "\2\2\u00f9\u00eb\3\2\2\2\u00f9\u00ed\3\2\2\2\u00fa\'\3\2\2\2\u00fb\u0103"+ - "\5.\30\2\u00fc\u0103\5*\26\2\u00fd\u0103\5\64\33\2\u00fe\u00ff\7)\2\2"+ - "\u00ff\u0100\5\36\20\2\u0100\u0101\7*\2\2\u0101\u0103\3\2\2\2\u0102\u00fb"+ - "\3\2\2\2\u0102\u00fc\3\2\2\2\u0102\u00fd\3\2\2\2\u0102\u00fe\3\2\2\2\u0103"+ - ")\3\2\2\2\u0104\u0105\5,\27\2\u0105\u010e\7)\2\2\u0106\u010b\5\36\20\2"+ - "\u0107\u0108\7&\2\2\u0108\u010a\5\36\20\2\u0109\u0107\3\2\2\2\u010a\u010d"+ - "\3\2\2\2\u010b\u0109\3\2\2\2\u010b\u010c\3\2\2\2\u010c\u010f\3\2\2\2\u010d"+ - "\u010b\3\2\2\2\u010e\u0106\3\2\2\2\u010e\u010f\3\2\2\2\u010f\u0110\3\2"+ - "\2\2\u0110\u0111\7*\2\2\u0111+\3\2\2\2\u0112\u0113\t\6\2\2\u0113-\3\2"+ - "\2\2\u0114\u0119\7\16\2\2\u0115\u0119\5:\36\2\u0116\u0119\5\62\32\2\u0117"+ - "\u0119\5<\37\2\u0118\u0114\3\2\2\2\u0118\u0115\3\2\2\2\u0118\u0116\3\2"+ - "\2\2\u0118\u0117\3\2\2\2\u0119/\3\2\2\2\u011a\u011b\t\7\2\2\u011b\61\3"+ - "\2\2\2\u011c\u011d\t\b\2\2\u011d\63\3\2\2\2\u011e\u012a\5\66\34\2\u011f"+ - "\u0120\7%\2\2\u0120\u0129\5\66\34\2\u0121\u0123\7\'\2\2\u0122\u0124\7"+ - "-\2\2\u0123\u0122\3\2\2\2\u0124\u0125\3\2\2\2\u0125\u0123\3\2\2\2\u0125"+ - "\u0126\3\2\2\2\u0126\u0127\3\2\2\2\u0127\u0129\7(\2\2\u0128\u011f\3\2"+ - "\2\2\u0128\u0121\3\2\2\2\u0129\u012c\3\2\2\2\u012a\u0128\3\2\2\2\u012a"+ - "\u012b\3\2\2\2\u012b\65\3\2\2\2\u012c\u012a\3\2\2\2\u012d\u012e\t\t\2"+ - "\2\u012e\67\3\2\2\2\u012f\u0131\5:\36\2\u0130\u0132\7/\2\2\u0131\u0130"+ - "\3\2\2\2\u0131\u0132\3\2\2\2\u01329\3\2\2\2\u0133\u0136\7.\2\2\u0134\u0136"+ - "\7-\2\2\u0135\u0133\3\2\2\2\u0135\u0134\3\2\2\2\u0136;\3\2\2\2\u0137\u0138"+ - "\7,\2\2\u0138=\3\2\2\2\u0139\u013a\t\n\2\2\u013a?\3\2\2\2(JPZ^`eimsw\u0080"+ + "\n\30\3\31\3\31\3\32\3\32\3\33\5\33\u0120\n\33\3\33\3\33\3\33\3\33\3\33"+ + "\6\33\u0127\n\33\r\33\16\33\u0128\3\33\7\33\u012c\n\33\f\33\16\33\u012f"+ + "\13\33\3\34\3\34\3\35\3\35\5\35\u0135\n\35\3\36\3\36\5\36\u0139\n\36\3"+ + "\37\3\37\3 \3 \3 \2\4 $!\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&("+ + "*,.\60\62\64\668:<>\2\13\3\2 !\3\2\"$\3\2\7\b\5\2\n\13\21\22\30\30\4\2"+ + "\60\60\62\62\3\2\32\37\4\2\6\6\24\24\3\2\60\61\4\2--\60\60\2\u014e\2@"+ + "\3\2\2\2\4C\3\2\2\2\6F\3\2\2\2\bP\3\2\2\2\nR\3\2\2\2\fW\3\2\2\2\16k\3"+ + "\2\2\2\20y\3\2\2\2\22\u0085\3\2\2\2\24\u008e\3\2\2\2\26\u0092\3\2\2\2"+ + "\30\u009e\3\2\2\2\32\u00a2\3\2\2\2\34\u00a6\3\2\2\2\36\u00ab\3\2\2\2 "+ + "\u00b4\3\2\2\2\"\u00c6\3\2\2\2$\u00cf\3\2\2\2&\u00f9\3\2\2\2(\u0102\3"+ + "\2\2\2*\u0104\3\2\2\2,\u0112\3\2\2\2.\u0118\3\2\2\2\60\u011a\3\2\2\2\62"+ + "\u011c\3\2\2\2\64\u011f\3\2\2\2\66\u0130\3\2\2\28\u0132\3\2\2\2:\u0138"+ + "\3\2\2\2<\u013a\3\2\2\2>\u013c\3\2\2\2@A\5\6\4\2AB\7\2\2\3B\3\3\2\2\2"+ + "CD\5\36\20\2DE\7\2\2\3E\5\3\2\2\2FJ\5\b\5\2GI\5\20\t\2HG\3\2\2\2IL\3\2"+ + "\2\2JH\3\2\2\2JK\3\2\2\2K\7\3\2\2\2LJ\3\2\2\2MQ\5\f\7\2NQ\5\16\b\2OQ\5"+ + "\32\16\2PM\3\2\2\2PN\3\2\2\2PO\3\2\2\2Q\t\3\2\2\2RS\7\27\2\2ST\7\f\2\2"+ + "TU\7\31\2\2UV\58\35\2V\13\3\2\2\2W`\7\23\2\2XZ\5\22\n\2Y[\5\n\6\2ZY\3"+ + "\2\2\2Z[\3\2\2\2[a\3\2\2\2\\^\5\n\6\2]_\5\22\n\2^]\3\2\2\2^_\3\2\2\2_"+ + "a\3\2\2\2`X\3\2\2\2`\\\3\2\2\2`a\3\2\2\2ac\3\2\2\2bd\5\26\f\2cb\3\2\2"+ + "\2de\3\2\2\2ec\3\2\2\2ef\3\2\2\2fi\3\2\2\2gh\7\25\2\2hj\5\26\f\2ig\3\2"+ + "\2\2ij\3\2\2\2j\r\3\2\2\2km\7\t\2\2ln\5\22\n\2ml\3\2\2\2mn\3\2\2\2no\3"+ + "\2\2\2oq\5\24\13\2pr\5\24\13\2qp\3\2\2\2rs\3\2\2\2sq\3\2\2\2st\3\2\2\2"+ + "tw\3\2\2\2uv\7\25\2\2vx\5\24\13\2wu\3\2\2\2wx\3\2\2\2x\17\3\2\2\2yz\7"+ + "+\2\2z\u0083\7\60\2\2{\u0080\5 \21\2|}\7&\2\2}\177\5 \21\2~|\3\2\2\2\177"+ + "\u0082\3\2\2\2\u0080~\3\2\2\2\u0080\u0081\3\2\2\2\u0081\u0084\3\2\2\2"+ + "\u0082\u0080\3\2\2\2\u0083{\3\2\2\2\u0083\u0084\3\2\2\2\u0084\21\3\2\2"+ + "\2\u0085\u0086\7\5\2\2\u0086\u008b\5\36\20\2\u0087\u0088\7&\2\2\u0088"+ + "\u008a\5\36\20\2\u0089\u0087\3\2\2\2\u008a\u008d\3\2\2\2\u008b\u0089\3"+ + "\2\2\2\u008b\u008c\3\2\2\2\u008c\23\3\2\2\2\u008d\u008b\3\2\2\2\u008e"+ + "\u0090\5\30\r\2\u008f\u0091\5\22\n\2\u0090\u008f\3\2\2\2\u0090\u0091\3"+ + "\2\2\2\u0091\25\3\2\2\2\u0092\u0094\5\30\r\2\u0093\u0095\5\22\n\2\u0094"+ + "\u0093\3\2\2\2\u0094\u0095\3\2\2\2\u0095\u009c\3\2\2\2\u0096\u0097\7\'"+ + "\2\2\u0097\u0098\7\60\2\2\u0098\u0099\7\31\2\2\u0099\u009a\5:\36\2\u009a"+ + "\u009b\7(\2\2\u009b\u009d\3\2\2\2\u009c\u0096\3\2\2\2\u009c\u009d\3\2"+ + "\2\2\u009d\27\3\2\2\2\u009e\u009f\7\'\2\2\u009f\u00a0\5\34\17\2\u00a0"+ + "\u00a1\7(\2\2\u00a1\31\3\2\2\2\u00a2\u00a3\5\34\17\2\u00a3\33\3\2\2\2"+ + "\u00a4\u00a7\7\4\2\2\u00a5\u00a7\5> \2\u00a6\u00a4\3\2\2\2\u00a6\u00a5"+ + "\3\2\2\2\u00a7\u00a8\3\2\2\2\u00a8\u00a9\7\26\2\2\u00a9\u00aa\5\36\20"+ + "\2\u00aa\35\3\2\2\2\u00ab\u00ac\5 \21\2\u00ac\37\3\2\2\2\u00ad\u00ae\b"+ + "\21\1\2\u00ae\u00af\7\r\2\2\u00af\u00b5\5 \21\7\u00b0\u00b1\7\60\2\2\u00b1"+ + "\u00b2\7\17\2\2\u00b2\u00b5\5\30\r\2\u00b3\u00b5\5\"\22\2\u00b4\u00ad"+ + "\3\2\2\2\u00b4\u00b0\3\2\2\2\u00b4\u00b3\3\2\2\2\u00b5\u00be\3\2\2\2\u00b6"+ + "\u00b7\f\4\2\2\u00b7\u00b8\7\3\2\2\u00b8\u00bd\5 \21\5\u00b9\u00ba\f\3"+ + "\2\2\u00ba\u00bb\7\20\2\2\u00bb\u00bd\5 \21\4\u00bc\u00b6\3\2\2\2\u00bc"+ + "\u00b9\3\2\2\2\u00bd\u00c0\3\2\2\2\u00be\u00bc\3\2\2\2\u00be\u00bf\3\2"+ + "\2\2\u00bf!\3\2\2\2\u00c0\u00be\3\2\2\2\u00c1\u00c7\5$\23\2\u00c2\u00c3"+ + "\5$\23\2\u00c3\u00c4\5\60\31\2\u00c4\u00c5\5$\23\2\u00c5\u00c7\3\2\2\2"+ + "\u00c6\u00c1\3\2\2\2\u00c6\u00c2\3\2\2\2\u00c7#\3\2\2\2\u00c8\u00c9\b"+ + "\23\1\2\u00c9\u00cb\5(\25\2\u00ca\u00cc\5&\24\2\u00cb\u00ca\3\2\2\2\u00cb"+ + "\u00cc\3\2\2\2\u00cc\u00d0\3\2\2\2\u00cd\u00ce\t\2\2\2\u00ce\u00d0\5$"+ + "\23\5\u00cf\u00c8\3\2\2\2\u00cf\u00cd\3\2\2\2\u00d0\u00d9\3\2\2\2\u00d1"+ + "\u00d2\f\4\2\2\u00d2\u00d3\t\3\2\2\u00d3\u00d8\5$\23\5\u00d4\u00d5\f\3"+ + "\2\2\u00d5\u00d6\t\2\2\2\u00d6\u00d8\5$\23\4\u00d7\u00d1\3\2\2\2\u00d7"+ + "\u00d4\3\2\2\2\u00d8\u00db\3\2\2\2\u00d9\u00d7\3\2\2\2\u00d9\u00da\3\2"+ + "\2\2\u00da%\3\2\2\2\u00db\u00d9\3\2\2\2\u00dc\u00de\7\r\2\2\u00dd\u00dc"+ + "\3\2\2\2\u00dd\u00de\3\2\2\2\u00de\u00df\3\2\2\2\u00df\u00e0\t\4\2\2\u00e0"+ + "\u00e1\7)\2\2\u00e1\u00e6\5\36\20\2\u00e2\u00e3\7&\2\2\u00e3\u00e5\5\36"+ + "\20\2\u00e4\u00e2\3\2\2\2\u00e5\u00e8\3\2\2\2\u00e6\u00e4\3\2\2\2\u00e6"+ + "\u00e7\3\2\2\2\u00e7\u00e9\3\2\2\2\u00e8\u00e6\3\2\2\2\u00e9\u00ea\7*"+ + "\2\2\u00ea\u00fa\3\2\2\2\u00eb\u00ec\t\5\2\2\u00ec\u00fa\5.\30\2\u00ed"+ + "\u00ee\t\5\2\2\u00ee\u00ef\7)\2\2\u00ef\u00f4\5.\30\2\u00f0\u00f1\7&\2"+ + "\2\u00f1\u00f3\5.\30\2\u00f2\u00f0\3\2\2\2\u00f3\u00f6\3\2\2\2\u00f4\u00f2"+ + "\3\2\2\2\u00f4\u00f5\3\2\2\2\u00f5\u00f7\3\2\2\2\u00f6\u00f4\3\2\2\2\u00f7"+ + "\u00f8\7*\2\2\u00f8\u00fa\3\2\2\2\u00f9\u00dd\3\2\2\2\u00f9\u00eb\3\2"+ + "\2\2\u00f9\u00ed\3\2\2\2\u00fa\'\3\2\2\2\u00fb\u0103\5.\30\2\u00fc\u0103"+ + "\5*\26\2\u00fd\u0103\5\64\33\2\u00fe\u00ff\7)\2\2\u00ff\u0100\5\36\20"+ + "\2\u0100\u0101\7*\2\2\u0101\u0103\3\2\2\2\u0102\u00fb\3\2\2\2\u0102\u00fc"+ + "\3\2\2\2\u0102\u00fd\3\2\2\2\u0102\u00fe\3\2\2\2\u0103)\3\2\2\2\u0104"+ + "\u0105\5,\27\2\u0105\u010e\7)\2\2\u0106\u010b\5\36\20\2\u0107\u0108\7"+ + "&\2\2\u0108\u010a\5\36\20\2\u0109\u0107\3\2\2\2\u010a\u010d\3\2\2\2\u010b"+ + "\u0109\3\2\2\2\u010b\u010c\3\2\2\2\u010c\u010f\3\2\2\2\u010d\u010b\3\2"+ + "\2\2\u010e\u0106\3\2\2\2\u010e\u010f\3\2\2\2\u010f\u0110\3\2\2\2\u0110"+ + "\u0111\7*\2\2\u0111+\3\2\2\2\u0112\u0113\t\6\2\2\u0113-\3\2\2\2\u0114"+ + "\u0119\7\16\2\2\u0115\u0119\5:\36\2\u0116\u0119\5\62\32\2\u0117\u0119"+ + "\5<\37\2\u0118\u0114\3\2\2\2\u0118\u0115\3\2\2\2\u0118\u0116\3\2\2\2\u0118"+ + "\u0117\3\2\2\2\u0119/\3\2\2\2\u011a\u011b\t\7\2\2\u011b\61\3\2\2\2\u011c"+ + "\u011d\t\b\2\2\u011d\63\3\2\2\2\u011e\u0120\7,\2\2\u011f\u011e\3\2\2\2"+ + "\u011f\u0120\3\2\2\2\u0120\u0121\3\2\2\2\u0121\u012d\5\66\34\2\u0122\u0123"+ + "\7%\2\2\u0123\u012c\5\66\34\2\u0124\u0126\7\'\2\2\u0125\u0127\7.\2\2\u0126"+ + "\u0125\3\2\2\2\u0127\u0128\3\2\2\2\u0128\u0126\3\2\2\2\u0128\u0129\3\2"+ + "\2\2\u0129\u012a\3\2\2\2\u012a\u012c\7(\2\2\u012b\u0122\3\2\2\2\u012b"+ + "\u0124\3\2\2\2\u012c\u012f\3\2\2\2\u012d\u012b\3\2\2\2\u012d\u012e\3\2"+ + "\2\2\u012e\65\3\2\2\2\u012f\u012d\3\2\2\2\u0130\u0131\t\t\2\2\u0131\67"+ + "\3\2\2\2\u0132\u0134\5:\36\2\u0133\u0135\7\60\2\2\u0134\u0133\3\2\2\2"+ + "\u0134\u0135\3\2\2\2\u01359\3\2\2\2\u0136\u0139\7/\2\2\u0137\u0139\7."+ + "\2\2\u0138\u0136\3\2\2\2\u0138\u0137\3\2\2\2\u0139;\3\2\2\2\u013a\u013b"+ + "\7-\2\2\u013b=\3\2\2\2\u013c\u013d\t\n\2\2\u013d?\3\2\2\2)JPZ^`eimsw\u0080"+ "\u0083\u008b\u0090\u0094\u009c\u00a6\u00b4\u00bc\u00be\u00c6\u00cb\u00cf"+ - "\u00d7\u00d9\u00dd\u00e6\u00f4\u00f9\u0102\u010b\u010e\u0118\u0125\u0128"+ - "\u012a\u0131\u0135"; + "\u00d7\u00d9\u00dd\u00e6\u00f4\u00f9\u0102\u010b\u010e\u0118\u011f\u0128"+ + "\u012b\u012d\u0134\u0138"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlParser.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlParser.java index a893d1b3637ad..c30208196845d 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlParser.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlParser.java @@ -21,12 +21,14 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.expression.UnresolvedAttribute; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; import java.util.Arrays; import java.util.BitSet; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; @@ -38,7 +40,11 @@ public class EqlParser { private static final Logger log = LogManager.getLogger(); private final boolean DEBUG = false; + private final Set optionals; + public EqlParser(Set optionals) { + this.optionals = optionals; + } /** * Parses an EQL statement into execution plan */ @@ -103,7 +109,7 @@ private T invokeParser(String eql, ParserParams params, log.info("Parse tree {} " + tree.toStringTree()); } - return visitor.apply(new AstBuilder(params), tree); + return visitor.apply(new AstBuilder(params, optionals), tree); } catch (StackOverflowError e) { throw new ParsingException("EQL statement is too large, " + "causing stack overflow when generating the parsing tree: [{}]", eql); diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/ExpressionBuilder.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/ExpressionBuilder.java index 860a56894cf87..c1ff890a54a70 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/ExpressionBuilder.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/ExpressionBuilder.java @@ -17,6 +17,7 @@ import org.elasticsearch.xpack.eql.parser.EqlBaseParser.ArithmeticUnaryContext; import org.elasticsearch.xpack.eql.parser.EqlBaseParser.ComparisonContext; import org.elasticsearch.xpack.eql.parser.EqlBaseParser.DereferenceContext; +import org.elasticsearch.xpack.eql.parser.EqlBaseParser.ExpressionContext; import org.elasticsearch.xpack.eql.parser.EqlBaseParser.FunctionExpressionContext; import org.elasticsearch.xpack.eql.parser.EqlBaseParser.JoinKeysContext; import org.elasticsearch.xpack.eql.parser.EqlBaseParser.LogicalBinaryContext; @@ -54,6 +55,7 @@ import java.time.ZoneId; import java.util.List; +import java.util.Set; import static java.util.Collections.emptyList; import static java.util.stream.Collectors.toList; @@ -66,9 +68,11 @@ public class ExpressionBuilder extends IdentifierBuilder { protected final ParserParams params; + private final Set optionals; - public ExpressionBuilder(ParserParams params) { + public ExpressionBuilder(ParserParams params, Set optionals) { this.params = params; + this.optionals = optionals; } protected Expression expression(ParseTree ctx) { @@ -86,8 +90,18 @@ public Expression visitSingleExpression(EqlBaseParser.SingleExpressionContext ct @Override public List visitJoinKeys(JoinKeysContext ctx) { + if (ctx == null) { + return emptyList(); + } try { - return ctx != null ? visitList(this, ctx.expression(), Attribute.class) : emptyList(); + List keys = ctx.expression(); + for (ExpressionContext k : keys) { + if ("?".equals(k.getStart().getText())) { + Source source = source(k); + throw new ParsingException(source, "Cannot use unsupported optional field [{}] as a join key", source.text()); + } + } + return visitList(this, keys, Attribute.class); } catch (ClassCastException ex) { Source source = source(ctx); throw new ParsingException(source, "Unsupported join key ", source.text()); @@ -219,7 +233,12 @@ public Literal visitDecimalLiteral(EqlBaseParser.DecimalLiteralContext ctx) { @Override public UnresolvedAttribute visitDereference(DereferenceContext ctx) { - return new UnresolvedAttribute(source(ctx), visitQualifiedName(ctx.qualifiedName())); + String name = visitQualifiedName(ctx.qualifiedName()); + UnresolvedAttribute attr = new UnresolvedAttribute(source(ctx), name); + if ("?".equals(ctx.getStart().getText())) { + optionals.add(attr); + } + return attr; } @Override diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/LogicalPlanBuilder.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/LogicalPlanBuilder.java index 4a7198ac7eea7..e0ad55c6a10eb 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/LogicalPlanBuilder.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/LogicalPlanBuilder.java @@ -71,8 +71,8 @@ public abstract class LogicalPlanBuilder extends ExpressionBuilder { private final UnresolvedRelation RELATION = new UnresolvedRelation(synthetic(""), null, "", false, ""); private final EmptyAttribute UNSPECIFIED_FIELD = new EmptyAttribute(synthetic("")); - public LogicalPlanBuilder(ParserParams params) { - super(params); + public LogicalPlanBuilder(ParserParams params, Set optionals) { + super(params, optionals); } private Attribute fieldTimestamp() { diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/session/EqlSession.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/session/EqlSession.java index ed57aed80a87a..cd7aea810a77d 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/session/EqlSession.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/session/EqlSession.java @@ -21,10 +21,14 @@ import org.elasticsearch.xpack.eql.parser.ParserParams; import org.elasticsearch.xpack.eql.plan.physical.PhysicalPlan; import org.elasticsearch.xpack.eql.planner.Planner; +import org.elasticsearch.xpack.ql.expression.UnresolvedAttribute; import org.elasticsearch.xpack.ql.expression.function.FunctionRegistry; import org.elasticsearch.xpack.ql.index.IndexResolver; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; +import java.util.HashSet; +import java.util.Set; + import static org.elasticsearch.action.ActionListener.wrap; import static org.elasticsearch.xpack.ql.util.ActionListeners.map; @@ -41,6 +45,8 @@ public class EqlSession { private final Planner planner; private final CircuitBreaker circuitBreaker; + private final Set optionals = new HashSet<>(); + public EqlSession(Client client, EqlConfiguration cfg, IndexResolver indexResolver, PreAnalyzer preAnalyzer, PostAnalyzer postAnalyzer, FunctionRegistry functionRegistry, Verifier verifier, Optimizer optimizer, Planner planner, CircuitBreaker circuitBreaker) { @@ -50,7 +56,7 @@ public EqlSession(Client client, EqlConfiguration cfg, IndexResolver indexResolv this.indexResolver = indexResolver; this.preAnalyzer = preAnalyzer; this.postAnalyzer = postAnalyzer; - this.analyzer = new Analyzer(cfg, functionRegistry, verifier); + this.analyzer = new Analyzer(cfg, functionRegistry, verifier, optionals); this.optimizer = optimizer; this.planner = planner; this.circuitBreaker = circuitBreaker; @@ -117,6 +123,6 @@ private LogicalPlan postAnalyze(LogicalPlan verified) { } private LogicalPlan doParse(String eql, ParserParams params) { - return new EqlParser().createStatement(eql, params); + return new EqlParser(optionals).createStatement(eql, params); } } diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/AnalyzerTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/AnalyzerTests.java new file mode 100644 index 0000000000000..98880fed06394 --- /dev/null +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/AnalyzerTests.java @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.eql.analysis; + +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.eql.expression.function.EqlFunctionRegistry; +import org.elasticsearch.xpack.eql.expression.function.scalar.string.Concat; +import org.elasticsearch.xpack.eql.parser.EqlParser; +import org.elasticsearch.xpack.eql.plan.logical.Head; +import org.elasticsearch.xpack.eql.stats.Metrics; +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.expression.FieldAttribute; +import org.elasticsearch.xpack.ql.expression.Literal; +import org.elasticsearch.xpack.ql.expression.UnresolvedAttribute; +import org.elasticsearch.xpack.ql.expression.predicate.logical.And; +import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; +import org.elasticsearch.xpack.ql.index.EsIndex; +import org.elasticsearch.xpack.ql.index.IndexResolution; +import org.elasticsearch.xpack.ql.plan.logical.Filter; +import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; +import org.elasticsearch.xpack.ql.plan.logical.OrderBy; +import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.ql.type.EsField; +import org.elasticsearch.xpack.ql.type.TypesTests; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.elasticsearch.xpack.eql.EqlTestUtils.TEST_CFG; + +public class AnalyzerTests extends ESTestCase { + + private static final String INDEX_NAME = "test"; + private static Set optionals = new HashSet<>(); + static { + optionals.add(new UnresolvedAttribute(Source.EMPTY, "foo")); + optionals.add(new UnresolvedAttribute(Source.EMPTY, "bar")); + optionals.add(new UnresolvedAttribute(Source.EMPTY, "pid")); // this one also exists in the index mapping + } + private EqlParser parser = new EqlParser(optionals); + private IndexResolution index = loadIndexResolution("mapping-default.json"); + + private static Map loadEqlMapping(String name) { + return TypesTests.loadMapping(name); + } + + public static IndexResolution loadIndexResolution(String name) { + return IndexResolution.valid(new EsIndex(INDEX_NAME, loadEqlMapping(name))); + } + + private LogicalPlan accept(IndexResolution resolution, String eql) { + PreAnalyzer preAnalyzer = new PreAnalyzer(); + Analyzer analyzer = new Analyzer(TEST_CFG, new EqlFunctionRegistry(), new Verifier(new Metrics()), optionals); + return analyzer.analyze(preAnalyzer.preAnalyze(parser.createStatement(eql), resolution)); + } + + private LogicalPlan accept(String eql) { + return accept(index, eql); + } + + private Equals equalsCondition(String query) { + LogicalPlan plan = accept(query); + assertTrue(plan instanceof Head); + Head head = (Head) plan; + assertTrue(head.child() instanceof OrderBy); + OrderBy orderBy = (OrderBy) head.child(); + assertTrue(orderBy.child() instanceof Filter); + + Filter filter = (Filter) orderBy.child(); + assertTrue(filter.condition() instanceof And); + And condition = (And) filter.condition(); + assertTrue(condition.right() instanceof Equals); + return (Equals) condition.right(); + } + + public void testOptionalFieldOnTheLeft() { + Equals check = equalsCondition("process where ?foo == 123"); + assertEquals(Literal.NULL, check.left()); + assertTrue(check.right() instanceof Literal); + assertEquals(123, ((Literal) check.right()).value()); + } + + public void testOptionalFieldOnTheRight() { + Equals check = equalsCondition("process where 123 == ?bar"); + assertEquals(Literal.NULL, check.right()); + assertTrue(check.left() instanceof Literal); + assertEquals(123, ((Literal) check.left()).value()); + } + + public void testOptionalFieldsInsideFunction() { + Equals check = equalsCondition("process where concat(?foo, \" \", ?bar) == \"test\""); + assertEquals("test", ((Literal) check.right()).value()); + assertTrue(check.left() instanceof Concat); + Concat concat = (Concat) check.left(); + List arguments = new ArrayList<>(3); + arguments.add(Literal.NULL); + arguments.add(new Literal(Source.EMPTY, " ", DataTypes.KEYWORD)); + arguments.add(Literal.NULL); + assertEquals(arguments, concat.arguments()); + } + + public void testOptionalFieldExistsInMapping() { + Equals check = equalsCondition("process where ?pid == 123"); + assertTrue(check.left() instanceof FieldAttribute); + assertEquals("pid", ((FieldAttribute) check.left()).name()); + assertTrue(check.right() instanceof Literal); + assertEquals(123, ((Literal) check.right()).value()); + } +} diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/VerifierTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/VerifierTests.java index 7534b05401657..93af69e960ea0 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/VerifierTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/VerifierTests.java @@ -16,14 +16,17 @@ import org.elasticsearch.xpack.eql.parser.ParsingException; import org.elasticsearch.xpack.eql.session.EqlConfiguration; import org.elasticsearch.xpack.eql.stats.Metrics; +import org.elasticsearch.xpack.ql.expression.UnresolvedAttribute; import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; +import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.ql.type.TypesTests; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -36,7 +39,7 @@ public class VerifierTests extends ESTestCase { private static final String INDEX_NAME = "test"; - private final EqlParser parser = new EqlParser(); + private final EqlParser parser = new EqlParser(new HashSet<>()); private final IndexResolution index = loadIndexResolution("mapping-default.json"); @@ -49,8 +52,12 @@ private IndexResolution loadIndexResolution(String name) { } private LogicalPlan accept(IndexResolution resolution, String eql) { + Set optionals = new HashSet<>(); + optionals.add(new UnresolvedAttribute(Source.EMPTY, "foo")); + optionals.add(new UnresolvedAttribute(Source.EMPTY, "bar")); + PreAnalyzer preAnalyzer = new PreAnalyzer(); - Analyzer analyzer = new Analyzer(EqlTestUtils.TEST_CFG, new EqlFunctionRegistry(), new Verifier(new Metrics())); + Analyzer analyzer = new Analyzer(EqlTestUtils.TEST_CFG, new EqlFunctionRegistry(), new Verifier(new Metrics()), optionals); return analyzer.analyze(preAnalyzer.preAnalyze(parser.createStatement(eql), resolution)); } @@ -141,6 +148,20 @@ public void testArrayIndexesUnsupported() { errorParsing("registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == \"EN-us")); } + // Test unsupported optional fields as join keys + public void testOptionalFieldsUnsupported() { + assertEquals("1:14: Cannot use unsupported optional field [?x] as a join key", + errorParsing("sequence by ?x, y, pid [any where true] by a [any where true] by b")); + assertEquals("1:17: Cannot use unsupported optional field [?y] as a join key", + errorParsing("sequence by x, ?y, ?pid [any where true] by a [any where true] by b")); + assertEquals("1:44: Cannot use unsupported optional field [?a] as a join key", + errorParsing("sequence by x, y, pid [any where true] by ?a [any where true] by b")); + assertEquals("1:72: Cannot use unsupported optional field [?b] as a join key", + errorParsing("sequence by x, y, pid [any where true] by a, c [any where true] by d, ?b")); + assertEquals("1:1: extraneous input '?' expecting {'any', 'join', 'sequence', STRING, IDENTIFIER}", + errorParsing("?x where true")); + } + // Test valid/supported queries public void testQueryOk() { // Mismatched type, still ok @@ -176,6 +197,12 @@ public void testQueryOk() { accept("file where serial_event_id * 2 == 164"); accept("file where serial_event_id / 2 == 41"); accept("file where serial_event_id % 40 == 2"); + + // optional fields + accept("file where ?foo == 123"); + accept("file where ?foo == null"); + accept("file where serial_event_id == 82 and (true == (?bar in (\"abc\", \"xyz\")))"); + accept("file where concat(?foo, \"test\", ?bar) == \"onetest!\""); } // Test mapping that doesn\"t have property event.category defined @@ -387,7 +414,7 @@ private LogicalPlan analyzeWithVerifierFunction(Function()); IndexResolution resolution = IndexResolution.valid(new EsIndex("irrelevant", loadEqlMapping("mapping-default.json"))); return analyzer.analyze(preAnalyzer.preAnalyze(parser.createStatement("any where true"), resolution)); } diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/optimizer/OptimizerTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/optimizer/OptimizerTests.java index 279c85f61ac52..a439fdbeaf2c6 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/optimizer/OptimizerTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/optimizer/OptimizerTests.java @@ -56,6 +56,7 @@ import org.elasticsearch.xpack.ql.type.TypesTests; import java.time.ZoneId; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -74,7 +75,7 @@ public class OptimizerTests extends ESTestCase { private static final String INDEX_NAME = "test"; - private EqlParser parser = new EqlParser(); + private EqlParser parser = new EqlParser(new HashSet<>()); private IndexResolution index = loadIndexResolution("mapping-default.json"); private Optimizer optimizer = new Optimizer(); @@ -89,7 +90,7 @@ public static IndexResolution loadIndexResolution(String name) { private LogicalPlan accept(IndexResolution resolution, String eql) { PreAnalyzer preAnalyzer = new PreAnalyzer(); PostAnalyzer postAnalyzer = new PostAnalyzer(); - Analyzer analyzer = new Analyzer(TEST_CFG, new EqlFunctionRegistry(), new Verifier(new Metrics())); + Analyzer analyzer = new Analyzer(TEST_CFG, new EqlFunctionRegistry(), new Verifier(new Metrics()), new HashSet<>()); return optimizer.optimize(postAnalyzer.postAnalyze(analyzer.analyze(preAnalyzer.preAnalyze(parser.createStatement(eql), resolution)), TEST_CFG)); } diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/optimizer/TomlFoldTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/optimizer/TomlFoldTests.java index 87e509acf75ef..913b22380f823 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/optimizer/TomlFoldTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/optimizer/TomlFoldTests.java @@ -37,9 +37,9 @@ public class TomlFoldTests extends ESTestCase { protected static final String PARAM_FORMATTING = "%1$s.test -> %2$s"; - private static final EqlParser PARSER = new EqlParser(); + private static final EqlParser PARSER = new EqlParser(new HashSet<>()); private static final EqlFunctionRegistry FUNCTION_REGISTRY = new EqlFunctionRegistry(); - private static final Analyzer ANALYZER = new Analyzer(TEST_CFG, FUNCTION_REGISTRY, new Verifier(new Metrics())); + private static final Analyzer ANALYZER = new Analyzer(TEST_CFG, FUNCTION_REGISTRY, new Verifier(new Metrics()), new HashSet<>()); private final int num; private final EqlFoldSpec spec; diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/ExpressionTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/ExpressionTests.java index d9243f8bf1af1..3d196c2345f16 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/ExpressionTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/ExpressionTests.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import static org.elasticsearch.xpack.eql.parser.AbstractBuilder.unquoteString; @@ -46,7 +47,7 @@ public class ExpressionTests extends ESTestCase { - private final EqlParser parser = new EqlParser(); + private final EqlParser parser = new EqlParser(new HashSet<>()); private static Source source(String text) { return new Source(0, 0, text); diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/GrammarTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/GrammarTests.java index 09c4d9e4008f1..8097e28c1881b 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/GrammarTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/GrammarTests.java @@ -20,6 +20,7 @@ import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -30,7 +31,7 @@ public class GrammarTests extends ESTestCase { public void testSupportedQueries() throws Exception { - EqlParser parser = new EqlParser(); + EqlParser parser = new EqlParser(new HashSet<>()); List> lines = readQueries("/queries-supported.eql"); for (Tuple line : lines) { String q = line.v1(); @@ -39,7 +40,7 @@ public void testSupportedQueries() throws Exception { } public void testUnsupportedQueries() throws Exception { - EqlParser parser = new EqlParser(); + EqlParser parser = new EqlParser(new HashSet<>()); List> lines = readQueries("/queries-unsupported.eql"); for (Tuple line : lines) { String q = line.v1(); diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/LogicalPlanTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/LogicalPlanTests.java index b5267a3241c90..5dc71c5719663 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/LogicalPlanTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/parser/LogicalPlanTests.java @@ -33,6 +33,7 @@ import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataTypes; +import java.util.HashSet; import java.util.List; import java.util.concurrent.TimeUnit; @@ -41,7 +42,7 @@ public class LogicalPlanTests extends ESTestCase { - private final EqlParser parser = new EqlParser(); + private final EqlParser parser = new EqlParser(new HashSet<>()); private Expression expr(String source) { return parser.createExpression(source); diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/planner/AbstractQueryTranslatorTestCase.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/planner/AbstractQueryTranslatorTestCase.java index b9a1d1415dbbf..431348023f76c 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/planner/AbstractQueryTranslatorTestCase.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/planner/AbstractQueryTranslatorTestCase.java @@ -22,14 +22,16 @@ import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; +import java.util.HashSet; + import static org.elasticsearch.xpack.ql.type.TypesTests.loadMapping; public abstract class AbstractQueryTranslatorTestCase extends ESTestCase { - protected EqlParser parser = new EqlParser(); + protected EqlParser parser = new EqlParser(new HashSet<>()); protected PreAnalyzer preAnalyzer = new PreAnalyzer(); protected PostAnalyzer postAnalyzer = new PostAnalyzer(); protected EqlConfiguration configuration = EqlTestUtils.randomConfiguration(); - protected Analyzer analyzer = new Analyzer(configuration, new EqlFunctionRegistry(), new Verifier(new Metrics())); + protected Analyzer analyzer = new Analyzer(configuration, new EqlFunctionRegistry(), new Verifier(new Metrics()), new HashSet<>()); protected Optimizer optimizer = new Optimizer(); protected Planner planner = new Planner(); diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/stats/VerifierMetricsTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/stats/VerifierMetricsTests.java index 5a242e9616dbe..8ed46673be66d 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/stats/VerifierMetricsTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/stats/VerifierMetricsTests.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.eql.parser.EqlParser; import org.elasticsearch.xpack.ql.index.IndexResolution; +import java.util.HashSet; import java.util.Set; import static org.elasticsearch.xpack.eql.stats.FeatureMetric.EVENT; @@ -41,7 +42,7 @@ public class VerifierMetricsTests extends ESTestCase { - private EqlParser parser = new EqlParser(); + private EqlParser parser = new EqlParser(new HashSet<>()); private PreAnalyzer preAnalyzer = new PreAnalyzer(); private EqlFunctionRegistry eqlFunctionRegistry = new EqlFunctionRegistry(); private IndexResolution index = OptimizerTests.loadIndexResolution("mapping-default.json"); @@ -166,7 +167,7 @@ private void assertCounters(Counters actual, Set metrics) { private Counters eql(String query) { Metrics metrics = new Metrics(); Verifier verifier = new Verifier(metrics); - Analyzer analyzer = new Analyzer(EqlTestUtils.randomConfiguration(), eqlFunctionRegistry, verifier); + Analyzer analyzer = new Analyzer(EqlTestUtils.randomConfiguration(), eqlFunctionRegistry, verifier, new HashSet<>()); analyzer.analyze(preAnalyzer.preAnalyze(parser.createStatement(query), index)); return metrics.stats(); } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/analyzer/AnalyzerRules.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/analyzer/AnalyzerRules.java index fb83682bbb643..3ad5695574ff7 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/analyzer/AnalyzerRules.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/analyzer/AnalyzerRules.java @@ -56,7 +56,6 @@ protected boolean skipResolved() { } } - public abstract static class AnalyzerRule extends Rule { // transformUp (post-order) - that is first children and then the node