From fac5855e71c5f521e32988a7dee424dbfb002f98 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Tue, 11 Sep 2018 00:05:38 +0300 Subject: [PATCH 1/4] SQL: Introduce support for NULL values Make SQL aware of missing and/or unmapped fields treating them as NULL Make _all_ functions and operators null-safe aware, including when used in filtering or sorting contexts Add missing and null-safe doc value extractor Modify dataset to have null fields spread around (in groups of 10) Enforce missing last and unmapped_type inside sorting Consolidate Predicate templating and declaration Add support for Like/RLike in scripting Introduce early schema declaration for CSV spec tests: to keep the doc snippets in place, introduce schema:: prefix to declare the CSV schema upfront. Fix #32079 --- x-pack/plugin/sql/src/main/antlr/SqlBase.g4 | 5 +- .../plugin/sql/src/main/antlr/SqlBase.tokens | 294 ++-- .../sql/src/main/antlr/SqlBaseLexer.tokens | 292 ++-- .../sql/execution/search/SourceGenerator.java | 11 +- .../extractor/CompositeKeyExtractor.java | 4 +- .../function/scalar/BinaryScalarFunction.java | 10 +- .../scalar/datetime/DateTimeFunction.java | 7 +- .../function/scalar/math/BinaryMathPipe.java | 3 +- .../scalar/math/BinaryMathProcessor.java | 29 +- .../scalar/math/BinaryNumericFunction.java | 19 +- .../scalar/math/BinaryNumericProcessor.java | 76 - .../expression/function/scalar/math/Cot.java | 10 - .../function/scalar/math/Degrees.java | 5 - .../function/scalar/math/MathFunction.java | 2 +- .../function/scalar/math/MathProcessor.java | 16 +- .../function/scalar/math/Power.java | 5 - .../function/scalar/math/Random.java | 11 - .../function/scalar/math/Round.java | 17 - .../function/scalar/math/Truncate.java | 17 - .../scalar/string/BinaryStringFunction.java | 14 +- .../string/BinaryStringNumericPipe.java | 4 +- .../string/BinaryStringNumericProcessor.java | 58 +- .../scalar/string/BinaryStringProcessor.java | 59 - .../scalar/string/BinaryStringStringPipe.java | 3 +- .../string/BinaryStringStringProcessor.java | 48 +- .../function/scalar/string/Concat.java | 19 +- .../scalar/string/ConcatFunctionPipe.java | 3 +- .../string/ConcatFunctionProcessor.java | 23 +- .../string/LocateFunctionProcessor.java | 6 +- .../scalar/string/StringProcessor.java | 19 +- .../whitelist/InternalSqlScriptUtils.java | 292 +++- .../gen/processor/BinaryProcessor.java | 21 +- .../processor/FunctionalBinaryProcessor.java | 68 + .../expression/gen/script/ScriptWeaver.java | 3 +- .../sql/expression/gen/script/Scripts.java | 91 ++ .../expression/predicate/BinaryOperator.java | 10 +- .../expression/predicate/BinaryPredicate.java | 51 +- .../predicate/PredicateBiFunction.java | 32 + .../sql/expression/predicate/Predicates.java | 2 + .../xpack/sql/expression/predicate/Range.java | 103 +- .../predicate/{ => logical}/And.java | 18 +- .../predicate/{ => logical}/BinaryLogic.java | 20 +- .../predicate/logical/BinaryLogicPipe.java | 54 + .../logical/BinaryLogicProcessor.java | 91 ++ .../predicate/{ => logical}/Not.java | 2 +- .../predicate/{ => logical}/Or.java | 14 +- .../arithmetic/ArithmeticOperation.java | 35 +- .../arithmetic/BinaryArithmeticPipe.java | 6 +- .../arithmetic/BinaryArithmeticProcessor.java | 23 +- .../operator/comparison/BinaryComparison.java | 43 +- .../comparison/BinaryComparisonPipe.java | 3 +- .../comparison/BinaryComparisonProcessor.java | 15 +- .../comparison/BinaryOperatorProcessor.java | 76 - .../sql/expression/predicate/regex/Like.java | 48 +- .../sql/expression/predicate/regex/RLike.java | 40 +- .../predicate/regex/RegexMatch.java | 40 + .../expression/predicate/regex/RegexPipe.java | 34 + .../predicate/regex/RegexProcessor.java | 98 ++ .../xpack/sql/optimizer/Optimizer.java | 14 +- .../xpack/sql/parser/ExpressionBuilder.java | 13 +- .../xpack/sql/parser/SqlBaseLexer.java | 636 ++++---- .../xpack/sql/parser/SqlBaseParser.java | 1332 +++++++++-------- .../xpack/sql/planner/QueryTranslator.java | 18 +- .../xpack/sql/querydsl/agg/AggFilter.java | 10 +- .../xpack/sql/querydsl/agg/AndAggFilter.java | 17 +- .../xpack/sql/querydsl/agg/OrAggFilter.java | 17 +- .../sql/querydsl/container/ScriptSort.java | 4 +- .../xpack/sql/querydsl/query/ScriptQuery.java | 8 +- .../xpack/sql/util/ReflectionUtils.java | 12 +- .../xpack/sql/plugin/sql_whitelist.txt | 107 +- .../search/SourceGeneratorTests.java | 7 +- .../scalar/string/ConcatProcessorTests.java | 6 +- .../xpack/sql/optimizer/OptimizerTests.java | 8 +- .../sql/parser/EscapedFunctionsTests.java | 2 +- .../sql/parser/LikeEscapingParsingTests.java | 2 +- .../qa/sql/nosecurity/JdbcDocCsvSpecIT.java | 4 +- .../xpack/qa/sql/jdbc/CsvSpecTestCase.java | 3 +- .../xpack/qa/sql/jdbc/CsvTestUtils.java | 40 +- .../xpack/qa/sql/jdbc/DataLoader.java | 13 +- .../xpack/qa/sql/jdbc/JdbcAssert.java | 8 +- .../xpack/qa/sql/jdbc/LocalH2.java | 33 +- .../xpack/qa/sql/jdbc/SqlSpecTestCase.java | 2 - .../xpack/qa/sql/rest/RestSqlTestCase.java | 6 +- x-pack/qa/sql/src/main/resources/agg.csv-spec | 45 +- x-pack/qa/sql/src/main/resources/agg.sql-spec | 34 +- .../sql/src/main/resources/agg_nulls.sql-spec | 14 - .../qa/sql/src/main/resources/alias.csv-spec | 6 +- .../main/resources/case-functions.sql-spec | 4 +- .../sql/src/main/resources/columns.csv-spec | 1 + .../sql/src/main/resources/command.csv-spec | 3 - .../sql/src/main/resources/datetime.csv-spec | 116 +- .../qa/sql/src/main/resources/docs.csv-spec | 99 +- .../qa/sql/src/main/resources/employees.csv | 80 +- .../main/resources/employees_with_nulls.csv | 101 -- .../sql/src/main/resources/example.csv-spec | 4 + .../sql/src/main/resources/functions.csv-spec | 486 +++--- .../qa/sql/src/main/resources/math.csv-spec | 115 +- .../qa/sql/src/main/resources/nested.csv-spec | 40 +- .../resources/setup_test_emp_with_nulls.sql | 12 - .../main/resources/string-functions.sql-spec | 14 +- 100 files changed, 3171 insertions(+), 2747 deletions(-) delete mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericProcessor.java delete mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringProcessor.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/processor/FunctionalBinaryProcessor.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/Scripts.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/PredicateBiFunction.java rename x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/{ => logical}/And.java (74%) rename x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/{ => logical}/BinaryLogic.java (60%) create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogicPipe.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogicProcessor.java rename x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/{ => logical}/Not.java (97%) rename x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/{ => logical}/Or.java (74%) delete mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryOperatorProcessor.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexMatch.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexPipe.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexProcessor.java delete mode 100644 x-pack/qa/sql/src/main/resources/agg_nulls.sql-spec delete mode 100644 x-pack/qa/sql/src/main/resources/employees_with_nulls.csv delete mode 100644 x-pack/qa/sql/src/main/resources/setup_test_emp_with_nulls.sql diff --git a/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 b/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 index 75dd646d9326c..859cc26bf9ca5 100644 --- a/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 +++ b/x-pack/plugin/sql/src/main/antlr/SqlBase.g4 @@ -88,7 +88,7 @@ queryTerm ; orderBy - : expression ordering=(ASC | DESC)? + : expression ordering=(ASC | DESC)? (NULLS nullOrdering=(FIRST | LAST))? ; querySpecification @@ -357,6 +357,7 @@ EXISTS: 'EXISTS'; EXPLAIN: 'EXPLAIN'; EXTRACT: 'EXTRACT'; FALSE: 'FALSE'; +FIRST: 'FIRST'; FORMAT: 'FORMAT'; FROM: 'FROM'; FULL: 'FULL'; @@ -368,6 +369,7 @@ IN: 'IN'; INNER: 'INNER'; IS: 'IS'; JOIN: 'JOIN'; +LAST: 'LAST'; LEFT: 'LEFT'; LIKE: 'LIKE'; LIMIT: 'LIMIT'; @@ -376,6 +378,7 @@ MATCH: 'MATCH'; NATURAL: 'NATURAL'; NOT: 'NOT'; NULL: 'NULL'; +NULLS: 'NULLS'; ON: 'ON'; OPTIMIZED: 'OPTIMIZED'; OR: 'OR'; diff --git a/x-pack/plugin/sql/src/main/antlr/SqlBase.tokens b/x-pack/plugin/sql/src/main/antlr/SqlBase.tokens index 527cc676e1d80..1a90fb72ef51b 100644 --- a/x-pack/plugin/sql/src/main/antlr/SqlBase.tokens +++ b/x-pack/plugin/sql/src/main/antlr/SqlBase.tokens @@ -25,85 +25,88 @@ EXISTS=24 EXPLAIN=25 EXTRACT=26 FALSE=27 -FORMAT=28 -FROM=29 -FULL=30 -FUNCTIONS=31 -GRAPHVIZ=32 -GROUP=33 -HAVING=34 -IN=35 -INNER=36 -IS=37 -JOIN=38 -LEFT=39 -LIKE=40 -LIMIT=41 -MAPPED=42 -MATCH=43 -NATURAL=44 -NOT=45 -NULL=46 -ON=47 -OPTIMIZED=48 -OR=49 -ORDER=50 -OUTER=51 -PARSED=52 -PHYSICAL=53 -PLAN=54 -RIGHT=55 -RLIKE=56 -QUERY=57 -SCHEMAS=58 -SELECT=59 -SHOW=60 -SYS=61 -TABLE=62 -TABLES=63 -TEXT=64 -TRUE=65 -TYPE=66 -TYPES=67 -USING=68 -VERIFY=69 -WHERE=70 -WITH=71 -ESCAPE_ESC=72 -FUNCTION_ESC=73 -LIMIT_ESC=74 -DATE_ESC=75 -TIME_ESC=76 -TIMESTAMP_ESC=77 -GUID_ESC=78 -ESC_END=79 -EQ=80 -NEQ=81 -LT=82 -LTE=83 -GT=84 -GTE=85 -PLUS=86 -MINUS=87 -ASTERISK=88 -SLASH=89 -PERCENT=90 -CONCAT=91 -DOT=92 -PARAM=93 -STRING=94 -INTEGER_VALUE=95 -DECIMAL_VALUE=96 -IDENTIFIER=97 -DIGIT_IDENTIFIER=98 -TABLE_IDENTIFIER=99 -QUOTED_IDENTIFIER=100 -BACKQUOTED_IDENTIFIER=101 -SIMPLE_COMMENT=102 -BRACKETED_COMMENT=103 -WS=104 -UNRECOGNIZED=105 -DELIMITER=106 +FIRST=28 +FORMAT=29 +FROM=30 +FULL=31 +FUNCTIONS=32 +GRAPHVIZ=33 +GROUP=34 +HAVING=35 +IN=36 +INNER=37 +IS=38 +JOIN=39 +LAST=40 +LEFT=41 +LIKE=42 +LIMIT=43 +MAPPED=44 +MATCH=45 +NATURAL=46 +NOT=47 +NULL=48 +NULLS=49 +ON=50 +OPTIMIZED=51 +OR=52 +ORDER=53 +OUTER=54 +PARSED=55 +PHYSICAL=56 +PLAN=57 +RIGHT=58 +RLIKE=59 +QUERY=60 +SCHEMAS=61 +SELECT=62 +SHOW=63 +SYS=64 +TABLE=65 +TABLES=66 +TEXT=67 +TRUE=68 +TYPE=69 +TYPES=70 +USING=71 +VERIFY=72 +WHERE=73 +WITH=74 +ESCAPE_ESC=75 +FUNCTION_ESC=76 +LIMIT_ESC=77 +DATE_ESC=78 +TIME_ESC=79 +TIMESTAMP_ESC=80 +GUID_ESC=81 +ESC_END=82 +EQ=83 +NEQ=84 +LT=85 +LTE=86 +GT=87 +GTE=88 +PLUS=89 +MINUS=90 +ASTERISK=91 +SLASH=92 +PERCENT=93 +CONCAT=94 +DOT=95 +PARAM=96 +STRING=97 +INTEGER_VALUE=98 +DECIMAL_VALUE=99 +IDENTIFIER=100 +DIGIT_IDENTIFIER=101 +TABLE_IDENTIFIER=102 +QUOTED_IDENTIFIER=103 +BACKQUOTED_IDENTIFIER=104 +SIMPLE_COMMENT=105 +BRACKETED_COMMENT=106 +WS=107 +UNRECOGNIZED=108 +DELIMITER=109 '('=1 ')'=2 ','=3 @@ -131,68 +134,71 @@ DELIMITER=106 'EXPLAIN'=25 'EXTRACT'=26 'FALSE'=27 -'FORMAT'=28 -'FROM'=29 -'FULL'=30 -'FUNCTIONS'=31 -'GRAPHVIZ'=32 -'GROUP'=33 -'HAVING'=34 -'IN'=35 -'INNER'=36 -'IS'=37 -'JOIN'=38 -'LEFT'=39 -'LIKE'=40 -'LIMIT'=41 -'MAPPED'=42 -'MATCH'=43 -'NATURAL'=44 -'NOT'=45 -'NULL'=46 -'ON'=47 -'OPTIMIZED'=48 -'OR'=49 -'ORDER'=50 -'OUTER'=51 -'PARSED'=52 -'PHYSICAL'=53 -'PLAN'=54 -'RIGHT'=55 -'RLIKE'=56 -'QUERY'=57 -'SCHEMAS'=58 -'SELECT'=59 -'SHOW'=60 -'SYS'=61 -'TABLE'=62 -'TABLES'=63 -'TEXT'=64 -'TRUE'=65 -'TYPE'=66 -'TYPES'=67 -'USING'=68 -'VERIFY'=69 -'WHERE'=70 -'WITH'=71 -'{ESCAPE'=72 -'{FN'=73 -'{LIMIT'=74 -'{D'=75 -'{T'=76 -'{TS'=77 -'{GUID'=78 -'}'=79 -'='=80 -'<'=82 -'<='=83 -'>'=84 -'>='=85 -'+'=86 -'-'=87 -'*'=88 -'/'=89 -'%'=90 -'||'=91 -'.'=92 -'?'=93 +'FIRST'=28 +'FORMAT'=29 +'FROM'=30 +'FULL'=31 +'FUNCTIONS'=32 +'GRAPHVIZ'=33 +'GROUP'=34 +'HAVING'=35 +'IN'=36 +'INNER'=37 +'IS'=38 +'JOIN'=39 +'LAST'=40 +'LEFT'=41 +'LIKE'=42 +'LIMIT'=43 +'MAPPED'=44 +'MATCH'=45 +'NATURAL'=46 +'NOT'=47 +'NULL'=48 +'NULLS'=49 +'ON'=50 +'OPTIMIZED'=51 +'OR'=52 +'ORDER'=53 +'OUTER'=54 +'PARSED'=55 +'PHYSICAL'=56 +'PLAN'=57 +'RIGHT'=58 +'RLIKE'=59 +'QUERY'=60 +'SCHEMAS'=61 +'SELECT'=62 +'SHOW'=63 +'SYS'=64 +'TABLE'=65 +'TABLES'=66 +'TEXT'=67 +'TRUE'=68 +'TYPE'=69 +'TYPES'=70 +'USING'=71 +'VERIFY'=72 +'WHERE'=73 +'WITH'=74 +'{ESCAPE'=75 +'{FN'=76 +'{LIMIT'=77 +'{D'=78 +'{T'=79 +'{TS'=80 +'{GUID'=81 +'}'=82 +'='=83 +'<'=85 +'<='=86 +'>'=87 +'>='=88 +'+'=89 +'-'=90 +'*'=91 +'/'=92 +'%'=93 +'||'=94 +'.'=95 +'?'=96 diff --git a/x-pack/plugin/sql/src/main/antlr/SqlBaseLexer.tokens b/x-pack/plugin/sql/src/main/antlr/SqlBaseLexer.tokens index 155d4860e0ea0..b3ca016bb4584 100644 --- a/x-pack/plugin/sql/src/main/antlr/SqlBaseLexer.tokens +++ b/x-pack/plugin/sql/src/main/antlr/SqlBaseLexer.tokens @@ -25,84 +25,87 @@ EXISTS=24 EXPLAIN=25 EXTRACT=26 FALSE=27 -FORMAT=28 -FROM=29 -FULL=30 -FUNCTIONS=31 -GRAPHVIZ=32 -GROUP=33 -HAVING=34 -IN=35 -INNER=36 -IS=37 -JOIN=38 -LEFT=39 -LIKE=40 -LIMIT=41 -MAPPED=42 -MATCH=43 -NATURAL=44 -NOT=45 -NULL=46 -ON=47 -OPTIMIZED=48 -OR=49 -ORDER=50 -OUTER=51 -PARSED=52 -PHYSICAL=53 -PLAN=54 -RIGHT=55 -RLIKE=56 -QUERY=57 -SCHEMAS=58 -SELECT=59 -SHOW=60 -SYS=61 -TABLE=62 -TABLES=63 -TEXT=64 -TRUE=65 -TYPE=66 -TYPES=67 -USING=68 -VERIFY=69 -WHERE=70 -WITH=71 -ESCAPE_ESC=72 -FUNCTION_ESC=73 -LIMIT_ESC=74 -DATE_ESC=75 -TIME_ESC=76 -TIMESTAMP_ESC=77 -GUID_ESC=78 -ESC_END=79 -EQ=80 -NEQ=81 -LT=82 -LTE=83 -GT=84 -GTE=85 -PLUS=86 -MINUS=87 -ASTERISK=88 -SLASH=89 -PERCENT=90 -CONCAT=91 -DOT=92 -PARAM=93 -STRING=94 -INTEGER_VALUE=95 -DECIMAL_VALUE=96 -IDENTIFIER=97 -DIGIT_IDENTIFIER=98 -TABLE_IDENTIFIER=99 -QUOTED_IDENTIFIER=100 -BACKQUOTED_IDENTIFIER=101 -SIMPLE_COMMENT=102 -BRACKETED_COMMENT=103 -WS=104 -UNRECOGNIZED=105 +FIRST=28 +FORMAT=29 +FROM=30 +FULL=31 +FUNCTIONS=32 +GRAPHVIZ=33 +GROUP=34 +HAVING=35 +IN=36 +INNER=37 +IS=38 +JOIN=39 +LAST=40 +LEFT=41 +LIKE=42 +LIMIT=43 +MAPPED=44 +MATCH=45 +NATURAL=46 +NOT=47 +NULL=48 +NULLS=49 +ON=50 +OPTIMIZED=51 +OR=52 +ORDER=53 +OUTER=54 +PARSED=55 +PHYSICAL=56 +PLAN=57 +RIGHT=58 +RLIKE=59 +QUERY=60 +SCHEMAS=61 +SELECT=62 +SHOW=63 +SYS=64 +TABLE=65 +TABLES=66 +TEXT=67 +TRUE=68 +TYPE=69 +TYPES=70 +USING=71 +VERIFY=72 +WHERE=73 +WITH=74 +ESCAPE_ESC=75 +FUNCTION_ESC=76 +LIMIT_ESC=77 +DATE_ESC=78 +TIME_ESC=79 +TIMESTAMP_ESC=80 +GUID_ESC=81 +ESC_END=82 +EQ=83 +NEQ=84 +LT=85 +LTE=86 +GT=87 +GTE=88 +PLUS=89 +MINUS=90 +ASTERISK=91 +SLASH=92 +PERCENT=93 +CONCAT=94 +DOT=95 +PARAM=96 +STRING=97 +INTEGER_VALUE=98 +DECIMAL_VALUE=99 +IDENTIFIER=100 +DIGIT_IDENTIFIER=101 +TABLE_IDENTIFIER=102 +QUOTED_IDENTIFIER=103 +BACKQUOTED_IDENTIFIER=104 +SIMPLE_COMMENT=105 +BRACKETED_COMMENT=106 +WS=107 +UNRECOGNIZED=108 '('=1 ')'=2 ','=3 @@ -130,68 +133,71 @@ UNRECOGNIZED=105 'EXPLAIN'=25 'EXTRACT'=26 'FALSE'=27 -'FORMAT'=28 -'FROM'=29 -'FULL'=30 -'FUNCTIONS'=31 -'GRAPHVIZ'=32 -'GROUP'=33 -'HAVING'=34 -'IN'=35 -'INNER'=36 -'IS'=37 -'JOIN'=38 -'LEFT'=39 -'LIKE'=40 -'LIMIT'=41 -'MAPPED'=42 -'MATCH'=43 -'NATURAL'=44 -'NOT'=45 -'NULL'=46 -'ON'=47 -'OPTIMIZED'=48 -'OR'=49 -'ORDER'=50 -'OUTER'=51 -'PARSED'=52 -'PHYSICAL'=53 -'PLAN'=54 -'RIGHT'=55 -'RLIKE'=56 -'QUERY'=57 -'SCHEMAS'=58 -'SELECT'=59 -'SHOW'=60 -'SYS'=61 -'TABLE'=62 -'TABLES'=63 -'TEXT'=64 -'TRUE'=65 -'TYPE'=66 -'TYPES'=67 -'USING'=68 -'VERIFY'=69 -'WHERE'=70 -'WITH'=71 -'{ESCAPE'=72 -'{FN'=73 -'{LIMIT'=74 -'{D'=75 -'{T'=76 -'{TS'=77 -'{GUID'=78 -'}'=79 -'='=80 -'<'=82 -'<='=83 -'>'=84 -'>='=85 -'+'=86 -'-'=87 -'*'=88 -'/'=89 -'%'=90 -'||'=91 -'.'=92 -'?'=93 +'FIRST'=28 +'FORMAT'=29 +'FROM'=30 +'FULL'=31 +'FUNCTIONS'=32 +'GRAPHVIZ'=33 +'GROUP'=34 +'HAVING'=35 +'IN'=36 +'INNER'=37 +'IS'=38 +'JOIN'=39 +'LAST'=40 +'LEFT'=41 +'LIKE'=42 +'LIMIT'=43 +'MAPPED'=44 +'MATCH'=45 +'NATURAL'=46 +'NOT'=47 +'NULL'=48 +'NULLS'=49 +'ON'=50 +'OPTIMIZED'=51 +'OR'=52 +'ORDER'=53 +'OUTER'=54 +'PARSED'=55 +'PHYSICAL'=56 +'PLAN'=57 +'RIGHT'=58 +'RLIKE'=59 +'QUERY'=60 +'SCHEMAS'=61 +'SELECT'=62 +'SHOW'=63 +'SYS'=64 +'TABLE'=65 +'TABLES'=66 +'TEXT'=67 +'TRUE'=68 +'TYPE'=69 +'TYPES'=70 +'USING'=71 +'VERIFY'=72 +'WHERE'=73 +'WITH'=74 +'{ESCAPE'=75 +'{FN'=76 +'{LIMIT'=77 +'{D'=78 +'{T'=79 +'{TS'=80 +'{GUID'=81 +'}'=82 +'='=83 +'<'=85 +'<='=86 +'>'=87 +'>='=88 +'+'=89 +'-'=90 +'*'=91 +'/'=92 +'%'=93 +'||'=94 +'.'=95 +'?'=96 diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/SourceGenerator.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/SourceGenerator.java index bac4fdcfb2a63..a3e8253ae2aad 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/SourceGenerator.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/SourceGenerator.java @@ -34,6 +34,7 @@ public abstract class SourceGenerator { private static final List NO_STORED_FIELD = singletonList(StoredFieldsContext._NONE_); + private static final String MISSING_LAST = "_last"; public static SearchSourceBuilder sourceBuilder(QueryContainer container, QueryBuilder filter, Integer size) { QueryBuilder finalQuery = null; @@ -110,9 +111,15 @@ private static void sorting(QueryContainer container, SearchSourceBuilder source FieldAttribute fa = (FieldAttribute) attr; fa = fa.isInexact() ? fa.exactAttribute() : fa; - sortBuilder = fieldSort(fa.name()); + sortBuilder = fieldSort(fa.name()) + .missing(MISSING_LAST) + .unmappedType(fa.dataType().esType); + if (fa.isNested()) { - FieldSortBuilder fieldSort = fieldSort(fa.name()); + FieldSortBuilder fieldSort = fieldSort(fa.name()) + .missing(MISSING_LAST) + .unmappedType(fa.dataType().esType); + NestedSortBuilder newSort = new NestedSortBuilder(fa.nestedParent().name()); NestedSortBuilder nestedSort = fieldSort.getNestedSort(); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/CompositeKeyExtractor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/CompositeKeyExtractor.java index e6a2f4adfe217..e8e2db4f052b2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/CompositeKeyExtractor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/CompositeKeyExtractor.java @@ -107,7 +107,9 @@ public Object extract(Bucket bucket) { Object object = ((Map) m).get(key); if (timeZone != null) { - if (object instanceof Long) { + if (object == null) { + return object; + } else if (object instanceof Long) { object = new DateTime(((Long) object).longValue(), DateTimeZone.forTimeZone(timeZone)); } else { throw new SqlIllegalArgumentException("Invalid date key returned: {}", object); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/BinaryScalarFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/BinaryScalarFunction.java index 5b9196f462b0a..706894388458a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/BinaryScalarFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/BinaryScalarFunction.java @@ -7,10 +7,12 @@ import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; +import org.elasticsearch.xpack.sql.expression.gen.script.Scripts; import org.elasticsearch.xpack.sql.tree.Location; import java.util.Arrays; import java.util.List; +import java.util.Locale; public abstract class BinaryScalarFunction extends ScalarFunction { @@ -53,5 +55,11 @@ public ScriptTemplate asScript() { return asScriptFrom(leftScript, rightScript); } - protected abstract ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript); + protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { + return Scripts.binaryMethod(scriptMethodName(), leftScript, rightScript, dataType()); + } + + protected String scriptMethodName() { + return getClass().getSimpleName().toLowerCase(Locale.ROOT); + } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java index 2ecfc27376de6..bb6944b60aa0b 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java @@ -47,12 +47,17 @@ public static Integer dateTimeChrono(long millis, String tzId, String chronoName return Integer.valueOf(time.get(ChronoField.valueOf(chronoName))); } + public static Integer dateTimeChrono(ZonedDateTime millis, String tzId, String chronoName) { + ZonedDateTime time = millis.withZoneSameInstant(ZoneId.of(tzId)); + return Integer.valueOf(time.get(ChronoField.valueOf(chronoName))); + } + @Override public ScriptTemplate scriptWithField(FieldAttribute field) { ParamsBuilder params = paramsBuilder(); String template = null; - template = formatTemplate("{sql}.dateTimeChrono(doc[{}].value.millis, {}, {})"); + template = formatTemplate("{sql}.dateTimeChrono(doc[{}].value, {}, {})"); params.variable(field.name()) .variable(timeZone().getID()) .variable(chronoField().name()); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathPipe.java index 0a598275c7fb7..199b333c566f5 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathPipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathPipe.java @@ -21,8 +21,7 @@ public class BinaryMathPipe extends BinaryPipe { private final BinaryMathOperation operation; - public BinaryMathPipe(Location location, Expression expression, Pipe left, - Pipe right, BinaryMathOperation operation) { + public BinaryMathPipe(Location location, Expression expression, Pipe left, Pipe right, BinaryMathOperation operation) { super(location, expression, left, right); this.operation = operation; } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessor.java index 3a4f6dd501453..397f84b4cf840 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessor.java @@ -6,10 +6,10 @@ package org.elasticsearch.xpack.sql.expression.function.scalar.math; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor.BinaryMathOperation; import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation; +import org.elasticsearch.xpack.sql.expression.gen.processor.FunctionalBinaryProcessor; import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Arithmetics; @@ -19,7 +19,7 @@ /** * Binary math operations. Sister class to {@link MathOperation}. */ -public class BinaryMathProcessor extends BinaryNumericProcessor { +public class BinaryMathProcessor extends FunctionalBinaryProcessor { public enum BinaryMathOperation implements BiFunction { @@ -27,12 +27,6 @@ public enum BinaryMathOperation implements BiFunction { MOD(Arithmetics::mod), POWER((l, r) -> Math.pow(l.doubleValue(), r.doubleValue())), ROUND((l, r) -> { - if (l == null) { - return null; - } - if (r == null) { - return l; - } if (r instanceof Float || r instanceof Double) { throw new SqlIllegalArgumentException("An integer number is required; received [{}] as second parameter", r); } @@ -43,12 +37,6 @@ public enum BinaryMathOperation implements BiFunction { return Math.round(Math.abs(middleResult)) / tenAtScale * sign; }), TRUNCATE((l, r) -> { - if (l == null) { - return null; - } - if (r == null) { - return l; - } if (r instanceof Float || r instanceof Double) { throw new SqlIllegalArgumentException("An integer number is required; received [{}] as second parameter", r); } @@ -66,6 +54,9 @@ public enum BinaryMathOperation implements BiFunction { @Override public final Number apply(Number left, Number right) { + if (left == null || right == null) { + return null; + } return process.apply(left, right); } } @@ -81,12 +72,14 @@ public BinaryMathProcessor(StreamInput in) throws IOException { } @Override - protected void doWrite(StreamOutput out) throws IOException { - out.writeEnum(operation()); + public String getWriteableName() { + return NAME; } @Override - public String getWriteableName() { - return NAME; + protected void checkParameter(Object param) { + if (!(param instanceof Number)) { + throw new SqlIllegalArgumentException("A number is required; received {}", param); + } } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericFunction.java index 4de63345aabeb..1d26a88c012aa 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericFunction.java @@ -10,16 +10,11 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.BinaryScalarFunction; import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor.BinaryMathOperation; import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.type.DataType; -import java.util.Locale; import java.util.Objects; -import static java.lang.String.format; -import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; - public abstract class BinaryNumericFunction extends BinaryScalarFunction { private final BinaryMathOperation operation; @@ -51,7 +46,7 @@ protected TypeResolution resolveType() { protected TypeResolution resolveInputType(DataType inputType) { return inputType.isNumeric() ? TypeResolution.TYPE_RESOLVED : - new TypeResolution("'%s' requires a numeric type, received %s", mathFunction(), inputType.esType); + new TypeResolution("'%s' requires a numeric type, received %s", scriptMethodName(), inputType.esType); } @Override @@ -64,18 +59,6 @@ protected Pipe makePipe() { return new BinaryMathPipe(location(), this, Expressions.pipe(left()), Expressions.pipe(right()), operation); } - @Override - protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - return new ScriptTemplate(format(Locale.ROOT, "Math.%s(%s,%s)", mathFunction(), leftScript.template(), rightScript.template()), - paramsBuilder() - .script(leftScript.params()).script(rightScript.params()) - .build(), dataType()); - } - - protected String mathFunction() { - return getClass().getSimpleName().toLowerCase(Locale.ROOT); - } - @Override public int hashCode() { return Objects.hash(left(), right(), operation); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericProcessor.java deleted file mode 100644 index 599db91673f89..0000000000000 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericProcessor.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.sql.expression.function.scalar.math; - -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; -import org.elasticsearch.xpack.sql.expression.gen.processor.BinaryProcessor; -import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; - -import java.io.IOException; -import java.util.Locale; -import java.util.Objects; -import java.util.function.BiFunction; - -public abstract class BinaryNumericProcessor & BiFunction> extends BinaryProcessor { - - private final O operation; - - protected BinaryNumericProcessor(Processor left, Processor right, O operation) { - super(left, right); - this.operation = operation; - } - - protected BinaryNumericProcessor(StreamInput in, Reader reader) throws IOException { - super(in); - operation = reader.read(in); - } - - protected O operation() { - return operation; - } - - @Override - protected Object doProcess(Object left, Object right) { - if (left == null || right == null) { - return null; - } - if (!(left instanceof Number)) { - throw new SqlIllegalArgumentException("A number is required; received {}", left); - } - if (!(right instanceof Number)) { - throw new SqlIllegalArgumentException("A number is required; received {}", right); - } - - return operation.apply((Number) left, (Number) right); - } - - @Override - public int hashCode() { - return Objects.hash(operation); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - BinaryNumericProcessor other = (BinaryNumericProcessor) obj; - return Objects.equals(operation, other.operation) - && Objects.equals(left(), other.left()) - && Objects.equals(right(), other.right()); - } - - @Override - public String toString() { - return String.format(Locale.ROOT, "(%s %s %s)", left(), operation, right()); - } -} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Cot.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Cot.java index 5bf51fd7a0f93..692b3e7cbd7f0 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Cot.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Cot.java @@ -10,10 +10,6 @@ import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import java.util.Locale; - -import static java.lang.String.format; - /** * Cotangent * function. @@ -33,12 +29,6 @@ protected Cot replaceChild(Expression newChild) { return new Cot(location(), newChild); } - @Override - public String processScript(String template) { - // FIXME: needs to be null aware - return super.processScript(format(Locale.ROOT, "1.0 / Math.tan(%s)", template)); - } - @Override protected MathOperation operation() { return MathOperation.COT; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Degrees.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Degrees.java index 138fda5bcaeb4..c7a2df1aae158 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Degrees.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Degrees.java @@ -29,11 +29,6 @@ protected Degrees replaceChild(Expression newChild) { return new Degrees(location(), newChild); } - @Override - protected String mathFunction() { - return "toDegrees"; - } - @Override protected MathOperation operation() { return MathOperation.DEGREES; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java index d119305322194..4b7ed1e74429a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java @@ -41,7 +41,7 @@ public Object fold() { @Override public String processScript(String template) { - return super.processScript(format(Locale.ROOT, "Math.%s(%s)", mathFunction(), template)); + return super.processScript(format(Locale.ROOT, "{sql}.%s(%s)", mathFunction(), template)); } protected String mathFunction() { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathProcessor.java index 07da9b2e3cc27..2f71f63484792 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathProcessor.java @@ -22,14 +22,14 @@ public class MathProcessor implements Processor { public enum MathOperation { ABS((Object l) -> { if (l instanceof Float) { - return Math.abs(((Float) l).floatValue()); + return Double.valueOf(Math.abs(((Float) l).floatValue())); } if (l instanceof Double) { return Math.abs(((Double) l).doubleValue()); } long lo = ((Number) l).longValue(); //handles the corner-case of Long.MIN_VALUE - return lo >= 0 ? lo : lo == Long.MIN_VALUE ? Long.MAX_VALUE : -lo; + return lo >= 0 ? lo : lo == Long.MIN_VALUE ? Double.valueOf(Long.MAX_VALUE) : -lo; }), ACOS(Math::acos), @@ -52,15 +52,15 @@ public enum MathOperation { RANDOM((Object l) -> l != null ? new Random(((Number) l).longValue()).nextDouble() : Randomness.get().nextDouble(), true), - SIGN((DoubleFunction) Math::signum), + SIGN((DoubleFunction) Math::signum), SIN(Math::sin), SINH(Math::sinh), SQRT(Math::sqrt), TAN(Math::tan); - private final Function apply; + private final Function apply; - MathOperation(Function apply) { + MathOperation(Function apply) { this(apply, false); } @@ -69,7 +69,7 @@ public enum MathOperation { * If true, nulls are passed through, otherwise the function is short-circuited * and null returned. */ - MathOperation(Function apply, boolean nullAware) { + MathOperation(Function apply, boolean nullAware) { if (nullAware) { this.apply = apply; } else { @@ -77,7 +77,7 @@ public enum MathOperation { } } - MathOperation(DoubleFunction apply) { + MathOperation(DoubleFunction apply) { this.apply = (Object l) -> l == null ? null : apply.apply(((Number) l).doubleValue()); } @@ -85,7 +85,7 @@ public enum MathOperation { this.apply = l -> supplier.get(); } - public final Object apply(Object l) { + public final Double apply(Object l) { return apply.apply(l); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Power.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Power.java index 03dbc41a34857..646fb80102fb2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Power.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Power.java @@ -25,9 +25,4 @@ protected NodeInfo info() { protected Power replaceChildren(Expression newLeft, Expression newRight) { return new Power(location(), newLeft, newRight); } - - @Override - protected String mathFunction() { - return "pow"; - } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Random.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Random.java index c3ee2201fdd2b..88b45ba613e2d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Random.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Random.java @@ -10,10 +10,6 @@ import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import java.util.Locale; - -import static java.lang.String.format; - /** * Returns a random double (using the given seed). */ @@ -33,13 +29,6 @@ protected Random replaceChild(Expression newChild) { return new Random(location(), newChild); } - @Override - public String processScript(String template) { - //TODO: Painless script uses Random since Randomness is not whitelisted - return super.processScript( - format(Locale.ROOT, "%s != null ? new Random((long) %s).nextDouble() : Math.random()", template, template)); - } - @Override protected MathOperation operation() { return MathOperation.RANDOM; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Round.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Round.java index d2e87daa0e29d..05244c2a74e95 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Round.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Round.java @@ -8,16 +8,10 @@ import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.expression.Literal; import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor.BinaryMathOperation; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; -import java.util.Locale; - -import static java.lang.String.format; -import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; - /** * Function that takes two parameters: one is the field/value itself, the other is a non-floating point numeric * which indicates how the rounding should behave. If positive, it will round the number till that parameter @@ -39,17 +33,6 @@ protected NodeInfo info() { protected Round replaceChildren(Expression newLeft, Expression newRight) { return new Round(location(), newLeft, newRight); } - - @Override - protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s)"), - mathFunction(), - leftScript.template(), - rightScript.template()), - paramsBuilder() - .script(leftScript.params()).script(rightScript.params()) - .build(), dataType()); - } @Override public DataType dataType() { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Truncate.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Truncate.java index 58fdede908767..2dedd75d5b323 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Truncate.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Truncate.java @@ -8,16 +8,10 @@ import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.expression.Literal; import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor.BinaryMathOperation; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; -import java.util.Locale; - -import static java.lang.String.format; -import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; - /** * Function that takes two parameters: one is the field/value itself, the other is a non-floating point numeric * which indicates how the truncation should behave. If positive, it will truncate the number till that @@ -40,17 +34,6 @@ protected Truncate replaceChildren(Expression newLeft, Expression newRight) { return new Truncate(location(), newLeft, newRight); } - @Override - protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s)"), - mathFunction(), - leftScript.template(), - rightScript.template()), - paramsBuilder() - .script(leftScript.params()).script(rightScript.params()) - .build(), dataType()); - } - @Override public DataType dataType() { return left().dataType(); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringFunction.java index 093d6c95e78fd..c1e7433444233 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringFunction.java @@ -16,7 +16,6 @@ import java.util.Objects; import java.util.function.BiFunction; -import static java.lang.String.format; import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; /** @@ -59,17 +58,10 @@ public Object fold() { } @Override - public ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - // basically, transform the script to InternalSqlScriptUtils.[function_name](function_or_field1, function_or_field2) - return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s)"), - operation().toString().toLowerCase(Locale.ROOT), - leftScript.template(), - rightScript.template()), - paramsBuilder() - .script(leftScript.params()).script(rightScript.params()) - .build(), dataType()); + protected String scriptMethodName() { + return operation().toString().toLowerCase(Locale.ROOT); } - + @Override public ScriptTemplate scriptWithField(FieldAttribute field) { return new ScriptTemplate(processScript("doc[{}].value"), diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericPipe.java index 55f5b677864b3..e8898533543da 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericPipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericPipe.java @@ -21,8 +21,8 @@ public class BinaryStringNumericPipe extends BinaryPipe { private final BinaryStringNumericOperation operation; - public BinaryStringNumericPipe(Location location, Expression expression, Pipe left, - Pipe right, BinaryStringNumericOperation operation) { + public BinaryStringNumericPipe(Location location, Expression expression, Pipe left, Pipe right, + BinaryStringNumericOperation operation) { super(location, expression, left, right); this.operation = operation; } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericProcessor.java index 164330dc9e61f..2296b46c4b4a8 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericProcessor.java @@ -6,9 +6,9 @@ package org.elasticsearch.xpack.sql.expression.function.scalar.string; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringNumericProcessor.BinaryStringNumericOperation; +import org.elasticsearch.xpack.sql.expression.gen.processor.FunctionalBinaryProcessor; import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; import java.io.IOException; @@ -18,32 +18,28 @@ * Processor class covering string manipulating functions that have the first parameter as string, * second parameter as numeric and a string result. */ -public class BinaryStringNumericProcessor extends BinaryStringProcessor { +public class BinaryStringNumericProcessor extends FunctionalBinaryProcessor { - public static final String NAME = "sn"; - - public BinaryStringNumericProcessor(StreamInput in) throws IOException { - super(in, i -> i.readEnum(BinaryStringNumericOperation.class)); - } - - public BinaryStringNumericProcessor(Processor left, Processor right, BinaryStringNumericOperation operation) { - super(left, right, operation); - } - public enum BinaryStringNumericOperation implements BiFunction { LEFT((s,c) -> { int i = c.intValue(); - if (i < 0) return ""; + if (i < 0) { + return ""; + } return i > s.length() ? s : s.substring(0, i); }), RIGHT((s,c) -> { int i = c.intValue(); - if (i < 0) return ""; + if (i < 0) { + return ""; + } return i > s.length() ? s : s.substring(s.length() - i); }), REPEAT((s,c) -> { int i = c.intValue(); - if (i <= 0) return null; + if (i <= 0) { + return null; + } StringBuilder sb = new StringBuilder(s.length() * i); for (int j = 0; j < i; j++) { @@ -57,23 +53,33 @@ public enum BinaryStringNumericOperation implements BiFunction op; - + @Override public String apply(String stringExp, Number count) { + if (stringExp == null || count == null) { + return null; + } return op.apply(stringExp, count); } } + public static final String NAME = "sn"; + + public BinaryStringNumericProcessor(Processor left, Processor right, BinaryStringNumericOperation operation) { + super(left, right, operation); + } + + public BinaryStringNumericProcessor(StreamInput in) throws IOException { + super(in, i -> i.readEnum(BinaryStringNumericOperation.class)); + } + @Override - protected void doWrite(StreamOutput out) throws IOException { - out.writeEnum(operation()); + public String getWriteableName() { + return NAME; } @Override protected Object doProcess(Object left, Object right) { - if (left == null || right == null) { - return null; - } if (!(left instanceof String || left instanceof Character)) { throw new SqlIllegalArgumentException("A string/char is required; received [{}]", left); } @@ -81,12 +87,6 @@ protected Object doProcess(Object left, Object right) { throw new SqlIllegalArgumentException("A number is required; received [{}]", right); } - return operation().apply(left instanceof Character ? left.toString() : (String) left, (Number) right); - } - - @Override - public String getWriteableName() { - return NAME; + return super.doProcess(left.toString(), right); } - -} +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringProcessor.java deleted file mode 100644 index b19a441b320b6..0000000000000 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringProcessor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.sql.expression.function.scalar.string; - -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.xpack.sql.expression.gen.processor.BinaryProcessor; -import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; - -import java.io.IOException; -import java.util.Objects; -import java.util.function.BiFunction; - -public abstract class BinaryStringProcessor & BiFunction, T, R> extends BinaryProcessor { - - private final O operation; - - public BinaryStringProcessor(Processor left, Processor right, O operation) { - super(left, right); - this.operation = operation; - } - - public BinaryStringProcessor(StreamInput in, Reader reader) throws IOException { - super(in); - operation = reader.read(in); - } - - protected O operation() { - return operation; - } - - @Override - public int hashCode() { - return Objects.hash(operation); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - BinaryStringProcessor other = (BinaryStringProcessor) obj; - return Objects.equals(operation, other.operation) - && Objects.equals(left(), other.left()) - && Objects.equals(right(), other.right()); - } - - @Override - public String toString() { - return operation.toString(); - } -} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringPipe.java index ec1ab78c42d99..c660a7bcf6f47 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringPipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringPipe.java @@ -21,8 +21,7 @@ public class BinaryStringStringPipe extends BinaryPipe { private final BinaryStringStringOperation operation; - public BinaryStringStringPipe(Location location, Expression expression, Pipe left, - Pipe right, BinaryStringStringOperation operation) { + public BinaryStringStringPipe(Location location, Expression expression, Pipe left, Pipe right, BinaryStringStringOperation operation) { super(location, expression, left, right); this.operation = operation; } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringProcessor.java index c10232d22d6a3..00836d2c28441 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringProcessor.java @@ -6,9 +6,9 @@ package org.elasticsearch.xpack.sql.expression.function.scalar.string; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringStringProcessor.BinaryStringStringOperation; +import org.elasticsearch.xpack.sql.expression.gen.processor.FunctionalBinaryProcessor; import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; import java.io.IOException; @@ -17,21 +17,10 @@ /** * Processor class covering string manipulating functions that have two string parameters and a numeric result. */ -public class BinaryStringStringProcessor extends BinaryStringProcessor { +public class BinaryStringStringProcessor extends FunctionalBinaryProcessor { - public static final String NAME = "ss"; - - public BinaryStringStringProcessor(StreamInput in) throws IOException { - super(in, i -> i.readEnum(BinaryStringStringOperation.class)); - } - - public BinaryStringStringProcessor(Processor left, Processor right, BinaryStringStringOperation operation) { - super(left, right, operation); - } - public enum BinaryStringStringOperation implements BiFunction { POSITION((sub,str) -> { - if (sub == null || str == null) return null; int pos = str.indexOf(sub); return pos < 0 ? 0 : pos+1; }); @@ -43,21 +32,31 @@ public enum BinaryStringStringOperation implements BiFunction op; @Override - public Number apply(String stringExpLeft, String stringExpRight) { - return op.apply(stringExpLeft, stringExpRight); + public Number apply(String left, String right) { + if (left == null || right == null) { + return null; + } + return op.apply(left, right); } } + public static final String NAME = "ss"; + + public BinaryStringStringProcessor(StreamInput in) throws IOException { + super(in, i -> i.readEnum(BinaryStringStringOperation.class)); + } + + public BinaryStringStringProcessor(Processor left, Processor right, BinaryStringStringOperation operation) { + super(left, right, operation); + } + @Override - protected void doWrite(StreamOutput out) throws IOException { - out.writeEnum(operation()); + public String getWriteableName() { + return NAME; } @Override protected Object doProcess(Object left, Object right) { - if (left == null || right == null) { - return null; - } if (!(left instanceof String || left instanceof Character)) { throw new SqlIllegalArgumentException("A string/char is required; received [{}]", left); } @@ -65,13 +64,6 @@ protected Object doProcess(Object left, Object right) { throw new SqlIllegalArgumentException("A string/char is required; received [{}]", right); } - return operation().apply(left instanceof Character ? left.toString() : (String) left, - right instanceof Character ? right.toString() : (String) right); + return super.doProcess(left.toString(), right.toString()); } - - @Override - public String getWriteableName() { - return NAME; - } - } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Concat.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Concat.java index f996402694651..9733160cdd993 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Concat.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Concat.java @@ -15,10 +15,7 @@ import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; -import java.util.Locale; - -import static java.lang.String.format; -import static org.elasticsearch.xpack.sql.expression.function.scalar.string.ConcatFunctionProcessor.doProcessInScripts; +import static org.elasticsearch.xpack.sql.expression.function.scalar.string.ConcatFunctionProcessor.process; import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; /** @@ -58,7 +55,7 @@ public boolean foldable() { @Override public Object fold() { - return doProcessInScripts(left().fold(), right().fold()); + return process(left().fold(), right().fold()); } @Override @@ -71,18 +68,6 @@ protected NodeInfo info() { return NodeInfo.create(this, Concat::new, left(), right()); } - @Override - protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - // basically, transform the script to InternalSqlScriptUtils.[function_name](function_or_field1, function_or_field2) - return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s)"), - "concat", - leftScript.template(), - rightScript.template()), - paramsBuilder() - .script(leftScript.params()).script(rightScript.params()) - .build(), dataType()); - } - @Override public ScriptTemplate scriptWithField(FieldAttribute field) { return new ScriptTemplate(processScript("doc[{}].value"), diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatFunctionPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatFunctionPipe.java index 82e65f88f1da8..6624f5434e37a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatFunctionPipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatFunctionPipe.java @@ -15,8 +15,7 @@ public class ConcatFunctionPipe extends BinaryPipe { - public ConcatFunctionPipe(Location location, Expression expression, Pipe left, - Pipe right) { + public ConcatFunctionPipe(Location location, Expression expression, Pipe left, Pipe right) { super(location, expression, left, right); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatFunctionProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatFunctionProcessor.java index 675851032ba7f..55dc1ea213f45 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatFunctionProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatFunctionProcessor.java @@ -10,6 +10,7 @@ import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.gen.processor.BinaryProcessor; import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; +import org.elasticsearch.xpack.sql.util.StringUtils; import java.io.IOException; import java.util.Objects; @@ -27,14 +28,26 @@ public ConcatFunctionProcessor(StreamInput in) throws IOException { } @Override - protected Object doProcess(Object source1, Object source2) { - return doProcessInScripts(source1, source2); + public Object process(Object input) { + Object l = left().process(input); + checkParameter(l); + Object r = right().process(input); + checkParameter(r); + return doProcess(l, r); } - + + @Override + protected Object doProcess(Object left, Object right) { + return process(left, right); + } + /** * Used in Painless scripting */ - public static Object doProcessInScripts(Object source1, Object source2) { + public static Object process(Object source1, Object source2) { + if (source1 == null && source2 == null) { + return StringUtils.EMPTY; + } if (source1 == null) { return source2; } @@ -79,4 +92,4 @@ public int hashCode() { @Override protected void doWrite(StreamOutput out) throws IOException { } -} +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LocateFunctionProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LocateFunctionProcessor.java index dc26a4869c0d9..0509efa04a766 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LocateFunctionProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LocateFunctionProcessor.java @@ -42,7 +42,7 @@ public Object process(Object input) { return doProcess(pattern().process(input), source().process(input), start() == null ? null : start().process(input)); } - public static Object doProcess(Object pattern, Object source, Object start) { + public static Integer doProcess(Object pattern, Object source, Object start) { if (source == null) { return null; } @@ -63,9 +63,9 @@ public static Object doProcess(Object pattern, Object source, Object start) { String stringSource = source instanceof Character ? source.toString() : (String) source; String stringPattern = pattern instanceof Character ? pattern.toString() : (String) pattern; - return 1 + (start != null ? + return Integer.valueOf(1 + (start != null ? stringSource.indexOf(stringPattern, ((Number) start).intValue() - 1) - : stringSource.indexOf(stringPattern)); + : stringSource.indexOf(stringPattern))); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/StringProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/StringProcessor.java index bbeeb417c59e9..af8aff0725a1a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/StringProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/StringProcessor.java @@ -71,29 +71,12 @@ public enum StringOperation { private final Function apply; StringOperation(StringFunction apply) { - this.apply = l -> l == null ? null : apply.apply(l); + this.apply = l -> l == null ? null : apply.apply((l)); } StringOperation(NumericFunction apply) { this.apply = l -> l == null ? null : apply.apply((l)); } - - StringOperation(Function apply) { - this(apply, false); - } - - /** - * Wrapper for nulls around the given function. - * If true, nulls are passed through, otherwise the function is short-circuited - * and null returned. - */ - StringOperation(Function apply, boolean nullAware) { - if (nullAware) { - this.apply = apply; - } else { - this.apply = l -> l == null ? null : apply.apply(l); - } - } public final Object apply(Object l) { return apply.apply(l); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java index ec52d64cfbf23..d7b63019a0ae1 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java @@ -5,10 +5,14 @@ */ package org.elasticsearch.xpack.sql.expression.function.scalar.whitelist; +import org.elasticsearch.index.fielddata.ScriptDocValues; +import org.elasticsearch.script.JodaCompatibleZonedDateTime; +import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeFunction; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NamedDateTimeProcessor.NameExtractor; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.QuarterProcessor; import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor.BinaryMathOperation; +import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation; import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringNumericProcessor.BinaryStringNumericOperation; import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringStringProcessor.BinaryStringStringOperation; import org.elasticsearch.xpack.sql.expression.function.scalar.string.ConcatFunctionProcessor; @@ -17,6 +21,13 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.string.ReplaceFunctionProcessor; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; import org.elasticsearch.xpack.sql.expression.function.scalar.string.SubstringFunctionProcessor; +import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation; +import org.elasticsearch.xpack.sql.expression.predicate.regex.RegexProcessor.RegexOperation; +import org.elasticsearch.xpack.sql.util.StringUtils; + +import java.util.Map; /** * Whitelisted class for SQL scripts. @@ -27,30 +38,243 @@ public final class InternalSqlScriptUtils { private InternalSqlScriptUtils() {} - public static Integer dateTimeChrono(long millis, String tzId, String chronoName) { - return DateTimeFunction.dateTimeChrono(millis, tzId, chronoName); + // + // Utilities + // + + // safe missing mapping/value extractor + public static Object docValue(Map> doc, String fieldName) { + if (doc.containsKey(fieldName)) { + ScriptDocValues docValues = doc.get(fieldName); + if (docValues.size() > 0) { + return docValues.get(0); + } + } + return null; } - public static String dayName(long millis, String tzId) { - return NameExtractor.DAY_NAME.extract(millis, tzId); + public static boolean nullSafeFilter(Boolean filter) { + return filter == null ? false : filter.booleanValue(); } - - public static String monthName(long millis, String tzId) { - return NameExtractor.MONTH_NAME.extract(millis, tzId); + + public static double nullSafeSortNumeric(Number sort) { + return sort == null ? 0.0d : sort.doubleValue(); + } + + public static String nullSafeSortString(Object sort) { + return sort == null ? StringUtils.EMPTY : sort.toString(); + } + + + // + // Operators + // + + // + // Logical + // + public static Boolean eq(Object left, Object right) { + return BinaryComparisonOperation.EQ.apply(left, right); + } + + public static Boolean lt(Object left, Object right) { + return BinaryComparisonOperation.LT.apply(left, right); } - public static Integer quarter(long millis, String tzId) { - return QuarterProcessor.quarter(millis, tzId); + public static Boolean lte(Object left, Object right) { + return BinaryComparisonOperation.LTE.apply(left, right); + } + + public static Boolean gt(Object left, Object right) { + return BinaryComparisonOperation.GT.apply(left, right); + } + + public static Boolean gte(Object left, Object right) { + return BinaryComparisonOperation.GTE.apply(left, right); + } + + public static Boolean and(Boolean left, Boolean right) { + return BinaryLogicOperation.AND.apply(left, right); } + public static Boolean or(Boolean left, Boolean right) { + return BinaryLogicOperation.OR.apply(left, right); + } + + // + // Regex + // + public static Boolean regex(String value, String pattern) { + return RegexOperation.match(value, pattern); + } + + // + // Math + // + public static Number add(Number left, Number right) { + return BinaryArithmeticOperation.ADD.apply(left, right); + } + + public static Number sub(Number left, Number right) { + return BinaryArithmeticOperation.SUB.apply(left, right); + } + + public static Number mul(Number left, Number right) { + return BinaryArithmeticOperation.MUL.apply(left, right); + } + + public static Number div(Number left, Number right) { + return BinaryArithmeticOperation.DIV.apply(left, right); + } + + public static Number mod(Number left, Number right) { + return BinaryArithmeticOperation.MOD.apply(left, right); + } + public static Number round(Number v, Number s) { return BinaryMathOperation.ROUND.apply(v, s); } - + public static Number truncate(Number v, Number s) { return BinaryMathOperation.TRUNCATE.apply(v, s); } + + public static Double abs(Number value) { + return MathOperation.ABS.apply(value); + } + + public static Double acos(Number value) { + return MathOperation.ACOS.apply(value); + } + + public static Double asin(Number value) { + return MathOperation.ASIN.apply(value); + } + + public static Double atan(Number value) { + return MathOperation.ATAN.apply(value); + } + + public static Double cbrt(Number value) { + return MathOperation.CBRT.apply(value); + } + + public static Double ceil(Number value) { + return MathOperation.CEIL.apply(value); + } + + public static Double cos(Number value) { + return MathOperation.COS.apply(value); + } + + public static Double cosh(Number value) { + return MathOperation.COSH.apply(value); + } + + public static Double cot(Number value) { + return MathOperation.COT.apply(value); + } + + public static Double degrees(Number value) { + return MathOperation.DEGREES.apply(value); + } + + public static Double e(Number value) { + return MathOperation.E.apply(value); + } + + public static Double exp(Number value) { + return MathOperation.EXP.apply(value); + } + + public static Double expm1(Number value) { + return MathOperation.EXPM1.apply(value); + } + + public static Double floor(Number value) { + return MathOperation.FLOOR.apply(value); + } + + public static Double log(Number value) { + return MathOperation.LOG.apply(value); + } + + public static Double log10(Number value) { + return MathOperation.LOG10.apply(value); + } + + public static Double pi(Number value) { + return MathOperation.PI.apply(value); + } + + public static Double radians(Number value) { + return MathOperation.RADIANS.apply(value); + } + + public static Double random(Number value) { + return MathOperation.RANDOM.apply(value); + } + + public static Double sign(Number value) { + return MathOperation.SIGN.apply(value); + } + + public static Double sin(Number value) { + return MathOperation.SIN.apply(value); + } + + public static Double sinh(Number value) { + return MathOperation.SINH.apply(value); + } + + public static Double sqrt(Number value) { + return MathOperation.SQRT.apply(value); + } + + public static Double tan(Number value) { + return MathOperation.TAN.apply(value); + } + + // + // Date/Time functions + // + public static Integer dateTimeChrono(Object dateTime, String tzId, String chronoName) { + if (dateTime == null || tzId == null || chronoName == null) { + return null; + } + // use dedicated method + if (dateTime instanceof JodaCompatibleZonedDateTime) { + return DateTimeFunction.dateTimeChrono(((JodaCompatibleZonedDateTime) dateTime).getZonedDateTime(), tzId, chronoName); + } + throw new SqlIllegalArgumentException("Invalid date encountered [{}]", dateTime); + } + + public static String dayName(Long millis, String tzId) { + if (millis == null || tzId == null) { + return null; + } + return NameExtractor.DAY_NAME.extract(millis, tzId); + } + + public static String monthName(Long millis, String tzId) { + if (millis == null || tzId == null) { + return null; + } + + return NameExtractor.MONTH_NAME.extract(millis, tzId); + } + + public static Integer quarter(Long millis, String tzId) { + if (millis == null || tzId == null) { + return null; + } + + return QuarterProcessor.quarter(millis, tzId); + } + // + // String functions + // public static Integer ascii(String s) { return (Integer) StringOperation.ASCII.apply(s); } @@ -58,43 +282,43 @@ public static Integer ascii(String s) { public static Integer bitLength(String s) { return (Integer) StringOperation.BIT_LENGTH.apply(s); } - + public static String character(Number n) { return (String) StringOperation.CHAR.apply(n); } - + public static Integer charLength(String s) { return (Integer) StringOperation.CHAR_LENGTH.apply(s); } public static String concat(String s1, String s2) { - return ConcatFunctionProcessor.doProcessInScripts(s1, s2).toString(); + return (String) ConcatFunctionProcessor.process(s1, s2); } - - public static String insert(String s, int start, int length, String r) { - return InsertFunctionProcessor.doProcess(s, start, length, r).toString(); + + public static String insert(String s, Number start, Number length, String r) { + return (String) InsertFunctionProcessor.doProcess(s, start, length, r); } - + public static String lcase(String s) { return (String) StringOperation.LCASE.apply(s); } - - public static String left(String s, int count) { + + public static String left(String s, Number count) { return BinaryStringNumericOperation.LEFT.apply(s, count); } - + public static Integer length(String s) { return (Integer) StringOperation.LENGTH.apply(s); } - + public static Integer locate(String s1, String s2) { return locate(s1, s2, null); } - public static Integer locate(String s1, String s2, Integer pos) { - return (Integer) LocateFunctionProcessor.doProcess(s1, s2, pos); + public static Integer locate(String s1, String s2, Number pos) { + return LocateFunctionProcessor.doProcess(s1, s2, pos); } - + public static String ltrim(String s) { return (String) StringOperation.LTRIM.apply(s); } @@ -102,35 +326,35 @@ public static String ltrim(String s) { public static Integer octetLength(String s) { return (Integer) StringOperation.OCTET_LENGTH.apply(s); } - + public static Integer position(String s1, String s2) { return (Integer) BinaryStringStringOperation.POSITION.apply(s1, s2); } - public static String repeat(String s, int count) { + public static String repeat(String s, Number count) { return BinaryStringNumericOperation.REPEAT.apply(s, count); } public static String replace(String s1, String s2, String s3) { - return ReplaceFunctionProcessor.doProcess(s1, s2, s3).toString(); + return (String) ReplaceFunctionProcessor.doProcess(s1, s2, s3); } - public static String right(String s, int count) { + public static String right(String s, Number count) { return BinaryStringNumericOperation.RIGHT.apply(s, count); } - + public static String rtrim(String s) { return (String) StringOperation.RTRIM.apply(s); } - + public static String space(Number n) { return (String) StringOperation.SPACE.apply(n); } - - public static String substring(String s, int start, int length) { - return SubstringFunctionProcessor.doProcess(s, start, length).toString(); + + public static String substring(String s, Number start, Number length) { + return (String) SubstringFunctionProcessor.doProcess(s, start, length); } - + public static String ucase(String s) { return (String) StringOperation.UCASE.apply(s); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/processor/BinaryProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/processor/BinaryProcessor.java index c3222e2fa03a9..b504c2072fec6 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/processor/BinaryProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/processor/BinaryProcessor.java @@ -35,7 +35,26 @@ public final void writeTo(StreamOutput out) throws IOException { @Override public Object process(Object input) { - return doProcess(left.process(input), right.process(input)); + Object l = left.process(input); + if (l == null) { + return null; + } + checkParameter(l); + + Object r = right.process(input); + if (r == null) { + return null; + } + checkParameter(r); + + return doProcess(l, r); + } + + /** + * Checks the parameter (typically for its type) if the value is not null. + */ + protected void checkParameter(Object param) { + //no-op } protected Processor left() { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/processor/FunctionalBinaryProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/processor/FunctionalBinaryProcessor.java new file mode 100644 index 0000000000000..7e5d3a6089ca5 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/processor/FunctionalBinaryProcessor.java @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.expression.gen.processor; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; + +import java.io.IOException; +import java.util.Objects; +import java.util.function.BiFunction; + +/** + * Base class for definition binary processors based on functions (for applying) defined as enums (for serialization purposes). + */ +public abstract class FunctionalBinaryProcessor & BiFunction> extends BinaryProcessor { + + private final F function; + + protected FunctionalBinaryProcessor(Processor left, Processor right, F function) { + super(left, right); + this.function = function; + } + + protected FunctionalBinaryProcessor(StreamInput in, Reader reader) throws IOException { + super(in); + this.function = reader.read(in); + } + + public F function() { + return function; + } + + @Override + protected void doWrite(StreamOutput out) throws IOException { + out.writeEnum(function()); + } + + @SuppressWarnings("unchecked") + @Override + protected Object doProcess(Object left, Object right) { + return function.apply((T) left, (U) right); + } + + @Override + public int hashCode() { + return Objects.hash(left(), right(), function()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + FunctionalBinaryProcessor other = (FunctionalBinaryProcessor) obj; + return Objects.equals(function(), other.function()) + && Objects.equals(left(), other.left()) + && Objects.equals(right(), other.right()); + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/ScriptWeaver.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/ScriptWeaver.java index f171c03b1e433..da41ecbd8a44e 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/ScriptWeaver.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/ScriptWeaver.java @@ -13,7 +13,6 @@ import org.elasticsearch.xpack.sql.expression.FieldAttribute; import org.elasticsearch.xpack.sql.expression.function.aggregate.AggregateFunctionAttribute; import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunctionAttribute; -import org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalSqlScriptUtils; import org.elasticsearch.xpack.sql.type.DataType; import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; @@ -75,6 +74,6 @@ default String processScript(String script) { } default String formatTemplate(String template) { - return template.replace("{sql}", InternalSqlScriptUtils.class.getSimpleName()).replace("{}", "params.%s"); + return Scripts.formatTemplate(template); } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/Scripts.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/Scripts.java new file mode 100644 index 0000000000000..d0a159c50afd1 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/Scripts.java @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.expression.gen.script; + +import org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalSqlScriptUtils; +import org.elasticsearch.xpack.sql.type.DataType; + +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Pattern; + +import static java.lang.String.format; +import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; + +public final class Scripts { + + private Scripts() {} + + private static final Map FORMATTING_PATTERNS; + + static { + Map patterns = new LinkedHashMap<>(); + patterns.put("doc[{}].value", "{sql}.docValue(doc,{})"); + patterns.put("{sql}", InternalSqlScriptUtils.class.getSimpleName()); + patterns.put("{}", "params.%s"); + + FORMATTING_PATTERNS = new LinkedHashMap<>(); + + for (Entry entry : patterns.entrySet()) { + FORMATTING_PATTERNS.put(Pattern.compile(entry.getKey(), Pattern.LITERAL), entry.getValue()); + } + } + + /** + * Expands common tokens inside the script: + * + *
+     * {sql} -> InternalSqlScriptUtils
+     * doc[{}].value -> InternalSqlScriptUtils.docValue(doc, {})
+     * {}    -> params.%s
+     * 
+ */ + public static String formatTemplate(String template) { + for (Entry entry : FORMATTING_PATTERNS.entrySet()) { + template = entry.getKey().matcher(template).replaceAll(entry.getValue()); + } + return template; + } + + public static ScriptTemplate nullSafeFilter(ScriptTemplate script) { + return new ScriptTemplate(formatTemplate( + format(Locale.ROOT, "{sql}.nullSafeFilter(%s)", script.template())), + script.params(), + DataType.BOOLEAN); + } + + public static ScriptTemplate nullSafeSort(ScriptTemplate script) { + String methodName = script.outputType().isNumeric() ? "nullSafeSortNumeric" : "nullSafeSortString"; + return new ScriptTemplate(formatTemplate( + format(Locale.ROOT, "{sql}.%s(%s)", methodName, script.template())), + script.params(), + script.outputType()); + } + + public static ScriptTemplate and(ScriptTemplate left, ScriptTemplate right) { + return binaryMethod("and", left, right, DataType.BOOLEAN); + } + + public static ScriptTemplate or(ScriptTemplate left, ScriptTemplate right) { + return binaryMethod("or", left, right, DataType.BOOLEAN); + } + + public static ScriptTemplate binaryMethod(String methodName, ScriptTemplate leftScript, ScriptTemplate rightScript, + DataType dataType) { + return new ScriptTemplate(format(Locale.ROOT, formatTemplate("{sql}.%s(%s,%s)"), + methodName, + leftScript.template(), + rightScript.template()), + paramsBuilder() + .script(leftScript.params()) + .script(rightScript.params()) + .build(), + dataType); + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryOperator.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryOperator.java index 27e979bc30a57..9684913dba86d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryOperator.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryOperator.java @@ -13,19 +13,19 @@ * Operator is a specialized binary predicate where both sides have the compatible types * (it's up to the analyzer to do any conversion if needed). */ -public abstract class BinaryOperator extends BinaryPredicate { +public abstract class BinaryOperator> extends BinaryPredicate { public interface Negateable { - BinaryOperator negate(); + BinaryOperator negate(); } - protected BinaryOperator(Location location, Expression left, Expression right, String symbol) { - super(location, left, right, symbol); + protected BinaryOperator(Location location, Expression left, Expression right, F function) { + super(location, left, right, function); } protected abstract TypeResolution resolveInputType(DataType inputType); - public abstract BinaryOperator swapLeftAndRight(); + public abstract BinaryOperator swapLeftAndRight(); @Override protected TypeResolution resolveType() { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryPredicate.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryPredicate.java index ead90c13e88e3..1dcb7c843c0ec 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryPredicate.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryPredicate.java @@ -15,24 +15,35 @@ /** * Binary operator. Operators act as _special_ functions in that they have a symbol - * instead of a name and do not use parathensis. + * instead of a name and do not use parentheses. * Further more they are not registered as the rest of the functions as are implicit * to the language. */ -public abstract class BinaryPredicate extends BinaryScalarFunction { +public abstract class BinaryPredicate> extends BinaryScalarFunction { - private final String symbol; private final String name; + private final F function; - protected BinaryPredicate(Location location, Expression left, Expression right, String symbol) { + protected BinaryPredicate(Location location, Expression left, Expression right, F function) { super(location, left, right); - this.name = name(left, right, symbol); - this.symbol = symbol; + this.name = name(left, right, function.symbol()); + this.function = function; + } + + @SuppressWarnings("unchecked") + @Override + public R fold() { + return function().apply((T) left().fold(), (U) right().fold()); + } + + @Override + protected String scriptMethodName() { + return function.scriptMethodName(); } @Override public int hashCode() { - return Objects.hash(left(), right()); + return Objects.hash(left(), right(), function.symbol()); } @Override @@ -47,13 +58,26 @@ public boolean equals(Object obj) { return false; } - BinaryPredicate other = (BinaryPredicate) obj; + BinaryPredicate other = (BinaryPredicate) obj; - return Objects.equals(symbol, other.symbol) + return Objects.equals(other.symbol(), other.symbol()) && Objects.equals(left(), other.left()) && Objects.equals(right(), other.right()); } + @Override + public String name() { + return name; + } + + public String symbol() { + return function.symbol(); + } + + public F function() { + return function; + } + private static String name(Expression left, Expression right, String symbol) { StringBuilder sb = new StringBuilder(); sb.append(Expressions.name(left)); @@ -72,13 +96,4 @@ private static String name(Expression left, Expression right, String symbol) { } return sb.toString(); } - - @Override - public String name() { - return name; - } - - public final String symbol() { - return symbol; - } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/PredicateBiFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/PredicateBiFunction.java new file mode 100644 index 0000000000000..4966d0c9ab659 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/PredicateBiFunction.java @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.expression.predicate; + +import java.util.Locale; +import java.util.function.BiFunction; + +public interface PredicateBiFunction extends BiFunction { + + String name(); + + String symbol(); + + @Override + default R apply(T t, U u) { + if (t == null || u == null) { + return null; + } + + return doApply(t, u); + } + + R doApply(T t, U u); + + default String scriptMethodName() { + return name().toLowerCase(Locale.ROOT); + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Predicates.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Predicates.java index 6fb26cb6dcc61..87907d66b5a73 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Predicates.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Predicates.java @@ -6,6 +6,8 @@ package org.elasticsearch.xpack.sql.expression.predicate; import org.elasticsearch.xpack.sql.expression.Expression; +import org.elasticsearch.xpack.sql.expression.predicate.logical.And; +import org.elasticsearch.xpack.sql.expression.predicate.logical.Or; import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; import java.util.ArrayList; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Range.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Range.java index 4395e263e060c..42021cad5901e 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Range.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Range.java @@ -5,56 +5,56 @@ */ package org.elasticsearch.xpack.sql.expression.predicate; -import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; -import org.elasticsearch.xpack.sql.expression.Attribute; import org.elasticsearch.xpack.sql.expression.Expression; -import org.elasticsearch.xpack.sql.expression.FieldAttribute; -import org.elasticsearch.xpack.sql.expression.Foldables; -import org.elasticsearch.xpack.sql.expression.NamedExpression; +import org.elasticsearch.xpack.sql.expression.Expressions; +import org.elasticsearch.xpack.sql.expression.Literal; +import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunction; import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe; import org.elasticsearch.xpack.sql.expression.gen.script.Params; import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptWeaver; +import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicPipe; +import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparison; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonPipe; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; -import org.elasticsearch.xpack.sql.type.EsField; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Objects; import static java.lang.String.format; -import static java.util.Collections.emptyMap; +import static java.util.Arrays.asList; import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; // BETWEEN or range - is a mix of gt(e) AND lt(e) -public class Range extends NamedExpression implements ScriptWeaver { +public class Range extends ScalarFunction { + private final String name; private final Expression value, lower, upper; private final boolean includeLower, includeUpper; public Range(Location location, Expression value, Expression lower, boolean includeLower, Expression upper, boolean includeUpper) { - this(location, null, value, lower, includeLower, upper, includeUpper); - } - - public Range(Location location, String name, Expression value, Expression lower, boolean includeLower, Expression upper, - boolean includeUpper) { - super(location, name == null ? defaultName(value, lower, upper, includeLower, includeUpper) : name, - Arrays.asList(value, lower, upper), null); + super(location, asList(value, lower, upper)); this.value = value; this.lower = lower; this.upper = upper; this.includeLower = includeLower; this.includeUpper = includeUpper; + this.name = name(value, lower, upper, includeLower, includeUpper); + } + + @Override + public String name() { + return name; } @Override protected NodeInfo info() { - return NodeInfo.create(this, Range::new, name(), value, lower, includeLower, upper, includeUpper); + return NodeInfo.create(this, Range::new, value, lower, includeLower, upper, includeUpper); } @Override @@ -130,18 +130,25 @@ public DataType dataType() { @Override public ScriptTemplate asScript() { - ScriptTemplate scriptTemplate = asScript(value); - - String template = formatTemplate(format(Locale.ROOT, "({} %s %s) && (%s %s {})", - includeLower() ? "<=" : "<", - scriptTemplate.template(), - scriptTemplate.template(), - includeUpper() ? "<=" : "<")); - - Params params = paramsBuilder().variable(Foldables.valueOf(lower)) - .script(scriptTemplate.params()) - .script(scriptTemplate.params()) - .variable(Foldables.valueOf(upper)) + ScriptTemplate valueScript = asScript(value); + ScriptTemplate lowerScript = asScript(lower); + ScriptTemplate upperScript = asScript(upper); + + + String template = formatTemplate(format(Locale.ROOT, "{sql}.and({sql}.%s(%s, %s), {sql}.%s(%s, %s))", + includeLower() ? "gte" : "gt", + valueScript.template(), + lowerScript.template(), + includeUpper() ? "lte" : "lt", + valueScript.template(), + upperScript.template() + )); + + Params params = paramsBuilder() + .script(valueScript.params()) + .script(lowerScript.params()) + .script(valueScript.params()) + .script(upperScript.params()) .build(); return new ScriptTemplate(template, params, DataType.BOOLEAN); @@ -149,13 +156,12 @@ public ScriptTemplate asScript() { @Override protected Pipe makePipe() { - throw new SqlIllegalArgumentException("Not supported yet"); - } - - @Override - public Attribute toAttribute() { - return new FieldAttribute(location(), "not yet implemented", - new EsField("not yet implemented", DataType.UNSUPPORTED, emptyMap(), false)); + BinaryComparisonPipe lowerPipe = new BinaryComparisonPipe(location(), this, Expressions.pipe(value()), Expressions.pipe(lower()), + includeLower() ? BinaryComparisonOperation.GTE : BinaryComparisonOperation.GT); + BinaryComparisonPipe upperPipe = new BinaryComparisonPipe(location(), this, Expressions.pipe(value()), Expressions.pipe(upper()), + includeUpper() ? BinaryComparisonOperation.LTE : BinaryComparisonOperation.LT); + BinaryLogicPipe and = new BinaryLogicPipe(location(), this, lowerPipe, upperPipe, BinaryLogicOperation.AND); + return and; } @Override @@ -181,13 +187,28 @@ public boolean equals(Object obj) { && Objects.equals(upper, other.upper); } - private static String defaultName(Expression value, Expression lower, Expression upper, boolean includeLower, boolean includeUpper) { + private static String name(Expression value, Expression lower, Expression upper, boolean includeLower, boolean includeUpper) { StringBuilder sb = new StringBuilder(); - sb.append(lower); + sb.append(Expressions.name(lower)); + if (!(lower instanceof Literal)) { + sb.insert(0, "("); + sb.append(")"); + } sb.append(includeLower ? " <= " : " < "); - sb.append(value); + int pos = sb.length(); + sb.append(Expressions.name(value)); + if (!(value instanceof Literal)) { + sb.insert(pos, "("); + sb.append(")"); + } sb.append(includeUpper ? " <= " : " < "); - sb.append(upper); + pos = sb.length(); + sb.append(Expressions.name(upper)); + if (!(upper instanceof Literal)) { + sb.insert(pos, "("); + sb.append(")"); + } + return sb.toString(); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/And.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/And.java similarity index 74% rename from x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/And.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/And.java index c7f5b7dacec2f..8f4cc857f8099 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/And.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/And.java @@ -3,19 +3,18 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.sql.expression.predicate; +package org.elasticsearch.xpack.sql.expression.predicate.logical; import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator.Negateable; +import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import java.util.Objects; - public class And extends BinaryLogic implements Negateable { public And(Location location, Expression left, Expression right) { - super(location, left, right, "&&"); + super(location, left, right, BinaryLogicOperation.AND); } @Override @@ -24,22 +23,17 @@ protected NodeInfo info() { } @Override - protected BinaryOperator replaceChildren(Expression newLeft, Expression newRight) { + protected And replaceChildren(Expression newLeft, Expression newRight) { return new And(location(), newLeft, newRight); } @Override - public Object fold() { - return Objects.equals(left().fold(), Boolean.TRUE) && Objects.equals(right().fold(), Boolean.TRUE); + public And swapLeftAndRight() { + return new And(location(), right(), left()); } @Override public Or negate() { return new Or(location(), new Not(location(), left()), new Not(location(), right())); } - - @Override - public And swapLeftAndRight() { - return new And(location(), right(), left()); - } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryLogic.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogic.java similarity index 60% rename from x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryLogic.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogic.java index 01fefb2c8e737..68147bd727ab0 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryLogic.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogic.java @@ -3,19 +3,20 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.sql.expression.predicate; +package org.elasticsearch.xpack.sql.expression.predicate.logical; import org.elasticsearch.xpack.sql.expression.Expression; -import org.elasticsearch.xpack.sql.expression.gen.pipeline.AggNameInput; +import org.elasticsearch.xpack.sql.expression.Expressions; import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; +import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator; +import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.type.DataType; -public abstract class BinaryLogic extends BinaryOperator { +public abstract class BinaryLogic extends BinaryOperator { - protected BinaryLogic(Location location, Expression left, Expression right, String symbol) { - super(location, left, right, symbol); + protected BinaryLogic(Location location, Expression left, Expression right, BinaryLogicOperation operation) { + super(location, left, right, operation); } @Override @@ -29,13 +30,8 @@ protected TypeResolution resolveInputType(DataType inputType) { "'%s' requires type %s not %s", symbol(), DataType.BOOLEAN.sqlName(), inputType.sqlName()); } - @Override - protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - return new ScriptTemplate(""); + return new BinaryLogicPipe(location(), this, Expressions.pipe(left()), Expressions.pipe(right()), function()); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogicPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogicPipe.java new file mode 100644 index 0000000000000..26c19ab124e60 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogicPipe.java @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.expression.predicate.logical; + +import org.elasticsearch.xpack.sql.expression.Expression; +import org.elasticsearch.xpack.sql.expression.gen.pipeline.BinaryPipe; +import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe; +import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; +import org.elasticsearch.xpack.sql.tree.Location; +import org.elasticsearch.xpack.sql.tree.NodeInfo; + +import java.util.Objects; + +public class BinaryLogicPipe extends BinaryPipe { + + private final BinaryLogicOperation operation; + + public BinaryLogicPipe(Location location, Expression expression, Pipe left, Pipe right, BinaryLogicOperation operation) { + super(location, expression, left, right); + this.operation = operation; + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, BinaryLogicPipe::new, expression(), left(), right(), operation); + } + + @Override + protected BinaryPipe replaceChildren(Pipe left, Pipe right) { + return new BinaryLogicPipe(location(), expression(), left, right, operation); + } + + @Override + public BinaryLogicProcessor asProcessor() { + return new BinaryLogicProcessor(left().asProcessor(), right().asProcessor(), operation); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), operation); + } + + @Override + public boolean equals(Object obj) { + if (super.equals(obj)) { + BinaryLogicPipe other = (BinaryLogicPipe) obj; + return Objects.equals(operation, other.operation); + } + return false; + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogicProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogicProcessor.java new file mode 100644 index 0000000000000..7e3aef2b8c721 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/BinaryLogicProcessor.java @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.expression.predicate.logical; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.expression.gen.processor.FunctionalBinaryProcessor; +import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; +import org.elasticsearch.xpack.sql.expression.predicate.PredicateBiFunction; +import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; + +import java.io.IOException; +import java.util.function.BiFunction; + +public class BinaryLogicProcessor extends FunctionalBinaryProcessor { + + public enum BinaryLogicOperation implements PredicateBiFunction { + + AND((l, r) -> { + if (Boolean.FALSE.equals(l) || Boolean.FALSE.equals(r)) { + return Boolean.FALSE; + } + if (l == null || r == null) { + return null; + } + return l.booleanValue() && r.booleanValue(); + }, "&&"), + OR((l, r) -> { + if (Boolean.TRUE.equals(l) || Boolean.TRUE.equals(r)) { + return Boolean.TRUE; + } + if (l == null || r == null) { + return null; + } + return l.booleanValue() || r.booleanValue(); + }, "||"); + + private final BiFunction process; + private final String symbol; + + BinaryLogicOperation(BiFunction process, String symbol) { + this.process = process; + this.symbol = symbol; + } + + @Override + public String symbol() { + return symbol; + } + + @Override + public Boolean apply(Boolean left, Boolean right) { + return process.apply(left, right); + } + + @Override + public final Boolean doApply(Boolean left, Boolean right) { + return null; + } + + @Override + public String toString() { + return symbol; + } + } + + public static final String NAME = "lb"; + + public BinaryLogicProcessor(Processor left, Processor right, BinaryLogicOperation operation) { + super(left, right, operation); + } + + public BinaryLogicProcessor(StreamInput in) throws IOException { + super(in, i -> i.readEnum(BinaryLogicOperation.class)); + } + + @Override + public String getWriteableName() { + return NAME; + } + + @Override + protected void checkParameter(Object param) { + if (!(param instanceof Boolean)) { + throw new SqlIllegalArgumentException("A boolean is required; received {}", param); + } + } +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Not.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/Not.java similarity index 97% rename from x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Not.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/Not.java index 4b6e7ba4b46a4..48a307fa0621a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Not.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/Not.java @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.sql.expression.predicate; +package org.elasticsearch.xpack.sql.expression.predicate.logical; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.Expression; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Or.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/Or.java similarity index 74% rename from x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Or.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/Or.java index 614ef94adaa5a..a731f53f000bc 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Or.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/logical/Or.java @@ -3,19 +3,18 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.sql.expression.predicate; +package org.elasticsearch.xpack.sql.expression.predicate.logical; import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator.Negateable; +import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import java.util.Objects; - public class Or extends BinaryLogic implements Negateable { public Or(Location location, Expression left, Expression right) { - super(location, left, right, "||"); + super(location, left, right, BinaryLogicOperation.OR); } @Override @@ -24,15 +23,10 @@ protected NodeInfo info() { } @Override - protected BinaryOperator replaceChildren(Expression newLeft, Expression newRight) { + protected Or replaceChildren(Expression newLeft, Expression newRight) { return new Or(location(), newLeft, newRight); } - @Override - public Object fold() { - return Objects.equals(left().fold(), Boolean.TRUE) || Objects.equals(right().fold(), Boolean.TRUE); - } - @Override public Or swapLeftAndRight() { return new Or(location(), right(), left()); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/ArithmeticOperation.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/ArithmeticOperation.java index 24a7281beb97a..049c454735577 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/ArithmeticOperation.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/ArithmeticOperation.java @@ -8,25 +8,16 @@ import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.expression.Expressions; import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator; import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypeConversion; -import java.util.Locale; +public abstract class ArithmeticOperation extends BinaryOperator { -import static java.lang.String.format; -import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; - -public abstract class ArithmeticOperation extends BinaryOperator { - - private final BinaryArithmeticOperation operation; - - ArithmeticOperation(Location location, Expression left, Expression right, BinaryArithmeticOperation operation) { - super(location, left, right, operation.symbol()); - this.operation = operation; + protected ArithmeticOperation(Location location, Expression left, Expression right, BinaryArithmeticOperation operation) { + super(location, left, right, operation); } @Override @@ -46,26 +37,8 @@ public DataType dataType() { return DataTypeConversion.commonType(left().dataType(), right().dataType()); } - @Override - public Object fold() { - return operation.apply((Number) left().fold(), (Number) right().fold()); - } - - @Override - protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - String op = operation.symbol(); - // escape % - if (operation == BinaryArithmeticOperation.MOD) { - op = "%" + op; - } - return new ScriptTemplate(format(Locale.ROOT, "(%s) %s (%s)", leftScript.template(), op, rightScript.template()), - paramsBuilder() - .script(leftScript.params()).script(rightScript.params()) - .build(), dataType()); - } - @Override protected Pipe makePipe() { - return new BinaryArithmeticPipe(location(), this, Expressions.pipe(left()), Expressions.pipe(right()), operation); + return new BinaryArithmeticPipe(location(), this, Expressions.pipe(left()), Expressions.pipe(right()), function()); } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/BinaryArithmeticPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/BinaryArithmeticPipe.java index 06bed035141c9..dde8ae6af5e46 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/BinaryArithmeticPipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/BinaryArithmeticPipe.java @@ -18,16 +18,14 @@ public class BinaryArithmeticPipe extends BinaryPipe { private final BinaryArithmeticOperation operation; - public BinaryArithmeticPipe(Location location, Expression expression, Pipe left, - Pipe right, BinaryArithmeticOperation operation) { + public BinaryArithmeticPipe(Location location, Expression expression, Pipe left, Pipe right, BinaryArithmeticOperation operation) { super(location, expression, left, right); this.operation = operation; } @Override protected NodeInfo info() { - return NodeInfo.create(this, BinaryArithmeticPipe::new, - expression(), left(), right(), operation); + return NodeInfo.create(this, BinaryArithmeticPipe::new, expression(), left(), right(), operation); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessor.java index f7811ba7cba7e..097acf8e716e9 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessor.java @@ -6,18 +6,18 @@ package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryNumericProcessor; +import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.expression.gen.processor.FunctionalBinaryProcessor; import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; +import org.elasticsearch.xpack.sql.expression.predicate.PredicateBiFunction; import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import java.io.IOException; import java.util.function.BiFunction; -public class BinaryArithmeticProcessor extends BinaryNumericProcessor { +public class BinaryArithmeticProcessor extends FunctionalBinaryProcessor { - public enum BinaryArithmeticOperation implements BiFunction { - + public enum BinaryArithmeticOperation implements PredicateBiFunction { ADD(Arithmetics::add, "+"), SUB(Arithmetics::sub, "-"), MUL(Arithmetics::mul, "*"), @@ -32,12 +32,13 @@ public enum BinaryArithmeticOperation implements BiFunction { - public BinaryComparison(Location location, Expression left, Expression right, BinaryComparisonOperation operation) { - super(location, left, right, operation.symbol()); - this.operation = operation; + protected BinaryComparison(Location location, Expression left, Expression right, BinaryComparisonOperation operation) { + super(location, left, right, operation); } @Override @@ -34,25 +25,6 @@ protected TypeResolution resolveInputType(DataType inputType) { return TypeResolution.TYPE_RESOLVED; } - @Override - protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - String op = operation.symbol(); - return new ScriptTemplate(format(Locale.ROOT, "(%s) %s (%s)", leftScript.template(), op, rightScript.template()), - paramsBuilder() - .script(leftScript.params()).script(rightScript.params()) - .build(), dataType()); - } - - @Override - protected Pipe makePipe() { - return new BinaryComparisonPipe(location(), this, Expressions.pipe(left()), Expressions.pipe(right()), operation); - } - - @Override - public Object fold() { - return operation.apply(left().fold(), right().fold()); - } - @Override protected Expression canonicalize() { return left().hashCode() > right().hashCode() ? swapLeftAndRight() : this; @@ -63,8 +35,9 @@ public DataType dataType() { return DataType.BOOLEAN; } - public static Integer compare(Object left, Object right) { - return Comparisons.compare(left, right); + @Override + protected Pipe makePipe() { + return new BinaryComparisonPipe(location(), this, Expressions.pipe(left()), Expressions.pipe(right()), function()); } @Override @@ -77,4 +50,8 @@ public String toString() { sb.append(right()); return sb.toString(); } + + public static Integer compare(Object left, Object right) { + return Comparisons.compare(left, right); + } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryComparisonPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryComparisonPipe.java index a7ca4a2dea343..84c9221fb4762 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryComparisonPipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryComparisonPipe.java @@ -18,8 +18,7 @@ public class BinaryComparisonPipe extends BinaryPipe { private final BinaryComparisonOperation operation; - public BinaryComparisonPipe(Location location, Expression expression, Pipe left, - Pipe right, BinaryComparisonOperation operation) { + public BinaryComparisonPipe(Location location, Expression expression, Pipe left, Pipe right, BinaryComparisonOperation operation) { super(location, expression, left, right); this.operation = operation; } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryComparisonProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryComparisonProcessor.java index 25856f914039c..e33d7b282006d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryComparisonProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryComparisonProcessor.java @@ -6,16 +6,17 @@ package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.xpack.sql.expression.gen.processor.FunctionalBinaryProcessor; import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; +import org.elasticsearch.xpack.sql.expression.predicate.PredicateBiFunction; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation; import java.io.IOException; import java.util.function.BiFunction; -public class BinaryComparisonProcessor extends BinaryOperatorProcessor { +public class BinaryComparisonProcessor extends FunctionalBinaryProcessor { - public enum BinaryComparisonOperation implements BiFunction { + public enum BinaryComparisonOperation implements PredicateBiFunction { EQ(Comparisons::eq, "=="), GT(Comparisons::gt, ">"), @@ -31,12 +32,13 @@ public enum BinaryComparisonOperation implements BiFunction i.readEnum(BinaryComparisonOperation.class)); } - @Override - protected void doWrite(StreamOutput out) throws IOException { - out.writeEnum(operation()); - } - @Override public String getWriteableName() { return NAME; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryOperatorProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryOperatorProcessor.java deleted file mode 100644 index 621154eb8d0ec..0000000000000 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/BinaryOperatorProcessor.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison; - -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.xpack.sql.expression.gen.processor.BinaryProcessor; -import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; - -import java.io.IOException; -import java.util.Locale; -import java.util.Objects; -import java.util.function.BiFunction; - -public abstract class BinaryOperatorProcessor & BiFunction> extends BinaryProcessor { - - private final O operation; - - protected BinaryOperatorProcessor(Processor left, Processor right, O operation) { - super(left, right); - this.operation = operation; - } - - protected BinaryOperatorProcessor(StreamInput in, Reader reader) throws IOException { - super(in); - operation = reader.read(in); - } - - protected O operation() { - return operation; - } - - @Override - protected Object doProcess(Object left, Object right) { - if (left == null || right == null) { - return null; - } - - checkParameter(left); - checkParameter(right); - - return operation.apply(left, right); - } - - protected void checkParameter(Object param) { - //no-op - } - - @Override - public int hashCode() { - return Objects.hash(operation); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - BinaryOperatorProcessor other = (BinaryOperatorProcessor) obj; - return Objects.equals(operation, other.operation) - && Objects.equals(left(), other.left()) - && Objects.equals(right(), other.right()); - } - - @Override - public String toString() { - return String.format(Locale.ROOT, "(%s %s %s)", left(), operation, right()); - } -} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/Like.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/Like.java index 9804214a28ac0..a5c8028f6709a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/Like.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/Like.java @@ -5,62 +5,32 @@ */ package org.elasticsearch.xpack.sql.expression.predicate.regex; -import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.Expression; -import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; -import org.elasticsearch.xpack.sql.expression.predicate.BinaryPredicate; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import org.elasticsearch.xpack.sql.type.DataType; -import java.util.regex.Pattern; - -public class Like extends BinaryPredicate { +public class Like extends RegexMatch { public Like(Location location, Expression left, LikePattern right) { - super(location, left, right, "LIKE"); + super(location, left, right); } @Override protected NodeInfo info() { - return NodeInfo.create(this, Like::new, left(), right()); - } - - @Override - protected BinaryPredicate replaceChildren(Expression newLeft, Expression newRight) { - return new Like(location(), newLeft, (LikePattern) newRight); - } - - @Override - public LikePattern right() { - return (LikePattern) super.right(); + return NodeInfo.create(this, Like::new, left(), pattern()); } - @Override - public boolean foldable() { - // right() is not directly foldable in any context but Like can fold it. - return left().foldable(); - } - - @Override - public Object fold() { - Pattern p = Pattern.compile(right().asJavaRegex()); - return p.matcher(left().fold().toString()).matches(); + public LikePattern pattern() { + return (LikePattern) right(); } @Override - public DataType dataType() { - return DataType.BOOLEAN; - } - - @Override - protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - throw new SqlIllegalArgumentException("Not supported yet"); + protected Like replaceChildren(Expression newLeft, Expression newRight) { + return new Like(location(), newLeft, (LikePattern) newRight); } @Override - protected Pipe makePipe() { - throw new SqlIllegalArgumentException("Not supported yet"); + protected String asString(Expression pattern) { + return ((LikePattern) pattern).asJavaRegex(); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RLike.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RLike.java index f445b49cf31c9..346c3062bfaa8 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RLike.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RLike.java @@ -5,57 +5,29 @@ */ package org.elasticsearch.xpack.sql.expression.predicate.regex; -import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.expression.Literal; -import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; -import org.elasticsearch.xpack.sql.expression.predicate.BinaryPredicate; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import org.elasticsearch.xpack.sql.type.DataType; -import java.util.regex.Pattern; - -public class RLike extends BinaryPredicate { +public class RLike extends RegexMatch { public RLike(Location location, Expression left, Literal right) { - super(location, left, right, "RLIKE"); + super(location, left, right); } @Override protected NodeInfo info() { - return NodeInfo.create(this, RLike::new, left(), right()); + return NodeInfo.create(this, RLike::new, left(), (Literal) right()); } @Override - protected BinaryPredicate replaceChildren(Expression newLeft, Expression newRight) { + protected RLike replaceChildren(Expression newLeft, Expression newRight) { return new RLike(location(), newLeft, (Literal) newRight); } @Override - public Literal right() { - return (Literal) super.right(); - } - - @Override - public Object fold() { - Pattern p = Pattern.compile(right().fold().toString()); - return p.matcher(left().fold().toString()).matches(); - } - - @Override - public DataType dataType() { - return DataType.BOOLEAN; - } - - @Override - protected ScriptTemplate asScriptFrom(ScriptTemplate leftScript, ScriptTemplate rightScript) { - throw new SqlIllegalArgumentException("Not supported yet"); - } - - @Override - protected Pipe makePipe() { - throw new SqlIllegalArgumentException("Not supported yet"); + protected String asString(Expression pattern) { + return pattern.fold().toString(); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexMatch.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexMatch.java new file mode 100644 index 0000000000000..e1e410064924c --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexMatch.java @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.expression.predicate.regex; + +import org.elasticsearch.xpack.sql.expression.Expression; +import org.elasticsearch.xpack.sql.expression.predicate.BinaryPredicate; +import org.elasticsearch.xpack.sql.expression.predicate.regex.RegexProcessor.RegexOperation; +import org.elasticsearch.xpack.sql.tree.Location; +import org.elasticsearch.xpack.sql.type.DataType; + +public abstract class RegexMatch extends BinaryPredicate { + + protected RegexMatch(Location location, Expression value, Expression pattern) { + super(location, value, pattern, RegexOperation.INSTANCE); + } + + @Override + public DataType dataType() { + return DataType.BOOLEAN; + } + + @Override + public boolean foldable() { + // right() is not directly foldable in any context but Like can fold it. + return left().foldable(); + } + + @Override + public Boolean fold() { + Object val = left().fold(); + val = val != null ? val.toString() : val; + return function().apply((String) val, asString(right())); + } + + protected abstract String asString(Expression pattern); +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexPipe.java new file mode 100644 index 0000000000000..7ce8b2b0fc9b4 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexPipe.java @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.expression.predicate.regex; + +import org.elasticsearch.xpack.sql.expression.Expression; +import org.elasticsearch.xpack.sql.expression.gen.pipeline.BinaryPipe; +import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe; +import org.elasticsearch.xpack.sql.tree.Location; +import org.elasticsearch.xpack.sql.tree.NodeInfo; + +public class RegexPipe extends BinaryPipe { + + public RegexPipe(Location location, Expression expression, Pipe left, Pipe right) { + super(location, expression, left, right); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, RegexPipe::new, expression(), left(), right()); + } + + @Override + protected BinaryPipe replaceChildren(Pipe left, Pipe right) { + return new RegexPipe(location(), expression(), left, right); + } + + @Override + public RegexProcessor asProcessor() { + return new RegexProcessor(left().asProcessor(), right().asProcessor()); + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexProcessor.java new file mode 100644 index 0000000000000..ada6accab7e1b --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexProcessor.java @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.expression.predicate.regex; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.expression.gen.processor.BinaryProcessor; +import org.elasticsearch.xpack.sql.expression.gen.processor.Processor; +import org.elasticsearch.xpack.sql.expression.predicate.PredicateBiFunction; + +import java.io.IOException; +import java.util.Objects; +import java.util.regex.Pattern; + +public class RegexProcessor extends BinaryProcessor { + + public static class RegexOperation implements PredicateBiFunction { + + public static final RegexOperation INSTANCE = new RegexOperation(); + + @Override + public String name() { + return symbol(); + } + + @Override + public String symbol() { + return "REGEX"; + } + + @Override + public Boolean doApply(String value, String pattern) { + return match(value, pattern); + } + + public static Boolean match(Object value, Object pattern) { + if (value == null && pattern == null) { + return null; + } + + Pattern p = Pattern.compile(pattern.toString()); + return p.matcher(value.toString()).matches(); + } + } + + public static final String NAME = "rgx"; + + public RegexProcessor(Processor value, Processor pattern) { + super(value, pattern); + } + + public RegexProcessor(StreamInput in) throws IOException { + super(in); + } + + @Override + protected Boolean doProcess(Object value, Object pattern) { + return RegexOperation.match(value, pattern); + } + + @Override + protected void checkParameter(Object param) { + if (!(param instanceof String || param instanceof Character)) { + throw new SqlIllegalArgumentException("A string/char is required; received [{}]", param); + } + } + + @Override + public String getWriteableName() { + return NAME; + } + + @Override + protected void doWrite(StreamOutput out) throws IOException {} + + @Override + public int hashCode() { + return Objects.hash(left(), right()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + RegexProcessor other = (RegexProcessor) obj; + return Objects.equals(left(), other.left()) && Objects.equals(right(), other.right()); + } +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java index deb4ccb7da27f..dffb42709ea24 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java @@ -36,14 +36,14 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.Cast; import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunction; import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunctionAttribute; -import org.elasticsearch.xpack.sql.expression.predicate.And; import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator; import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator.Negateable; import org.elasticsearch.xpack.sql.expression.predicate.BinaryPredicate; -import org.elasticsearch.xpack.sql.expression.predicate.Not; -import org.elasticsearch.xpack.sql.expression.predicate.Or; import org.elasticsearch.xpack.sql.expression.predicate.Predicates; import org.elasticsearch.xpack.sql.expression.predicate.Range; +import org.elasticsearch.xpack.sql.expression.predicate.logical.And; +import org.elasticsearch.xpack.sql.expression.predicate.logical.Not; +import org.elasticsearch.xpack.sql.expression.predicate.logical.Or; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparison; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThan; @@ -1137,7 +1137,7 @@ static class BooleanSimplification extends OptimizerExpressionRule { @Override protected Expression rule(Expression e) { if (e instanceof BinaryPredicate) { - return simplifyAndOr((BinaryPredicate) e); + return simplifyAndOr((BinaryPredicate) e); } if (e instanceof Not) { return simplifyNot((Not) e); @@ -1146,7 +1146,7 @@ protected Expression rule(Expression e) { return e; } - private Expression simplifyAndOr(BinaryPredicate bc) { + private Expression simplifyAndOr(BinaryPredicate bc) { Expression l = bc.left(); Expression r = bc.right(); @@ -1292,10 +1292,10 @@ static class BooleanLiteralsOnTheRight extends OptimizerExpressionRule { @Override protected Expression rule(Expression e) { - return e instanceof BinaryOperator ? literalToTheRight((BinaryOperator) e) : e; + return e instanceof BinaryOperator ? literalToTheRight((BinaryOperator) e) : e; } - private Expression literalToTheRight(BinaryOperator be) { + private Expression literalToTheRight(BinaryOperator be) { return be.left() instanceof Literal && !(be.right() instanceof Literal) ? be.swapLeftAndRight() : be; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java index 0c738bcc1e99e..b3dfdaf404acf 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java @@ -23,15 +23,15 @@ import org.elasticsearch.xpack.sql.expression.function.Function; import org.elasticsearch.xpack.sql.expression.function.UnresolvedFunction; import org.elasticsearch.xpack.sql.expression.function.scalar.Cast; -import org.elasticsearch.xpack.sql.expression.predicate.And; import org.elasticsearch.xpack.sql.expression.predicate.In; import org.elasticsearch.xpack.sql.expression.predicate.IsNotNull; -import org.elasticsearch.xpack.sql.expression.predicate.Not; -import org.elasticsearch.xpack.sql.expression.predicate.Or; import org.elasticsearch.xpack.sql.expression.predicate.Range; import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MatchQueryPredicate; import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MultiMatchQueryPredicate; import org.elasticsearch.xpack.sql.expression.predicate.fulltext.StringQueryPredicate; +import org.elasticsearch.xpack.sql.expression.predicate.logical.And; +import org.elasticsearch.xpack.sql.expression.predicate.logical.Not; +import org.elasticsearch.xpack.sql.expression.predicate.logical.Or; import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Add; import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Div; import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mod; @@ -348,8 +348,13 @@ private String getQueryOptions(MatchQueryOptionsContext optionsCtx) { @Override public Order visitOrderBy(OrderByContext ctx) { + if (ctx.NULLS() != null && ctx.nullOrdering.getType() != SqlBaseParser.LAST) { + throw new ParsingException(source(ctx.nullOrdering), "Null ordering can only be [LAST], found [{}]", + ctx.nullOrdering.getText()); + } + return new Order(source(ctx), expression(ctx.expression()), - ctx.DESC() != null ? Order.OrderDirection.DESC : Order.OrderDirection.ASC); + ctx.DESC() != null ? Order.OrderDirection.DESC : Order.OrderDirection.ASC); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseLexer.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseLexer.java index 0361d719e63a7..f82072aa13cb4 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseLexer.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseLexer.java @@ -20,19 +20,19 @@ class SqlBaseLexer extends Lexer { T__0=1, T__1=2, T__2=3, T__3=4, ALL=5, ANALYZE=6, ANALYZED=7, AND=8, ANY=9, AS=10, ASC=11, BETWEEN=12, BY=13, CAST=14, CATALOG=15, CATALOGS=16, COLUMNS=17, DEBUG=18, DESC=19, DESCRIBE=20, DISTINCT=21, ESCAPE=22, EXECUTABLE=23, - EXISTS=24, EXPLAIN=25, EXTRACT=26, FALSE=27, FORMAT=28, FROM=29, FULL=30, - FUNCTIONS=31, GRAPHVIZ=32, GROUP=33, HAVING=34, IN=35, INNER=36, IS=37, - JOIN=38, LEFT=39, LIKE=40, LIMIT=41, MAPPED=42, MATCH=43, NATURAL=44, - NOT=45, NULL=46, ON=47, OPTIMIZED=48, OR=49, ORDER=50, OUTER=51, PARSED=52, - PHYSICAL=53, PLAN=54, RIGHT=55, RLIKE=56, QUERY=57, SCHEMAS=58, SELECT=59, - SHOW=60, SYS=61, TABLE=62, TABLES=63, TEXT=64, TRUE=65, TYPE=66, TYPES=67, - USING=68, VERIFY=69, WHERE=70, WITH=71, ESCAPE_ESC=72, FUNCTION_ESC=73, - LIMIT_ESC=74, DATE_ESC=75, TIME_ESC=76, TIMESTAMP_ESC=77, GUID_ESC=78, - ESC_END=79, EQ=80, NEQ=81, LT=82, LTE=83, GT=84, GTE=85, PLUS=86, MINUS=87, - ASTERISK=88, SLASH=89, PERCENT=90, CONCAT=91, DOT=92, PARAM=93, STRING=94, - INTEGER_VALUE=95, DECIMAL_VALUE=96, IDENTIFIER=97, DIGIT_IDENTIFIER=98, - TABLE_IDENTIFIER=99, QUOTED_IDENTIFIER=100, BACKQUOTED_IDENTIFIER=101, - SIMPLE_COMMENT=102, BRACKETED_COMMENT=103, WS=104, UNRECOGNIZED=105; + EXISTS=24, EXPLAIN=25, EXTRACT=26, FALSE=27, FIRST=28, FORMAT=29, FROM=30, + FULL=31, FUNCTIONS=32, GRAPHVIZ=33, GROUP=34, HAVING=35, IN=36, INNER=37, + IS=38, JOIN=39, LAST=40, LEFT=41, LIKE=42, LIMIT=43, MAPPED=44, MATCH=45, + NATURAL=46, NOT=47, NULL=48, NULLS=49, ON=50, OPTIMIZED=51, OR=52, ORDER=53, + OUTER=54, PARSED=55, PHYSICAL=56, PLAN=57, RIGHT=58, RLIKE=59, QUERY=60, + SCHEMAS=61, SELECT=62, SHOW=63, SYS=64, TABLE=65, TABLES=66, TEXT=67, + TRUE=68, TYPE=69, TYPES=70, USING=71, VERIFY=72, WHERE=73, WITH=74, ESCAPE_ESC=75, + FUNCTION_ESC=76, LIMIT_ESC=77, DATE_ESC=78, TIME_ESC=79, TIMESTAMP_ESC=80, + GUID_ESC=81, ESC_END=82, EQ=83, NEQ=84, LT=85, LTE=86, GT=87, GTE=88, + PLUS=89, MINUS=90, ASTERISK=91, SLASH=92, PERCENT=93, CONCAT=94, DOT=95, + PARAM=96, STRING=97, INTEGER_VALUE=98, DECIMAL_VALUE=99, IDENTIFIER=100, + DIGIT_IDENTIFIER=101, TABLE_IDENTIFIER=102, QUOTED_IDENTIFIER=103, BACKQUOTED_IDENTIFIER=104, + SIMPLE_COMMENT=105, BRACKETED_COMMENT=106, WS=107, UNRECOGNIZED=108; public static String[] modeNames = { "DEFAULT_MODE" }; @@ -41,18 +41,18 @@ class SqlBaseLexer extends Lexer { "T__0", "T__1", "T__2", "T__3", "ALL", "ANALYZE", "ANALYZED", "AND", "ANY", "AS", "ASC", "BETWEEN", "BY", "CAST", "CATALOG", "CATALOGS", "COLUMNS", "DEBUG", "DESC", "DESCRIBE", "DISTINCT", "ESCAPE", "EXECUTABLE", "EXISTS", - "EXPLAIN", "EXTRACT", "FALSE", "FORMAT", "FROM", "FULL", "FUNCTIONS", - "GRAPHVIZ", "GROUP", "HAVING", "IN", "INNER", "IS", "JOIN", "LEFT", "LIKE", - "LIMIT", "MAPPED", "MATCH", "NATURAL", "NOT", "NULL", "ON", "OPTIMIZED", - "OR", "ORDER", "OUTER", "PARSED", "PHYSICAL", "PLAN", "RIGHT", "RLIKE", - "QUERY", "SCHEMAS", "SELECT", "SHOW", "SYS", "TABLE", "TABLES", "TEXT", - "TRUE", "TYPE", "TYPES", "USING", "VERIFY", "WHERE", "WITH", "ESCAPE_ESC", - "FUNCTION_ESC", "LIMIT_ESC", "DATE_ESC", "TIME_ESC", "TIMESTAMP_ESC", - "GUID_ESC", "ESC_END", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", - "MINUS", "ASTERISK", "SLASH", "PERCENT", "CONCAT", "DOT", "PARAM", "STRING", - "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "DIGIT_IDENTIFIER", "TABLE_IDENTIFIER", - "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "EXPONENT", "DIGIT", "LETTER", - "SIMPLE_COMMENT", "BRACKETED_COMMENT", "WS", "UNRECOGNIZED" + "EXPLAIN", "EXTRACT", "FALSE", "FIRST", "FORMAT", "FROM", "FULL", "FUNCTIONS", + "GRAPHVIZ", "GROUP", "HAVING", "IN", "INNER", "IS", "JOIN", "LAST", "LEFT", + "LIKE", "LIMIT", "MAPPED", "MATCH", "NATURAL", "NOT", "NULL", "NULLS", + "ON", "OPTIMIZED", "OR", "ORDER", "OUTER", "PARSED", "PHYSICAL", "PLAN", + "RIGHT", "RLIKE", "QUERY", "SCHEMAS", "SELECT", "SHOW", "SYS", "TABLE", + "TABLES", "TEXT", "TRUE", "TYPE", "TYPES", "USING", "VERIFY", "WHERE", + "WITH", "ESCAPE_ESC", "FUNCTION_ESC", "LIMIT_ESC", "DATE_ESC", "TIME_ESC", + "TIMESTAMP_ESC", "GUID_ESC", "ESC_END", "EQ", "NEQ", "LT", "LTE", "GT", + "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", "CONCAT", "DOT", + "PARAM", "STRING", "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "DIGIT_IDENTIFIER", + "TABLE_IDENTIFIER", "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "EXPONENT", + "DIGIT", "LETTER", "SIMPLE_COMMENT", "BRACKETED_COMMENT", "WS", "UNRECOGNIZED" }; private static final String[] _LITERAL_NAMES = { @@ -60,32 +60,33 @@ class SqlBaseLexer extends Lexer { "'AND'", "'ANY'", "'AS'", "'ASC'", "'BETWEEN'", "'BY'", "'CAST'", "'CATALOG'", "'CATALOGS'", "'COLUMNS'", "'DEBUG'", "'DESC'", "'DESCRIBE'", "'DISTINCT'", "'ESCAPE'", "'EXECUTABLE'", "'EXISTS'", "'EXPLAIN'", "'EXTRACT'", "'FALSE'", - "'FORMAT'", "'FROM'", "'FULL'", "'FUNCTIONS'", "'GRAPHVIZ'", "'GROUP'", - "'HAVING'", "'IN'", "'INNER'", "'IS'", "'JOIN'", "'LEFT'", "'LIKE'", "'LIMIT'", - "'MAPPED'", "'MATCH'", "'NATURAL'", "'NOT'", "'NULL'", "'ON'", "'OPTIMIZED'", - "'OR'", "'ORDER'", "'OUTER'", "'PARSED'", "'PHYSICAL'", "'PLAN'", "'RIGHT'", - "'RLIKE'", "'QUERY'", "'SCHEMAS'", "'SELECT'", "'SHOW'", "'SYS'", "'TABLE'", - "'TABLES'", "'TEXT'", "'TRUE'", "'TYPE'", "'TYPES'", "'USING'", "'VERIFY'", - "'WHERE'", "'WITH'", "'{ESCAPE'", "'{FN'", "'{LIMIT'", "'{D'", "'{T'", - "'{TS'", "'{GUID'", "'}'", "'='", null, "'<'", "'<='", "'>'", "'>='", - "'+'", "'-'", "'*'", "'/'", "'%'", "'||'", "'.'", "'?'" + "'FIRST'", "'FORMAT'", "'FROM'", "'FULL'", "'FUNCTIONS'", "'GRAPHVIZ'", + "'GROUP'", "'HAVING'", "'IN'", "'INNER'", "'IS'", "'JOIN'", "'LAST'", + "'LEFT'", "'LIKE'", "'LIMIT'", "'MAPPED'", "'MATCH'", "'NATURAL'", "'NOT'", + "'NULL'", "'NULLS'", "'ON'", "'OPTIMIZED'", "'OR'", "'ORDER'", "'OUTER'", + "'PARSED'", "'PHYSICAL'", "'PLAN'", "'RIGHT'", "'RLIKE'", "'QUERY'", "'SCHEMAS'", + "'SELECT'", "'SHOW'", "'SYS'", "'TABLE'", "'TABLES'", "'TEXT'", "'TRUE'", + "'TYPE'", "'TYPES'", "'USING'", "'VERIFY'", "'WHERE'", "'WITH'", "'{ESCAPE'", + "'{FN'", "'{LIMIT'", "'{D'", "'{T'", "'{TS'", "'{GUID'", "'}'", "'='", + null, "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", + "'||'", "'.'", "'?'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, "ALL", "ANALYZE", "ANALYZED", "AND", "ANY", "AS", "ASC", "BETWEEN", "BY", "CAST", "CATALOG", "CATALOGS", "COLUMNS", "DEBUG", "DESC", "DESCRIBE", "DISTINCT", "ESCAPE", "EXECUTABLE", "EXISTS", - "EXPLAIN", "EXTRACT", "FALSE", "FORMAT", "FROM", "FULL", "FUNCTIONS", - "GRAPHVIZ", "GROUP", "HAVING", "IN", "INNER", "IS", "JOIN", "LEFT", "LIKE", - "LIMIT", "MAPPED", "MATCH", "NATURAL", "NOT", "NULL", "ON", "OPTIMIZED", - "OR", "ORDER", "OUTER", "PARSED", "PHYSICAL", "PLAN", "RIGHT", "RLIKE", - "QUERY", "SCHEMAS", "SELECT", "SHOW", "SYS", "TABLE", "TABLES", "TEXT", - "TRUE", "TYPE", "TYPES", "USING", "VERIFY", "WHERE", "WITH", "ESCAPE_ESC", - "FUNCTION_ESC", "LIMIT_ESC", "DATE_ESC", "TIME_ESC", "TIMESTAMP_ESC", - "GUID_ESC", "ESC_END", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", - "MINUS", "ASTERISK", "SLASH", "PERCENT", "CONCAT", "DOT", "PARAM", "STRING", - "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "DIGIT_IDENTIFIER", "TABLE_IDENTIFIER", - "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "SIMPLE_COMMENT", "BRACKETED_COMMENT", - "WS", "UNRECOGNIZED" + "EXPLAIN", "EXTRACT", "FALSE", "FIRST", "FORMAT", "FROM", "FULL", "FUNCTIONS", + "GRAPHVIZ", "GROUP", "HAVING", "IN", "INNER", "IS", "JOIN", "LAST", "LEFT", + "LIKE", "LIMIT", "MAPPED", "MATCH", "NATURAL", "NOT", "NULL", "NULLS", + "ON", "OPTIMIZED", "OR", "ORDER", "OUTER", "PARSED", "PHYSICAL", "PLAN", + "RIGHT", "RLIKE", "QUERY", "SCHEMAS", "SELECT", "SHOW", "SYS", "TABLE", + "TABLES", "TEXT", "TRUE", "TYPE", "TYPES", "USING", "VERIFY", "WHERE", + "WITH", "ESCAPE_ESC", "FUNCTION_ESC", "LIMIT_ESC", "DATE_ESC", "TIME_ESC", + "TIMESTAMP_ESC", "GUID_ESC", "ESC_END", "EQ", "NEQ", "LT", "LTE", "GT", + "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", "CONCAT", "DOT", + "PARAM", "STRING", "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "DIGIT_IDENTIFIER", + "TABLE_IDENTIFIER", "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "SIMPLE_COMMENT", + "BRACKETED_COMMENT", "WS", "UNRECOGNIZED" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -142,7 +143,7 @@ public SqlBaseLexer(CharStream input) { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2k\u036f\b\1\4\2\t"+ + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2n\u0386\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"+ @@ -154,54 +155,55 @@ public SqlBaseLexer(CharStream input) { "\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+ "\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+ "`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k\t"+ - "k\4l\tl\4m\tm\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\6\3\7\3\7"+ - "\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3"+ - "\t\3\t\3\n\3\n\3\n\3\n\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\r\3\r\3\r\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\20\3\20\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\21\3\21"+ - "\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\23"+ - "\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25"+ - "\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27"+ - "\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\31"+ - "\3\31\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32"+ - "\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34\3\34"+ - "\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\37\3\37"+ - "\3\37\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$\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+\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\60\3\60\3\60\3\61\3\61\3\61\3\61"+ - "\3\61\3\61\3\61\3\61\3\61\3\61\3\62\3\62\3\62\3\63\3\63\3\63\3\63\3\63"+ - "\3\63\3\64\3\64\3\64\3\64\3\64\3\64\3\65\3\65\3\65\3\65\3\65\3\65\3\65"+ - "\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\67\3\67\3\67\3\67\3\67"+ - "\38\38\38\38\38\38\39\39\39\39\39\39\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?"+ - "\3?\3?\3@\3@\3@\3@\3@\3@\3@\3A\3A\3A\3A\3A\3B\3B\3B\3B\3B\3C\3C\3C\3C"+ - "\3C\3D\3D\3D\3D\3D\3D\3E\3E\3E\3E\3E\3E\3F\3F\3F\3F\3F\3F\3F\3G\3G\3G"+ - "\3G\3G\3G\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3I\3I\3J\3J\3J\3J\3K\3K\3K"+ - "\3K\3K\3K\3K\3L\3L\3L\3M\3M\3M\3N\3N\3N\3N\3O\3O\3O\3O\3O\3O\3P\3P\3Q"+ - "\3Q\3R\3R\3R\3R\3R\3R\3R\5R\u02b0\nR\3S\3S\3T\3T\3T\3U\3U\3V\3V\3V\3W"+ - "\3W\3X\3X\3Y\3Y\3Z\3Z\3[\3[\3\\\3\\\3\\\3]\3]\3^\3^\3_\3_\3_\3_\7_\u02d1"+ - "\n_\f_\16_\u02d4\13_\3_\3_\3`\6`\u02d9\n`\r`\16`\u02da\3a\6a\u02de\na"+ - "\ra\16a\u02df\3a\3a\7a\u02e4\na\fa\16a\u02e7\13a\3a\3a\6a\u02eb\na\ra"+ - "\16a\u02ec\3a\6a\u02f0\na\ra\16a\u02f1\3a\3a\7a\u02f6\na\fa\16a\u02f9"+ - "\13a\5a\u02fb\na\3a\3a\3a\3a\6a\u0301\na\ra\16a\u0302\3a\3a\5a\u0307\n"+ - "a\3b\3b\5b\u030b\nb\3b\3b\3b\7b\u0310\nb\fb\16b\u0313\13b\3c\3c\3c\3c"+ - "\6c\u0319\nc\rc\16c\u031a\3d\3d\3d\6d\u0320\nd\rd\16d\u0321\3e\3e\3e\3"+ - "e\7e\u0328\ne\fe\16e\u032b\13e\3e\3e\3f\3f\3f\3f\7f\u0333\nf\ff\16f\u0336"+ - "\13f\3f\3f\3g\3g\5g\u033c\ng\3g\6g\u033f\ng\rg\16g\u0340\3h\3h\3i\3i\3"+ - "j\3j\3j\3j\7j\u034b\nj\fj\16j\u034e\13j\3j\5j\u0351\nj\3j\5j\u0354\nj"+ - "\3j\3j\3k\3k\3k\3k\3k\7k\u035d\nk\fk\16k\u0360\13k\3k\3k\3k\3k\3k\3l\6"+ - "l\u0368\nl\rl\16l\u0369\3l\3l\3m\3m\3\u035e\2n\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,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u{?}@\177A\u0081"+ - "B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095"+ - "L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9"+ - "V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd"+ - "`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9f\u00cbg\u00cd\2\u00cf\2\u00d1"+ - "\2\u00d3h\u00d5i\u00d7j\u00d9k\3\2\f\3\2))\4\2BBaa\5\2<\3>\3>\3>\3>\3>\3>"+ + "\3>\3?\3?\3?\3?\3?\3?\3?\3@\3@\3@\3@\3@\3A\3A\3A\3A\3B\3B\3B\3B\3B\3B"+ + "\3C\3C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3E\3E\3E\3E\3E\3F\3F\3F\3F\3F\3G"+ + "\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3I\3J\3J\3J\3J\3J"+ + "\3J\3K\3K\3K\3K\3K\3L\3L\3L\3L\3L\3L\3L\3L\3M\3M\3M\3M\3N\3N\3N\3N\3N"+ + "\3N\3N\3O\3O\3O\3P\3P\3P\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3R\3R\3S\3S\3T\3T\3U"+ + "\3U\3U\3U\3U\3U\3U\5U\u02c7\nU\3V\3V\3W\3W\3W\3X\3X\3Y\3Y\3Y\3Z\3Z\3["+ + "\3[\3\\\3\\\3]\3]\3^\3^\3_\3_\3_\3`\3`\3a\3a\3b\3b\3b\3b\7b\u02e8\nb\f"+ + "b\16b\u02eb\13b\3b\3b\3c\6c\u02f0\nc\rc\16c\u02f1\3d\6d\u02f5\nd\rd\16"+ + "d\u02f6\3d\3d\7d\u02fb\nd\fd\16d\u02fe\13d\3d\3d\6d\u0302\nd\rd\16d\u0303"+ + "\3d\6d\u0307\nd\rd\16d\u0308\3d\3d\7d\u030d\nd\fd\16d\u0310\13d\5d\u0312"+ + "\nd\3d\3d\3d\3d\6d\u0318\nd\rd\16d\u0319\3d\3d\5d\u031e\nd\3e\3e\5e\u0322"+ + "\ne\3e\3e\3e\7e\u0327\ne\fe\16e\u032a\13e\3f\3f\3f\3f\6f\u0330\nf\rf\16"+ + "f\u0331\3g\3g\3g\6g\u0337\ng\rg\16g\u0338\3h\3h\3h\3h\7h\u033f\nh\fh\16"+ + "h\u0342\13h\3h\3h\3i\3i\3i\3i\7i\u034a\ni\fi\16i\u034d\13i\3i\3i\3j\3"+ + "j\5j\u0353\nj\3j\6j\u0356\nj\rj\16j\u0357\3k\3k\3l\3l\3m\3m\3m\3m\7m\u0362"+ + "\nm\fm\16m\u0365\13m\3m\5m\u0368\nm\3m\5m\u036b\nm\3m\3m\3n\3n\3n\3n\3"+ + "n\7n\u0374\nn\fn\16n\u0377\13n\3n\3n\3n\3n\3n\3o\6o\u037f\no\ro\16o\u0380"+ + "\3o\3o\3p\3p\3\u0375\2q\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,W-Y.[/]\60_\61a\62"+ + "c\63e\64g\65i\66k\67m8o9q:s;u{?}@\177A\u0081B\u0083C\u0085D\u0087"+ + "E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009b"+ + "O\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00af"+ + "Y\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3"+ + "c\u00c5d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3\2\u00d5\2\u00d7"+ + "\2\u00d9k\u00dbl\u00ddm\u00dfn\3\2\f\3\2))\4\2BBaa\5\2<\3\2\2\2\u018d\u018e"+ - "\7H\2\2\u018e\u018f\7W\2\2\u018f\u0190\7P\2\2\u0190\u0191\7E\2\2\u0191"+ - "\u0192\7V\2\2\u0192\u0193\7K\2\2\u0193\u0194\7Q\2\2\u0194\u0195\7P\2\2"+ - "\u0195\u0196\7U\2\2\u0196@\3\2\2\2\u0197\u0198\7I\2\2\u0198\u0199\7T\2"+ - "\2\u0199\u019a\7C\2\2\u019a\u019b\7R\2\2\u019b\u019c\7J\2\2\u019c\u019d"+ - "\7X\2\2\u019d\u019e\7K\2\2\u019e\u019f\7\\\2\2\u019fB\3\2\2\2\u01a0\u01a1"+ - "\7I\2\2\u01a1\u01a2\7T\2\2\u01a2\u01a3\7Q\2\2\u01a3\u01a4\7W\2\2\u01a4"+ - "\u01a5\7R\2\2\u01a5D\3\2\2\2\u01a6\u01a7\7J\2\2\u01a7\u01a8\7C\2\2\u01a8"+ - "\u01a9\7X\2\2\u01a9\u01aa\7K\2\2\u01aa\u01ab\7P\2\2\u01ab\u01ac\7I\2\2"+ - "\u01acF\3\2\2\2\u01ad\u01ae\7K\2\2\u01ae\u01af\7P\2\2\u01afH\3\2\2\2\u01b0"+ - "\u01b1\7K\2\2\u01b1\u01b2\7P\2\2\u01b2\u01b3\7P\2\2\u01b3\u01b4\7G\2\2"+ - "\u01b4\u01b5\7T\2\2\u01b5J\3\2\2\2\u01b6\u01b7\7K\2\2\u01b7\u01b8\7U\2"+ - "\2\u01b8L\3\2\2\2\u01b9\u01ba\7L\2\2\u01ba\u01bb\7Q\2\2\u01bb\u01bc\7"+ - "K\2\2\u01bc\u01bd\7P\2\2\u01bdN\3\2\2\2\u01be\u01bf\7N\2\2\u01bf\u01c0"+ - "\7G\2\2\u01c0\u01c1\7H\2\2\u01c1\u01c2\7V\2\2\u01c2P\3\2\2\2\u01c3\u01c4"+ - "\7N\2\2\u01c4\u01c5\7K\2\2\u01c5\u01c6\7M\2\2\u01c6\u01c7\7G\2\2\u01c7"+ - "R\3\2\2\2\u01c8\u01c9\7N\2\2\u01c9\u01ca\7K\2\2\u01ca\u01cb\7O\2\2\u01cb"+ - "\u01cc\7K\2\2\u01cc\u01cd\7V\2\2\u01cdT\3\2\2\2\u01ce\u01cf\7O\2\2\u01cf"+ - "\u01d0\7C\2\2\u01d0\u01d1\7R\2\2\u01d1\u01d2\7R\2\2\u01d2\u01d3\7G\2\2"+ - "\u01d3\u01d4\7F\2\2\u01d4V\3\2\2\2\u01d5\u01d6\7O\2\2\u01d6\u01d7\7C\2"+ - "\2\u01d7\u01d8\7V\2\2\u01d8\u01d9\7E\2\2\u01d9\u01da\7J\2\2\u01daX\3\2"+ - "\2\2\u01db\u01dc\7P\2\2\u01dc\u01dd\7C\2\2\u01dd\u01de\7V\2\2\u01de\u01df"+ - "\7W\2\2\u01df\u01e0\7T\2\2\u01e0\u01e1\7C\2\2\u01e1\u01e2\7N\2\2\u01e2"+ - "Z\3\2\2\2\u01e3\u01e4\7P\2\2\u01e4\u01e5\7Q\2\2\u01e5\u01e6\7V\2\2\u01e6"+ - "\\\3\2\2\2\u01e7\u01e8\7P\2\2\u01e8\u01e9\7W\2\2\u01e9\u01ea\7N\2\2\u01ea"+ - "\u01eb\7N\2\2\u01eb^\3\2\2\2\u01ec\u01ed\7Q\2\2\u01ed\u01ee\7P\2\2\u01ee"+ - "`\3\2\2\2\u01ef\u01f0\7Q\2\2\u01f0\u01f1\7R\2\2\u01f1\u01f2\7V\2\2\u01f2"+ - "\u01f3\7K\2\2\u01f3\u01f4\7O\2\2\u01f4\u01f5\7K\2\2\u01f5\u01f6\7\\\2"+ - "\2\u01f6\u01f7\7G\2\2\u01f7\u01f8\7F\2\2\u01f8b\3\2\2\2\u01f9\u01fa\7"+ - "Q\2\2\u01fa\u01fb\7T\2\2\u01fbd\3\2\2\2\u01fc\u01fd\7Q\2\2\u01fd\u01fe"+ - "\7T\2\2\u01fe\u01ff\7F\2\2\u01ff\u0200\7G\2\2\u0200\u0201\7T\2\2\u0201"+ - "f\3\2\2\2\u0202\u0203\7Q\2\2\u0203\u0204\7W\2\2\u0204\u0205\7V\2\2\u0205"+ - "\u0206\7G\2\2\u0206\u0207\7T\2\2\u0207h\3\2\2\2\u0208\u0209\7R\2\2\u0209"+ - "\u020a\7C\2\2\u020a\u020b\7T\2\2\u020b\u020c\7U\2\2\u020c\u020d\7G\2\2"+ - "\u020d\u020e\7F\2\2\u020ej\3\2\2\2\u020f\u0210\7R\2\2\u0210\u0211\7J\2"+ - "\2\u0211\u0212\7[\2\2\u0212\u0213\7U\2\2\u0213\u0214\7K\2\2\u0214\u0215"+ - "\7E\2\2\u0215\u0216\7C\2\2\u0216\u0217\7N\2\2\u0217l\3\2\2\2\u0218\u0219"+ - "\7R\2\2\u0219\u021a\7N\2\2\u021a\u021b\7C\2\2\u021b\u021c\7P\2\2\u021c"+ - "n\3\2\2\2\u021d\u021e\7T\2\2\u021e\u021f\7K\2\2\u021f\u0220\7I\2\2\u0220"+ - "\u0221\7J\2\2\u0221\u0222\7V\2\2\u0222p\3\2\2\2\u0223\u0224\7T\2\2\u0224"+ - "\u0225\7N\2\2\u0225\u0226\7K\2\2\u0226\u0227\7M\2\2\u0227\u0228\7G\2\2"+ - "\u0228r\3\2\2\2\u0229\u022a\7S\2\2\u022a\u022b\7W\2\2\u022b\u022c\7G\2"+ - "\2\u022c\u022d\7T\2\2\u022d\u022e\7[\2\2\u022et\3\2\2\2\u022f\u0230\7"+ - "U\2\2\u0230\u0231\7E\2\2\u0231\u0232\7J\2\2\u0232\u0233\7G\2\2\u0233\u0234"+ - "\7O\2\2\u0234\u0235\7C\2\2\u0235\u0236\7U\2\2\u0236v\3\2\2\2\u0237\u0238"+ - "\7U\2\2\u0238\u0239\7G\2\2\u0239\u023a\7N\2\2\u023a\u023b\7G\2\2\u023b"+ - "\u023c\7E\2\2\u023c\u023d\7V\2\2\u023dx\3\2\2\2\u023e\u023f\7U\2\2\u023f"+ - "\u0240\7J\2\2\u0240\u0241\7Q\2\2\u0241\u0242\7Y\2\2\u0242z\3\2\2\2\u0243"+ - "\u0244\7U\2\2\u0244\u0245\7[\2\2\u0245\u0246\7U\2\2\u0246|\3\2\2\2\u0247"+ - "\u0248\7V\2\2\u0248\u0249\7C\2\2\u0249\u024a\7D\2\2\u024a\u024b\7N\2\2"+ - "\u024b\u024c\7G\2\2\u024c~\3\2\2\2\u024d\u024e\7V\2\2\u024e\u024f\7C\2"+ - "\2\u024f\u0250\7D\2\2\u0250\u0251\7N\2\2\u0251\u0252\7G\2\2\u0252\u0253"+ - "\7U\2\2\u0253\u0080\3\2\2\2\u0254\u0255\7V\2\2\u0255\u0256\7G\2\2\u0256"+ - "\u0257\7Z\2\2\u0257\u0258\7V\2\2\u0258\u0082\3\2\2\2\u0259\u025a\7V\2"+ - "\2\u025a\u025b\7T\2\2\u025b\u025c\7W\2\2\u025c\u025d\7G\2\2\u025d\u0084"+ - "\3\2\2\2\u025e\u025f\7V\2\2\u025f\u0260\7[\2\2\u0260\u0261\7R\2\2\u0261"+ - "\u0262\7G\2\2\u0262\u0086\3\2\2\2\u0263\u0264\7V\2\2\u0264\u0265\7[\2"+ - "\2\u0265\u0266\7R\2\2\u0266\u0267\7G\2\2\u0267\u0268\7U\2\2\u0268\u0088"+ - "\3\2\2\2\u0269\u026a\7W\2\2\u026a\u026b\7U\2\2\u026b\u026c\7K\2\2\u026c"+ - "\u026d\7P\2\2\u026d\u026e\7I\2\2\u026e\u008a\3\2\2\2\u026f\u0270\7X\2"+ - "\2\u0270\u0271\7G\2\2\u0271\u0272\7T\2\2\u0272\u0273\7K\2\2\u0273\u0274"+ - "\7H\2\2\u0274\u0275\7[\2\2\u0275\u008c\3\2\2\2\u0276\u0277\7Y\2\2\u0277"+ - "\u0278\7J\2\2\u0278\u0279\7G\2\2\u0279\u027a\7T\2\2\u027a\u027b\7G\2\2"+ - "\u027b\u008e\3\2\2\2\u027c\u027d\7Y\2\2\u027d\u027e\7K\2\2\u027e\u027f"+ - "\7V\2\2\u027f\u0280\7J\2\2\u0280\u0090\3\2\2\2\u0281\u0282\7}\2\2\u0282"+ - "\u0283\7G\2\2\u0283\u0284\7U\2\2\u0284\u0285\7E\2\2\u0285\u0286\7C\2\2"+ - "\u0286\u0287\7R\2\2\u0287\u0288\7G\2\2\u0288\u0092\3\2\2\2\u0289\u028a"+ - "\7}\2\2\u028a\u028b\7H\2\2\u028b\u028c\7P\2\2\u028c\u0094\3\2\2\2\u028d"+ - "\u028e\7}\2\2\u028e\u028f\7N\2\2\u028f\u0290\7K\2\2\u0290\u0291\7O\2\2"+ - "\u0291\u0292\7K\2\2\u0292\u0293\7V\2\2\u0293\u0096\3\2\2\2\u0294\u0295"+ - "\7}\2\2\u0295\u0296\7F\2\2\u0296\u0098\3\2\2\2\u0297\u0298\7}\2\2\u0298"+ - "\u0299\7V\2\2\u0299\u009a\3\2\2\2\u029a\u029b\7}\2\2\u029b\u029c\7V\2"+ - "\2\u029c\u029d\7U\2\2\u029d\u009c\3\2\2\2\u029e\u029f\7}\2\2\u029f\u02a0"+ - "\7I\2\2\u02a0\u02a1\7W\2\2\u02a1\u02a2\7K\2\2\u02a2\u02a3\7F\2\2\u02a3"+ - "\u009e\3\2\2\2\u02a4\u02a5\7\177\2\2\u02a5\u00a0\3\2\2\2\u02a6\u02a7\7"+ - "?\2\2\u02a7\u00a2\3\2\2\2\u02a8\u02a9\7>\2\2\u02a9\u02b0\7@\2\2\u02aa"+ - "\u02ab\7#\2\2\u02ab\u02b0\7?\2\2\u02ac\u02ad\7>\2\2\u02ad\u02ae\7?\2\2"+ - "\u02ae\u02b0\7@\2\2\u02af\u02a8\3\2\2\2\u02af\u02aa\3\2\2\2\u02af\u02ac"+ - "\3\2\2\2\u02b0\u00a4\3\2\2\2\u02b1\u02b2\7>\2\2\u02b2\u00a6\3\2\2\2\u02b3"+ - "\u02b4\7>\2\2\u02b4\u02b5\7?\2\2\u02b5\u00a8\3\2\2\2\u02b6\u02b7\7@\2"+ - "\2\u02b7\u00aa\3\2\2\2\u02b8\u02b9\7@\2\2\u02b9\u02ba\7?\2\2\u02ba\u00ac"+ - "\3\2\2\2\u02bb\u02bc\7-\2\2\u02bc\u00ae\3\2\2\2\u02bd\u02be\7/\2\2\u02be"+ - "\u00b0\3\2\2\2\u02bf\u02c0\7,\2\2\u02c0\u00b2\3\2\2\2\u02c1\u02c2\7\61"+ - "\2\2\u02c2\u00b4\3\2\2\2\u02c3\u02c4\7\'\2\2\u02c4\u00b6\3\2\2\2\u02c5"+ - "\u02c6\7~\2\2\u02c6\u02c7\7~\2\2\u02c7\u00b8\3\2\2\2\u02c8\u02c9\7\60"+ - "\2\2\u02c9\u00ba\3\2\2\2\u02ca\u02cb\7A\2\2\u02cb\u00bc\3\2\2\2\u02cc"+ - "\u02d2\7)\2\2\u02cd\u02d1\n\2\2\2\u02ce\u02cf\7)\2\2\u02cf\u02d1\7)\2"+ - "\2\u02d0\u02cd\3\2\2\2\u02d0\u02ce\3\2\2\2\u02d1\u02d4\3\2\2\2\u02d2\u02d0"+ - "\3\2\2\2\u02d2\u02d3\3\2\2\2\u02d3\u02d5\3\2\2\2\u02d4\u02d2\3\2\2\2\u02d5"+ - "\u02d6\7)\2\2\u02d6\u00be\3\2\2\2\u02d7\u02d9\5\u00cfh\2\u02d8\u02d7\3"+ - "\2\2\2\u02d9\u02da\3\2\2\2\u02da\u02d8\3\2\2\2\u02da\u02db\3\2\2\2\u02db"+ - "\u00c0\3\2\2\2\u02dc\u02de\5\u00cfh\2\u02dd\u02dc\3\2\2\2\u02de\u02df"+ - "\3\2\2\2\u02df\u02dd\3\2\2\2\u02df\u02e0\3\2\2\2\u02e0\u02e1\3\2\2\2\u02e1"+ - "\u02e5\5\u00b9]\2\u02e2\u02e4\5\u00cfh\2\u02e3\u02e2\3\2\2\2\u02e4\u02e7"+ - "\3\2\2\2\u02e5\u02e3\3\2\2\2\u02e5\u02e6\3\2\2\2\u02e6\u0307\3\2\2\2\u02e7"+ - "\u02e5\3\2\2\2\u02e8\u02ea\5\u00b9]\2\u02e9\u02eb\5\u00cfh\2\u02ea\u02e9"+ - "\3\2\2\2\u02eb\u02ec\3\2\2\2\u02ec\u02ea\3\2\2\2\u02ec\u02ed\3\2\2\2\u02ed"+ - "\u0307\3\2\2\2\u02ee\u02f0\5\u00cfh\2\u02ef\u02ee\3\2\2\2\u02f0\u02f1"+ - "\3\2\2\2\u02f1\u02ef\3\2\2\2\u02f1\u02f2\3\2\2\2\u02f2\u02fa\3\2\2\2\u02f3"+ - "\u02f7\5\u00b9]\2\u02f4\u02f6\5\u00cfh\2\u02f5\u02f4\3\2\2\2\u02f6\u02f9"+ - "\3\2\2\2\u02f7\u02f5\3\2\2\2\u02f7\u02f8\3\2\2\2\u02f8\u02fb\3\2\2\2\u02f9"+ - "\u02f7\3\2\2\2\u02fa\u02f3\3\2\2\2\u02fa\u02fb\3\2\2\2\u02fb\u02fc\3\2"+ - "\2\2\u02fc\u02fd\5\u00cdg\2\u02fd\u0307\3\2\2\2\u02fe\u0300\5\u00b9]\2"+ - "\u02ff\u0301\5\u00cfh\2\u0300\u02ff\3\2\2\2\u0301\u0302\3\2\2\2\u0302"+ - "\u0300\3\2\2\2\u0302\u0303\3\2\2\2\u0303\u0304\3\2\2\2\u0304\u0305\5\u00cd"+ - "g\2\u0305\u0307\3\2\2\2\u0306\u02dd\3\2\2\2\u0306\u02e8\3\2\2\2\u0306"+ - "\u02ef\3\2\2\2\u0306\u02fe\3\2\2\2\u0307\u00c2\3\2\2\2\u0308\u030b\5\u00d1"+ - "i\2\u0309\u030b\7a\2\2\u030a\u0308\3\2\2\2\u030a\u0309\3\2\2\2\u030b\u0311"+ - "\3\2\2\2\u030c\u0310\5\u00d1i\2\u030d\u0310\5\u00cfh\2\u030e\u0310\t\3"+ - "\2\2\u030f\u030c\3\2\2\2\u030f\u030d\3\2\2\2\u030f\u030e\3\2\2\2\u0310"+ - "\u0313\3\2\2\2\u0311\u030f\3\2\2\2\u0311\u0312\3\2\2\2\u0312\u00c4\3\2"+ - "\2\2\u0313\u0311\3\2\2\2\u0314\u0318\5\u00cfh\2\u0315\u0319\5\u00d1i\2"+ - "\u0316\u0319\5\u00cfh\2\u0317\u0319\t\4\2\2\u0318\u0315\3\2\2\2\u0318"+ - "\u0316\3\2\2\2\u0318\u0317\3\2\2\2\u0319\u031a\3\2\2\2\u031a\u0318\3\2"+ - "\2\2\u031a\u031b\3\2\2\2\u031b\u00c6\3\2\2\2\u031c\u0320\5\u00d1i\2\u031d"+ - "\u0320\5\u00cfh\2\u031e\u0320\7a\2\2\u031f\u031c\3\2\2\2\u031f\u031d\3"+ - "\2\2\2\u031f\u031e\3\2\2\2\u0320\u0321\3\2\2\2\u0321\u031f\3\2\2\2\u0321"+ - "\u0322\3\2\2\2\u0322\u00c8\3\2\2\2\u0323\u0329\7$\2\2\u0324\u0328\n\5"+ - "\2\2\u0325\u0326\7$\2\2\u0326\u0328\7$\2\2\u0327\u0324\3\2\2\2\u0327\u0325"+ - "\3\2\2\2\u0328\u032b\3\2\2\2\u0329\u0327\3\2\2\2\u0329\u032a\3\2\2\2\u032a"+ - "\u032c\3\2\2\2\u032b\u0329\3\2\2\2\u032c\u032d\7$\2\2\u032d\u00ca\3\2"+ - "\2\2\u032e\u0334\7b\2\2\u032f\u0333\n\6\2\2\u0330\u0331\7b\2\2\u0331\u0333"+ - "\7b\2\2\u0332\u032f\3\2\2\2\u0332\u0330\3\2\2\2\u0333\u0336\3\2\2\2\u0334"+ - "\u0332\3\2\2\2\u0334\u0335\3\2\2\2\u0335\u0337\3\2\2\2\u0336\u0334\3\2"+ - "\2\2\u0337\u0338\7b\2\2\u0338\u00cc\3\2\2\2\u0339\u033b\7G\2\2\u033a\u033c"+ - "\t\7\2\2\u033b\u033a\3\2\2\2\u033b\u033c\3\2\2\2\u033c\u033e\3\2\2\2\u033d"+ - "\u033f\5\u00cfh\2\u033e\u033d\3\2\2\2\u033f\u0340\3\2\2\2\u0340\u033e"+ - "\3\2\2\2\u0340\u0341\3\2\2\2\u0341\u00ce\3\2\2\2\u0342\u0343\t\b\2\2\u0343"+ - "\u00d0\3\2\2\2\u0344\u0345\t\t\2\2\u0345\u00d2\3\2\2\2\u0346\u0347\7/"+ - "\2\2\u0347\u0348\7/\2\2\u0348\u034c\3\2\2\2\u0349\u034b\n\n\2\2\u034a"+ - "\u0349\3\2\2\2\u034b\u034e\3\2\2\2\u034c\u034a\3\2\2\2\u034c\u034d\3\2"+ - "\2\2\u034d\u0350\3\2\2\2\u034e\u034c\3\2\2\2\u034f\u0351\7\17\2\2\u0350"+ - "\u034f\3\2\2\2\u0350\u0351\3\2\2\2\u0351\u0353\3\2\2\2\u0352\u0354\7\f"+ - "\2\2\u0353\u0352\3\2\2\2\u0353\u0354\3\2\2\2\u0354\u0355\3\2\2\2\u0355"+ - "\u0356\bj\2\2\u0356\u00d4\3\2\2\2\u0357\u0358\7\61\2\2\u0358\u0359\7,"+ - "\2\2\u0359\u035e\3\2\2\2\u035a\u035d\5\u00d5k\2\u035b\u035d\13\2\2\2\u035c"+ - "\u035a\3\2\2\2\u035c\u035b\3\2\2\2\u035d\u0360\3\2\2\2\u035e\u035f\3\2"+ - "\2\2\u035e\u035c\3\2\2\2\u035f\u0361\3\2\2\2\u0360\u035e\3\2\2\2\u0361"+ - "\u0362\7,\2\2\u0362\u0363\7\61\2\2\u0363\u0364\3\2\2\2\u0364\u0365\bk"+ - "\2\2\u0365\u00d6\3\2\2\2\u0366\u0368\t\13\2\2\u0367\u0366\3\2\2\2\u0368"+ - "\u0369\3\2\2\2\u0369\u0367\3\2\2\2\u0369\u036a\3\2\2\2\u036a\u036b\3\2"+ - "\2\2\u036b\u036c\bl\2\2\u036c\u00d8\3\2\2\2\u036d\u036e\13\2\2\2\u036e"+ - "\u00da\3\2\2\2\"\2\u02af\u02d0\u02d2\u02da\u02df\u02e5\u02ec\u02f1\u02f7"+ - "\u02fa\u0302\u0306\u030a\u030f\u0311\u0318\u031a\u031f\u0321\u0327\u0329"+ - "\u0332\u0334\u033b\u0340\u034c\u0350\u0353\u035c\u035e\u0369\3\2\3\2"; + "\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd"+ + "\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2\2\2\u00d9\3\2\2\2\2\u00db\3\2\2"+ + "\2\2\u00dd\3\2\2\2\2\u00df\3\2\2\2\3\u00e1\3\2\2\2\5\u00e3\3\2\2\2\7\u00e5"+ + "\3\2\2\2\t\u00e7\3\2\2\2\13\u00e9\3\2\2\2\r\u00ed\3\2\2\2\17\u00f5\3\2"+ + "\2\2\21\u00fe\3\2\2\2\23\u0102\3\2\2\2\25\u0106\3\2\2\2\27\u0109\3\2\2"+ + "\2\31\u010d\3\2\2\2\33\u0115\3\2\2\2\35\u0118\3\2\2\2\37\u011d\3\2\2\2"+ + "!\u0125\3\2\2\2#\u012e\3\2\2\2%\u0136\3\2\2\2\'\u013c\3\2\2\2)\u0141\3"+ + "\2\2\2+\u014a\3\2\2\2-\u0153\3\2\2\2/\u015a\3\2\2\2\61\u0165\3\2\2\2\63"+ + "\u016c\3\2\2\2\65\u0174\3\2\2\2\67\u017c\3\2\2\29\u0182\3\2\2\2;\u0188"+ + "\3\2\2\2=\u018f\3\2\2\2?\u0194\3\2\2\2A\u0199\3\2\2\2C\u01a3\3\2\2\2E"+ + "\u01ac\3\2\2\2G\u01b2\3\2\2\2I\u01b9\3\2\2\2K\u01bc\3\2\2\2M\u01c2\3\2"+ + "\2\2O\u01c5\3\2\2\2Q\u01ca\3\2\2\2S\u01cf\3\2\2\2U\u01d4\3\2\2\2W\u01d9"+ + "\3\2\2\2Y\u01df\3\2\2\2[\u01e6\3\2\2\2]\u01ec\3\2\2\2_\u01f4\3\2\2\2a"+ + "\u01f8\3\2\2\2c\u01fd\3\2\2\2e\u0203\3\2\2\2g\u0206\3\2\2\2i\u0210\3\2"+ + "\2\2k\u0213\3\2\2\2m\u0219\3\2\2\2o\u021f\3\2\2\2q\u0226\3\2\2\2s\u022f"+ + "\3\2\2\2u\u0234\3\2\2\2w\u023a\3\2\2\2y\u0240\3\2\2\2{\u0246\3\2\2\2}"+ + "\u024e\3\2\2\2\177\u0255\3\2\2\2\u0081\u025a\3\2\2\2\u0083\u025e\3\2\2"+ + "\2\u0085\u0264\3\2\2\2\u0087\u026b\3\2\2\2\u0089\u0270\3\2\2\2\u008b\u0275"+ + "\3\2\2\2\u008d\u027a\3\2\2\2\u008f\u0280\3\2\2\2\u0091\u0286\3\2\2\2\u0093"+ + "\u028d\3\2\2\2\u0095\u0293\3\2\2\2\u0097\u0298\3\2\2\2\u0099\u02a0\3\2"+ + "\2\2\u009b\u02a4\3\2\2\2\u009d\u02ab\3\2\2\2\u009f\u02ae\3\2\2\2\u00a1"+ + "\u02b1\3\2\2\2\u00a3\u02b5\3\2\2\2\u00a5\u02bb\3\2\2\2\u00a7\u02bd\3\2"+ + "\2\2\u00a9\u02c6\3\2\2\2\u00ab\u02c8\3\2\2\2\u00ad\u02ca\3\2\2\2\u00af"+ + "\u02cd\3\2\2\2\u00b1\u02cf\3\2\2\2\u00b3\u02d2\3\2\2\2\u00b5\u02d4\3\2"+ + "\2\2\u00b7\u02d6\3\2\2\2\u00b9\u02d8\3\2\2\2\u00bb\u02da\3\2\2\2\u00bd"+ + "\u02dc\3\2\2\2\u00bf\u02df\3\2\2\2\u00c1\u02e1\3\2\2\2\u00c3\u02e3\3\2"+ + "\2\2\u00c5\u02ef\3\2\2\2\u00c7\u031d\3\2\2\2\u00c9\u0321\3\2\2\2\u00cb"+ + "\u032b\3\2\2\2\u00cd\u0336\3\2\2\2\u00cf\u033a\3\2\2\2\u00d1\u0345\3\2"+ + "\2\2\u00d3\u0350\3\2\2\2\u00d5\u0359\3\2\2\2\u00d7\u035b\3\2\2\2\u00d9"+ + "\u035d\3\2\2\2\u00db\u036e\3\2\2\2\u00dd\u037e\3\2\2\2\u00df\u0384\3\2"+ + "\2\2\u00e1\u00e2\7*\2\2\u00e2\4\3\2\2\2\u00e3\u00e4\7+\2\2\u00e4\6\3\2"+ + "\2\2\u00e5\u00e6\7.\2\2\u00e6\b\3\2\2\2\u00e7\u00e8\7<\2\2\u00e8\n\3\2"+ + "\2\2\u00e9\u00ea\7C\2\2\u00ea\u00eb\7N\2\2\u00eb\u00ec\7N\2\2\u00ec\f"+ + "\3\2\2\2\u00ed\u00ee\7C\2\2\u00ee\u00ef\7P\2\2\u00ef\u00f0\7C\2\2\u00f0"+ + "\u00f1\7N\2\2\u00f1\u00f2\7[\2\2\u00f2\u00f3\7\\\2\2\u00f3\u00f4\7G\2"+ + "\2\u00f4\16\3\2\2\2\u00f5\u00f6\7C\2\2\u00f6\u00f7\7P\2\2\u00f7\u00f8"+ + "\7C\2\2\u00f8\u00f9\7N\2\2\u00f9\u00fa\7[\2\2\u00fa\u00fb\7\\\2\2\u00fb"+ + "\u00fc\7G\2\2\u00fc\u00fd\7F\2\2\u00fd\20\3\2\2\2\u00fe\u00ff\7C\2\2\u00ff"+ + "\u0100\7P\2\2\u0100\u0101\7F\2\2\u0101\22\3\2\2\2\u0102\u0103\7C\2\2\u0103"+ + "\u0104\7P\2\2\u0104\u0105\7[\2\2\u0105\24\3\2\2\2\u0106\u0107\7C\2\2\u0107"+ + "\u0108\7U\2\2\u0108\26\3\2\2\2\u0109\u010a\7C\2\2\u010a\u010b\7U\2\2\u010b"+ + "\u010c\7E\2\2\u010c\30\3\2\2\2\u010d\u010e\7D\2\2\u010e\u010f\7G\2\2\u010f"+ + "\u0110\7V\2\2\u0110\u0111\7Y\2\2\u0111\u0112\7G\2\2\u0112\u0113\7G\2\2"+ + "\u0113\u0114\7P\2\2\u0114\32\3\2\2\2\u0115\u0116\7D\2\2\u0116\u0117\7"+ + "[\2\2\u0117\34\3\2\2\2\u0118\u0119\7E\2\2\u0119\u011a\7C\2\2\u011a\u011b"+ + "\7U\2\2\u011b\u011c\7V\2\2\u011c\36\3\2\2\2\u011d\u011e\7E\2\2\u011e\u011f"+ + "\7C\2\2\u011f\u0120\7V\2\2\u0120\u0121\7C\2\2\u0121\u0122\7N\2\2\u0122"+ + "\u0123\7Q\2\2\u0123\u0124\7I\2\2\u0124 \3\2\2\2\u0125\u0126\7E\2\2\u0126"+ + "\u0127\7C\2\2\u0127\u0128\7V\2\2\u0128\u0129\7C\2\2\u0129\u012a\7N\2\2"+ + "\u012a\u012b\7Q\2\2\u012b\u012c\7I\2\2\u012c\u012d\7U\2\2\u012d\"\3\2"+ + "\2\2\u012e\u012f\7E\2\2\u012f\u0130\7Q\2\2\u0130\u0131\7N\2\2\u0131\u0132"+ + "\7W\2\2\u0132\u0133\7O\2\2\u0133\u0134\7P\2\2\u0134\u0135\7U\2\2\u0135"+ + "$\3\2\2\2\u0136\u0137\7F\2\2\u0137\u0138\7G\2\2\u0138\u0139\7D\2\2\u0139"+ + "\u013a\7W\2\2\u013a\u013b\7I\2\2\u013b&\3\2\2\2\u013c\u013d\7F\2\2\u013d"+ + "\u013e\7G\2\2\u013e\u013f\7U\2\2\u013f\u0140\7E\2\2\u0140(\3\2\2\2\u0141"+ + "\u0142\7F\2\2\u0142\u0143\7G\2\2\u0143\u0144\7U\2\2\u0144\u0145\7E\2\2"+ + "\u0145\u0146\7T\2\2\u0146\u0147\7K\2\2\u0147\u0148\7D\2\2\u0148\u0149"+ + "\7G\2\2\u0149*\3\2\2\2\u014a\u014b\7F\2\2\u014b\u014c\7K\2\2\u014c\u014d"+ + "\7U\2\2\u014d\u014e\7V\2\2\u014e\u014f\7K\2\2\u014f\u0150\7P\2\2\u0150"+ + "\u0151\7E\2\2\u0151\u0152\7V\2\2\u0152,\3\2\2\2\u0153\u0154\7G\2\2\u0154"+ + "\u0155\7U\2\2\u0155\u0156\7E\2\2\u0156\u0157\7C\2\2\u0157\u0158\7R\2\2"+ + "\u0158\u0159\7G\2\2\u0159.\3\2\2\2\u015a\u015b\7G\2\2\u015b\u015c\7Z\2"+ + "\2\u015c\u015d\7G\2\2\u015d\u015e\7E\2\2\u015e\u015f\7W\2\2\u015f\u0160"+ + "\7V\2\2\u0160\u0161\7C\2\2\u0161\u0162\7D\2\2\u0162\u0163\7N\2\2\u0163"+ + "\u0164\7G\2\2\u0164\60\3\2\2\2\u0165\u0166\7G\2\2\u0166\u0167\7Z\2\2\u0167"+ + "\u0168\7K\2\2\u0168\u0169\7U\2\2\u0169\u016a\7V\2\2\u016a\u016b\7U\2\2"+ + "\u016b\62\3\2\2\2\u016c\u016d\7G\2\2\u016d\u016e\7Z\2\2\u016e\u016f\7"+ + "R\2\2\u016f\u0170\7N\2\2\u0170\u0171\7C\2\2\u0171\u0172\7K\2\2\u0172\u0173"+ + "\7P\2\2\u0173\64\3\2\2\2\u0174\u0175\7G\2\2\u0175\u0176\7Z\2\2\u0176\u0177"+ + "\7V\2\2\u0177\u0178\7T\2\2\u0178\u0179\7C\2\2\u0179\u017a\7E\2\2\u017a"+ + "\u017b\7V\2\2\u017b\66\3\2\2\2\u017c\u017d\7H\2\2\u017d\u017e\7C\2\2\u017e"+ + "\u017f\7N\2\2\u017f\u0180\7U\2\2\u0180\u0181\7G\2\2\u01818\3\2\2\2\u0182"+ + "\u0183\7H\2\2\u0183\u0184\7K\2\2\u0184\u0185\7T\2\2\u0185\u0186\7U\2\2"+ + "\u0186\u0187\7V\2\2\u0187:\3\2\2\2\u0188\u0189\7H\2\2\u0189\u018a\7Q\2"+ + "\2\u018a\u018b\7T\2\2\u018b\u018c\7O\2\2\u018c\u018d\7C\2\2\u018d\u018e"+ + "\7V\2\2\u018e<\3\2\2\2\u018f\u0190\7H\2\2\u0190\u0191\7T\2\2\u0191\u0192"+ + "\7Q\2\2\u0192\u0193\7O\2\2\u0193>\3\2\2\2\u0194\u0195\7H\2\2\u0195\u0196"+ + "\7W\2\2\u0196\u0197\7N\2\2\u0197\u0198\7N\2\2\u0198@\3\2\2\2\u0199\u019a"+ + "\7H\2\2\u019a\u019b\7W\2\2\u019b\u019c\7P\2\2\u019c\u019d\7E\2\2\u019d"+ + "\u019e\7V\2\2\u019e\u019f\7K\2\2\u019f\u01a0\7Q\2\2\u01a0\u01a1\7P\2\2"+ + "\u01a1\u01a2\7U\2\2\u01a2B\3\2\2\2\u01a3\u01a4\7I\2\2\u01a4\u01a5\7T\2"+ + "\2\u01a5\u01a6\7C\2\2\u01a6\u01a7\7R\2\2\u01a7\u01a8\7J\2\2\u01a8\u01a9"+ + "\7X\2\2\u01a9\u01aa\7K\2\2\u01aa\u01ab\7\\\2\2\u01abD\3\2\2\2\u01ac\u01ad"+ + "\7I\2\2\u01ad\u01ae\7T\2\2\u01ae\u01af\7Q\2\2\u01af\u01b0\7W\2\2\u01b0"+ + "\u01b1\7R\2\2\u01b1F\3\2\2\2\u01b2\u01b3\7J\2\2\u01b3\u01b4\7C\2\2\u01b4"+ + "\u01b5\7X\2\2\u01b5\u01b6\7K\2\2\u01b6\u01b7\7P\2\2\u01b7\u01b8\7I\2\2"+ + "\u01b8H\3\2\2\2\u01b9\u01ba\7K\2\2\u01ba\u01bb\7P\2\2\u01bbJ\3\2\2\2\u01bc"+ + "\u01bd\7K\2\2\u01bd\u01be\7P\2\2\u01be\u01bf\7P\2\2\u01bf\u01c0\7G\2\2"+ + "\u01c0\u01c1\7T\2\2\u01c1L\3\2\2\2\u01c2\u01c3\7K\2\2\u01c3\u01c4\7U\2"+ + "\2\u01c4N\3\2\2\2\u01c5\u01c6\7L\2\2\u01c6\u01c7\7Q\2\2\u01c7\u01c8\7"+ + "K\2\2\u01c8\u01c9\7P\2\2\u01c9P\3\2\2\2\u01ca\u01cb\7N\2\2\u01cb\u01cc"+ + "\7C\2\2\u01cc\u01cd\7U\2\2\u01cd\u01ce\7V\2\2\u01ceR\3\2\2\2\u01cf\u01d0"+ + "\7N\2\2\u01d0\u01d1\7G\2\2\u01d1\u01d2\7H\2\2\u01d2\u01d3\7V\2\2\u01d3"+ + "T\3\2\2\2\u01d4\u01d5\7N\2\2\u01d5\u01d6\7K\2\2\u01d6\u01d7\7M\2\2\u01d7"+ + "\u01d8\7G\2\2\u01d8V\3\2\2\2\u01d9\u01da\7N\2\2\u01da\u01db\7K\2\2\u01db"+ + "\u01dc\7O\2\2\u01dc\u01dd\7K\2\2\u01dd\u01de\7V\2\2\u01deX\3\2\2\2\u01df"+ + "\u01e0\7O\2\2\u01e0\u01e1\7C\2\2\u01e1\u01e2\7R\2\2\u01e2\u01e3\7R\2\2"+ + "\u01e3\u01e4\7G\2\2\u01e4\u01e5\7F\2\2\u01e5Z\3\2\2\2\u01e6\u01e7\7O\2"+ + "\2\u01e7\u01e8\7C\2\2\u01e8\u01e9\7V\2\2\u01e9\u01ea\7E\2\2\u01ea\u01eb"+ + "\7J\2\2\u01eb\\\3\2\2\2\u01ec\u01ed\7P\2\2\u01ed\u01ee\7C\2\2\u01ee\u01ef"+ + "\7V\2\2\u01ef\u01f0\7W\2\2\u01f0\u01f1\7T\2\2\u01f1\u01f2\7C\2\2\u01f2"+ + "\u01f3\7N\2\2\u01f3^\3\2\2\2\u01f4\u01f5\7P\2\2\u01f5\u01f6\7Q\2\2\u01f6"+ + "\u01f7\7V\2\2\u01f7`\3\2\2\2\u01f8\u01f9\7P\2\2\u01f9\u01fa\7W\2\2\u01fa"+ + "\u01fb\7N\2\2\u01fb\u01fc\7N\2\2\u01fcb\3\2\2\2\u01fd\u01fe\7P\2\2\u01fe"+ + "\u01ff\7W\2\2\u01ff\u0200\7N\2\2\u0200\u0201\7N\2\2\u0201\u0202\7U\2\2"+ + "\u0202d\3\2\2\2\u0203\u0204\7Q\2\2\u0204\u0205\7P\2\2\u0205f\3\2\2\2\u0206"+ + "\u0207\7Q\2\2\u0207\u0208\7R\2\2\u0208\u0209\7V\2\2\u0209\u020a\7K\2\2"+ + "\u020a\u020b\7O\2\2\u020b\u020c\7K\2\2\u020c\u020d\7\\\2\2\u020d\u020e"+ + "\7G\2\2\u020e\u020f\7F\2\2\u020fh\3\2\2\2\u0210\u0211\7Q\2\2\u0211\u0212"+ + "\7T\2\2\u0212j\3\2\2\2\u0213\u0214\7Q\2\2\u0214\u0215\7T\2\2\u0215\u0216"+ + "\7F\2\2\u0216\u0217\7G\2\2\u0217\u0218\7T\2\2\u0218l\3\2\2\2\u0219\u021a"+ + "\7Q\2\2\u021a\u021b\7W\2\2\u021b\u021c\7V\2\2\u021c\u021d\7G\2\2\u021d"+ + "\u021e\7T\2\2\u021en\3\2\2\2\u021f\u0220\7R\2\2\u0220\u0221\7C\2\2\u0221"+ + "\u0222\7T\2\2\u0222\u0223\7U\2\2\u0223\u0224\7G\2\2\u0224\u0225\7F\2\2"+ + "\u0225p\3\2\2\2\u0226\u0227\7R\2\2\u0227\u0228\7J\2\2\u0228\u0229\7[\2"+ + "\2\u0229\u022a\7U\2\2\u022a\u022b\7K\2\2\u022b\u022c\7E\2\2\u022c\u022d"+ + "\7C\2\2\u022d\u022e\7N\2\2\u022er\3\2\2\2\u022f\u0230\7R\2\2\u0230\u0231"+ + "\7N\2\2\u0231\u0232\7C\2\2\u0232\u0233\7P\2\2\u0233t\3\2\2\2\u0234\u0235"+ + "\7T\2\2\u0235\u0236\7K\2\2\u0236\u0237\7I\2\2\u0237\u0238\7J\2\2\u0238"+ + "\u0239\7V\2\2\u0239v\3\2\2\2\u023a\u023b\7T\2\2\u023b\u023c\7N\2\2\u023c"+ + "\u023d\7K\2\2\u023d\u023e\7M\2\2\u023e\u023f\7G\2\2\u023fx\3\2\2\2\u0240"+ + "\u0241\7S\2\2\u0241\u0242\7W\2\2\u0242\u0243\7G\2\2\u0243\u0244\7T\2\2"+ + "\u0244\u0245\7[\2\2\u0245z\3\2\2\2\u0246\u0247\7U\2\2\u0247\u0248\7E\2"+ + "\2\u0248\u0249\7J\2\2\u0249\u024a\7G\2\2\u024a\u024b\7O\2\2\u024b\u024c"+ + "\7C\2\2\u024c\u024d\7U\2\2\u024d|\3\2\2\2\u024e\u024f\7U\2\2\u024f\u0250"+ + "\7G\2\2\u0250\u0251\7N\2\2\u0251\u0252\7G\2\2\u0252\u0253\7E\2\2\u0253"+ + "\u0254\7V\2\2\u0254~\3\2\2\2\u0255\u0256\7U\2\2\u0256\u0257\7J\2\2\u0257"+ + "\u0258\7Q\2\2\u0258\u0259\7Y\2\2\u0259\u0080\3\2\2\2\u025a\u025b\7U\2"+ + "\2\u025b\u025c\7[\2\2\u025c\u025d\7U\2\2\u025d\u0082\3\2\2\2\u025e\u025f"+ + "\7V\2\2\u025f\u0260\7C\2\2\u0260\u0261\7D\2\2\u0261\u0262\7N\2\2\u0262"+ + "\u0263\7G\2\2\u0263\u0084\3\2\2\2\u0264\u0265\7V\2\2\u0265\u0266\7C\2"+ + "\2\u0266\u0267\7D\2\2\u0267\u0268\7N\2\2\u0268\u0269\7G\2\2\u0269\u026a"+ + "\7U\2\2\u026a\u0086\3\2\2\2\u026b\u026c\7V\2\2\u026c\u026d\7G\2\2\u026d"+ + "\u026e\7Z\2\2\u026e\u026f\7V\2\2\u026f\u0088\3\2\2\2\u0270\u0271\7V\2"+ + "\2\u0271\u0272\7T\2\2\u0272\u0273\7W\2\2\u0273\u0274\7G\2\2\u0274\u008a"+ + "\3\2\2\2\u0275\u0276\7V\2\2\u0276\u0277\7[\2\2\u0277\u0278\7R\2\2\u0278"+ + "\u0279\7G\2\2\u0279\u008c\3\2\2\2\u027a\u027b\7V\2\2\u027b\u027c\7[\2"+ + "\2\u027c\u027d\7R\2\2\u027d\u027e\7G\2\2\u027e\u027f\7U\2\2\u027f\u008e"+ + "\3\2\2\2\u0280\u0281\7W\2\2\u0281\u0282\7U\2\2\u0282\u0283\7K\2\2\u0283"+ + "\u0284\7P\2\2\u0284\u0285\7I\2\2\u0285\u0090\3\2\2\2\u0286\u0287\7X\2"+ + "\2\u0287\u0288\7G\2\2\u0288\u0289\7T\2\2\u0289\u028a\7K\2\2\u028a\u028b"+ + "\7H\2\2\u028b\u028c\7[\2\2\u028c\u0092\3\2\2\2\u028d\u028e\7Y\2\2\u028e"+ + "\u028f\7J\2\2\u028f\u0290\7G\2\2\u0290\u0291\7T\2\2\u0291\u0292\7G\2\2"+ + "\u0292\u0094\3\2\2\2\u0293\u0294\7Y\2\2\u0294\u0295\7K\2\2\u0295\u0296"+ + "\7V\2\2\u0296\u0297\7J\2\2\u0297\u0096\3\2\2\2\u0298\u0299\7}\2\2\u0299"+ + "\u029a\7G\2\2\u029a\u029b\7U\2\2\u029b\u029c\7E\2\2\u029c\u029d\7C\2\2"+ + "\u029d\u029e\7R\2\2\u029e\u029f\7G\2\2\u029f\u0098\3\2\2\2\u02a0\u02a1"+ + "\7}\2\2\u02a1\u02a2\7H\2\2\u02a2\u02a3\7P\2\2\u02a3\u009a\3\2\2\2\u02a4"+ + "\u02a5\7}\2\2\u02a5\u02a6\7N\2\2\u02a6\u02a7\7K\2\2\u02a7\u02a8\7O\2\2"+ + "\u02a8\u02a9\7K\2\2\u02a9\u02aa\7V\2\2\u02aa\u009c\3\2\2\2\u02ab\u02ac"+ + "\7}\2\2\u02ac\u02ad\7F\2\2\u02ad\u009e\3\2\2\2\u02ae\u02af\7}\2\2\u02af"+ + "\u02b0\7V\2\2\u02b0\u00a0\3\2\2\2\u02b1\u02b2\7}\2\2\u02b2\u02b3\7V\2"+ + "\2\u02b3\u02b4\7U\2\2\u02b4\u00a2\3\2\2\2\u02b5\u02b6\7}\2\2\u02b6\u02b7"+ + "\7I\2\2\u02b7\u02b8\7W\2\2\u02b8\u02b9\7K\2\2\u02b9\u02ba\7F\2\2\u02ba"+ + "\u00a4\3\2\2\2\u02bb\u02bc\7\177\2\2\u02bc\u00a6\3\2\2\2\u02bd\u02be\7"+ + "?\2\2\u02be\u00a8\3\2\2\2\u02bf\u02c0\7>\2\2\u02c0\u02c7\7@\2\2\u02c1"+ + "\u02c2\7#\2\2\u02c2\u02c7\7?\2\2\u02c3\u02c4\7>\2\2\u02c4\u02c5\7?\2\2"+ + "\u02c5\u02c7\7@\2\2\u02c6\u02bf\3\2\2\2\u02c6\u02c1\3\2\2\2\u02c6\u02c3"+ + "\3\2\2\2\u02c7\u00aa\3\2\2\2\u02c8\u02c9\7>\2\2\u02c9\u00ac\3\2\2\2\u02ca"+ + "\u02cb\7>\2\2\u02cb\u02cc\7?\2\2\u02cc\u00ae\3\2\2\2\u02cd\u02ce\7@\2"+ + "\2\u02ce\u00b0\3\2\2\2\u02cf\u02d0\7@\2\2\u02d0\u02d1\7?\2\2\u02d1\u00b2"+ + "\3\2\2\2\u02d2\u02d3\7-\2\2\u02d3\u00b4\3\2\2\2\u02d4\u02d5\7/\2\2\u02d5"+ + "\u00b6\3\2\2\2\u02d6\u02d7\7,\2\2\u02d7\u00b8\3\2\2\2\u02d8\u02d9\7\61"+ + "\2\2\u02d9\u00ba\3\2\2\2\u02da\u02db\7\'\2\2\u02db\u00bc\3\2\2\2\u02dc"+ + "\u02dd\7~\2\2\u02dd\u02de\7~\2\2\u02de\u00be\3\2\2\2\u02df\u02e0\7\60"+ + "\2\2\u02e0\u00c0\3\2\2\2\u02e1\u02e2\7A\2\2\u02e2\u00c2\3\2\2\2\u02e3"+ + "\u02e9\7)\2\2\u02e4\u02e8\n\2\2\2\u02e5\u02e6\7)\2\2\u02e6\u02e8\7)\2"+ + "\2\u02e7\u02e4\3\2\2\2\u02e7\u02e5\3\2\2\2\u02e8\u02eb\3\2\2\2\u02e9\u02e7"+ + "\3\2\2\2\u02e9\u02ea\3\2\2\2\u02ea\u02ec\3\2\2\2\u02eb\u02e9\3\2\2\2\u02ec"+ + "\u02ed\7)\2\2\u02ed\u00c4\3\2\2\2\u02ee\u02f0\5\u00d5k\2\u02ef\u02ee\3"+ + "\2\2\2\u02f0\u02f1\3\2\2\2\u02f1\u02ef\3\2\2\2\u02f1\u02f2\3\2\2\2\u02f2"+ + "\u00c6\3\2\2\2\u02f3\u02f5\5\u00d5k\2\u02f4\u02f3\3\2\2\2\u02f5\u02f6"+ + "\3\2\2\2\u02f6\u02f4\3\2\2\2\u02f6\u02f7\3\2\2\2\u02f7\u02f8\3\2\2\2\u02f8"+ + "\u02fc\5\u00bf`\2\u02f9\u02fb\5\u00d5k\2\u02fa\u02f9\3\2\2\2\u02fb\u02fe"+ + "\3\2\2\2\u02fc\u02fa\3\2\2\2\u02fc\u02fd\3\2\2\2\u02fd\u031e\3\2\2\2\u02fe"+ + "\u02fc\3\2\2\2\u02ff\u0301\5\u00bf`\2\u0300\u0302\5\u00d5k\2\u0301\u0300"+ + "\3\2\2\2\u0302\u0303\3\2\2\2\u0303\u0301\3\2\2\2\u0303\u0304\3\2\2\2\u0304"+ + "\u031e\3\2\2\2\u0305\u0307\5\u00d5k\2\u0306\u0305\3\2\2\2\u0307\u0308"+ + "\3\2\2\2\u0308\u0306\3\2\2\2\u0308\u0309\3\2\2\2\u0309\u0311\3\2\2\2\u030a"+ + "\u030e\5\u00bf`\2\u030b\u030d\5\u00d5k\2\u030c\u030b\3\2\2\2\u030d\u0310"+ + "\3\2\2\2\u030e\u030c\3\2\2\2\u030e\u030f\3\2\2\2\u030f\u0312\3\2\2\2\u0310"+ + "\u030e\3\2\2\2\u0311\u030a\3\2\2\2\u0311\u0312\3\2\2\2\u0312\u0313\3\2"+ + "\2\2\u0313\u0314\5\u00d3j\2\u0314\u031e\3\2\2\2\u0315\u0317\5\u00bf`\2"+ + "\u0316\u0318\5\u00d5k\2\u0317\u0316\3\2\2\2\u0318\u0319\3\2\2\2\u0319"+ + "\u0317\3\2\2\2\u0319\u031a\3\2\2\2\u031a\u031b\3\2\2\2\u031b\u031c\5\u00d3"+ + "j\2\u031c\u031e\3\2\2\2\u031d\u02f4\3\2\2\2\u031d\u02ff\3\2\2\2\u031d"+ + "\u0306\3\2\2\2\u031d\u0315\3\2\2\2\u031e\u00c8\3\2\2\2\u031f\u0322\5\u00d7"+ + "l\2\u0320\u0322\7a\2\2\u0321\u031f\3\2\2\2\u0321\u0320\3\2\2\2\u0322\u0328"+ + "\3\2\2\2\u0323\u0327\5\u00d7l\2\u0324\u0327\5\u00d5k\2\u0325\u0327\t\3"+ + "\2\2\u0326\u0323\3\2\2\2\u0326\u0324\3\2\2\2\u0326\u0325\3\2\2\2\u0327"+ + "\u032a\3\2\2\2\u0328\u0326\3\2\2\2\u0328\u0329\3\2\2\2\u0329\u00ca\3\2"+ + "\2\2\u032a\u0328\3\2\2\2\u032b\u032f\5\u00d5k\2\u032c\u0330\5\u00d7l\2"+ + "\u032d\u0330\5\u00d5k\2\u032e\u0330\t\4\2\2\u032f\u032c\3\2\2\2\u032f"+ + "\u032d\3\2\2\2\u032f\u032e\3\2\2\2\u0330\u0331\3\2\2\2\u0331\u032f\3\2"+ + "\2\2\u0331\u0332\3\2\2\2\u0332\u00cc\3\2\2\2\u0333\u0337\5\u00d7l\2\u0334"+ + "\u0337\5\u00d5k\2\u0335\u0337\7a\2\2\u0336\u0333\3\2\2\2\u0336\u0334\3"+ + "\2\2\2\u0336\u0335\3\2\2\2\u0337\u0338\3\2\2\2\u0338\u0336\3\2\2\2\u0338"+ + "\u0339\3\2\2\2\u0339\u00ce\3\2\2\2\u033a\u0340\7$\2\2\u033b\u033f\n\5"+ + "\2\2\u033c\u033d\7$\2\2\u033d\u033f\7$\2\2\u033e\u033b\3\2\2\2\u033e\u033c"+ + "\3\2\2\2\u033f\u0342\3\2\2\2\u0340\u033e\3\2\2\2\u0340\u0341\3\2\2\2\u0341"+ + "\u0343\3\2\2\2\u0342\u0340\3\2\2\2\u0343\u0344\7$\2\2\u0344\u00d0\3\2"+ + "\2\2\u0345\u034b\7b\2\2\u0346\u034a\n\6\2\2\u0347\u0348\7b\2\2\u0348\u034a"+ + "\7b\2\2\u0349\u0346\3\2\2\2\u0349\u0347\3\2\2\2\u034a\u034d\3\2\2\2\u034b"+ + "\u0349\3\2\2\2\u034b\u034c\3\2\2\2\u034c\u034e\3\2\2\2\u034d\u034b\3\2"+ + "\2\2\u034e\u034f\7b\2\2\u034f\u00d2\3\2\2\2\u0350\u0352\7G\2\2\u0351\u0353"+ + "\t\7\2\2\u0352\u0351\3\2\2\2\u0352\u0353\3\2\2\2\u0353\u0355\3\2\2\2\u0354"+ + "\u0356\5\u00d5k\2\u0355\u0354\3\2\2\2\u0356\u0357\3\2\2\2\u0357\u0355"+ + "\3\2\2\2\u0357\u0358\3\2\2\2\u0358\u00d4\3\2\2\2\u0359\u035a\t\b\2\2\u035a"+ + "\u00d6\3\2\2\2\u035b\u035c\t\t\2\2\u035c\u00d8\3\2\2\2\u035d\u035e\7/"+ + "\2\2\u035e\u035f\7/\2\2\u035f\u0363\3\2\2\2\u0360\u0362\n\n\2\2\u0361"+ + "\u0360\3\2\2\2\u0362\u0365\3\2\2\2\u0363\u0361\3\2\2\2\u0363\u0364\3\2"+ + "\2\2\u0364\u0367\3\2\2\2\u0365\u0363\3\2\2\2\u0366\u0368\7\17\2\2\u0367"+ + "\u0366\3\2\2\2\u0367\u0368\3\2\2\2\u0368\u036a\3\2\2\2\u0369\u036b\7\f"+ + "\2\2\u036a\u0369\3\2\2\2\u036a\u036b\3\2\2\2\u036b\u036c\3\2\2\2\u036c"+ + "\u036d\bm\2\2\u036d\u00da\3\2\2\2\u036e\u036f\7\61\2\2\u036f\u0370\7,"+ + "\2\2\u0370\u0375\3\2\2\2\u0371\u0374\5\u00dbn\2\u0372\u0374\13\2\2\2\u0373"+ + "\u0371\3\2\2\2\u0373\u0372\3\2\2\2\u0374\u0377\3\2\2\2\u0375\u0376\3\2"+ + "\2\2\u0375\u0373\3\2\2\2\u0376\u0378\3\2\2\2\u0377\u0375\3\2\2\2\u0378"+ + "\u0379\7,\2\2\u0379\u037a\7\61\2\2\u037a\u037b\3\2\2\2\u037b\u037c\bn"+ + "\2\2\u037c\u00dc\3\2\2\2\u037d\u037f\t\13\2\2\u037e\u037d\3\2\2\2\u037f"+ + "\u0380\3\2\2\2\u0380\u037e\3\2\2\2\u0380\u0381\3\2\2\2\u0381\u0382\3\2"+ + "\2\2\u0382\u0383\bo\2\2\u0383\u00de\3\2\2\2\u0384\u0385\13\2\2\2\u0385"+ + "\u00e0\3\2\2\2\"\2\u02c6\u02e7\u02e9\u02f1\u02f6\u02fc\u0303\u0308\u030e"+ + "\u0311\u0319\u031d\u0321\u0326\u0328\u032f\u0331\u0336\u0338\u033e\u0340"+ + "\u0349\u034b\u0352\u0357\u0363\u0367\u036a\u0373\u0375\u0380\3\2\3\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseParser.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseParser.java index 9e7848e8e6ef2..321cd058c08a6 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseParser.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlBaseParser.java @@ -20,19 +20,19 @@ class SqlBaseParser extends Parser { T__0=1, T__1=2, T__2=3, T__3=4, ALL=5, ANALYZE=6, ANALYZED=7, AND=8, ANY=9, AS=10, ASC=11, BETWEEN=12, BY=13, CAST=14, CATALOG=15, CATALOGS=16, COLUMNS=17, DEBUG=18, DESC=19, DESCRIBE=20, DISTINCT=21, ESCAPE=22, EXECUTABLE=23, - EXISTS=24, EXPLAIN=25, EXTRACT=26, FALSE=27, FORMAT=28, FROM=29, FULL=30, - FUNCTIONS=31, GRAPHVIZ=32, GROUP=33, HAVING=34, IN=35, INNER=36, IS=37, - JOIN=38, LEFT=39, LIKE=40, LIMIT=41, MAPPED=42, MATCH=43, NATURAL=44, - NOT=45, NULL=46, ON=47, OPTIMIZED=48, OR=49, ORDER=50, OUTER=51, PARSED=52, - PHYSICAL=53, PLAN=54, RIGHT=55, RLIKE=56, QUERY=57, SCHEMAS=58, SELECT=59, - SHOW=60, SYS=61, TABLE=62, TABLES=63, TEXT=64, TRUE=65, TYPE=66, TYPES=67, - USING=68, VERIFY=69, WHERE=70, WITH=71, ESCAPE_ESC=72, FUNCTION_ESC=73, - LIMIT_ESC=74, DATE_ESC=75, TIME_ESC=76, TIMESTAMP_ESC=77, GUID_ESC=78, - ESC_END=79, EQ=80, NEQ=81, LT=82, LTE=83, GT=84, GTE=85, PLUS=86, MINUS=87, - ASTERISK=88, SLASH=89, PERCENT=90, CONCAT=91, DOT=92, PARAM=93, STRING=94, - INTEGER_VALUE=95, DECIMAL_VALUE=96, IDENTIFIER=97, DIGIT_IDENTIFIER=98, - TABLE_IDENTIFIER=99, QUOTED_IDENTIFIER=100, BACKQUOTED_IDENTIFIER=101, - SIMPLE_COMMENT=102, BRACKETED_COMMENT=103, WS=104, UNRECOGNIZED=105, DELIMITER=106; + EXISTS=24, EXPLAIN=25, EXTRACT=26, FALSE=27, FIRST=28, FORMAT=29, FROM=30, + FULL=31, FUNCTIONS=32, GRAPHVIZ=33, GROUP=34, HAVING=35, IN=36, INNER=37, + IS=38, JOIN=39, LAST=40, LEFT=41, LIKE=42, LIMIT=43, MAPPED=44, MATCH=45, + NATURAL=46, NOT=47, NULL=48, NULLS=49, ON=50, OPTIMIZED=51, OR=52, ORDER=53, + OUTER=54, PARSED=55, PHYSICAL=56, PLAN=57, RIGHT=58, RLIKE=59, QUERY=60, + SCHEMAS=61, SELECT=62, SHOW=63, SYS=64, TABLE=65, TABLES=66, TEXT=67, + TRUE=68, TYPE=69, TYPES=70, USING=71, VERIFY=72, WHERE=73, WITH=74, ESCAPE_ESC=75, + FUNCTION_ESC=76, LIMIT_ESC=77, DATE_ESC=78, TIME_ESC=79, TIMESTAMP_ESC=80, + GUID_ESC=81, ESC_END=82, EQ=83, NEQ=84, LT=85, LTE=86, GT=87, GTE=88, + PLUS=89, MINUS=90, ASTERISK=91, SLASH=92, PERCENT=93, CONCAT=94, DOT=95, + PARAM=96, STRING=97, INTEGER_VALUE=98, DECIMAL_VALUE=99, IDENTIFIER=100, + DIGIT_IDENTIFIER=101, TABLE_IDENTIFIER=102, QUOTED_IDENTIFIER=103, BACKQUOTED_IDENTIFIER=104, + SIMPLE_COMMENT=105, BRACKETED_COMMENT=106, WS=107, UNRECOGNIZED=108, DELIMITER=109; public static final int RULE_singleStatement = 0, RULE_singleExpression = 1, RULE_statement = 2, RULE_query = 3, RULE_queryNoWith = 4, RULE_limitClause = 5, RULE_queryTerm = 6, @@ -68,32 +68,33 @@ class SqlBaseParser extends Parser { "'AND'", "'ANY'", "'AS'", "'ASC'", "'BETWEEN'", "'BY'", "'CAST'", "'CATALOG'", "'CATALOGS'", "'COLUMNS'", "'DEBUG'", "'DESC'", "'DESCRIBE'", "'DISTINCT'", "'ESCAPE'", "'EXECUTABLE'", "'EXISTS'", "'EXPLAIN'", "'EXTRACT'", "'FALSE'", - "'FORMAT'", "'FROM'", "'FULL'", "'FUNCTIONS'", "'GRAPHVIZ'", "'GROUP'", - "'HAVING'", "'IN'", "'INNER'", "'IS'", "'JOIN'", "'LEFT'", "'LIKE'", "'LIMIT'", - "'MAPPED'", "'MATCH'", "'NATURAL'", "'NOT'", "'NULL'", "'ON'", "'OPTIMIZED'", - "'OR'", "'ORDER'", "'OUTER'", "'PARSED'", "'PHYSICAL'", "'PLAN'", "'RIGHT'", - "'RLIKE'", "'QUERY'", "'SCHEMAS'", "'SELECT'", "'SHOW'", "'SYS'", "'TABLE'", - "'TABLES'", "'TEXT'", "'TRUE'", "'TYPE'", "'TYPES'", "'USING'", "'VERIFY'", - "'WHERE'", "'WITH'", "'{ESCAPE'", "'{FN'", "'{LIMIT'", "'{D'", "'{T'", - "'{TS'", "'{GUID'", "'}'", "'='", null, "'<'", "'<='", "'>'", "'>='", - "'+'", "'-'", "'*'", "'/'", "'%'", "'||'", "'.'", "'?'" + "'FIRST'", "'FORMAT'", "'FROM'", "'FULL'", "'FUNCTIONS'", "'GRAPHVIZ'", + "'GROUP'", "'HAVING'", "'IN'", "'INNER'", "'IS'", "'JOIN'", "'LAST'", + "'LEFT'", "'LIKE'", "'LIMIT'", "'MAPPED'", "'MATCH'", "'NATURAL'", "'NOT'", + "'NULL'", "'NULLS'", "'ON'", "'OPTIMIZED'", "'OR'", "'ORDER'", "'OUTER'", + "'PARSED'", "'PHYSICAL'", "'PLAN'", "'RIGHT'", "'RLIKE'", "'QUERY'", "'SCHEMAS'", + "'SELECT'", "'SHOW'", "'SYS'", "'TABLE'", "'TABLES'", "'TEXT'", "'TRUE'", + "'TYPE'", "'TYPES'", "'USING'", "'VERIFY'", "'WHERE'", "'WITH'", "'{ESCAPE'", + "'{FN'", "'{LIMIT'", "'{D'", "'{T'", "'{TS'", "'{GUID'", "'}'", "'='", + null, "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", "'%'", + "'||'", "'.'", "'?'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, "ALL", "ANALYZE", "ANALYZED", "AND", "ANY", "AS", "ASC", "BETWEEN", "BY", "CAST", "CATALOG", "CATALOGS", "COLUMNS", "DEBUG", "DESC", "DESCRIBE", "DISTINCT", "ESCAPE", "EXECUTABLE", "EXISTS", - "EXPLAIN", "EXTRACT", "FALSE", "FORMAT", "FROM", "FULL", "FUNCTIONS", - "GRAPHVIZ", "GROUP", "HAVING", "IN", "INNER", "IS", "JOIN", "LEFT", "LIKE", - "LIMIT", "MAPPED", "MATCH", "NATURAL", "NOT", "NULL", "ON", "OPTIMIZED", - "OR", "ORDER", "OUTER", "PARSED", "PHYSICAL", "PLAN", "RIGHT", "RLIKE", - "QUERY", "SCHEMAS", "SELECT", "SHOW", "SYS", "TABLE", "TABLES", "TEXT", - "TRUE", "TYPE", "TYPES", "USING", "VERIFY", "WHERE", "WITH", "ESCAPE_ESC", - "FUNCTION_ESC", "LIMIT_ESC", "DATE_ESC", "TIME_ESC", "TIMESTAMP_ESC", - "GUID_ESC", "ESC_END", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", - "MINUS", "ASTERISK", "SLASH", "PERCENT", "CONCAT", "DOT", "PARAM", "STRING", - "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "DIGIT_IDENTIFIER", "TABLE_IDENTIFIER", - "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "SIMPLE_COMMENT", "BRACKETED_COMMENT", - "WS", "UNRECOGNIZED", "DELIMITER" + "EXPLAIN", "EXTRACT", "FALSE", "FIRST", "FORMAT", "FROM", "FULL", "FUNCTIONS", + "GRAPHVIZ", "GROUP", "HAVING", "IN", "INNER", "IS", "JOIN", "LAST", "LEFT", + "LIKE", "LIMIT", "MAPPED", "MATCH", "NATURAL", "NOT", "NULL", "NULLS", + "ON", "OPTIMIZED", "OR", "ORDER", "OUTER", "PARSED", "PHYSICAL", "PLAN", + "RIGHT", "RLIKE", "QUERY", "SCHEMAS", "SELECT", "SHOW", "SYS", "TABLE", + "TABLES", "TEXT", "TRUE", "TYPE", "TYPES", "USING", "VERIFY", "WHERE", + "WITH", "ESCAPE_ESC", "FUNCTION_ESC", "LIMIT_ESC", "DATE_ESC", "TIME_ESC", + "TIMESTAMP_ESC", "GUID_ESC", "ESC_END", "EQ", "NEQ", "LT", "LTE", "GT", + "GTE", "PLUS", "MINUS", "ASTERISK", "SLASH", "PERCENT", "CONCAT", "DOT", + "PARAM", "STRING", "INTEGER_VALUE", "DECIMAL_VALUE", "IDENTIFIER", "DIGIT_IDENTIFIER", + "TABLE_IDENTIFIER", "QUOTED_IDENTIFIER", "BACKQUOTED_IDENTIFIER", "SIMPLE_COMMENT", + "BRACKETED_COMMENT", "WS", "UNRECOGNIZED", "DELIMITER" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -644,7 +645,7 @@ public final StatementContext statement() throws RecognitionException { setState(117); _errHandler.sync(this); _la = _input.LA(1); - while (((((_la - 28)) & ~0x3f) == 0 && ((1L << (_la - 28)) & ((1L << (FORMAT - 28)) | (1L << (PLAN - 28)) | (1L << (VERIFY - 28)))) != 0)) { + while (((((_la - 29)) & ~0x3f) == 0 && ((1L << (_la - 29)) & ((1L << (FORMAT - 29)) | (1L << (PLAN - 29)) | (1L << (VERIFY - 29)))) != 0)) { { setState(115); switch (_input.LA(1)) { @@ -1511,11 +1512,15 @@ public final QueryTermContext queryTerm() throws RecognitionException { public static class OrderByContext extends ParserRuleContext { public Token ordering; + public Token nullOrdering; public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } + public TerminalNode NULLS() { return getToken(SqlBaseParser.NULLS, 0); } public TerminalNode ASC() { return getToken(SqlBaseParser.ASC, 0); } public TerminalNode DESC() { return getToken(SqlBaseParser.DESC, 0); } + public TerminalNode FIRST() { return getToken(SqlBaseParser.FIRST, 0); } + public TerminalNode LAST() { return getToken(SqlBaseParser.LAST, 0); } public OrderByContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -1559,6 +1564,23 @@ public final OrderByContext orderBy() throws RecognitionException { } } + setState(257); + _la = _input.LA(1); + if (_la==NULLS) { + { + setState(255); + match(NULLS); + setState(256); + ((OrderByContext)_localctx).nullOrdering = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==FIRST || _la==LAST) ) { + ((OrderByContext)_localctx).nullOrdering = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + } + } } catch (RecognitionException re) { @@ -1627,75 +1649,75 @@ public final QuerySpecificationContext querySpecification() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(255); + setState(259); match(SELECT); - setState(257); + setState(261); _la = _input.LA(1); if (_la==ALL || _la==DISTINCT) { { - setState(256); + setState(260); setQuantifier(); } } - setState(259); + setState(263); selectItem(); - setState(264); + setState(268); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(260); + setState(264); match(T__2); - setState(261); + setState(265); selectItem(); } } - setState(266); + setState(270); _errHandler.sync(this); _la = _input.LA(1); } - setState(268); + setState(272); _la = _input.LA(1); if (_la==FROM) { { - setState(267); + setState(271); fromClause(); } } - setState(272); + setState(276); _la = _input.LA(1); if (_la==WHERE) { { - setState(270); + setState(274); match(WHERE); - setState(271); + setState(275); ((QuerySpecificationContext)_localctx).where = booleanExpression(0); } } - setState(277); + setState(281); _la = _input.LA(1); if (_la==GROUP) { { - setState(274); + setState(278); match(GROUP); - setState(275); + setState(279); match(BY); - setState(276); + setState(280); groupBy(); } } - setState(281); + setState(285); _la = _input.LA(1); if (_la==HAVING) { { - setState(279); + setState(283); match(HAVING); - setState(280); + setState(284); ((QuerySpecificationContext)_localctx).having = booleanExpression(0); } } @@ -1747,23 +1769,23 @@ public final FromClauseContext fromClause() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(283); + setState(287); match(FROM); - setState(284); + setState(288); relation(); - setState(289); + setState(293); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(285); + setState(289); match(T__2); - setState(286); + setState(290); relation(); } } - setState(291); + setState(295); _errHandler.sync(this); _la = _input.LA(1); } @@ -1816,30 +1838,30 @@ public final GroupByContext groupBy() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(293); + setState(297); _la = _input.LA(1); if (_la==ALL || _la==DISTINCT) { { - setState(292); + setState(296); setQuantifier(); } } - setState(295); + setState(299); groupingElement(); - setState(300); + setState(304); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(296); + setState(300); match(T__2); - setState(297); + setState(301); groupingElement(); } } - setState(302); + setState(306); _errHandler.sync(this); _la = _input.LA(1); } @@ -1894,7 +1916,7 @@ public final GroupingElementContext groupingElement() throws RecognitionExceptio _localctx = new SingleGroupingSetContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(303); + setState(307); groupingExpressions(); } } @@ -1940,47 +1962,47 @@ public final GroupingExpressionsContext groupingExpressions() throws Recognition enterRule(_localctx, 24, RULE_groupingExpressions); int _la; try { - setState(318); + setState(322); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,37,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,38,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(305); + setState(309); match(T__0); - setState(314); + setState(318); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << ANALYZE) | (1L << ANALYZED) | (1L << CAST) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXISTS) | (1L << EXPLAIN) | (1L << EXTRACT) | (1L << FALSE) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << LEFT) | (1L << MAPPED) | (1L << MATCH) | (1L << NOT) | (1L << NULL) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RIGHT) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW) | (1L << SYS) | (1L << TABLES))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (TEXT - 64)) | (1L << (TRUE - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (FUNCTION_ESC - 64)) | (1L << (DATE_ESC - 64)) | (1L << (TIME_ESC - 64)) | (1L << (TIMESTAMP_ESC - 64)) | (1L << (GUID_ESC - 64)) | (1L << (PLUS - 64)) | (1L << (MINUS - 64)) | (1L << (ASTERISK - 64)) | (1L << (PARAM - 64)) | (1L << (STRING - 64)) | (1L << (INTEGER_VALUE - 64)) | (1L << (DECIMAL_VALUE - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << ANALYZE) | (1L << ANALYZED) | (1L << CAST) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXISTS) | (1L << EXPLAIN) | (1L << EXTRACT) | (1L << FALSE) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << LEFT) | (1L << MAPPED) | (1L << MATCH) | (1L << NOT) | (1L << NULL) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RIGHT) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (SYS - 64)) | (1L << (TABLES - 64)) | (1L << (TEXT - 64)) | (1L << (TRUE - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (FUNCTION_ESC - 64)) | (1L << (DATE_ESC - 64)) | (1L << (TIME_ESC - 64)) | (1L << (TIMESTAMP_ESC - 64)) | (1L << (GUID_ESC - 64)) | (1L << (PLUS - 64)) | (1L << (MINUS - 64)) | (1L << (ASTERISK - 64)) | (1L << (PARAM - 64)) | (1L << (STRING - 64)) | (1L << (INTEGER_VALUE - 64)) | (1L << (DECIMAL_VALUE - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { { - setState(306); + setState(310); expression(); - setState(311); + setState(315); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(307); + setState(311); match(T__2); - setState(308); + setState(312); expression(); } } - setState(313); + setState(317); _errHandler.sync(this); _la = _input.LA(1); } } } - setState(316); + setState(320); match(T__1); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(317); + setState(321); expression(); } break; @@ -2031,15 +2053,15 @@ public final NamedQueryContext namedQuery() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(320); + setState(324); ((NamedQueryContext)_localctx).name = identifier(); - setState(321); + setState(325); match(AS); - setState(322); + setState(326); match(T__0); - setState(323); + setState(327); queryNoWith(); - setState(324); + setState(328); match(T__1); } } @@ -2083,7 +2105,7 @@ public final SetQuantifierContext setQuantifier() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(326); + setState(330); _la = _input.LA(1); if ( !(_la==ALL || _la==DISTINCT) ) { _errHandler.recoverInline(this); @@ -2146,22 +2168,22 @@ public final SelectItemContext selectItem() throws RecognitionException { _localctx = new SelectExpressionContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(328); + setState(332); expression(); - setState(333); + setState(337); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << AS) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW) | (1L << SYS) | (1L << TABLES))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << AS) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (SYS - 64)) | (1L << (TABLES - 64)) | (1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { { - setState(330); + setState(334); _la = _input.LA(1); if (_la==AS) { { - setState(329); + setState(333); match(AS); } } - setState(332); + setState(336); identifier(); } } @@ -2215,19 +2237,19 @@ public final RelationContext relation() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(335); - relationPrimary(); setState(339); + relationPrimary(); + setState(343); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << FULL) | (1L << INNER) | (1L << JOIN) | (1L << LEFT) | (1L << NATURAL) | (1L << RIGHT))) != 0)) { { { - setState(336); + setState(340); joinRelation(); } } - setState(341); + setState(345); _errHandler.sync(this); _la = _input.LA(1); } @@ -2281,7 +2303,7 @@ public final JoinRelationContext joinRelation() throws RecognitionException { enterRule(_localctx, 34, RULE_joinRelation); int _la; try { - setState(353); + setState(357); switch (_input.LA(1)) { case FULL: case INNER: @@ -2291,18 +2313,18 @@ public final JoinRelationContext joinRelation() throws RecognitionException { enterOuterAlt(_localctx, 1); { { - setState(342); + setState(346); joinType(); } - setState(343); + setState(347); match(JOIN); - setState(344); + setState(348); ((JoinRelationContext)_localctx).right = relationPrimary(); - setState(346); + setState(350); _la = _input.LA(1); if (_la==ON || _la==USING) { { - setState(345); + setState(349); joinCriteria(); } } @@ -2312,13 +2334,13 @@ public final JoinRelationContext joinRelation() throws RecognitionException { case NATURAL: enterOuterAlt(_localctx, 2); { - setState(348); + setState(352); match(NATURAL); - setState(349); + setState(353); joinType(); - setState(350); + setState(354); match(JOIN); - setState(351); + setState(355); ((JoinRelationContext)_localctx).right = relationPrimary(); } break; @@ -2367,17 +2389,17 @@ public final JoinTypeContext joinType() throws RecognitionException { enterRule(_localctx, 36, RULE_joinType); int _la; try { - setState(370); + setState(374); switch (_input.LA(1)) { case INNER: case JOIN: enterOuterAlt(_localctx, 1); { - setState(356); + setState(360); _la = _input.LA(1); if (_la==INNER) { { - setState(355); + setState(359); match(INNER); } } @@ -2387,13 +2409,13 @@ public final JoinTypeContext joinType() throws RecognitionException { case LEFT: enterOuterAlt(_localctx, 2); { - setState(358); + setState(362); match(LEFT); - setState(360); + setState(364); _la = _input.LA(1); if (_la==OUTER) { { - setState(359); + setState(363); match(OUTER); } } @@ -2403,13 +2425,13 @@ public final JoinTypeContext joinType() throws RecognitionException { case RIGHT: enterOuterAlt(_localctx, 3); { - setState(362); + setState(366); match(RIGHT); - setState(364); + setState(368); _la = _input.LA(1); if (_la==OUTER) { { - setState(363); + setState(367); match(OUTER); } } @@ -2419,13 +2441,13 @@ public final JoinTypeContext joinType() throws RecognitionException { case FULL: enterOuterAlt(_localctx, 4); { - setState(366); + setState(370); match(FULL); - setState(368); + setState(372); _la = _input.LA(1); if (_la==OUTER) { { - setState(367); + setState(371); match(OUTER); } } @@ -2483,43 +2505,43 @@ public final JoinCriteriaContext joinCriteria() throws RecognitionException { enterRule(_localctx, 38, RULE_joinCriteria); int _la; try { - setState(386); + setState(390); switch (_input.LA(1)) { case ON: enterOuterAlt(_localctx, 1); { - setState(372); + setState(376); match(ON); - setState(373); + setState(377); booleanExpression(0); } break; case USING: enterOuterAlt(_localctx, 2); { - setState(374); + setState(378); match(USING); - setState(375); + setState(379); match(T__0); - setState(376); + setState(380); identifier(); - setState(381); + setState(385); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(377); + setState(381); match(T__2); - setState(378); + setState(382); identifier(); } } - setState(383); + setState(387); _errHandler.sync(this); _la = _input.LA(1); } - setState(384); + setState(388); match(T__1); } break; @@ -2624,29 +2646,29 @@ public final RelationPrimaryContext relationPrimary() throws RecognitionExceptio enterRule(_localctx, 40, RULE_relationPrimary); int _la; try { - setState(413); + setState(417); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,56,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,57,_ctx) ) { case 1: _localctx = new TableNameContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(388); + setState(392); tableIdentifier(); - setState(393); + setState(397); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << AS) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW) | (1L << SYS) | (1L << TABLES))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << AS) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (SYS - 64)) | (1L << (TABLES - 64)) | (1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { { - setState(390); + setState(394); _la = _input.LA(1); if (_la==AS) { { - setState(389); + setState(393); match(AS); } } - setState(392); + setState(396); qualifiedName(); } } @@ -2657,26 +2679,26 @@ public final RelationPrimaryContext relationPrimary() throws RecognitionExceptio _localctx = new AliasedQueryContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(395); + setState(399); match(T__0); - setState(396); + setState(400); queryNoWith(); - setState(397); + setState(401); match(T__1); - setState(402); + setState(406); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << AS) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW) | (1L << SYS) | (1L << TABLES))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << AS) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (SYS - 64)) | (1L << (TABLES - 64)) | (1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { { - setState(399); + setState(403); _la = _input.LA(1); if (_la==AS) { { - setState(398); + setState(402); match(AS); } } - setState(401); + setState(405); qualifiedName(); } } @@ -2687,26 +2709,26 @@ public final RelationPrimaryContext relationPrimary() throws RecognitionExceptio _localctx = new AliasedRelationContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(404); + setState(408); match(T__0); - setState(405); + setState(409); relation(); - setState(406); + setState(410); match(T__1); - setState(411); + setState(415); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << AS) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW) | (1L << SYS) | (1L << TABLES))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << AS) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (SYS - 64)) | (1L << (TABLES - 64)) | (1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { { - setState(408); + setState(412); _la = _input.LA(1); if (_la==AS) { { - setState(407); + setState(411); match(AS); } } - setState(410); + setState(414); qualifiedName(); } } @@ -2755,7 +2777,7 @@ public final ExpressionContext expression() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(415); + setState(419); booleanExpression(0); } } @@ -2963,18 +2985,18 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc int _alt; enterOuterAlt(_localctx, 1); { - setState(448); + setState(452); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,57,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,58,_ctx) ) { case 1: { _localctx = new LogicalNotContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(418); + setState(422); match(NOT); - setState(419); + setState(423); booleanExpression(8); } break; @@ -2983,13 +3005,13 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new ExistsContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(420); + setState(424); match(EXISTS); - setState(421); + setState(425); match(T__0); - setState(422); + setState(426); query(); - setState(423); + setState(427); match(T__1); } break; @@ -2998,15 +3020,15 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new StringQueryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(425); + setState(429); match(QUERY); - setState(426); + setState(430); match(T__0); - setState(427); + setState(431); ((StringQueryContext)_localctx).queryString = string(); - setState(428); + setState(432); matchQueryOptions(); - setState(429); + setState(433); match(T__1); } break; @@ -3015,19 +3037,19 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new MatchQueryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(431); + setState(435); match(MATCH); - setState(432); + setState(436); match(T__0); - setState(433); + setState(437); ((MatchQueryContext)_localctx).singleField = qualifiedName(); - setState(434); + setState(438); match(T__2); - setState(435); + setState(439); ((MatchQueryContext)_localctx).queryString = string(); - setState(436); + setState(440); matchQueryOptions(); - setState(437); + setState(441); match(T__1); } break; @@ -3036,19 +3058,19 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new MultiMatchQueryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(439); + setState(443); match(MATCH); - setState(440); + setState(444); match(T__0); - setState(441); + setState(445); ((MultiMatchQueryContext)_localctx).multiFields = string(); - setState(442); + setState(446); match(T__2); - setState(443); + setState(447); ((MultiMatchQueryContext)_localctx).queryString = string(); - setState(444); + setState(448); matchQueryOptions(); - setState(445); + setState(449); match(T__1); } break; @@ -3057,33 +3079,33 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new BooleanDefaultContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(447); + setState(451); predicated(); } break; } _ctx.stop = _input.LT(-1); - setState(458); + setState(462); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,59,_ctx); + _alt = getInterpreter().adaptivePredict(_input,60,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(456); + setState(460); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,58,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,59,_ctx) ) { case 1: { _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(450); + setState(454); if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(451); + setState(455); ((LogicalBinaryContext)_localctx).operator = match(AND); - setState(452); + setState(456); ((LogicalBinaryContext)_localctx).right = booleanExpression(3); } break; @@ -3092,20 +3114,20 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); ((LogicalBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_booleanExpression); - setState(453); + setState(457); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(454); + setState(458); ((LogicalBinaryContext)_localctx).operator = match(OR); - setState(455); + setState(459); ((LogicalBinaryContext)_localctx).right = booleanExpression(2); } break; } } } - setState(460); + setState(464); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,59,_ctx); + _alt = getInterpreter().adaptivePredict(_input,60,_ctx); } } } @@ -3153,19 +3175,19 @@ public final MatchQueryOptionsContext matchQueryOptions() throws RecognitionExce try { enterOuterAlt(_localctx, 1); { - setState(465); + setState(469); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(461); + setState(465); match(T__2); - setState(462); + setState(466); string(); } } - setState(467); + setState(471); _errHandler.sync(this); _la = _input.LA(1); } @@ -3214,14 +3236,14 @@ public final PredicatedContext predicated() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(468); + setState(472); valueExpression(0); - setState(470); + setState(474); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,61,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,62,_ctx) ) { case 1: { - setState(469); + setState(473); predicate(); } break; @@ -3297,142 +3319,142 @@ public final PredicateContext predicate() throws RecognitionException { enterRule(_localctx, 50, RULE_predicate); int _la; try { - setState(518); + setState(522); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,69,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,70,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(473); + setState(477); _la = _input.LA(1); if (_la==NOT) { { - setState(472); + setState(476); match(NOT); } } - setState(475); + setState(479); ((PredicateContext)_localctx).kind = match(BETWEEN); - setState(476); + setState(480); ((PredicateContext)_localctx).lower = valueExpression(0); - setState(477); + setState(481); match(AND); - setState(478); + setState(482); ((PredicateContext)_localctx).upper = valueExpression(0); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(481); + setState(485); _la = _input.LA(1); if (_la==NOT) { { - setState(480); + setState(484); match(NOT); } } - setState(483); + setState(487); ((PredicateContext)_localctx).kind = match(IN); - setState(484); + setState(488); match(T__0); - setState(485); + setState(489); expression(); - setState(490); + setState(494); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(486); + setState(490); match(T__2); - setState(487); + setState(491); expression(); } } - setState(492); + setState(496); _errHandler.sync(this); _la = _input.LA(1); } - setState(493); + setState(497); match(T__1); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(496); + setState(500); _la = _input.LA(1); if (_la==NOT) { { - setState(495); + setState(499); match(NOT); } } - setState(498); + setState(502); ((PredicateContext)_localctx).kind = match(IN); - setState(499); + setState(503); match(T__0); - setState(500); + setState(504); query(); - setState(501); + setState(505); match(T__1); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(504); + setState(508); _la = _input.LA(1); if (_la==NOT) { { - setState(503); + setState(507); match(NOT); } } - setState(506); + setState(510); ((PredicateContext)_localctx).kind = match(LIKE); - setState(507); + setState(511); pattern(); } break; case 5: enterOuterAlt(_localctx, 5); { - setState(509); + setState(513); _la = _input.LA(1); if (_la==NOT) { { - setState(508); + setState(512); match(NOT); } } - setState(511); + setState(515); ((PredicateContext)_localctx).kind = match(RLIKE); - setState(512); + setState(516); ((PredicateContext)_localctx).regex = string(); } break; case 6: enterOuterAlt(_localctx, 6); { - setState(513); + setState(517); match(IS); - setState(515); + setState(519); _la = _input.LA(1); if (_la==NOT) { { - setState(514); + setState(518); match(NOT); } } - setState(517); + setState(521); ((PredicateContext)_localctx).kind = match(NULL); } break; @@ -3479,9 +3501,9 @@ public final LikePatternContext likePattern() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(520); + setState(524); match(LIKE); - setState(521); + setState(525); pattern(); } } @@ -3529,14 +3551,14 @@ public final PatternContext pattern() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(523); + setState(527); ((PatternContext)_localctx).value = string(); - setState(525); + setState(529); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,70,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,71,_ctx) ) { case 1: { - setState(524); + setState(528); patternEscape(); } break; @@ -3584,25 +3606,25 @@ public final PatternEscapeContext patternEscape() throws RecognitionException { PatternEscapeContext _localctx = new PatternEscapeContext(_ctx, getState()); enterRule(_localctx, 56, RULE_patternEscape); try { - setState(533); + setState(537); switch (_input.LA(1)) { case ESCAPE: enterOuterAlt(_localctx, 1); { - setState(527); + setState(531); match(ESCAPE); - setState(528); + setState(532); ((PatternEscapeContext)_localctx).escape = string(); } break; case ESCAPE_ESC: enterOuterAlt(_localctx, 2); { - setState(529); + setState(533); match(ESCAPE_ESC); - setState(530); + setState(534); ((PatternEscapeContext)_localctx).escape = string(); - setState(531); + setState(535); match(ESC_END); } break; @@ -3747,7 +3769,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti int _alt; enterOuterAlt(_localctx, 1); { - setState(539); + setState(543); switch (_input.LA(1)) { case T__0: case ANALYZE: @@ -3801,7 +3823,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _ctx = _localctx; _prevctx = _localctx; - setState(536); + setState(540); primaryExpression(); } break; @@ -3811,7 +3833,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _localctx = new ArithmeticUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(537); + setState(541); ((ArithmeticUnaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -3819,7 +3841,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti } else { consume(); } - setState(538); + setState(542); valueExpression(4); } break; @@ -3827,33 +3849,33 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(553); + setState(557); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,74,_ctx); + _alt = getInterpreter().adaptivePredict(_input,75,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(551); + setState(555); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,73,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,74,_ctx) ) { case 1: { _localctx = new ArithmeticBinaryContext(new ValueExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_valueExpression); - setState(541); + setState(545); if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); - setState(542); + setState(546); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); - if ( !(((((_la - 88)) & ~0x3f) == 0 && ((1L << (_la - 88)) & ((1L << (ASTERISK - 88)) | (1L << (SLASH - 88)) | (1L << (PERCENT - 88)))) != 0)) ) { + if ( !(((((_la - 91)) & ~0x3f) == 0 && ((1L << (_la - 91)) & ((1L << (ASTERISK - 91)) | (1L << (SLASH - 91)) | (1L << (PERCENT - 91)))) != 0)) ) { ((ArithmeticBinaryContext)_localctx).operator = (Token)_errHandler.recoverInline(this); } else { consume(); } - setState(543); + setState(547); ((ArithmeticBinaryContext)_localctx).right = valueExpression(4); } break; @@ -3862,9 +3884,9 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _localctx = new ArithmeticBinaryContext(new ValueExpressionContext(_parentctx, _parentState)); ((ArithmeticBinaryContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_valueExpression); - setState(544); + setState(548); if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); - setState(545); + setState(549); ((ArithmeticBinaryContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==PLUS || _la==MINUS) ) { @@ -3872,7 +3894,7 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti } else { consume(); } - setState(546); + setState(550); ((ArithmeticBinaryContext)_localctx).right = valueExpression(3); } break; @@ -3881,20 +3903,20 @@ private ValueExpressionContext valueExpression(int _p) throws RecognitionExcepti _localctx = new ComparisonContext(new ValueExpressionContext(_parentctx, _parentState)); ((ComparisonContext)_localctx).left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_valueExpression); - setState(547); + setState(551); if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); - setState(548); + setState(552); comparisonOperator(); - setState(549); + setState(553); ((ComparisonContext)_localctx).right = valueExpression(2); } break; } } } - setState(555); + setState(559); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,74,_ctx); + _alt = getInterpreter().adaptivePredict(_input,75,_ctx); } } } @@ -4080,14 +4102,14 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce enterRule(_localctx, 60, RULE_primaryExpression); int _la; try { - setState(575); + setState(579); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,76,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,77,_ctx) ) { case 1: _localctx = new CastContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(556); + setState(560); castExpression(); } break; @@ -4095,7 +4117,7 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new ExtractContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(557); + setState(561); extractExpression(); } break; @@ -4103,7 +4125,7 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new ConstantDefaultContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(558); + setState(562); constant(); } break; @@ -4111,18 +4133,18 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new StarContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(562); + setState(566); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW) | (1L << SYS) | (1L << TABLES))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (SYS - 64)) | (1L << (TABLES - 64)) | (1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { { - setState(559); + setState(563); qualifiedName(); - setState(560); + setState(564); match(DOT); } } - setState(564); + setState(568); match(ASTERISK); } break; @@ -4130,7 +4152,7 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new FunctionContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(565); + setState(569); functionExpression(); } break; @@ -4138,11 +4160,11 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new SubqueryExpressionContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(566); + setState(570); match(T__0); - setState(567); + setState(571); query(); - setState(568); + setState(572); match(T__1); } break; @@ -4150,7 +4172,7 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new DereferenceContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(570); + setState(574); qualifiedName(); } break; @@ -4158,11 +4180,11 @@ public final PrimaryExpressionContext primaryExpression() throws RecognitionExce _localctx = new ParenthesizedExpressionContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(571); + setState(575); match(T__0); - setState(572); + setState(576); expression(); - setState(573); + setState(577); match(T__1); } break; @@ -4208,23 +4230,23 @@ public final CastExpressionContext castExpression() throws RecognitionException CastExpressionContext _localctx = new CastExpressionContext(_ctx, getState()); enterRule(_localctx, 62, RULE_castExpression); try { - setState(582); + setState(586); switch (_input.LA(1)) { case CAST: enterOuterAlt(_localctx, 1); { - setState(577); + setState(581); castTemplate(); } break; case FUNCTION_ESC: enterOuterAlt(_localctx, 2); { - setState(578); + setState(582); match(FUNCTION_ESC); - setState(579); + setState(583); castTemplate(); - setState(580); + setState(584); match(ESC_END); } break; @@ -4277,17 +4299,17 @@ public final CastTemplateContext castTemplate() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(584); + setState(588); match(CAST); - setState(585); + setState(589); match(T__0); - setState(586); + setState(590); expression(); - setState(587); + setState(591); match(AS); - setState(588); + setState(592); dataType(); - setState(589); + setState(593); match(T__1); } } @@ -4331,23 +4353,23 @@ public final ExtractExpressionContext extractExpression() throws RecognitionExce ExtractExpressionContext _localctx = new ExtractExpressionContext(_ctx, getState()); enterRule(_localctx, 66, RULE_extractExpression); try { - setState(596); + setState(600); switch (_input.LA(1)) { case EXTRACT: enterOuterAlt(_localctx, 1); { - setState(591); + setState(595); extractTemplate(); } break; case FUNCTION_ESC: enterOuterAlt(_localctx, 2); { - setState(592); + setState(596); match(FUNCTION_ESC); - setState(593); + setState(597); extractTemplate(); - setState(594); + setState(598); match(ESC_END); } break; @@ -4401,17 +4423,17 @@ public final ExtractTemplateContext extractTemplate() throws RecognitionExceptio try { enterOuterAlt(_localctx, 1); { - setState(598); + setState(602); match(EXTRACT); - setState(599); + setState(603); match(T__0); - setState(600); + setState(604); ((ExtractTemplateContext)_localctx).field = identifier(); - setState(601); + setState(605); match(FROM); - setState(602); + setState(606); valueExpression(0); - setState(603); + setState(607); match(T__1); } } @@ -4454,7 +4476,7 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx FunctionExpressionContext _localctx = new FunctionExpressionContext(_ctx, getState()); enterRule(_localctx, 70, RULE_functionExpression); try { - setState(610); + setState(614); switch (_input.LA(1)) { case ANALYZE: case ANALYZED: @@ -4489,18 +4511,18 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx case BACKQUOTED_IDENTIFIER: enterOuterAlt(_localctx, 1); { - setState(605); + setState(609); functionTemplate(); } break; case FUNCTION_ESC: enterOuterAlt(_localctx, 2); { - setState(606); + setState(610); match(FUNCTION_ESC); - setState(607); + setState(611); functionTemplate(); - setState(608); + setState(612); match(ESC_END); } break; @@ -4558,45 +4580,45 @@ public final FunctionTemplateContext functionTemplate() throws RecognitionExcept try { enterOuterAlt(_localctx, 1); { - setState(612); + setState(616); functionName(); - setState(613); + setState(617); match(T__0); - setState(625); + setState(629); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << ALL) | (1L << ANALYZE) | (1L << ANALYZED) | (1L << CAST) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << DISTINCT) | (1L << EXECUTABLE) | (1L << EXISTS) | (1L << EXPLAIN) | (1L << EXTRACT) | (1L << FALSE) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << LEFT) | (1L << MAPPED) | (1L << MATCH) | (1L << NOT) | (1L << NULL) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RIGHT) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW) | (1L << SYS) | (1L << TABLES))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (TEXT - 64)) | (1L << (TRUE - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (FUNCTION_ESC - 64)) | (1L << (DATE_ESC - 64)) | (1L << (TIME_ESC - 64)) | (1L << (TIMESTAMP_ESC - 64)) | (1L << (GUID_ESC - 64)) | (1L << (PLUS - 64)) | (1L << (MINUS - 64)) | (1L << (ASTERISK - 64)) | (1L << (PARAM - 64)) | (1L << (STRING - 64)) | (1L << (INTEGER_VALUE - 64)) | (1L << (DECIMAL_VALUE - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << ALL) | (1L << ANALYZE) | (1L << ANALYZED) | (1L << CAST) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << DISTINCT) | (1L << EXECUTABLE) | (1L << EXISTS) | (1L << EXPLAIN) | (1L << EXTRACT) | (1L << FALSE) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << LEFT) | (1L << MAPPED) | (1L << MATCH) | (1L << NOT) | (1L << NULL) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RIGHT) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (SYS - 64)) | (1L << (TABLES - 64)) | (1L << (TEXT - 64)) | (1L << (TRUE - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (FUNCTION_ESC - 64)) | (1L << (DATE_ESC - 64)) | (1L << (TIME_ESC - 64)) | (1L << (TIMESTAMP_ESC - 64)) | (1L << (GUID_ESC - 64)) | (1L << (PLUS - 64)) | (1L << (MINUS - 64)) | (1L << (ASTERISK - 64)) | (1L << (PARAM - 64)) | (1L << (STRING - 64)) | (1L << (INTEGER_VALUE - 64)) | (1L << (DECIMAL_VALUE - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { { - setState(615); + setState(619); _la = _input.LA(1); if (_la==ALL || _la==DISTINCT) { { - setState(614); + setState(618); setQuantifier(); } } - setState(617); + setState(621); expression(); - setState(622); + setState(626); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__2) { { { - setState(618); + setState(622); match(T__2); - setState(619); + setState(623); expression(); } } - setState(624); + setState(628); _errHandler.sync(this); _la = _input.LA(1); } } } - setState(627); + setState(631); match(T__1); } } @@ -4640,19 +4662,19 @@ public final FunctionNameContext functionName() throws RecognitionException { FunctionNameContext _localctx = new FunctionNameContext(_ctx, getState()); enterRule(_localctx, 74, RULE_functionName); try { - setState(632); + setState(636); switch (_input.LA(1)) { case LEFT: enterOuterAlt(_localctx, 1); { - setState(629); + setState(633); match(LEFT); } break; case RIGHT: enterOuterAlt(_localctx, 2); { - setState(630); + setState(634); match(RIGHT); } break; @@ -4687,7 +4709,7 @@ public final FunctionNameContext functionName() throws RecognitionException { case BACKQUOTED_IDENTIFIER: enterOuterAlt(_localctx, 3); { - setState(631); + setState(635); identifier(); } break; @@ -4899,13 +4921,13 @@ public final ConstantContext constant() throws RecognitionException { enterRule(_localctx, 76, RULE_constant); try { int _alt; - setState(659); + setState(663); switch (_input.LA(1)) { case NULL: _localctx = new NullLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(634); + setState(638); match(NULL); } break; @@ -4914,7 +4936,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new NumericLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(635); + setState(639); number(); } break; @@ -4923,7 +4945,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new BooleanLiteralContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(636); + setState(640); booleanValue(); } break; @@ -4931,7 +4953,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new StringLiteralContext(_localctx); enterOuterAlt(_localctx, 4); { - setState(638); + setState(642); _errHandler.sync(this); _alt = 1; do { @@ -4939,7 +4961,7 @@ public final ConstantContext constant() throws RecognitionException { case 1: { { - setState(637); + setState(641); match(STRING); } } @@ -4947,9 +4969,9 @@ public final ConstantContext constant() throws RecognitionException { default: throw new NoViableAltException(this); } - setState(640); + setState(644); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,84,_ctx); + _alt = getInterpreter().adaptivePredict(_input,85,_ctx); } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); } break; @@ -4957,7 +4979,7 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new ParamLiteralContext(_localctx); enterOuterAlt(_localctx, 5); { - setState(642); + setState(646); match(PARAM); } break; @@ -4965,11 +4987,11 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new DateEscapedLiteralContext(_localctx); enterOuterAlt(_localctx, 6); { - setState(643); + setState(647); match(DATE_ESC); - setState(644); + setState(648); string(); - setState(645); + setState(649); match(ESC_END); } break; @@ -4977,11 +4999,11 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new TimeEscapedLiteralContext(_localctx); enterOuterAlt(_localctx, 7); { - setState(647); + setState(651); match(TIME_ESC); - setState(648); + setState(652); string(); - setState(649); + setState(653); match(ESC_END); } break; @@ -4989,11 +5011,11 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new TimestampEscapedLiteralContext(_localctx); enterOuterAlt(_localctx, 8); { - setState(651); + setState(655); match(TIMESTAMP_ESC); - setState(652); + setState(656); string(); - setState(653); + setState(657); match(ESC_END); } break; @@ -5001,11 +5023,11 @@ public final ConstantContext constant() throws RecognitionException { _localctx = new GuidEscapedLiteralContext(_localctx); enterOuterAlt(_localctx, 9); { - setState(655); + setState(659); match(GUID_ESC); - setState(656); + setState(660); string(); - setState(657); + setState(661); match(ESC_END); } break; @@ -5057,9 +5079,9 @@ public final ComparisonOperatorContext comparisonOperator() throws RecognitionEx try { enterOuterAlt(_localctx, 1); { - setState(661); + setState(665); _la = _input.LA(1); - if ( !(((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (EQ - 80)) | (1L << (NEQ - 80)) | (1L << (LT - 80)) | (1L << (LTE - 80)) | (1L << (GT - 80)) | (1L << (GTE - 80)))) != 0)) ) { + if ( !(((((_la - 83)) & ~0x3f) == 0 && ((1L << (_la - 83)) & ((1L << (EQ - 83)) | (1L << (NEQ - 83)) | (1L << (LT - 83)) | (1L << (LTE - 83)) | (1L << (GT - 83)) | (1L << (GTE - 83)))) != 0)) ) { _errHandler.recoverInline(this); } else { consume(); @@ -5106,7 +5128,7 @@ public final BooleanValueContext booleanValue() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(663); + setState(667); _la = _input.LA(1); if ( !(_la==FALSE || _la==TRUE) ) { _errHandler.recoverInline(this); @@ -5164,7 +5186,7 @@ public final DataTypeContext dataType() throws RecognitionException { _localctx = new PrimitiveDataTypeContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(665); + setState(669); identifier(); } } @@ -5216,25 +5238,25 @@ public final QualifiedNameContext qualifiedName() throws RecognitionException { int _alt; enterOuterAlt(_localctx, 1); { - setState(672); + setState(676); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,86,_ctx); + _alt = getInterpreter().adaptivePredict(_input,87,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { { { - setState(667); + setState(671); identifier(); - setState(668); + setState(672); match(DOT); } } } - setState(674); + setState(678); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,86,_ctx); + _alt = getInterpreter().adaptivePredict(_input,87,_ctx); } - setState(675); + setState(679); identifier(); } } @@ -5279,13 +5301,13 @@ public final IdentifierContext identifier() throws RecognitionException { IdentifierContext _localctx = new IdentifierContext(_ctx, getState()); enterRule(_localctx, 86, RULE_identifier); try { - setState(679); + setState(683); switch (_input.LA(1)) { case QUOTED_IDENTIFIER: case BACKQUOTED_IDENTIFIER: enterOuterAlt(_localctx, 1); { - setState(677); + setState(681); quoteIdentifier(); } break; @@ -5318,7 +5340,7 @@ public final IdentifierContext identifier() throws RecognitionException { case DIGIT_IDENTIFIER: enterOuterAlt(_localctx, 2); { - setState(678); + setState(682); unquoteIdentifier(); } break; @@ -5371,43 +5393,43 @@ public final TableIdentifierContext tableIdentifier() throws RecognitionExceptio enterRule(_localctx, 88, RULE_tableIdentifier); int _la; try { - setState(693); + setState(697); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,90,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,91,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(684); + setState(688); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW) | (1L << SYS) | (1L << TABLES))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (SYS - 64)) | (1L << (TABLES - 64)) | (1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)) | (1L << (IDENTIFIER - 64)) | (1L << (DIGIT_IDENTIFIER - 64)) | (1L << (QUOTED_IDENTIFIER - 64)) | (1L << (BACKQUOTED_IDENTIFIER - 64)))) != 0)) { { - setState(681); + setState(685); ((TableIdentifierContext)_localctx).catalog = identifier(); - setState(682); + setState(686); match(T__3); } } - setState(686); + setState(690); match(TABLE_IDENTIFIER); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(690); + setState(694); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,89,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,90,_ctx) ) { case 1: { - setState(687); + setState(691); ((TableIdentifierContext)_localctx).catalog = identifier(); - setState(688); + setState(692); match(T__3); } break; } - setState(692); + setState(696); ((TableIdentifierContext)_localctx).name = identifier(); } break; @@ -5474,13 +5496,13 @@ public final QuoteIdentifierContext quoteIdentifier() throws RecognitionExceptio QuoteIdentifierContext _localctx = new QuoteIdentifierContext(_ctx, getState()); enterRule(_localctx, 90, RULE_quoteIdentifier); try { - setState(697); + setState(701); switch (_input.LA(1)) { case QUOTED_IDENTIFIER: _localctx = new QuotedIdentifierContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(695); + setState(699); match(QUOTED_IDENTIFIER); } break; @@ -5488,7 +5510,7 @@ public final QuoteIdentifierContext quoteIdentifier() throws RecognitionExceptio _localctx = new BackQuotedIdentifierContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(696); + setState(700); match(BACKQUOTED_IDENTIFIER); } break; @@ -5560,13 +5582,13 @@ public final UnquoteIdentifierContext unquoteIdentifier() throws RecognitionExce UnquoteIdentifierContext _localctx = new UnquoteIdentifierContext(_ctx, getState()); enterRule(_localctx, 92, RULE_unquoteIdentifier); try { - setState(702); + setState(706); switch (_input.LA(1)) { case IDENTIFIER: _localctx = new UnquotedIdentifierContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(699); + setState(703); match(IDENTIFIER); } break; @@ -5598,7 +5620,7 @@ public final UnquoteIdentifierContext unquoteIdentifier() throws RecognitionExce _localctx = new UnquotedIdentifierContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(700); + setState(704); nonReserved(); } break; @@ -5606,7 +5628,7 @@ public final UnquoteIdentifierContext unquoteIdentifier() throws RecognitionExce _localctx = new DigitIdentifierContext(_localctx); enterOuterAlt(_localctx, 3); { - setState(701); + setState(705); match(DIGIT_IDENTIFIER); } break; @@ -5675,13 +5697,13 @@ public final NumberContext number() throws RecognitionException { NumberContext _localctx = new NumberContext(_ctx, getState()); enterRule(_localctx, 94, RULE_number); try { - setState(706); + setState(710); switch (_input.LA(1)) { case DECIMAL_VALUE: _localctx = new DecimalLiteralContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(704); + setState(708); match(DECIMAL_VALUE); } break; @@ -5689,7 +5711,7 @@ public final NumberContext number() throws RecognitionException { _localctx = new IntegerLiteralContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(705); + setState(709); match(INTEGER_VALUE); } break; @@ -5737,7 +5759,7 @@ public final StringContext string() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(708); + setState(712); _la = _input.LA(1); if ( !(_la==PARAM || _la==STRING) ) { _errHandler.recoverInline(this); @@ -5809,9 +5831,9 @@ public final NonReservedContext nonReserved() throws RecognitionException { try { enterOuterAlt(_localctx, 1); { - setState(710); + setState(714); _la = _input.LA(1); - if ( !(((((_la - 6)) & ~0x3f) == 0 && ((1L << (_la - 6)) & ((1L << (ANALYZE - 6)) | (1L << (ANALYZED - 6)) | (1L << (CATALOGS - 6)) | (1L << (COLUMNS - 6)) | (1L << (DEBUG - 6)) | (1L << (EXECUTABLE - 6)) | (1L << (EXPLAIN - 6)) | (1L << (FORMAT - 6)) | (1L << (FUNCTIONS - 6)) | (1L << (GRAPHVIZ - 6)) | (1L << (MAPPED - 6)) | (1L << (OPTIMIZED - 6)) | (1L << (PARSED - 6)) | (1L << (PHYSICAL - 6)) | (1L << (PLAN - 6)) | (1L << (RLIKE - 6)) | (1L << (QUERY - 6)) | (1L << (SCHEMAS - 6)) | (1L << (SHOW - 6)) | (1L << (SYS - 6)) | (1L << (TABLES - 6)) | (1L << (TEXT - 6)) | (1L << (TYPE - 6)) | (1L << (TYPES - 6)) | (1L << (VERIFY - 6)))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << ANALYZE) | (1L << ANALYZED) | (1L << CATALOGS) | (1L << COLUMNS) | (1L << DEBUG) | (1L << EXECUTABLE) | (1L << EXPLAIN) | (1L << FORMAT) | (1L << FUNCTIONS) | (1L << GRAPHVIZ) | (1L << MAPPED) | (1L << OPTIMIZED) | (1L << PARSED) | (1L << PHYSICAL) | (1L << PLAN) | (1L << RLIKE) | (1L << QUERY) | (1L << SCHEMAS) | (1L << SHOW))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (SYS - 64)) | (1L << (TABLES - 64)) | (1L << (TEXT - 64)) | (1L << (TYPE - 64)) | (1L << (TYPES - 64)) | (1L << (VERIFY - 64)))) != 0)) ) { _errHandler.recoverInline(this); } else { consume(); @@ -5860,7 +5882,7 @@ private boolean valueExpression_sempred(ValueExpressionContext _localctx, int pr } public static final String _serializedATN = - "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3l\u02cb\4\2\t\2\4"+ + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3o\u02cf\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"+ @@ -5878,268 +5900,270 @@ private boolean valueExpression_sempred(ValueExpressionContext _localctx, int pr "\16\5\u00da\13\5\5\5\u00dc\n\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\7\6\u00e6"+ "\n\6\f\6\16\6\u00e9\13\6\5\6\u00eb\n\6\3\6\5\6\u00ee\n\6\3\7\3\7\3\7\3"+ "\7\3\7\5\7\u00f5\n\7\3\b\3\b\3\b\3\b\3\b\5\b\u00fc\n\b\3\t\3\t\5\t\u0100"+ - "\n\t\3\n\3\n\5\n\u0104\n\n\3\n\3\n\3\n\7\n\u0109\n\n\f\n\16\n\u010c\13"+ - "\n\3\n\5\n\u010f\n\n\3\n\3\n\5\n\u0113\n\n\3\n\3\n\3\n\5\n\u0118\n\n\3"+ - "\n\3\n\5\n\u011c\n\n\3\13\3\13\3\13\3\13\7\13\u0122\n\13\f\13\16\13\u0125"+ - "\13\13\3\f\5\f\u0128\n\f\3\f\3\f\3\f\7\f\u012d\n\f\f\f\16\f\u0130\13\f"+ - "\3\r\3\r\3\16\3\16\3\16\3\16\7\16\u0138\n\16\f\16\16\16\u013b\13\16\5"+ - "\16\u013d\n\16\3\16\3\16\5\16\u0141\n\16\3\17\3\17\3\17\3\17\3\17\3\17"+ - "\3\20\3\20\3\21\3\21\5\21\u014d\n\21\3\21\5\21\u0150\n\21\3\22\3\22\7"+ - "\22\u0154\n\22\f\22\16\22\u0157\13\22\3\23\3\23\3\23\3\23\5\23\u015d\n"+ - "\23\3\23\3\23\3\23\3\23\3\23\5\23\u0164\n\23\3\24\5\24\u0167\n\24\3\24"+ - "\3\24\5\24\u016b\n\24\3\24\3\24\5\24\u016f\n\24\3\24\3\24\5\24\u0173\n"+ - "\24\5\24\u0175\n\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\7\25\u017e\n\25"+ - "\f\25\16\25\u0181\13\25\3\25\3\25\5\25\u0185\n\25\3\26\3\26\5\26\u0189"+ - "\n\26\3\26\5\26\u018c\n\26\3\26\3\26\3\26\3\26\5\26\u0192\n\26\3\26\5"+ - "\26\u0195\n\26\3\26\3\26\3\26\3\26\5\26\u019b\n\26\3\26\5\26\u019e\n\26"+ - "\5\26\u01a0\n\26\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+ + "\n\t\3\t\3\t\5\t\u0104\n\t\3\n\3\n\5\n\u0108\n\n\3\n\3\n\3\n\7\n\u010d"+ + "\n\n\f\n\16\n\u0110\13\n\3\n\5\n\u0113\n\n\3\n\3\n\5\n\u0117\n\n\3\n\3"+ + "\n\3\n\5\n\u011c\n\n\3\n\3\n\5\n\u0120\n\n\3\13\3\13\3\13\3\13\7\13\u0126"+ + "\n\13\f\13\16\13\u0129\13\13\3\f\5\f\u012c\n\f\3\f\3\f\3\f\7\f\u0131\n"+ + "\f\f\f\16\f\u0134\13\f\3\r\3\r\3\16\3\16\3\16\3\16\7\16\u013c\n\16\f\16"+ + "\16\16\u013f\13\16\5\16\u0141\n\16\3\16\3\16\5\16\u0145\n\16\3\17\3\17"+ + "\3\17\3\17\3\17\3\17\3\20\3\20\3\21\3\21\5\21\u0151\n\21\3\21\5\21\u0154"+ + "\n\21\3\22\3\22\7\22\u0158\n\22\f\22\16\22\u015b\13\22\3\23\3\23\3\23"+ + "\3\23\5\23\u0161\n\23\3\23\3\23\3\23\3\23\3\23\5\23\u0168\n\23\3\24\5"+ + "\24\u016b\n\24\3\24\3\24\5\24\u016f\n\24\3\24\3\24\5\24\u0173\n\24\3\24"+ + "\3\24\5\24\u0177\n\24\5\24\u0179\n\24\3\25\3\25\3\25\3\25\3\25\3\25\3"+ + "\25\7\25\u0182\n\25\f\25\16\25\u0185\13\25\3\25\3\25\5\25\u0189\n\25\3"+ + "\26\3\26\5\26\u018d\n\26\3\26\5\26\u0190\n\26\3\26\3\26\3\26\3\26\5\26"+ + "\u0196\n\26\3\26\5\26\u0199\n\26\3\26\3\26\3\26\3\26\5\26\u019f\n\26\3"+ + "\26\5\26\u01a2\n\26\5\26\u01a4\n\26\3\27\3\27\3\30\3\30\3\30\3\30\3\30"+ "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+ - "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u01c3\n\30\3\30\3\30\3\30"+ - "\3\30\3\30\3\30\7\30\u01cb\n\30\f\30\16\30\u01ce\13\30\3\31\3\31\7\31"+ - "\u01d2\n\31\f\31\16\31\u01d5\13\31\3\32\3\32\5\32\u01d9\n\32\3\33\5\33"+ - "\u01dc\n\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u01e4\n\33\3\33\3\33\3"+ - "\33\3\33\3\33\7\33\u01eb\n\33\f\33\16\33\u01ee\13\33\3\33\3\33\3\33\5"+ - "\33\u01f3\n\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u01fb\n\33\3\33\3\33"+ - "\3\33\5\33\u0200\n\33\3\33\3\33\3\33\3\33\5\33\u0206\n\33\3\33\5\33\u0209"+ - "\n\33\3\34\3\34\3\34\3\35\3\35\5\35\u0210\n\35\3\36\3\36\3\36\3\36\3\36"+ - "\3\36\5\36\u0218\n\36\3\37\3\37\3\37\3\37\5\37\u021e\n\37\3\37\3\37\3"+ - "\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\7\37\u022a\n\37\f\37\16\37\u022d"+ - "\13\37\3 \3 \3 \3 \3 \3 \5 \u0235\n \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 \3 "+ - "\5 \u0242\n \3!\3!\3!\3!\3!\5!\u0249\n!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3"+ - "#\3#\3#\3#\3#\5#\u0257\n#\3$\3$\3$\3$\3$\3$\3$\3%\3%\3%\3%\3%\5%\u0265"+ - "\n%\3&\3&\3&\5&\u026a\n&\3&\3&\3&\7&\u026f\n&\f&\16&\u0272\13&\5&\u0274"+ - "\n&\3&\3&\3\'\3\'\3\'\5\'\u027b\n\'\3(\3(\3(\3(\6(\u0281\n(\r(\16(\u0282"+ - "\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\5(\u0296\n(\3)\3)"+ - "\3*\3*\3+\3+\3,\3,\3,\7,\u02a1\n,\f,\16,\u02a4\13,\3,\3,\3-\3-\5-\u02aa"+ - "\n-\3.\3.\3.\5.\u02af\n.\3.\3.\3.\3.\5.\u02b5\n.\3.\5.\u02b8\n.\3/\3/"+ - "\5/\u02bc\n/\3\60\3\60\3\60\5\60\u02c1\n\60\3\61\3\61\5\61\u02c5\n\61"+ - "\3\62\3\62\3\63\3\63\3\63\2\4.<\64\2\4\6\b\n\f\16\20\22\24\26\30\32\34"+ - "\36 \"$&(*,.\60\62\64\668:<>@BDFHJLNPRTVXZ\\^`bd\2\20\b\2\7\7\t\t\31\31"+ - ",,\62\62\66\66\4\2\"\"BB\4\2\t\t\62\62\4\2\37\37%%\3\2\25\26\4\2\7\7a"+ - "a\4\2\r\r\25\25\4\2\7\7\27\27\3\2XY\3\2Z\\\3\2RW\4\2\35\35CC\3\2_`\20"+ - "\2\b\t\22\24\31\31\33\33\36\36!\",,\62\62\668:<>?ABDEGG\u0320\2f\3\2\2"+ - "\2\4i\3\2\2\2\6\u00d0\3\2\2\2\b\u00db\3\2\2\2\n\u00df\3\2\2\2\f\u00f4"+ - "\3\2\2\2\16\u00fb\3\2\2\2\20\u00fd\3\2\2\2\22\u0101\3\2\2\2\24\u011d\3"+ - "\2\2\2\26\u0127\3\2\2\2\30\u0131\3\2\2\2\32\u0140\3\2\2\2\34\u0142\3\2"+ - "\2\2\36\u0148\3\2\2\2 \u014a\3\2\2\2\"\u0151\3\2\2\2$\u0163\3\2\2\2&\u0174"+ - "\3\2\2\2(\u0184\3\2\2\2*\u019f\3\2\2\2,\u01a1\3\2\2\2.\u01c2\3\2\2\2\60"+ - "\u01d3\3\2\2\2\62\u01d6\3\2\2\2\64\u0208\3\2\2\2\66\u020a\3\2\2\28\u020d"+ - "\3\2\2\2:\u0217\3\2\2\2<\u021d\3\2\2\2>\u0241\3\2\2\2@\u0248\3\2\2\2B"+ - "\u024a\3\2\2\2D\u0256\3\2\2\2F\u0258\3\2\2\2H\u0264\3\2\2\2J\u0266\3\2"+ - "\2\2L\u027a\3\2\2\2N\u0295\3\2\2\2P\u0297\3\2\2\2R\u0299\3\2\2\2T\u029b"+ - "\3\2\2\2V\u02a2\3\2\2\2X\u02a9\3\2\2\2Z\u02b7\3\2\2\2\\\u02bb\3\2\2\2"+ - "^\u02c0\3\2\2\2`\u02c4\3\2\2\2b\u02c6\3\2\2\2d\u02c8\3\2\2\2fg\5\6\4\2"+ - "gh\7\2\2\3h\3\3\2\2\2ij\5,\27\2jk\7\2\2\3k\5\3\2\2\2l\u00d1\5\b\5\2m{"+ - "\7\33\2\2nw\7\3\2\2op\78\2\2pv\t\2\2\2qr\7\36\2\2rv\t\3\2\2st\7G\2\2t"+ - "v\5R*\2uo\3\2\2\2uq\3\2\2\2us\3\2\2\2vy\3\2\2\2wu\3\2\2\2wx\3\2\2\2xz"+ - "\3\2\2\2yw\3\2\2\2z|\7\4\2\2{n\3\2\2\2{|\3\2\2\2|}\3\2\2\2}\u00d1\5\6"+ - "\4\2~\u008a\7\24\2\2\177\u0086\7\3\2\2\u0080\u0081\78\2\2\u0081\u0085"+ - "\t\4\2\2\u0082\u0083\7\36\2\2\u0083\u0085\t\3\2\2\u0084\u0080\3\2\2\2"+ - "\u0084\u0082\3\2\2\2\u0085\u0088\3\2\2\2\u0086\u0084\3\2\2\2\u0086\u0087"+ - "\3\2\2\2\u0087\u0089\3\2\2\2\u0088\u0086\3\2\2\2\u0089\u008b\7\4\2\2\u008a"+ - "\177\3\2\2\2\u008a\u008b\3\2\2\2\u008b\u008c\3\2\2\2\u008c\u00d1\5\6\4"+ - "\2\u008d\u008e\7>\2\2\u008e\u0091\7A\2\2\u008f\u0092\5\66\34\2\u0090\u0092"+ - "\5Z.\2\u0091\u008f\3\2\2\2\u0091\u0090\3\2\2\2\u0091\u0092\3\2\2\2\u0092"+ - "\u00d1\3\2\2\2\u0093\u0094\7>\2\2\u0094\u0095\7\23\2\2\u0095\u0098\t\5"+ - "\2\2\u0096\u0099\5\66\34\2\u0097\u0099\5Z.\2\u0098\u0096\3\2\2\2\u0098"+ - "\u0097\3\2\2\2\u0099\u00d1\3\2\2\2\u009a\u009d\t\6\2\2\u009b\u009e\5\66"+ - "\34\2\u009c\u009e\5Z.\2\u009d\u009b\3\2\2\2\u009d\u009c\3\2\2\2\u009e"+ - "\u00d1\3\2\2\2\u009f\u00a0\7>\2\2\u00a0\u00a2\7!\2\2\u00a1\u00a3\5\66"+ - "\34\2\u00a2\u00a1\3\2\2\2\u00a2\u00a3\3\2\2\2\u00a3\u00d1\3\2\2\2\u00a4"+ - "\u00a5\7>\2\2\u00a5\u00d1\7<\2\2\u00a6\u00a7\7?\2\2\u00a7\u00d1\7\22\2"+ - "\2\u00a8\u00a9\7?\2\2\u00a9\u00ac\7A\2\2\u00aa\u00ab\7\21\2\2\u00ab\u00ad"+ - "\5\66\34\2\u00ac\u00aa\3\2\2\2\u00ac\u00ad\3\2\2\2\u00ad\u00b0\3\2\2\2"+ - "\u00ae\u00b1\5\66\34\2\u00af\u00b1\5Z.\2\u00b0\u00ae\3\2\2\2\u00b0\u00af"+ - "\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1\u00bb\3\2\2\2\u00b2\u00b3\7D\2\2\u00b3"+ - "\u00b8\5b\62\2\u00b4\u00b5\7\5\2\2\u00b5\u00b7\5b\62\2\u00b6\u00b4\3\2"+ - "\2\2\u00b7\u00ba\3\2\2\2\u00b8\u00b6\3\2\2\2\u00b8\u00b9\3\2\2\2\u00b9"+ - "\u00bc\3\2\2\2\u00ba\u00b8\3\2\2\2\u00bb\u00b2\3\2\2\2\u00bb\u00bc\3\2"+ - "\2\2\u00bc\u00d1\3\2\2\2\u00bd\u00be\7?\2\2\u00be\u00c1\7\23\2\2\u00bf"+ - "\u00c0\7\21\2\2\u00c0\u00c2\5b\62\2\u00c1\u00bf\3\2\2\2\u00c1\u00c2\3"+ - "\2\2\2\u00c2\u00c6\3\2\2\2\u00c3\u00c4\7@\2\2\u00c4\u00c7\5\66\34\2\u00c5"+ - "\u00c7\5Z.\2\u00c6\u00c3\3\2\2\2\u00c6\u00c5\3\2\2\2\u00c6\u00c7\3\2\2"+ - "\2\u00c7\u00c9\3\2\2\2\u00c8\u00ca\5\66\34\2\u00c9\u00c8\3\2\2\2\u00c9"+ - "\u00ca\3\2\2\2\u00ca\u00d1\3\2\2\2\u00cb\u00cc\7?\2\2\u00cc\u00d1\7E\2"+ - "\2\u00cd\u00ce\7?\2\2\u00ce\u00cf\7@\2\2\u00cf\u00d1\7E\2\2\u00d0l\3\2"+ - "\2\2\u00d0m\3\2\2\2\u00d0~\3\2\2\2\u00d0\u008d\3\2\2\2\u00d0\u0093\3\2"+ - "\2\2\u00d0\u009a\3\2\2\2\u00d0\u009f\3\2\2\2\u00d0\u00a4\3\2\2\2\u00d0"+ - "\u00a6\3\2\2\2\u00d0\u00a8\3\2\2\2\u00d0\u00bd\3\2\2\2\u00d0\u00cb\3\2"+ - "\2\2\u00d0\u00cd\3\2\2\2\u00d1\7\3\2\2\2\u00d2\u00d3\7I\2\2\u00d3\u00d8"+ - "\5\34\17\2\u00d4\u00d5\7\5\2\2\u00d5\u00d7\5\34\17\2\u00d6\u00d4\3\2\2"+ - "\2\u00d7\u00da\3\2\2\2\u00d8\u00d6\3\2\2\2\u00d8\u00d9\3\2\2\2\u00d9\u00dc"+ - "\3\2\2\2\u00da\u00d8\3\2\2\2\u00db\u00d2\3\2\2\2\u00db\u00dc\3\2\2\2\u00dc"+ - "\u00dd\3\2\2\2\u00dd\u00de\5\n\6\2\u00de\t\3\2\2\2\u00df\u00ea\5\16\b"+ - "\2\u00e0\u00e1\7\64\2\2\u00e1\u00e2\7\17\2\2\u00e2\u00e7\5\20\t\2\u00e3"+ - "\u00e4\7\5\2\2\u00e4\u00e6\5\20\t\2\u00e5\u00e3\3\2\2\2\u00e6\u00e9\3"+ - "\2\2\2\u00e7\u00e5\3\2\2\2\u00e7\u00e8\3\2\2\2\u00e8\u00eb\3\2\2\2\u00e9"+ - "\u00e7\3\2\2\2\u00ea\u00e0\3\2\2\2\u00ea\u00eb\3\2\2\2\u00eb\u00ed\3\2"+ - "\2\2\u00ec\u00ee\5\f\7\2\u00ed\u00ec\3\2\2\2\u00ed\u00ee\3\2\2\2\u00ee"+ - "\13\3\2\2\2\u00ef\u00f0\7+\2\2\u00f0\u00f5\t\7\2\2\u00f1\u00f2\7L\2\2"+ - "\u00f2\u00f3\t\7\2\2\u00f3\u00f5\7Q\2\2\u00f4\u00ef\3\2\2\2\u00f4\u00f1"+ - "\3\2\2\2\u00f5\r\3\2\2\2\u00f6\u00fc\5\22\n\2\u00f7\u00f8\7\3\2\2\u00f8"+ - "\u00f9\5\n\6\2\u00f9\u00fa\7\4\2\2\u00fa\u00fc\3\2\2\2\u00fb\u00f6\3\2"+ - "\2\2\u00fb\u00f7\3\2\2\2\u00fc\17\3\2\2\2\u00fd\u00ff\5,\27\2\u00fe\u0100"+ - "\t\b\2\2\u00ff\u00fe\3\2\2\2\u00ff\u0100\3\2\2\2\u0100\21\3\2\2\2\u0101"+ - "\u0103\7=\2\2\u0102\u0104\5\36\20\2\u0103\u0102\3\2\2\2\u0103\u0104\3"+ - "\2\2\2\u0104\u0105\3\2\2\2\u0105\u010a\5 \21\2\u0106\u0107\7\5\2\2\u0107"+ - "\u0109\5 \21\2\u0108\u0106\3\2\2\2\u0109\u010c\3\2\2\2\u010a\u0108\3\2"+ - "\2\2\u010a\u010b\3\2\2\2\u010b\u010e\3\2\2\2\u010c\u010a\3\2\2\2\u010d"+ - "\u010f\5\24\13\2\u010e\u010d\3\2\2\2\u010e\u010f\3\2\2\2\u010f\u0112\3"+ - "\2\2\2\u0110\u0111\7H\2\2\u0111\u0113\5.\30\2\u0112\u0110\3\2\2\2\u0112"+ - "\u0113\3\2\2\2\u0113\u0117\3\2\2\2\u0114\u0115\7#\2\2\u0115\u0116\7\17"+ - "\2\2\u0116\u0118\5\26\f\2\u0117\u0114\3\2\2\2\u0117\u0118\3\2\2\2\u0118"+ - "\u011b\3\2\2\2\u0119\u011a\7$\2\2\u011a\u011c\5.\30\2\u011b\u0119\3\2"+ - "\2\2\u011b\u011c\3\2\2\2\u011c\23\3\2\2\2\u011d\u011e\7\37\2\2\u011e\u0123"+ - "\5\"\22\2\u011f\u0120\7\5\2\2\u0120\u0122\5\"\22\2\u0121\u011f\3\2\2\2"+ - "\u0122\u0125\3\2\2\2\u0123\u0121\3\2\2\2\u0123\u0124\3\2\2\2\u0124\25"+ - "\3\2\2\2\u0125\u0123\3\2\2\2\u0126\u0128\5\36\20\2\u0127\u0126\3\2\2\2"+ - "\u0127\u0128\3\2\2\2\u0128\u0129\3\2\2\2\u0129\u012e\5\30\r\2\u012a\u012b"+ - "\7\5\2\2\u012b\u012d\5\30\r\2\u012c\u012a\3\2\2\2\u012d\u0130\3\2\2\2"+ - "\u012e\u012c\3\2\2\2\u012e\u012f\3\2\2\2\u012f\27\3\2\2\2\u0130\u012e"+ - "\3\2\2\2\u0131\u0132\5\32\16\2\u0132\31\3\2\2\2\u0133\u013c\7\3\2\2\u0134"+ - "\u0139\5,\27\2\u0135\u0136\7\5\2\2\u0136\u0138\5,\27\2\u0137\u0135\3\2"+ - "\2\2\u0138\u013b\3\2\2\2\u0139\u0137\3\2\2\2\u0139\u013a\3\2\2\2\u013a"+ - "\u013d\3\2\2\2\u013b\u0139\3\2\2\2\u013c\u0134\3\2\2\2\u013c\u013d\3\2"+ - "\2\2\u013d\u013e\3\2\2\2\u013e\u0141\7\4\2\2\u013f\u0141\5,\27\2\u0140"+ - "\u0133\3\2\2\2\u0140\u013f\3\2\2\2\u0141\33\3\2\2\2\u0142\u0143\5X-\2"+ - "\u0143\u0144\7\f\2\2\u0144\u0145\7\3\2\2\u0145\u0146\5\n\6\2\u0146\u0147"+ - "\7\4\2\2\u0147\35\3\2\2\2\u0148\u0149\t\t\2\2\u0149\37\3\2\2\2\u014a\u014f"+ - "\5,\27\2\u014b\u014d\7\f\2\2\u014c\u014b\3\2\2\2\u014c\u014d\3\2\2\2\u014d"+ - "\u014e\3\2\2\2\u014e\u0150\5X-\2\u014f\u014c\3\2\2\2\u014f\u0150\3\2\2"+ - "\2\u0150!\3\2\2\2\u0151\u0155\5*\26\2\u0152\u0154\5$\23\2\u0153\u0152"+ - "\3\2\2\2\u0154\u0157\3\2\2\2\u0155\u0153\3\2\2\2\u0155\u0156\3\2\2\2\u0156"+ - "#\3\2\2\2\u0157\u0155\3\2\2\2\u0158\u0159\5&\24\2\u0159\u015a\7(\2\2\u015a"+ - "\u015c\5*\26\2\u015b\u015d\5(\25\2\u015c\u015b\3\2\2\2\u015c\u015d\3\2"+ - "\2\2\u015d\u0164\3\2\2\2\u015e\u015f\7.\2\2\u015f\u0160\5&\24\2\u0160"+ - "\u0161\7(\2\2\u0161\u0162\5*\26\2\u0162\u0164\3\2\2\2\u0163\u0158\3\2"+ - "\2\2\u0163\u015e\3\2\2\2\u0164%\3\2\2\2\u0165\u0167\7&\2\2\u0166\u0165"+ - "\3\2\2\2\u0166\u0167\3\2\2\2\u0167\u0175\3\2\2\2\u0168\u016a\7)\2\2\u0169"+ - "\u016b\7\65\2\2\u016a\u0169\3\2\2\2\u016a\u016b\3\2\2\2\u016b\u0175\3"+ - "\2\2\2\u016c\u016e\79\2\2\u016d\u016f\7\65\2\2\u016e\u016d\3\2\2\2\u016e"+ - "\u016f\3\2\2\2\u016f\u0175\3\2\2\2\u0170\u0172\7 \2\2\u0171\u0173\7\65"+ - "\2\2\u0172\u0171\3\2\2\2\u0172\u0173\3\2\2\2\u0173\u0175\3\2\2\2\u0174"+ - "\u0166\3\2\2\2\u0174\u0168\3\2\2\2\u0174\u016c\3\2\2\2\u0174\u0170\3\2"+ - "\2\2\u0175\'\3\2\2\2\u0176\u0177\7\61\2\2\u0177\u0185\5.\30\2\u0178\u0179"+ - "\7F\2\2\u0179\u017a\7\3\2\2\u017a\u017f\5X-\2\u017b\u017c\7\5\2\2\u017c"+ - "\u017e\5X-\2\u017d\u017b\3\2\2\2\u017e\u0181\3\2\2\2\u017f\u017d\3\2\2"+ - "\2\u017f\u0180\3\2\2\2\u0180\u0182\3\2\2\2\u0181\u017f\3\2\2\2\u0182\u0183"+ - "\7\4\2\2\u0183\u0185\3\2\2\2\u0184\u0176\3\2\2\2\u0184\u0178\3\2\2\2\u0185"+ - ")\3\2\2\2\u0186\u018b\5Z.\2\u0187\u0189\7\f\2\2\u0188\u0187\3\2\2\2\u0188"+ - "\u0189\3\2\2\2\u0189\u018a\3\2\2\2\u018a\u018c\5V,\2\u018b\u0188\3\2\2"+ - "\2\u018b\u018c\3\2\2\2\u018c\u01a0\3\2\2\2\u018d\u018e\7\3\2\2\u018e\u018f"+ - "\5\n\6\2\u018f\u0194\7\4\2\2\u0190\u0192\7\f\2\2\u0191\u0190\3\2\2\2\u0191"+ - "\u0192\3\2\2\2\u0192\u0193\3\2\2\2\u0193\u0195\5V,\2\u0194\u0191\3\2\2"+ - "\2\u0194\u0195\3\2\2\2\u0195\u01a0\3\2\2\2\u0196\u0197\7\3\2\2\u0197\u0198"+ - "\5\"\22\2\u0198\u019d\7\4\2\2\u0199\u019b\7\f\2\2\u019a\u0199\3\2\2\2"+ - "\u019a\u019b\3\2\2\2\u019b\u019c\3\2\2\2\u019c\u019e\5V,\2\u019d\u019a"+ - "\3\2\2\2\u019d\u019e\3\2\2\2\u019e\u01a0\3\2\2\2\u019f\u0186\3\2\2\2\u019f"+ - "\u018d\3\2\2\2\u019f\u0196\3\2\2\2\u01a0+\3\2\2\2\u01a1\u01a2\5.\30\2"+ - "\u01a2-\3\2\2\2\u01a3\u01a4\b\30\1\2\u01a4\u01a5\7/\2\2\u01a5\u01c3\5"+ - ".\30\n\u01a6\u01a7\7\32\2\2\u01a7\u01a8\7\3\2\2\u01a8\u01a9\5\b\5\2\u01a9"+ - "\u01aa\7\4\2\2\u01aa\u01c3\3\2\2\2\u01ab\u01ac\7;\2\2\u01ac\u01ad\7\3"+ - "\2\2\u01ad\u01ae\5b\62\2\u01ae\u01af\5\60\31\2\u01af\u01b0\7\4\2\2\u01b0"+ - "\u01c3\3\2\2\2\u01b1\u01b2\7-\2\2\u01b2\u01b3\7\3\2\2\u01b3\u01b4\5V,"+ - "\2\u01b4\u01b5\7\5\2\2\u01b5\u01b6\5b\62\2\u01b6\u01b7\5\60\31\2\u01b7"+ - "\u01b8\7\4\2\2\u01b8\u01c3\3\2\2\2\u01b9\u01ba\7-\2\2\u01ba\u01bb\7\3"+ - "\2\2\u01bb\u01bc\5b\62\2\u01bc\u01bd\7\5\2\2\u01bd\u01be\5b\62\2\u01be"+ - "\u01bf\5\60\31\2\u01bf\u01c0\7\4\2\2\u01c0\u01c3\3\2\2\2\u01c1\u01c3\5"+ - "\62\32\2\u01c2\u01a3\3\2\2\2\u01c2\u01a6\3\2\2\2\u01c2\u01ab\3\2\2\2\u01c2"+ - "\u01b1\3\2\2\2\u01c2\u01b9\3\2\2\2\u01c2\u01c1\3\2\2\2\u01c3\u01cc\3\2"+ - "\2\2\u01c4\u01c5\f\4\2\2\u01c5\u01c6\7\n\2\2\u01c6\u01cb\5.\30\5\u01c7"+ - "\u01c8\f\3\2\2\u01c8\u01c9\7\63\2\2\u01c9\u01cb\5.\30\4\u01ca\u01c4\3"+ - "\2\2\2\u01ca\u01c7\3\2\2\2\u01cb\u01ce\3\2\2\2\u01cc\u01ca\3\2\2\2\u01cc"+ - "\u01cd\3\2\2\2\u01cd/\3\2\2\2\u01ce\u01cc\3\2\2\2\u01cf\u01d0\7\5\2\2"+ - "\u01d0\u01d2\5b\62\2\u01d1\u01cf\3\2\2\2\u01d2\u01d5\3\2\2\2\u01d3\u01d1"+ - "\3\2\2\2\u01d3\u01d4\3\2\2\2\u01d4\61\3\2\2\2\u01d5\u01d3\3\2\2\2\u01d6"+ - "\u01d8\5<\37\2\u01d7\u01d9\5\64\33\2\u01d8\u01d7\3\2\2\2\u01d8\u01d9\3"+ - "\2\2\2\u01d9\63\3\2\2\2\u01da\u01dc\7/\2\2\u01db\u01da\3\2\2\2\u01db\u01dc"+ - "\3\2\2\2\u01dc\u01dd\3\2\2\2\u01dd\u01de\7\16\2\2\u01de\u01df\5<\37\2"+ - "\u01df\u01e0\7\n\2\2\u01e0\u01e1\5<\37\2\u01e1\u0209\3\2\2\2\u01e2\u01e4"+ - "\7/\2\2\u01e3\u01e2\3\2\2\2\u01e3\u01e4\3\2\2\2\u01e4\u01e5\3\2\2\2\u01e5"+ - "\u01e6\7%\2\2\u01e6\u01e7\7\3\2\2\u01e7\u01ec\5,\27\2\u01e8\u01e9\7\5"+ - "\2\2\u01e9\u01eb\5,\27\2\u01ea\u01e8\3\2\2\2\u01eb\u01ee\3\2\2\2\u01ec"+ - "\u01ea\3\2\2\2\u01ec\u01ed\3\2\2\2\u01ed\u01ef\3\2\2\2\u01ee\u01ec\3\2"+ - "\2\2\u01ef\u01f0\7\4\2\2\u01f0\u0209\3\2\2\2\u01f1\u01f3\7/\2\2\u01f2"+ - "\u01f1\3\2\2\2\u01f2\u01f3\3\2\2\2\u01f3\u01f4\3\2\2\2\u01f4\u01f5\7%"+ - "\2\2\u01f5\u01f6\7\3\2\2\u01f6\u01f7\5\b\5\2\u01f7\u01f8\7\4\2\2\u01f8"+ - "\u0209\3\2\2\2\u01f9\u01fb\7/\2\2\u01fa\u01f9\3\2\2\2\u01fa\u01fb\3\2"+ - "\2\2\u01fb\u01fc\3\2\2\2\u01fc\u01fd\7*\2\2\u01fd\u0209\58\35\2\u01fe"+ - "\u0200\7/\2\2\u01ff\u01fe\3\2\2\2\u01ff\u0200\3\2\2\2\u0200\u0201\3\2"+ - "\2\2\u0201\u0202\7:\2\2\u0202\u0209\5b\62\2\u0203\u0205\7\'\2\2\u0204"+ - "\u0206\7/\2\2\u0205\u0204\3\2\2\2\u0205\u0206\3\2\2\2\u0206\u0207\3\2"+ - "\2\2\u0207\u0209\7\60\2\2\u0208\u01db\3\2\2\2\u0208\u01e3\3\2\2\2\u0208"+ - "\u01f2\3\2\2\2\u0208\u01fa\3\2\2\2\u0208\u01ff\3\2\2\2\u0208\u0203\3\2"+ - "\2\2\u0209\65\3\2\2\2\u020a\u020b\7*\2\2\u020b\u020c\58\35\2\u020c\67"+ - "\3\2\2\2\u020d\u020f\5b\62\2\u020e\u0210\5:\36\2\u020f\u020e\3\2\2\2\u020f"+ - "\u0210\3\2\2\2\u02109\3\2\2\2\u0211\u0212\7\30\2\2\u0212\u0218\5b\62\2"+ - "\u0213\u0214\7J\2\2\u0214\u0215\5b\62\2\u0215\u0216\7Q\2\2\u0216\u0218"+ - "\3\2\2\2\u0217\u0211\3\2\2\2\u0217\u0213\3\2\2\2\u0218;\3\2\2\2\u0219"+ - "\u021a\b\37\1\2\u021a\u021e\5> \2\u021b\u021c\t\n\2\2\u021c\u021e\5<\37"+ - "\6\u021d\u0219\3\2\2\2\u021d\u021b\3\2\2\2\u021e\u022b\3\2\2\2\u021f\u0220"+ - "\f\5\2\2\u0220\u0221\t\13\2\2\u0221\u022a\5<\37\6\u0222\u0223\f\4\2\2"+ - "\u0223\u0224\t\n\2\2\u0224\u022a\5<\37\5\u0225\u0226\f\3\2\2\u0226\u0227"+ - "\5P)\2\u0227\u0228\5<\37\4\u0228\u022a\3\2\2\2\u0229\u021f\3\2\2\2\u0229"+ - "\u0222\3\2\2\2\u0229\u0225\3\2\2\2\u022a\u022d\3\2\2\2\u022b\u0229\3\2"+ - "\2\2\u022b\u022c\3\2\2\2\u022c=\3\2\2\2\u022d\u022b\3\2\2\2\u022e\u0242"+ - "\5@!\2\u022f\u0242\5D#\2\u0230\u0242\5N(\2\u0231\u0232\5V,\2\u0232\u0233"+ - "\7^\2\2\u0233\u0235\3\2\2\2\u0234\u0231\3\2\2\2\u0234\u0235\3\2\2\2\u0235"+ - "\u0236\3\2\2\2\u0236\u0242\7Z\2\2\u0237\u0242\5H%\2\u0238\u0239\7\3\2"+ - "\2\u0239\u023a\5\b\5\2\u023a\u023b\7\4\2\2\u023b\u0242\3\2\2\2\u023c\u0242"+ - "\5V,\2\u023d\u023e\7\3\2\2\u023e\u023f\5,\27\2\u023f\u0240\7\4\2\2\u0240"+ - "\u0242\3\2\2\2\u0241\u022e\3\2\2\2\u0241\u022f\3\2\2\2\u0241\u0230\3\2"+ - "\2\2\u0241\u0234\3\2\2\2\u0241\u0237\3\2\2\2\u0241\u0238\3\2\2\2\u0241"+ - "\u023c\3\2\2\2\u0241\u023d\3\2\2\2\u0242?\3\2\2\2\u0243\u0249\5B\"\2\u0244"+ - "\u0245\7K\2\2\u0245\u0246\5B\"\2\u0246\u0247\7Q\2\2\u0247\u0249\3\2\2"+ - "\2\u0248\u0243\3\2\2\2\u0248\u0244\3\2\2\2\u0249A\3\2\2\2\u024a\u024b"+ - "\7\20\2\2\u024b\u024c\7\3\2\2\u024c\u024d\5,\27\2\u024d\u024e\7\f\2\2"+ - "\u024e\u024f\5T+\2\u024f\u0250\7\4\2\2\u0250C\3\2\2\2\u0251\u0257\5F$"+ - "\2\u0252\u0253\7K\2\2\u0253\u0254\5F$\2\u0254\u0255\7Q\2\2\u0255\u0257"+ - "\3\2\2\2\u0256\u0251\3\2\2\2\u0256\u0252\3\2\2\2\u0257E\3\2\2\2\u0258"+ - "\u0259\7\34\2\2\u0259\u025a\7\3\2\2\u025a\u025b\5X-\2\u025b\u025c\7\37"+ - "\2\2\u025c\u025d\5<\37\2\u025d\u025e\7\4\2\2\u025eG\3\2\2\2\u025f\u0265"+ - "\5J&\2\u0260\u0261\7K\2\2\u0261\u0262\5J&\2\u0262\u0263\7Q\2\2\u0263\u0265"+ - "\3\2\2\2\u0264\u025f\3\2\2\2\u0264\u0260\3\2\2\2\u0265I\3\2\2\2\u0266"+ - "\u0267\5L\'\2\u0267\u0273\7\3\2\2\u0268\u026a\5\36\20\2\u0269\u0268\3"+ - "\2\2\2\u0269\u026a\3\2\2\2\u026a\u026b\3\2\2\2\u026b\u0270\5,\27\2\u026c"+ - "\u026d\7\5\2\2\u026d\u026f\5,\27\2\u026e\u026c\3\2\2\2\u026f\u0272\3\2"+ - "\2\2\u0270\u026e\3\2\2\2\u0270\u0271\3\2\2\2\u0271\u0274\3\2\2\2\u0272"+ - "\u0270\3\2\2\2\u0273\u0269\3\2\2\2\u0273\u0274\3\2\2\2\u0274\u0275\3\2"+ - "\2\2\u0275\u0276\7\4\2\2\u0276K\3\2\2\2\u0277\u027b\7)\2\2\u0278\u027b"+ - "\79\2\2\u0279\u027b\5X-\2\u027a\u0277\3\2\2\2\u027a\u0278\3\2\2\2\u027a"+ - "\u0279\3\2\2\2\u027bM\3\2\2\2\u027c\u0296\7\60\2\2\u027d\u0296\5`\61\2"+ - "\u027e\u0296\5R*\2\u027f\u0281\7`\2\2\u0280\u027f\3\2\2\2\u0281\u0282"+ - "\3\2\2\2\u0282\u0280\3\2\2\2\u0282\u0283\3\2\2\2\u0283\u0296\3\2\2\2\u0284"+ - "\u0296\7_\2\2\u0285\u0286\7M\2\2\u0286\u0287\5b\62\2\u0287\u0288\7Q\2"+ - "\2\u0288\u0296\3\2\2\2\u0289\u028a\7N\2\2\u028a\u028b\5b\62\2\u028b\u028c"+ - "\7Q\2\2\u028c\u0296\3\2\2\2\u028d\u028e\7O\2\2\u028e\u028f\5b\62\2\u028f"+ - "\u0290\7Q\2\2\u0290\u0296\3\2\2\2\u0291\u0292\7P\2\2\u0292\u0293\5b\62"+ - "\2\u0293\u0294\7Q\2\2\u0294\u0296\3\2\2\2\u0295\u027c\3\2\2\2\u0295\u027d"+ - "\3\2\2\2\u0295\u027e\3\2\2\2\u0295\u0280\3\2\2\2\u0295\u0284\3\2\2\2\u0295"+ - "\u0285\3\2\2\2\u0295\u0289\3\2\2\2\u0295\u028d\3\2\2\2\u0295\u0291\3\2"+ - "\2\2\u0296O\3\2\2\2\u0297\u0298\t\f\2\2\u0298Q\3\2\2\2\u0299\u029a\t\r"+ - "\2\2\u029aS\3\2\2\2\u029b\u029c\5X-\2\u029cU\3\2\2\2\u029d\u029e\5X-\2"+ - "\u029e\u029f\7^\2\2\u029f\u02a1\3\2\2\2\u02a0\u029d\3\2\2\2\u02a1\u02a4"+ - "\3\2\2\2\u02a2\u02a0\3\2\2\2\u02a2\u02a3\3\2\2\2\u02a3\u02a5\3\2\2\2\u02a4"+ - "\u02a2\3\2\2\2\u02a5\u02a6\5X-\2\u02a6W\3\2\2\2\u02a7\u02aa\5\\/\2\u02a8"+ - "\u02aa\5^\60\2\u02a9\u02a7\3\2\2\2\u02a9\u02a8\3\2\2\2\u02aaY\3\2\2\2"+ - "\u02ab\u02ac\5X-\2\u02ac\u02ad\7\6\2\2\u02ad\u02af\3\2\2\2\u02ae\u02ab"+ - "\3\2\2\2\u02ae\u02af\3\2\2\2\u02af\u02b0\3\2\2\2\u02b0\u02b8\7e\2\2\u02b1"+ - "\u02b2\5X-\2\u02b2\u02b3\7\6\2\2\u02b3\u02b5\3\2\2\2\u02b4\u02b1\3\2\2"+ - "\2\u02b4\u02b5\3\2\2\2\u02b5\u02b6\3\2\2\2\u02b6\u02b8\5X-\2\u02b7\u02ae"+ - "\3\2\2\2\u02b7\u02b4\3\2\2\2\u02b8[\3\2\2\2\u02b9\u02bc\7f\2\2\u02ba\u02bc"+ - "\7g\2\2\u02bb\u02b9\3\2\2\2\u02bb\u02ba\3\2\2\2\u02bc]\3\2\2\2\u02bd\u02c1"+ - "\7c\2\2\u02be\u02c1\5d\63\2\u02bf\u02c1\7d\2\2\u02c0\u02bd\3\2\2\2\u02c0"+ - "\u02be\3\2\2\2\u02c0\u02bf\3\2\2\2\u02c1_\3\2\2\2\u02c2\u02c5\7b\2\2\u02c3"+ - "\u02c5\7a\2\2\u02c4\u02c2\3\2\2\2\u02c4\u02c3\3\2\2\2\u02c5a\3\2\2\2\u02c6"+ - "\u02c7\t\16\2\2\u02c7c\3\2\2\2\u02c8\u02c9\t\17\2\2\u02c9e\3\2\2\2`uw"+ - "{\u0084\u0086\u008a\u0091\u0098\u009d\u00a2\u00ac\u00b0\u00b8\u00bb\u00c1"+ - "\u00c6\u00c9\u00d0\u00d8\u00db\u00e7\u00ea\u00ed\u00f4\u00fb\u00ff\u0103"+ - "\u010a\u010e\u0112\u0117\u011b\u0123\u0127\u012e\u0139\u013c\u0140\u014c"+ - "\u014f\u0155\u015c\u0163\u0166\u016a\u016e\u0172\u0174\u017f\u0184\u0188"+ - "\u018b\u0191\u0194\u019a\u019d\u019f\u01c2\u01ca\u01cc\u01d3\u01d8\u01db"+ - "\u01e3\u01ec\u01f2\u01fa\u01ff\u0205\u0208\u020f\u0217\u021d\u0229\u022b"+ - "\u0234\u0241\u0248\u0256\u0264\u0269\u0270\u0273\u027a\u0282\u0295\u02a2"+ - "\u02a9\u02ae\u02b4\u02b7\u02bb\u02c0\u02c4"; + "\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u01c7"+ + "\n\30\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u01cf\n\30\f\30\16\30\u01d2\13"+ + "\30\3\31\3\31\7\31\u01d6\n\31\f\31\16\31\u01d9\13\31\3\32\3\32\5\32\u01dd"+ + "\n\32\3\33\5\33\u01e0\n\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u01e8\n"+ + "\33\3\33\3\33\3\33\3\33\3\33\7\33\u01ef\n\33\f\33\16\33\u01f2\13\33\3"+ + "\33\3\33\3\33\5\33\u01f7\n\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u01ff"+ + "\n\33\3\33\3\33\3\33\5\33\u0204\n\33\3\33\3\33\3\33\3\33\5\33\u020a\n"+ + "\33\3\33\5\33\u020d\n\33\3\34\3\34\3\34\3\35\3\35\5\35\u0214\n\35\3\36"+ + "\3\36\3\36\3\36\3\36\3\36\5\36\u021c\n\36\3\37\3\37\3\37\3\37\5\37\u0222"+ + "\n\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\7\37\u022e\n\37"+ + "\f\37\16\37\u0231\13\37\3 \3 \3 \3 \3 \3 \5 \u0239\n \3 \3 \3 \3 \3 \3"+ + " \3 \3 \3 \3 \3 \5 \u0246\n \3!\3!\3!\3!\3!\5!\u024d\n!\3\"\3\"\3\"\3"+ + "\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\5#\u025b\n#\3$\3$\3$\3$\3$\3$\3$\3%\3%\3"+ + "%\3%\3%\5%\u0269\n%\3&\3&\3&\5&\u026e\n&\3&\3&\3&\7&\u0273\n&\f&\16&\u0276"+ + "\13&\5&\u0278\n&\3&\3&\3\'\3\'\3\'\5\'\u027f\n\'\3(\3(\3(\3(\6(\u0285"+ + "\n(\r(\16(\u0286\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\5"+ + "(\u029a\n(\3)\3)\3*\3*\3+\3+\3,\3,\3,\7,\u02a5\n,\f,\16,\u02a8\13,\3,"+ + "\3,\3-\3-\5-\u02ae\n-\3.\3.\3.\5.\u02b3\n.\3.\3.\3.\3.\5.\u02b9\n.\3."+ + "\5.\u02bc\n.\3/\3/\5/\u02c0\n/\3\60\3\60\3\60\5\60\u02c5\n\60\3\61\3\61"+ + "\5\61\u02c9\n\61\3\62\3\62\3\63\3\63\3\63\2\4.<\64\2\4\6\b\n\f\16\20\22"+ + "\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BDFHJLNPRTVXZ\\^`bd\2\21\b"+ + "\2\7\7\t\t\31\31..\65\6599\4\2##EE\4\2\t\t\65\65\4\2 &&\3\2\25\26\4\2"+ + "\7\7dd\4\2\r\r\25\25\4\2\36\36**\4\2\7\7\27\27\3\2[\\\3\2]_\3\2UZ\4\2"+ + "\35\35FF\3\2bc\20\2\b\t\22\24\31\31\33\33\37\37\"#..\65\659;=?ABDEGHJ"+ + "J\u0325\2f\3\2\2\2\4i\3\2\2\2\6\u00d0\3\2\2\2\b\u00db\3\2\2\2\n\u00df"+ + "\3\2\2\2\f\u00f4\3\2\2\2\16\u00fb\3\2\2\2\20\u00fd\3\2\2\2\22\u0105\3"+ + "\2\2\2\24\u0121\3\2\2\2\26\u012b\3\2\2\2\30\u0135\3\2\2\2\32\u0144\3\2"+ + "\2\2\34\u0146\3\2\2\2\36\u014c\3\2\2\2 \u014e\3\2\2\2\"\u0155\3\2\2\2"+ + "$\u0167\3\2\2\2&\u0178\3\2\2\2(\u0188\3\2\2\2*\u01a3\3\2\2\2,\u01a5\3"+ + "\2\2\2.\u01c6\3\2\2\2\60\u01d7\3\2\2\2\62\u01da\3\2\2\2\64\u020c\3\2\2"+ + "\2\66\u020e\3\2\2\28\u0211\3\2\2\2:\u021b\3\2\2\2<\u0221\3\2\2\2>\u0245"+ + "\3\2\2\2@\u024c\3\2\2\2B\u024e\3\2\2\2D\u025a\3\2\2\2F\u025c\3\2\2\2H"+ + "\u0268\3\2\2\2J\u026a\3\2\2\2L\u027e\3\2\2\2N\u0299\3\2\2\2P\u029b\3\2"+ + "\2\2R\u029d\3\2\2\2T\u029f\3\2\2\2V\u02a6\3\2\2\2X\u02ad\3\2\2\2Z\u02bb"+ + "\3\2\2\2\\\u02bf\3\2\2\2^\u02c4\3\2\2\2`\u02c8\3\2\2\2b\u02ca\3\2\2\2"+ + "d\u02cc\3\2\2\2fg\5\6\4\2gh\7\2\2\3h\3\3\2\2\2ij\5,\27\2jk\7\2\2\3k\5"+ + "\3\2\2\2l\u00d1\5\b\5\2m{\7\33\2\2nw\7\3\2\2op\7;\2\2pv\t\2\2\2qr\7\37"+ + "\2\2rv\t\3\2\2st\7J\2\2tv\5R*\2uo\3\2\2\2uq\3\2\2\2us\3\2\2\2vy\3\2\2"+ + "\2wu\3\2\2\2wx\3\2\2\2xz\3\2\2\2yw\3\2\2\2z|\7\4\2\2{n\3\2\2\2{|\3\2\2"+ + "\2|}\3\2\2\2}\u00d1\5\6\4\2~\u008a\7\24\2\2\177\u0086\7\3\2\2\u0080\u0081"+ + "\7;\2\2\u0081\u0085\t\4\2\2\u0082\u0083\7\37\2\2\u0083\u0085\t\3\2\2\u0084"+ + "\u0080\3\2\2\2\u0084\u0082\3\2\2\2\u0085\u0088\3\2\2\2\u0086\u0084\3\2"+ + "\2\2\u0086\u0087\3\2\2\2\u0087\u0089\3\2\2\2\u0088\u0086\3\2\2\2\u0089"+ + "\u008b\7\4\2\2\u008a\177\3\2\2\2\u008a\u008b\3\2\2\2\u008b\u008c\3\2\2"+ + "\2\u008c\u00d1\5\6\4\2\u008d\u008e\7A\2\2\u008e\u0091\7D\2\2\u008f\u0092"+ + "\5\66\34\2\u0090\u0092\5Z.\2\u0091\u008f\3\2\2\2\u0091\u0090\3\2\2\2\u0091"+ + "\u0092\3\2\2\2\u0092\u00d1\3\2\2\2\u0093\u0094\7A\2\2\u0094\u0095\7\23"+ + "\2\2\u0095\u0098\t\5\2\2\u0096\u0099\5\66\34\2\u0097\u0099\5Z.\2\u0098"+ + "\u0096\3\2\2\2\u0098\u0097\3\2\2\2\u0099\u00d1\3\2\2\2\u009a\u009d\t\6"+ + "\2\2\u009b\u009e\5\66\34\2\u009c\u009e\5Z.\2\u009d\u009b\3\2\2\2\u009d"+ + "\u009c\3\2\2\2\u009e\u00d1\3\2\2\2\u009f\u00a0\7A\2\2\u00a0\u00a2\7\""+ + "\2\2\u00a1\u00a3\5\66\34\2\u00a2\u00a1\3\2\2\2\u00a2\u00a3\3\2\2\2\u00a3"+ + "\u00d1\3\2\2\2\u00a4\u00a5\7A\2\2\u00a5\u00d1\7?\2\2\u00a6\u00a7\7B\2"+ + "\2\u00a7\u00d1\7\22\2\2\u00a8\u00a9\7B\2\2\u00a9\u00ac\7D\2\2\u00aa\u00ab"+ + "\7\21\2\2\u00ab\u00ad\5\66\34\2\u00ac\u00aa\3\2\2\2\u00ac\u00ad\3\2\2"+ + "\2\u00ad\u00b0\3\2\2\2\u00ae\u00b1\5\66\34\2\u00af\u00b1\5Z.\2\u00b0\u00ae"+ + "\3\2\2\2\u00b0\u00af\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1\u00bb\3\2\2\2\u00b2"+ + "\u00b3\7G\2\2\u00b3\u00b8\5b\62\2\u00b4\u00b5\7\5\2\2\u00b5\u00b7\5b\62"+ + "\2\u00b6\u00b4\3\2\2\2\u00b7\u00ba\3\2\2\2\u00b8\u00b6\3\2\2\2\u00b8\u00b9"+ + "\3\2\2\2\u00b9\u00bc\3\2\2\2\u00ba\u00b8\3\2\2\2\u00bb\u00b2\3\2\2\2\u00bb"+ + "\u00bc\3\2\2\2\u00bc\u00d1\3\2\2\2\u00bd\u00be\7B\2\2\u00be\u00c1\7\23"+ + "\2\2\u00bf\u00c0\7\21\2\2\u00c0\u00c2\5b\62\2\u00c1\u00bf\3\2\2\2\u00c1"+ + "\u00c2\3\2\2\2\u00c2\u00c6\3\2\2\2\u00c3\u00c4\7C\2\2\u00c4\u00c7\5\66"+ + "\34\2\u00c5\u00c7\5Z.\2\u00c6\u00c3\3\2\2\2\u00c6\u00c5\3\2\2\2\u00c6"+ + "\u00c7\3\2\2\2\u00c7\u00c9\3\2\2\2\u00c8\u00ca\5\66\34\2\u00c9\u00c8\3"+ + "\2\2\2\u00c9\u00ca\3\2\2\2\u00ca\u00d1\3\2\2\2\u00cb\u00cc\7B\2\2\u00cc"+ + "\u00d1\7H\2\2\u00cd\u00ce\7B\2\2\u00ce\u00cf\7C\2\2\u00cf\u00d1\7H\2\2"+ + "\u00d0l\3\2\2\2\u00d0m\3\2\2\2\u00d0~\3\2\2\2\u00d0\u008d\3\2\2\2\u00d0"+ + "\u0093\3\2\2\2\u00d0\u009a\3\2\2\2\u00d0\u009f\3\2\2\2\u00d0\u00a4\3\2"+ + "\2\2\u00d0\u00a6\3\2\2\2\u00d0\u00a8\3\2\2\2\u00d0\u00bd\3\2\2\2\u00d0"+ + "\u00cb\3\2\2\2\u00d0\u00cd\3\2\2\2\u00d1\7\3\2\2\2\u00d2\u00d3\7L\2\2"+ + "\u00d3\u00d8\5\34\17\2\u00d4\u00d5\7\5\2\2\u00d5\u00d7\5\34\17\2\u00d6"+ + "\u00d4\3\2\2\2\u00d7\u00da\3\2\2\2\u00d8\u00d6\3\2\2\2\u00d8\u00d9\3\2"+ + "\2\2\u00d9\u00dc\3\2\2\2\u00da\u00d8\3\2\2\2\u00db\u00d2\3\2\2\2\u00db"+ + "\u00dc\3\2\2\2\u00dc\u00dd\3\2\2\2\u00dd\u00de\5\n\6\2\u00de\t\3\2\2\2"+ + "\u00df\u00ea\5\16\b\2\u00e0\u00e1\7\67\2\2\u00e1\u00e2\7\17\2\2\u00e2"+ + "\u00e7\5\20\t\2\u00e3\u00e4\7\5\2\2\u00e4\u00e6\5\20\t\2\u00e5\u00e3\3"+ + "\2\2\2\u00e6\u00e9\3\2\2\2\u00e7\u00e5\3\2\2\2\u00e7\u00e8\3\2\2\2\u00e8"+ + "\u00eb\3\2\2\2\u00e9\u00e7\3\2\2\2\u00ea\u00e0\3\2\2\2\u00ea\u00eb\3\2"+ + "\2\2\u00eb\u00ed\3\2\2\2\u00ec\u00ee\5\f\7\2\u00ed\u00ec\3\2\2\2\u00ed"+ + "\u00ee\3\2\2\2\u00ee\13\3\2\2\2\u00ef\u00f0\7-\2\2\u00f0\u00f5\t\7\2\2"+ + "\u00f1\u00f2\7O\2\2\u00f2\u00f3\t\7\2\2\u00f3\u00f5\7T\2\2\u00f4\u00ef"+ + "\3\2\2\2\u00f4\u00f1\3\2\2\2\u00f5\r\3\2\2\2\u00f6\u00fc\5\22\n\2\u00f7"+ + "\u00f8\7\3\2\2\u00f8\u00f9\5\n\6\2\u00f9\u00fa\7\4\2\2\u00fa\u00fc\3\2"+ + "\2\2\u00fb\u00f6\3\2\2\2\u00fb\u00f7\3\2\2\2\u00fc\17\3\2\2\2\u00fd\u00ff"+ + "\5,\27\2\u00fe\u0100\t\b\2\2\u00ff\u00fe\3\2\2\2\u00ff\u0100\3\2\2\2\u0100"+ + "\u0103\3\2\2\2\u0101\u0102\7\63\2\2\u0102\u0104\t\t\2\2\u0103\u0101\3"+ + "\2\2\2\u0103\u0104\3\2\2\2\u0104\21\3\2\2\2\u0105\u0107\7@\2\2\u0106\u0108"+ + "\5\36\20\2\u0107\u0106\3\2\2\2\u0107\u0108\3\2\2\2\u0108\u0109\3\2\2\2"+ + "\u0109\u010e\5 \21\2\u010a\u010b\7\5\2\2\u010b\u010d\5 \21\2\u010c\u010a"+ + "\3\2\2\2\u010d\u0110\3\2\2\2\u010e\u010c\3\2\2\2\u010e\u010f\3\2\2\2\u010f"+ + "\u0112\3\2\2\2\u0110\u010e\3\2\2\2\u0111\u0113\5\24\13\2\u0112\u0111\3"+ + "\2\2\2\u0112\u0113\3\2\2\2\u0113\u0116\3\2\2\2\u0114\u0115\7K\2\2\u0115"+ + "\u0117\5.\30\2\u0116\u0114\3\2\2\2\u0116\u0117\3\2\2\2\u0117\u011b\3\2"+ + "\2\2\u0118\u0119\7$\2\2\u0119\u011a\7\17\2\2\u011a\u011c\5\26\f\2\u011b"+ + "\u0118\3\2\2\2\u011b\u011c\3\2\2\2\u011c\u011f\3\2\2\2\u011d\u011e\7%"+ + "\2\2\u011e\u0120\5.\30\2\u011f\u011d\3\2\2\2\u011f\u0120\3\2\2\2\u0120"+ + "\23\3\2\2\2\u0121\u0122\7 \2\2\u0122\u0127\5\"\22\2\u0123\u0124\7\5\2"+ + "\2\u0124\u0126\5\"\22\2\u0125\u0123\3\2\2\2\u0126\u0129\3\2\2\2\u0127"+ + "\u0125\3\2\2\2\u0127\u0128\3\2\2\2\u0128\25\3\2\2\2\u0129\u0127\3\2\2"+ + "\2\u012a\u012c\5\36\20\2\u012b\u012a\3\2\2\2\u012b\u012c\3\2\2\2\u012c"+ + "\u012d\3\2\2\2\u012d\u0132\5\30\r\2\u012e\u012f\7\5\2\2\u012f\u0131\5"+ + "\30\r\2\u0130\u012e\3\2\2\2\u0131\u0134\3\2\2\2\u0132\u0130\3\2\2\2\u0132"+ + "\u0133\3\2\2\2\u0133\27\3\2\2\2\u0134\u0132\3\2\2\2\u0135\u0136\5\32\16"+ + "\2\u0136\31\3\2\2\2\u0137\u0140\7\3\2\2\u0138\u013d\5,\27\2\u0139\u013a"+ + "\7\5\2\2\u013a\u013c\5,\27\2\u013b\u0139\3\2\2\2\u013c\u013f\3\2\2\2\u013d"+ + "\u013b\3\2\2\2\u013d\u013e\3\2\2\2\u013e\u0141\3\2\2\2\u013f\u013d\3\2"+ + "\2\2\u0140\u0138\3\2\2\2\u0140\u0141\3\2\2\2\u0141\u0142\3\2\2\2\u0142"+ + "\u0145\7\4\2\2\u0143\u0145\5,\27\2\u0144\u0137\3\2\2\2\u0144\u0143\3\2"+ + "\2\2\u0145\33\3\2\2\2\u0146\u0147\5X-\2\u0147\u0148\7\f\2\2\u0148\u0149"+ + "\7\3\2\2\u0149\u014a\5\n\6\2\u014a\u014b\7\4\2\2\u014b\35\3\2\2\2\u014c"+ + "\u014d\t\n\2\2\u014d\37\3\2\2\2\u014e\u0153\5,\27\2\u014f\u0151\7\f\2"+ + "\2\u0150\u014f\3\2\2\2\u0150\u0151\3\2\2\2\u0151\u0152\3\2\2\2\u0152\u0154"+ + "\5X-\2\u0153\u0150\3\2\2\2\u0153\u0154\3\2\2\2\u0154!\3\2\2\2\u0155\u0159"+ + "\5*\26\2\u0156\u0158\5$\23\2\u0157\u0156\3\2\2\2\u0158\u015b\3\2\2\2\u0159"+ + "\u0157\3\2\2\2\u0159\u015a\3\2\2\2\u015a#\3\2\2\2\u015b\u0159\3\2\2\2"+ + "\u015c\u015d\5&\24\2\u015d\u015e\7)\2\2\u015e\u0160\5*\26\2\u015f\u0161"+ + "\5(\25\2\u0160\u015f\3\2\2\2\u0160\u0161\3\2\2\2\u0161\u0168\3\2\2\2\u0162"+ + "\u0163\7\60\2\2\u0163\u0164\5&\24\2\u0164\u0165\7)\2\2\u0165\u0166\5*"+ + "\26\2\u0166\u0168\3\2\2\2\u0167\u015c\3\2\2\2\u0167\u0162\3\2\2\2\u0168"+ + "%\3\2\2\2\u0169\u016b\7\'\2\2\u016a\u0169\3\2\2\2\u016a\u016b\3\2\2\2"+ + "\u016b\u0179\3\2\2\2\u016c\u016e\7+\2\2\u016d\u016f\78\2\2\u016e\u016d"+ + "\3\2\2\2\u016e\u016f\3\2\2\2\u016f\u0179\3\2\2\2\u0170\u0172\7<\2\2\u0171"+ + "\u0173\78\2\2\u0172\u0171\3\2\2\2\u0172\u0173\3\2\2\2\u0173\u0179\3\2"+ + "\2\2\u0174\u0176\7!\2\2\u0175\u0177\78\2\2\u0176\u0175\3\2\2\2\u0176\u0177"+ + "\3\2\2\2\u0177\u0179\3\2\2\2\u0178\u016a\3\2\2\2\u0178\u016c\3\2\2\2\u0178"+ + "\u0170\3\2\2\2\u0178\u0174\3\2\2\2\u0179\'\3\2\2\2\u017a\u017b\7\64\2"+ + "\2\u017b\u0189\5.\30\2\u017c\u017d\7I\2\2\u017d\u017e\7\3\2\2\u017e\u0183"+ + "\5X-\2\u017f\u0180\7\5\2\2\u0180\u0182\5X-\2\u0181\u017f\3\2\2\2\u0182"+ + "\u0185\3\2\2\2\u0183\u0181\3\2\2\2\u0183\u0184\3\2\2\2\u0184\u0186\3\2"+ + "\2\2\u0185\u0183\3\2\2\2\u0186\u0187\7\4\2\2\u0187\u0189\3\2\2\2\u0188"+ + "\u017a\3\2\2\2\u0188\u017c\3\2\2\2\u0189)\3\2\2\2\u018a\u018f\5Z.\2\u018b"+ + "\u018d\7\f\2\2\u018c\u018b\3\2\2\2\u018c\u018d\3\2\2\2\u018d\u018e\3\2"+ + "\2\2\u018e\u0190\5V,\2\u018f\u018c\3\2\2\2\u018f\u0190\3\2\2\2\u0190\u01a4"+ + "\3\2\2\2\u0191\u0192\7\3\2\2\u0192\u0193\5\n\6\2\u0193\u0198\7\4\2\2\u0194"+ + "\u0196\7\f\2\2\u0195\u0194\3\2\2\2\u0195\u0196\3\2\2\2\u0196\u0197\3\2"+ + "\2\2\u0197\u0199\5V,\2\u0198\u0195\3\2\2\2\u0198\u0199\3\2\2\2\u0199\u01a4"+ + "\3\2\2\2\u019a\u019b\7\3\2\2\u019b\u019c\5\"\22\2\u019c\u01a1\7\4\2\2"+ + "\u019d\u019f\7\f\2\2\u019e\u019d\3\2\2\2\u019e\u019f\3\2\2\2\u019f\u01a0"+ + "\3\2\2\2\u01a0\u01a2\5V,\2\u01a1\u019e\3\2\2\2\u01a1\u01a2\3\2\2\2\u01a2"+ + "\u01a4\3\2\2\2\u01a3\u018a\3\2\2\2\u01a3\u0191\3\2\2\2\u01a3\u019a\3\2"+ + "\2\2\u01a4+\3\2\2\2\u01a5\u01a6\5.\30\2\u01a6-\3\2\2\2\u01a7\u01a8\b\30"+ + "\1\2\u01a8\u01a9\7\61\2\2\u01a9\u01c7\5.\30\n\u01aa\u01ab\7\32\2\2\u01ab"+ + "\u01ac\7\3\2\2\u01ac\u01ad\5\b\5\2\u01ad\u01ae\7\4\2\2\u01ae\u01c7\3\2"+ + "\2\2\u01af\u01b0\7>\2\2\u01b0\u01b1\7\3\2\2\u01b1\u01b2\5b\62\2\u01b2"+ + "\u01b3\5\60\31\2\u01b3\u01b4\7\4\2\2\u01b4\u01c7\3\2\2\2\u01b5\u01b6\7"+ + "/\2\2\u01b6\u01b7\7\3\2\2\u01b7\u01b8\5V,\2\u01b8\u01b9\7\5\2\2\u01b9"+ + "\u01ba\5b\62\2\u01ba\u01bb\5\60\31\2\u01bb\u01bc\7\4\2\2\u01bc\u01c7\3"+ + "\2\2\2\u01bd\u01be\7/\2\2\u01be\u01bf\7\3\2\2\u01bf\u01c0\5b\62\2\u01c0"+ + "\u01c1\7\5\2\2\u01c1\u01c2\5b\62\2\u01c2\u01c3\5\60\31\2\u01c3\u01c4\7"+ + "\4\2\2\u01c4\u01c7\3\2\2\2\u01c5\u01c7\5\62\32\2\u01c6\u01a7\3\2\2\2\u01c6"+ + "\u01aa\3\2\2\2\u01c6\u01af\3\2\2\2\u01c6\u01b5\3\2\2\2\u01c6\u01bd\3\2"+ + "\2\2\u01c6\u01c5\3\2\2\2\u01c7\u01d0\3\2\2\2\u01c8\u01c9\f\4\2\2\u01c9"+ + "\u01ca\7\n\2\2\u01ca\u01cf\5.\30\5\u01cb\u01cc\f\3\2\2\u01cc\u01cd\7\66"+ + "\2\2\u01cd\u01cf\5.\30\4\u01ce\u01c8\3\2\2\2\u01ce\u01cb\3\2\2\2\u01cf"+ + "\u01d2\3\2\2\2\u01d0\u01ce\3\2\2\2\u01d0\u01d1\3\2\2\2\u01d1/\3\2\2\2"+ + "\u01d2\u01d0\3\2\2\2\u01d3\u01d4\7\5\2\2\u01d4\u01d6\5b\62\2\u01d5\u01d3"+ + "\3\2\2\2\u01d6\u01d9\3\2\2\2\u01d7\u01d5\3\2\2\2\u01d7\u01d8\3\2\2\2\u01d8"+ + "\61\3\2\2\2\u01d9\u01d7\3\2\2\2\u01da\u01dc\5<\37\2\u01db\u01dd\5\64\33"+ + "\2\u01dc\u01db\3\2\2\2\u01dc\u01dd\3\2\2\2\u01dd\63\3\2\2\2\u01de\u01e0"+ + "\7\61\2\2\u01df\u01de\3\2\2\2\u01df\u01e0\3\2\2\2\u01e0\u01e1\3\2\2\2"+ + "\u01e1\u01e2\7\16\2\2\u01e2\u01e3\5<\37\2\u01e3\u01e4\7\n\2\2\u01e4\u01e5"+ + "\5<\37\2\u01e5\u020d\3\2\2\2\u01e6\u01e8\7\61\2\2\u01e7\u01e6\3\2\2\2"+ + "\u01e7\u01e8\3\2\2\2\u01e8\u01e9\3\2\2\2\u01e9\u01ea\7&\2\2\u01ea\u01eb"+ + "\7\3\2\2\u01eb\u01f0\5,\27\2\u01ec\u01ed\7\5\2\2\u01ed\u01ef\5,\27\2\u01ee"+ + "\u01ec\3\2\2\2\u01ef\u01f2\3\2\2\2\u01f0\u01ee\3\2\2\2\u01f0\u01f1\3\2"+ + "\2\2\u01f1\u01f3\3\2\2\2\u01f2\u01f0\3\2\2\2\u01f3\u01f4\7\4\2\2\u01f4"+ + "\u020d\3\2\2\2\u01f5\u01f7\7\61\2\2\u01f6\u01f5\3\2\2\2\u01f6\u01f7\3"+ + "\2\2\2\u01f7\u01f8\3\2\2\2\u01f8\u01f9\7&\2\2\u01f9\u01fa\7\3\2\2\u01fa"+ + "\u01fb\5\b\5\2\u01fb\u01fc\7\4\2\2\u01fc\u020d\3\2\2\2\u01fd\u01ff\7\61"+ + "\2\2\u01fe\u01fd\3\2\2\2\u01fe\u01ff\3\2\2\2\u01ff\u0200\3\2\2\2\u0200"+ + "\u0201\7,\2\2\u0201\u020d\58\35\2\u0202\u0204\7\61\2\2\u0203\u0202\3\2"+ + "\2\2\u0203\u0204\3\2\2\2\u0204\u0205\3\2\2\2\u0205\u0206\7=\2\2\u0206"+ + "\u020d\5b\62\2\u0207\u0209\7(\2\2\u0208\u020a\7\61\2\2\u0209\u0208\3\2"+ + "\2\2\u0209\u020a\3\2\2\2\u020a\u020b\3\2\2\2\u020b\u020d\7\62\2\2\u020c"+ + "\u01df\3\2\2\2\u020c\u01e7\3\2\2\2\u020c\u01f6\3\2\2\2\u020c\u01fe\3\2"+ + "\2\2\u020c\u0203\3\2\2\2\u020c\u0207\3\2\2\2\u020d\65\3\2\2\2\u020e\u020f"+ + "\7,\2\2\u020f\u0210\58\35\2\u0210\67\3\2\2\2\u0211\u0213\5b\62\2\u0212"+ + "\u0214\5:\36\2\u0213\u0212\3\2\2\2\u0213\u0214\3\2\2\2\u02149\3\2\2\2"+ + "\u0215\u0216\7\30\2\2\u0216\u021c\5b\62\2\u0217\u0218\7M\2\2\u0218\u0219"+ + "\5b\62\2\u0219\u021a\7T\2\2\u021a\u021c\3\2\2\2\u021b\u0215\3\2\2\2\u021b"+ + "\u0217\3\2\2\2\u021c;\3\2\2\2\u021d\u021e\b\37\1\2\u021e\u0222\5> \2\u021f"+ + "\u0220\t\13\2\2\u0220\u0222\5<\37\6\u0221\u021d\3\2\2\2\u0221\u021f\3"+ + "\2\2\2\u0222\u022f\3\2\2\2\u0223\u0224\f\5\2\2\u0224\u0225\t\f\2\2\u0225"+ + "\u022e\5<\37\6\u0226\u0227\f\4\2\2\u0227\u0228\t\13\2\2\u0228\u022e\5"+ + "<\37\5\u0229\u022a\f\3\2\2\u022a\u022b\5P)\2\u022b\u022c\5<\37\4\u022c"+ + "\u022e\3\2\2\2\u022d\u0223\3\2\2\2\u022d\u0226\3\2\2\2\u022d\u0229\3\2"+ + "\2\2\u022e\u0231\3\2\2\2\u022f\u022d\3\2\2\2\u022f\u0230\3\2\2\2\u0230"+ + "=\3\2\2\2\u0231\u022f\3\2\2\2\u0232\u0246\5@!\2\u0233\u0246\5D#\2\u0234"+ + "\u0246\5N(\2\u0235\u0236\5V,\2\u0236\u0237\7a\2\2\u0237\u0239\3\2\2\2"+ + "\u0238\u0235\3\2\2\2\u0238\u0239\3\2\2\2\u0239\u023a\3\2\2\2\u023a\u0246"+ + "\7]\2\2\u023b\u0246\5H%\2\u023c\u023d\7\3\2\2\u023d\u023e\5\b\5\2\u023e"+ + "\u023f\7\4\2\2\u023f\u0246\3\2\2\2\u0240\u0246\5V,\2\u0241\u0242\7\3\2"+ + "\2\u0242\u0243\5,\27\2\u0243\u0244\7\4\2\2\u0244\u0246\3\2\2\2\u0245\u0232"+ + "\3\2\2\2\u0245\u0233\3\2\2\2\u0245\u0234\3\2\2\2\u0245\u0238\3\2\2\2\u0245"+ + "\u023b\3\2\2\2\u0245\u023c\3\2\2\2\u0245\u0240\3\2\2\2\u0245\u0241\3\2"+ + "\2\2\u0246?\3\2\2\2\u0247\u024d\5B\"\2\u0248\u0249\7N\2\2\u0249\u024a"+ + "\5B\"\2\u024a\u024b\7T\2\2\u024b\u024d\3\2\2\2\u024c\u0247\3\2\2\2\u024c"+ + "\u0248\3\2\2\2\u024dA\3\2\2\2\u024e\u024f\7\20\2\2\u024f\u0250\7\3\2\2"+ + "\u0250\u0251\5,\27\2\u0251\u0252\7\f\2\2\u0252\u0253\5T+\2\u0253\u0254"+ + "\7\4\2\2\u0254C\3\2\2\2\u0255\u025b\5F$\2\u0256\u0257\7N\2\2\u0257\u0258"+ + "\5F$\2\u0258\u0259\7T\2\2\u0259\u025b\3\2\2\2\u025a\u0255\3\2\2\2\u025a"+ + "\u0256\3\2\2\2\u025bE\3\2\2\2\u025c\u025d\7\34\2\2\u025d\u025e\7\3\2\2"+ + "\u025e\u025f\5X-\2\u025f\u0260\7 \2\2\u0260\u0261\5<\37\2\u0261\u0262"+ + "\7\4\2\2\u0262G\3\2\2\2\u0263\u0269\5J&\2\u0264\u0265\7N\2\2\u0265\u0266"+ + "\5J&\2\u0266\u0267\7T\2\2\u0267\u0269\3\2\2\2\u0268\u0263\3\2\2\2\u0268"+ + "\u0264\3\2\2\2\u0269I\3\2\2\2\u026a\u026b\5L\'\2\u026b\u0277\7\3\2\2\u026c"+ + "\u026e\5\36\20\2\u026d\u026c\3\2\2\2\u026d\u026e\3\2\2\2\u026e\u026f\3"+ + "\2\2\2\u026f\u0274\5,\27\2\u0270\u0271\7\5\2\2\u0271\u0273\5,\27\2\u0272"+ + "\u0270\3\2\2\2\u0273\u0276\3\2\2\2\u0274\u0272\3\2\2\2\u0274\u0275\3\2"+ + "\2\2\u0275\u0278\3\2\2\2\u0276\u0274\3\2\2\2\u0277\u026d\3\2\2\2\u0277"+ + "\u0278\3\2\2\2\u0278\u0279\3\2\2\2\u0279\u027a\7\4\2\2\u027aK\3\2\2\2"+ + "\u027b\u027f\7+\2\2\u027c\u027f\7<\2\2\u027d\u027f\5X-\2\u027e\u027b\3"+ + "\2\2\2\u027e\u027c\3\2\2\2\u027e\u027d\3\2\2\2\u027fM\3\2\2\2\u0280\u029a"+ + "\7\62\2\2\u0281\u029a\5`\61\2\u0282\u029a\5R*\2\u0283\u0285\7c\2\2\u0284"+ + "\u0283\3\2\2\2\u0285\u0286\3\2\2\2\u0286\u0284\3\2\2\2\u0286\u0287\3\2"+ + "\2\2\u0287\u029a\3\2\2\2\u0288\u029a\7b\2\2\u0289\u028a\7P\2\2\u028a\u028b"+ + "\5b\62\2\u028b\u028c\7T\2\2\u028c\u029a\3\2\2\2\u028d\u028e\7Q\2\2\u028e"+ + "\u028f\5b\62\2\u028f\u0290\7T\2\2\u0290\u029a\3\2\2\2\u0291\u0292\7R\2"+ + "\2\u0292\u0293\5b\62\2\u0293\u0294\7T\2\2\u0294\u029a\3\2\2\2\u0295\u0296"+ + "\7S\2\2\u0296\u0297\5b\62\2\u0297\u0298\7T\2\2\u0298\u029a\3\2\2\2\u0299"+ + "\u0280\3\2\2\2\u0299\u0281\3\2\2\2\u0299\u0282\3\2\2\2\u0299\u0284\3\2"+ + "\2\2\u0299\u0288\3\2\2\2\u0299\u0289\3\2\2\2\u0299\u028d\3\2\2\2\u0299"+ + "\u0291\3\2\2\2\u0299\u0295\3\2\2\2\u029aO\3\2\2\2\u029b\u029c\t\r\2\2"+ + "\u029cQ\3\2\2\2\u029d\u029e\t\16\2\2\u029eS\3\2\2\2\u029f\u02a0\5X-\2"+ + "\u02a0U\3\2\2\2\u02a1\u02a2\5X-\2\u02a2\u02a3\7a\2\2\u02a3\u02a5\3\2\2"+ + "\2\u02a4\u02a1\3\2\2\2\u02a5\u02a8\3\2\2\2\u02a6\u02a4\3\2\2\2\u02a6\u02a7"+ + "\3\2\2\2\u02a7\u02a9\3\2\2\2\u02a8\u02a6\3\2\2\2\u02a9\u02aa\5X-\2\u02aa"+ + "W\3\2\2\2\u02ab\u02ae\5\\/\2\u02ac\u02ae\5^\60\2\u02ad\u02ab\3\2\2\2\u02ad"+ + "\u02ac\3\2\2\2\u02aeY\3\2\2\2\u02af\u02b0\5X-\2\u02b0\u02b1\7\6\2\2\u02b1"+ + "\u02b3\3\2\2\2\u02b2\u02af\3\2\2\2\u02b2\u02b3\3\2\2\2\u02b3\u02b4\3\2"+ + "\2\2\u02b4\u02bc\7h\2\2\u02b5\u02b6\5X-\2\u02b6\u02b7\7\6\2\2\u02b7\u02b9"+ + "\3\2\2\2\u02b8\u02b5\3\2\2\2\u02b8\u02b9\3\2\2\2\u02b9\u02ba\3\2\2\2\u02ba"+ + "\u02bc\5X-\2\u02bb\u02b2\3\2\2\2\u02bb\u02b8\3\2\2\2\u02bc[\3\2\2\2\u02bd"+ + "\u02c0\7i\2\2\u02be\u02c0\7j\2\2\u02bf\u02bd\3\2\2\2\u02bf\u02be\3\2\2"+ + "\2\u02c0]\3\2\2\2\u02c1\u02c5\7f\2\2\u02c2\u02c5\5d\63\2\u02c3\u02c5\7"+ + "g\2\2\u02c4\u02c1\3\2\2\2\u02c4\u02c2\3\2\2\2\u02c4\u02c3\3\2\2\2\u02c5"+ + "_\3\2\2\2\u02c6\u02c9\7e\2\2\u02c7\u02c9\7d\2\2\u02c8\u02c6\3\2\2\2\u02c8"+ + "\u02c7\3\2\2\2\u02c9a\3\2\2\2\u02ca\u02cb\t\17\2\2\u02cbc\3\2\2\2\u02cc"+ + "\u02cd\t\20\2\2\u02cde\3\2\2\2auw{\u0084\u0086\u008a\u0091\u0098\u009d"+ + "\u00a2\u00ac\u00b0\u00b8\u00bb\u00c1\u00c6\u00c9\u00d0\u00d8\u00db\u00e7"+ + "\u00ea\u00ed\u00f4\u00fb\u00ff\u0103\u0107\u010e\u0112\u0116\u011b\u011f"+ + "\u0127\u012b\u0132\u013d\u0140\u0144\u0150\u0153\u0159\u0160\u0167\u016a"+ + "\u016e\u0172\u0176\u0178\u0183\u0188\u018c\u018f\u0195\u0198\u019e\u01a1"+ + "\u01a3\u01c6\u01ce\u01d0\u01d7\u01dc\u01df\u01e7\u01f0\u01f6\u01fe\u0203"+ + "\u0209\u020c\u0213\u021b\u0221\u022d\u022f\u0238\u0245\u024c\u025a\u0268"+ + "\u026d\u0274\u0277\u027e\u0286\u0299\u02a6\u02ad\u02b2\u02b8\u02bb\u02bf"+ + "\u02c4\u02c8"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java index 12b68ceee3336..806944e3a7905 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java @@ -32,15 +32,14 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeFunction; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeHistogramFunction; import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; -import org.elasticsearch.xpack.sql.expression.predicate.And; -import org.elasticsearch.xpack.sql.expression.predicate.BinaryPredicate; import org.elasticsearch.xpack.sql.expression.predicate.IsNotNull; -import org.elasticsearch.xpack.sql.expression.predicate.Not; -import org.elasticsearch.xpack.sql.expression.predicate.Or; import org.elasticsearch.xpack.sql.expression.predicate.Range; import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MatchQueryPredicate; import org.elasticsearch.xpack.sql.expression.predicate.fulltext.MultiMatchQueryPredicate; import org.elasticsearch.xpack.sql.expression.predicate.fulltext.StringQueryPredicate; +import org.elasticsearch.xpack.sql.expression.predicate.logical.And; +import org.elasticsearch.xpack.sql.expression.predicate.logical.Not; +import org.elasticsearch.xpack.sql.expression.predicate.logical.Or; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparison; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.GreaterThan; @@ -50,6 +49,7 @@ import org.elasticsearch.xpack.sql.expression.predicate.regex.Like; import org.elasticsearch.xpack.sql.expression.predicate.regex.LikePattern; import org.elasticsearch.xpack.sql.expression.predicate.regex.RLike; +import org.elasticsearch.xpack.sql.expression.predicate.regex.RegexMatch; import org.elasticsearch.xpack.sql.querydsl.agg.AggFilter; import org.elasticsearch.xpack.sql.querydsl.agg.AndAggFilter; import org.elasticsearch.xpack.sql.querydsl.agg.AvgAgg; @@ -394,10 +394,10 @@ static String field(AggregateFunction af) { // TODO: need to optimize on ngram // TODO: see whether escaping is needed - static class Likes extends ExpressionTranslator { + static class Likes extends ExpressionTranslator { @Override - protected QueryTranslation asQuery(BinaryPredicate e, boolean onAggs) { + protected QueryTranslation asQuery(RegexMatch e, boolean onAggs) { Query q = null; boolean inexact = true; String target = null; @@ -412,7 +412,7 @@ protected QueryTranslation asQuery(BinaryPredicate e, boolean onAggs) { } if (e instanceof Like) { - LikePattern p = ((Like) e).right(); + LikePattern p = ((Like) e).pattern(); if (inexact) { q = new QueryStringQuery(e.location(), p.asLuceneWildcard(), target); } @@ -459,10 +459,10 @@ protected QueryTranslation asQuery(MultiMatchQueryPredicate q, boolean onAggs) { } } - static class BinaryLogic extends ExpressionTranslator { + static class BinaryLogic extends ExpressionTranslator { @Override - protected QueryTranslation asQuery(BinaryPredicate e, boolean onAggs) { + protected QueryTranslation asQuery(org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogic e, boolean onAggs) { if (e instanceof And) { return and(e.location(), toQuery(e.left(), onAggs), toQuery(e.right(), onAggs)); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AggFilter.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AggFilter.java index 38f7f81946dd7..ea71156b0b05f 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AggFilter.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AggFilter.java @@ -5,20 +5,20 @@ */ package org.elasticsearch.xpack.sql.querydsl.agg; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; - import org.elasticsearch.script.Script; import org.elasticsearch.search.aggregations.PipelineAggregationBuilder; import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.sql.util.Check; +import java.util.Collection; +import java.util.Map; +import java.util.Objects; + import static org.elasticsearch.search.aggregations.pipeline.PipelineAggregatorBuilders.bucketSelector; public class AggFilter extends PipelineAgg { - private static final String BUCKET_SELECTOR_ID_PREFIX = "having"; + private static final String BUCKET_SELECTOR_ID_PREFIX = "having."; private final ScriptTemplate scriptTemplate; private final Map aggPaths; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AndAggFilter.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AndAggFilter.java index c2c980c856818..503c88ea7fc0c 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AndAggFilter.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AndAggFilter.java @@ -5,14 +5,7 @@ */ package org.elasticsearch.xpack.sql.querydsl.agg; -import org.elasticsearch.xpack.sql.expression.gen.script.Params; -import org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; -import org.elasticsearch.xpack.sql.type.DataType; - -import java.util.Locale; - -import static java.lang.String.format; +import org.elasticsearch.xpack.sql.expression.gen.script.Scripts; public class AndAggFilter extends AggFilter { @@ -21,12 +14,6 @@ public AndAggFilter(AggFilter left, AggFilter right) { } public AndAggFilter(String name, AggFilter left, AggFilter right) { - super(name, and(left.scriptTemplate(), right.scriptTemplate())); - } - - private static ScriptTemplate and(ScriptTemplate left, ScriptTemplate right) { - String template = format(Locale.ROOT, "( %s ) && ( %s )", left.template(), right.template()); - Params params = new ParamsBuilder().script(left.params()).script(right.params()).build(); - return new ScriptTemplate(template, params, DataType.BOOLEAN); + super(name, Scripts.and(left.scriptTemplate(), right.scriptTemplate())); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/OrAggFilter.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/OrAggFilter.java index 120f0a5848c7f..4c5ab50b2627e 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/OrAggFilter.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/OrAggFilter.java @@ -5,14 +5,7 @@ */ package org.elasticsearch.xpack.sql.querydsl.agg; -import org.elasticsearch.xpack.sql.expression.gen.script.Params; -import org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder; -import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; -import org.elasticsearch.xpack.sql.type.DataType; - -import java.util.Locale; - -import static java.lang.String.format; +import org.elasticsearch.xpack.sql.expression.gen.script.Scripts; public class OrAggFilter extends AggFilter { @@ -21,12 +14,6 @@ public OrAggFilter(AggFilter left, AggFilter right) { } public OrAggFilter(String name, AggFilter left, AggFilter right) { - super(name, and(left.scriptTemplate(), right.scriptTemplate())); - } - - private static ScriptTemplate and(ScriptTemplate left, ScriptTemplate right) { - String template = format(Locale.ROOT, "( %s ) || ( %s )", left.template(), right.template()); - Params params = new ParamsBuilder().script(left.params()).script(right.params()).build(); - return new ScriptTemplate(template, params, DataType.BOOLEAN); + super(name, Scripts.or(left.scriptTemplate(), right.scriptTemplate())); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScriptSort.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScriptSort.java index b7d7da7a9d0da..8aa69cd061ae0 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScriptSort.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScriptSort.java @@ -6,6 +6,7 @@ package org.elasticsearch.xpack.sql.querydsl.container; import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; +import org.elasticsearch.xpack.sql.expression.gen.script.Scripts; import java.util.Objects; @@ -15,7 +16,8 @@ public class ScriptSort extends Sort { public ScriptSort(ScriptTemplate script, Direction direction) { super(direction); - this.script = script; + // + this.script = Scripts.nullSafeSort(script); } public ScriptTemplate script() { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/query/ScriptQuery.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/query/ScriptQuery.java index 7c93f7cc95c43..6d9a1639f4f5d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/query/ScriptQuery.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/query/ScriptQuery.java @@ -5,12 +5,13 @@ */ package org.elasticsearch.xpack.sql.querydsl.query; -import java.util.Objects; - import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; +import org.elasticsearch.xpack.sql.expression.gen.script.Scripts; import org.elasticsearch.xpack.sql.tree.Location; +import java.util.Objects; + import static org.elasticsearch.index.query.QueryBuilders.scriptQuery; public class ScriptQuery extends LeafQuery { @@ -19,7 +20,8 @@ public class ScriptQuery extends LeafQuery { public ScriptQuery(Location location, ScriptTemplate script) { super(location); - this.script = script; + // make script null safe + this.script = Scripts.nullSafeFilter(script); } public ScriptTemplate script() { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/util/ReflectionUtils.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/util/ReflectionUtils.java index 0ddccccf7ddf0..13a859d516105 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/util/ReflectionUtils.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/util/ReflectionUtils.java @@ -24,7 +24,17 @@ public static Class detectSuperTypeForRuleLike(Class c) { c); } - return (Class) typeArguments[0]; + Type tp = typeArguments[0]; + + if (tp instanceof Class) { + return (Class) tp; + } else if (tp instanceof ParameterizedType) { + Type rawType = ((ParameterizedType) type).getRawType(); + if (rawType instanceof Class) { + return (Class) rawType; + } + } + throw new SqlIllegalArgumentException("Unexpected class structure for class {}", c); } clazz = clazz.getSuperclass(); } diff --git a/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt b/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt index f8b15b202d8af..4b52ef78e21f3 100644 --- a/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt +++ b/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt @@ -7,32 +7,101 @@ # This file contains a whitelist for SQL specific utilities available inside SQL scripting class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalSqlScriptUtils { - - Integer dateTimeChrono(long, String, String) - String dayName(long, String) - String monthName(long, String) - Integer quarter(long, String) + +# +# Utilities +# + def docValue(java.util.Map, String) + boolean nullSafeFilter(Boolean) + double nullSafeSortNumeric(Number) + String nullSafeSortString(Object) + +# +# Comparison +# + Boolean eq(Object, Object) + Boolean lt(Object, Object) + Boolean lte(Object, Object) + Boolean gt(Object, Object) + Boolean gte(Object, Object) + +# +# Logical +# + Boolean and(Boolean, Boolean) + Boolean or(Boolean, Boolean) + +# +# Regex +# + Boolean regex(String, String) + +# +# Math +# + Number add(Number, Number) + Number div(Number, Number) + Number mod(Number, Number) + Number mul(Number, Number) + Number sub(Number, Number) Number round(Number, Number) Number truncate(Number, Number) + + Double abs(Number) + Double acos(Number) + Double asin(Number) + Double atan(Number) + Double cbrt(Number) + Double ceil(Number) + Double cos(Number) + Double cosh(Number) + Double cot(Number) + Double degrees(Number) + Double e(Number) + Double exp(Number) + Double expm1(Number) + Double floor(Number) + Double log(Number) + Double log10(Number) + Double pi(Number) + Double radians(Number) + Double random(Number) + Double sign(Number) + Double sin(Number) + Double sinh(Number) + Double sqrt(Number) + Double tan(Number) + +# +# Date/Time functions +# + Integer dateTimeChrono(Object, String, String) + String dayName(Long, String) + String monthName(Long, String) + Integer quarter(Long, String) + +# +# ASCII Functions +# Integer ascii(String) Integer bitLength(String) - String character(Number) + String character(Number) Integer charLength(String) - String concat(String, String) - String insert(String, int, int, String) - String lcase(String) - String left(String, int) + String concat(String, String) + String insert(String, Number, Number, String) + String lcase(String) + String left(String, Number) Integer length(String) Integer locate(String, String) - Integer locate(String, String, Integer) - String ltrim(String) + Integer locate(String, String, Number) + String ltrim(String) Integer octetLength(String) Integer position(String, String) - String repeat(String, int) - String replace(String, String, String) - String right(String, int) - String rtrim(String) - String space(Number) - String substring(String, int, int) - String ucase(String) + String repeat(String, Number) + String replace(String, String, String) + String right(String, Number) + String rtrim(String) + String space(Number) + String substring(String, Number, Number) + String ucase(String) } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java index 3d84f852bc870..28980f9041d16 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java @@ -10,6 +10,7 @@ import org.elasticsearch.search.aggregations.AggregatorFactories.Builder; import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.elasticsearch.search.sort.FieldSortBuilder; import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.sql.expression.FieldAttribute; @@ -90,15 +91,17 @@ public void testSortScoreSpecified() { } public void testSortFieldSpecified() { + FieldSortBuilder sortField = fieldSort("test").missing("_last").unmappedType("keyword"); + QueryContainer container = new QueryContainer() .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", new KeywordEsField("test")), Direction.ASC)); SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, null, randomIntBetween(1, 10)); - assertEquals(singletonList(fieldSort("test").order(SortOrder.ASC)), sourceBuilder.sorts()); + assertEquals(singletonList(sortField.order(SortOrder.ASC)), sourceBuilder.sorts()); container = new QueryContainer() .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", new KeywordEsField("test")), Direction.DESC)); sourceBuilder = SourceGenerator.sourceBuilder(container, null, randomIntBetween(1, 10)); - assertEquals(singletonList(fieldSort("test").order(SortOrder.DESC)), sourceBuilder.sorts()); + assertEquals(singletonList(sortField.order(SortOrder.DESC)), sourceBuilder.sorts()); } public void testNoSort() { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatProcessorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatProcessorTests.java index 1a99d4ab27d89..6e1bf94e643bd 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatProcessorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/ConcatProcessorTests.java @@ -13,15 +13,15 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.Processors; import org.elasticsearch.xpack.sql.expression.gen.processor.ConstantProcessor; -import static org.elasticsearch.xpack.sql.tree.Location.EMPTY; import static org.elasticsearch.xpack.sql.expression.function.scalar.FunctionTestUtils.l; +import static org.elasticsearch.xpack.sql.tree.Location.EMPTY; public class ConcatProcessorTests extends AbstractWireSerializingTestCase { @Override protected ConcatFunctionProcessor createTestInstance() { return new ConcatFunctionProcessor( - new ConstantProcessor(randomRealisticUnicodeOfLengthBetween(0, 128)), + new ConstantProcessor(randomRealisticUnicodeOfLengthBetween(0, 128)), new ConstantProcessor(randomRealisticUnicodeOfLengthBetween(0, 128))); } @@ -43,7 +43,7 @@ public void testConcatFunctionWithValidInput() { public void testConcatFunctionWithEdgeCases() { assertEquals("foo", new Concat(EMPTY, l("foo"), l(null)).makePipe().asProcessor().process(null)); assertEquals("bar", new Concat(EMPTY, l(null), l("bar")).makePipe().asProcessor().process(null)); - assertNull(new Concat(EMPTY, l(null), l(null)).makePipe().asProcessor().process(null)); + assertEquals("", new Concat(EMPTY, l(null), l(null)).makePipe().asProcessor().process(null)); } public void testConcatFunctionInputsValidation() { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java index cf1f64bd583b2..74b8b37203435 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java @@ -29,12 +29,12 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.math.Abs; import org.elasticsearch.xpack.sql.expression.function.scalar.math.E; import org.elasticsearch.xpack.sql.expression.function.scalar.math.Floor; -import org.elasticsearch.xpack.sql.expression.predicate.And; import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator; import org.elasticsearch.xpack.sql.expression.predicate.IsNotNull; -import org.elasticsearch.xpack.sql.expression.predicate.Not; -import org.elasticsearch.xpack.sql.expression.predicate.Or; import org.elasticsearch.xpack.sql.expression.predicate.Range; +import org.elasticsearch.xpack.sql.expression.predicate.logical.And; +import org.elasticsearch.xpack.sql.expression.predicate.logical.Not; +import org.elasticsearch.xpack.sql.expression.predicate.logical.Or; import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Add; import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Div; import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mod; @@ -319,7 +319,7 @@ private static Object foldFunction(Function f) { return ((Literal) new ConstantFolding().rule(f)).value(); } - private static Object foldOperator(BinaryOperator b) { + private static Object foldOperator(BinaryOperator b) { return ((Literal) new ConstantFolding().rule(b)).value(); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/EscapedFunctionsTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/EscapedFunctionsTests.java index 710689ca861ca..0df368252d187 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/EscapedFunctionsTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/EscapedFunctionsTests.java @@ -69,7 +69,7 @@ private Limit limit(int limit) { private LikePattern likeEscape(String like, String character) { Expression exp = parser.createExpression(format(Locale.ROOT, "exp LIKE '%s' {escape '%s'}", like, character)); assertThat(exp, instanceOf(Like.class)); - return ((Like) exp).right(); + return ((Like) exp).pattern(); } private Function function(String name) { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java index 890718737a4bd..0a20202a67dbd 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java @@ -39,7 +39,7 @@ private LikePattern like(String pattern) { } assertThat(exp, instanceOf(Like.class)); Like l = (Like) exp; - return l.right(); + return l.pattern(); } public void testNoEscaping() { diff --git a/x-pack/qa/sql/no-security/src/test/java/org/elasticsearch/xpack/qa/sql/nosecurity/JdbcDocCsvSpecIT.java b/x-pack/qa/sql/no-security/src/test/java/org/elasticsearch/xpack/qa/sql/nosecurity/JdbcDocCsvSpecIT.java index aca0e37cd2d2b..c8fc587bd6ac6 100644 --- a/x-pack/qa/sql/no-security/src/test/java/org/elasticsearch/xpack/qa/sql/nosecurity/JdbcDocCsvSpecIT.java +++ b/x-pack/qa/sql/no-security/src/test/java/org/elasticsearch/xpack/qa/sql/nosecurity/JdbcDocCsvSpecIT.java @@ -74,12 +74,12 @@ protected void assertResults(ResultSet expected, ResultSet elastic) throws SQLEx @Override protected boolean logEsResultSet() { - return false; + return true; } @Override protected final void doTest() throws Throwable { - try (Connection csv = csvConnection(testCase.expectedResults); Connection es = esJdbc()) { + try (Connection csv = csvConnection(testCase); Connection es = esJdbc()) { // pass the testName as table for debugging purposes (in case the underlying reader is missing) ResultSet expected = executeCsvQuery(csv, testName); diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/CsvSpecTestCase.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/CsvSpecTestCase.java index a8ce308f3231e..0402b312338b9 100644 --- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/CsvSpecTestCase.java +++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/CsvSpecTestCase.java @@ -49,8 +49,7 @@ public CsvSpecTestCase(String fileName, String groupName, String testName, Integ @Override protected final void doTest() throws Throwable { - try (Connection csv = csvConnection(testCase.expectedResults); - Connection es = esJdbc()) { + try (Connection csv = csvConnection(testCase); Connection es = esJdbc()) { // pass the testName as table for debugging purposes (in case the underlying reader is missing) ResultSet expected = executeCsvQuery(csv, testName); diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/CsvTestUtils.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/CsvTestUtils.java index 856629f8d9188..937a5a70b8ad0 100644 --- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/CsvTestUtils.java +++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/CsvTestUtils.java @@ -25,7 +25,9 @@ import java.util.Locale; import java.util.Properties; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.arrayWithSize; +import static org.hamcrest.Matchers.isEmptyOrNullString; import static org.junit.Assert.assertThat; /** @@ -55,12 +57,12 @@ public static ResultSet executeCsvQuery(Connection csv, String csvTableName) thr * * Use {@link #executeCsvQuery} to obtain ResultSet from this connection */ - public static Connection csvConnection(String expectedResults) throws IOException, SQLException { + public static Connection csvConnection(CsvTestCase csvTest) throws IOException, SQLException { Properties csvProperties = new Properties(); csvProperties.setProperty("charset", "UTF-8"); csvProperties.setProperty("separator", "|"); csvProperties.setProperty("trimValues", "true"); - Tuple resultsAndTypes = extractColumnTypesAndStripCli(expectedResults); + Tuple resultsAndTypes = extractColumnTypesAndStripCli(csvTest.earlySchema, csvTest.expectedResults); csvProperties.setProperty("columnTypes", resultsAndTypes.v2()); Reader reader = new StringReader(resultsAndTypes.v1()); TableReader tableReader = new TableReader() { @@ -78,7 +80,7 @@ public List getTableNames(Connection connection) throws SQLException { }; } - private static Tuple extractColumnTypesAndStripCli(String expectedResults) throws IOException { + private static Tuple extractColumnTypesAndStripCli(String schema, String expectedResults) throws IOException { try (StringReader reader = new StringReader(expectedResults); BufferedReader bufferedReader = new BufferedReader(reader); StringWriter writer = new StringWriter(); @@ -87,8 +89,14 @@ private static Tuple extractColumnTypesAndStripCli(String expect String header = bufferedReader.readLine(); Tuple headerAndTypes; + String sch = schema; if (header.contains(":")) { - headerAndTypes = extractColumnTypesFromHeader(header); + assertThat("Cannot declare schema both individually and inside the header", sch, isEmptyOrNullString()); + sch = header; + } + + if (Strings.hasText(sch)) { + headerAndTypes = extractColumnTypesFromHeader(sch); } else { // No type information in headers, no need to parse columns - trigger auto-detection headerAndTypes = new Tuple<>(header, ""); @@ -160,6 +168,9 @@ public static CsvSpecParser specParser() { } private static class CsvSpecParser implements SpecBaseIntegrationTestCase.Parser { + private static final String SCHEMA_PREFIX = "schema::"; + + private final StringBuilder earlySchema = new StringBuilder(); private final StringBuilder query = new StringBuilder(); private final StringBuilder data = new StringBuilder(); private CsvTestCase testCase; @@ -168,17 +179,25 @@ private static class CsvSpecParser implements SpecBaseIntegrationTestCase.Parser public Object parse(String line) { // read the query if (testCase == null) { - if (line.endsWith(";")) { + if (line.startsWith(SCHEMA_PREFIX)) { + assertThat("Early schema already declared " + earlySchema, earlySchema.length(), is(0)); + earlySchema.append(line.substring(SCHEMA_PREFIX.length()).trim()); + } + else { + if (line.endsWith(";")) { // pick up the query testCase = new CsvTestCase(); query.append(line.substring(0, line.length() - 1).trim()); testCase.query = query.toString(); + testCase.earlySchema = earlySchema.toString(); + earlySchema.setLength(0); query.setLength(0); - } - // keep reading the query - else { - query.append(line); - query.append("\r\n"); + } + // keep reading the query + else { + query.append(line); + query.append("\r\n"); + } } } // read the results @@ -204,6 +223,7 @@ public Object parse(String line) { public static class CsvTestCase { public String query; + public String earlySchema; public String expectedResults; } } diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/DataLoader.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/DataLoader.java index 22ba2a1037d96..75204d9ff1230 100644 --- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/DataLoader.java +++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/DataLoader.java @@ -6,12 +6,12 @@ package org.elasticsearch.xpack.qa.sql.jdbc; import org.apache.http.HttpHost; +import org.apache.logging.log4j.LogManager; import org.elasticsearch.client.Request; import org.elasticsearch.client.RestClient; import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.Strings; import org.elasticsearch.common.SuppressForbidden; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.json.JsonXContent; @@ -33,7 +33,7 @@ public class DataLoader { public static void main(String[] args) throws Exception { try (RestClient client = RestClient.builder(new HttpHost("localhost", 9200)).build()) { loadEmpDatasetIntoEs(client); - Loggers.getLogger(DataLoader.class).info("Data loaded"); + LogManager.getLogger(DataLoader.class).info("Data loaded"); } } @@ -44,7 +44,6 @@ protected static void loadDatasetIntoEs(RestClient client) throws Exception { protected static void loadEmpDatasetIntoEs(RestClient client) throws Exception { loadEmpDatasetIntoEs(client, "test_emp", "employees"); loadEmpDatasetIntoEs(client, "test_emp_copy", "employees"); - loadEmpDatasetIntoEs(client, "test_emp_with_nulls", "employees_with_nulls"); makeAlias(client, "test_alias", "test_emp", "test_emp_copy"); makeAlias(client, "test_alias_emp", "test_emp", "test_emp_copy"); } @@ -134,12 +133,16 @@ protected static void loadEmpDatasetIntoEs(RestClient client, String index, Stri bulk.append("{\"index\":{}}\n"); bulk.append('{'); String emp_no = fields.get(1); + + boolean hadLastItem = false; + for (int f = 0; f < fields.size(); f++) { // an empty value in the csv file is treated as 'null', thus skipping it in the bulk request if (fields.get(f).trim().length() > 0) { - if (f != 0) { - bulk.append(','); + if (hadLastItem) { + bulk.append(","); } + hadLastItem = true; bulk.append('"').append(titles.get(f)).append("\":\"").append(fields.get(f)).append('"'); } } diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java index b0a0d36fba446..fa5c5dc7a5b39 100644 --- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java +++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java @@ -26,6 +26,7 @@ import static java.sql.Types.SMALLINT; import static java.sql.Types.TINYINT; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -177,7 +178,12 @@ private static void doAssertResultSetData(ResultSet expected, ResultSet actual, // handle nulls first if (expectedObject == null || actualObject == null) { - assertEquals(msg, expectedObject, actualObject); + // hack for JDBC CSV nulls + if ("null".equals(expectedObject)) { + assertNull(msg, actualObject); + } else { + assertEquals(msg, expectedObject, actualObject); + } } // then timestamp else if (type == Types.TIMESTAMP || type == Types.TIMESTAMP_WITH_TIMEZONE) { diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/LocalH2.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/LocalH2.java index e807a2dbf2e8e..8aa5a2287a805 100644 --- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/LocalH2.java +++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/LocalH2.java @@ -16,6 +16,22 @@ public class LocalH2 extends ExternalResource implements CheckedSupplier { + /* + * The syntax on the connection string is fairly particular: + * mem:; creates an anonymous database in memory. The `;` is + * technically the separator that comes after the name. + * DATABASE_TO_UPPER=false turns *off* H2's Oracle-like habit + * of upper-casing everything that isn't quoted. + * ALIAS_COLUMN_NAME=true turn *on* returning alias names in + * result set metadata which is what most DBs do except + * for MySQL and, by default, H2. Our jdbc driver does it. + */ + // http://www.h2database.com/html/features.html#in_memory_databases + private static String memUrl(String name) { + String n = name == null ? "" : name; + return "jdbc:h2:mem:" + n + ";DATABASE_TO_UPPER=false;ALIAS_COLUMN_NAME=true"; + } + static { try { // Initialize h2 so we can use it for testing @@ -30,7 +46,7 @@ public class LocalH2 extends ExternalResource implements CheckedSupplier initializer; - /* - * The syntax on the connection string is fairly particular: - * mem:; creates an anonymous database in memory. The `;` is - * technically the separator that comes after the name. - * DATABASE_TO_UPPER=false turns *off* H2's Oracle-like habit - * of upper-casing everything that isn't quoted. - * ALIAS_COLUMN_NAME=true turn *on* returning alias names in - * result set metadata which is what most DBs do except - * for MySQL and, by default, H2. Our jdbc driver does it. - */ - // http://www.h2database.com/html/features.html#in_memory_databases public LocalH2(CheckedConsumer initializer) { - this.url = "jdbc:h2:mem:essql;DATABASE_TO_UPPER=false;ALIAS_COLUMN_NAME=true"; + this.url = memUrl("essql"); this.initializer = initializer; } @@ -76,4 +81,4 @@ protected void after() { public Connection get() throws SQLException { return DriverManager.getConnection(url, DEFAULTS); } -} +} \ No newline at end of file diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/SqlSpecTestCase.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/SqlSpecTestCase.java index 605e19807ed4c..10fae56be48d4 100644 --- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/SqlSpecTestCase.java +++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/SqlSpecTestCase.java @@ -27,7 +27,6 @@ public abstract class SqlSpecTestCase extends SpecBaseIntegrationTestCase { @ClassRule public static LocalH2 H2 = new LocalH2((c) -> { c.createStatement().execute("RUNSCRIPT FROM 'classpath:/setup_test_emp.sql'"); - c.createStatement().execute("RUNSCRIPT FROM 'classpath:/setup_test_emp_with_nulls.sql'"); }); @ParametersFactory(argumentFormatting = PARAM_FORMATTING) @@ -42,7 +41,6 @@ public static List readScriptSpec() throws Exception { tests.addAll(readScriptSpec("/arithmetic.sql-spec", parser)); tests.addAll(readScriptSpec("/string-functions.sql-spec", parser)); tests.addAll(readScriptSpec("/case-functions.sql-spec", parser)); - tests.addAll(readScriptSpec("/agg_nulls.sql-spec", parser)); return tests; } diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java index 4c5141dc9f608..dd79bd0851491 100644 --- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java +++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java @@ -464,7 +464,7 @@ public void testTranslateQueryWithGroupByAndHaving() throws IOException { @SuppressWarnings("unchecked") Map termsScript = (Map) terms.get("script"); assertEquals(3, termsScript.size()); - assertEquals("Math.abs(doc[params.v0].value)", termsScript.get("source")); + assertEquals("InternalSqlScriptUtils.abs(InternalSqlScriptUtils.docValue(doc,params.v0))", termsScript.get("source")); assertEquals("painless", termsScript.get("lang")); @SuppressWarnings("unchecked") @@ -494,7 +494,7 @@ public void testTranslateQueryWithGroupByAndHaving() throws IOException { } } Collections.sort(aggKeys); - assertEquals("having" + aggKeys.get(1), aggFilterKey); + assertEquals("having." + aggKeys.get(1), aggFilterKey); @SuppressWarnings("unchecked") Map having = (Map) aggregations2.get(aggFilterKey); @@ -513,7 +513,7 @@ public void testTranslateQueryWithGroupByAndHaving() throws IOException { @SuppressWarnings("unchecked") Map filterScript = (Map) bucketSelector.get("script"); assertEquals(3, filterScript.size()); - assertEquals("(params.a0) > (params.v0)", filterScript.get("source")); + assertEquals("InternalSqlScriptUtils.gt(params.a0,params.v0)", filterScript.get("source")); assertEquals("painless", filterScript.get("lang")); @SuppressWarnings("unchecked") Map filterScriptParams = (Map) filterScript.get("params"); diff --git a/x-pack/qa/sql/src/main/resources/agg.csv-spec b/x-pack/qa/sql/src/main/resources/agg.csv-spec index d274e5379c968..db5ed60997679 100644 --- a/x-pack/qa/sql/src/main/resources/agg.csv-spec +++ b/x-pack/qa/sql/src/main/resources/agg.csv-spec @@ -6,64 +6,72 @@ singlePercentileWithoutComma SELECT gender, PERCENTILE(emp_no, 97) p1 FROM test_emp GROUP BY gender; gender:s | p1:d -F | 10099.1936 -M | 10095.6112 +null |10019.0 +F |10099.51 +M |10095.789999999999 ; singlePercentileWithComma SELECT gender, PERCENTILE(emp_no, 97.76) p1 FROM test_emp GROUP BY gender; gender:s | p1:d -F | 10099.1936 -M | 10095.6112 +null |10019.0 +F |10099.51 +M |10095.789999999999 ; multiplePercentilesOneWithCommaOneWithout SELECT gender, PERCENTILE(emp_no, 92.45) p1, PERCENTILE(emp_no, 91) p2 FROM test_emp GROUP BY gender; gender:s | p1:d | p2:d -F | 10096.826000000001 | 10094.68 -M | 10090.319 | 10089.320000000002 +null |10018.745 |10018.599999999999 +F |10098.0085 |10096.119999999999 +M |10091.393 |10090.37 ; multiplePercentilesWithoutComma SELECT gender, PERCENTILE(emp_no, 91) p1, PERCENTILE(emp_no, 89) p2 FROM test_emp GROUP BY gender; gender:s | p1:d | p2:d -F | 10094.68 | 10092.08 -M | 10089.320000000002 | 10085.18 +null |10018.599999999999 |10018.4 +F |10096.119999999999 |10093.74 +M |10090.37 |10086.92 ; multiplePercentilesWithComma SELECT gender, PERCENTILE(emp_no, 85.7) p1, PERCENTILE(emp_no, 94.3) p2 FROM test_emp GROUP BY gender; gender:s | p1:d | p2:d -F | 10088.852 | 10097.792 -M | 10083.134 | 10091.932 +null |10018.070000000002 |10018.929999999998 +F |10091.343 |10098.619 +M |10084.349 |10093.502 ; percentileRank SELECT gender, PERCENTILE_RANK(emp_no, 10025) rank FROM test_emp GROUP BY gender; gender:s | rank:d -F | 26.351351351351347 -M | 23.41269841269841 +null |100.0 +F |17.424242424242426 +M |15.350877192982457 ; multiplePercentileRanks SELECT gender, PERCENTILE_RANK(emp_no, 10030.0) rank1, PERCENTILE_RANK(emp_no, 10025) rank2 FROM test_emp GROUP BY gender; gender:s | rank1:d | rank2:d -F | 29.93762993762994 | 26.351351351351347 -M | 29.365079365079367 | 23.41269841269841 +null |100.0 |100.0 +F |21.445221445221442 |17.424242424242426 +M |21.929824561403507 |15.350877192982457 ; multiplePercentilesAndPercentileRank SELECT gender, PERCENTILE(emp_no, 97.76) p1, PERCENTILE(emp_no, 93.3) p2, PERCENTILE_RANK(emp_no, 10025) rank FROM test_emp GROUP BY gender; gender:s | p1:d | p2:d | rank:d -F | 10099.1936 | 10098.021 | 26.351351351351347 -M | 10095.6112 | 10090.846 | 23.41269841269841 +null |10019.0 |10018.83 |100.0 +F |10099.7608 |10098.289 |17.424242424242426 +M |10096.2232 |10092.362 |15.350877192982457 ; sum @@ -110,6 +118,7 @@ SELECT gender, KURTOSIS(salary) k, SKEWNESS(salary) s FROM test_emp GROUP BY gen gender:s | k:d | s:d -F | 1.8427808415250482 | 0.04517149340491813 -M | 2.259327644285826 | 0.40268950715550333 +null |2.2215791166941923 |-0.03373126000214023 +F |1.7873117044424276 |0.05504995122217512 +M |2.280646181070106 |0.44302407229580243 ; \ No newline at end of file diff --git a/x-pack/qa/sql/src/main/resources/agg.sql-spec b/x-pack/qa/sql/src/main/resources/agg.sql-spec index a61c825623cb9..c97f4da0fbc24 100644 --- a/x-pack/qa/sql/src/main/resources/agg.sql-spec +++ b/x-pack/qa/sql/src/main/resources/agg.sql-spec @@ -139,12 +139,22 @@ aggCountOnColumnAndMultipleHaving SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10 AND c < 70 ORDER BY gender ; aggCountOnColumnAndMultipleHavingEquals SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10 AND c = 63 ORDER BY gender ; +// +// Count(column) = Column(*) which is a bug +// https://github.com/elastic/elasticsearch/issues/34549 +// aggCountOnColumnAndMultipleHavingWithLimit SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10 AND c < 70 ORDER BY gender LIMIT 1; -aggCountOnColumnAndHavingBetween -SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c BETWEEN 10 AND 70 ORDER BY gender; -aggCountOnColumnAndHavingBetweenWithLimit +aggCountOnColumnAndHavingBetween-Ignore +SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c BETWEEN 10 AND 70 ORDER BY gender ASC; +aggCountOnColumnAndHavingBetweenWithLimit-Ignore SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c BETWEEN 10 AND 70 ORDER BY gender LIMIT 1; +aggCountStarAndMultipleHavingWithLimit +SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING c > 10 AND c < 70 ORDER BY gender LIMIT 1; +aggCountStarAndHavingBetween +SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING c BETWEEN 10 AND 70 ORDER BY gender ASC; +aggCountStarAndHavingBetweenWithLimit +SELECT gender g, COUNT(*) c FROM "test_emp" GROUP BY g HAVING c BETWEEN 10 AND 70 ORDER BY gender LIMIT 1; aggCountOnColumnAndHavingOnAliasAndFunction SELECT gender g, COUNT(gender) c FROM "test_emp" GROUP BY g HAVING c > 10 AND COUNT(gender) < 70 ORDER BY gender; aggCountOnColumnAndHavingOnAliasAndFunctionWildcard -> COUNT(*/1) vs COUNT(gender) @@ -413,3 +423,21 @@ aggRepeatFunctionBetweenSelectAndHaving SELECT gender, COUNT(DISTINCT languages) AS c FROM test_emp GROUP BY gender HAVING count(DISTINCT languages) > 0 ORDER BY gender; + +// +// NULL tests +// +selectGenderWithNullsAndGroupByGender +SELECT gender, COUNT(*) count FROM test_emp GROUP BY gender ORDER BY gender; +selectFirstNameWithNullsAndGroupByFirstName +SELECT first_name FROM test_emp GROUP BY first_name ORDER BY first_name; +selectCountWhereIsNull +SELECT COUNT(*) count FROM test_emp WHERE first_name IS NULL; +selectLanguagesCountWithNullsAndGroupByLanguage +SELECT languages l, COUNT(*) c FROM test_emp GROUP BY languages ORDER BY languages; +selectHireDateGroupByHireDate +SELECT hire_date HD, COUNT(*) c FROM test_emp GROUP BY hire_date ORDER BY hire_date DESC; +selectHireDateGroupByHireDate +SELECT hire_date HD, COUNT(*) c FROM test_emp GROUP BY hire_date ORDER BY hire_date DESC; +selectSalaryGroupBySalary +SELECT salary, COUNT(*) c FROM test_emp GROUP BY salary ORDER BY salary DESC; \ No newline at end of file diff --git a/x-pack/qa/sql/src/main/resources/agg_nulls.sql-spec b/x-pack/qa/sql/src/main/resources/agg_nulls.sql-spec deleted file mode 100644 index 17fbb70a40bcb..0000000000000 --- a/x-pack/qa/sql/src/main/resources/agg_nulls.sql-spec +++ /dev/null @@ -1,14 +0,0 @@ -selectGenderWithNullsAndGroupByGender -SELECT gender, COUNT(*) count FROM test_emp_with_nulls GROUP BY gender ORDER BY gender; -selectFirstNameWithNullsAndGroupByFirstName -SELECT first_name FROM test_emp_with_nulls GROUP BY first_name ORDER BY first_name; -selectCountWhereIsNull -SELECT COUNT(*) count FROM test_emp_with_nulls WHERE first_name IS NULL; -selectLanguagesCountWithNullsAndGroupByLanguage -SELECT languages l, COUNT(*) c FROM test_emp_with_nulls GROUP BY languages ORDER BY languages; -selectHireDateGroupByHireDate -SELECT hire_date HD, COUNT(*) c FROM test_emp_with_nulls GROUP BY hire_date ORDER BY hire_date DESC; -selectHireDateGroupByHireDate -SELECT hire_date HD, COUNT(*) c FROM test_emp_with_nulls GROUP BY hire_date ORDER BY hire_date DESC; -selectSalaryGroupBySalary -SELECT salary, COUNT(*) c FROM test_emp_with_nulls GROUP BY salary ORDER BY salary DESC; \ No newline at end of file diff --git a/x-pack/qa/sql/src/main/resources/alias.csv-spec b/x-pack/qa/sql/src/main/resources/alias.csv-spec index 57c7307065e18..a5f928d73e5a3 100644 --- a/x-pack/qa/sql/src/main/resources/alias.csv-spec +++ b/x-pack/qa/sql/src/main/resources/alias.csv-spec @@ -86,7 +86,6 @@ test_alias | ALIAS test_alias_emp | ALIAS test_emp | BASE TABLE test_emp_copy | BASE TABLE -test_emp_with_nulls | BASE TABLE ; testGroupByOnAlias @@ -94,8 +93,9 @@ SELECT gender g, PERCENTILE(emp_no, 97) p1 FROM test_alias GROUP BY g ORDER BY g g:s | p1:d -M | 10095.75 -F | 10099.28 +M | 10096.0 +F | 10099.52 +null | 10019.0 ; testGroupByOnPattern diff --git a/x-pack/qa/sql/src/main/resources/case-functions.sql-spec b/x-pack/qa/sql/src/main/resources/case-functions.sql-spec index f18f9c7eaa18d..9024497554983 100644 --- a/x-pack/qa/sql/src/main/resources/case-functions.sql-spec +++ b/x-pack/qa/sql/src/main/resources/case-functions.sql-spec @@ -4,10 +4,10 @@ selectInsertWithLcaseAndLengthWithOrderBy SELECT "first_name" origFN, "last_name" origLN, INSERT(UCASE("first_name"),LENGTH("first_name")+1,123,LCASE("last_name")) modified FROM "test_emp" WHERE ASCII("first_name")=65 ORDER BY "first_name" ASC, "last_name" ASC LIMIT 10; upperCasingTheSecondLetterFromTheRightFromFirstName -SELECT CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) f FROM "test_emp" ORDER BY "first_name" LIMIT 10; +SELECT CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) f FROM "test_emp" ORDER BY "first_name" NULLS LAST LIMIT 10; upperCasingTheSecondLetterFromTheRightFromFirstNameWithOrderByAndGroupBy -SELECT CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) f, COUNT(*) c FROM "test_emp" GROUP BY CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) ORDER BY CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) LIMIT 10; +SELECT CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) f, COUNT(*) c FROM "test_emp" GROUP BY CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) ORDER BY CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) DESC LIMIT 5; upperCasingTheSecondLetterFromTheRightFromFirstNameWithWhere SELECT CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) f, COUNT(*) c FROM "test_emp" WHERE CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1))='AlejandRo' GROUP BY CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) ORDER BY CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT(RIGHT("first_name",2),1))),RIGHT("first_name",1)) LIMIT 10; diff --git a/x-pack/qa/sql/src/main/resources/columns.csv-spec b/x-pack/qa/sql/src/main/resources/columns.csv-spec index a88d509a5a6ee..c00a8e0123f42 100644 --- a/x-pack/qa/sql/src/main/resources/columns.csv-spec +++ b/x-pack/qa/sql/src/main/resources/columns.csv-spec @@ -12,4 +12,5 @@ SELECT gender, FLOOR(PERCENTILE(emp_no, 97.76)) p1 FROM test_emp GROUP BY gender gender:s | p1:l M | 10096 F | 10099 +null | 10019 ; \ No newline at end of file diff --git a/x-pack/qa/sql/src/main/resources/command.csv-spec b/x-pack/qa/sql/src/main/resources/command.csv-spec index d1fa73c272ed3..879fa486d07f5 100644 --- a/x-pack/qa/sql/src/main/resources/command.csv-spec +++ b/x-pack/qa/sql/src/main/resources/command.csv-spec @@ -156,7 +156,6 @@ test_alias |ALIAS test_alias_emp |ALIAS test_emp |BASE TABLE test_emp_copy |BASE TABLE -test_emp_with_nulls|BASE TABLE ; showTablesSimpleLike @@ -172,7 +171,6 @@ SHOW TABLES LIKE 'test_emp%'; name:s | type:s test_emp |BASE TABLE test_emp_copy |BASE TABLE -test_emp_with_nulls|BASE TABLE ; showTablesIdentifier @@ -187,7 +185,6 @@ SHOW TABLES "test_e*,-test_emp"; name:s | type:s test_emp_copy |BASE TABLE -test_emp_with_nulls|BASE TABLE ; showTablesIdentifierPatternOnAliases diff --git a/x-pack/qa/sql/src/main/resources/datetime.csv-spec b/x-pack/qa/sql/src/main/resources/datetime.csv-spec index d5984d7671010..754a6da38af03 100644 --- a/x-pack/qa/sql/src/main/resources/datetime.csv-spec +++ b/x-pack/qa/sql/src/main/resources/datetime.csv-spec @@ -94,74 +94,76 @@ dateTimeAggByYear SELECT YEAR(birth_date) AS d, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY YEAR(birth_date) ORDER BY YEAR(birth_date) LIMIT 13; d:i | s:i -1952 | 90472 -1953 | 110398 -1954 | 80447 -1955 | 40240 -1956 | 60272 -1957 | 50280 -1958 | 70225 -1959 | 110517 -1960 | 100501 -1961 | 100606 -1962 | 60361 -1963 | 80372 -1964 | 40264 -; +null |100445 +1952 |80425 +1953 |110398 +1954 |80447 +1955 |40240 +1956 |50230 +1957 |40235 +1958 |70225 +1959 |90436 +1960 |80412 +1961 |80513 +1962 |60361 +1963 |70324 +; dateTimeAggByMonth SELECT MONTH(birth_date) AS d, COUNT(*) AS c, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY MONTH(birth_date) ORDER BY MONTH(birth_date) DESC; d:i | c:l | s:i -12 | 7 | 70325 -11 | 8 | 80439 -10 | 9 | 90517 -9 | 13 | 130688 -8 | 8 | 80376 -7 | 11 | 110486 -6 | 8 | 80314 -5 | 10 | 100573 -4 | 9 | 90450 -3 | 2 | 20164 -2 | 9 | 90430 -1 | 6 | 60288 +12 |7 |70325 +11 |8 |80439 +10 |9 |90517 +9 |10 |100561 +8 |6 |60290 +7 |9 |90392 +6 |7 |70267 +5 |10 |100573 +4 |8 |80401 +3 |2 |20164 +2 |8 |80388 +1 |6 |60288 +null |10 |100445 ; dateTimeAggByDayOfMonth SELECT DAY_OF_MONTH(birth_date) AS d, COUNT(*) AS c, CAST(SUM(emp_no) AS INT) s FROM "test_emp" GROUP BY DAY_OF_MONTH(birth_date) ORDER BY DAY_OF_MONTH(birth_date) DESC; d:i | c:l | s:i -31 | 1 | 10025 -30 | 2 | 20147 -29 | 3 | 30104 -28 | 2 | 20125 -27 | 3 | 30169 -26 | 4 | 40190 -25 | 5 | 50443 -24 | 2 | 20069 -23 | 7 | 70413 -22 | 1 | 10037 -21 | 6 | 60359 -20 | 4 | 40135 -19 | 8 | 80299 -18 | 2 | 20169 -17 | 1 | 10081 -16 | 1 | 10096 -15 | 2 | 20132 -14 | 4 | 40173 -13 | 5 | 50264 -12 | 1 | 10014 -11 | 2 | 20141 -10 | 2 | 20063 -9 | 3 | 30189 -8 | 2 | 20057 -7 | 5 | 50240 -6 | 4 | 40204 -5 | 2 | 20103 -4 | 3 | 30157 -3 | 4 | 40204 -2 | 4 | 40081 -1 | 5 | 50167 +31 |1 |10025 +30 |2 |20147 +29 |2 |20057 +28 |2 |20125 +27 |2 |20128 +26 |3 |30148 +25 |5 |50443 +24 |1 |10020 +23 |6 |60367 +22 |1 |10037 +21 |5 |50315 +20 |4 |40135 +19 |7 |70256 +18 |2 |20169 +17 |1 |10081 +16 |1 |10096 +15 |2 |20132 +14 |3 |30128 +13 |4 |40224 +12 |1 |10014 +11 |1 |10093 +10 |2 |20063 +9 |3 |30189 +8 |2 |20057 +7 |5 |50240 +6 |4 |40204 +5 |2 |20103 +4 |3 |30157 +3 |4 |40204 +2 |4 |40081 +1 |5 |50167 +null |10 |100445 ; constantYear diff --git a/x-pack/qa/sql/src/main/resources/docs.csv-spec b/x-pack/qa/sql/src/main/resources/docs.csv-spec index 49e67cf5f36ea..d225c3d35daab 100644 --- a/x-pack/qa/sql/src/main/resources/docs.csv-spec +++ b/x-pack/qa/sql/src/main/resources/docs.csv-spec @@ -148,7 +148,8 @@ emp |BASE TABLE // end::showTablesLikeMixed ; -showTablesLikeEscape-Ignore +showTablesLikeEscape +schema::name:s|type:s // tag::showTablesLikeEscape SHOW TABLES LIKE 'emp!%' ESCAPE '!'; @@ -463,23 +464,27 @@ Facello /////////////////////////////// groupByColumn +schema::g:s // tag::groupByColumn SELECT gender AS g FROM emp GROUP BY gender; g --------------- -F -M +null +F +M // end::groupByColumn ; groupByOrdinal +schema::gender:s // tag::groupByOrdinal SELECT gender FROM emp GROUP BY 1; gender --------------- +null F M @@ -487,11 +492,13 @@ M ; groupByAlias +schema::g:s // tag::groupByAlias SELECT gender AS g FROM emp GROUP BY g; g --------------- +null F M @@ -504,6 +511,7 @@ SELECT languages + 1 AS l FROM emp GROUP BY l; l --------------- +null 2 3 4 @@ -515,21 +523,28 @@ SELECT languages + 1 AS l FROM emp GROUP BY l; ; groupByMulti +schema::g:s|l:i|c:l // tag::groupByMulti SELECT gender g, languages l, COUNT(*) c FROM "emp" GROUP BY g, l ORDER BY languages ASC, gender DESC; - g | l | c + g | l | c ---------------+---------------+--------------- -M |1 |12 -F |1 |4 -M |2 |12 -F |2 |8 -M |3 |15 -F |3 |7 -M |4 |11 -F |4 |7 -M |5 |13 -F |5 |11 +M |null |7 +F |null |3 +M |1 |9 +F |1 |4 +null |1 |2 +M |2 |11 +F |2 |5 +null |2 |3 +M |3 |11 +F |3 |6 +M |4 |11 +F |4 |6 +null |4 |1 +M |5 |8 +F |5 |9 +null |5 |4 // end::groupByMulti @@ -537,37 +552,43 @@ F |5 |11 groupByAndAgg +schema::g:s|c:i // tag::groupByAndAgg SELECT gender AS g, COUNT(*) AS c FROM emp GROUP BY gender; g | c ---------------+--------------- -F |37 -M |63 +null |10 +F |33 +M |57 // end::groupByAndAgg ; groupByAndAggExpression // tag::groupByAndAggExpression +schema::g:s|salary:i SELECT gender AS g, ROUND((MIN(salary) / 100)) AS salary FROM emp GROUP BY gender; g | salary ---------------+--------------- +null |253 F |260 -M |253 - +M |259 // end::groupByAndAggExpression ; groupByAndMultipleAggs +schema::g:s|k:d|s:d // tag::groupByAndMultipleAggs SELECT gender AS g, KURTOSIS(salary) AS k, SKEWNESS(salary) AS s FROM emp GROUP BY gender; g | k | s ---------------+------------------+------------------- -F |1.8427808415250482|0.04517149340491813 -M |2.259327644285826 |0.40268950715550333 +null |2.2215791166941923|-0.03373126000214023 +F |1.7873117044424276|0.05504995122217512 +M |2.280646181070106 |0.44302407229580243 + // end::groupByAndMultipleAggs ; @@ -595,9 +616,10 @@ SELECT languages AS l, COUNT(*) AS c FROM emp GROUP BY l HAVING c BETWEEN 15 AND l | c ---------------+--------------- -1 |16 -2 |20 -4 |18 +1 |15 +2 |19 +3 |17 +4 |18 // end::groupByHaving ; @@ -608,11 +630,13 @@ SELECT MIN(salary) AS min, MAX(salary) AS max, MAX(salary) - MIN(salary) AS diff min | max | diff ---------------+---------------+--------------- +28336 |74999 |46663 25976 |73717 |47741 29175 |73578 |44403 -26436 |74999 |48563 +26436 |74970 |48534 27215 |74572 |47357 -25324 |73851 |48527 +25324 |66817 |41493 + // end::groupByHavingMultiple ; @@ -815,11 +839,12 @@ SELECT languages, PERCENTILE(salary, 95) AS "95th" FROM emp languages | 95th ---------------+----------------- -1 |72605.2 -2 |71741.0 -3 |74981.6 +null |74999.0 +1 |72790.5 +2 |71924.70000000001 +3 |73638.25 4 |72115.59999999999 -5 |68927.19999999998 +5 |61071.7 // end::aggPercentile ; @@ -829,11 +854,12 @@ SELECT languages, PERCENTILE_RANK(salary, 65000) AS rank FROM emp GROUP BY langu languages | rank ---------------+----------------- -1 |75.37108985853756 -2 |89.43605326660112 -3 |77.74873333978765 +null |73.65766569962062 +1 |73.7291625157734 +2 |88.88005607010643 +3 |79.43662623295829 4 |85.70446389643493 -5 |92.52677973666592 +5 |100.0 // end::aggPercentileRank ; @@ -1038,11 +1064,11 @@ LaLaLa // end::stringRepeat ; -stringReplace-Ignore +stringReplace // tag::stringReplace -SELECT REPLACE('Elastic', 'El', 'Fant'); +SELECT REPLACE('Elastic','El','Fant'); - REPLACE(Elastic, El, Fant) + REPLACE(Elastic,El,Fant) ----------------------------- Fantastic // end::stringReplace @@ -1069,6 +1095,7 @@ Elastic ; stringSpace-Ignore +schema::SPACE(3):s // tag::stringSpace SELECT SPACE(3); diff --git a/x-pack/qa/sql/src/main/resources/employees.csv b/x-pack/qa/sql/src/main/resources/employees.csv index 4425a4b592f70..2710fdefceca7 100644 --- a/x-pack/qa/sql/src/main/resources/employees.csv +++ b/x-pack/qa/sql/src/main/resources/employees.csv @@ -8,46 +8,46 @@ birth_date,emp_no,first_name,gender,hire_date,languages,last_name,salary 1957-05-23T00:00:00Z,10007,Tzvetan,F,1989-02-10T00:00:00Z,4,Zielinski,74572 1958-02-19T00:00:00Z,10008,Saniya,M,1994-09-15T00:00:00Z,2,Kalloufi,43906 1952-04-19T00:00:00Z,10009,Sumant,F,1985-02-18T00:00:00Z,1,Peac,66174 -1963-06-01T00:00:00Z,10010,Duangkaew,F,1989-08-24T00:00:00Z,4,Piveteau,45797 -1953-11-07T00:00:00Z,10011,Mary,F,1990-01-22T00:00:00Z,5,Sluis,31120 -1960-10-04T00:00:00Z,10012,Patricio,M,1992-12-18T00:00:00Z,5,Bridgland,48942 -1963-06-07T00:00:00Z,10013,Eberhardt,M,1985-10-20T00:00:00Z,1,Terkki,48735 -1956-02-12T00:00:00Z,10014,Berni,M,1987-03-11T00:00:00Z,5,Genin,37137 -1959-08-19T00:00:00Z,10015,Guoxiang,M,1987-07-02T00:00:00Z,5,Nooteboom,25324 -1961-05-02T00:00:00Z,10016,Kazuhito,M,1995-01-27T00:00:00Z,2,Cappelletti,61358 -1958-07-06T00:00:00Z,10017,Cristinel,F,1993-08-03T00:00:00Z,2,Bouloucos,58715 -1954-06-19T00:00:00Z,10018,Kazuhide,F,1987-04-03T00:00:00Z,2,Peha,56760 -1953-01-23T00:00:00Z,10019,Lillian,M,1999-04-30T00:00:00Z,1,Haddadi,73717 -1952-12-24T00:00:00Z,10020,Mayuko,M,1991-01-26T00:00:00Z,3,Warwick,40031 -1960-02-20T00:00:00Z,10021,Ramzi,M,1988-02-10T00:00:00Z,5,Erde,60408 -1952-07-08T00:00:00Z,10022,Shahaf,M,1995-08-22T00:00:00Z,3,Famili,48233 -1953-09-29T00:00:00Z,10023,Bojan,F,1989-12-17T00:00:00Z,2,Montemayor,47896 -1958-09-05T00:00:00Z,10024,Suzette,F,1997-05-19T00:00:00Z,3,Pettey,64675 -1958-10-31T00:00:00Z,10025,Prasadram,M,1987-08-17T00:00:00Z,5,Heyers,47411 -1953-04-03T00:00:00Z,10026,Yongqiao,M,1995-03-20T00:00:00Z,3,Berztiss,28336 -1962-07-10T00:00:00Z,10027,Divier,F,1989-07-07T00:00:00Z,5,Reistad,73851 -1963-11-26T00:00:00Z,10028,Domenick,M,1991-10-22T00:00:00Z,1,Tempesti,39356 -1956-12-13T00:00:00Z,10029,Otmar,M,1985-11-20T00:00:00Z,3,Herbst,74999 -1958-07-14T00:00:00Z,10030,Elvis,M,1994-02-17T00:00:00Z,3,Demeyer,67492 -1959-01-27T00:00:00Z,10031,Karsten,M,1991-09-01T00:00:00Z,4,Joslin,37716 -1960-08-09T00:00:00Z,10032,Jeong,F,1990-06-20T00:00:00Z,3,Reistad,62233 -1956-11-14T00:00:00Z,10033,Arif,M,1987-03-18T00:00:00Z,1,Merlo,70011 -1962-12-29T00:00:00Z,10034,Bader,M,1988-09-21T00:00:00Z,1,Swan,39878 -1953-02-08T00:00:00Z,10035,Alain,M,1988-09-05T00:00:00Z,5,Chappelet,25945 -1959-08-10T00:00:00Z,10036,Adamantios,M,1992-01-03T00:00:00Z,4,Portugali,60781 -1963-07-22T00:00:00Z,10037,Pradeep,M,1990-12-05T00:00:00Z,2,Makrucki,37691 -1960-07-20T00:00:00Z,10038,Huan,M,1989-09-20T00:00:00Z,4,Lortz,35222 -1959-10-01T00:00:00Z,10039,Alejandro,M,1988-01-19T00:00:00Z,2,Brender,36051 -1959-09-13T00:00:00Z,10040,Weiyi,F,1993-02-14T00:00:00Z,4,Meriste,37112 -1959-08-27T00:00:00Z,10041,Uri,F,1989-11-12T00:00:00Z,1,Lenart,56415 -1956-02-26T00:00:00Z,10042,Magy,F,1993-03-21T00:00:00Z,3,Stamatiou,30404 -1960-09-19T00:00:00Z,10043,Yishay,M,1990-10-20T00:00:00Z,1,Tzvieli,34341 -1961-09-21T00:00:00Z,10044,Mingsen,F,1994-05-21T00:00:00Z,1,Casley,39728 -1957-08-14T00:00:00Z,10045,Moss,M,1989-09-02T00:00:00Z,3,Shanbhogue,74970 -1960-07-23T00:00:00Z,10046,Lucien,M,1992-06-20T00:00:00Z,4,Rosenbaum,50064 -1952-06-29T00:00:00Z,10047,Zvonko,M,1989-03-31T00:00:00Z,4,Nyanchama,42716 -1963-07-11T00:00:00Z,10048,Florian,M,1985-02-24T00:00:00Z,3,Syrotiuk,26436 -1961-04-24T00:00:00Z,10049,Basil,F,1992-05-04T00:00:00Z,5,Tramer,37853 +1963-06-01T00:00:00Z,10010,Duangkaew,,1989-08-24T00:00:00Z,4,Piveteau,45797 +1953-11-07T00:00:00Z,10011,Mary,,1990-01-22T00:00:00Z,5,Sluis,31120 +1960-10-04T00:00:00Z,10012,Patricio,,1992-12-18T00:00:00Z,5,Bridgland,48942 +1963-06-07T00:00:00Z,10013,Eberhardt,,1985-10-20T00:00:00Z,1,Terkki,48735 +1956-02-12T00:00:00Z,10014,Berni,,1987-03-11T00:00:00Z,5,Genin,37137 +1959-08-19T00:00:00Z,10015,Guoxiang,,1987-07-02T00:00:00Z,5,Nooteboom,25324 +1961-05-02T00:00:00Z,10016,Kazuhito,,1995-01-27T00:00:00Z,2,Cappelletti,61358 +1958-07-06T00:00:00Z,10017,Cristinel,,1993-08-03T00:00:00Z,2,Bouloucos,58715 +1954-06-19T00:00:00Z,10018,Kazuhide,,1987-04-03T00:00:00Z,2,Peha,56760 +1953-01-23T00:00:00Z,10019,Lillian,,1999-04-30T00:00:00Z,1,Haddadi,73717 +1952-12-24T00:00:00Z,10020,Mayuko,M,1991-01-26T00:00:00Z,,Warwick,40031 +1960-02-20T00:00:00Z,10021,Ramzi,M,1988-02-10T00:00:00Z,,Erde,60408 +1952-07-08T00:00:00Z,10022,Shahaf,M,1995-08-22T00:00:00Z,,Famili,48233 +1953-09-29T00:00:00Z,10023,Bojan,F,1989-12-17T00:00:00Z,,Montemayor,47896 +1958-09-05T00:00:00Z,10024,Suzette,F,1997-05-19T00:00:00Z,,Pettey,64675 +1958-10-31T00:00:00Z,10025,Prasadram,M,1987-08-17T00:00:00Z,,Heyers,47411 +1953-04-03T00:00:00Z,10026,Yongqiao,M,1995-03-20T00:00:00Z,,Berztiss,28336 +1962-07-10T00:00:00Z,10027,Divier,F,1989-07-07T00:00:00Z,,Reistad,73851 +1963-11-26T00:00:00Z,10028,Domenick,M,1991-10-22T00:00:00Z,,Tempesti,39356 +1956-12-13T00:00:00Z,10029,Otmar,M,1985-11-20T00:00:00Z,,Herbst,74999 +1958-07-14T00:00:00Z,10030,,M,1994-02-17T00:00:00Z,3,Demeyer,67492 +1959-01-27T00:00:00Z,10031,,M,1991-09-01T00:00:00Z,4,Joslin,37716 +1960-08-09T00:00:00Z,10032,,F,1990-06-20T00:00:00Z,3,Reistad,62233 +1956-11-14T00:00:00Z,10033,,M,1987-03-18T00:00:00Z,1,Merlo,70011 +1962-12-29T00:00:00Z,10034,,M,1988-09-21T00:00:00Z,1,Swan,39878 +1953-02-08T00:00:00Z,10035,,M,1988-09-05T00:00:00Z,5,Chappelet,25945 +1959-08-10T00:00:00Z,10036,,M,1992-01-03T00:00:00Z,4,Portugali,60781 +1963-07-22T00:00:00Z,10037,,M,1990-12-05T00:00:00Z,2,Makrucki,37691 +1960-07-20T00:00:00Z,10038,,M,1989-09-20T00:00:00Z,4,Lortz,35222 +1959-10-01T00:00:00Z,10039,,M,1988-01-19T00:00:00Z,2,Brender,36051 +,10040,Weiyi,F,1993-02-14T00:00:00Z,4,Meriste,37112 +,10041,Uri,F,1989-11-12T00:00:00Z,1,Lenart,56415 +,10042,Magy,F,1993-03-21T00:00:00Z,3,Stamatiou,30404 +,10043,Yishay,M,1990-10-20T00:00:00Z,1,Tzvieli,34341 +,10044,Mingsen,F,1994-05-21T00:00:00Z,1,Casley,39728 +,10045,Moss,M,1989-09-02T00:00:00Z,3,Shanbhogue,74970 +,10046,Lucien,M,1992-06-20T00:00:00Z,4,Rosenbaum,50064 +,10047,Zvonko,M,1989-03-31T00:00:00Z,4,Nyanchama,42716 +,10048,Florian,M,1985-02-24T00:00:00Z,3,Syrotiuk,26436 +,10049,Basil,F,1992-05-04T00:00:00Z,5,Tramer,37853 1958-05-21T00:00:00Z,10050,Yinghua,M,1990-12-25T00:00:00Z,2,Dredge,43026 1953-07-28T00:00:00Z,10051,Hidefumi,M,1992-10-15T00:00:00Z,3,Caine,58121 1961-02-26T00:00:00Z,10052,Heping,M,1988-05-21T00:00:00Z,1,Nitsch,55360 diff --git a/x-pack/qa/sql/src/main/resources/employees_with_nulls.csv b/x-pack/qa/sql/src/main/resources/employees_with_nulls.csv deleted file mode 100644 index 482da640470d0..0000000000000 --- a/x-pack/qa/sql/src/main/resources/employees_with_nulls.csv +++ /dev/null @@ -1,101 +0,0 @@ -birth_date,emp_no,first_name,gender,hire_date,languages,last_name,salary -1953-09-02T00:00:00Z,10001,Georgi,,1986-06-26T00:00:00Z,2,Facello,57305 -1964-06-02T00:00:00Z,10002,Bezalel,,1985-11-21T00:00:00Z,5,Simmel,56371 -1959-12-03T00:00:00Z,10003,Parto,,1986-08-28T00:00:00Z,4,Bamford,61805 -1954-05-01T00:00:00Z,10004,Chirstian,,1986-12-01T00:00:00Z,5,Koblick,36174 -1955-01-21T00:00:00Z,10005,Kyoichi,,1989-09-12T00:00:00Z,1,Maliniak,63528 -1953-04-20T00:00:00Z,10006,Anneke,,1989-06-02T00:00:00Z,3,Preusig,60335 -1957-05-23T00:00:00Z,10007,Tzvetan,,1989-02-10T00:00:00Z,4,Zielinski,74572 -1958-02-19T00:00:00Z,10008,Saniya,,1994-09-15T00:00:00Z,2,Kalloufi,43906 -1952-04-19T00:00:00Z,10009,Sumant,,1985-02-18T00:00:00Z,1,Peac,66174 -1963-06-01T00:00:00Z,10010,Duangkaew,,1989-08-24T00:00:00Z,4,Piveteau,45797 -1953-11-07T00:00:00Z,10011,Mary,F,1990-01-22T00:00:00Z,5,Sluis,31120 -1960-10-04T00:00:00Z,10012,Patricio,M,1992-12-18T00:00:00Z,5,Bridgland,48942 -1963-06-07T00:00:00Z,10013,Eberhardt,M,1985-10-20T00:00:00Z,1,Terkki,48735 -1956-02-12T00:00:00Z,10014,Berni,M,1987-03-11T00:00:00Z,5,Genin,37137 -1959-08-19T00:00:00Z,10015,Guoxiang,M,1987-07-02T00:00:00Z,5,Nooteboom,25324 -1961-05-02T00:00:00Z,10016,Kazuhito,M,1995-01-27T00:00:00Z,2,Cappelletti,61358 -1958-07-06T00:00:00Z,10017,Cristinel,F,1993-08-03T00:00:00Z,2,Bouloucos,58715 -1954-06-19T00:00:00Z,10018,Kazuhide,F,1993-08-03T00:00:00Z,2,Peha,56760 -1953-01-23T00:00:00Z,10019,Lillian,M,1993-08-03T00:00:00Z,1,Haddadi,73717 -1952-12-24T00:00:00Z,10020,,M,1991-01-26T00:00:00Z,3,Warwick,40031 -1960-02-20T00:00:00Z,10021,,M,1989-12-17T00:00:00Z,5,Erde,60408 -1952-07-08T00:00:00Z,10022,,M,1995-08-22T00:00:00Z,3,Famili,48233 -1953-09-29T00:00:00Z,10023,,F,1989-12-17T00:00:00Z,2,Montemayor,47896 -1958-09-05T00:00:00Z,10024,,F,1997-05-19T00:00:00Z,3,Pettey,64675 -1958-10-31T00:00:00Z,10025,Prasadram,M,1987-08-17T00:00:00Z,5,Heyers,47411 -1953-04-03T00:00:00Z,10026,Yongqiao,M,1995-03-20T00:00:00Z,3,Berztiss,28336 -1962-07-10T00:00:00Z,10027,Divier,F,1989-07-07T00:00:00Z,5,Reistad,73851 -1963-11-26T00:00:00Z,10028,Domenick,M,1991-10-22T00:00:00Z,1,Tempesti,39356 -1956-12-13T00:00:00Z,10029,Otmar,M,1985-11-20T00:00:00Z,,Herbst,74999 -1958-07-14T00:00:00Z,10030,Elvis,M,1994-02-17T00:00:00Z,,Demeyer,67492 -1959-01-27T00:00:00Z,10031,Karsten,M,1994-02-17T00:00:00Z,,Joslin,37716 -1960-08-09T00:00:00Z,10032,Jeong,F,1990-06-20T00:00:00Z,,Reistad,62233 -1956-11-14T00:00:00Z,10033,Arif,M,1987-03-18T00:00:00Z,,Merlo,70011 -1962-12-29T00:00:00Z,10034,Bader,M,1988-09-05T00:00:00Z,,Swan,39878 -1953-02-08T00:00:00Z,10035,Alain,M,1988-09-05T00:00:00Z,,Chappelet,25945 -1959-08-10T00:00:00Z,10036,Adamantios,M,1992-01-03T00:00:00Z,,Portugali,60781 -1963-07-22T00:00:00Z,10037,Pradeep,M,1990-12-05T00:00:00Z,,Makrucki,37691 -1960-07-20T00:00:00Z,10038,Huan,M,1989-09-20T00:00:00Z,,Lortz,35222 -1959-10-01T00:00:00Z,10039,Alejandro,M,1988-01-19T00:00:00Z,,Brender,36051 -1959-09-13T00:00:00Z,10040,Weiyi,F,1993-02-14T00:00:00Z,,Meriste,37112 -1959-08-27T00:00:00Z,10041,Uri,F,1989-11-12T00:00:00Z,1,Lenart,56415 -1956-02-26T00:00:00Z,10042,Magy,F,1993-03-21T00:00:00Z,3,Stamatiou,30404 -1960-09-19T00:00:00Z,10043,Yishay,M,1990-10-20T00:00:00Z,1,Tzvieli,34341 -1961-09-21T00:00:00Z,10044,Mingsen,F,1994-05-21T00:00:00Z,1,Casley,39728 -1957-08-14T00:00:00Z,10045,Moss,M,1989-09-02T00:00:00Z,3,Shanbhogue,74970 -1960-07-23T00:00:00Z,10046,Lucien,M,1992-06-20T00:00:00Z,4,Rosenbaum,50064 -1952-06-29T00:00:00Z,10047,Zvonko,M,1989-03-31T00:00:00Z,4,Nyanchama,42716 -1963-07-11T00:00:00Z,10048,Florian,M,1985-02-24T00:00:00Z,3,Syrotiuk,26436 -1961-04-24T00:00:00Z,10049,Basil,F,1992-05-04T00:00:00Z,5,Tramer,37853 -1958-05-21T00:00:00Z,10050,Yinghua,M,1990-12-25T00:00:00Z,2,Dredge,43026 -1953-07-28T00:00:00Z,10051,Hidefumi,M,1992-10-15T00:00:00Z,3,Caine,58121 -1961-02-26T00:00:00Z,10052,Heping,M,1988-05-21T00:00:00Z,1,Nitsch,55360 -1954-09-13T00:00:00Z,10053,Sanjiv,F,1986-02-04T00:00:00Z,3,Zschoche,54462 -1957-04-04T00:00:00Z,10054,Mayumi,M,1995-03-13T00:00:00Z,4,Schueller,65367 -1956-06-06T00:00:00Z,10055,Georgy,M,1992-04-27T00:00:00Z,5,Dredge,49281 -1961-09-01T00:00:00Z,10056,Brendon,F,1990-02-01T00:00:00Z,2,Bernini,33370 -1954-05-30T00:00:00Z,10057,Ebbe,F,1992-01-15T00:00:00Z,4,Callaway,27215 -1954-10-01T00:00:00Z,10058,Berhard,M,1987-04-13T00:00:00Z,3,McFarlin,38376 -1953-09-19T00:00:00Z,10059,Alejandro,F,1991-06-26T00:00:00Z,2,McAlpine,44307 -1961-10-15T00:00:00Z,10060,Breannda,M,1987-11-02T00:00:00Z,2,Billingsley,29175 -1962-10-19T00:00:00Z,10061,Tse,M,1985-09-17T00:00:00Z,1,Herber,49095 -1961-11-02T00:00:00Z,10062,Anoosh,M,1991-08-30T00:00:00Z,3,Peyn,65030 -1952-08-06T00:00:00Z,10063,Gino,F,1989-04-08T00:00:00Z,3,Leonhardt,52121 -1959-04-07T00:00:00Z,10064,Udi,M,1985-11-20T00:00:00Z,5,Jansch,33956 -1963-04-14T00:00:00Z,10065,Satosi,M,1988-05-18T00:00:00Z,2,Awdeh,50249 -1952-11-13T00:00:00Z,10066,Kwee,M,1986-02-26T00:00:00Z,5,Schusler,31897 -1953-01-07T00:00:00Z,10067,Claudi,M,1987-03-04T00:00:00Z,2,Stavenow,52044 -1962-11-26T00:00:00Z,10068,Charlene,M,1987-08-07T00:00:00Z,3,Brattka,28941 -1960-09-06T00:00:00Z,10069,Margareta,F,1989-11-05T00:00:00Z,5,Bierman,41933 -1955-08-20T00:00:00Z,10070,Reuven,M,1985-10-14T00:00:00Z,3,Garigliano,54329 -1958-01-21T00:00:00Z,10071,Hisao,M,1987-10-01T00:00:00Z,2,Lipner,40612 -1952-05-15T00:00:00Z,10072,Hironoby,F,1988-07-21T00:00:00Z,5,Sidou,54518 -1954-02-23T00:00:00Z,10073,Shir,M,1991-12-01T00:00:00Z,4,McClurg,32568 -1955-08-28T00:00:00Z,10074,Mokhtar,F,1990-08-13T00:00:00Z,5,Bernatsky,38992 -1960-03-09T00:00:00Z,10075,Gao,F,1987-03-19T00:00:00Z,5,Dolinsky,51956 -1952-06-13T00:00:00Z,10076,Erez,F,1985-07-09T00:00:00Z,3,Ritzmann,62405 -1964-04-18T00:00:00Z,10077,Mona,M,1990-03-02T00:00:00Z,5,Azuma,46595 -1959-12-25T00:00:00Z,10078,Danel,F,1987-05-26T00:00:00Z,2,Mondadori,69904 -1961-10-05T00:00:00Z,10079,Kshitij,F,1986-03-27T00:00:00Z,2,Gils,32263 -1957-12-03T00:00:00Z,10080,Premal,M,1985-11-19T00:00:00Z,5,Baek,52833 -1960-12-17T00:00:00Z,10081,Zhongwei,M,1986-10-30T00:00:00Z,2,Rosen,50128 -1963-09-09T00:00:00Z,10082,Parviz,M,1990-01-03T00:00:00Z,4,Lortz,49818 -1959-07-23T00:00:00Z,10083,Vishv,M,1987-03-31T00:00:00Z,1,Zockler, -1960-05-25T00:00:00Z,10084,Tuval,M,1995-12-15T00:00:00Z,1,Kalloufi, -1962-11-07T00:00:00Z,10085,Kenroku,M,1994-04-09T00:00:00Z,5,Malabarba, -1962-11-19T00:00:00Z,10086,Somnath,M,1990-02-16T00:00:00Z,1,Foote, -1959-07-23T00:00:00Z,10087,Xinglin,F,1986-09-08T00:00:00Z,5,Eugenio, -1954-02-25T00:00:00Z,10088,Jungsoon,F,1988-09-02T00:00:00Z,5,Syrzycki, -1963-03-21T00:00:00Z,10089,Sudharsan,F,1986-08-12T00:00:00Z,4,Flasterstein, -1961-05-30T00:00:00Z,10090,Kendra,M,1986-03-14T00:00:00Z,2,Hofting,44956 -1955-10-04T00:00:00Z,10091,Amabile,M,1992-11-18T00:00:00Z,3,Gomatam,38645 -1964-10-18T00:00:00Z,10092,Valdiodio,F,1989-09-22T00:00:00Z,1,Niizuma,25976 -1964-06-11T00:00:00Z,10093,Sailaja,M,1996-11-05T00:00:00Z,3,Desikan,45656 -1957-05-25T00:00:00Z,10094,Arumugam,F,1987-04-18T00:00:00Z,5,Ossenbruggen,66817 -1965-01-03T00:00:00Z,10095,Hilari,M,1986-07-15T00:00:00Z,4,Morton,37702 -1954-09-16T00:00:00Z,10096,Jayson,M,1990-01-14T00:00:00Z,4,Mandell,43889 -1952-02-27T00:00:00Z,10097,Remzi,M,1990-09-15T00:00:00Z,3,Waschkowski,71165 -1961-09-23T00:00:00Z,10098,Sreekrishna,F,1985-05-13T00:00:00Z,4,Servieres,44817 -1956-05-25T00:00:00Z,10099,Valter,F,1988-10-18T00:00:00Z,2,Sullins,73578 -1953-04-21T00:00:00Z,10100,Hironobu,F,1987-09-21T00:00:00Z,4,Haraldson,68431 diff --git a/x-pack/qa/sql/src/main/resources/example.csv-spec b/x-pack/qa/sql/src/main/resources/example.csv-spec index 77e9947af9369..8ccdf258c33f2 100644 --- a/x-pack/qa/sql/src/main/resources/example.csv-spec +++ b/x-pack/qa/sql/src/main/resources/example.csv-spec @@ -3,6 +3,10 @@ // name of the test - translated into 'testName' name +// optional schema declaration - needs to start with schema:: followed by list of columnName:ColumnType +// suitable for snippets included in the docs +schema::A:d,B:d,C:i + // ES SQL query SELECT COUNT(*) FROM "emp"; diff --git a/x-pack/qa/sql/src/main/resources/functions.csv-spec b/x-pack/qa/sql/src/main/resources/functions.csv-spec index b0c9323005fa4..6e6ccf872b585 100644 --- a/x-pack/qa/sql/src/main/resources/functions.csv-spec +++ b/x-pack/qa/sql/src/main/resources/functions.csv-spec @@ -2,161 +2,146 @@ bitLengthGroupByAndOrderBy SELECT BIT_LENGTH(first_name), COUNT(*) count FROM "test_emp" GROUP BY BIT_LENGTH(first_name) ORDER BY BIT_LENGTH(first_name) LIMIT 10; BIT_LENGTH(first_name):i| count:l -24 |4 -32 |11 -40 |16 -48 |24 -56 |19 -64 |14 -72 |10 -80 |1 -88 |1 +null |10 +24 |4 +32 |9 +40 |12 +48 |24 +56 |17 +64 |14 +72 |9 +88 |1 ; bitLengthOrderByFieldWithWhere SELECT BIT_LENGTH(first_name) len, first_name FROM "test_emp" WHERE BIT_LENGTH(first_name) > 64 ORDER BY first_name LIMIT 10; len:i | first_name:s -80 |Adamantios -72 |Alejandro -72 |Alejandro -72 |Chirstian -72 |Cristinel -72 |Duangkaew -72 |Eberhardt -72 |Margareta -72 |Prasadram -88 |Sreekrishna +72 |Alejandro +72 |Chirstian +72 |Cristinel +72 |Duangkaew +72 |Eberhardt +72 |Margareta +72 |Prasadram +88 |Sreekrishna +72 |Sudharsan +72 |Valdiodio ; selectConcatWithOrderBy SELECT first_name f, last_name l, CONCAT(first_name,last_name) cct FROM test_emp ORDER BY CONCAT(first_name,last_name) LIMIT 10; -f:s | l:s | cct:s -Adamantios | Portugali | AdamantiosPortugali -Alain | Chappelet | AlainChappelet -Alejandro | Brender | AlejandroBrender -Alejandro | McAlpine | AlejandroMcAlpine -Amabile | Gomatam | AmabileGomatam -Anneke | Preusig | AnnekePreusig -Anoosh | Peyn | AnooshPeyn -Arif | Merlo | ArifMerlo -Arumugam | Ossenbruggen | ArumugamOssenbruggen -Bader | Swan | BaderSwan +f:s | l:s | cct:s +Alejandro |McAlpine |AlejandroMcAlpine +Amabile |Gomatam |AmabileGomatam +Anneke |Preusig |AnnekePreusig +Anoosh |Peyn |AnooshPeyn +Arumugam |Ossenbruggen |ArumugamOssenbruggen +Basil |Tramer |BasilTramer +Berhard |McFarlin |BerhardMcFarlin +Berni |Genin |BerniGenin +Bezalel |Simmel |BezalelSimmel +Bojan |Montemayor |BojanMontemayor ; selectNestedConcatWithOrderBy -SELECT first_name f, last_name l, CONCAT(first_name,CONCAT(' ',last_name)) cct FROM test_emp ORDER BY CONCAT(first_name,CONCAT(' ',last_name)) LIMIT 10; +SELECT first_name f, last_name l, CONCAT(first_name,CONCAT(' ',last_name)) cct FROM test_emp ORDER BY CONCAT(first_name,CONCAT(' ',last_name)) DESC LIMIT 10; -f:s | l:s | cct:s -Adamantios | Portugali | Adamantios Portugali -Alain | Chappelet | Alain Chappelet -Alejandro | Brender | Alejandro Brender -Alejandro | McAlpine | Alejandro McAlpine -Amabile | Gomatam | Amabile Gomatam -Anneke | Preusig | Anneke Preusig -Anoosh | Peyn | Anoosh Peyn -Arif | Merlo | Arif Merlo -Arumugam | Ossenbruggen | Arumugam Ossenbruggen -Bader | Swan | Bader Swan +f:s | l:s | cct:s +Zvonko |Nyanchama |Zvonko Nyanchama +Zhongwei |Rosen |Zhongwei Rosen +Yongqiao |Berztiss |Yongqiao Berztiss +Yishay |Tzvieli |Yishay Tzvieli +Yinghua |Dredge |Yinghua Dredge +Xinglin |Eugenio |Xinglin Eugenio +Weiyi |Meriste |Weiyi Meriste +Vishv |Zockler |Vishv Zockler +Valter |Sullins |Valter Sullins +Valdiodio |Niizuma |Valdiodio Niizuma ; selectConcatWithGroupBy SELECT CONCAT(first_name,last_name) cct FROM test_emp GROUP BY CONCAT(first_name,last_name) ORDER BY CONCAT(first_name,last_name) LIMIT 1; cct:s -AdamantiosPortugali +AlejandroMcAlpine ; selectAsciiOfConcatWithGroupByOrderByCount SELECT ASCII(CONCAT("first_name","last_name")) ascii, COUNT(*) count FROM "test_emp" GROUP BY ASCII(CONCAT("first_name","last_name")) ORDER BY ASCII(CONCAT("first_name","last_name")) DESC LIMIT 10; -ascii:i | count:l -90 | 2 -89 | 3 -88 | 1 -87 | 1 -86 | 3 -85 | 2 -84 | 3 -83 | 11 -82 | 3 -80 | 6 +ascii:i | count:l +90 |2 +89 |3 +88 |1 +87 |1 +86 |3 +85 |2 +84 |3 +83 |12 +82 |4 +80 |6 ; selectRepeatTwice SELECT "first_name" orig, REPEAT("first_name",2) reps FROM "test_emp" WHERE ASCII("first_name")=65 ORDER BY REPEAT("first_name",2) ASC LIMIT 10; -orig:s | reps:s -Adamantios | AdamantiosAdamantios -Alain | AlainAlain -Alejandro | AlejandroAlejandro -Alejandro | AlejandroAlejandro -Amabile | AmabileAmabile -Anneke | AnnekeAnneke -Anoosh | AnooshAnoosh -Arif | ArifArif -Arumugam | ArumugamArumugam +orig:s | reps:s +Alejandro |AlejandroAlejandro +Amabile |AmabileAmabile +Anneke |AnnekeAnneke +Anoosh |AnooshAnoosh +Arumugam |ArumugamArumugam ; selectInsertWithLcase SELECT "first_name" orig, INSERT("first_name",2,1000,LCASE("first_name")) modified FROM "test_emp" WHERE ASCII("first_name")=65 ORDER BY "first_name" ASC LIMIT 10; -orig:s | modified:s -Adamantios | Aadamantios -Alain | Aalain -Alejandro | Aalejandro -Alejandro | Aalejandro -Amabile | Aamabile -Anneke | Aanneke -Anoosh | Aanoosh -Arif | Aarif -Arumugam | Aarumugam +orig:s | modified:s +Alejandro |Aalejandro +Amabile |Aamabile +Anneke |Aanneke +Anoosh |Aanoosh +Arumugam |Aarumugam ; selectInsertWithLcaseAndLengthWithOrderBy SELECT "first_name" origFN, "last_name" origLN, INSERT(UCASE("first_name"),LENGTH("first_name")+1,123,LCASE("last_name")) modified FROM "test_emp" WHERE ASCII("first_name")=65 ORDER BY "first_name" ASC LIMIT 10; -origFN:s | origLN:s | modified:s -Adamantios | Portugali | ADAMANTIOSportugali -Alain | Chappelet | ALAINchappelet -Alejandro | Brender | ALEJANDRObrender -Alejandro | McAlpine | ALEJANDROmcalpine -Amabile | Gomatam | AMABILEgomatam -Anneke | Preusig | ANNEKEpreusig -Anoosh | Peyn | ANOOSHpeyn -Arif | Merlo | ARIFmerlo -Arumugam | Ossenbruggen | ARUMUGAMossenbruggen +origFN:s | origLN:s | modified:s +Alejandro |McAlpine |ALEJANDROmcalpine +Amabile |Gomatam |AMABILEgomatam +Anneke |Preusig |ANNEKEpreusig +Anoosh |Peyn |ANOOSHpeyn +Arumugam |Ossenbruggen |ARUMUGAMossenbruggen ; selectInsertWithUcaseWithGroupByAndOrderBy SELECT INSERT(UCASE("first_name"),2,123000,INSERT(UCASE("last_name"),2,500,'')) modified, COUNT(*) count FROM "test_emp" WHERE ASCII("first_name")=65 GROUP BY INSERT(UCASE("first_name"),2,123000,INSERT(UCASE("last_name"),2,500,'')) ORDER BY INSERT(UCASE("first_name"),2,123000,INSERT(UCASE("last_name"),2,500,'')) ASC LIMIT 10; -modified:s | count:l -AB | 1 -AC | 1 -AG | 1 -AM | 2 -AO | 1 -AP | 3 +modified:s | count:l +AG |1 +AM |1 +AO |1 +AP |2 ; selectSubstringWithGroupBy SELECT SUBSTRING("first_name",1,2) modified, COUNT(*) count FROM "test_emp" WHERE ASCII("first_name")=65 GROUP BY SUBSTRING("first_name",1,2) ORDER BY SUBSTRING("first_name",1,2) ASC LIMIT 10; -modified:s | count:l -Ad | 1 -Al | 3 -Am | 1 -An | 2 -Ar | 2 +modified:s | count:l +Al |1 +Am |1 +An |2 +Ar |1 ; selectSubstringWithWhereCountAndGroupBy SELECT SUBSTRING("first_name",1,2) modified, COUNT(*) count FROM "test_emp" WHERE SUBSTRING("first_name",1,2)='Al' GROUP BY SUBSTRING("first_name",1,2) LIMIT 10; modified:s | count:l -Al | 3 +Al | 1 ; //this one doesn't return anything. The problem is "IS NOT NULL". GH issue created to generally investigate the NULLs usage: https://github.com/elastic/elasticsearch/issues/32079 @@ -182,16 +167,16 @@ SELECT SUBSTRING("first_name",5,20) modified, COUNT(*) count FROM "test_emp" GRO modified:s | count:l ---------------+--------------- - |15 -adram |1 -af |1 -aja |1 -al |1 -andro |2 -antios |1 -ard |1 -areta |1 -arsan |1 +null |10 + |13 +adram |1 +af |1 +aja |1 +al |1 +andro |1 +ard |1 +areta |1 +arsan |1 ; selectReplace @@ -199,16 +184,17 @@ SELECT REPLACE("first_name",'A','X') modified, "first_name" origFN FROM "test_em modified:s | origFN:s ---------------+--------------- -Xdamantios |Adamantios -Xlain |Alain -Xlejandro |Alejandro -Xlejandro |Alejandro -Xmabile |Amabile -Xnneke |Anneke -Xnoosh |Anoosh -Xrif |Arif -Xrumugam |Arumugam -Bader |Bader +Xlejandro |Alejandro +Xmabile |Amabile +Xnneke |Anneke +Xnoosh |Anoosh +Xrumugam |Arumugam +Basil |Basil +Berhard |Berhard +Berni |Berni +Bezalel |Bezalel +Bojan |Bojan + ; selectReplaceWithGroupBy @@ -216,16 +202,16 @@ SELECT REPLACE("first_name",'jan','_JAN_') modified, COUNT(*) count FROM "test_e modified:s | count:l ---------------+--------------- -Adamantios |1 -Alain |1 -Ale_JAN_dro |2 -Amabile |1 -Anneke |1 -Anoosh |1 -Arif |1 -Arumugam |1 -Bader |1 -Basil |1 +null |10 +Ale_JAN_dro |1 +Amabile |1 +Anneke |1 +Anoosh |1 +Arumugam |1 +Basil |1 +Berhard |1 +Berni |1 +Bezalel |1 ; selectReplaceWithCastAndCondition @@ -233,11 +219,11 @@ SELECT REPLACE(CAST("languages" AS VARCHAR),'1','100') foo, "languages" FROM "te foo:s | languages:bt ---------------+--------------- -2 |2 -100 |1 -2 |2 -100 |1 -100 |1 +2 |2 +100 |1 +2 |2 +100 |1 +100 |1 ; selectPositionWithConditionAndLcase @@ -245,8 +231,18 @@ SELECT POSITION('x',LCASE("first_name")) pos, "first_name" FROM "test_emp" WHERE pos:i | first_name:s ---------------+--------------- -4 |Guoxiang -1 |Xinglin +4 |Guoxiang +null |null +null |null +null |null +null |null +null |null +null |null +null |null +null |null +null |null +null |null +1 |Xinglin ; selectPositionWithLcaseAndConditionWithGroupByAndOrderBy @@ -254,12 +250,13 @@ SELECT POSITION('m',LCASE("first_name")), COUNT(*) pos FROM "test_emp" WHERE POS POSITION(m,LCASE(first_name)):i| pos:l -------------------------------+--------------- -9 |1 -7 |1 -4 |3 -3 |6 -2 |1 -1 |9 +9 |1 +7 |1 +4 |2 +3 |6 +2 |1 +1 |9 +null |10 ; selectInsertWithPositionAndCondition @@ -267,19 +264,18 @@ SELECT INSERT("first_name",POSITION('m',"first_name"),1,'M') modified, POSITION( modified:s | pos:i ---------------+--------------- -SuMant |3 -RaMzi |3 -PrasadraM |9 -DoMenick |3 -OtMar |3 -AdaMantios |4 -HidefuMi |7 -MayuMi |5 -PreMal |4 -SoMnath |3 -AMabile |2 -AruMugam |4 -ReMzi |3 +SuMant |3 +RaMzi |3 +PrasadraM |9 +DoMenick |3 +OtMar |3 +HidefuMi |7 +MayuMi |5 +PreMal |4 +SoMnath |3 +AMabile |2 +AruMugam |4 +ReMzi |3 ; selectLocateAndInsertWithLocateWithConditionAndThreeParameters @@ -287,17 +283,17 @@ SELECT LOCATE('a',"first_name",7) pos, INSERT("first_name",LOCATE('a',"first_nam pos:i |INSERT(first_name,LOCATE(a,first_name,7),1,AAA):s ---------------+----------------------------------------------- -8 |ChirstiAAAn -7 |DuangkAAAew -8 |PrasadrAAAm -7 |YongqiAAAo -7 |YinghuAAA -8 |BreanndAAA -9 |MargaretAAA -8 |SudharsAAAn -7 |SailajAAA -7 |ArumugAAAm -11 |SreekrishnAAA +8 |ChirstiAAAn +7 |DuangkAAAew +8 |PrasadrAAAm +7 |YongqiAAAo +7 |YinghuAAA +8 |BreanndAAA +9 |MargaretAAA +8 |SudharsAAAn +7 |SailajAAA +7 |ArumugAAAm +11 |SreekrishnAAA ; selectLocateAndInsertWithLocateWithConditionAndTwoParameters @@ -305,48 +301,48 @@ SELECT LOCATE('a',"first_name") pos, INSERT("first_name",LOCATE('a',"first_name" pos:i |INSERT(first_name,LOCATE(a,first_name),1,AAA):s ---------------+--------------------------------------------- -3 |AdAAAmantios -3 |AlAAAin -5 |AlejAAAndro -5 |AlejAAAndro -3 |AmAAAbile -7 |ArumugAAAm -2 |BAAAder -2 |BAAAsil -5 |BerhAAArd -4 |BezAAAlel +5 |AlejAAAndro +3 |AmAAAbile +7 |ArumugAAAm +2 |BAAAsil +5 |BerhAAArd +4 |BezAAAlel +4 |BojAAAn +4 |BreAAAnnda +3 |ChAAArlene +8 |ChirstiAAAn ; selectLeft SELECT LEFT("first_name",2) f FROM "test_emp" ORDER BY "first_name" LIMIT 10; f:s -Ad -Al -Al -Al -Am -An -An -Ar -Ar -Ba +Al +Am +An +An +Ar +Ba +Be +Be +Be +Bo ; selectRight SELECT RIGHT("first_name",2) f FROM "test_emp" ORDER BY "first_name" LIMIT 10; f:s -os -in -ro -ro -le -ke -sh -if -am -er +ro +le +ke +sh +am +il +rd +ni +el +an ; selectRightWithGroupByAndOrderBy @@ -354,47 +350,47 @@ SELECT RIGHT("first_name",2) f, COUNT(*) count FROM "test_emp" GROUP BY RIGHT("f f:s |count:l ---------------+--------------------------------------------- -af |1 -al |2 -am |2 -an |7 -ao |3 -ar |2 -ay |1 -be |1 -bu |1 -by |1 +null |10 +af |1 +al |2 +am |2 +an |6 +ao |3 +ar |2 +ay |1 +be |1 +bu |1 ; octetLengthGroupByAndOrderBy SELECT OCTET_LENGTH(first_name), COUNT(*) count FROM "test_emp" GROUP BY OCTET_LENGTH(first_name) ORDER BY OCTET_LENGTH(first_name) LIMIT 10; OCTET_LENGTH(first_name):i| count:l -3 |4 -4 |11 -5 |16 -6 |24 -7 |19 -8 |14 -9 |10 -10 |1 -11 |1 +null |10 +3 |4 +4 |9 +5 |12 +6 |24 +7 |17 +8 |14 +9 |9 +11 |1 ; octetLengthOrderByFieldWithWhere SELECT OCTET_LENGTH(first_name) len, first_name FROM "test_emp" WHERE OCTET_LENGTH(first_name) > 8 ORDER BY first_name LIMIT 10; len:i | first_name:s -10 |Adamantios -9 |Alejandro -9 |Alejandro -9 |Chirstian -9 |Cristinel -9 |Duangkaew -9 |Eberhardt -9 |Margareta -9 |Prasadram -11 |Sreekrishna +9 |Alejandro +9 |Chirstian +9 |Cristinel +9 |Duangkaew +9 |Eberhardt +9 |Margareta +9 |Prasadram +11 |Sreekrishna +9 |Sudharsan +9 |Valdiodio ; upperCasingTheSecondLetterFromTheRightFromFirstName @@ -402,16 +398,16 @@ SELECT CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT f:s -AdamantiOs -AlaIn -AlejandRo -AlejandRo -AmabiLe -AnneKe -AnooSh -ArIf -ArumugAm -BadEr +AlejandRo +AmabiLe +AnneKe +AnooSh +ArumugAm +BasIl +BerhaRd +BerNi +BezalEl +BojAn ; upperCasingTheSecondLetterFromTheRightFromFirstNameWithOrderByAndGroupBy @@ -419,16 +415,16 @@ SELECT CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT f:s |c:l ---------------+--------------------------------------------- -AdamantiOs |1 -AlaIn |1 -AlejandRo |2 -AmabiLe |1 -AnneKe |1 -AnooSh |1 -ArIf |1 -ArumugAm |1 -BadEr |1 -BasIl |1 + |10 +AlejandRo |1 +AmabiLe |1 +AnneKe |1 +AnooSh |1 +ArumugAm |1 +BasIl |1 +BerNi |1 +BerhaRd |1 +BezalEl |1 ; upperCasingTheSecondLetterFromTheRightFromFirstNameWithWhere @@ -436,7 +432,7 @@ SELECT CONCAT(CONCAT(SUBSTRING("first_name",1,LENGTH("first_name")-2),UCASE(LEFT f:s |c:l ---------------+--------------------------------------------- -AlejandRo |2 +AlejandRo |1 ; diff --git a/x-pack/qa/sql/src/main/resources/math.csv-spec b/x-pack/qa/sql/src/main/resources/math.csv-spec index 1c292200ccd91..9ec40848b3089 100644 --- a/x-pack/qa/sql/src/main/resources/math.csv-spec +++ b/x-pack/qa/sql/src/main/resources/math.csv-spec @@ -4,13 +4,12 @@ SELECT TRUNCATE(ASCII(LEFT(first_name, 1)), 1), COUNT(*) count FROM test_emp GRO TRUNCATE(ASCII(LEFT(first_name,1)),1):i| count:l ---------------------------------------+--------------- -65 |9 -66 |8 -72 |7 -75 |8 -77 |9 -80 |6 -83 |11 +null |10 +66 |7 +72 |6 +75 |7 +77 |9 +83 |11 ; truncateWithNoSecondParameterWithAsciiHavingAndOrderBy @@ -18,47 +17,46 @@ SELECT TRUNCATE(ASCII(LEFT(first_name, 1))), COUNT(*) count FROM test_emp GROUP TRUNCATE(ASCII(LEFT(first_name,1)),0):i| count:l ---------------------------------------+--------------- -65 |9 -66 |8 -72 |7 -75 |8 -77 |9 -80 |6 -83 |11 +null |10 +66 |7 +72 |6 +75 |7 +77 |9 +83 |11 ; roundWithGroupByAndOrderBy SELECT ROUND(salary, 2) ROUNDED, salary FROM test_emp GROUP BY ROUNDED, salary ORDER BY ROUNDED LIMIT 10; - ROUNDED | salary --------------+--------------- -25324 |25324 -25945 |25945 -25976 |25976 -26436 |26436 -27215 |27215 -28035 |28035 -28336 |28336 -28941 |28941 -29175 |29175 -30404 |30404 + ROUNDED | salary +---------------+--------------- +25324 |25324 +25945 |25945 +25976 |25976 +26436 |26436 +27215 |27215 +28035 |28035 +28336 |28336 +28941 |28941 +29175 |29175 +30404 |30404 ; truncateWithGroupByAndOrderBy SELECT TRUNCATE(salary, 2) TRUNCATED, salary FROM test_emp GROUP BY TRUNCATED, salary ORDER BY TRUNCATED LIMIT 10; - TRUNCATED | salary --------------+--------------- -25324 |25324 -25945 |25945 -25976 |25976 -26436 |26436 -27215 |27215 -28035 |28035 -28336 |28336 -28941 |28941 -29175 |29175 -30404 |30404 + TRUNCATED | salary +---------------+--------------- +25324 |25324 +25945 |25945 +25976 |25976 +26436 |26436 +27215 |27215 +28035 |28035 +28336 |28336 +28941 |28941 +29175 |29175 +30404 |30404 ; truncateWithAsciiAndOrderBy @@ -66,21 +64,21 @@ SELECT TRUNCATE(ASCII(LEFT(first_name,1)), -1) AS initial, first_name, ASCII(LEF initial | first_name |ASCII(LEFT(first_name,1)) ---------------+---------------+------------------------- -90 |Zvonko |90 -90 |Zhongwei |90 -80 |Yongqiao |89 -80 |Yishay |89 -80 |Yinghua |89 -80 |Xinglin |88 -80 |Weiyi |87 -80 |Vishv |86 -80 |Valdiodio |86 -80 |Valter |86 -80 |Uri |85 -80 |Udi |85 -80 |Tzvetan |84 -80 |Tse |84 -80 |Tuval |84 +90 |Zvonko |90 +90 |Zhongwei |90 +80 |Yongqiao |89 +80 |Yishay |89 +80 |Yinghua |89 +80 |Xinglin |88 +80 |Weiyi |87 +80 |Vishv |86 +80 |Valdiodio |86 +80 |Valter |86 +80 |Uri |85 +80 |Udi |85 +80 |Tzvetan |84 +80 |Tse |84 +80 |Tuval |84 ; truncateWithHavingAndGroupBy @@ -88,11 +86,12 @@ SELECT MIN(salary) mi, MAX(salary) ma, COUNT(*) c, TRUNCATE(AVG(salary)) tr FROM mi:i | ma:I | c:l | tr:i ---------------+---------------+-----------------+----------------- -25976 |73717 |16 |49875 -29175 |73578 |20 |48164 -26436 |74999 |22 |52154 -27215 |74572 |18 |47733 -25324 |73851 |24 |44040 +28336 |74999 |10 |52519 +25976 |73717 |15 |50576 +29175 |73578 |19 |48178 +26436 |74970 |17 |52418 +27215 |74572 |18 |47733 +25324 |66817 |21 |41680 ; // https://github.com/elastic/elasticsearch/issues/33773 diff --git a/x-pack/qa/sql/src/main/resources/nested.csv-spec b/x-pack/qa/sql/src/main/resources/nested.csv-spec index 7f7b97896ed35..0a188bd7faf13 100644 --- a/x-pack/qa/sql/src/main/resources/nested.csv-spec +++ b/x-pack/qa/sql/src/main/resources/nested.csv-spec @@ -44,11 +44,11 @@ SELECT first_name f, last_name l, YEAR(dep.from_date) d FROM test_emp WHERE dep. f:s | l:s | d:i -Alain | Chappelet | 1988 -Chirstian | Koblick | 1986 -Duangkaew | Piveteau | 1996 -Elvis | Demeyer | 1994 -Gino | Leonhardt | 1989 +Chirstian |Koblick |1986 +Duangkaew |Piveteau |1996 +Gino |Leonhardt |1989 +Hidefumi |Caine |1992 +Jayson |Mandell |1999 ; filterPerNestedWithOrderByNested @@ -56,11 +56,11 @@ SELECT first_name f, last_name l, YEAR(dep.from_date) d FROM test_emp WHERE dep. f:s | l:s | d:i -Sreekrishna | Servieres | 1985 -Zhongwei | Rosen | 1986 -Chirstian | Koblick | 1986 -Vishv | Zockler | 1987 -Alain | Chappelet | 1988 +Sreekrishna |Servieres |1985 +Zhongwei |Rosen |1986 +Chirstian |Koblick |1986 +Vishv |Zockler |1987 +null |Chappelet |1988 ; filterPerNestedWithOrderByNestedWithAlias @@ -92,11 +92,11 @@ SELECT first_name f, last_name l, YEAR(dep.from_date) start FROM test_emp WHERE f:s | l:s | start:i -Sreekrishna | Servieres | 1985 -Zhongwei | Rosen | 1986 -Chirstian | Koblick | 1986 -Alain | Chappelet | 1988 -Zvonko | Nyanchama | 1989 +Sreekrishna |Servieres |1985 +Zhongwei |Rosen |1986 +Chirstian |Koblick |1986 +null |Chappelet |1988 +Zvonko |Nyanchama |1989 ; selectWithScalarOnNestedWithoutProjection @@ -104,9 +104,9 @@ SELECT first_name f, last_name l FROM test_emp WHERE dep.dep_name = 'Production' f:s | l:s -Sreekrishna | Servieres -Zhongwei | Rosen -Chirstian | Koblick -Alain | Chappelet -Zvonko | Nyanchama +Sreekrishna |Servieres +Zhongwei |Rosen +Chirstian |Koblick +null |Chappelet +Zvonko |Nyanchama ; diff --git a/x-pack/qa/sql/src/main/resources/setup_test_emp_with_nulls.sql b/x-pack/qa/sql/src/main/resources/setup_test_emp_with_nulls.sql deleted file mode 100644 index c6afaa9018aa1..0000000000000 --- a/x-pack/qa/sql/src/main/resources/setup_test_emp_with_nulls.sql +++ /dev/null @@ -1,12 +0,0 @@ -DROP TABLE IF EXISTS "test_emp_with_nulls"; -CREATE TABLE "test_emp_with_nulls" ( - "birth_date" TIMESTAMP WITH TIME ZONE, - "emp_no" INT, - "first_name" VARCHAR(50), - "gender" VARCHAR(1), - "hire_date" TIMESTAMP WITH TIME ZONE, - "languages" TINYINT, - "last_name" VARCHAR(50), - "salary" INT - ) - AS SELECT * FROM CSVREAD('classpath:/employees_with_nulls.csv'); \ No newline at end of file diff --git a/x-pack/qa/sql/src/main/resources/string-functions.sql-spec b/x-pack/qa/sql/src/main/resources/string-functions.sql-spec index f039e5c487e2f..a2e8e67bd6b31 100644 --- a/x-pack/qa/sql/src/main/resources/string-functions.sql-spec +++ b/x-pack/qa/sql/src/main/resources/string-functions.sql-spec @@ -137,7 +137,7 @@ spaceFilter SELECT SPACE(languages) spaces, languages FROM "test_emp" WHERE SPACE(languages) = ' '; spaceFilterWithLengthFunctions -SELECT SPACE(languages) spaces, languages, first_name FROM "test_emp" WHERE CHAR_LENGTH(SPACE(languages)) = 3 ORDER BY first_name; +SELECT SPACE(languages) spaces, languages, first_name FROM "test_emp" WHERE CHAR_LENGTH(SPACE(languages)) = 3 ORDER BY first_name NULLS LAST; spaceInline1 SELECT SPACE(5) space; @@ -189,7 +189,7 @@ ltrimGroupByAndOrderBy SELECT LTRIM(first_name) lt FROM "test_emp" GROUP BY LTRIM(first_name) HAVING COUNT(*)>1; spaceGroupByWithCharLength -SELECT CAST(CHAR_LENGTH(SPACE(languages)) AS INT) cls FROM "test_emp" GROUP BY CHAR_LENGTH(SPACE(languages)); +SELECT CAST(CHAR_LENGTH(SPACE(languages)) AS INT) cls FROM "test_emp" GROUP BY CHAR_LENGTH(SPACE(languages)) ORDER BY CHAR_LENGTH(SPACE(languages)) ASC; spaceGroupByAndOrderBy SELECT SPACE("languages") s, COUNT(*) count FROM "test_emp" GROUP BY SPACE("languages") ORDER BY SPACE(languages); @@ -228,7 +228,7 @@ selectSubstringWithWhereAndGroupBy SELECT SUBSTRING("first_name",5,20) modified, COUNT(*) count FROM "test_emp" GROUP BY SUBSTRING("first_name",5,20) ORDER BY SUBSTRING("first_name",5,20) LIMIT 10; selectReplace -SELECT REPLACE("first_name",'A','X') modified, "first_name" origFN FROM "test_emp" ORDER BY "first_name" LIMIT 10; +SELECT REPLACE("first_name",'A','X') modified, "first_name" origFN FROM "test_emp" ORDER BY "first_name" NULLS LAST LIMIT 10; selectReplaceWithGroupBy SELECT REPLACE("first_name",'jan','_JAN_') modified, COUNT(*) count FROM "test_emp" GROUP BY REPLACE("first_name",'jan','_JAN_') ORDER BY REPLACE("first_name",'jan','_JAN_') LIMIT 10; @@ -237,10 +237,10 @@ selectReplaceWithCastAndCondition SELECT REPLACE(CAST("languages" AS VARCHAR),'1','100') foo, "languages" FROM "test_emp" WHERE "languages"=1 OR "languages"=2 LIMIT 5; selectPositionWithConditionAndLcase -SELECT POSITION('x',LCASE("first_name")) pos, "first_name" FROM "test_emp" WHERE POSITION('x',LCASE("first_name")) != 0; +SELECT POSITION('x',LCASE("first_name")) pos, "first_name" FROM "test_emp" WHERE POSITION('x',LCASE("first_name")) > 0 ORDER BY "first_name" NULLS LAST; selectPositionWithLcaseAndConditionWithGroupByAndOrderBy -SELECT POSITION('m',LCASE("first_name")) posOfM, COUNT(*) pos FROM "test_emp" WHERE POSITION('m',LCASE("first_name")) != 0 GROUP BY POSITION('m',LCASE("first_name")) ORDER BY POSITION('m',LCASE("first_name")) DESC; +SELECT POSITION('m',LCASE("first_name")) posOfM, COUNT(*) pos FROM "test_emp" WHERE POSITION('m',LCASE("first_name")) > 0 GROUP BY POSITION('m',LCASE("first_name")) ORDER BY POSITION('m',LCASE("first_name")) NULLS LAST; selectInsertWithPositionAndCondition SELECT INSERT("first_name",POSITION('m',"first_name"),1,'M') modified, POSITION('m',"first_name") pos FROM "test_emp" WHERE POSITION('m',"first_name") > 1; @@ -252,10 +252,10 @@ selectLocateAndInsertWithLocateWithConditionAndTwoParameters SELECT LOCATE('a',"first_name") pos, INSERT("first_name",LOCATE('a',"first_name"),1,'AAA') inserted FROM "test_emp" WHERE LOCATE('a',"first_name") > 0 ORDER BY "first_name" LIMIT 10; selectLeft -SELECT LEFT("first_name",2) f FROM "test_emp" ORDER BY "first_name" LIMIT 10; +SELECT LEFT("first_name",2) f FROM "test_emp" ORDER BY "first_name" NULLS LAST LIMIT 10; selectRight -SELECT RIGHT("first_name",2) f FROM "test_emp" ORDER BY "first_name" LIMIT 10; +SELECT RIGHT("first_name",2) f FROM "test_emp" ORDER BY "first_name" NULLS LAST LIMIT 10; selectRightWithGroupByAndOrderBy SELECT RIGHT("first_name",2) f, COUNT(*) count FROM "test_emp" GROUP BY RIGHT("first_name",2) ORDER BY RIGHT("first_name",2) LIMIT 10; From 11112171039bd42cf2eed7dd5c8b296d1eb93217 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Thu, 18 Oct 2018 17:38:05 +0300 Subject: [PATCH 2/4] Generalize NULLS LAST/FIRST --- .../xpack/sql/analysis/analyzer/Analyzer.java | 3 ++- .../sql/execution/search/SourceGenerator.java | 5 ++-- .../xpack/sql/expression/Order.java | 19 ++++++++++--- .../xpack/sql/parser/ExpressionBuilder.java | 9 +++---- .../xpack/sql/planner/QueryFolder.java | 10 ++++--- .../sql/querydsl/container/AttributeSort.java | 11 ++++---- .../sql/querydsl/container/ScoreSort.java | 9 ++++--- .../sql/querydsl/container/ScriptSort.java | 8 +++--- .../xpack/sql/querydsl/container/Sort.java | 27 ++++++++++++++++++- .../search/SourceGeneratorTests.java | 15 ++++++----- .../xpack/sql/optimizer/OptimizerTests.java | 2 +- .../xpack/qa/sql/jdbc/DebugCsvSpec.java | 4 +-- 12 files changed, 80 insertions(+), 42 deletions(-) diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java index c13160c933590..9876718d4d295 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java @@ -487,7 +487,8 @@ protected LogicalPlan rule(LogicalPlan plan) { if (ordinal != null) { changed = true; if (ordinal > 0 && ordinal <= max) { - newOrder.add(new Order(order.location(), orderBy.child().output().get(ordinal - 1), order.direction())); + newOrder.add(new Order(order.location(), orderBy.child().output().get(ordinal - 1), order.direction(), + order.nullsPosition())); } else { throw new AnalysisException(order, "Invalid %d specified in OrderBy (valid range is [1, %d])", ordinal, max); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/SourceGenerator.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/SourceGenerator.java index a3e8253ae2aad..16f283a1231da 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/SourceGenerator.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/SourceGenerator.java @@ -34,7 +34,6 @@ public abstract class SourceGenerator { private static final List NO_STORED_FIELD = singletonList(StoredFieldsContext._NONE_); - private static final String MISSING_LAST = "_last"; public static SearchSourceBuilder sourceBuilder(QueryContainer container, QueryBuilder filter, Integer size) { QueryBuilder finalQuery = null; @@ -112,12 +111,12 @@ private static void sorting(QueryContainer container, SearchSourceBuilder source fa = fa.isInexact() ? fa.exactAttribute() : fa; sortBuilder = fieldSort(fa.name()) - .missing(MISSING_LAST) + .missing(as.missing().position()) .unmappedType(fa.dataType().esType); if (fa.isNested()) { FieldSortBuilder fieldSort = fieldSort(fa.name()) - .missing(MISSING_LAST) + .missing(as.missing().position()) .unmappedType(fa.dataType().esType); NestedSortBuilder newSort = new NestedSortBuilder(fa.nestedParent().name()); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Order.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Order.java index 79ffad823805e..0b62f7035ed3d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Order.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Order.java @@ -20,18 +20,24 @@ public enum OrderDirection { ASC, DESC } + public enum NullsPosition { + FIRST, LAST; + } + private final Expression child; private final OrderDirection direction; + private final NullsPosition nulls; - public Order(Location location, Expression child, OrderDirection direction) { + public Order(Location location, Expression child, OrderDirection direction, NullsPosition nulls) { super(location, singletonList(child)); this.child = child; this.direction = direction; + this.nulls = nulls == null ? (direction == OrderDirection.DESC ? NullsPosition.FIRST : NullsPosition.LAST) : nulls; } @Override protected NodeInfo info() { - return NodeInfo.create(this, Order::new, child, direction); + return NodeInfo.create(this, Order::new, child, direction, nulls); } @Override @@ -49,7 +55,7 @@ public Order replaceChildren(List newChildren) { if (newChildren.size() != 1) { throw new IllegalArgumentException("expected [1] child but received [" + newChildren.size() + "]"); } - return new Order(location(), newChildren.get(0), direction); + return new Order(location(), newChildren.get(0), direction, nulls); } public Expression child() { @@ -60,6 +66,10 @@ public OrderDirection direction() { return direction; } + public NullsPosition nullsPosition() { + return nulls; + } + @Override public boolean foldable() { return false; @@ -67,7 +77,7 @@ public boolean foldable() { @Override public int hashCode() { - return Objects.hash(child, direction); + return Objects.hash(child, direction, nulls); } @Override @@ -82,6 +92,7 @@ public boolean equals(Object obj) { Order other = (Order) obj; return Objects.equals(direction, other.direction) + && Objects.equals(nulls, other.nulls) && Objects.equals(child, other.child); } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java index b3dfdaf404acf..5375f50dde51c 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java @@ -17,6 +17,7 @@ import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.expression.Literal; import org.elasticsearch.xpack.sql.expression.Order; +import org.elasticsearch.xpack.sql.expression.Order.NullsPosition; import org.elasticsearch.xpack.sql.expression.ScalarSubquery; import org.elasticsearch.xpack.sql.expression.UnresolvedAttribute; import org.elasticsearch.xpack.sql.expression.UnresolvedStar; @@ -348,13 +349,9 @@ private String getQueryOptions(MatchQueryOptionsContext optionsCtx) { @Override public Order visitOrderBy(OrderByContext ctx) { - if (ctx.NULLS() != null && ctx.nullOrdering.getType() != SqlBaseParser.LAST) { - throw new ParsingException(source(ctx.nullOrdering), "Null ordering can only be [LAST], found [{}]", - ctx.nullOrdering.getText()); - } - return new Order(source(ctx), expression(ctx.expression()), - ctx.DESC() != null ? Order.OrderDirection.DESC : Order.OrderDirection.ASC); + ctx.DESC() != null ? Order.OrderDirection.DESC : Order.OrderDirection.ASC, + ctx.NULLS() != null ? (ctx.FIRST() != null ? NullsPosition.FIRST : NullsPosition.LAST) : null); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryFolder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryFolder.java index 8c81301933085..8616205b00359 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryFolder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryFolder.java @@ -53,6 +53,7 @@ import org.elasticsearch.xpack.sql.querydsl.container.ScoreSort; import org.elasticsearch.xpack.sql.querydsl.container.ScriptSort; import org.elasticsearch.xpack.sql.querydsl.container.Sort.Direction; +import org.elasticsearch.xpack.sql.querydsl.container.Sort.Missing; import org.elasticsearch.xpack.sql.querydsl.query.Query; import org.elasticsearch.xpack.sql.rule.Rule; import org.elasticsearch.xpack.sql.rule.RuleExecutor; @@ -423,6 +424,7 @@ protected PhysicalPlan rule(OrderExec plan) { for (Order order : plan.order()) { Direction direction = Direction.from(order.direction()); + Missing missing = Missing.from(order.nullsPosition()); // check whether sorting is on an group (and thus nested agg) or field Attribute attr = ((NamedExpression) order.child()).toAttribute(); @@ -451,19 +453,19 @@ protected PhysicalPlan rule(OrderExec plan) { if (sfa.orderBy() instanceof NamedExpression) { Attribute at = ((NamedExpression) sfa.orderBy()).toAttribute(); at = qContainer.aliases().getOrDefault(at, at); - qContainer = qContainer.sort(new AttributeSort(at, direction)); + qContainer = qContainer.sort(new AttributeSort(at, direction, missing)); } else if (!sfa.orderBy().foldable()) { // ignore constant throw new PlanningException("does not know how to order by expression {}", sfa.orderBy()); } } else { // nope, use scripted sorting - qContainer = qContainer.sort(new ScriptSort(sfa.script(), direction)); + qContainer = qContainer.sort(new ScriptSort(sfa.script(), direction, missing)); } } else if (attr instanceof ScoreAttribute) { - qContainer = qContainer.sort(new ScoreSort(direction)); + qContainer = qContainer.sort(new ScoreSort(direction, missing)); } else { - qContainer = qContainer.sort(new AttributeSort(attr, direction)); + qContainer = qContainer.sort(new AttributeSort(attr, direction, missing)); } } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/AttributeSort.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/AttributeSort.java index 0fde127f6345d..d1dd2d17a94e4 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/AttributeSort.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/AttributeSort.java @@ -5,16 +5,16 @@ */ package org.elasticsearch.xpack.sql.querydsl.container; -import java.util.Objects; - import org.elasticsearch.xpack.sql.expression.Attribute; +import java.util.Objects; + public class AttributeSort extends Sort { private final Attribute attribute; - public AttributeSort(Attribute attribute, Direction direction) { - super(direction); + public AttributeSort(Attribute attribute, Direction direction, Missing missing) { + super(direction, missing); this.attribute = attribute; } @@ -24,7 +24,7 @@ public Attribute attribute() { @Override public int hashCode() { - return Objects.hash(attribute, direction()); + return Objects.hash(attribute, direction(), missing()); } @Override @@ -39,6 +39,7 @@ public boolean equals(Object obj) { AttributeSort other = (AttributeSort) obj; return Objects.equals(direction(), other.direction()) + && Objects.equals(missing(), other.missing()) && Objects.equals(attribute, other.attribute); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScoreSort.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScoreSort.java index c05864578d9c8..21b4621d0d460 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScoreSort.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScoreSort.java @@ -8,13 +8,13 @@ import java.util.Objects; public class ScoreSort extends Sort { - public ScoreSort(Direction direction) { - super(direction); + public ScoreSort(Direction direction, Missing missing) { + super(direction, missing); } @Override public int hashCode() { - return Objects.hash(direction()); + return Objects.hash(direction(), missing()); } @Override @@ -28,6 +28,7 @@ public boolean equals(Object obj) { } ScriptSort other = (ScriptSort) obj; - return Objects.equals(direction(), other.direction()); + return Objects.equals(direction(), other.direction()) + && Objects.equals(missing(), other.missing()); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScriptSort.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScriptSort.java index 8aa69cd061ae0..604bb3b8a0c61 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScriptSort.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/ScriptSort.java @@ -14,9 +14,8 @@ public class ScriptSort extends Sort { private final ScriptTemplate script; - public ScriptSort(ScriptTemplate script, Direction direction) { - super(direction); - // + public ScriptSort(ScriptTemplate script, Direction direction, Missing missing) { + super(direction, missing); this.script = Scripts.nullSafeSort(script); } @@ -26,7 +25,7 @@ public ScriptTemplate script() { @Override public int hashCode() { - return Objects.hash(direction(), script); + return Objects.hash(direction(), missing(), script); } @Override @@ -41,6 +40,7 @@ public boolean equals(Object obj) { ScriptSort other = (ScriptSort) obj; return Objects.equals(direction(), other.direction()) + && Objects.equals(missing(), other.missing()) && Objects.equals(script, other.script); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/Sort.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/Sort.java index 07250b3a9ccd4..549b53994ecbb 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/Sort.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/Sort.java @@ -6,6 +6,7 @@ package org.elasticsearch.xpack.sql.querydsl.container; import org.elasticsearch.search.sort.SortOrder; +import org.elasticsearch.xpack.sql.expression.Order.NullsPosition; import org.elasticsearch.xpack.sql.expression.Order.OrderDirection; public class Sort { @@ -22,13 +23,37 @@ public SortOrder asOrder() { } } + public enum Missing { + FIRST("_first"), LAST("_last"); + + private final String position; + + Missing(String position) { + this.position = position; + } + + public static Missing from(NullsPosition pos) { + return pos == null || pos == NullsPosition.FIRST ? FIRST : LAST; + } + + public String position() { + return position; + } + } + private final Direction direction; + private final Missing missing; - protected Sort(Direction direction) { + protected Sort(Direction direction, Missing nulls) { this.direction = direction; + this.missing = nulls; } public Direction direction() { return direction; } + + public Missing missing() { + return missing; + } } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java index 28980f9041d16..ae7830ad6d9fe 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.xpack.sql.querydsl.container.QueryContainer; import org.elasticsearch.xpack.sql.querydsl.container.ScoreSort; import org.elasticsearch.xpack.sql.querydsl.container.Sort.Direction; +import org.elasticsearch.xpack.sql.querydsl.container.Sort.Missing; import org.elasticsearch.xpack.sql.querydsl.query.MatchQuery; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.type.KeywordEsField; @@ -85,23 +86,25 @@ public void testSelectScoreForcesTrackingScore() { public void testSortScoreSpecified() { QueryContainer container = new QueryContainer() - .sort(new ScoreSort(Direction.DESC)); + .sort(new ScoreSort(Direction.DESC, null)); SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, null, randomIntBetween(1, 10)); assertEquals(singletonList(scoreSort()), sourceBuilder.sorts()); } public void testSortFieldSpecified() { - FieldSortBuilder sortField = fieldSort("test").missing("_last").unmappedType("keyword"); + FieldSortBuilder sortField = fieldSort("test").unmappedType("keyword"); QueryContainer container = new QueryContainer() - .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", new KeywordEsField("test")), Direction.ASC)); + .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", new KeywordEsField("test")), Direction.ASC, + Missing.LAST)); SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, null, randomIntBetween(1, 10)); - assertEquals(singletonList(sortField.order(SortOrder.ASC)), sourceBuilder.sorts()); + assertEquals(singletonList(sortField.order(SortOrder.ASC).missing("_last")), sourceBuilder.sorts()); container = new QueryContainer() - .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", new KeywordEsField("test")), Direction.DESC)); + .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", new KeywordEsField("test")), Direction.DESC, + Missing.FIRST)); sourceBuilder = SourceGenerator.sourceBuilder(container, null, randomIntBetween(1, 10)); - assertEquals(singletonList(sortField.order(SortOrder.DESC)), sourceBuilder.sorts()); + assertEquals(singletonList(sortField.order(SortOrder.DESC).missing("_first")), sourceBuilder.sorts()); } public void testNoSort() { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java index 74b8b37203435..608be8ab86f49 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java @@ -204,7 +204,7 @@ public void testReplaceFoldableAttributes() { // SELECT p = new Project(EMPTY, p, Arrays.asList(a, b)); // ORDER BY - p = new OrderBy(EMPTY, p, singletonList(new Order(EMPTY, b, OrderDirection.ASC))); + p = new OrderBy(EMPTY, p, singletonList(new Order(EMPTY, b, OrderDirection.ASC, null))); LogicalPlan result = new ReplaceFoldableAttributes().apply(p); assertNotSame(p, result); diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/DebugCsvSpec.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/DebugCsvSpec.java index c4d25f4311327..4e7842dd25adf 100644 --- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/DebugCsvSpec.java +++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/DebugCsvSpec.java @@ -54,9 +54,7 @@ protected boolean logEsResultSet() { @Override protected final void doTest() throws Throwable { - try (Connection csv = csvConnection(testCase.expectedResults); - Connection es = esJdbc()) { - + try (Connection csv = csvConnection(testCase); Connection es = esJdbc()) { // pass the testName as table for debugging purposes (in case the underlying reader is missing) ResultSet expected = executeCsvQuery(csv, testName); ResultSet elasticResults = executeJdbcQuery(es, testCase.query); From 04bd07a62f1b575aeda5f1bbb8693bc3bad53f2a Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Thu, 18 Oct 2018 19:24:56 +0300 Subject: [PATCH 3/4] Address feedback --- .../scalar/datetime/BaseDateTimeFunction.java | 32 ++++++++++++++- .../scalar/datetime/DateTimeFunction.java | 26 +----------- .../function/scalar/datetime/DayName.java | 9 +---- .../function/scalar/datetime/MonthName.java | 10 +---- .../datetime/NamedDateTimeFunction.java | 40 +++++-------------- .../datetime/NamedDateTimeProcessor.java | 35 ++++++++-------- .../function/scalar/datetime/Quarter.java | 30 ++------------ .../scalar/datetime/QuarterProcessor.java | 9 ++++- .../scalar/string/StringProcessor.java | 4 +- .../whitelist/InternalSqlScriptUtils.java | 32 ++++++++------- .../expression/predicate/BinaryPredicate.java | 2 +- .../predicate/regex/RegexProcessor.java | 2 +- .../xpack/sql/plugin/sql_whitelist.txt | 6 +-- .../xpack/qa/sql/jdbc/JdbcAssert.java | 2 +- .../sql/src/main/resources/datetime.sql-spec | 10 +++++ 15 files changed, 108 insertions(+), 141 deletions(-) diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BaseDateTimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BaseDateTimeFunction.java index b3c621bc14a89..952941342b583 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BaseDateTimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BaseDateTimeFunction.java @@ -12,7 +12,9 @@ import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; +import org.joda.time.DateTime; +import java.util.Objects; import java.util.TimeZone; abstract class BaseDateTimeFunction extends UnaryScalarFunction { @@ -60,4 +62,32 @@ public String name() { public boolean foldable() { return field().foldable(); } -} + + @Override + public Object fold() { + DateTime folded = (DateTime) field().fold(); + if (folded == null) { + return null; + } + + return doFold(folded.getMillis(), timeZone().getID()); + } + + protected abstract Object doFold(long millis, String tzId); + + + @Override + public boolean equals(Object obj) { + if (obj == null || obj.getClass() != getClass()) { + return false; + } + BaseDateTimeFunction other = (BaseDateTimeFunction) obj; + return Objects.equals(other.field(), field()) + && Objects.equals(other.timeZone(), timeZone()); + } + + @Override + public int hashCode() { + return Objects.hash(field(), timeZone()); + } +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java index bb6944b60aa0b..fbb095f2f00b5 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java @@ -15,13 +15,11 @@ import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.type.DataType; -import org.joda.time.DateTime; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.temporal.ChronoField; -import java.util.Objects; import java.util.TimeZone; import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; @@ -33,13 +31,8 @@ public abstract class DateTimeFunction extends BaseDateTimeFunction { } @Override - public Object fold() { - DateTime folded = (DateTime) field().fold(); - if (folded == null) { - return null; - } - - return dateTimeChrono(folded.getMillis(), timeZone().getID(), chronoField().name()); + protected Object doFold(long millis, String tzId) { + return dateTimeChrono(millis, tzId, chronoField().name()); } public static Integer dateTimeChrono(long millis, String tzId, String chronoName) { @@ -84,19 +77,4 @@ public DataType dataType() { // used for applying ranges public abstract String dateTimeFormat(); - - @Override - public boolean equals(Object obj) { - if (obj == null || obj.getClass() != getClass()) { - return false; - } - DateTimeFunction other = (DateTimeFunction) obj; - return Objects.equals(other.field(), field()) - && Objects.equals(other.timeZone(), timeZone()); - } - - @Override - public int hashCode() { - return Objects.hash(field(), timeZone()); - } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayName.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayName.java index 77cf427770436..8d6e12544d059 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayName.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayName.java @@ -18,7 +18,7 @@ public class DayName extends NamedDateTimeFunction { public DayName(Location location, Expression field, TimeZone timeZone) { - super(location, field, timeZone); + super(location, field, timeZone, NameExtractor.DAY_NAME); } @Override @@ -30,9 +30,4 @@ protected NodeCtor2 ctorForInfo() { protected DayName replaceChild(Expression newChild) { return new DayName(location(), newChild, timeZone()); } - - @Override - protected NameExtractor nameExtractor() { - return NameExtractor.DAY_NAME; - } -} +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/MonthName.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/MonthName.java index 75be997840661..7a95128101515 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/MonthName.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/MonthName.java @@ -18,7 +18,7 @@ public class MonthName extends NamedDateTimeFunction { public MonthName(Location location, Expression field, TimeZone timeZone) { - super(location, field, timeZone); + super(location, field, timeZone, NameExtractor.MONTH_NAME); } @Override @@ -30,10 +30,4 @@ protected NodeCtor2 ctorForInfo() { protected MonthName replaceChild(Expression newChild) { return new MonthName(location(), newChild, timeZone()); } - - @Override - protected NameExtractor nameExtractor() { - return NameExtractor.MONTH_NAME; - } - -} +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeFunction.java index 935e517ee0ff7..ed43996fe8e33 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeFunction.java @@ -15,10 +15,8 @@ import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.util.StringUtils; -import org.joda.time.DateTime; import java.util.Locale; -import java.util.Objects; import java.util.TimeZone; import static java.lang.String.format; @@ -29,25 +27,23 @@ */ abstract class NamedDateTimeFunction extends BaseDateTimeFunction { - NamedDateTimeFunction(Location location, Expression field, TimeZone timeZone) { + private final NameExtractor nameExtractor; + + NamedDateTimeFunction(Location location, Expression field, TimeZone timeZone, NameExtractor nameExtractor) { super(location, field, timeZone); + this.nameExtractor = nameExtractor; } @Override - public Object fold() { - DateTime folded = (DateTime) field().fold(); - if (folded == null) { - return null; - } - - return nameExtractor().extract(folded.getMillis(), timeZone().getID()); + protected Object doFold(long millis, String tzId) { + return nameExtractor.extract(millis, tzId); } @Override public ScriptTemplate scriptWithField(FieldAttribute field) { return new ScriptTemplate( - formatTemplate(format(Locale.ROOT, "{sql}.%s(doc[{}].value.millis, {})", - StringUtils.underscoreToLowerCamelCase(nameExtractor().name()))), + formatTemplate(format(Locale.ROOT, "{sql}.%s(doc[{}].value, {})", + StringUtils.underscoreToLowerCamelCase(nameExtractor.name()))), paramsBuilder() .variable(field.name()) .variable(timeZone().getID()).build(), @@ -56,29 +52,11 @@ public ScriptTemplate scriptWithField(FieldAttribute field) { @Override protected final Pipe makePipe() { - return new UnaryPipe(location(), this, Expressions.pipe(field()), - new NamedDateTimeProcessor(nameExtractor(), timeZone())); + return new UnaryPipe(location(), this, Expressions.pipe(field()), new NamedDateTimeProcessor(nameExtractor, timeZone())); } - protected abstract NameExtractor nameExtractor(); - @Override public DataType dataType() { return DataType.KEYWORD; } - - @Override - public boolean equals(Object obj) { - if (obj == null || obj.getClass() != getClass()) { - return false; - } - NamedDateTimeFunction other = (NamedDateTimeFunction) obj; - return Objects.equals(other.field(), field()) - && Objects.equals(other.timeZone(), timeZone()); - } - - @Override - public int hashCode() { - return Objects.hash(field(), timeZone()); - } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeProcessor.java index 43b3db07236a5..50eac88ae2c44 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeProcessor.java @@ -16,36 +16,35 @@ import java.util.Locale; import java.util.Objects; import java.util.TimeZone; -import java.util.function.BiFunction; +import java.util.function.Function; public class NamedDateTimeProcessor extends BaseDateTimeProcessor { public enum NameExtractor { // for the moment we'll use no specific Locale, but we might consider introducing a Locale parameter, just like the timeZone one - DAY_NAME((Long millis, String tzId) -> { - ZonedDateTime time = ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of(tzId)); - return time.format(DateTimeFormatter.ofPattern(DAY_NAME_FORMAT, Locale.ROOT)); - }), - MONTH_NAME((Long millis, String tzId) -> { - ZonedDateTime time = ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of(tzId)); - return time.format(DateTimeFormatter.ofPattern(MONTH_NAME_FORMAT, Locale.ROOT)); - }); - - private final BiFunction apply; - - NameExtractor(BiFunction apply) { + DAY_NAME(time -> time.format(DAY_NAME_FORMATTER)), + MONTH_NAME(time -> time.format(MONTH_NAME_FORMATTER)); + + private final Function apply; + + NameExtractor(Function apply) { this.apply = apply; } public final String extract(Long millis, String tzId) { - return apply.apply(millis, tzId); + return extract(ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of(tzId)), tzId); + } + + public final String extract(ZonedDateTime millis, String tzId) { + return apply.apply(millis.withZoneSameInstant(ZoneId.of(tzId))); } } public static final String NAME = "ndt"; - private static final String MONTH_NAME_FORMAT = "MMMM"; - private static final String DAY_NAME_FORMAT = "EEEE"; - + private static final DateTimeFormatter DAY_NAME_FORMATTER = DateTimeFormatter.ofPattern("EEEE", Locale.ROOT); + private static final DateTimeFormatter MONTH_NAME_FORMATTER = DateTimeFormatter.ofPattern("MMMM", Locale.ROOT); + + private final NameExtractor extractor; public NamedDateTimeProcessor(NameExtractor extractor, TimeZone timeZone) { @@ -97,4 +96,4 @@ public boolean equals(Object obj) { public String toString() { return extractor.toString(); } -} +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/Quarter.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/Quarter.java index 9cf15f637df31..c9a1d4ee721aa 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/Quarter.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/Quarter.java @@ -15,9 +15,7 @@ import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo.NodeCtor2; import org.elasticsearch.xpack.sql.type.DataType; -import org.joda.time.DateTime; -import java.util.Objects; import java.util.TimeZone; import static org.elasticsearch.xpack.sql.expression.function.scalar.datetime.QuarterProcessor.quarter; @@ -25,25 +23,18 @@ public class Quarter extends BaseDateTimeFunction { - protected static final String QUARTER_FORMAT = "q"; - public Quarter(Location location, Expression field, TimeZone timeZone) { super(location, field, timeZone); } @Override - public Object fold() { - DateTime folded = (DateTime) field().fold(); - if (folded == null) { - return null; - } - - return quarter(folded.getMillis(), timeZone().getID()); + protected Object doFold(long millis, String tzId) { + return quarter(millis, tzId); } @Override public ScriptTemplate scriptWithField(FieldAttribute field) { - return new ScriptTemplate(formatTemplate("{sql}.quarter(doc[{}].value.millis, {})"), + return new ScriptTemplate(formatTemplate("{sql}.quarter(doc[{}].value, {})"), paramsBuilder() .variable(field.name()) .variable(timeZone().getID()) @@ -70,19 +61,4 @@ protected Pipe makePipe() { public DataType dataType() { return DataType.INTEGER; } - - @Override - public boolean equals(Object obj) { - if (obj == null || obj.getClass() != getClass()) { - return false; - } - BaseDateTimeFunction other = (BaseDateTimeFunction) obj; - return Objects.equals(other.field(), field()) - && Objects.equals(other.timeZone(), timeZone()); - } - - @Override - public int hashCode() { - return Objects.hash(field(), timeZone()); - } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/QuarterProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/QuarterProcessor.java index c6904216d0fec..c4d6864b27574 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/QuarterProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/QuarterProcessor.java @@ -28,6 +28,7 @@ public QuarterProcessor(StreamInput in) throws IOException { } public static final String NAME = "q"; + private static final DateTimeFormatter QUARTER_FORMAT = DateTimeFormatter.ofPattern("q", Locale.ROOT); @Override public String getWriteableName() { @@ -40,8 +41,12 @@ public Object doProcess(long millis) { } public static Integer quarter(long millis, String tzId) { - ZonedDateTime time = ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of(tzId)); - return Integer.valueOf(time.format(DateTimeFormatter.ofPattern(Quarter.QUARTER_FORMAT, Locale.ROOT))); + return quarter(ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of(tzId)), tzId); + } + + public static Integer quarter(ZonedDateTime zdt, String tzId) { + ZonedDateTime time = zdt.withZoneSameInstant(ZoneId.of(tzId)); + return Integer.valueOf(time.format(QUARTER_FORMAT)); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/StringProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/StringProcessor.java index af8aff0725a1a..fb9f152504bd3 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/StringProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/StringProcessor.java @@ -71,11 +71,11 @@ public enum StringOperation { private final Function apply; StringOperation(StringFunction apply) { - this.apply = l -> l == null ? null : apply.apply((l)); + this.apply = l -> l == null ? null : apply.apply(l); } StringOperation(NumericFunction apply) { - this.apply = l -> l == null ? null : apply.apply((l)); + this.apply = l -> l == null ? null : apply.apply(l); } public final Object apply(Object l) { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java index d7b63019a0ae1..c6f445c0590e6 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java @@ -27,6 +27,7 @@ import org.elasticsearch.xpack.sql.expression.predicate.regex.RegexProcessor.RegexOperation; import org.elasticsearch.xpack.sql.util.StringUtils; +import java.time.ZonedDateTime; import java.util.Map; /** @@ -242,34 +243,35 @@ public static Integer dateTimeChrono(Object dateTime, String tzId, String chrono if (dateTime == null || tzId == null || chronoName == null) { return null; } - // use dedicated method - if (dateTime instanceof JodaCompatibleZonedDateTime) { - return DateTimeFunction.dateTimeChrono(((JodaCompatibleZonedDateTime) dateTime).getZonedDateTime(), tzId, chronoName); - } - throw new SqlIllegalArgumentException("Invalid date encountered [{}]", dateTime); + return DateTimeFunction.dateTimeChrono(asDateTime(dateTime), tzId, chronoName); } - public static String dayName(Long millis, String tzId) { - if (millis == null || tzId == null) { + public static String dayName(Object dateTime, String tzId) { + if (dateTime == null || tzId == null) { return null; } - return NameExtractor.DAY_NAME.extract(millis, tzId); + return NameExtractor.DAY_NAME.extract(asDateTime(dateTime), tzId); } - public static String monthName(Long millis, String tzId) { - if (millis == null || tzId == null) { + public static String monthName(Object dateTime, String tzId) { + if (dateTime == null || tzId == null) { return null; } - - return NameExtractor.MONTH_NAME.extract(millis, tzId); + return NameExtractor.MONTH_NAME.extract(asDateTime(dateTime), tzId); } - public static Integer quarter(Long millis, String tzId) { - if (millis == null || tzId == null) { + public static Integer quarter(Object dateTime, String tzId) { + if (dateTime == null || tzId == null) { return null; } + return QuarterProcessor.quarter(asDateTime(dateTime), tzId); + } - return QuarterProcessor.quarter(millis, tzId); + private static ZonedDateTime asDateTime(Object dateTime) { + if (dateTime instanceof JodaCompatibleZonedDateTime) { + return ((JodaCompatibleZonedDateTime) dateTime).getZonedDateTime(); + } + throw new SqlIllegalArgumentException("Invalid date encountered [{}]", dateTime); } // diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryPredicate.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryPredicate.java index 1dcb7c843c0ec..6303d2799552d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryPredicate.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryPredicate.java @@ -60,7 +60,7 @@ public boolean equals(Object obj) { BinaryPredicate other = (BinaryPredicate) obj; - return Objects.equals(other.symbol(), other.symbol()) + return Objects.equals(symbol(), other.symbol()) && Objects.equals(left(), other.left()) && Objects.equals(right(), other.right()); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexProcessor.java index ada6accab7e1b..16f6f0a694966 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/regex/RegexProcessor.java @@ -38,7 +38,7 @@ public Boolean doApply(String value, String pattern) { } public static Boolean match(Object value, Object pattern) { - if (value == null && pattern == null) { + if (value == null || pattern == null) { return null; } diff --git a/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt b/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt index 4b52ef78e21f3..ea229940193a3 100644 --- a/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt +++ b/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt @@ -76,9 +76,9 @@ class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalS # Date/Time functions # Integer dateTimeChrono(Object, String, String) - String dayName(Long, String) - String monthName(Long, String) - Integer quarter(Long, String) + String dayName(Object, String) + String monthName(Object, String) + Integer quarter(Object, String) # # ASCII Functions diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java index fa5c5dc7a5b39..b55383f1e3f57 100644 --- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java +++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/jdbc/JdbcAssert.java @@ -179,7 +179,7 @@ private static void doAssertResultSetData(ResultSet expected, ResultSet actual, // handle nulls first if (expectedObject == null || actualObject == null) { // hack for JDBC CSV nulls - if ("null".equals(expectedObject)) { + if (expectedObject != null && "null".equals(expectedObject.toString().toLowerCase(Locale.ROOT))) { assertNull(msg, actualObject); } else { assertEquals(msg, expectedObject, actualObject); diff --git a/x-pack/qa/sql/src/main/resources/datetime.sql-spec b/x-pack/qa/sql/src/main/resources/datetime.sql-spec index 81012b7bebf92..888ebba43bb2a 100644 --- a/x-pack/qa/sql/src/main/resources/datetime.sql-spec +++ b/x-pack/qa/sql/src/main/resources/datetime.sql-spec @@ -84,6 +84,16 @@ SELECT MONTHNAME("hire_date") AS month, COUNT(*) AS count FROM "test_emp" GROUP // dayNameWithHaving // SELECT DAYNAME("hire_date") FROM "test_emp" GROUP BY DAYNAME("hire_date") HAVING MAX("emp_no") > ASCII(DAYNAME("hire_date")); +dayNameGroupBy +SELECT DAYNAME(birth_date) AS dn FROM test_emp GROUP BY DAYNAME(birth_date) ORDER BY DAYNAME(birth_date) ASC NULLS FIRST LIMIT 10; + +monthNameGroupBy +SELECT MONTHNAME(birth_date) AS mn FROM test_emp GROUP BY MONTHNAME(birth_date) ORDER BY MONTHNAME(birth_date) ASC NULLS FIRST LIMIT 10; + +quarterGroupBy +SELECT QUARTER(birth_date) AS q FROM test_emp GROUP BY QUARTER(birth_date) ORDER BY QUARTER(birth_date) ASC NULLS FIRST LIMIT 10; + + dayNameWithDoubleGroupByAndOrderBy SELECT COUNT(*) c, DAYNAME(hire_date) day_name, DAY(hire_date) day FROM test_emp WHERE MONTHNAME(hire_date) = 'August' GROUP BY DAYNAME(hire_date), DAY(hire_date) ORDER BY DAYNAME(hire_date), DAY(hire_date); From b05c145132bd803f1c53d5df6a6bb7c504ffdaee Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Thu, 18 Oct 2018 21:23:25 +0300 Subject: [PATCH 4/4] Minor polish Push REST/YAML fix Update docs --- .../sql/endpoints/translate.asciidoc | 4 +++- .../sql/expression/gen/script/Scripts.java | 23 ++++++++----------- .../rest-api-spec/test/sql/translate.yml | 2 ++ .../qa/sql/src/main/resources/select.sql-spec | 18 +++++++++++++++ 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/docs/reference/sql/endpoints/translate.asciidoc b/docs/reference/sql/endpoints/translate.asciidoc index db450b5f914c8..8d99c2154e881 100644 --- a/docs/reference/sql/endpoints/translate.asciidoc +++ b/docs/reference/sql/endpoints/translate.asciidoc @@ -43,7 +43,9 @@ Which returns: "sort" : [ { "page_count" : { - "order" : "desc" + "order" : "desc", + "missing" : "_first", + "unmapped_type" : "short" } } ] diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/Scripts.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/Scripts.java index d0a159c50afd1..69ad3661dc5bb 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/Scripts.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/Scripts.java @@ -9,33 +9,28 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalSqlScriptUtils; import org.elasticsearch.xpack.sql.type.DataType; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Pattern; +import java.util.stream.Stream; import static java.lang.String.format; +import static java.util.stream.Collectors.toMap; import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; public final class Scripts { private Scripts() {} - private static final Map FORMATTING_PATTERNS; - - static { - Map patterns = new LinkedHashMap<>(); - patterns.put("doc[{}].value", "{sql}.docValue(doc,{})"); - patterns.put("{sql}", InternalSqlScriptUtils.class.getSimpleName()); - patterns.put("{}", "params.%s"); - - FORMATTING_PATTERNS = new LinkedHashMap<>(); - - for (Entry entry : patterns.entrySet()) { - FORMATTING_PATTERNS.put(Pattern.compile(entry.getKey(), Pattern.LITERAL), entry.getValue()); - } - } + private static final Map FORMATTING_PATTERNS = Collections.unmodifiableMap(Stream.of( + new SimpleEntry<>("doc[{}].value", "{sql}.docValue(doc,{})"), + new SimpleEntry<>("{sql}", InternalSqlScriptUtils.class.getSimpleName()), + new SimpleEntry<>("{}", "params.%s")) + .collect(toMap(e -> Pattern.compile(e.getKey(), Pattern.LITERAL), Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new))); /** * Expands common tokens inside the script: diff --git a/x-pack/plugin/src/test/resources/rest-api-spec/test/sql/translate.yml b/x-pack/plugin/src/test/resources/rest-api-spec/test/sql/translate.yml index f47ea2d4d7e15..0a22a189fa7b6 100644 --- a/x-pack/plugin/src/test/resources/rest-api-spec/test/sql/translate.yml +++ b/x-pack/plugin/src/test/resources/rest-api-spec/test/sql/translate.yml @@ -33,3 +33,5 @@ sort: - int: order: asc + missing: _last + unmapped_type: long diff --git a/x-pack/qa/sql/src/main/resources/select.sql-spec b/x-pack/qa/sql/src/main/resources/select.sql-spec index ce57606e35b0c..ce259d07f5f17 100644 --- a/x-pack/qa/sql/src/main/resources/select.sql-spec +++ b/x-pack/qa/sql/src/main/resources/select.sql-spec @@ -34,6 +34,24 @@ SELECT first_name, last_name FROM "test_emp" ORDER BY emp_no LIMIT 5; multipleColumnWithAliasWithAndWithoutAsWithLimit SELECT first_name f, last_name AS l FROM "test_emp" ORDER BY emp_no LIMIT 5; +// +// SELECT constant literals with FROM +// + +constantWithLimit +SELECT 3 FROM "test_emp" LIMIT 5; +constantAndColumnWithLimit +SELECT 3, first_name, last_name FROM "test_emp" ORDER BY emp_no LIMIT 5; +constantComparisonWithLimit +SELECT 1=1 AS bool FROM "test_emp" LIMIT 5; +constantComparisonAndColumnWithLimit +SELECT 1=1 AS bool, first_name, last_name FROM "test_emp" ORDER BY emp_no LIMIT 5; +castWithLiteralWithFrom +SELECT CAST(1 AS INT) AS constant FROM "test_emp" LIMIT 5; +castWithLiteralAndColumnWithFrom +SELECT CAST((CAST(languages AS BIT) OR CAST(1 AS BIT)) AS INT) AS bool FROM test_emp LIMIT 5; +castWithColumnAndLiteralCombinedAndSelectColumnWithFrom +SELECT CAST((CAST(languages AS BIT) OR CAST(1 AS BIT)) AS INT) AS bool, languages FROM test_emp ORDER BY languages ASC NULLS FIRST LIMIT 5; // // SELECT with CAST